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