This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFA/symtab] Handle weak functions as global


On Sun, Nov 28, 2004 at 09:08:32PM -0500, Elena Zannoni wrote:
> Interesting. This is just gdb not following in the symbol searches any
> of the ELF scoping rules. Can you add a small testcase?

I'll have to limit it to GCC - the patch only affects weak symbols. 
Here's a test case; one unexpected failure without the patch, none
with.  Two known failures (see below).

> If you compile the files with bar() as shared libraries, what version
> of bar does gdb pick from main?

The right one, with or without the patch - if you link the library
contaning file1 first on the command line, it breaks in file1.c,
otherwise it breaks in file2.c.  I think you could get GDB to give the
wrong answer with more complicated tests - for instance using dlopen.
Like you said, GDB doesn't know anything about ELF scoping (and I don't
think it could know everything about it, either - does the link map
expose enough information about search order?).

The only way I could get the test to work was by using a weak symbol
and building the shared libraries without debug information.  This
patch only changes the minsym type; with debug information,
lookup_minimal_symbol is never called.  The original problem came up
because "open" is an assembly stub in GDB.

This exposed a related problem, which I've filed as gdb/1824.  If one
has debug and the other doesn't, lookup_symbol will succeed, and we'll
always breakpoint the full symbol.  Global minimal symbols could
be handled before static full symbols, one object at a time.  Or, as I
suggest in the bug report, we could just breakpoint both copies.  I
suspect that's more robust and more useful.

Testcase look OK?  I finally added some shared library utility code to
gdb.exp.

-- 
Daniel Jacobowitz

2004-11-30  Daniel Jacobowitz  <dan@debian.org>

	* gdb.base/solib-weak.c, gdb.base/solib-weak.exp, gdb.base/weaklib1.c,
	gdb.base/weaklib2.c: New files.
	* lib/gdb.exp (gdb_compile): Handle shlib=.
	(gdb_compile_shlib): New function.

