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