xref: /kvm-unit-tests/lib/stack.c (revision 52266791750d89b7f4ab6bad4d42de0056e4fb32)
1*52266791SPeter Feiner #include <libcflat.h>
2*52266791SPeter Feiner #include <stack.h>
3*52266791SPeter Feiner 
4*52266791SPeter Feiner #define MAX_DEPTH 20
5*52266791SPeter Feiner 
6*52266791SPeter Feiner static void print_stack(const void **return_addrs, int depth,
7*52266791SPeter Feiner 			bool top_is_return_address)
8*52266791SPeter Feiner {
9*52266791SPeter Feiner 	int i = 0;
10*52266791SPeter Feiner 
11*52266791SPeter Feiner 	printf("\tSTACK:");
12*52266791SPeter Feiner 
13*52266791SPeter Feiner 	/* @addr indicates a non-return address, as expected by the stack
14*52266791SPeter Feiner 	 * pretty printer script. */
15*52266791SPeter Feiner 	if (depth > 0 && !top_is_return_address) {
16*52266791SPeter Feiner 		printf(" @%lx", (unsigned long) return_addrs[0]);
17*52266791SPeter Feiner 		i++;
18*52266791SPeter Feiner 	}
19*52266791SPeter Feiner 
20*52266791SPeter Feiner 	for (; i < depth; i++) {
21*52266791SPeter Feiner 		printf(" %lx", (unsigned long) return_addrs[i]);
22*52266791SPeter Feiner 	}
23*52266791SPeter Feiner 	printf("\n");
24*52266791SPeter Feiner }
25*52266791SPeter Feiner 
26*52266791SPeter Feiner void dump_stack(void)
27*52266791SPeter Feiner {
28*52266791SPeter Feiner 	const void *return_addrs[MAX_DEPTH];
29*52266791SPeter Feiner 	int depth;
30*52266791SPeter Feiner 
31*52266791SPeter Feiner 	depth = backtrace(return_addrs, MAX_DEPTH);
32*52266791SPeter Feiner 	print_stack(&return_addrs[1], depth ? depth - 1 : 0, true);
33*52266791SPeter Feiner }
34*52266791SPeter Feiner 
35*52266791SPeter Feiner void dump_frame_stack(const void *instruction, const void *frame)
36*52266791SPeter Feiner {
37*52266791SPeter Feiner 	const void *return_addrs[MAX_DEPTH];
38*52266791SPeter Feiner 	int depth;
39*52266791SPeter Feiner 
40*52266791SPeter Feiner 	return_addrs[0] = instruction;
41*52266791SPeter Feiner 	depth = backtrace_frame(frame, &return_addrs[1], MAX_DEPTH - 1);
42*52266791SPeter Feiner 	print_stack(return_addrs, depth + 1, false);
43*52266791SPeter Feiner }
44*52266791SPeter Feiner 
45*52266791SPeter Feiner #ifndef HAVE_ARCH_BACKTRACE
46*52266791SPeter Feiner int backtrace(const void **return_addrs, int max_depth)
47*52266791SPeter Feiner {
48*52266791SPeter Feiner 	static int walking;
49*52266791SPeter Feiner 	int depth = 0;
50*52266791SPeter Feiner 	void *addr;
51*52266791SPeter Feiner 
52*52266791SPeter Feiner 	if (walking) {
53*52266791SPeter Feiner 		printf("RECURSIVE STACK WALK!!!\n");
54*52266791SPeter Feiner 		return 0;
55*52266791SPeter Feiner 	}
56*52266791SPeter Feiner 	walking = 1;
57*52266791SPeter Feiner 
58*52266791SPeter Feiner 	/* __builtin_return_address requires a compile-time constant argument */
59*52266791SPeter Feiner #define GET_RETURN_ADDRESS(i)						\
60*52266791SPeter Feiner 	if (max_depth == i)						\
61*52266791SPeter Feiner 		goto done;						\
62*52266791SPeter Feiner 	addr = __builtin_return_address(i);				\
63*52266791SPeter Feiner 	if (!addr)							\
64*52266791SPeter Feiner 		goto done;						\
65*52266791SPeter Feiner 	return_addrs[i] = __builtin_extract_return_addr(addr);		\
66*52266791SPeter Feiner 	depth = i + 1;							\
67*52266791SPeter Feiner 
68*52266791SPeter Feiner 	GET_RETURN_ADDRESS(0)
69*52266791SPeter Feiner 	GET_RETURN_ADDRESS(1)
70*52266791SPeter Feiner 	GET_RETURN_ADDRESS(2)
71*52266791SPeter Feiner 	GET_RETURN_ADDRESS(3)
72*52266791SPeter Feiner 	GET_RETURN_ADDRESS(4)
73*52266791SPeter Feiner 	GET_RETURN_ADDRESS(5)
74*52266791SPeter Feiner 	GET_RETURN_ADDRESS(6)
75*52266791SPeter Feiner 	GET_RETURN_ADDRESS(7)
76*52266791SPeter Feiner 	GET_RETURN_ADDRESS(8)
77*52266791SPeter Feiner 	GET_RETURN_ADDRESS(9)
78*52266791SPeter Feiner 	GET_RETURN_ADDRESS(10)
79*52266791SPeter Feiner 	GET_RETURN_ADDRESS(11)
80*52266791SPeter Feiner 	GET_RETURN_ADDRESS(12)
81*52266791SPeter Feiner 	GET_RETURN_ADDRESS(13)
82*52266791SPeter Feiner 	GET_RETURN_ADDRESS(14)
83*52266791SPeter Feiner 	GET_RETURN_ADDRESS(15)
84*52266791SPeter Feiner 	GET_RETURN_ADDRESS(16)
85*52266791SPeter Feiner 	GET_RETURN_ADDRESS(17)
86*52266791SPeter Feiner 	GET_RETURN_ADDRESS(18)
87*52266791SPeter Feiner 	GET_RETURN_ADDRESS(19)
88*52266791SPeter Feiner 	GET_RETURN_ADDRESS(20)
89*52266791SPeter Feiner 
90*52266791SPeter Feiner #undef GET_RETURN_ADDRESS
91*52266791SPeter Feiner 
92*52266791SPeter Feiner done:
93*52266791SPeter Feiner 	walking = 0;
94*52266791SPeter Feiner 	return depth;
95*52266791SPeter Feiner }
96*52266791SPeter Feiner #endif  /* HAVE_ARCH_BACKTRACE */
97