diff options
author | Milian Wolff <milian.wolff@kdab.com> | 2017-06-27 23:13:08 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2019-05-02 13:51:08 +0000 |
commit | 4478ce2b6daf19bd1cb74d20bfe6b9dbf5df6c50 (patch) | |
tree | b80bb5ff3e86ea40c385682bcdcf1d92b3554298 | |
parent | 15a4e2d8dcde52994a85361154c44e7810779d7a (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.cpp | 35 |
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 { |