This is the mail archive of the gdb-patches@sourceware.org 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: [PING] [rfc]: Framework for looking up multiply defined global symbols in shared libraries


Markus Deuling wrote:
Hi Daniel,

Daniel Jacobowitz wrote:
Please use skip_shlib_tests instead.  You will probably also need to
exclude a list of targets where -Bsymbolic won't work.

(I realize skip_shlib_tests doesn't exist yet.  Gimme a day or so and
it will, I'll be working on those patches next.)

thank you very much for your effort and your very valuable input. I'll rework the patch and come up with it when you're done with that patch that includes skip_shlib_tests.




This is the reworked patch for multiply defined symbols in shared libraries. I included your input including the new skip_shlib_tests and gdb_load_shlibs. Again thank you very much for reviewing.

The testsuite showed no regressions. The ChangeLog also had to be changed. Would this be ok to commit?

ChangeLog:
* cp-namespace.c (lookup_symbol_file): Add block to call for lookup_symbol_global.
* Makefile.in (solist_h): Update dependencies.
(solib.o): Likewise.
(symtab.o): Likewise.
* solib.c (solib_global_lookup): New function.
* solib-svr4.c (has_SYMBOLIC): New function.
(elf_lookup_lib_symbol): New function.
(_initialize_svr4_solib): Add elf_lookup_lib_symbol to svr4_so_ops.
* solist.h: New include "symtab.h".
(target_so_ops): New member lookup_lib_global_symbol.
(solib_global_lookup): Declare.
* symtab.c: New include "solist.h".
(lookup_objfile_from_block): New function.
(lookup_global_symbol_from_objfile): New function.
(basic_lookup_symbol_nonlocal): Add block to call for lookup_symbol_global.
(lookup_symbol_global): Call solib_global_lookup first.
* symtab.h (lookup_symbol_global): Add block to declaration.
(lookup_objfile_from_block): Declare.
(lookup_global_symbol_from_objfile): Declare.
* gdb.base/libmd.c: New file for testcase.
* gdb.base/libmd.h: Likewise.
* gdb.base/solib_symbol.c: Likewise.
* gdb.base/solib_symbol.exp: New testcase for multiply defined global
symbol lookup.



-- Markus Deuling GNU Toolchain for Linux on Cell BE deuling@de.ibm.com

diff -urN src/gdb/cp-namespace.c dev/gdb/cp-namespace.c
--- src/gdb/cp-namespace.c	2007-01-09 18:58:50.000000000 +0100
+++ dev/gdb/cp-namespace.c	2007-05-18 05:40:42.000000000 +0200
@@ -491,7 +491,7 @@
     }
   else
     {
-      sym = lookup_symbol_global (name, linkage_name, domain, symtab);
+      sym = lookup_symbol_global (name, linkage_name, block, domain, symtab);
     }
 
   if (sym != NULL)
diff -urN src/gdb/Makefile.in dev/gdb/Makefile.in
--- src/gdb/Makefile.in	2007-05-18 05:34:55.000000000 +0200
+++ dev/gdb/Makefile.in	2007-05-18 05:40:42.000000000 +0200
@@ -797,7 +797,7 @@
 solib_pa64_h = solib-pa64.h
 solib_som_h = solib-som.h
 solib_svr4_h = solib-svr4.h
-solist_h = solist.h
+solist_h = solist.h $(symtab_h)
 source_h = source.h
 sparc64_tdep_h = sparc64-tdep.h $(sparc_tdep_h)
 sparc_nat_h = sparc-nat.h
@@ -2572,7 +2572,7 @@
 	$(objfiles_h) $(exceptions_h) $(gdbcore_h) $(command_h) $(target_h) \
 	$(frame_h) $(gdb_regex_h) $(inferior_h) $(environ_h) $(language_h) \
 	$(gdbcmd_h) $(completer_h) $(filenames_h) $(exec_h) $(solist_h) \
-	$(observer_h) $(readline_h)
+	$(observer_h) $(readline_h) $(objfiles_h)
 solib-frv.o: solib-frv.c $(defs_h) $(gdb_string_h) $(inferior_h) \
 	$(gdbcore_h) $(solist_h) $(frv_tdep_h) $(objfiles_h) $(symtab_h) \
 	$(language_h) $(command_h) $(gdbcmd_h) $(elf_frv_h) $(solib_h)
