summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2008-12-15 14:50:29 +0100
committerMark Wielaard <mjw@redhat.com>2008-12-15 14:50:29 +0100
commit13d343c0c39e334cf11ee06cbc0f3ec01d440f41 (patch)
treeaa5fc57aa70fee41346595e0cfde056e9240994d
parentd2f4d7286629da6e9f1b844beefb141a4d3ef2c3 (diff)
downloadsystemtap-steved-13d343c0c39e334cf11ee06cbc0f3ec01d440f41.tar.gz
systemtap-steved-13d343c0c39e334cf11ee06cbc0f3ec01d440f41.tar.xz
systemtap-steved-13d343c0c39e334cf11ee06cbc0f3ec01d440f41.zip
Work around buggy dwfl_module_relocate_address in dump_unwindsyms.
-rw-r--r--ChangeLog5
-rw-r--r--translate.cxx23
2 files changed, 25 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index c46c0ef2..9cb4949d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2008-12-15 Mark Wielaard <mjw@redhat.com>
+
+ * translate.cxx (dump_unwindsyms): Work around buggy
+ dwfl_module_relocate_address.
+
2008-12-10 Mark Wielaard <mjw@redhat.com>
* tapsets.cxx
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")