// SPDX-License-Identifier: GPL-2.0-only /* * Backtrace support. */ #include #include #include extern char vector_stub_start, vector_stub_end; int arch_backtrace_frame(const void *frame, const void **return_addrs, int max_depth, bool current_frame) { const void *fp = frame; static bool walking; void *lr; int depth; bool is_exception = false; unsigned long addr; if (current_frame) fp = __builtin_frame_address(0); if (walking) { printf("RECURSIVE STACK WALK!!!\n"); return 0; } walking = true; /* * ARM64 stack grows down. fp points to the previous fp on the stack, * and lr is just above it */ for (depth = 0; fp && depth < max_depth; ++depth) { asm volatile ("ldp %0, %1, [%2]" : "=r" (fp), "=r" (lr) : "r" (fp) : ); return_addrs[depth] = lr; /* * If this is an exception, add 1 to the pointer so when the * pretty_print_stacks script is run it would get the right * address (it deducts 1 to find the call address, but we want * the actual address). */ if (is_exception) return_addrs[depth] += 1; /* Check if we are in the exception handlers for the next entry */ addr = (unsigned long)lr; is_exception = (addr >= (unsigned long)&vector_stub_start && addr < (unsigned long)&vector_stub_end); } walking = false; return depth; }