diff --git a/src/processor/stackwalker_arm64.cc b/src/processor/stackwalker_arm64.cc index f9660112..47e245ed 100644 --- a/src/processor/stackwalker_arm64.cc +++ b/src/processor/stackwalker_arm64.cc @@ -54,8 +54,29 @@ StackwalkerARM64::StackwalkerARM64(const SystemInfo* system_info, StackFrameSymbolizer* resolver_helper) : Stackwalker(system_info, memory, modules, resolver_helper), context_(context), - context_frame_validity_(StackFrameARM64::CONTEXT_VALID_ALL) { } + context_frame_validity_(StackFrameARM64::CONTEXT_VALID_ALL), + address_range_mask_(0xffffffffffffffff) { + if (modules && modules->module_count() > 0) { + // ARM64 supports storing pointer authentication codes in the upper bits of + // a pointer. Make a best guess at the range of valid addresses based on the + // range of loaded modules. + const CodeModule *high_module = + modules->GetModuleAtSequence(modules->module_count() - 1); + uint64_t mask = high_module->base_address() + high_module->size(); + mask |= mask >> 1; + mask |= mask >> 2; + mask |= mask >> 4; + mask |= mask >> 8; + mask |= mask >> 16; + mask |= mask >> 32; + address_range_mask_ = mask; + } +} +uint64_t StackwalkerARM64::PtrauthStrip(uint64_t ptr) { + uint64_t stripped = ptr & address_range_mask_; + return modules_ && modules_->GetModuleForAddress(stripped) ? stripped : ptr; +} StackFrame* StackwalkerARM64::GetContextFrame() { if (!context_) { @@ -71,6 +92,8 @@ StackFrame* StackwalkerARM64::GetContextFrame() { frame->context_validity = context_frame_validity_; frame->trust = StackFrame::FRAME_TRUST_CONTEXT; frame->instruction = frame->context.iregs[MD_CONTEXT_ARM64_REG_PC]; + frame->context.iregs[MD_CONTEXT_ARM64_REG_LR] = + PtrauthStrip(frame->context.iregs[MD_CONTEXT_ARM64_REG_LR]); return frame; } @@ -202,6 +225,8 @@ StackFrameARM64* StackwalkerARM64::GetCallerByFramePointer( return NULL; } + caller_lr = PtrauthStrip(caller_lr); + uint64_t caller_sp = last_fp ? last_fp + 16 : last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP]; diff --git a/src/processor/stackwalker_arm64.h b/src/processor/stackwalker_arm64.h index 121e8246..241383ea 100644 --- a/src/processor/stackwalker_arm64.h +++ b/src/processor/stackwalker_arm64.h @@ -68,6 +68,9 @@ class StackwalkerARM64 : public Stackwalker { } private: + // Strip pointer authentication codes from an address. + uint64_t PtrauthStrip(uint64_t ptr); + // Implementation of Stackwalker, using arm64 context and stack conventions. virtual StackFrame* GetContextFrame(); virtual StackFrame* GetCallerFrame(const CallStack* stack, @@ -95,6 +98,10 @@ class StackwalkerARM64 : public Stackwalker { // CONTEXT_VALID_ALL in real use; it is only changeable for the sake of // unit tests. uint64_t context_frame_validity_; + + // A mask of the valid address bits, determined from the address range of + // modules_. + uint64_t address_range_mask_; };