1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Backtrace support.
4 */
5 #include <libcflat.h>
6 #include <stdbool.h>
7 #include <stack.h>
8
9 extern char vector_stub_start, vector_stub_end;
10
arch_backtrace_frame(const void * frame,const void ** return_addrs,int max_depth,bool current_frame)11 int arch_backtrace_frame(const void *frame, const void **return_addrs,
12 int max_depth, bool current_frame)
13 {
14 const void *fp = frame;
15 static bool walking;
16 void *lr;
17 int depth;
18 bool is_exception = false;
19 unsigned long addr;
20
21 if (current_frame)
22 fp = __builtin_frame_address(0);
23
24 if (walking) {
25 printf("RECURSIVE STACK WALK!!!\n");
26 return 0;
27 }
28 walking = true;
29
30 /*
31 * ARM64 stack grows down. fp points to the previous fp on the stack,
32 * and lr is just above it
33 */
34 for (depth = 0; fp && depth < max_depth; ++depth) {
35
36 asm volatile ("ldp %0, %1, [%2]"
37 : "=r" (fp), "=r" (lr)
38 : "r" (fp)
39 : );
40
41 return_addrs[depth] = lr;
42
43 /*
44 * If this is an exception, add 1 to the pointer so when the
45 * pretty_print_stacks script is run it would get the right
46 * address (it deducts 1 to find the call address, but we want
47 * the actual address).
48 */
49 if (is_exception)
50 return_addrs[depth] += 1;
51
52 /* Check if we are in the exception handlers for the next entry */
53 addr = (unsigned long)lr;
54 is_exception = (addr >= (unsigned long)&vector_stub_start &&
55 addr < (unsigned long)&vector_stub_end);
56 }
57
58 walking = false;
59 return depth;
60 }
61