summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2022-05-28 22:28:37 +0200
committerMilian Wolff <milian.wolff@kdab.com>2022-06-08 20:18:20 +0000
commit443bd9ba86615f319fecd3fbb47f1c2413ae373c (patch)
treeac280fdd1a6130f31fe65133ddca5cdb111a0f17
parent10c8a4e0ce9134f2d5cabb162b3b6d1f287ce8b7 (diff)
Move code to extract symbol cache into perfaddresscache
This makes the code more easily reusable and moves code that belongs together logically into the same file. Change-Id: Icce3a1ce4dc05f3a7cd9333fa7c88bd3a1b118ec Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
-rw-r--r--app/perfaddresscache.cpp17
-rw-r--r--app/perfaddresscache.h18
-rw-r--r--app/perfsymboltable.cpp35
3 files changed, 38 insertions, 32 deletions
diff --git a/app/perfaddresscache.cpp b/app/perfaddresscache.cpp
index 825c2cd..278ea2f 100644
--- a/app/perfaddresscache.cpp
+++ b/app/perfaddresscache.cpp
@@ -120,3 +120,20 @@ void PerfAddressCache::setSymbolCache(const QByteArray &filePath, SymbolCache ca
cache.erase(std::unique(cache.begin(), cache.end()), cache.end());
m_symbolCache[filePath] = cache;
}
+
+PerfAddressCache::SymbolCache PerfAddressCache::extractSymbols(Dwfl_Module *module, quint64 elfStart, bool isArmArch)
+{
+ PerfAddressCache::SymbolCache cache;
+
+ const auto numSymbols = dwfl_module_getsymtab(module);
+ for (int i = 0; i < numSymbols; ++i) {
+ GElf_Sym sym;
+ GElf_Addr symAddr;
+ const auto symbol = dwfl_module_getsym_info(module, i, &sym, &symAddr, nullptr, nullptr, nullptr);
+ if (symbol) {
+ const quint64 start = alignedAddress(sym.st_value, isArmArch);
+ cache.append({symAddr - elfStart, start, sym.st_size, symbol});
+ }
+ }
+ return cache;
+}
diff --git a/app/perfaddresscache.h b/app/perfaddresscache.h
index 055ac3e..fd978bd 100644
--- a/app/perfaddresscache.h
+++ b/app/perfaddresscache.h
@@ -25,9 +25,23 @@
#include "perfelfmap.h"
+#include <libdwfl.h>
+
class PerfAddressCache
{
public:
+ static quint64 symbolAddress(quint64 addr, bool isArmArch)
+ {
+ // For dwfl API call we need the raw pointer into symtab, so we need to adjust ip.
+ return (!isArmArch || (addr & 1)) ? addr : addr + 1;
+ }
+
+ static quint64 alignedAddress(quint64 addr, bool isArmArch)
+ {
+ // Adjust addr back. The symtab entries are 1 off for all practical purposes.
+ return (isArmArch && (addr & 1)) ? addr - 1 : addr;
+ }
+
struct AddressCacheEntry
{
AddressCacheEntry(int locationId = -1, bool isInterworking = false)
@@ -73,6 +87,10 @@ public:
/// find the symbol that encompasses @p relAddr in @p filePath
/// if the found symbol wasn't yet demangled, it will be demangled now
SymbolCacheEntry findSymbol(const QByteArray &filePath, quint64 relAddr);
+
+ /// extract all symbols in @p module into a structure suitable to be passed to @p setSymbols
+ static SymbolCache extractSymbols(Dwfl_Module *module, quint64 elfStart, bool isArmArch);
+
private:
QHash<QByteArray, OffsetAddressCache> m_cache;
QHash<QByteArray, SymbolCache> m_symbolCache;
diff --git a/app/perfsymboltable.cpp b/app/perfsymboltable.cpp
index ac8ae11..f025670 100644
--- a/app/perfsymboltable.cpp
+++ b/app/perfsymboltable.cpp
@@ -611,35 +611,6 @@ static QByteArray fakeSymbolFromSection(Dwfl_Module *mod, Dwarf_Addr addr)
return sym;
}
-static quint64 symbolAddress(quint64 addr, bool isArmArch)
-{
- // For dwfl API call we need the raw pointer into symtab, so we need to adjust ip.
- return (!isArmArch || (addr & 1)) ? addr : addr + 1;
-}
-
-static quint64 alignedAddress(quint64 addr, bool isArmArch)
-{
- // Adjust addr back. The symtab entries are 1 off for all practical purposes.
- return (isArmArch && (addr & 1)) ? addr - 1 : addr;
-}
-
-static PerfAddressCache::SymbolCache cacheSymbols(Dwfl_Module *module, quint64 elfStart, bool isArmArch)
-{
- PerfAddressCache::SymbolCache cache;
-
- const auto numSymbols = dwfl_module_getsymtab(module);
- for (int i = 0; i < numSymbols; ++i) {
- GElf_Sym sym;
- GElf_Addr symAddr;
- const auto symbol = dwfl_module_getsym_info(module, i, &sym, &symAddr, nullptr, nullptr, nullptr);
- if (symbol) {
- const quint64 start = alignedAddress(sym.st_value, isArmArch);
- cache.append({symAddr - elfStart, start, sym.st_size, symbol});
- }
- }
- return cache;
-}
-
int PerfSymbolTable::lookupFrame(Dwarf_Addr ip, bool isKernel,
bool *isInterworking)
{
@@ -666,7 +637,7 @@ int PerfSymbolTable::lookupFrame(Dwarf_Addr ip, bool isKernel,
Dwfl_Module *mod = module(ip, elf);
const bool isArmArch = (m_unwind->architecture() == PerfRegisterInfo::ARCH_ARM);
- PerfUnwind::Location addressLocation(symbolAddress(ip, isArmArch), 0, -1, m_pid);
+ PerfUnwind::Location addressLocation(PerfAddressCache::symbolAddress(ip, isArmArch), 0, -1, m_pid);
PerfUnwind::Location functionLocation(addressLocation);
QByteArray symname;
@@ -680,7 +651,7 @@ int PerfSymbolTable::lookupFrame(Dwarf_Addr ip, bool isKernel,
// cache all symbols in a sorted lookup table and demangle them on-demand
// note that the symbols within the symtab aren't necessarily sorted,
// which makes searching repeatedly via dwfl_module_addrinfo potentially very slow
- addressCache->setSymbolCache(elf.originalPath, cacheSymbols(mod, elfStart, isArmArch));
+ addressCache->setSymbolCache(elf.originalPath, PerfAddressCache::extractSymbols(mod, elfStart, isArmArch));
}
auto cachedAddrInfo = addressCache->findSymbol(elf.originalPath, addressLocation.address - elfStart);
@@ -689,7 +660,7 @@ int PerfSymbolTable::lookupFrame(Dwarf_Addr ip, bool isKernel,
symname = cachedAddrInfo.symname;
start = cachedAddrInfo.value;
size = cachedAddrInfo.size;
- relAddr = alignedAddress(start + off, isArmArch);
+ relAddr = PerfAddressCache::alignedAddress(start + off, isArmArch);
Dwarf_Addr bias = 0;
functionLocation.address -= off; // in case we don't find anything better