summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--app/perfsymboltable.cpp35
1 files changed, 35 insertions, 0 deletions
diff --git a/app/perfsymboltable.cpp b/app/perfsymboltable.cpp
index 50e6fbc..6469ce5 100644
--- a/app/perfsymboltable.cpp
+++ b/app/perfsymboltable.cpp
@@ -559,6 +559,40 @@ PerfElfMap::ElfInfo PerfSymbolTable::findElf(quint64 ip) const
return m_elfs.findElf(ip);
}
+static QByteArray fakeSymbolFromSection(Dwfl_Module *mod, Dwarf_Addr addr)
+{
+ Dwarf_Addr bias = 0;
+ auto elf = dwfl_module_getelf(mod, &bias);
+ const auto moduleAddr = addr - bias;
+ auto section = dwfl_module_address_section(mod, &addr, &bias);
+ if (!elf || !section)
+ return {};
+
+ size_t textSectionIndex = 0;
+ if (elf_getshdrstrndx(elf, &textSectionIndex) != 0)
+ return {};
+
+ size_t offset = 0;
+ if (auto shdr = elf64_getshdr(section)) {
+ offset = shdr->sh_name;
+ } else if (auto shdr = elf32_getshdr(section)) {
+ offset = shdr->sh_name;
+ }
+
+ auto str = elf_strptr(elf, textSectionIndex, offset);
+ if (!str || str == QLatin1String(".text"))
+ return {};
+
+ // mark .plt entries etc. by section name, see also:
+ // http://www.mail-archive.com/elfutils-devel@sourceware.org/msg00019.html
+ QByteArray sym = str;
+ sym.prepend('<');
+ sym.append('+');
+ sym.append(QByteArray::number(quint64(moduleAddr), 16));
+ sym.append('>');
+ return sym;
+}
+
int PerfSymbolTable::lookupFrame(Dwarf_Addr ip, bool isKernel,
bool *isInterworking)
{
@@ -626,6 +660,7 @@ int PerfSymbolTable::lookupFrame(Dwarf_Addr ip, bool isKernel,
}
if (off == addressLocation.address) {// no symbol found
+ symname = fakeSymbolFromSection(mod, addressLocation.address);
functionLocation.address = elfStart; // use the start of the elf as "function"
addressLocation.parentLocationId = m_unwind->resolveLocation(functionLocation);
} else {