xref: /kvm-unit-tests/lib/riscv/stack.c (revision 6fba6b84bae33db2b7fda1d4ff50f1d78e83adba)
1*6fba6b84SAndrew Jones // SPDX-License-Identifier: GPL-2.0-only
2*6fba6b84SAndrew Jones #include <libcflat.h>
3*6fba6b84SAndrew Jones #include <stack.h>
4*6fba6b84SAndrew Jones 
5*6fba6b84SAndrew Jones int backtrace_frame(const void *frame, const void **return_addrs, int max_depth)
6*6fba6b84SAndrew Jones {
7*6fba6b84SAndrew Jones 	static bool walking;
8*6fba6b84SAndrew Jones 	const unsigned long *fp = (unsigned long *)frame;
9*6fba6b84SAndrew Jones 	int depth;
10*6fba6b84SAndrew Jones 
11*6fba6b84SAndrew Jones 	if (walking) {
12*6fba6b84SAndrew Jones 		printf("RECURSIVE STACK WALK!!!\n");
13*6fba6b84SAndrew Jones 		return 0;
14*6fba6b84SAndrew Jones 	}
15*6fba6b84SAndrew Jones 	walking = true;
16*6fba6b84SAndrew Jones 
17*6fba6b84SAndrew Jones 	for (depth = 0; fp && depth < max_depth; ++depth) {
18*6fba6b84SAndrew Jones 		return_addrs[depth] = (void *)fp[-1];
19*6fba6b84SAndrew Jones 		if (return_addrs[depth] == 0)
20*6fba6b84SAndrew Jones 			break;
21*6fba6b84SAndrew Jones 		fp = (unsigned long *)fp[-2];
22*6fba6b84SAndrew Jones 	}
23*6fba6b84SAndrew Jones 
24*6fba6b84SAndrew Jones 	walking = false;
25*6fba6b84SAndrew Jones 	return depth;
26*6fba6b84SAndrew Jones }
27*6fba6b84SAndrew Jones 
28*6fba6b84SAndrew Jones int backtrace(const void **return_addrs, int max_depth)
29*6fba6b84SAndrew Jones {
30*6fba6b84SAndrew Jones 	return backtrace_frame(__builtin_frame_address(0),
31*6fba6b84SAndrew Jones 			       return_addrs, max_depth);
32*6fba6b84SAndrew Jones }
33