Skip to content

Commit

Permalink
Strip PAC bits for return addresses in stack traces
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 705945725
Change-Id: I0a87d81244999849b163480758247b2e87c2d430
  • Loading branch information
Abseil Team authored and copybara-github committed Dec 13, 2024
1 parent fffac11 commit 3de434a
Showing 1 changed file with 15 additions and 1 deletion.
16 changes: 15 additions & 1 deletion absl/debugging/internal/stacktrace_aarch64-inl.inc
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,20 @@ static void **NextStackFrame(void **old_frame_pointer, const void *uc,
return new_frame_pointer;
}

// When PAC-RET (-mbranch-protection=pac-ret) is enabled, return addresses
// stored on the stack will be signed, which means that pointer bits outside of
// the VA range are potentially set. Since the stacktrace code is expected to
// return normal code pointers, this function clears those bits.
inline void* ClearPacBits(void* ptr) {
register void* x30 __asm__("x30") = ptr;
// The normal instruction for clearing PAC bits is XPACI, but for
// compatibility with ARM platforms that do not support pointer
// authentication, we use the hint space instruction XPACLRI instead. Hint
// space instructions behave as NOPs on unsupported platforms.
asm("xpaclri" : "+r"(x30));
return x30;
}

template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
// We count on the bottom frame being this one. See the comment
// at prev_return_address
Expand Down Expand Up @@ -219,7 +233,7 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
if (skip_count > 0) {
skip_count--;
} else {
result[n] = prev_return_address;
result[n] = ClearPacBits(prev_return_address);
if (IS_STACK_FRAMES) {
sizes[n] = static_cast<int>(
ComputeStackFrameSize(prev_frame_pointer, frame_pointer));
Expand Down

0 comments on commit 3de434a

Please sign in to comment.