diff options
author | Milian Wolff <milian.wolff@kdab.com> | 2017-05-14 01:55:30 +0200 |
---|---|---|
committer | Milian Wolff <milian.wolff@kdab.com> | 2017-09-06 10:36:49 +0000 |
commit | cd24974ea8da75ad264ba981ed16215fabe70ba7 (patch) | |
tree | 1d33445efac48a2f07aba483a14c338633388542 | |
parent | 9917e10ade3cb0c4fd3404c41541b43efe97c3fe (diff) |
Extend fallback code to find debug link file based on original path
By remembering the path under which a file was originally referenced
in the mmap call, we can use this information to find debug link
files. I.e. we will now try to find the debug link file in the
original binary target folder, which is where this debug link file
often resides.
This is useful for lazy people like me who don't want to set the
application path every time they use perfparser.
Change-Id: I8e33f137b186ed857b9b4da1d0618d0ae903d0cd
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
-rw-r--r-- | app/perfelfmap.cpp | 13 | ||||
-rw-r--r-- | app/perfelfmap.h | 12 | ||||
-rw-r--r-- | app/perfsymboltable.cpp | 17 | ||||
-rw-r--r-- | tests/auto/elfmap/tst_elfmap.cpp | 4 |
4 files changed, 35 insertions, 11 deletions
diff --git a/app/perfelfmap.cpp b/app/perfelfmap.cpp index b6a3b1a..a55bfd5 100644 --- a/app/perfelfmap.cpp +++ b/app/perfelfmap.cpp @@ -29,6 +29,7 @@ QDebug operator<<(QDebug stream, const PerfElfMap::ElfInfo& info) << "localFile=" << info.localFile.absoluteFilePath() << ", " << "isFile=" << info.isFile() << ", " << "originalFileName=" << info.originalFileName << ", " + << "originalPath=" << info.originalPath << ", " << "addr=" << info.addr << ", " << "len=" << info.length << ", " << "pgoff=" << info.pgoff << ", " @@ -52,7 +53,8 @@ struct SortByAddr } bool PerfElfMap::registerElf(const quint64 addr, const quint64 len, quint64 pgoff, - const QFileInfo &fullPath, const QByteArray &originalFileName) + const QFileInfo &fullPath, const QByteArray &originalFileName, + const QByteArray &originalPath) { bool cacheInvalid = false; const quint64 addrEnd = addr + len; @@ -69,12 +71,13 @@ bool PerfElfMap::registerElf(const quint64 addr, const quint64 len, quint64 pgof // reinsert any fragments of it that remain. if (i->addr < addr) { - newElfs.push_back(ElfInfo(i->localFile, i->addr, addr - i->addr, - i->pgoff, i->originalFileName)); + newElfs.push_back(ElfInfo(i->localFile, i->addr, addr - i->addr, i->pgoff, + i->originalFileName, i->originalPath)); } if (iEnd > addrEnd) { newElfs.push_back(ElfInfo(i->localFile, addrEnd, iEnd - addrEnd, - i->pgoff + addrEnd - i->addr, i->originalFileName)); + i->pgoff + addrEnd - i->addr, + i->originalFileName, i->originalPath)); } removedElfs.push_back(std::distance(m_elfs.begin(), i)); @@ -90,7 +93,7 @@ bool PerfElfMap::registerElf(const quint64 addr, const quint64 len, quint64 pgof for (auto it = removedElfs.rbegin(), end = removedElfs.rend(); it != end; ++it) m_elfs.remove(*it); - newElfs.push_back(ElfInfo(fullPath, addr, len, pgoff, originalFileName)); + newElfs.push_back(ElfInfo(fullPath, addr, len, pgoff, originalFileName, originalPath)); for (const auto &elf : newElfs) { auto it = std::lower_bound(m_elfs.begin(), m_elfs.end(), diff --git a/app/perfelfmap.h b/app/perfelfmap.h index 8812721..47c6fe5 100644 --- a/app/perfelfmap.h +++ b/app/perfelfmap.h @@ -30,11 +30,15 @@ public: struct ElfInfo { explicit ElfInfo(const QFileInfo &localFile = QFileInfo(), quint64 addr = 0, quint64 length = 0, quint64 pgoff = 0, - const QByteArray &originalFileName = {}) : + const QByteArray &originalFileName = {}, + const QByteArray &originalPath = {}) : localFile(localFile), originalFileName(originalFileName.isEmpty() ? localFile.fileName().toLocal8Bit() : originalFileName), + originalPath(originalPath.isEmpty() + ? localFile.absoluteFilePath().toLocal8Bit() + : originalPath), addr(addr), length(length), pgoff(pgoff) {} @@ -53,6 +57,7 @@ public: return isFile() == rhs.isFile() && (!isFile() || localFile == rhs.localFile) && originalFileName == rhs.originalFileName + && originalPath == rhs.originalPath && addr == rhs.addr && length == rhs.length && pgoff == rhs.pgoff; @@ -60,13 +65,16 @@ public: QFileInfo localFile; QByteArray originalFileName; + QByteArray originalPath; quint64 addr; quint64 length; quint64 pgoff; }; bool registerElf(quint64 addr, quint64 len, quint64 pgoff, - const QFileInfo &fullPath, const QByteArray &originalFileName = {}); + const QFileInfo &fullPath, + const QByteArray &originalFileName = {}, + const QByteArray &originalPath = {}); ElfInfo findElf(quint64 ip) const; bool isEmpty() const diff --git a/app/perfsymboltable.cpp b/app/perfsymboltable.cpp index 604d68e..e791675 100644 --- a/app/perfsymboltable.cpp +++ b/app/perfsymboltable.cpp @@ -326,7 +326,7 @@ void PerfSymbolTable::registerElf(const PerfRecordMmap &mmap, const QByteArray & } bool cacheInvalid = m_elfs.registerElf(mmap.addr(), mmap.len(), mmap.pgoff(), fullPath, - fileName.toUtf8()); + fileName.toUtf8(), mmap.filename()); // There is no need to clear the symbol or location caches in PerfUnwind. Some locations become // stale this way, but we still need to keep their IDs, as the receiver might still use them for @@ -507,7 +507,20 @@ int PerfSymbolTable::findDebugInfo(Dwfl_Module *module, const char *moduleName, // fall-back, mostly for situations where we loaded a file via it's build-id. // search all known paths for the debug link in that case - const auto debugLinkFile = findFile(debugLink, QFile(debugLink).fileName()); + const auto debugLinkString = QFile(debugLink).fileName(); + auto debugLinkFile = findFile(debugLink, debugLinkString); + if (!debugLinkFile.isFile()) { + // fall-back to original file path with debug link file name + const auto &elf = m_elfs.findElf(base); + const auto &dir = QFileInfo(m_unwind->systemRoot() + + QString::fromUtf8(elf.originalPath)).absoluteDir(); + debugLinkFile.setFile(dir, debugLinkString); + if (!debugLinkFile.isFile()) { // try again in .debug folder + debugLinkFile.setFile(dir, QLatin1String(".debug") + + QDir::separator() + debugLinkString); + } + } + if (!debugLinkFile.isFile()) return ret; diff --git a/tests/auto/elfmap/tst_elfmap.cpp b/tests/auto/elfmap/tst_elfmap.cpp index de54e82..d56442b 100644 --- a/tests/auto/elfmap/tst_elfmap.cpp +++ b/tests/auto/elfmap/tst_elfmap.cpp @@ -27,8 +27,8 @@ namespace { bool registerElf(PerfElfMap *map, const PerfElfMap::ElfInfo &info) { - return map->registerElf(info.addr, info.length, info.pgoff, - info.localFile, info.originalFileName); + return map->registerElf(info.addr, info.length, info.pgoff, info.localFile, + info.originalFileName, info.originalPath); } } |