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 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