xref: /aosp_15_r20/external/google-breakpad/src/processor/stackwalker.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1*9712c20fSFrederick Mayle // Copyright 2010 Google LLC
2*9712c20fSFrederick Mayle //
3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle // met:
6*9712c20fSFrederick Mayle //
7*9712c20fSFrederick Mayle //     * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle //     * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle // distribution.
13*9712c20fSFrederick Mayle //     * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle // this software without specific prior written permission.
16*9712c20fSFrederick Mayle //
17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle 
29*9712c20fSFrederick Mayle // stackwalker.cc: Generic stackwalker.
30*9712c20fSFrederick Mayle //
31*9712c20fSFrederick Mayle // See stackwalker.h for documentation.
32*9712c20fSFrederick Mayle //
33*9712c20fSFrederick Mayle // Author: Mark Mentovai
34*9712c20fSFrederick Mayle 
35*9712c20fSFrederick Mayle #ifdef HAVE_CONFIG_H
36*9712c20fSFrederick Mayle #include <config.h>  // Must come first
37*9712c20fSFrederick Mayle #endif
38*9712c20fSFrederick Mayle 
39*9712c20fSFrederick Mayle #include "google_breakpad/processor/stackwalker.h"
40*9712c20fSFrederick Mayle 
41*9712c20fSFrederick Mayle #include <assert.h>
42*9712c20fSFrederick Mayle 
43*9712c20fSFrederick Mayle #include "common/scoped_ptr.h"
44*9712c20fSFrederick Mayle #include "google_breakpad/processor/call_stack.h"
45*9712c20fSFrederick Mayle #include "google_breakpad/processor/code_module.h"
46*9712c20fSFrederick Mayle #include "google_breakpad/processor/code_modules.h"
47*9712c20fSFrederick Mayle #include "google_breakpad/processor/dump_context.h"
48*9712c20fSFrederick Mayle #include "google_breakpad/processor/stack_frame.h"
49*9712c20fSFrederick Mayle #include "google_breakpad/processor/stack_frame_symbolizer.h"
50*9712c20fSFrederick Mayle #include "google_breakpad/processor/system_info.h"
51*9712c20fSFrederick Mayle #include "processor/linked_ptr.h"
52*9712c20fSFrederick Mayle #include "processor/logging.h"
53*9712c20fSFrederick Mayle #include "processor/stackwalker_ppc.h"
54*9712c20fSFrederick Mayle #include "processor/stackwalker_ppc64.h"
55*9712c20fSFrederick Mayle #include "processor/stackwalker_sparc.h"
56*9712c20fSFrederick Mayle #include "processor/stackwalker_x86.h"
57*9712c20fSFrederick Mayle #include "processor/stackwalker_amd64.h"
58*9712c20fSFrederick Mayle #include "processor/stackwalker_arm.h"
59*9712c20fSFrederick Mayle #include "processor/stackwalker_arm64.h"
60*9712c20fSFrederick Mayle #include "processor/stackwalker_mips.h"
61*9712c20fSFrederick Mayle #include "processor/stackwalker_riscv.h"
62*9712c20fSFrederick Mayle #include "processor/stackwalker_riscv64.h"
63*9712c20fSFrederick Mayle 
64*9712c20fSFrederick Mayle namespace google_breakpad {
65*9712c20fSFrederick Mayle 
66*9712c20fSFrederick Mayle const int Stackwalker::kRASearchWords = 40;
67*9712c20fSFrederick Mayle 
68*9712c20fSFrederick Mayle // This default is just a sanity check: a large enough value
69*9712c20fSFrederick Mayle // that allow capturing unbounded recursion traces, yet provide a
70*9712c20fSFrederick Mayle // guardrail against stack walking bugs. The stack walking invariants
71*9712c20fSFrederick Mayle // guarantee that the unwinding process is strictly monotonic and
72*9712c20fSFrederick Mayle // practically bounded by the size of the stack memory range.
73*9712c20fSFrederick Mayle uint32_t Stackwalker::max_frames_ = 1 << 20;  // 1M
74*9712c20fSFrederick Mayle bool Stackwalker::max_frames_set_ = false;
75*9712c20fSFrederick Mayle 
76*9712c20fSFrederick Mayle uint32_t Stackwalker::max_frames_scanned_ = 1 << 14;  // 16k
77*9712c20fSFrederick Mayle 
Stackwalker(const SystemInfo * system_info,MemoryRegion * memory,const CodeModules * modules,StackFrameSymbolizer * frame_symbolizer)78*9712c20fSFrederick Mayle Stackwalker::Stackwalker(const SystemInfo* system_info,
79*9712c20fSFrederick Mayle                          MemoryRegion* memory,
80*9712c20fSFrederick Mayle                          const CodeModules* modules,
81*9712c20fSFrederick Mayle                          StackFrameSymbolizer* frame_symbolizer)
82*9712c20fSFrederick Mayle     : system_info_(system_info),
83*9712c20fSFrederick Mayle       memory_(memory),
84*9712c20fSFrederick Mayle       modules_(modules),
85*9712c20fSFrederick Mayle       unloaded_modules_(NULL),
86*9712c20fSFrederick Mayle       frame_symbolizer_(frame_symbolizer) {
87*9712c20fSFrederick Mayle   assert(frame_symbolizer_);
88*9712c20fSFrederick Mayle }
89*9712c20fSFrederick Mayle 
InsertSpecialAttentionModule(StackFrameSymbolizer::SymbolizerResult symbolizer_result,const CodeModule * module,vector<const CodeModule * > * modules)90*9712c20fSFrederick Mayle void InsertSpecialAttentionModule(
91*9712c20fSFrederick Mayle     StackFrameSymbolizer::SymbolizerResult symbolizer_result,
92*9712c20fSFrederick Mayle     const CodeModule* module,
93*9712c20fSFrederick Mayle     vector<const CodeModule*>* modules) {
94*9712c20fSFrederick Mayle   if (!module) {
95*9712c20fSFrederick Mayle     return;
96*9712c20fSFrederick Mayle   }
97*9712c20fSFrederick Mayle   assert(symbolizer_result == StackFrameSymbolizer::kError ||
98*9712c20fSFrederick Mayle          symbolizer_result == StackFrameSymbolizer::kWarningCorruptSymbols);
99*9712c20fSFrederick Mayle   bool found = false;
100*9712c20fSFrederick Mayle   vector<const CodeModule*>::iterator iter;
101*9712c20fSFrederick Mayle   for (iter = modules->begin(); iter != modules->end(); ++iter) {
102*9712c20fSFrederick Mayle     if (*iter == module) {
103*9712c20fSFrederick Mayle       found = true;
104*9712c20fSFrederick Mayle       break;
105*9712c20fSFrederick Mayle     }
106*9712c20fSFrederick Mayle   }
107*9712c20fSFrederick Mayle   if (!found) {
108*9712c20fSFrederick Mayle     BPLOG(INFO) << ((symbolizer_result == StackFrameSymbolizer::kError) ?
109*9712c20fSFrederick Mayle                        "Couldn't load symbols for: " :
110*9712c20fSFrederick Mayle                        "Detected corrupt symbols for: ")
111*9712c20fSFrederick Mayle                 << module->debug_file() << "|" << module->debug_identifier();
112*9712c20fSFrederick Mayle     modules->push_back(module);
113*9712c20fSFrederick Mayle   }
114*9712c20fSFrederick Mayle }
115*9712c20fSFrederick Mayle 
Walk(CallStack * stack,vector<const CodeModule * > * modules_without_symbols,vector<const CodeModule * > * modules_with_corrupt_symbols)116*9712c20fSFrederick Mayle bool Stackwalker::Walk(
117*9712c20fSFrederick Mayle     CallStack* stack,
118*9712c20fSFrederick Mayle     vector<const CodeModule*>* modules_without_symbols,
119*9712c20fSFrederick Mayle     vector<const CodeModule*>* modules_with_corrupt_symbols) {
120*9712c20fSFrederick Mayle   BPLOG_IF(ERROR, !stack) << "Stackwalker::Walk requires |stack|";
121*9712c20fSFrederick Mayle   assert(stack);
122*9712c20fSFrederick Mayle   stack->Clear();
123*9712c20fSFrederick Mayle 
124*9712c20fSFrederick Mayle   BPLOG_IF(ERROR, !modules_without_symbols) << "Stackwalker::Walk requires "
125*9712c20fSFrederick Mayle                                             << "|modules_without_symbols|";
126*9712c20fSFrederick Mayle   BPLOG_IF(ERROR, !modules_without_symbols) << "Stackwalker::Walk requires "
127*9712c20fSFrederick Mayle                                             << "|modules_with_corrupt_symbols|";
128*9712c20fSFrederick Mayle   assert(modules_without_symbols);
129*9712c20fSFrederick Mayle   assert(modules_with_corrupt_symbols);
130*9712c20fSFrederick Mayle 
131*9712c20fSFrederick Mayle   // Begin with the context frame, and keep getting callers until there are
132*9712c20fSFrederick Mayle   // no more.
133*9712c20fSFrederick Mayle 
134*9712c20fSFrederick Mayle   // Keep track of the number of scanned or otherwise dubious frames seen
135*9712c20fSFrederick Mayle   // so far, as the caller may have set a limit.
136*9712c20fSFrederick Mayle   uint32_t scanned_frames = 0;
137*9712c20fSFrederick Mayle 
138*9712c20fSFrederick Mayle   // Take ownership of the pointer returned by GetContextFrame.
139*9712c20fSFrederick Mayle   scoped_ptr<StackFrame> frame(GetContextFrame());
140*9712c20fSFrederick Mayle 
141*9712c20fSFrederick Mayle   while (frame.get()) {
142*9712c20fSFrederick Mayle     // frame already contains a good frame with properly set instruction and
143*9712c20fSFrederick Mayle     // frame_pointer fields.  The frame structure comes from either the
144*9712c20fSFrederick Mayle     // context frame (above) or a caller frame (below).
145*9712c20fSFrederick Mayle 
146*9712c20fSFrederick Mayle     std::deque<std::unique_ptr<StackFrame>> inlined_frames;
147*9712c20fSFrederick Mayle     // Resolve the module information, if a module map was provided.
148*9712c20fSFrederick Mayle     StackFrameSymbolizer::SymbolizerResult symbolizer_result =
149*9712c20fSFrederick Mayle         frame_symbolizer_->FillSourceLineInfo(modules_, unloaded_modules_,
150*9712c20fSFrederick Mayle                                               system_info_,
151*9712c20fSFrederick Mayle                                               frame.get(), &inlined_frames);
152*9712c20fSFrederick Mayle     switch (symbolizer_result) {
153*9712c20fSFrederick Mayle       case StackFrameSymbolizer::kInterrupt:
154*9712c20fSFrederick Mayle         BPLOG(INFO) << "Stack walk is interrupted.";
155*9712c20fSFrederick Mayle         return false;
156*9712c20fSFrederick Mayle         break;
157*9712c20fSFrederick Mayle       case StackFrameSymbolizer::kError:
158*9712c20fSFrederick Mayle         InsertSpecialAttentionModule(symbolizer_result, frame->module,
159*9712c20fSFrederick Mayle                                      modules_without_symbols);
160*9712c20fSFrederick Mayle         break;
161*9712c20fSFrederick Mayle       case StackFrameSymbolizer::kWarningCorruptSymbols:
162*9712c20fSFrederick Mayle         InsertSpecialAttentionModule(symbolizer_result, frame->module,
163*9712c20fSFrederick Mayle                                      modules_with_corrupt_symbols);
164*9712c20fSFrederick Mayle         break;
165*9712c20fSFrederick Mayle       case StackFrameSymbolizer::kNoError:
166*9712c20fSFrederick Mayle         break;
167*9712c20fSFrederick Mayle       default:
168*9712c20fSFrederick Mayle         assert(false);
169*9712c20fSFrederick Mayle         break;
170*9712c20fSFrederick Mayle     }
171*9712c20fSFrederick Mayle 
172*9712c20fSFrederick Mayle     // Keep track of the number of dubious frames so far.
173*9712c20fSFrederick Mayle     switch (frame.get()->trust) {
174*9712c20fSFrederick Mayle        case StackFrame::FRAME_TRUST_NONE:
175*9712c20fSFrederick Mayle        case StackFrame::FRAME_TRUST_SCAN:
176*9712c20fSFrederick Mayle        case StackFrame::FRAME_TRUST_CFI_SCAN:
177*9712c20fSFrederick Mayle          scanned_frames++;
178*9712c20fSFrederick Mayle          break;
179*9712c20fSFrederick Mayle       default:
180*9712c20fSFrederick Mayle         break;
181*9712c20fSFrederick Mayle     }
182*9712c20fSFrederick Mayle     // Add all nested inlined frames belonging to this frame from the innermost
183*9712c20fSFrederick Mayle     // frame to the outermost frame.
184*9712c20fSFrederick Mayle     while (!inlined_frames.empty()) {
185*9712c20fSFrederick Mayle       stack->frames_.push_back(inlined_frames.front().release());
186*9712c20fSFrederick Mayle       inlined_frames.pop_front();
187*9712c20fSFrederick Mayle     }
188*9712c20fSFrederick Mayle     // Add the frame to the call stack.  Relinquish the ownership claim
189*9712c20fSFrederick Mayle     // over the frame, because the stack now owns it.
190*9712c20fSFrederick Mayle     stack->frames_.push_back(frame.release());
191*9712c20fSFrederick Mayle     if (stack->frames_.size() > max_frames_) {
192*9712c20fSFrederick Mayle       // Only emit an error message in the case where the limit
193*9712c20fSFrederick Mayle       // reached is the default limit, not set by the user.
194*9712c20fSFrederick Mayle       if (!max_frames_set_)
195*9712c20fSFrederick Mayle         BPLOG(ERROR) << "The stack is over " << max_frames_ << " frames.";
196*9712c20fSFrederick Mayle       break;
197*9712c20fSFrederick Mayle     }
198*9712c20fSFrederick Mayle 
199*9712c20fSFrederick Mayle     // Get the next frame and take ownership.
200*9712c20fSFrederick Mayle     bool stack_scan_allowed = scanned_frames < max_frames_scanned_;
201*9712c20fSFrederick Mayle     frame.reset(GetCallerFrame(stack, stack_scan_allowed));
202*9712c20fSFrederick Mayle   }
203*9712c20fSFrederick Mayle 
204*9712c20fSFrederick Mayle   return true;
205*9712c20fSFrederick Mayle }
206*9712c20fSFrederick Mayle 
207*9712c20fSFrederick Mayle // static
StackwalkerForCPU(const SystemInfo * system_info,DumpContext * context,MemoryRegion * memory,const CodeModules * modules,const CodeModules * unloaded_modules,StackFrameSymbolizer * frame_symbolizer)208*9712c20fSFrederick Mayle Stackwalker* Stackwalker::StackwalkerForCPU(
209*9712c20fSFrederick Mayle     const SystemInfo* system_info,
210*9712c20fSFrederick Mayle     DumpContext* context,
211*9712c20fSFrederick Mayle     MemoryRegion* memory,
212*9712c20fSFrederick Mayle     const CodeModules* modules,
213*9712c20fSFrederick Mayle     const CodeModules* unloaded_modules,
214*9712c20fSFrederick Mayle     StackFrameSymbolizer* frame_symbolizer) {
215*9712c20fSFrederick Mayle   if (!context) {
216*9712c20fSFrederick Mayle     BPLOG(ERROR) << "Can't choose a stackwalker implementation without context";
217*9712c20fSFrederick Mayle     return NULL;
218*9712c20fSFrederick Mayle   }
219*9712c20fSFrederick Mayle 
220*9712c20fSFrederick Mayle   Stackwalker* cpu_stackwalker = NULL;
221*9712c20fSFrederick Mayle 
222*9712c20fSFrederick Mayle   uint32_t cpu = context->GetContextCPU();
223*9712c20fSFrederick Mayle   switch (cpu) {
224*9712c20fSFrederick Mayle     case MD_CONTEXT_X86:
225*9712c20fSFrederick Mayle       cpu_stackwalker = new StackwalkerX86(system_info,
226*9712c20fSFrederick Mayle                                            context->GetContextX86(),
227*9712c20fSFrederick Mayle                                            memory, modules, frame_symbolizer);
228*9712c20fSFrederick Mayle       break;
229*9712c20fSFrederick Mayle 
230*9712c20fSFrederick Mayle     case MD_CONTEXT_PPC:
231*9712c20fSFrederick Mayle       cpu_stackwalker = new StackwalkerPPC(system_info,
232*9712c20fSFrederick Mayle                                            context->GetContextPPC(),
233*9712c20fSFrederick Mayle                                            memory, modules, frame_symbolizer);
234*9712c20fSFrederick Mayle       break;
235*9712c20fSFrederick Mayle 
236*9712c20fSFrederick Mayle     case MD_CONTEXT_PPC64:
237*9712c20fSFrederick Mayle       cpu_stackwalker = new StackwalkerPPC64(system_info,
238*9712c20fSFrederick Mayle                                              context->GetContextPPC64(),
239*9712c20fSFrederick Mayle                                              memory, modules, frame_symbolizer);
240*9712c20fSFrederick Mayle       break;
241*9712c20fSFrederick Mayle 
242*9712c20fSFrederick Mayle     case MD_CONTEXT_AMD64:
243*9712c20fSFrederick Mayle       cpu_stackwalker = new StackwalkerAMD64(system_info,
244*9712c20fSFrederick Mayle                                              context->GetContextAMD64(),
245*9712c20fSFrederick Mayle                                              memory, modules, frame_symbolizer);
246*9712c20fSFrederick Mayle       break;
247*9712c20fSFrederick Mayle 
248*9712c20fSFrederick Mayle     case MD_CONTEXT_SPARC:
249*9712c20fSFrederick Mayle       cpu_stackwalker = new StackwalkerSPARC(system_info,
250*9712c20fSFrederick Mayle                                              context->GetContextSPARC(),
251*9712c20fSFrederick Mayle                                              memory, modules, frame_symbolizer);
252*9712c20fSFrederick Mayle       break;
253*9712c20fSFrederick Mayle 
254*9712c20fSFrederick Mayle     case MD_CONTEXT_MIPS:
255*9712c20fSFrederick Mayle     case MD_CONTEXT_MIPS64:
256*9712c20fSFrederick Mayle       cpu_stackwalker = new StackwalkerMIPS(system_info,
257*9712c20fSFrederick Mayle                                             context->GetContextMIPS(),
258*9712c20fSFrederick Mayle                                             memory, modules, frame_symbolizer);
259*9712c20fSFrederick Mayle       break;
260*9712c20fSFrederick Mayle 
261*9712c20fSFrederick Mayle     case MD_CONTEXT_ARM:
262*9712c20fSFrederick Mayle     {
263*9712c20fSFrederick Mayle       int fp_register = -1;
264*9712c20fSFrederick Mayle       if (system_info->os_short == "ios")
265*9712c20fSFrederick Mayle         fp_register = MD_CONTEXT_ARM_REG_IOS_FP;
266*9712c20fSFrederick Mayle       cpu_stackwalker = new StackwalkerARM(system_info,
267*9712c20fSFrederick Mayle                                            context->GetContextARM(),
268*9712c20fSFrederick Mayle                                            fp_register, memory, modules,
269*9712c20fSFrederick Mayle                                            frame_symbolizer);
270*9712c20fSFrederick Mayle       break;
271*9712c20fSFrederick Mayle     }
272*9712c20fSFrederick Mayle 
273*9712c20fSFrederick Mayle     case MD_CONTEXT_ARM64:
274*9712c20fSFrederick Mayle       cpu_stackwalker = new StackwalkerARM64(system_info,
275*9712c20fSFrederick Mayle                                              context->GetContextARM64(),
276*9712c20fSFrederick Mayle                                              memory, modules,
277*9712c20fSFrederick Mayle                                              frame_symbolizer);
278*9712c20fSFrederick Mayle       break;
279*9712c20fSFrederick Mayle 
280*9712c20fSFrederick Mayle     case MD_CONTEXT_RISCV:
281*9712c20fSFrederick Mayle       cpu_stackwalker = new StackwalkerRISCV(system_info,
282*9712c20fSFrederick Mayle                                              context->GetContextRISCV(),
283*9712c20fSFrederick Mayle                                              memory, modules,
284*9712c20fSFrederick Mayle                                              frame_symbolizer);
285*9712c20fSFrederick Mayle       break;
286*9712c20fSFrederick Mayle 
287*9712c20fSFrederick Mayle     case MD_CONTEXT_RISCV64:
288*9712c20fSFrederick Mayle       cpu_stackwalker = new StackwalkerRISCV64(system_info,
289*9712c20fSFrederick Mayle                                                context->GetContextRISCV64(),
290*9712c20fSFrederick Mayle                                                memory, modules,
291*9712c20fSFrederick Mayle                                                frame_symbolizer);
292*9712c20fSFrederick Mayle       break;
293*9712c20fSFrederick Mayle   }
294*9712c20fSFrederick Mayle 
295*9712c20fSFrederick Mayle   BPLOG_IF(ERROR, !cpu_stackwalker) << "Unknown CPU type " << HexString(cpu) <<
296*9712c20fSFrederick Mayle                                        ", can't choose a stackwalker "
297*9712c20fSFrederick Mayle                                        "implementation";
298*9712c20fSFrederick Mayle   if (cpu_stackwalker) {
299*9712c20fSFrederick Mayle     cpu_stackwalker->unloaded_modules_ = unloaded_modules;
300*9712c20fSFrederick Mayle   }
301*9712c20fSFrederick Mayle   return cpu_stackwalker;
302*9712c20fSFrederick Mayle }
303*9712c20fSFrederick Mayle 
304*9712c20fSFrederick Mayle // CONSIDER: check stack alignment?
TerminateWalk(uint64_t caller_ip,uint64_t caller_sp,uint64_t callee_sp,bool first_unwind) const305*9712c20fSFrederick Mayle bool Stackwalker::TerminateWalk(uint64_t caller_ip,
306*9712c20fSFrederick Mayle                                 uint64_t caller_sp,
307*9712c20fSFrederick Mayle                                 uint64_t callee_sp,
308*9712c20fSFrederick Mayle                                 bool first_unwind) const {
309*9712c20fSFrederick Mayle   // Treat an instruction address less than 4k as end-of-stack.
310*9712c20fSFrederick Mayle   // (using InstructionAddressSeemsValid() here is very tempting,
311*9712c20fSFrederick Mayle   // but we need to handle JITted code)
312*9712c20fSFrederick Mayle   if (caller_ip < (1 << 12)) {
313*9712c20fSFrederick Mayle     return true;
314*9712c20fSFrederick Mayle   }
315*9712c20fSFrederick Mayle 
316*9712c20fSFrederick Mayle   // NOTE: The stack address range is implicitly checked
317*9712c20fSFrederick Mayle   //   when the stack memory is accessed.
318*9712c20fSFrederick Mayle 
319*9712c20fSFrederick Mayle   // The stack pointer should monotonically increase. For first unwind
320*9712c20fSFrederick Mayle   // we allow caller_sp == callee_sp to account for architectures where
321*9712c20fSFrederick Mayle   // the return address is stored in a register (so it's possible to have
322*9712c20fSFrederick Mayle   // leaf functions which don't move the stack pointer)
323*9712c20fSFrederick Mayle   if (first_unwind ? (caller_sp < callee_sp) : (caller_sp <= callee_sp)) {
324*9712c20fSFrederick Mayle     return true;
325*9712c20fSFrederick Mayle   }
326*9712c20fSFrederick Mayle 
327*9712c20fSFrederick Mayle   return false;
328*9712c20fSFrederick Mayle }
329*9712c20fSFrederick Mayle 
InstructionAddressSeemsValid(uint64_t address) const330*9712c20fSFrederick Mayle bool Stackwalker::InstructionAddressSeemsValid(uint64_t address) const {
331*9712c20fSFrederick Mayle   StackFrame frame;
332*9712c20fSFrederick Mayle   frame.instruction = address;
333*9712c20fSFrederick Mayle   StackFrameSymbolizer::SymbolizerResult symbolizer_result =
334*9712c20fSFrederick Mayle       frame_symbolizer_->FillSourceLineInfo(modules_, unloaded_modules_,
335*9712c20fSFrederick Mayle                                             system_info_, &frame, nullptr);
336*9712c20fSFrederick Mayle 
337*9712c20fSFrederick Mayle   if (!frame.module) {
338*9712c20fSFrederick Mayle     // not inside any loaded module
339*9712c20fSFrederick Mayle     return false;
340*9712c20fSFrederick Mayle   }
341*9712c20fSFrederick Mayle 
342*9712c20fSFrederick Mayle   if (!frame_symbolizer_->HasImplementation()) {
343*9712c20fSFrederick Mayle     // No valid implementation to symbolize stack frame, but the address is
344*9712c20fSFrederick Mayle     // within a known module.
345*9712c20fSFrederick Mayle     return true;
346*9712c20fSFrederick Mayle   }
347*9712c20fSFrederick Mayle 
348*9712c20fSFrederick Mayle   if (symbolizer_result != StackFrameSymbolizer::kNoError &&
349*9712c20fSFrederick Mayle       symbolizer_result != StackFrameSymbolizer::kWarningCorruptSymbols) {
350*9712c20fSFrederick Mayle     // Some error occurred during symbolization, but the address is within a
351*9712c20fSFrederick Mayle     // known module
352*9712c20fSFrederick Mayle     return true;
353*9712c20fSFrederick Mayle   }
354*9712c20fSFrederick Mayle 
355*9712c20fSFrederick Mayle   return !frame.function_name.empty();
356*9712c20fSFrederick Mayle }
357*9712c20fSFrederick Mayle 
358*9712c20fSFrederick Mayle }  // namespace google_breakpad
359