aboutsummaryrefslogtreecommitdiff
path: root/gdb/solib-svr4.c
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2007-07-03 12:14:44 +0000
committerUlrich Weigand <uweigand@de.ibm.com>2007-07-03 12:14:44 +0000
commit3a40aaa0eb849a9aacd6f1e83b94fb8b0947cdfb (patch)
tree24c19c39630f502332f0e3042a9662c3f20019ad /gdb/solib-svr4.c
parent3ccac826a3edc921e1e6c5ded9502781cca509af (diff)
downloadgdb-3a40aaa0eb849a9aacd6f1e83b94fb8b0947cdfb.zip
gdb-3a40aaa0eb849a9aacd6f1e83b94fb8b0947cdfb.tar.gz
gdb-3a40aaa0eb849a9aacd6f1e83b94fb8b0947cdfb.tar.bz2
2007-07-03 Markus Deuling <deuling@de.ibm.com>
* cp-namespace.c (lookup_symbol_file): Add block to lookup_symbol_global call. * Makefile.in (solist_h): Add dependency on symtab header. (symtab.o): Add dependency on solist header. * solib.c (solib_global_lookup): New function. * solib-svr4.c (scan_dyntag): Likewise. (elf_locate_base): Call helper routine scan_dyntag. (elf_lookup_lib_symbol): New function. (_initialize_svr4_solib): Add elf_lookup_lib_symbol to svr4_so_ops. * solist.h (symtab.h): New include. (struct target_so_ops): New member lookup_lib_global_symbol. (solib_global_lookup): New prototype. * 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 lookup_symbol_global call. (lookup_symbol_global): Call library-specific lookup procedure. * symtab.h (lookup_global_symbol_from_objfile): New prototype. * NEWS: Document framework. testsuite/ * gdb.base/solib-symbol.exp: New file (testcase multiple symbol lookup). * gdb.base/solib-symbol-lib.c: Likewise. * gdb.base/solib-symbol-main.c: Likewise.
Diffstat (limited to 'gdb/solib-svr4.c')
-rw-r--r--gdb/solib-svr4.c212
1 files changed, 109 insertions, 103 deletions
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index c531ccb..7dfe707e 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -354,6 +354,76 @@ bfd_lookup_symbol (bfd *abfd, char *symname, flagword sect_flags)
return symaddr;
}
+/* Scan for DYNTAG in .dynamic section of ABFD. If DYNTAG is found 1 is
+ returned and the corresponding PTR is set. */
+
+static int
+scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr)
+{
+ int arch_size, step, sect_size;
+ long dyn_tag;
+ CORE_ADDR dyn_ptr, dyn_addr;
+ gdb_byte *bufend, *buf;
+ Elf32_External_Dyn *x_dynp_32;
+ Elf64_External_Dyn *x_dynp_64;
+ struct bfd_section *sect;
+
+ if (abfd == NULL)
+ return 0;
+ arch_size = bfd_get_arch_size (abfd);
+ if (arch_size == -1)
+ return 0;
+
+ /* Find the start address of the .dynamic section. */
+ sect = bfd_get_section_by_name (abfd, ".dynamic");
+ if (sect == NULL)
+ return 0;
+ dyn_addr = bfd_section_vma (abfd, sect);
+
+ /* Read in .dynamic section, silently ignore errors. */
+ sect_size = bfd_section_size (abfd, sect);
+ buf = alloca (sect_size);
+ if (target_read_memory (dyn_addr, buf, sect_size))
+ {
+ /* If target_read_memory fails, try reading the BFD file. */
+ if (!bfd_get_section_contents (abfd, sect,
+ buf, 0, sect_size))
+ return 0;
+ }
+
+ /* Iterate over BUF and scan for DYNTAG. If found, set PTR and return. */
+ step = (arch_size == 32) ? sizeof (Elf32_External_Dyn)
+ : sizeof (Elf64_External_Dyn);
+ for (bufend = buf + sect_size;
+ buf < bufend;
+ buf += step)
+ {
+ if (arch_size == 32)
+ {
+ x_dynp_32 = (Elf32_External_Dyn *) buf;
+ dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_tag);
+ dyn_ptr = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_un.d_ptr);
+ }
+ else
+ {
+ x_dynp_64 = (Elf64_External_Dyn *) buf;
+ dyn_tag = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_tag);
+ dyn_ptr = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_un.d_ptr);
+ }
+ if (dyn_tag == DT_NULL)
+ return 0;
+ if (dyn_tag == dyntag)
+ {
+ if (ptr)
+ *ptr = dyn_ptr;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+
/*
LOCAL FUNCTION
@@ -381,114 +451,31 @@ bfd_lookup_symbol (bfd *abfd, char *symname, flagword sect_flags)
static CORE_ADDR
elf_locate_base (void)
{
- struct bfd_section *dyninfo_sect;
- int dyninfo_sect_size;
- CORE_ADDR dyninfo_addr;
- gdb_byte *buf;
- gdb_byte *bufend;
- int arch_size;
+ struct minimal_symbol *msymbol;
+ CORE_ADDR dyn_ptr;
- /* Find the start address of the .dynamic section. */
- dyninfo_sect = bfd_get_section_by_name (exec_bfd, ".dynamic");
- if (dyninfo_sect == NULL)
- {
- /* This may be a static executable. Look for the symbol
- conventionally named _r_debug, as a last resort. */
- struct minimal_symbol *msymbol;
+ /* Find DT_DEBUG. */
+ if (scan_dyntag (DT_DEBUG, exec_bfd, &dyn_ptr))
+ return dyn_ptr;
- msymbol = lookup_minimal_symbol ("_r_debug", NULL, symfile_objfile);
- if (msymbol != NULL)
- return SYMBOL_VALUE_ADDRESS (msymbol);
- else
+ /* Find DT_MIPS_RLD_MAP. */
+ if (scan_dyntag (DT_MIPS_RLD_MAP, exec_bfd, &dyn_ptr))
+ {
+ gdb_byte *pbuf;
+ int pbuf_size = TYPE_LENGTH (builtin_type_void_data_ptr);
+ pbuf = alloca (pbuf_size);
+ /* DT_MIPS_RLD_MAP contains a pointer to the address
+ of the dynamic link structure. */
+ if (target_read_memory (dyn_ptr, pbuf, pbuf_size))
return 0;
+ return extract_typed_address (pbuf, builtin_type_void_data_ptr);
}
- dyninfo_addr = bfd_section_vma (exec_bfd, dyninfo_sect);
-
- /* Read in .dynamic section, silently ignore errors. */
- dyninfo_sect_size = bfd_section_size (exec_bfd, dyninfo_sect);
- buf = alloca (dyninfo_sect_size);
- if (target_read_memory (dyninfo_addr, buf, dyninfo_sect_size))
- return 0;
-
- /* Find the DT_DEBUG entry in the the .dynamic section.
- For mips elf we look for DT_MIPS_RLD_MAP, mips elf apparently has
- no DT_DEBUG entries. */
-
- arch_size = bfd_get_arch_size (exec_bfd);
- if (arch_size == -1) /* failure */
- return 0;
-
- if (arch_size == 32)
- { /* 32-bit elf */
- for (bufend = buf + dyninfo_sect_size;
- buf < bufend;
- buf += sizeof (Elf32_External_Dyn))
- {
- Elf32_External_Dyn *x_dynp = (Elf32_External_Dyn *) buf;
- long dyn_tag;
- CORE_ADDR dyn_ptr;
-
- dyn_tag = bfd_h_get_32 (exec_bfd, (bfd_byte *) x_dynp->d_tag);
- if (dyn_tag == DT_NULL)
- break;
- else if (dyn_tag == DT_DEBUG)
- {
- dyn_ptr = bfd_h_get_32 (exec_bfd,
- (bfd_byte *) x_dynp->d_un.d_ptr);
- return dyn_ptr;
- }
- else if (dyn_tag == DT_MIPS_RLD_MAP)
- {
- gdb_byte *pbuf;
- int pbuf_size = TYPE_LENGTH (builtin_type_void_data_ptr);
-
- pbuf = alloca (pbuf_size);
- /* DT_MIPS_RLD_MAP contains a pointer to the address
- of the dynamic link structure. */
- dyn_ptr = bfd_h_get_32 (exec_bfd,
- (bfd_byte *) x_dynp->d_un.d_ptr);
- if (target_read_memory (dyn_ptr, pbuf, pbuf_size))
- return 0;
- return extract_typed_address (pbuf, builtin_type_void_data_ptr);
- }
- }
- }
- else /* 64-bit elf */
- {
- for (bufend = buf + dyninfo_sect_size;
- buf < bufend;
- buf += sizeof (Elf64_External_Dyn))
- {
- Elf64_External_Dyn *x_dynp = (Elf64_External_Dyn *) buf;
- long dyn_tag;
- CORE_ADDR dyn_ptr;
-
- dyn_tag = bfd_h_get_64 (exec_bfd, (bfd_byte *) x_dynp->d_tag);
- if (dyn_tag == DT_NULL)
- break;
- else if (dyn_tag == DT_DEBUG)
- {
- dyn_ptr = bfd_h_get_64 (exec_bfd,
- (bfd_byte *) x_dynp->d_un.d_ptr);
- return dyn_ptr;
- }
- else if (dyn_tag == DT_MIPS_RLD_MAP)
- {
- gdb_byte *pbuf;
- int pbuf_size = TYPE_LENGTH (builtin_type_void_data_ptr);
-
- pbuf = alloca (pbuf_size);
- /* DT_MIPS_RLD_MAP contains a pointer to the address
- of the dynamic link structure. */
- dyn_ptr = bfd_h_get_64 (exec_bfd,
- (bfd_byte *) x_dynp->d_un.d_ptr);
- if (target_read_memory (dyn_ptr, pbuf, pbuf_size))
- return 0;
- return extract_typed_address (pbuf, builtin_type_void_data_ptr);
- }
- }
- }
+ /* This may be a static executable. Look for the symbol
+ conventionally named _r_debug, as a last resort. */
+ msymbol = lookup_minimal_symbol ("_r_debug", NULL, symfile_objfile);
+ if (msymbol != NULL)
+ return SYMBOL_VALUE_ADDRESS (msymbol);
/* DT_DEBUG entry not found. */
return 0;
@@ -1554,6 +1541,24 @@ svr4_lp64_fetch_link_map_offsets (void)
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
+ || scan_dyntag (DT_SYMBOLIC, objfile->obfd, NULL) != 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
@@ -1569,6 +1574,7 @@ _initialize_svr4_solib (void)
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;