diff options
-rw-r--r-- | app/perfunwind.cpp | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/app/perfunwind.cpp b/app/perfunwind.cpp index 09d17ce..5839322 100644 --- a/app/perfunwind.cpp +++ b/app/perfunwind.cpp @@ -300,8 +300,10 @@ static int frameCallback(Dwfl_Frame *state, void *arg) Dwarf_Addr pc = 0; PerfUnwind::UnwindInfo *ui = static_cast<PerfUnwind::UnwindInfo *>(arg); - bool isactivation; - if (!dwfl_frame_pc(state, &pc, &isactivation) + // do not query for activation directly, as this could potentially advance + // the unwinder internally - we must first ensure the module for the pc + // is reported + if (!dwfl_frame_pc(state, &pc, NULL) || (ui->maxFrames != -1 && ui->frames.length() > ui->maxFrames) || pc == 0) { ui->firstGuessedFrame = ui->frames.length(); @@ -309,9 +311,17 @@ static int frameCallback(Dwfl_Frame *state, void *arg) return DWARF_CB_ABORT; } + auto* symbolTable = ui->unwind->symbolTable(ui->sample->pid()); + + // ensure the module is reported + // if that fails, we will still try to unwind based on frame pointer + symbolTable->module(pc); + + // now we can query for the activation flag + bool isactivation = false; + dwfl_frame_pc(state, &pc, &isactivation); Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1); - auto* symbolTable = ui->unwind->symbolTable(ui->sample->pid()); // isKernel = false as unwinding generally only works on user code bool isInterworking = false; const auto frame = symbolTable->lookupFrame(pc_adjusted, false, &isInterworking); |