1diff --git a/src/processor/stackwalker_arm64.cc b/src/processor/stackwalker_arm64.cc 2--- a/src/processor/stackwalker_arm64.cc 3+++ b/src/processor/stackwalker_arm64.cc 4@@ -282,16 +282,27 @@ void StackwalkerARM64::CorrectRegLRByFra 5 << std::hex << (last_last_fp + 8); 6 return; 7 } 8 last_lr = PtrauthStrip(last_lr); 9 10 last_frame->context.iregs[MD_CONTEXT_ARM64_REG_LR] = last_lr; 11 } 12 13+bool StackwalkerARM64::ValidInstructionPointerInFrame(const StackFrameARM64& frame) { 14+ const uint64_t ip = frame.context.iregs[MD_CONTEXT_ARM64_REG_PC]; 15+ 16+ if ((ip < 0x1000) || (ip > 0x000fffffffffffff)) { 17+ // The IP points into the first page or above the user space threshold 18+ return false; 19+ } 20+ 21+ return true; 22+} 23+ 24 StackFrame* StackwalkerARM64::GetCallerFrame(const CallStack* stack, 25 bool stack_scan_allowed) { 26 if (!memory_ || !stack) { 27 BPLOG(ERROR) << "Can't get caller frame without memory or stack"; 28 return NULL; 29 } 30 31 const vector<StackFrame*> &frames = *stack->frames(); 32@@ -300,21 +311,22 @@ StackFrame* StackwalkerARM64::GetCallerF 33 34 // See if there is DWARF call frame information covering this address. 35 scoped_ptr<CFIFrameInfo> cfi_frame_info( 36 frame_symbolizer_->FindCFIFrameInfo(last_frame)); 37 if (cfi_frame_info.get()) 38 frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); 39 40 // If CFI failed, or there wasn't CFI available, fall back to frame pointer. 41- if (!frame.get()) 42+ if (!frame.get() || !ValidInstructionPointerInFrame(*frame)) 43 frame.reset(GetCallerByFramePointer(frames)); 44 45 // If everything failed, fall back to stack scanning. 46- if (stack_scan_allowed && !frame.get()) 47+ if (stack_scan_allowed && 48+ (!frame.get() || !ValidInstructionPointerInFrame(*frame))) 49 frame.reset(GetCallerByStackScan(frames)); 50 51 // If nothing worked, tell the caller. 52 if (!frame.get()) 53 return NULL; 54 55 // Should we terminate the stack walk? (end-of-stack or broken invariant) 56 if (TerminateWalk(frame->context.iregs[MD_CONTEXT_ARM64_REG_PC], 57diff --git a/src/processor/stackwalker_arm64.h b/src/processor/stackwalker_arm64.h 58--- a/src/processor/stackwalker_arm64.h 59+++ b/src/processor/stackwalker_arm64.h 60@@ -92,16 +92,19 @@ class StackwalkerARM64 : public Stackwal 61 62 // GetCallerByFramePointer() depends on the previous frame having recovered 63 // x30($LR) which may not have been done when using CFI. 64 // This function recovers $LR in the previous frame by using the frame-pointer 65 // two frames back to read it from the stack. 66 void CorrectRegLRByFramePointer(const vector<StackFrame*>& frames, 67 StackFrameARM64* last_frame); 68 69+ // Return true if the instruction pointer points into the first 4KiB of memory 70+ bool ValidInstructionPointerInFrame(const StackFrameARM64& frame); 71+ 72 // Stores the CPU context corresponding to the youngest stack frame, to 73 // be returned by GetContextFrame. 74 const MDRawContextARM64* context_; 75 76 // Validity mask for youngest stack frame. This is always 77 // CONTEXT_VALID_ALL in real use; it is only changeable for the sake of 78 // unit tests. 79 uint64_t context_frame_validity_; 80