xref: /aosp_15_r20/external/google-breakpad/src/processor/stackwalker_amd64.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_amd64.cc: amd64-specific stackwalker.
30*9712c20fSFrederick Mayle //
31*9712c20fSFrederick Mayle // See stackwalker_amd64.h for documentation.
32*9712c20fSFrederick Mayle //
33*9712c20fSFrederick Mayle // Author: Mark Mentovai, Ted Mielczarek
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 <assert.h>
40*9712c20fSFrederick Mayle 
41*9712c20fSFrederick Mayle #include "common/scoped_ptr.h"
42*9712c20fSFrederick Mayle #include "google_breakpad/processor/call_stack.h"
43*9712c20fSFrederick Mayle #include "google_breakpad/processor/memory_region.h"
44*9712c20fSFrederick Mayle #include "google_breakpad/processor/source_line_resolver_interface.h"
45*9712c20fSFrederick Mayle #include "google_breakpad/processor/stack_frame_cpu.h"
46*9712c20fSFrederick Mayle #include "google_breakpad/processor/system_info.h"
47*9712c20fSFrederick Mayle #include "processor/cfi_frame_info.h"
48*9712c20fSFrederick Mayle #include "processor/logging.h"
49*9712c20fSFrederick Mayle #include "processor/stackwalker_amd64.h"
50*9712c20fSFrederick Mayle 
51*9712c20fSFrederick Mayle namespace google_breakpad {
52*9712c20fSFrederick Mayle 
53*9712c20fSFrederick Mayle 
54*9712c20fSFrederick Mayle const StackwalkerAMD64::CFIWalker::RegisterSet
55*9712c20fSFrederick Mayle StackwalkerAMD64::cfi_register_map_[] = {
56*9712c20fSFrederick Mayle   // It may seem like $rip and $rsp are callee-saves, because the callee is
57*9712c20fSFrederick Mayle   // responsible for having them restored upon return. But the callee_saves
58*9712c20fSFrederick Mayle   // flags here really means that the walker should assume they're
59*9712c20fSFrederick Mayle   // unchanged if the CFI doesn't mention them --- clearly wrong for $rip
60*9712c20fSFrederick Mayle   // and $rsp.
61*9712c20fSFrederick Mayle   { "$rax", NULL, false,
62*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_RAX, &MDRawContextAMD64::rax },
63*9712c20fSFrederick Mayle   { "$rdx", NULL, false,
64*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_RDX, &MDRawContextAMD64::rdx },
65*9712c20fSFrederick Mayle   { "$rcx", NULL, false,
66*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_RCX, &MDRawContextAMD64::rcx },
67*9712c20fSFrederick Mayle   { "$rbx", NULL, true,
68*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_RBX, &MDRawContextAMD64::rbx },
69*9712c20fSFrederick Mayle   { "$rsi", NULL, false,
70*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_RSI, &MDRawContextAMD64::rsi },
71*9712c20fSFrederick Mayle   { "$rdi", NULL, false,
72*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_RDI, &MDRawContextAMD64::rdi },
73*9712c20fSFrederick Mayle   { "$rbp", NULL, true,
74*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_RBP, &MDRawContextAMD64::rbp },
75*9712c20fSFrederick Mayle   { "$rsp", ".cfa", false,
76*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_RSP, &MDRawContextAMD64::rsp },
77*9712c20fSFrederick Mayle   { "$r8", NULL, false,
78*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_R8,  &MDRawContextAMD64::r8 },
79*9712c20fSFrederick Mayle   { "$r9", NULL, false,
80*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_R9,  &MDRawContextAMD64::r9 },
81*9712c20fSFrederick Mayle   { "$r10", NULL, false,
82*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_R10, &MDRawContextAMD64::r10 },
83*9712c20fSFrederick Mayle   { "$r11", NULL, false,
84*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_R11, &MDRawContextAMD64::r11 },
85*9712c20fSFrederick Mayle   { "$r12", NULL, true,
86*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_R12, &MDRawContextAMD64::r12 },
87*9712c20fSFrederick Mayle   { "$r13", NULL, true,
88*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_R13, &MDRawContextAMD64::r13 },
89*9712c20fSFrederick Mayle   { "$r14", NULL, true,
90*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_R14, &MDRawContextAMD64::r14 },
91*9712c20fSFrederick Mayle   { "$r15", NULL, true,
92*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_R15, &MDRawContextAMD64::r15 },
93*9712c20fSFrederick Mayle   { "$rip", ".ra", false,
94*9712c20fSFrederick Mayle     StackFrameAMD64::CONTEXT_VALID_RIP, &MDRawContextAMD64::rip },
95*9712c20fSFrederick Mayle };
96*9712c20fSFrederick Mayle 
StackwalkerAMD64(const SystemInfo * system_info,const MDRawContextAMD64 * context,MemoryRegion * memory,const CodeModules * modules,StackFrameSymbolizer * resolver_helper)97*9712c20fSFrederick Mayle StackwalkerAMD64::StackwalkerAMD64(const SystemInfo* system_info,
98*9712c20fSFrederick Mayle                                    const MDRawContextAMD64* context,
99*9712c20fSFrederick Mayle                                    MemoryRegion* memory,
100*9712c20fSFrederick Mayle                                    const CodeModules* modules,
101*9712c20fSFrederick Mayle                                    StackFrameSymbolizer* resolver_helper)
102*9712c20fSFrederick Mayle     : Stackwalker(system_info, memory, modules, resolver_helper),
103*9712c20fSFrederick Mayle       context_(context),
104*9712c20fSFrederick Mayle       cfi_walker_(cfi_register_map_,
105*9712c20fSFrederick Mayle                   (sizeof(cfi_register_map_) / sizeof(cfi_register_map_[0]))) {
106*9712c20fSFrederick Mayle }
107*9712c20fSFrederick Mayle 
ReturnAddress() const108*9712c20fSFrederick Mayle uint64_t StackFrameAMD64::ReturnAddress() const {
109*9712c20fSFrederick Mayle   assert(context_validity & StackFrameAMD64::CONTEXT_VALID_RIP);
110*9712c20fSFrederick Mayle   return context.rip;
111*9712c20fSFrederick Mayle }
112*9712c20fSFrederick Mayle 
GetContextFrame()113*9712c20fSFrederick Mayle StackFrame* StackwalkerAMD64::GetContextFrame() {
114*9712c20fSFrederick Mayle   if (!context_) {
115*9712c20fSFrederick Mayle     BPLOG(ERROR) << "Can't get context frame without context";
116*9712c20fSFrederick Mayle     return NULL;
117*9712c20fSFrederick Mayle   }
118*9712c20fSFrederick Mayle 
119*9712c20fSFrederick Mayle   StackFrameAMD64* frame = new StackFrameAMD64();
120*9712c20fSFrederick Mayle 
121*9712c20fSFrederick Mayle   // The instruction pointer is stored directly in a register, so pull it
122*9712c20fSFrederick Mayle   // straight out of the CPU context structure.
123*9712c20fSFrederick Mayle   frame->context = *context_;
124*9712c20fSFrederick Mayle   frame->context_validity = StackFrameAMD64::CONTEXT_VALID_ALL;
125*9712c20fSFrederick Mayle   frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
126*9712c20fSFrederick Mayle   frame->instruction = frame->context.rip;
127*9712c20fSFrederick Mayle 
128*9712c20fSFrederick Mayle   return frame;
129*9712c20fSFrederick Mayle }
130*9712c20fSFrederick Mayle 
GetCallerByCFIFrameInfo(const vector<StackFrame * > & frames,CFIFrameInfo * cfi_frame_info)131*9712c20fSFrederick Mayle StackFrameAMD64* StackwalkerAMD64::GetCallerByCFIFrameInfo(
132*9712c20fSFrederick Mayle     const vector<StackFrame*>& frames,
133*9712c20fSFrederick Mayle     CFIFrameInfo* cfi_frame_info) {
134*9712c20fSFrederick Mayle   StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back());
135*9712c20fSFrederick Mayle 
136*9712c20fSFrederick Mayle   scoped_ptr<StackFrameAMD64> frame(new StackFrameAMD64());
137*9712c20fSFrederick Mayle   if (!cfi_walker_
138*9712c20fSFrederick Mayle       .FindCallerRegisters(*memory_, *cfi_frame_info,
139*9712c20fSFrederick Mayle                            last_frame->context, last_frame->context_validity,
140*9712c20fSFrederick Mayle                            &frame->context, &frame->context_validity))
141*9712c20fSFrederick Mayle     return NULL;
142*9712c20fSFrederick Mayle 
143*9712c20fSFrederick Mayle   // Make sure we recovered all the essentials.
144*9712c20fSFrederick Mayle   static const int essentials = (StackFrameAMD64::CONTEXT_VALID_RIP
145*9712c20fSFrederick Mayle                                  | StackFrameAMD64::CONTEXT_VALID_RSP);
146*9712c20fSFrederick Mayle   if ((frame->context_validity & essentials) != essentials)
147*9712c20fSFrederick Mayle     return NULL;
148*9712c20fSFrederick Mayle 
149*9712c20fSFrederick Mayle   if (!frame->context.rip || !frame->context.rsp) {
150*9712c20fSFrederick Mayle     BPLOG(ERROR) << "invalid rip/rsp";
151*9712c20fSFrederick Mayle     return NULL;
152*9712c20fSFrederick Mayle   }
153*9712c20fSFrederick Mayle 
154*9712c20fSFrederick Mayle   frame->trust = StackFrame::FRAME_TRUST_CFI;
155*9712c20fSFrederick Mayle   return frame.release();
156*9712c20fSFrederick Mayle }
157*9712c20fSFrederick Mayle 
158*9712c20fSFrederick Mayle // Returns true if `ptr` is not in x86-64 canonical form.
159*9712c20fSFrederick Mayle // https://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details
is_non_canonical(uint64_t ptr)160*9712c20fSFrederick Mayle static bool is_non_canonical(uint64_t ptr) {
161*9712c20fSFrederick Mayle   return ptr > 0x7FFFFFFFFFFF && ptr < 0xFFFF800000000000;
162*9712c20fSFrederick Mayle }
163*9712c20fSFrederick Mayle 
GetCallerByFramePointerRecovery(const vector<StackFrame * > & frames)164*9712c20fSFrederick Mayle StackFrameAMD64* StackwalkerAMD64::GetCallerByFramePointerRecovery(
165*9712c20fSFrederick Mayle     const vector<StackFrame*>& frames) {
166*9712c20fSFrederick Mayle   StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back());
167*9712c20fSFrederick Mayle   uint64_t last_rbp = last_frame->context.rbp;
168*9712c20fSFrederick Mayle 
169*9712c20fSFrederick Mayle   // Assume the presence of a frame pointer. This is not mandated by the
170*9712c20fSFrederick Mayle   // AMD64 ABI, c.f. section 3.2.2 footnote 7, though it is typical for
171*9712c20fSFrederick Mayle   // compilers to still preserve the frame pointer and not treat %rbp as a
172*9712c20fSFrederick Mayle   // general purpose register.
173*9712c20fSFrederick Mayle   //
174*9712c20fSFrederick Mayle   // With this assumption, the CALL instruction pushes the return address
175*9712c20fSFrederick Mayle   // onto the stack and sets %rip to the procedure to enter. The procedure
176*9712c20fSFrederick Mayle   // then establishes the stack frame with a prologue that PUSHes the current
177*9712c20fSFrederick Mayle   // %rbp onto the stack, MOVes the current %rsp to %rbp, and then allocates
178*9712c20fSFrederick Mayle   // space for any local variables. Using this procedure linking information,
179*9712c20fSFrederick Mayle   // it is possible to locate frame information for the callee:
180*9712c20fSFrederick Mayle   //
181*9712c20fSFrederick Mayle   // %caller_rsp = *(%callee_rbp + 16)
182*9712c20fSFrederick Mayle   // %caller_rip = *(%callee_rbp + 8)
183*9712c20fSFrederick Mayle   // %caller_rbp = *(%callee_rbp)
184*9712c20fSFrederick Mayle 
185*9712c20fSFrederick Mayle   // If rbp is not 8-byte aligned it can't be a frame pointer.
186*9712c20fSFrederick Mayle   if (last_rbp % 8 != 0) {
187*9712c20fSFrederick Mayle     return NULL;
188*9712c20fSFrederick Mayle   }
189*9712c20fSFrederick Mayle 
190*9712c20fSFrederick Mayle   uint64_t caller_rip, caller_rbp;
191*9712c20fSFrederick Mayle   if (memory_->GetMemoryAtAddress(last_rbp + 8, &caller_rip) &&
192*9712c20fSFrederick Mayle       memory_->GetMemoryAtAddress(last_rbp, &caller_rbp)) {
193*9712c20fSFrederick Mayle     uint64_t caller_rsp = last_rbp + 16;
194*9712c20fSFrederick Mayle 
195*9712c20fSFrederick Mayle     // If the recovered rip is not a canonical address it can't be
196*9712c20fSFrederick Mayle     // the return address, so rbp must not have been a frame pointer.
197*9712c20fSFrederick Mayle     if (is_non_canonical(caller_rip)) {
198*9712c20fSFrederick Mayle       return NULL;
199*9712c20fSFrederick Mayle     }
200*9712c20fSFrederick Mayle 
201*9712c20fSFrederick Mayle     // Check that rbp is within the right frame
202*9712c20fSFrederick Mayle     if (caller_rsp <= last_rbp || caller_rbp < caller_rsp) {
203*9712c20fSFrederick Mayle       return NULL;
204*9712c20fSFrederick Mayle     }
205*9712c20fSFrederick Mayle 
206*9712c20fSFrederick Mayle     // Sanity check that resulting rbp is still inside stack memory.
207*9712c20fSFrederick Mayle     uint64_t unused;
208*9712c20fSFrederick Mayle     if (!memory_->GetMemoryAtAddress(caller_rbp, &unused)) {
209*9712c20fSFrederick Mayle       return NULL;
210*9712c20fSFrederick Mayle     }
211*9712c20fSFrederick Mayle 
212*9712c20fSFrederick Mayle     StackFrameAMD64* frame = new StackFrameAMD64();
213*9712c20fSFrederick Mayle     frame->trust = StackFrame::FRAME_TRUST_FP;
214*9712c20fSFrederick Mayle     frame->context = last_frame->context;
215*9712c20fSFrederick Mayle     frame->context.rip = caller_rip;
216*9712c20fSFrederick Mayle     frame->context.rsp = caller_rsp;
217*9712c20fSFrederick Mayle     frame->context.rbp = caller_rbp;
218*9712c20fSFrederick Mayle     frame->context_validity = StackFrameAMD64::CONTEXT_VALID_RIP |
219*9712c20fSFrederick Mayle                               StackFrameAMD64::CONTEXT_VALID_RSP |
220*9712c20fSFrederick Mayle                               StackFrameAMD64::CONTEXT_VALID_RBP;
221*9712c20fSFrederick Mayle     return frame;
222*9712c20fSFrederick Mayle   }
223*9712c20fSFrederick Mayle 
224*9712c20fSFrederick Mayle   return NULL;
225*9712c20fSFrederick Mayle }
226*9712c20fSFrederick Mayle 
GetCallerBySimulatingReturn(const vector<StackFrame * > & frames)227*9712c20fSFrederick Mayle StackFrameAMD64* StackwalkerAMD64::GetCallerBySimulatingReturn(
228*9712c20fSFrederick Mayle     const vector<StackFrame*>& frames) {
229*9712c20fSFrederick Mayle   assert(frames.back()->trust == StackFrame::FRAME_TRUST_CONTEXT);
230*9712c20fSFrederick Mayle   StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back());
231*9712c20fSFrederick Mayle   uint64_t last_rsp = last_frame->context.rsp;
232*9712c20fSFrederick Mayle   uint64_t caller_rip_address, caller_rip;
233*9712c20fSFrederick Mayle   int searchwords = 1;
234*9712c20fSFrederick Mayle   if (!ScanForReturnAddress(last_rsp, &caller_rip_address, &caller_rip,
235*9712c20fSFrederick Mayle                             searchwords)) {
236*9712c20fSFrederick Mayle     // No plausible return address at the top of the stack. Unable to simulate
237*9712c20fSFrederick Mayle     // a return.
238*9712c20fSFrederick Mayle     return NULL;
239*9712c20fSFrederick Mayle   }
240*9712c20fSFrederick Mayle 
241*9712c20fSFrederick Mayle   // Create a new stack frame (ownership will be transferred to the caller)
242*9712c20fSFrederick Mayle   // and fill it in.
243*9712c20fSFrederick Mayle   StackFrameAMD64* frame = new StackFrameAMD64();
244*9712c20fSFrederick Mayle 
245*9712c20fSFrederick Mayle   frame->trust = StackFrame::FRAME_TRUST_LEAF;
246*9712c20fSFrederick Mayle   frame->context = last_frame->context;
247*9712c20fSFrederick Mayle   frame->context.rip = caller_rip;
248*9712c20fSFrederick Mayle   // The caller's %rsp is directly underneath the return address pushed by
249*9712c20fSFrederick Mayle   // the call.
250*9712c20fSFrederick Mayle   frame->context.rsp = caller_rip_address + 8;
251*9712c20fSFrederick Mayle   frame->context_validity = last_frame->context_validity;
252*9712c20fSFrederick Mayle 
253*9712c20fSFrederick Mayle   return frame;
254*9712c20fSFrederick Mayle }
255*9712c20fSFrederick Mayle 
GetCallerByStackScan(const vector<StackFrame * > & frames)256*9712c20fSFrederick Mayle StackFrameAMD64* StackwalkerAMD64::GetCallerByStackScan(
257*9712c20fSFrederick Mayle     const vector<StackFrame*>& frames) {
258*9712c20fSFrederick Mayle   StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back());
259*9712c20fSFrederick Mayle   uint64_t last_rsp = last_frame->context.rsp;
260*9712c20fSFrederick Mayle   uint64_t caller_rip_address, caller_rip;
261*9712c20fSFrederick Mayle 
262*9712c20fSFrederick Mayle   if (!ScanForReturnAddress(last_rsp, &caller_rip_address, &caller_rip,
263*9712c20fSFrederick Mayle                             /*is_context_frame=*/last_frame->trust ==
264*9712c20fSFrederick Mayle                                 StackFrame::FRAME_TRUST_CONTEXT)) {
265*9712c20fSFrederick Mayle     // No plausible return address was found.
266*9712c20fSFrederick Mayle     return NULL;
267*9712c20fSFrederick Mayle   }
268*9712c20fSFrederick Mayle 
269*9712c20fSFrederick Mayle   // Create a new stack frame (ownership will be transferred to the caller)
270*9712c20fSFrederick Mayle   // and fill it in.
271*9712c20fSFrederick Mayle   StackFrameAMD64* frame = new StackFrameAMD64();
272*9712c20fSFrederick Mayle 
273*9712c20fSFrederick Mayle   frame->trust = StackFrame::FRAME_TRUST_SCAN;
274*9712c20fSFrederick Mayle   frame->context = last_frame->context;
275*9712c20fSFrederick Mayle   frame->context.rip = caller_rip;
276*9712c20fSFrederick Mayle   // The caller's %rsp is directly underneath the return address pushed by
277*9712c20fSFrederick Mayle   // the call.
278*9712c20fSFrederick Mayle   frame->context.rsp = caller_rip_address + 8;
279*9712c20fSFrederick Mayle   frame->context_validity = StackFrameAMD64::CONTEXT_VALID_RIP |
280*9712c20fSFrederick Mayle                             StackFrameAMD64::CONTEXT_VALID_RSP;
281*9712c20fSFrederick Mayle 
282*9712c20fSFrederick Mayle   // Other unwinders give up if they don't have an %rbp value, so see if we
283*9712c20fSFrederick Mayle   // can pass some plausible value on.
284*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameAMD64::CONTEXT_VALID_RBP) {
285*9712c20fSFrederick Mayle     // Functions typically push their caller's %rbp immediately upon entry,
286*9712c20fSFrederick Mayle     // and then set %rbp to point to that. So if the callee's %rbp is
287*9712c20fSFrederick Mayle     // pointing to the first word below the alleged return address, presume
288*9712c20fSFrederick Mayle     // that the caller's %rbp is saved there.
289*9712c20fSFrederick Mayle     if (caller_rip_address - 8 == last_frame->context.rbp) {
290*9712c20fSFrederick Mayle       uint64_t caller_rbp = 0;
291*9712c20fSFrederick Mayle       if (memory_->GetMemoryAtAddress(last_frame->context.rbp, &caller_rbp) &&
292*9712c20fSFrederick Mayle           caller_rbp > caller_rip_address) {
293*9712c20fSFrederick Mayle         frame->context.rbp = caller_rbp;
294*9712c20fSFrederick Mayle         frame->context_validity |= StackFrameAMD64::CONTEXT_VALID_RBP;
295*9712c20fSFrederick Mayle       }
296*9712c20fSFrederick Mayle     } else if (last_frame->context.rbp >= caller_rip_address + 8) {
297*9712c20fSFrederick Mayle       // If the callee's %rbp is plausible as a value for the caller's
298*9712c20fSFrederick Mayle       // %rbp, presume that the callee left it unchanged.
299*9712c20fSFrederick Mayle       frame->context.rbp = last_frame->context.rbp;
300*9712c20fSFrederick Mayle       frame->context_validity |= StackFrameAMD64::CONTEXT_VALID_RBP;
301*9712c20fSFrederick Mayle     }
302*9712c20fSFrederick Mayle   }
303*9712c20fSFrederick Mayle 
304*9712c20fSFrederick Mayle   return frame;
305*9712c20fSFrederick Mayle }
306*9712c20fSFrederick Mayle 
GetCallerFrame(const CallStack * stack,bool stack_scan_allowed)307*9712c20fSFrederick Mayle StackFrame* StackwalkerAMD64::GetCallerFrame(const CallStack* stack,
308*9712c20fSFrederick Mayle                                              bool stack_scan_allowed) {
309*9712c20fSFrederick Mayle   if (!memory_ || !stack) {
310*9712c20fSFrederick Mayle     BPLOG(ERROR) << "Can't get caller frame without memory or stack";
311*9712c20fSFrederick Mayle     return NULL;
312*9712c20fSFrederick Mayle   }
313*9712c20fSFrederick Mayle 
314*9712c20fSFrederick Mayle   const vector<StackFrame*>& frames = *stack->frames();
315*9712c20fSFrederick Mayle   StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back());
316*9712c20fSFrederick Mayle   scoped_ptr<StackFrameAMD64> new_frame;
317*9712c20fSFrederick Mayle 
318*9712c20fSFrederick Mayle   // If we have CFI information, use it.
319*9712c20fSFrederick Mayle   scoped_ptr<CFIFrameInfo> cfi_frame_info(
320*9712c20fSFrederick Mayle       frame_symbolizer_->FindCFIFrameInfo(last_frame));
321*9712c20fSFrederick Mayle   if (cfi_frame_info.get())
322*9712c20fSFrederick Mayle     new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get()));
323*9712c20fSFrederick Mayle 
324*9712c20fSFrederick Mayle   // If CFI was not available and this is a Windows x64 stack, check whether
325*9712c20fSFrederick Mayle   // this is a leaf function which doesn't touch any callee-saved registers.
326*9712c20fSFrederick Mayle   // According to https://reviews.llvm.org/D24748, LLVM doesn't generate unwind
327*9712c20fSFrederick Mayle   // info for such functions. According to MSDN, leaf functions can be unwound
328*9712c20fSFrederick Mayle   // simply by simulating a return.
329*9712c20fSFrederick Mayle   if (!new_frame.get() &&
330*9712c20fSFrederick Mayle       last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT &&
331*9712c20fSFrederick Mayle       system_info_->os_short == "windows") {
332*9712c20fSFrederick Mayle     new_frame.reset(GetCallerBySimulatingReturn(frames));
333*9712c20fSFrederick Mayle   }
334*9712c20fSFrederick Mayle 
335*9712c20fSFrederick Mayle   // If CFI was not available or failed, try using frame pointer recovery.
336*9712c20fSFrederick Mayle   // Never try to use frame pointer unwinding on Windows x64 stack. MSVC never
337*9712c20fSFrederick Mayle   // generates code that works with frame pointer chasing, and LLVM does the
338*9712c20fSFrederick Mayle   // same. Stack scanning would be better.
339*9712c20fSFrederick Mayle   if (!new_frame.get() && system_info_->os_short != "windows") {
340*9712c20fSFrederick Mayle     new_frame.reset(GetCallerByFramePointerRecovery(frames));
341*9712c20fSFrederick Mayle   }
342*9712c20fSFrederick Mayle 
343*9712c20fSFrederick Mayle   // If all else fails, fall back to stack scanning.
344*9712c20fSFrederick Mayle   if (stack_scan_allowed && !new_frame.get()) {
345*9712c20fSFrederick Mayle     new_frame.reset(GetCallerByStackScan(frames));
346*9712c20fSFrederick Mayle   }
347*9712c20fSFrederick Mayle 
348*9712c20fSFrederick Mayle   // If nothing worked, tell the caller.
349*9712c20fSFrederick Mayle   if (!new_frame.get())
350*9712c20fSFrederick Mayle     return NULL;
351*9712c20fSFrederick Mayle 
352*9712c20fSFrederick Mayle   if (system_info_->os_short == "nacl") {
353*9712c20fSFrederick Mayle     // Apply constraints from Native Client's x86-64 sandbox.  These
354*9712c20fSFrederick Mayle     // registers have the 4GB-aligned sandbox base address (from r15)
355*9712c20fSFrederick Mayle     // added to them, and only the bottom 32 bits are relevant for
356*9712c20fSFrederick Mayle     // stack walking.
357*9712c20fSFrederick Mayle     new_frame->context.rip = static_cast<uint32_t>(new_frame->context.rip);
358*9712c20fSFrederick Mayle     new_frame->context.rsp = static_cast<uint32_t>(new_frame->context.rsp);
359*9712c20fSFrederick Mayle     new_frame->context.rbp = static_cast<uint32_t>(new_frame->context.rbp);
360*9712c20fSFrederick Mayle   }
361*9712c20fSFrederick Mayle 
362*9712c20fSFrederick Mayle   // Should we terminate the stack walk? (end-of-stack or broken invariant)
363*9712c20fSFrederick Mayle   if (TerminateWalk(new_frame->context.rip, new_frame->context.rsp,
364*9712c20fSFrederick Mayle                     last_frame->context.rsp,
365*9712c20fSFrederick Mayle                     /*first_unwind=*/last_frame->trust ==
366*9712c20fSFrederick Mayle                         StackFrame::FRAME_TRUST_CONTEXT)) {
367*9712c20fSFrederick Mayle     return NULL;
368*9712c20fSFrederick Mayle   }
369*9712c20fSFrederick Mayle 
370*9712c20fSFrederick Mayle   // new_frame->context.rip is the return address, which is the instruction
371*9712c20fSFrederick Mayle   // after the CALL that caused us to arrive at the callee. Set
372*9712c20fSFrederick Mayle   // new_frame->instruction to one less than that, so it points within the
373*9712c20fSFrederick Mayle   // CALL instruction. See StackFrame::instruction for details, and
374*9712c20fSFrederick Mayle   // StackFrameAMD64::ReturnAddress.
375*9712c20fSFrederick Mayle   new_frame->instruction = new_frame->context.rip - 1;
376*9712c20fSFrederick Mayle 
377*9712c20fSFrederick Mayle   return new_frame.release();
378*9712c20fSFrederick Mayle }
379*9712c20fSFrederick Mayle 
380*9712c20fSFrederick Mayle }  // namespace google_breakpad
381