diff options
author | Eike Ziller <eike.ziller@qt.io> | 2018-02-01 09:56:38 +0100 |
---|---|---|
committer | Eike Ziller <eike.ziller@qt.io> | 2018-02-01 09:56:38 +0100 |
commit | 2c52cab42d1b3070e26137299cbd9b0677af376c (patch) | |
tree | 0e09d6f95e48b97f05f52930ed8626b4c0ed67ff | |
parent | d35f2ee49a094d8462c0aa92735fca4993cc04e4 (diff) | |
parent | 37b6fd17c306c13333cb3bc0ad0a0ad357e2fe85 (diff) |
Merge remote-tracking branch 'origin/4.6'
Change-Id: Ide7a92f4f331c8df3214dc15a9c8268a74e1420f
-rw-r--r-- | app/perfunwind.cpp | 39 | ||||
-rw-r--r-- | app/perfunwind.h | 2 |
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); |