summaryrefslogtreecommitdiffstats
path: root/app/perfsymboltable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'app/perfsymboltable.cpp')
-rw-r--r--app/perfsymboltable.cpp43
1 files changed, 31 insertions, 12 deletions
diff --git a/app/perfsymboltable.cpp b/app/perfsymboltable.cpp
index 41f9c1e..bc3f18c 100644
--- a/app/perfsymboltable.cpp
+++ b/app/perfsymboltable.cpp
@@ -172,8 +172,9 @@ static bool findInExtraPath(QFileInfo &path, const QString &fileName)
return false;
}
-void PerfSymbolTable::registerElf(const PerfRecordMmap &mmap, const QString &appPath,
- const QString &systemRoot, const QString &extraLibsPath)
+void PerfSymbolTable::registerElf(const PerfRecordMmap &mmap, const QByteArray &buildId,
+ const QString &appPath, const QString &systemRoot,
+ const QString &extraLibsPath, const QString &debugInfoPath)
{
QLatin1String filePath(mmap.filename());
// special regions, such as [heap], [vdso], [stack], ... as well as //anon
@@ -184,9 +185,26 @@ void PerfSymbolTable::registerElf(const PerfRecordMmap &mmap, const QString &app
if (isSpecialRegion) {
// don not set fullPath, these regions don't represent a real file
} else if (mmap.pid() != PerfUnwind::s_kernelPid) {
- fullPath.setFile(appPath);
- if (!findInExtraPath(fullPath, fileInfo.fileName())) {
- bool found = false;
+ bool found = false;
+ // first try to find the debug information via build id, if available
+ if (!buildId.isEmpty()) {
+ const QString buildIdPath = QString::fromUtf8(mmap.filename() + '/'
+ + buildId.toHex() + "/elf");
+ foreach (const QString &extraPath, debugInfoPath.split(QLatin1Char(':'))) {
+ fullPath.setFile(extraPath);
+ if (findInExtraPath(fullPath, buildIdPath)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ // try to find the file in the app path
+ fullPath.setFile(appPath);
+ found = findInExtraPath(fullPath, fileInfo.fileName());
+ }
+ if (!found) {
+ // try to find the file in the extra libs path
foreach (const QString &extraPath, extraLibsPath.split(QLatin1Char(':'))) {
fullPath.setFile(extraPath);
if (findInExtraPath(fullPath, fileInfo.fileName())) {
@@ -194,9 +212,9 @@ void PerfSymbolTable::registerElf(const PerfRecordMmap &mmap, const QString &app
break;
}
}
- if (!found)
- fullPath.setFile(systemRoot + filePath);
}
+ if (!found) // last fall-back, try the system root
+ fullPath.setFile(systemRoot + filePath);
if (!m_firstElfFile.isOpen() && fullPath.exists()) {
m_firstElfFile.setFileName(fullPath.absoluteFilePath());
@@ -218,7 +236,8 @@ void PerfSymbolTable::registerElf(const PerfRecordMmap &mmap, const QString &app
fullPath.setFile(systemRoot + filePath);
}
- bool cacheInvalid = m_elfs.registerElf(mmap.addr(), mmap.len(), mmap.pgoff(), fullPath);
+ bool cacheInvalid = m_elfs.registerElf(mmap.addr(), mmap.len(), mmap.pgoff(), fullPath,
+ fileInfo.fileName().toUtf8());
// 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
@@ -356,7 +375,7 @@ void PerfSymbolTable::parseDwarf(Dwarf_Die *cudie, Dwarf_Addr bias, qint32 binar
static void reportError(const PerfElfMap::ElfInfo& info, const char *message)
{
- qWarning() << "failed to report" << info.file.absoluteFilePath() << "for"
+ qWarning() << "failed to report" << info.localFile.absoluteFilePath() << "for"
<< hex << info.addr << dec << ":" << message;
}
@@ -371,8 +390,8 @@ Dwfl_Module *PerfSymbolTable::reportElf(const PerfElfMap::ElfInfo& info)
}
Dwfl_Module *ret = dwfl_report_elf(
- m_dwfl, info.file.fileName().toLocal8Bit().constData(),
- info.file.absoluteFilePath().toLocal8Bit().constData(), -1, info.addr,
+ m_dwfl, info.originalFileName.constData(),
+ info.localFile.absoluteFilePath().toLocal8Bit().constData(), -1, info.addr,
false);
if (!ret)
reportError(info, dwfl_errmsg(dwfl_errno()));
@@ -401,7 +420,7 @@ int PerfSymbolTable::lookupFrame(Dwarf_Addr ip, bool isKernel,
const auto& elf = findElf(ip);
if (elf.isValid()) {
- binaryId = m_unwind->resolveString(elf.file.fileName().toLocal8Bit());
+ binaryId = m_unwind->resolveString(elf.originalFileName);
elfStart = elf.addr;
if (m_dwfl && !mod)
mod = reportElf(elf);