On Mon, Nov 18, 2013 at 08:29:05AM -0800, Ian Lance Taylor wrote: > On Mon, Nov 18, 2013 at 5:11 AM, Jakub Jelinek <ja...@redhat.com> wrote: > > > > info->dlpi_addr == 0 is true for executables (but those have also > > info->dlpi_name set to ""), but not just for those, it is true also > > for successfully prelinked shared libraries or any other libraries that > > have been linked at non-zero offset and the dynamic linker managed to mmap > > them where they were prelinked resp. linked to. > > > > BTW, I'm surprised you aren't adding base_address (well, in fact it is > > actually not base address, but load bias, difference between load address > > and link base address) to elf_initialize_syminfo created symbol addresses, > > because all of them should be biased by the load address. > > And, elf_initialize_syminfo should ignore st_shndx == SHN_UNDEF symbols, > > those shouldn't be biased but not even entered into the table. > > You're right, these are bugs.
So what about this fix then? Tested on a short testcase that links against a shared library without debug info and looks up the symbol using backtrace_syminfo. make check in libbacktrace also passes. 2013-11-18 Jakub Jelinek <ja...@redhat.com> * elf.c (SHN_UNDEF): Define. (elf_initialize_syminfo): Add base_address argument. Ignore symbols with st_shndx == SHN_UNDEF. Add base_address to address fields. (elf_add): Adjust caller. --- libbacktrace/elf.c.jj 2013-11-18 12:48:07.000000000 +0100 +++ libbacktrace/elf.c 2013-11-18 17:41:38.903835173 +0100 @@ -98,6 +98,7 @@ dl_iterate_phdr (int (*callback) (struct #undef EV_CURRENT #undef SHN_LORESERVE #undef SHN_XINDEX +#undef SHN_UNDEF #undef SHT_SYMTAB #undef SHT_STRTAB #undef SHT_DYNSYM @@ -183,6 +184,7 @@ typedef struct { b_elf_wxword sh_entsize; /* Entry size if section holds table */ } b_elf_shdr; /* Elf_Shdr. */ +#define SHN_UNDEF 0x0000 /* Undefined section */ #define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */ #define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */ @@ -342,6 +344,7 @@ elf_symbol_search (const void *vkey, con static int elf_initialize_syminfo (struct backtrace_state *state, + uintptr_t base_address, const unsigned char *symtab_data, size_t symtab_size, const unsigned char *strtab, size_t strtab_size, backtrace_error_callback error_callback, @@ -365,7 +368,8 @@ elf_initialize_syminfo (struct backtrace int info; info = sym->st_info & 0xf; - if (info == STT_FUNC || info == STT_OBJECT) + if ((info == STT_FUNC || info == STT_OBJECT) + && sym->st_shndx != SHN_UNDEF) ++elf_symbol_count; } @@ -385,6 +389,8 @@ elf_initialize_syminfo (struct backtrace info = sym->st_info & 0xf; if (info != STT_FUNC && info != STT_OBJECT) continue; + if (sym->st_shndx == SHN_UNDEF) + continue; if (sym->st_name >= strtab_size) { error_callback (data, "symbol string index out of range", 0); @@ -393,7 +399,7 @@ elf_initialize_syminfo (struct backtrace return 0; } elf_symbols[j].name = (const char *) strtab + sym->st_name; - elf_symbols[j].address = sym->st_value; + elf_symbols[j].address = sym->st_value + base_address; elf_symbols[j].size = sym->st_size; ++j; } @@ -733,7 +739,7 @@ elf_add (struct backtrace_state *state, if (sdata == NULL) goto fail; - if (!elf_initialize_syminfo (state, + if (!elf_initialize_syminfo (state, base_address, symtab_view.data, symtab_shdr->sh_size, strtab_view.data, strtab_shdr->sh_size, error_callback, data, sdata)) Jakub