Skip to content

Commit bdc4911

Browse files
committed
Fix ARM64 callgrind stack unwinding
1 parent 9bea3b4 commit bdc4911

2 files changed

Lines changed: 35 additions & 16 deletions

File tree

callgrind/bbcc.c

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -653,34 +653,38 @@ void CLG_(setup_bbcc)(BB* bb)
653653
/* Manipulate JmpKind if needed, only using BB specific info */
654654

655655
csp = CLG_(current_call_stack).sp;
656-
657656
/* A return not matching the top call in our callstack is a jump */
658657
if ( (jmpkind == jk_Return) && (csp >0)) {
659658
Int csp_up = csp-1;
660659
call_entry* top_ce = &(CLG_(current_call_stack).entry[csp_up]);
661660

662-
/* We have a real return if
663-
* - the stack pointer (SP) left the current stack frame, or
664-
* - SP has the same value as when reaching the current function
665-
* and the address of this BB is the return address of last call
666-
* (we even allow to leave multiple frames if the SP stays the
667-
* same and we find a matching return address)
668-
* The latter condition is needed because on PPC, SP can stay
669-
* the same over CALL=b(c)l / RET=b(c)lr boundaries
661+
/* We have a real return if the stack pointer (SP) left the
662+
* current stack frame. If the return target matches an older
663+
* shadow-stack frame whose entry SP is also outside the current
664+
* native frame, unwind all intervening frames. This happens in
665+
* hand-written startup/loader code that can collapse multiple native
666+
* frames before returning to a saved link register.
667+
*
668+
* If SP is unchanged, require the return target to match the recorded
669+
* return address. This is needed because on PPC, SP can stay the same
670+
* over CALL=b(c)l / RET=b(c)lr boundaries.
670671
*/
671-
if (sp < top_ce->sp) popcount_on_return = 0;
672-
else if (top_ce->sp == sp) {
672+
if (sp < top_ce->sp) {
673+
popcount_on_return = 0;
674+
}
675+
else {
676+
Bool sp_changed = top_ce->sp != sp;
673677
while(1) {
674678
if (top_ce->ret_addr == bb_addr(bb)) break;
675679
if (csp_up>0) {
676680
csp_up--;
677681
top_ce = &(CLG_(current_call_stack).entry[csp_up]);
678-
if (top_ce->sp == sp) {
682+
if (top_ce->sp <= sp) {
679683
popcount_on_return++;
680-
continue;
684+
continue;
681685
}
682686
}
683-
popcount_on_return = 0;
687+
popcount_on_return = sp_changed ? 1 : 0;
684688
break;
685689
}
686690
}

callgrind/main.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,8 +1471,17 @@ static
14711471
void zero_state_cost(thread_info* t)
14721472
{
14731473
CLG_(zero_cost)( CLG_(sets).full, CLG_(current_state).cost );
1474+
CLG_(zero_cost)( CLG_(sets).full, t->lastdump_cost );
14741475
}
14751476

1477+
static
1478+
void sync_lastdump_cost(thread_info* t)
1479+
{
1480+
CLG_(copy_cost)( CLG_(sets).full, t->lastdump_cost,
1481+
CLG_(current_state).cost );
1482+
}
1483+
1484+
14761485
void CLG_(set_instrument_state)(const HChar* reason, Bool state)
14771486
{
14781487
if (CLG_(instrument_state) == state) {
@@ -1486,9 +1495,15 @@ void CLG_(set_instrument_state)(const HChar* reason, Bool state)
14861495

14871496
VG_(discard_translations_safely)( (Addr)0x1000, ~(SizeT)0xfff, "callgrind");
14881497

1489-
/* reset internal state: call stacks, simulator */
1498+
/* Reset internal state: call stacks, simulator. Switching collection off
1499+
* leaves already materialized BBCC/JCC costs for the final dump, but the
1500+
* live event counter no longer tracks a complete interval after collection
1501+
* stops inside a BB. Mark the live counter as already summarized so readers
1502+
* use the dumped totals instead of a stale/partial header summary. The next
1503+
* ON transition starts a fresh interval by clearing both current and
1504+
* last-dump counters. */
14901505
CLG_(forall_threads)(unwind_thread);
1491-
CLG_(forall_threads)(zero_state_cost);
1506+
CLG_(forall_threads)(state ? zero_state_cost : sync_lastdump_cost);
14921507
(*CLG_(cachesim).clear)();
14931508

14941509
if (VG_(clo_verbosity) > 1)

0 commit comments

Comments
 (0)