diff options
Diffstat (limited to 'app/perfaddresscache.cpp')
-rw-r--r-- | app/perfaddresscache.cpp | 59 |
1 files changed, 46 insertions, 13 deletions
diff --git a/app/perfaddresscache.cpp b/app/perfaddresscache.cpp index 73db84d..18edef1 100644 --- a/app/perfaddresscache.cpp +++ b/app/perfaddresscache.cpp @@ -19,6 +19,10 @@ #include "perfaddresscache.h" +#include "perfdwarfdiecache.h" + +#include <algorithm> + namespace { quint64 relativeAddress(const PerfElfMap::ElfInfo& elf, quint64 addr) { @@ -49,17 +53,30 @@ void PerfAddressCache::cache(const PerfElfMap::ElfInfo& elf, quint64 addr, (*invalidAddressCache)[addr] = entry; } +static bool operator<(const PerfAddressCache::SymbolCacheEntry &lhs, const PerfAddressCache::SymbolCacheEntry &rhs) +{ + return lhs.offset < rhs.offset; +} + +static bool operator==(const PerfAddressCache::SymbolCacheEntry &lhs, const PerfAddressCache::SymbolCacheEntry &rhs) +{ + return lhs.offset == rhs.offset && lhs.size == rhs.size; +} + static bool operator<(const PerfAddressCache::SymbolCacheEntry &lhs, quint64 addr) { return lhs.offset < addr; } -PerfAddressCache::SymbolCacheEntry PerfAddressCache::findSymbol(const PerfElfMap::ElfInfo& elf, - quint64 addr) const + +bool PerfAddressCache::hasSymbolCache(const QByteArray &filePath) const { - Q_ASSERT(elf.isValid()); - const auto &symbols = m_symbolCache.value(elf.originalPath); - const auto relAddr = relativeAddress(elf, addr); + return m_symbolCache.contains(filePath); +} + +PerfAddressCache::SymbolCacheEntry PerfAddressCache::findSymbol(const QByteArray& filePath, quint64 relAddr) +{ + auto &symbols = m_symbolCache[filePath]; auto it = std::lower_bound(symbols.begin(), symbols.end(), relAddr); if (it != symbols.end() && it->offset == relAddr) @@ -69,17 +86,33 @@ PerfAddressCache::SymbolCacheEntry PerfAddressCache::findSymbol(const PerfElfMap --it; - if (it->offset <= relAddr && it->offset + it->size > relAddr) + if (it->offset <= relAddr && it->offset + it->size > relAddr) { + // demangle symbols on demand instead of demangling all symbols directly + // hopefully most of the symbols we won't ever encounter after all + if (!it->demangled) { + it->symname = demangle(it->symname); + it->demangled = true; + } return *it; + } return {}; } -void PerfAddressCache::cacheSymbol(const PerfElfMap::ElfInfo& elf, quint64 startAddr, quint64 size, - const QByteArray& symname) +void PerfAddressCache::setSymbolCache(const QByteArray &filePath, SymbolCache cache) { - Q_ASSERT(elf.isValid()); - auto &symbols = m_symbolCache[elf.originalPath]; - const auto offset = relativeAddress(elf, startAddr); - auto it = std::lower_bound(symbols.begin(), symbols.end(), offset); - symbols.insert(it, {offset, size, symname}); + /* + * use stable_sort to produce results that are comparable to what addr2line would + * return when we have entries like this in the symtab: + * + * 000000000045a130 l F .text 0000000000000033 .hidden __memmove_avx_unaligned + * 000000000045a180 l F .text 00000000000003d8 .hidden __memmove_avx_unaligned_erms + * 000000000045a180 l F .text 00000000000003d8 .hidden __memcpy_avx_unaligned_erms + * 000000000045a130 l F .text 0000000000000033 .hidden __memcpy_avx_unaligned + * + * here, addr2line would always find the first entry. we want to do the same + */ + + std::stable_sort(cache.begin(), cache.end()); + cache.erase(std::unique(cache.begin(), cache.end()), cache.end()); + m_symbolCache[filePath] = cache; } |