diff options
author | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2015-02-03 15:26:13 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@theqtcompany.com> | 2015-02-16 18:04:35 +0200 |
commit | be7d6f47f4309270cf7d288db47580c7037eafb9 (patch) | |
tree | d5e49b93ef477c41eb26728d8162da6175ce7ac8 | |
parent | 48db7f16d92adc9f660afe71272e53e9db4146f2 (diff) |
Take care of ARM .symtab weirdness when looking up symbols
Change-Id: I9409c6480a1ee6df11f92575133aec3b53bc087d
Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
-rw-r--r-- | perfunwind.cpp | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/perfunwind.cpp b/perfunwind.cpp index 73b9da0..3b6d09b 100644 --- a/perfunwind.cpp +++ b/perfunwind.cpp @@ -218,17 +218,27 @@ static PerfUnwind::Frame lookupSymbol(const PerfUnwind *unwind, Dwfl *dwfl, Dwar const char *filename = NULL; GElf_Sym sym; GElf_Off off; + + bool do_adjust = (unwind->architecture() == PerfRegisterInfo::ARCH_ARM); if (mod) { - symname = dwfl_module_addrinfo (mod, ip, &off, &sym, 0, 0, 0); + // For addrinfo we need the raw pointer into symtab, so we need to adjust ourselves. + symname = dwfl_module_addrinfo(mod, (!do_adjust || (ip & 1)) ? ip : ip + 1, &off, &sym, 0, + 0, 0); filename = dwfl_module_info(mod, 0, 0, 0, 0, 0, 0, 0); } - if (symname) + if (symname) { demangled = bfd_demangle(NULL, symname, 0x3); - else + // Adjust it back. The symtab entries are 1 off for all practical purposes. + return PerfUnwind::Frame((do_adjust && (sym.st_value & 1)) ? sym.st_value - 1 : + sym.st_value, + demangled ? demangled : symname, filename); + } else { qWarning() << "no symbol found for" << ip << "in" << filename; + return PerfUnwind::Frame(ip, symname, filename); + } + - return PerfUnwind::Frame(symname ? sym.st_value : ip, demangled ? demangled : symname, filename); } static int frameCallback(Dwfl_Frame *state, void *arg) |