summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Ziller <eike.ziller@qt.io>2018-02-01 09:56:38 +0100
committerEike Ziller <eike.ziller@qt.io>2018-02-01 09:56:38 +0100
commit2c52cab42d1b3070e26137299cbd9b0677af376c (patch)
tree0e09d6f95e48b97f05f52930ed8626b4c0ed67ff
parentd35f2ee49a094d8462c0aa92735fca4993cc04e4 (diff)
parent37b6fd17c306c13333cb3bc0ad0a0ad357e2fe85 (diff)
Merge remote-tracking branch 'origin/4.6'
-rw-r--r--app/perfunwind.cpp39
-rw-r--r--app/perfunwind.h2
2 files changed, 26 insertions, 15 deletions
diff --git a/app/perfunwind.cpp b/app/perfunwind.cpp
index 849b220..94b68ef 100644
--- a/app/perfunwind.cpp
+++ b/app/perfunwind.cpp
@@ -365,8 +365,12 @@ static int frameCallback(Dwfl_Frame *state, void *arg)
return DWARF_CB_OK;
}
-void PerfUnwind::unwindStack(Dwfl *dwfl)
+void PerfUnwind::unwindStack()
{
+ Dwfl *dwfl = symbolTable(m_currentUnwind.sample->pid())->attachDwfl(&m_currentUnwind);
+ if (!dwfl)
+ return;
+
dwfl_getthread_frames(dwfl, m_currentUnwind.sample->pid(), frameCallback, &m_currentUnwind);
if (m_currentUnwind.isInterworking) {
QVector<qint32> savedFrames = m_currentUnwind.frames;
@@ -417,12 +421,14 @@ void PerfUnwind::resolveCallchain()
// sometimes it skips the first user frame.
if (i == 0 && !isKernel && ip != m_currentUnwind.sample->ip()) {
+ symbols->attachDwfl(&m_currentUnwind);
m_currentUnwind.frames.append(symbols->lookupFrame(
m_currentUnwind.sample->ip(), false,
&m_currentUnwind.isInterworking));
}
if (ip <= PERF_CONTEXT_MAX) {
+ symbols->attachDwfl(&m_currentUnwind);
m_currentUnwind.frames.append(symbols->lookupFrame(
ip, isKernel,
&m_currentUnwind.isInterworking));
@@ -508,8 +514,7 @@ void PerfUnwind::analyze(const PerfRecordSample &sample)
if (m_stats.enabled) // don't do any time intensive work in stats mode
return;
- const bool isKernel = ipIsInKernelSpace(sample.ip());
-
+ PerfSymbolTable *kernelSymbols = symbolTable(s_kernelPid);
PerfSymbolTable *userSymbols = symbolTable(sample.pid());
for (int unwindingAttempt = 0; unwindingAttempt < 2; ++unwindingAttempt) {
@@ -519,32 +524,38 @@ void PerfUnwind::analyze(const PerfRecordSample &sample)
m_currentUnwind.frames.clear();
userSymbols->updatePerfMap();
-
- Dwfl *userDwfl = userSymbols->attachDwfl(&m_currentUnwind);
if (sample.callchain().length() > 0)
resolveCallchain();
+ bool userDirty = userSymbols->cacheIsDirty();
+ bool kernelDirty = kernelSymbols->cacheIsDirty();
+
// only try to unwind when resolveCallchain did not dirty the cache
- if (!userSymbols->cacheIsDirty()) {
- if (userDwfl && sample.registerAbi() != 0 && sample.userStack().length() > 0)
- unwindStack(userDwfl);
- else
+ if (!userDirty && !kernelDirty) {
+ if (sample.registerAbi() != 0 && sample.userStack().length() > 0) {
+ unwindStack();
+ userDirty = userSymbols->cacheIsDirty();
+ } else {
break;
+ }
}
// when the cache is dirty, we clean it up and try again, otherwise we can
// stop as unwinding should have succeeded
- if (userSymbols->cacheIsDirty())
+ if (userDirty)
userSymbols->clearCache(); // fail, try again
- else
+ if (kernelDirty)
+ kernelSymbols->clearCache();
+ if (!userDirty && !kernelDirty)
break; // success
}
// If nothing was found, at least look up the IP
if (m_currentUnwind.frames.isEmpty()) {
- PerfSymbolTable *symbols = isKernel ? symbolTable(s_kernelPid) : userSymbols;
- m_currentUnwind.frames.append(symbols->lookupFrame(sample.ip(), isKernel,
- &m_currentUnwind.isInterworking));
+ const bool isKernel = ipIsInKernelSpace(sample.ip());
+ PerfSymbolTable *ipSymbols = isKernel ? kernelSymbols : userSymbols;
+ m_currentUnwind.frames.append(ipSymbols->lookupFrame(sample.ip(), isKernel,
+ &m_currentUnwind.isInterworking));
}
diff --git a/app/perfunwind.h b/app/perfunwind.h
index a18d6a0..82713a3 100644
--- a/app/perfunwind.h
+++ b/app/perfunwind.h
@@ -284,7 +284,7 @@ private:
Stats m_stats;
- void unwindStack(Dwfl *dwfl);
+ void unwindStack();
void resolveCallchain();
void analyze(const PerfRecordSample &sample);
void sendBuffer(const QByteArray &buffer);