summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@theqtcompany.com>2015-02-03 15:26:13 +0100
committerUlf Hermann <ulf.hermann@theqtcompany.com>2015-02-16 18:04:35 +0200
commitbe7d6f47f4309270cf7d288db47580c7037eafb9 (patch)
treed5e49b93ef477c41eb26728d8162da6175ce7ac8
parent48db7f16d92adc9f660afe71272e53e9db4146f2 (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.cpp18
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)