summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Ziller <eike.ziller@qt.io>2017-03-16 10:27:22 +0100
committerEike Ziller <eike.ziller@qt.io>2017-03-16 10:27:22 +0100
commitec8049b495a56a13570ce866c1d20e2b990a1dcb (patch)
treee1ea71fb0168c090e0ff02503028a25c3da1780e
parent12bed4b961e7991452315f80a9adc5e825608554 (diff)
parent84ff48052518af05ccfe749863a155de33cef74c (diff)
Merge remote-tracking branch 'origin/4.3'
-rw-r--r--app/perfsymboltable.cpp2
-rw-r--r--app/perfunwind.cpp15
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);
}
}