@@ -2719,7 +2719,8 @@
 	$(language_h) $(demangle_h) $(inferior_h) $(linespec_h) $(source_h) \
 	$(filenames_h) $(objc_lang_h) $(ada_lang_h) $(hashtab_h) \
 	$(gdb_obstack_h) $(block_h) $(dictionary_h) $(gdb_string_h) \
-	$(gdb_stat_h) $(cp_abi_h) $(observer_h) $(gdb_assert_h)
+	$(gdb_stat_h) $(cp_abi_h) $(observer_h) $(gdb_assert_h) \
+	$(solist_h)
 target.o: target.c $(defs_h) $(gdb_string_h) $(target_h) $(gdbcmd_h) \
 	$(symtab_h) $(inferior_h) $(bfd_h) $(symfile_h) $(objfiles_h) \
 	$(gdb_wait_h) $(dcache_h) $(regcache_h) $(gdb_assert_h) $(gdbcore_h) \
diff -urN src/gdb/solib.c dev/gdb/solib.c
--- src/gdb/solib.c	2007-05-18 05:34:56.000000000 +0200
+++ dev/gdb/solib.c	2007-05-18 05:40:42.000000000 +0200
@@ -955,6 +955,26 @@
 }
 
 
+/* Handler for library-specific lookup of global symbol
+   NAME in BLOCK.  Detect objfile corresponding to BLOCK
+   and call the library-specific handler if it is installed
+   for the current target.  */
+
+struct symbol *
+solib_global_lookup (const struct objfile *objfile,
+		     const char *name,
+		     const char *linkage_name,
+		     const domain_enum domain,
+		     struct symtab **symtab)
+{
+  if (current_target_so_ops->lookup_lib_global_symbol != NULL)
+    return current_target_so_ops->lookup_lib_global_symbol (objfile,
+				name, linkage_name, domain, symtab);
+
+  return NULL;
+}
+
+
 extern initialize_file_ftype _initialize_solib; /* -Wmissing-prototypes */
 
 void
diff -urN src/gdb/solib-svr4.c dev/gdb/solib-svr4.c
--- src/gdb/solib-svr4.c	2007-05-18 05:34:56.000000000 +0200
+++ dev/gdb/solib-svr4.c	2007-05-18 05:58:33.000000000 +0200
@@ -378,6 +378,71 @@
 
  */
 
