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