diff options
author | Eike Ziller <eike.ziller@qt.io> | 2017-03-16 10:27:22 +0100 |
---|---|---|
committer | Eike Ziller <eike.ziller@qt.io> | 2017-03-16 10:27:22 +0100 |
commit | ec8049b495a56a13570ce866c1d20e2b990a1dcb (patch) | |
tree | e1ea71fb0168c090e0ff02503028a25c3da1780e | |
parent | 12bed4b961e7991452315f80a9adc5e825608554 (diff) | |
parent | 84ff48052518af05ccfe749863a155de33cef74c (diff) |
Merge remote-tracking branch 'origin/4.3'
Change-Id: I63447a15bc912c00dfd1f003ffb955a96fae77d2
-rw-r--r-- | app/perfsymboltable.cpp | 2 | ||||
-rw-r--r-- | app/perfunwind.cpp | 15 |
2 files changed, 14 insertions, 3 deletions
diff --git a/app/perfsymboltable.cpp b/app/perfsymboltable.cpp index fccf857..b54ff76 100644 --- a/app/perfsymboltable.cpp +++ b/app/perfsymboltable.cpp @@ -484,7 +484,7 @@ int PerfSymbolTable::lookupFrame(Dwarf_Addr ip, quint64 timestamp, bool isKernel Q_ASSERT(m_unwind->hasSymbol(addressLocation.parentLocationId)); int locationId = m_unwind->resolveLocation(addressLocation); - *isInterworking = (symname == "$at"); + *isInterworking = (symname == "$a" || symname == "$t"); m_addressCache.insert(ip, {locationId, *isInterworking}); return locationId; } diff --git a/app/perfunwind.cpp b/app/perfunwind.cpp index 25022be..caf2ece 100644 --- a/app/perfunwind.cpp +++ b/app/perfunwind.cpp @@ -228,15 +228,20 @@ static int frameCallback(Dwfl_Frame *state, void *arg) Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1); // isKernel = false as unwinding generally only works on user code + bool isInterworking = false; ui->frames.append(ui->unwind->symbolTable(ui->sample->pid())->lookupFrame( - pc_adjusted, ui->sample->time(), false, &ui->isInterworking)); + pc_adjusted, ui->sample->time(), false, &isInterworking)); + if (isInterworking && ui->frames.length() == 1) + ui->isInterworking = true; return DWARF_CB_OK; } void PerfUnwind::unwindStack(Dwfl *dwfl) { dwfl_getthread_frames(dwfl, m_currentUnwind.sample->pid(), frameCallback, &m_currentUnwind); - if (m_currentUnwind.frames.length() == 1 && m_currentUnwind.isInterworking) { + if (m_currentUnwind.isInterworking) { + QVector<qint32> savedFrames = m_currentUnwind.frames; + // If it's an ARM interworking veneer, we assume that we can find a return address in LR and // no stack has been used for the veneer itself. // The reasoning is that any symbol jumped to by the veneer has to work with or without @@ -244,7 +249,13 @@ void PerfUnwind::unwindStack(Dwfl *dwfl) // must be the same in both cases. Thus, the veneer cannot touch the stack pointer and there // has to be a return address in LR, provided by the caller. // So, just try again, and make setInitialRegisters use LR for IP. + m_currentUnwind.frames.resize(1); // Keep the actual veneer frame dwfl_getthread_frames(dwfl, m_currentUnwind.sample->pid(), frameCallback, &m_currentUnwind); + + // If the LR trick didn't result in a longer stack trace than the regular unwinding, just + // revert it. + if (savedFrames.length() > m_currentUnwind.frames.length()) + m_currentUnwind.frames.swap(savedFrames); } } |