+/* Scan OBFD for a SYMBOLIC flag in the .dynamic section.  If it is set then
+   OBFD is a DSO with a special rule for symbol lookup.  The lookup then starts
+   in the DSO before searching in the executable.  */
+
+static int
+has_SYMBOLIC (bfd *obfd)
+{
+  CORE_ADDR dyn_ptr = 0;
+  int sect_size, arch_size;
+  gdb_byte *buf, *bufstart, *bufend, *p;
+  asection *sect;
+
+  if (obfd == NULL)
+    return -1;
+  arch_size = bfd_get_arch_size (obfd);
+  if (arch_size == -1)
+    return -1;
+
+  /* Retrieve information about .dynamic section.  */
+  sect = bfd_get_section_by_name (obfd, ".dynamic");
+  if (!sect)
+    return -1;
+
+  /* Read the .dynamic section.  */
+  sect_size = bfd_section_size (obfd, sect);
+  buf = alloca (sect_size);
+  if (!bfd_get_section_contents (obfd, sect,
+				 buf, 0, sect_size))
+    return -1;
+
+  if (arch_size == 32)
+    { /* 32-bit elf */
+      for (bufend = buf + sect_size;
+	   buf < bufend;
+	   buf += sizeof (Elf32_External_Dyn))
+	{
+	  Elf32_External_Dyn *x_dynp = (Elf32_External_Dyn *) buf;
+	  long dyn_tag;
+	  dyn_tag = extract_unsigned_integer ((gdb_byte *) x_dynp->d_tag, 4);
+	  if (dyn_tag == DT_NULL)
+	    break;
+	  else if (dyn_tag == DT_SYMBOLIC)
+	    return 1;
+	}
+    }
+  else
+    { /* 64-bit elf */
+      for (bufend = buf + sect_size;
+	   buf < bufend;
+	   buf += sizeof (Elf64_External_Dyn))
+	{
+	  Elf64_External_Dyn *x_dynp = (Elf64_External_Dyn *) buf;
+	  long dyn_tag;
+
+	  dyn_tag = extract_unsigned_integer ((gdb_byte *) x_dynp->d_tag, 8);
+	  if (dyn_tag == DT_NULL)
+	    break;
+	  else if (dyn_tag == DT_SYMBOLIC)
+	    return 1;
+	}
+    }
+
+  return 0;
+}
+
 static CORE_ADDR
 elf_locate_base (void)
 {
@@ -1558,6 +1623,24 @@
 
 struct target_so_ops svr4_so_ops;
 
+/* Lookup global symbol for ELF DSOs linked with -Bsymbolic.
+   Those DSOs have a different rule for symbol lookup. The lookup
+   begins here in the DSO, not in the main executable.  */
+
+static struct symbol *
+elf_lookup_lib_symbol (const struct objfile *objfile,
+		       const char *name,
+		       const char *linkage_name,
+		       const domain_enum domain, struct symtab **symtab)
+{
+  if (objfile->obfd == NULL
+     || has_SYMBOLIC (objfile->obfd) != 1)
+    return NULL;
+
+  return  lookup_global_symbol_from_objfile
+		(objfile, name, linkage_name, domain, symtab);
+}
+
 extern initialize_file_ftype _initialize_svr4_solib; /* -Wmissing-prototypes */
 
 void
@@ -1573,6 +1656,7 @@
   svr4_so_ops.current_sos = svr4_current_sos;
   svr4_so_ops.open_symbol_file_object = open_symbol_file_object;
   svr4_so_ops.in_dynsym_resolve_code = svr4_in_dynsym_resolve_code;
+  svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
 
   /* FIXME: Don't do this here.  *_gdbarch_init() should set so_ops. */
   current_target_so_ops = &svr4_so_ops;
diff -urN src/gdb/solist.h dev/gdb/solist.h
--- src/gdb/solist.h	2007-01-09 18:58:58.000000000 +0100
+++ dev/gdb/solist.h	2007-05-18 05:40:42.000000000 +0200
@@ -23,6 +23,8 @@
 #define SOLIST_H
 
 #define SO_NAME_MAX_PATH_SIZE 512	/* FIXME: Should be dynamic */
+/* For domain_enum domain.  */
+#include "symtab.h"
 
 /* Forward declaration for target specific link map information.  This
    struct is opaque to all but the target specific file.  */
@@ -103,7 +105,14 @@
        Convenience function for remote debuggers finding host libs.  */
     int (*find_and_open_solib) (char *soname,
         unsigned o_flags, char **temp_pathname);
-    
+
+    /* Hook for looking up global symbols in a library-specific way.  */
+    struct symbol * (*lookup_lib_global_symbol) (const struct objfile *objfile,
+						 const char *name,
+						 const char *linkage_name,
+						 const domain_enum domain,
+						 struct symtab **symtab);
+
   };
 
 /* Free the memory associated with a (so_list *).  */
@@ -125,4 +134,11 @@
 #define TARGET_SO_IN_DYNSYM_RESOLVE_CODE \
   (current_target_so_ops->in_dynsym_resolve_code)
 
+/* Handler for library-specific global symbol lookup in solib.c.  */
+struct symbol *solib_global_lookup (const struct objfile *objfile,
+				    const char *name,
+				    const char *linkage_name,
+				    const domain_enum domain,
+				    struct symtab **symtab);
+
 #endif
diff -urN src/gdb/symtab.c dev/gdb/symtab.c
--- src/gdb/symtab.c	2007-04-18 13:12:57.000000000 +0200
+++ dev/gdb/symtab.c	2007-05-18 05:55:54.000000000 +0200
@@ -57,6 +57,7 @@
 #include "cp-abi.h"
 #include "observer.h"
 #include "gdb_assert.h"
+#include "solist.h"
 
 /* Prototypes for local functions */
 
@@ -1265,6 +1266,26 @@
   return NULL;
 }
 
+/* Look up OBJFILE to BLOCK.  */
+
+struct objfile *
+lookup_objfile_from_block (const struct block *block)
+{
+  struct objfile *obj;
+  struct symtab *s;
+
+  if (block == NULL)
+    return NULL;
+
+  block = block_global_block (block);
+  /* Go through SYMTABS.  */
+  ALL_SYMTABS (obj, s)
+    if (block == BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK))
+      return obj;
+
+  return NULL;
+}
+
 /* Look up a symbol in a block; if found, locate its symtab, fixup the
    symbol, and set block_found appropriately.  */
 
