diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2007-07-03 12:14:44 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@de.ibm.com> | 2007-07-03 12:14:44 +0000 |
commit | 3a40aaa0eb849a9aacd6f1e83b94fb8b0947cdfb (patch) | |
tree | 24c19c39630f502332f0e3042a9662c3f20019ad /gdb/solib-svr4.c | |
parent | 3ccac826a3edc921e1e6c5ded9502781cca509af (diff) | |
download | gdb-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.c | 212 |
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; |