diff options
Diffstat (limited to 'translate.cxx')
-rw-r--r-- | translate.cxx | 23 |
1 files changed, 20 insertions, 3 deletions
diff --git a/translate.cxx b/translate.cxx index 27f6a04b..bb976d59 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4523,9 +4523,26 @@ dump_unwindsyms (Dwfl_Module *m, if (n > 0) // only try to relocate if there exist relocation bases { - int ki = dwfl_module_relocate_address (m, &sym_addr); - dwfl_assert ("dwfl_module_relocate_address", ki >= 0); - secname = dwfl_module_relocation_info (m, ki, NULL); + // libdwfl up to 0.137 could miscalculate the relocated + // address for shared ET_DYN files (n > 0). Luckily + // dwfl_module_address_section does work correctly. + // Then we just need to add the section offset to get + // the (relative) address of the symbol when mapped in. + Dwarf_Addr bias; + Elf_Scn *sec; + GElf_Shdr *shdr, shdr_mem; + GElf_Ehdr *ehdr, ehdr_mem; + Elf *elf; + sec = dwfl_module_address_section (m, &sym_addr, &bias); + dwfl_assert ("dwfl_module_address_section", sec != NULL); + shdr = gelf_getshdr(sec, &shdr_mem); + sym_addr += shdr->sh_offset; + elf = dwfl_module_getelf (m, &bias); + ehdr = gelf_getehdr(elf, &ehdr_mem); + if (ehdr->e_type == ET_DYN) + secname = ""; + else + secname = elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name); } if (n == 1 && modname == "kernel") |