@@ -1306,6 +1327,57 @@
   return NULL;
 }
 
+/* Check all global symbols in OBJFILE in symtabs and
+   psymtabs.  */
+
+struct symbol *
+lookup_global_symbol_from_objfile (const struct objfile *objfile,
+				   const char *name,
+				   const char *linkage_name,
+				   const domain_enum domain,
+				   struct symtab **symtab)
+{
+  struct symbol *sym;
+  struct blockvector *bv;
+  const struct block *block;
+  struct symtab *s;
+  struct partial_symtab *ps;
+
+  /* Go through symtabs.  */
+  ALL_OBJFILE_SYMTABS (objfile, s)
+  {
+    bv = BLOCKVECTOR (s);
+    block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+    sym = lookup_block_symbol (block, name, linkage_name, domain);
+    if (sym)
+      {
+	block_found = block;
+	if (symtab != NULL)
+	  *symtab = s;
+	return fixup_symbol_section (sym, (struct objfile *)objfile);
+      }
+  }
+
+  /* Now go through psymtabs.  */
+  ALL_OBJFILE_PSYMTABS (objfile, ps)
+  {
+    if (!ps->readin
+	&& lookup_partial_symbol (ps, name, linkage_name,
+				  1, domain))
+      {
+	s = PSYMTAB_TO_SYMTAB (ps);
+	bv = BLOCKVECTOR (s);
+	block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+	sym = lookup_block_symbol (block, name, linkage_name, domain);
+	if (symtab != NULL)
+	  *symtab = s;
+	return fixup_symbol_section (sym, (struct objfile *)objfile);
+      }
+  }
+
+  return NULL;
+}
+
 /* Check to see if the symbol is defined in one of the symtabs.
    BLOCK_INDEX should be either GLOBAL_BLOCK or STATIC_BLOCK,
    depending on whether or not we want to search global symbols or
@@ -1571,7 +1643,7 @@
   if (sym != NULL)
     return sym;
 
-  return lookup_symbol_global (name, linkage_name, domain, symtab);
+  return lookup_symbol_global (name, linkage_name, block, domain, symtab);
 }
 
 /* Lookup a symbol in the static block associated to BLOCK, if there
@@ -1599,10 +1671,19 @@
 struct symbol *
 lookup_symbol_global (const char *name,
 		      const char *linkage_name,
+		      const struct block *block,
 		      const domain_enum domain,
 		      struct symtab **symtab)
 {
-  struct symbol *sym;
+  struct symbol *sym = NULL;
+  struct objfile *objfile = NULL;
+
+  /* Call library-specific lookup procedure.  */
+  objfile = lookup_objfile_from_block (block);
+  if (objfile != NULL)
+    sym = solib_global_lookup (objfile, name, linkage_name, domain, symtab);
+  if (sym != NULL)
+    return sym;
 
   sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, linkage_name,
 				   domain, symtab);
diff -urN src/gdb/symtab.h dev/gdb/symtab.h
--- src/gdb/symtab.h	2007-03-28 05:42:54.000000000 +0200
+++ dev/gdb/symtab.h	2007-05-18 05:40:42.000000000 +0200
@@ -1050,6 +1050,7 @@
 
 extern struct symbol *lookup_symbol_global (const char *name,
 					    const char *linkage_name,
+					    const struct block *block,
 					    const domain_enum domain,
 					    struct symtab **symtab);
 
@@ -1403,4 +1404,16 @@
    Defined in symtab.c, used in hppa-tdep.c. */
 extern int deprecated_hp_som_som_object_present;
 
+/* Lookup objfile to a block.  */
+extern struct objfile *
+lookup_objfile_from_block (const struct block *block);
+
+/* Check global symbols in objfile.  */
+struct symbol *lookup_global_symbol_from_objfile (const struct objfile *objfile,
+						  const char *name,
+						  const char *linkage_name,
+						  const domain_enum domain,
+						  struct symtab **symtab);
+
+
 #endif /* !defined(SYMTAB_H) */
