xref: /aosp_15_r20/external/google-breakpad/src/processor/stackwalker_riscv64.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1*9712c20fSFrederick Mayle // Copyright 2013 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_riscv64.cc: riscv64-specific stackwalker.
30*9712c20fSFrederick Mayle  *
31*9712c20fSFrederick Mayle  * See stackwalker_riscv64.h for documentation.
32*9712c20fSFrederick Mayle  *
33*9712c20fSFrederick Mayle  * Author: Iacopo Colonnelli
34*9712c20fSFrederick Mayle  */
35*9712c20fSFrederick Mayle 
36*9712c20fSFrederick Mayle #ifdef HAVE_CONFIG_H
37*9712c20fSFrederick Mayle #include <config.h>  // Must come first
38*9712c20fSFrederick Mayle #endif
39*9712c20fSFrederick Mayle 
40*9712c20fSFrederick Mayle #include "common/scoped_ptr.h"
41*9712c20fSFrederick Mayle #include "google_breakpad/processor/call_stack.h"
42*9712c20fSFrederick Mayle #include "google_breakpad/processor/code_modules.h"
43*9712c20fSFrederick Mayle #include "google_breakpad/processor/memory_region.h"
44*9712c20fSFrederick Mayle #include "google_breakpad/processor/stack_frame_cpu.h"
45*9712c20fSFrederick Mayle #include "google_breakpad/processor/system_info.h"
46*9712c20fSFrederick Mayle #include "processor/cfi_frame_info.h"
47*9712c20fSFrederick Mayle #include "processor/logging.h"
48*9712c20fSFrederick Mayle #include "processor/stackwalker_riscv64.h"
49*9712c20fSFrederick Mayle 
50*9712c20fSFrederick Mayle namespace google_breakpad {
51*9712c20fSFrederick Mayle 
StackwalkerRISCV64(const SystemInfo * system_info,const MDRawContextRISCV64 * context,MemoryRegion * memory,const CodeModules * modules,StackFrameSymbolizer * resolver_helper)52*9712c20fSFrederick Mayle StackwalkerRISCV64::StackwalkerRISCV64(const SystemInfo* system_info,
53*9712c20fSFrederick Mayle                                        const MDRawContextRISCV64* context,
54*9712c20fSFrederick Mayle                                        MemoryRegion* memory,
55*9712c20fSFrederick Mayle                                        const CodeModules* modules,
56*9712c20fSFrederick Mayle                                        StackFrameSymbolizer* resolver_helper)
57*9712c20fSFrederick Mayle     : Stackwalker(system_info, memory, modules, resolver_helper),
58*9712c20fSFrederick Mayle       context_(context),
59*9712c20fSFrederick Mayle       context_frame_validity_(StackFrameRISCV::CONTEXT_VALID_ALL) {
60*9712c20fSFrederick Mayle }
61*9712c20fSFrederick Mayle 
62*9712c20fSFrederick Mayle 
GetContextFrame()63*9712c20fSFrederick Mayle StackFrame* StackwalkerRISCV64::GetContextFrame() {
64*9712c20fSFrederick Mayle   if (!context_) {
65*9712c20fSFrederick Mayle     BPLOG(ERROR) << "Can't get context frame without context";
66*9712c20fSFrederick Mayle     return NULL;
67*9712c20fSFrederick Mayle   }
68*9712c20fSFrederick Mayle 
69*9712c20fSFrederick Mayle   StackFrameRISCV64* frame = new StackFrameRISCV64();
70*9712c20fSFrederick Mayle 
71*9712c20fSFrederick Mayle   frame->context = *context_;
72*9712c20fSFrederick Mayle   frame->context_validity = context_frame_validity_;
73*9712c20fSFrederick Mayle   frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
74*9712c20fSFrederick Mayle   frame->instruction = frame->context.pc;
75*9712c20fSFrederick Mayle 
76*9712c20fSFrederick Mayle   return frame;
77*9712c20fSFrederick Mayle }
78*9712c20fSFrederick Mayle 
GetCallerByCFIFrameInfo(const vector<StackFrame * > & frames,CFIFrameInfo * cfi_frame_info)79*9712c20fSFrederick Mayle StackFrameRISCV64* StackwalkerRISCV64::GetCallerByCFIFrameInfo(
80*9712c20fSFrederick Mayle     const vector<StackFrame*>& frames,
81*9712c20fSFrederick Mayle     CFIFrameInfo* cfi_frame_info) {
82*9712c20fSFrederick Mayle   StackFrameRISCV64* last_frame =
83*9712c20fSFrederick Mayle       static_cast<StackFrameRISCV64*>(frames.back());
84*9712c20fSFrederick Mayle 
85*9712c20fSFrederick Mayle   // Populate a dictionary with the valid register values in last_frame.
86*9712c20fSFrederick Mayle   CFIFrameInfo::RegisterValueMap<uint64_t> callee_registers;
87*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_PC)
88*9712c20fSFrederick Mayle     callee_registers["pc"] = last_frame->context.pc;
89*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_RA)
90*9712c20fSFrederick Mayle     callee_registers["ra"] = last_frame->context.ra;
91*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_SP)
92*9712c20fSFrederick Mayle     callee_registers["sp"] = last_frame->context.sp;
93*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_GP)
94*9712c20fSFrederick Mayle     callee_registers["gp"] = last_frame->context.gp;
95*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_TP)
96*9712c20fSFrederick Mayle     callee_registers["tp"] = last_frame->context.tp;
97*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_T0)
98*9712c20fSFrederick Mayle     callee_registers["t0"] = last_frame->context.t0;
99*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_T1)
100*9712c20fSFrederick Mayle     callee_registers["t1"] = last_frame->context.t1;
101*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_T2)
102*9712c20fSFrederick Mayle     callee_registers["t2"] = last_frame->context.t2;
103*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_S0)
104*9712c20fSFrederick Mayle     callee_registers["s0"] = last_frame->context.s0;
105*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_S1)
106*9712c20fSFrederick Mayle     callee_registers["s1"] = last_frame->context.s1;
107*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_A0)
108*9712c20fSFrederick Mayle     callee_registers["a0"] = last_frame->context.a0;
109*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_A1)
110*9712c20fSFrederick Mayle     callee_registers["a1"] = last_frame->context.a1;
111*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_A2)
112*9712c20fSFrederick Mayle     callee_registers["a2"] = last_frame->context.a2;
113*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_A3)
114*9712c20fSFrederick Mayle     callee_registers["a3"] = last_frame->context.a3;
115*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_A4)
116*9712c20fSFrederick Mayle     callee_registers["a4"] = last_frame->context.a4;
117*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_A5)
118*9712c20fSFrederick Mayle     callee_registers["a5"] = last_frame->context.a5;
119*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_A6)
120*9712c20fSFrederick Mayle     callee_registers["a6"] = last_frame->context.a6;
121*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_A7)
122*9712c20fSFrederick Mayle     callee_registers["a7"] = last_frame->context.a7;
123*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_S2)
124*9712c20fSFrederick Mayle     callee_registers["s2"] = last_frame->context.s2;
125*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_S3)
126*9712c20fSFrederick Mayle     callee_registers["s3"] = last_frame->context.s3;
127*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_S4)
128*9712c20fSFrederick Mayle     callee_registers["s4"] = last_frame->context.s4;
129*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_S5)
130*9712c20fSFrederick Mayle     callee_registers["s5"] = last_frame->context.s5;
131*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_S6)
132*9712c20fSFrederick Mayle     callee_registers["s6"] = last_frame->context.s6;
133*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_S7)
134*9712c20fSFrederick Mayle     callee_registers["s7"] = last_frame->context.s7;
135*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_S8)
136*9712c20fSFrederick Mayle     callee_registers["s8"] = last_frame->context.s8;
137*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_S9)
138*9712c20fSFrederick Mayle     callee_registers["s9"] = last_frame->context.s9;
139*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_S10)
140*9712c20fSFrederick Mayle     callee_registers["s10"] = last_frame->context.s10;
141*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_S11)
142*9712c20fSFrederick Mayle     callee_registers["s11"] = last_frame->context.s11;
143*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_T3)
144*9712c20fSFrederick Mayle     callee_registers["t3"] = last_frame->context.t3;
145*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_T4)
146*9712c20fSFrederick Mayle     callee_registers["t4"] = last_frame->context.t4;
147*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_T5)
148*9712c20fSFrederick Mayle     callee_registers["t5"] = last_frame->context.t5;
149*9712c20fSFrederick Mayle   if (last_frame->context_validity & StackFrameRISCV64::CONTEXT_VALID_T6)
150*9712c20fSFrederick Mayle     callee_registers["t6"] = last_frame->context.t6;
151*9712c20fSFrederick Mayle 
152*9712c20fSFrederick Mayle   // Use the STACK CFI data to recover the caller's register values.
153*9712c20fSFrederick Mayle   CFIFrameInfo::RegisterValueMap<uint64_t> caller_registers;
154*9712c20fSFrederick Mayle   if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_,
155*9712c20fSFrederick Mayle                                       &caller_registers)) {
156*9712c20fSFrederick Mayle     return NULL;
157*9712c20fSFrederick Mayle   }
158*9712c20fSFrederick Mayle 
159*9712c20fSFrederick Mayle   // Construct a new stack frame given the values the CFI recovered.
160*9712c20fSFrederick Mayle   CFIFrameInfo::RegisterValueMap<uint64_t>::iterator entry;
161*9712c20fSFrederick Mayle   scoped_ptr<StackFrameRISCV64> frame(new StackFrameRISCV64());
162*9712c20fSFrederick Mayle   entry = caller_registers.find("pc");
163*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
164*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_PC;
165*9712c20fSFrederick Mayle     frame->context.pc = entry->second;
166*9712c20fSFrederick Mayle   } else{
167*9712c20fSFrederick Mayle     // If the CFI doesn't recover the PC explicitly, then use .ra.
168*9712c20fSFrederick Mayle     entry = caller_registers.find(".ra");
169*9712c20fSFrederick Mayle     if (entry != caller_registers.end()) {
170*9712c20fSFrederick Mayle       frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_PC;
171*9712c20fSFrederick Mayle       frame->context.pc = entry->second;
172*9712c20fSFrederick Mayle     }
173*9712c20fSFrederick Mayle   }
174*9712c20fSFrederick Mayle   entry = caller_registers.find("ra");
175*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
176*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_RA;
177*9712c20fSFrederick Mayle     frame->context.ra = entry->second;
178*9712c20fSFrederick Mayle   }
179*9712c20fSFrederick Mayle   entry = caller_registers.find("sp");
180*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
181*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_SP;
182*9712c20fSFrederick Mayle     frame->context.sp = entry->second;
183*9712c20fSFrederick Mayle   } else {
184*9712c20fSFrederick Mayle     // If the CFI doesn't recover the SP explicitly, then use .cfa.
185*9712c20fSFrederick Mayle     entry = caller_registers.find(".cfa");
186*9712c20fSFrederick Mayle     if (entry != caller_registers.end()) {
187*9712c20fSFrederick Mayle       frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_SP;
188*9712c20fSFrederick Mayle       frame->context.sp = entry->second;
189*9712c20fSFrederick Mayle     }
190*9712c20fSFrederick Mayle   }
191*9712c20fSFrederick Mayle   entry = caller_registers.find("gp");
192*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
193*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_GP;
194*9712c20fSFrederick Mayle     frame->context.gp = entry->second;
195*9712c20fSFrederick Mayle   }
196*9712c20fSFrederick Mayle   entry = caller_registers.find("tp");
197*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
198*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_TP;
199*9712c20fSFrederick Mayle     frame->context.tp = entry->second;
200*9712c20fSFrederick Mayle   }
201*9712c20fSFrederick Mayle   entry = caller_registers.find("t0");
202*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
203*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_T0;
204*9712c20fSFrederick Mayle     frame->context.t0 = entry->second;
205*9712c20fSFrederick Mayle   }
206*9712c20fSFrederick Mayle   entry = caller_registers.find("t1");
207*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
208*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_T1;
209*9712c20fSFrederick Mayle     frame->context.t1 = entry->second;
210*9712c20fSFrederick Mayle   }
211*9712c20fSFrederick Mayle   entry = caller_registers.find("t2");
212*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
213*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_T2;
214*9712c20fSFrederick Mayle     frame->context.t2 = entry->second;
215*9712c20fSFrederick Mayle   }
216*9712c20fSFrederick Mayle   entry = caller_registers.find("s0");
217*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
218*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S0;
219*9712c20fSFrederick Mayle     frame->context.s0 = entry->second;
220*9712c20fSFrederick Mayle   } else if (last_frame->context_validity &
221*9712c20fSFrederick Mayle              StackFrameRISCV64::CONTEXT_VALID_S0) {
222*9712c20fSFrederick Mayle     // Since the register is callee-saves, assume the callee
223*9712c20fSFrederick Mayle     // has not yet changed it.
224*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S0;
225*9712c20fSFrederick Mayle     frame->context.s0 = last_frame->context.s0;
226*9712c20fSFrederick Mayle   }
227*9712c20fSFrederick Mayle   entry = caller_registers.find("s1");
228*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
229*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S1;
230*9712c20fSFrederick Mayle     frame->context.s1 = entry->second;
231*9712c20fSFrederick Mayle   } else if (last_frame->context_validity &
232*9712c20fSFrederick Mayle              StackFrameRISCV64::CONTEXT_VALID_S1) {
233*9712c20fSFrederick Mayle     // Since the register is callee-saves, assume the callee
234*9712c20fSFrederick Mayle     // has not yet changed it.
235*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S1;
236*9712c20fSFrederick Mayle     frame->context.s1 = last_frame->context.s1;
237*9712c20fSFrederick Mayle   }
238*9712c20fSFrederick Mayle   entry = caller_registers.find("a0");
239*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
240*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_A0;
241*9712c20fSFrederick Mayle     frame->context.a0 = entry->second;
242*9712c20fSFrederick Mayle   }
243*9712c20fSFrederick Mayle   entry = caller_registers.find("a1");
244*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
245*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_A1;
246*9712c20fSFrederick Mayle     frame->context.a1 = entry->second;
247*9712c20fSFrederick Mayle   }
248*9712c20fSFrederick Mayle   entry = caller_registers.find("a2");
249*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
250*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_A2;
251*9712c20fSFrederick Mayle     frame->context.a2 = entry->second;
252*9712c20fSFrederick Mayle   }
253*9712c20fSFrederick Mayle   entry = caller_registers.find("a3");
254*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
255*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_A3;
256*9712c20fSFrederick Mayle     frame->context.a3 = entry->second;
257*9712c20fSFrederick Mayle   }
258*9712c20fSFrederick Mayle   entry = caller_registers.find("a4");
259*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
260*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_A4;
261*9712c20fSFrederick Mayle     frame->context.a4 = entry->second;
262*9712c20fSFrederick Mayle   }
263*9712c20fSFrederick Mayle   entry = caller_registers.find("a5");
264*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
265*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_A5;
266*9712c20fSFrederick Mayle     frame->context.a5 = entry->second;
267*9712c20fSFrederick Mayle   }
268*9712c20fSFrederick Mayle   entry = caller_registers.find("a6");
269*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
270*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_A6;
271*9712c20fSFrederick Mayle     frame->context.a6 = entry->second;
272*9712c20fSFrederick Mayle   }
273*9712c20fSFrederick Mayle   entry = caller_registers.find("a7");
274*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
275*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_A7;
276*9712c20fSFrederick Mayle     frame->context.a7 = entry->second;
277*9712c20fSFrederick Mayle   }
278*9712c20fSFrederick Mayle   entry = caller_registers.find("s2");
279*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
280*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S2;
281*9712c20fSFrederick Mayle     frame->context.s2 = entry->second;
282*9712c20fSFrederick Mayle   } else if (last_frame->context_validity &
283*9712c20fSFrederick Mayle              StackFrameRISCV64::CONTEXT_VALID_S2) {
284*9712c20fSFrederick Mayle     // Since the register is callee-saves, assume the callee
285*9712c20fSFrederick Mayle     // has not yet changed it.
286*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S2;
287*9712c20fSFrederick Mayle     frame->context.s2 = last_frame->context.s2;
288*9712c20fSFrederick Mayle   }
289*9712c20fSFrederick Mayle   entry = caller_registers.find("s3");
290*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
291*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S3;
292*9712c20fSFrederick Mayle     frame->context.s3 = entry->second;
293*9712c20fSFrederick Mayle   } else if (last_frame->context_validity &
294*9712c20fSFrederick Mayle              StackFrameRISCV64::CONTEXT_VALID_S3) {
295*9712c20fSFrederick Mayle     // Since the register is callee-saves, assume the callee
296*9712c20fSFrederick Mayle     // has not yet changed it.
297*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S3;
298*9712c20fSFrederick Mayle     frame->context.s3 = last_frame->context.s3;
299*9712c20fSFrederick Mayle   }
300*9712c20fSFrederick Mayle   entry = caller_registers.find("s4");
301*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
302*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S4;
303*9712c20fSFrederick Mayle     frame->context.s4 = entry->second;
304*9712c20fSFrederick Mayle   } else if (last_frame->context_validity &
305*9712c20fSFrederick Mayle              StackFrameRISCV64::CONTEXT_VALID_S4) {
306*9712c20fSFrederick Mayle     // Since the register is callee-saves, assume the callee
307*9712c20fSFrederick Mayle     // has not yet changed it.
308*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S4;
309*9712c20fSFrederick Mayle     frame->context.s4 = last_frame->context.s4;
310*9712c20fSFrederick Mayle   }
311*9712c20fSFrederick Mayle   entry = caller_registers.find("s5");
312*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
313*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S5;
314*9712c20fSFrederick Mayle     frame->context.s5 = entry->second;
315*9712c20fSFrederick Mayle   } else if (last_frame->context_validity &
316*9712c20fSFrederick Mayle              StackFrameRISCV64::CONTEXT_VALID_S5) {
317*9712c20fSFrederick Mayle     // Since the register is callee-saves, assume the callee
318*9712c20fSFrederick Mayle     // has not yet changed it.
319*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S5;
320*9712c20fSFrederick Mayle     frame->context.s5 = last_frame->context.s5;
321*9712c20fSFrederick Mayle   }
322*9712c20fSFrederick Mayle   entry = caller_registers.find("s6");
323*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
324*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S6;
325*9712c20fSFrederick Mayle     frame->context.s6 = entry->second;
326*9712c20fSFrederick Mayle   } else if (last_frame->context_validity &
327*9712c20fSFrederick Mayle              StackFrameRISCV64::CONTEXT_VALID_S6) {
328*9712c20fSFrederick Mayle     // Since the register is callee-saves, assume the callee
329*9712c20fSFrederick Mayle     // has not yet changed it.
330*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S6;
331*9712c20fSFrederick Mayle     frame->context.s6 = last_frame->context.s6;
332*9712c20fSFrederick Mayle   }
333*9712c20fSFrederick Mayle   entry = caller_registers.find("s7");
334*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
335*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S7;
336*9712c20fSFrederick Mayle     frame->context.s7 = entry->second;
337*9712c20fSFrederick Mayle   } else if (last_frame->context_validity &
338*9712c20fSFrederick Mayle              StackFrameRISCV64::CONTEXT_VALID_S7) {
339*9712c20fSFrederick Mayle     // Since the register is callee-saves, assume the callee
340*9712c20fSFrederick Mayle     // has not yet changed it.
341*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S7;
342*9712c20fSFrederick Mayle     frame->context.s7 = last_frame->context.s7;
343*9712c20fSFrederick Mayle   }
344*9712c20fSFrederick Mayle   entry = caller_registers.find("s8");
345*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
346*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S8;
347*9712c20fSFrederick Mayle     frame->context.s8 = entry->second;
348*9712c20fSFrederick Mayle   } else if (last_frame->context_validity &
349*9712c20fSFrederick Mayle              StackFrameRISCV64::CONTEXT_VALID_S8) {
350*9712c20fSFrederick Mayle     // Since the register is callee-saves, assume the callee
351*9712c20fSFrederick Mayle     // has not yet changed it.
352*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S8;
353*9712c20fSFrederick Mayle     frame->context.s8 = last_frame->context.s8;
354*9712c20fSFrederick Mayle   }
355*9712c20fSFrederick Mayle   entry = caller_registers.find("s9");
356*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
357*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S9;
358*9712c20fSFrederick Mayle     frame->context.s9 = entry->second;
359*9712c20fSFrederick Mayle   } else if (last_frame->context_validity &
360*9712c20fSFrederick Mayle              StackFrameRISCV64::CONTEXT_VALID_S9) {
361*9712c20fSFrederick Mayle     // Since the register is callee-saves, assume the callee
362*9712c20fSFrederick Mayle     // has not yet changed it.
363*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S9;
364*9712c20fSFrederick Mayle     frame->context.s9 = last_frame->context.s9;
365*9712c20fSFrederick Mayle   }
366*9712c20fSFrederick Mayle   entry = caller_registers.find("s10");
367*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
368*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S10;
369*9712c20fSFrederick Mayle     frame->context.s10 = entry->second;
370*9712c20fSFrederick Mayle   } else if (last_frame->context_validity &
371*9712c20fSFrederick Mayle              StackFrameRISCV64::CONTEXT_VALID_S10) {
372*9712c20fSFrederick Mayle     // Since the register is callee-saves, assume the callee
373*9712c20fSFrederick Mayle     // has not yet changed it.
374*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S10;
375*9712c20fSFrederick Mayle     frame->context.s10 = last_frame->context.s10;
376*9712c20fSFrederick Mayle   }
377*9712c20fSFrederick Mayle   entry = caller_registers.find("s11");
378*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
379*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S11;
380*9712c20fSFrederick Mayle     frame->context.s11 = entry->second;
381*9712c20fSFrederick Mayle   } else if (last_frame->context_validity &
382*9712c20fSFrederick Mayle              StackFrameRISCV64::CONTEXT_VALID_S11) {
383*9712c20fSFrederick Mayle     // Since the register is callee-saves, assume the callee
384*9712c20fSFrederick Mayle     // has not yet changed it.
385*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_S11;
386*9712c20fSFrederick Mayle     frame->context.s11 = last_frame->context.s11;
387*9712c20fSFrederick Mayle   }
388*9712c20fSFrederick Mayle   entry = caller_registers.find("t3");
389*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
390*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_T3;
391*9712c20fSFrederick Mayle     frame->context.t3 = entry->second;
392*9712c20fSFrederick Mayle   }
393*9712c20fSFrederick Mayle   entry = caller_registers.find("t4");
394*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
395*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_T4;
396*9712c20fSFrederick Mayle     frame->context.t4 = entry->second;
397*9712c20fSFrederick Mayle   }
398*9712c20fSFrederick Mayle   entry = caller_registers.find("t5");
399*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
400*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_T5;
401*9712c20fSFrederick Mayle     frame->context.t5 = entry->second;
402*9712c20fSFrederick Mayle   }
403*9712c20fSFrederick Mayle   entry = caller_registers.find("t6");
404*9712c20fSFrederick Mayle   if (entry != caller_registers.end()) {
405*9712c20fSFrederick Mayle     frame->context_validity |= StackFrameRISCV64::CONTEXT_VALID_T6;
406*9712c20fSFrederick Mayle     frame->context.t6 = entry->second;
407*9712c20fSFrederick Mayle   }
408*9712c20fSFrederick Mayle 
409*9712c20fSFrederick Mayle   // If we didn't recover the PC and the SP, then the frame isn't very useful.
410*9712c20fSFrederick Mayle   static const uint64_t essentials = (StackFrameRISCV64::CONTEXT_VALID_SP
411*9712c20fSFrederick Mayle                                       | StackFrameRISCV64::CONTEXT_VALID_PC);
412*9712c20fSFrederick Mayle   if ((frame->context_validity & essentials) != essentials)
413*9712c20fSFrederick Mayle     return NULL;
414*9712c20fSFrederick Mayle 
415*9712c20fSFrederick Mayle   frame->trust = StackFrame::FRAME_TRUST_CFI;
416*9712c20fSFrederick Mayle   return frame.release();
417*9712c20fSFrederick Mayle }
418*9712c20fSFrederick Mayle 
GetCallerByStackScan(const vector<StackFrame * > & frames)419*9712c20fSFrederick Mayle StackFrameRISCV64* StackwalkerRISCV64::GetCallerByStackScan(
420*9712c20fSFrederick Mayle     const vector<StackFrame*>& frames) {
421*9712c20fSFrederick Mayle   StackFrameRISCV64* last_frame =
422*9712c20fSFrederick Mayle       static_cast<StackFrameRISCV64*>(frames.back());
423*9712c20fSFrederick Mayle   uint64_t last_sp = last_frame->context.sp;
424*9712c20fSFrederick Mayle   uint64_t caller_sp, caller_pc;
425*9712c20fSFrederick Mayle 
426*9712c20fSFrederick Mayle   if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc,
427*9712c20fSFrederick Mayle       last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) {
428*9712c20fSFrederick Mayle     // No plausible return address was found.
429*9712c20fSFrederick Mayle     return NULL;
430*9712c20fSFrederick Mayle   }
431*9712c20fSFrederick Mayle 
432*9712c20fSFrederick Mayle   // ScanForReturnAddress found a reasonable return address. Advance
433*9712c20fSFrederick Mayle   // sp to the location above the one where the return address was
434*9712c20fSFrederick Mayle   // found.
435*9712c20fSFrederick Mayle   caller_sp += 8;
436*9712c20fSFrederick Mayle 
437*9712c20fSFrederick Mayle   // Create a new stack frame (ownership will be transferred to the caller)
438*9712c20fSFrederick Mayle   // and fill it in.
439*9712c20fSFrederick Mayle   StackFrameRISCV64* frame = new StackFrameRISCV64();
440*9712c20fSFrederick Mayle 
441*9712c20fSFrederick Mayle   frame->trust = StackFrame::FRAME_TRUST_SCAN;
442*9712c20fSFrederick Mayle   frame->context = last_frame->context;
443*9712c20fSFrederick Mayle   frame->context.pc = caller_pc;
444*9712c20fSFrederick Mayle   frame->context.sp = caller_sp;
445*9712c20fSFrederick Mayle   frame->context_validity = StackFrameRISCV64::CONTEXT_VALID_PC |
446*9712c20fSFrederick Mayle                             StackFrameRISCV64::CONTEXT_VALID_SP;
447*9712c20fSFrederick Mayle 
448*9712c20fSFrederick Mayle   return frame;
449*9712c20fSFrederick Mayle }
450*9712c20fSFrederick Mayle 
GetCallerByFramePointer(const vector<StackFrame * > & frames)451*9712c20fSFrederick Mayle StackFrameRISCV64* StackwalkerRISCV64::GetCallerByFramePointer(
452*9712c20fSFrederick Mayle     const vector<StackFrame*>& frames) {
453*9712c20fSFrederick Mayle   StackFrameRISCV64* last_frame =
454*9712c20fSFrederick Mayle       static_cast<StackFrameRISCV64*>(frames.back());
455*9712c20fSFrederick Mayle 
456*9712c20fSFrederick Mayle   uint64_t last_fp = last_frame->context.s0;
457*9712c20fSFrederick Mayle 
458*9712c20fSFrederick Mayle   uint64_t caller_fp = 0;
459*9712c20fSFrederick Mayle   if (last_fp && !memory_->GetMemoryAtAddress(last_fp, &caller_fp)) {
460*9712c20fSFrederick Mayle     BPLOG(ERROR) << "Unable to read caller_fp from last_fp: 0x"
461*9712c20fSFrederick Mayle                  << std::hex << last_fp;
462*9712c20fSFrederick Mayle     return NULL;
463*9712c20fSFrederick Mayle   }
464*9712c20fSFrederick Mayle 
465*9712c20fSFrederick Mayle   uint64_t caller_ra = 0;
466*9712c20fSFrederick Mayle   if (last_fp && !memory_->GetMemoryAtAddress(last_fp + 8, &caller_ra)) {
467*9712c20fSFrederick Mayle     BPLOG(ERROR) << "Unable to read caller_ra from last_fp + 8: 0x"
468*9712c20fSFrederick Mayle                  << std::hex << (last_fp + 8);
469*9712c20fSFrederick Mayle     return NULL;
470*9712c20fSFrederick Mayle   }
471*9712c20fSFrederick Mayle 
472*9712c20fSFrederick Mayle   uint64_t caller_sp = last_fp ? last_fp + 16 : last_frame->context.s0;
473*9712c20fSFrederick Mayle 
474*9712c20fSFrederick Mayle   // Create a new stack frame (ownership will be transferred to the caller)
475*9712c20fSFrederick Mayle   // and fill it in.
476*9712c20fSFrederick Mayle   StackFrameRISCV64* frame = new StackFrameRISCV64();
477*9712c20fSFrederick Mayle 
478*9712c20fSFrederick Mayle   frame->trust = StackFrame::FRAME_TRUST_FP;
479*9712c20fSFrederick Mayle   frame->context = last_frame->context;
480*9712c20fSFrederick Mayle   frame->context.s0 = caller_fp;
481*9712c20fSFrederick Mayle   frame->context.sp = caller_sp;
482*9712c20fSFrederick Mayle   frame->context.pc = last_frame->context.ra;
483*9712c20fSFrederick Mayle   frame->context.ra = caller_ra;
484*9712c20fSFrederick Mayle   frame->context_validity = StackFrameRISCV64::CONTEXT_VALID_PC |
485*9712c20fSFrederick Mayle                             StackFrameRISCV64::CONTEXT_VALID_RA |
486*9712c20fSFrederick Mayle                             StackFrameRISCV64::CONTEXT_VALID_S0 |
487*9712c20fSFrederick Mayle                             StackFrameRISCV64::CONTEXT_VALID_SP;
488*9712c20fSFrederick Mayle   return frame;
489*9712c20fSFrederick Mayle }
490*9712c20fSFrederick Mayle 
GetCallerFrame(const CallStack * stack,bool stack_scan_allowed)491*9712c20fSFrederick Mayle StackFrame* StackwalkerRISCV64::GetCallerFrame(const CallStack* stack,
492*9712c20fSFrederick Mayle                                              bool stack_scan_allowed) {
493*9712c20fSFrederick Mayle   if (!memory_ || !stack) {
494*9712c20fSFrederick Mayle     BPLOG(ERROR) << "Can't get caller frame without memory or stack";
495*9712c20fSFrederick Mayle     return NULL;
496*9712c20fSFrederick Mayle   }
497*9712c20fSFrederick Mayle 
498*9712c20fSFrederick Mayle   const vector<StackFrame*>& frames = *stack->frames();
499*9712c20fSFrederick Mayle   StackFrameRISCV64* last_frame =
500*9712c20fSFrederick Mayle       static_cast<StackFrameRISCV64*>(frames.back());
501*9712c20fSFrederick Mayle   scoped_ptr<StackFrameRISCV64> frame;
502*9712c20fSFrederick Mayle 
503*9712c20fSFrederick Mayle   // Try to recover caller information from CFI.
504*9712c20fSFrederick Mayle   scoped_ptr<CFIFrameInfo> cfi_frame_info(
505*9712c20fSFrederick Mayle       frame_symbolizer_->FindCFIFrameInfo(last_frame));
506*9712c20fSFrederick Mayle   if (cfi_frame_info.get())
507*9712c20fSFrederick Mayle     frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get()));
508*9712c20fSFrederick Mayle 
509*9712c20fSFrederick Mayle   // If CFI failed, or there wasn't CFI available, fall back to frame pointer.
510*9712c20fSFrederick Mayle   if (!frame.get())
511*9712c20fSFrederick Mayle     frame.reset(GetCallerByFramePointer(frames));
512*9712c20fSFrederick Mayle 
513*9712c20fSFrederick Mayle   // If everything failed, fall back to stack scanning.
514*9712c20fSFrederick Mayle   if (stack_scan_allowed && !frame.get())
515*9712c20fSFrederick Mayle     frame.reset(GetCallerByStackScan(frames));
516*9712c20fSFrederick Mayle 
517*9712c20fSFrederick Mayle   // If nothing worked, tell the caller.
518*9712c20fSFrederick Mayle   if (!frame.get())
519*9712c20fSFrederick Mayle     return NULL;
520*9712c20fSFrederick Mayle 
521*9712c20fSFrederick Mayle   // Should we terminate the stack walk? (end-of-stack or broken invariant)
522*9712c20fSFrederick Mayle   if (TerminateWalk(frame->context.pc, frame->context.sp,
523*9712c20fSFrederick Mayle                     last_frame->context.sp,
524*9712c20fSFrederick Mayle                     last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT)) {
525*9712c20fSFrederick Mayle     return NULL;
526*9712c20fSFrederick Mayle   }
527*9712c20fSFrederick Mayle 
528*9712c20fSFrederick Mayle   // The new frame's context's PC is the return address, which is one
529*9712c20fSFrederick Mayle   // instruction past the instruction that caused us to arrive at the callee.
530*9712c20fSFrederick Mayle   // RISCV instructions have a uniform 4-byte encoding, so subtracting 4 off
531*9712c20fSFrederick Mayle   // the return address gets back to the beginning of the call instruction.
532*9712c20fSFrederick Mayle   // Callers that require the exact return address value may access
533*9712c20fSFrederick Mayle   // frame->context.pc.
534*9712c20fSFrederick Mayle   frame->instruction = frame->context.pc - 4;
535*9712c20fSFrederick Mayle 
536*9712c20fSFrederick Mayle   return frame.release();
537*9712c20fSFrederick Mayle }
538*9712c20fSFrederick Mayle 
539*9712c20fSFrederick Mayle }  // namespace google_breakpad
540