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