summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2017-05-14 01:55:30 +0200
committerMilian Wolff <milian.wolff@kdab.com>2017-09-06 10:36:49 +0000
commitcd24974ea8da75ad264ba981ed16215fabe70ba7 (patch)
tree1d33445efac48a2f07aba483a14c338633388542
parent9917e10ade3cb0c4fd3404c41541b43efe97c3fe (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.cpp13
-rw-r--r--app/perfelfmap.h12
-rw-r--r--app/perfsymboltable.cpp17
-rw-r--r--tests/auto/elfmap/tst_elfmap.cpp4
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);
}
}