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