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