Index: testsuite/gdb.base/solib-weak.c
===================================================================
RCS file: testsuite/gdb.base/solib-weak.c
diff -N testsuite/gdb.base/solib-weak.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.base/solib-weak.c	30 Nov 2004 21:22:27 -0000
@@ -0,0 +1,25 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2004 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+int
+main()
+{
+  foo ();
+  return 0;
+}                                                                                                       
Index: testsuite/gdb.base/solib-weak.exp
===================================================================
RCS file: testsuite/gdb.base/solib-weak.exp
diff -N testsuite/gdb.base/solib-weak.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.base/solib-weak.exp	30 Nov 2004 21:28:35 -0000
@@ -0,0 +1,109 @@
+#   Copyright 2004
+#   Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+
+# Test setting breakpoints on shared library functions provided by more
+# than one shared library, when one of the implementations is a "weak"
+# symbol.  GDB should set a breakpoint at the first copy it finds.
+
+# Don't try to run shared library test cases on a remote target for now.
+if ![isnative] then {
+    return 0
+}
+
+# This test uses GCC-specific syntax.
+if [get_compiler_info ${objdir}/${subdir}/solib-weak] {
+    return -1
+}
+
+if {$gcc_compiled == 0} {
+    return 0
+}
+
+proc do_test { lib1opts lib2opts lib1first } {
+    global objdir srcdir subdir
+
+    set testopts ""
+    if {$lib1opts == ""} {
+	append testopts "lib1 nodebug, "
+    } else {
+	append testopts "lib1 debug, "
+    }
+    if {$lib2opts == ""} {
+	append testopts "lib2 nodebug, "
+    } else {
+	append testopts "lib2 debug, "
+    }
+    if {$lib1first} {
+	append testopts "lib1 first"
+    } else {
+	append testopts "lib2 first"
+    }
+
+    set testfile "solib-weak"
+    set srcfile ${testfile}.c
+    set binfile ${objdir}/${subdir}/${testfile}
+
+    set libfile1 "weaklib1"
+    set libfile2 "weaklib2"
+    set lib1src ${srcdir}/${subdir}/${libfile1}.c
+    set lib2src ${srcdir}/${subdir}/${libfile2}.c
+    set lib1 ${objdir}/${subdir}/${libfile1}.sl
+    set lib2 ${objdir}/${subdir}/${libfile2}.sl
+
+    if $lib1first {
+	set exec_opts [list debug shlib=${lib1} shlib=${lib2}]
+	set expected_file ${libfile1}
+    } else {
+	set exec_opts [list debug shlib=${lib2} shlib=${lib1}]
+	set expected_file ${libfile2}
+    }
+
+    if { [gdb_compile_shlib ${lib1src} ${lib1} ${lib1opts}] != ""
+	 || [gdb_compile_shlib ${lib2src} ${lib2} ${lib2opts}] != ""
+	 || [gdb_compile "${srcdir}/${subdir}/${srcfile}" ${binfile} executable $exec_opts] != ""} {
+	return -1
+    }
+
+    gdb_exit
+    gdb_start
+    gdb_reinitialize_dir $srcdir/$subdir
+    gdb_load ${binfile}
+
+    runto_main
+
+    gdb_breakpoint "bar"
+
+    # If the library which will be used is compiled without debugging
+    # information, GDB will pick the wrong copy of "bar", i.e. the one
+    # with debugging information.
+
+    if {(${lib1opts} == "" && ${lib2opts} != "" && ${lib1first} == 1)
+	|| (${lib1opts} != "" && ${lib2opts} == "" && ${lib1first} == 0)} {
+	setup_kfail *-*-* gdb/1824
+    }
+
+    gdb_test "continue" "Breakpoint .* bar .*${expected_file}\\..*" \
+	"run to breakpoint - $testopts"
+}
+
+foreach lib1opts {{} {debug}} {
+    foreach lib2opts {{} {debug}} {
+	foreach lib1first {1 0} {
+	    do_test $lib1opts $lib2opts $lib1first
+	}
+    }
+}
Index: testsuite/gdb.base/weaklib1.c
===================================================================
RCS file: testsuite/gdb.base/weaklib1.c
diff -N testsuite/gdb.base/weaklib1.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.base/weaklib1.c	30 Nov 2004 21:22:26 -0000
@@ -0,0 +1,24 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2004 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+void __attribute__((weak))
+bar (void)
+{
+  puts ("bar in u1");
+}                                                                                                       
Index: testsuite/gdb.base/weaklib2.c
===================================================================
RCS file: testsuite/gdb.base/weaklib2.c
diff -N testsuite/gdb.base/weaklib2.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.base/weaklib2.c	30 Nov 2004 21:22:26 -0000
@@ -0,0 +1,31 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2004 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+ 
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+void bar (void);
+void
+foo (void)
+{ 
+  bar ();
+}                                                                                                       
+
+void
+bar (void)
+{ 
+  puts ("bar in u2");
+}                                                                                                       
Index: testsuite/lib/gdb.exp
===================================================================
RCS file: /big/fsf/rsync/src-cvs/src/gdb/testsuite/lib/gdb.exp,v
retrieving revision 1.58
diff -u -p -r1.58 gdb.exp
--- testsuite/lib/gdb.exp	10 Sep 2004 01:04:59 -0000	1.58
+++ testsuite/lib/gdb.exp	30 Nov 2004 21:24:17 -0000
@@ -1324,6 +1324,30 @@ proc gdb_compile {source dest type optio
     global gdb_wrapper_flags;
     global gdb_wrapper_initialized;
 
+    # Add platform-specific options if a shared library was specified using
+    # "shlib=librarypath" in OPTIONS.
+    set new_options ""
+    set shlib_found 0
+    foreach opt $options {
+	if [regexp {^shlib=(.*)} $opt dummy_var shlib_name] {
+	    lappend source $shlib_name
+	    if {$shlib_found == 0} {
+		set shlib_found 1
+		global gcc_compiled
+		if { ($gcc_compiled 
+		      &&  ([istarget "powerpc*-*-aix*"]
+			|| [istarget "rs6000*-*-aix*"] )) } {
+		    lappend options "additional_flags=-L${objdir}/${subdir}"
+		} elseif { [istarget "mips-sgi-irix*"] } {
+		    lappend options "additional_flags=-rpath ${objdir}/${subdir}"
+		}
+	    }
+	} else {
+	    lappend new_options $opt
+	}
+    }
+    set options $new_options
+
     if [target_info exists gdb_stub] {
 	set options2 { "additional_flags=-Dusestubs" }
 	lappend options "libs=[target_info gdb_stub]";
@@ -1434,6 +1458,50 @@ proc gdb_compile_objc {source dest type 
     }
 }
 
+# Build a shared library from SOURCES.  You must use get_compiler_info
+# first.
+
+proc gdb_compile_shlib {sources dest options} {
+    global gcc_compiled
+
+    set obj_options $options
+    if {$gcc_compiled == 0} {
+	if [istarget "hppa*-hp-hpux*"] then {
+	    lappend obj_options "additional_flags=+z"
+	} elseif { [istarget "mips-sgi-irix*"] } {
+	    # Disable SGI compiler's implicit -Dsgi
+	    lappend obj_options "additional_flags=-Usgi"
+	} else {
+	    # don't know what the compiler is...
+	}
+    } else {
+	if { !([istarget "powerpc*-*-aix*"]
+	       || [istarget "rs6000*-*-aix*"]) } {
+	    lappend obj_options "additional_flags=-fpic"
+	}
+    }
+
+    set outdir [file dirname $dest]
+    set objects ""
+    foreach source $sources {
+	set sourcebase [file tail $source]
+	if {[gdb_compile $source "${outdir}/${sourcebase}.o" object $obj_options] != ""} {
+	    return -1
+	}
+	lappend objects ${outdir}/${sourcebase}.o
+    }
+
+    if [istarget "hppa*-*-hpux*"] {
+	remote_exec build "ld -b ${objects} -o ${dest}"
+    } else {
+	set link_options options
+	lappend link_options "additional_flags=-shared"
+	if {[gdb_compile "${objects}" "${dest}" executable $link_options] != ""} {
+	    return -1
+	}
+    }
+}
+
 proc send_gdb { string } {
     global suppress_flag;
     if { $suppress_flag } {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]