diff -urN src/gdb/testsuite/gdb.base/libmd.c dev/gdb/testsuite/gdb.base/libmd.c
--- src/gdb/testsuite/gdb.base/libmd.c	1970-01-01 01:00:00.000000000 +0100
+++ dev/gdb/testsuite/gdb.base/libmd.c	2007-05-18 05:40:42.000000000 +0200
@@ -0,0 +1,36 @@
+/* Copyright 2007 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.
+
+   Contributed by Markus Deuling <deuling@de.ibm.com>.
+*/
+extern void foo();
+#include <stdio.h>
+#include "libmd.h"
+
+void foo2 ();
+
+void
+foo ()
+{
+  printf ("foo in lib\n");
+  return;
+}
+
+void
+foo2()
+{
+  printf ("foo2 in lib\n");
+  return;
+}
diff -urN src/gdb/testsuite/gdb.base/libmd.h dev/gdb/testsuite/gdb.base/libmd.h
--- src/gdb/testsuite/gdb.base/libmd.h	1970-01-01 01:00:00.000000000 +0100
+++ dev/gdb/testsuite/gdb.base/libmd.h	2007-05-18 05:40:42.000000000 +0200
@@ -0,0 +1,18 @@
+/* Copyright 2007 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.
+
+   Contributed by Markus Deuling <deuling@de.ibm.com>.
+*/
+extern void foo();
diff -urN src/gdb/testsuite/gdb.base/solib_symbol.c dev/gdb/testsuite/gdb.base/solib_symbol.c
--- src/gdb/testsuite/gdb.base/solib_symbol.c	1970-01-01 01:00:00.000000000 +0100
+++ dev/gdb/testsuite/gdb.base/solib_symbol.c	2007-05-18 05:40:42.000000000 +0200
@@ -0,0 +1,45 @@
+/* Copyright 2007 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.
+
+   Contributed by Markus Deuling <deuling@de.ibm.com>.
+*/
+extern void foo();
+#include <stdio.h>
+#include "libmd.h"
+
+extern void foo();
+void foo3();
+void foo2();
+
+int main ()
+{
+  printf ("in main\n");
+  foo ();
+  foo3 ();
+  return 0;
+}
+
+void foo3()
+{
+  printf ("foo3 in main\n");
+  return;
+}
+
+void foo2()
+{
+  printf ("foo2 in main\n");
+  return;
+}
+
diff -urN src/gdb/testsuite/gdb.base/solib_symbol.exp dev/gdb/testsuite/gdb.base/solib_symbol.exp
--- src/gdb/testsuite/gdb.base/solib_symbol.exp	1970-01-01 01:00:00.000000000 +0100
+++ dev/gdb/testsuite/gdb.base/solib_symbol.exp	2007-05-18 05:50:44.000000000 +0200
@@ -0,0 +1,80 @@
+# Copyright 2007 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. 
+#
+# Contributed by Markus Deuling <deuling@de.ibm.com>.
+#
+
+if {[skip_shlib_tests]} {
+    return 0
+}
+
+# Library file.
+set libname "libmd"
+set srcfile_lib ${srcdir}/${subdir}/${libname}.c
+set binfile_lib ${objdir}/${subdir}/${libname}.so
+set lib_flags [list debug ldflags=-Wl,-Bsymbolic]
+# Binary file.
+set testfile "solib_symbol"
+set srcfile ${srcdir}/${subdir}/${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+set bin_flags [list debug shlib=${binfile_lib}]
+
+if [get_compiler_info ${binfile}] {
+    return -1
+}
+
+if { [gdb_compile_shlib ${srcfile_lib} ${binfile_lib} $lib_flags] != ""
+     || [gdb_compile ${srcfile} ${binfile} executable $bin_flags] != "" } {
+  untested "Could not compile $binfile_lib or $binfile."
+  return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+gdb_load_shlibs $binfile_lib
+
+if ![runto_main] then {
+  fail "Can't run to main"
+  return 0
+}
+
+# Set a breakpoint in the binary.
+gdb_test "br foo2" \
+	 "Breakpoint.*file.*${srcfile}.*" \
+	 "foo2 in main"
+
+delete_breakpoints
+
+# Break in the library.
+gdb_test "br foo" \
+	 "" \
+	 "foo in libmd"
+
+gdb_test "continue" \
+	 "Continuing.*" \
+	 "continue"
+
+# This symbol is now looked up in the ELF library.
+gdb_test "br foo2" \
+	 "Breakpoint.*file.*${srcfile_lib}.*" \
+	 "foo2 in mdlib"
+
+gdb_exit
+
+return 0
+
+

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