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