xref: /kvm-unit-tests/lib/arm64/stack.c (revision d9de80518112e083dfe412546e422c4e044c31d9)
1*d9de8051SNadav Amit // SPDX-License-Identifier: GPL-2.0-only
2*d9de8051SNadav Amit /*
3*d9de8051SNadav Amit  * Backtrace support.
4*d9de8051SNadav Amit  */
5*d9de8051SNadav Amit #include <libcflat.h>
6*d9de8051SNadav Amit #include <stdbool.h>
7*d9de8051SNadav Amit #include <stack.h>
8*d9de8051SNadav Amit 
9*d9de8051SNadav Amit int backtrace_frame(const void *frame, const void **return_addrs, int max_depth)
10*d9de8051SNadav Amit {
11*d9de8051SNadav Amit 	const void *fp = frame;
12*d9de8051SNadav Amit 	static bool walking;
13*d9de8051SNadav Amit 	void *lr;
14*d9de8051SNadav Amit 	int depth;
15*d9de8051SNadav Amit 
16*d9de8051SNadav Amit 	if (walking) {
17*d9de8051SNadav Amit 		printf("RECURSIVE STACK WALK!!!\n");
18*d9de8051SNadav Amit 		return 0;
19*d9de8051SNadav Amit 	}
20*d9de8051SNadav Amit 	walking = true;
21*d9de8051SNadav Amit 
22*d9de8051SNadav Amit 	/*
23*d9de8051SNadav Amit 	 * ARM64 stack grows down. fp points to the previous fp on the stack,
24*d9de8051SNadav Amit 	 * and lr is just above it
25*d9de8051SNadav Amit 	 */
26*d9de8051SNadav Amit 	for (depth = 0; fp && depth < max_depth; ++depth) {
27*d9de8051SNadav Amit 
28*d9de8051SNadav Amit 		asm volatile ("ldp %0, %1, [%2]"
29*d9de8051SNadav Amit 				  : "=r" (fp), "=r" (lr)
30*d9de8051SNadav Amit 				  : "r" (fp)
31*d9de8051SNadav Amit 				  : );
32*d9de8051SNadav Amit 
33*d9de8051SNadav Amit 		return_addrs[depth] = lr;
34*d9de8051SNadav Amit 	}
35*d9de8051SNadav Amit 
36*d9de8051SNadav Amit 	walking = false;
37*d9de8051SNadav Amit 	return depth;
38*d9de8051SNadav Amit }
39*d9de8051SNadav Amit 
40*d9de8051SNadav Amit int backtrace(const void **return_addrs, int max_depth)
41*d9de8051SNadav Amit {
42*d9de8051SNadav Amit 	return backtrace_frame(__builtin_frame_address(0),
43*d9de8051SNadav Amit 			       return_addrs, max_depth);
44*d9de8051SNadav Amit }
45