summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2017-06-27 23:13:08 +0200
committerUlf Hermann <ulf.hermann@qt.io>2019-05-02 13:51:08 +0000
commit4478ce2b6daf19bd1cb74d20bfe6b9dbf5df6c50 (patch)
treeb80bb5ff3e86ea40c385682bcdcf1d92b3554298
parent15a4e2d8dcde52994a85361154c44e7810779d7a (diff)
Create fake symbols for addresses in .plt section
This is not as good as the fallback that binutils has. But any proper solution should be put into elfutils itself. See also: http://www.mail-archive.com/elfutils-devel@sourceware.org/msg00019.html Change-Id: Ief4d6450f97f0e25874a6163f442a8c1c257748e Reviewed-by: Milian Wolff <milian.wolff@kdab.com>
-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 {