xref: /kvm-unit-tests/lib/stack.c (revision 4b6da8266e20882f41cdbbe254b08b900a5b9fbe)
1*4b6da826SThomas Huth /*
2*4b6da826SThomas Huth  * stack related functions
3*4b6da826SThomas Huth  *
4*4b6da826SThomas Huth  * This code is free software; you can redistribute it and/or modify it
5*4b6da826SThomas Huth  * under the terms of the GNU Library General Public License version 2.
6*4b6da826SThomas Huth  */
7*4b6da826SThomas Huth 
852266791SPeter Feiner #include <libcflat.h>
952266791SPeter Feiner #include <stack.h>
1052266791SPeter Feiner 
1152266791SPeter Feiner #define MAX_DEPTH 20
1252266791SPeter Feiner 
1352266791SPeter Feiner static void print_stack(const void **return_addrs, int depth,
1452266791SPeter Feiner 			bool top_is_return_address)
1552266791SPeter Feiner {
1652266791SPeter Feiner 	int i = 0;
1752266791SPeter Feiner 
1852266791SPeter Feiner 	printf("\tSTACK:");
1952266791SPeter Feiner 
2052266791SPeter Feiner 	/* @addr indicates a non-return address, as expected by the stack
2152266791SPeter Feiner 	 * pretty printer script. */
2252266791SPeter Feiner 	if (depth > 0 && !top_is_return_address) {
2352266791SPeter Feiner 		printf(" @%lx", (unsigned long) return_addrs[0]);
2452266791SPeter Feiner 		i++;
2552266791SPeter Feiner 	}
2652266791SPeter Feiner 
2752266791SPeter Feiner 	for (; i < depth; i++) {
2852266791SPeter Feiner 		printf(" %lx", (unsigned long) return_addrs[i]);
2952266791SPeter Feiner 	}
3052266791SPeter Feiner 	printf("\n");
3152266791SPeter Feiner }
3252266791SPeter Feiner 
3352266791SPeter Feiner void dump_stack(void)
3452266791SPeter Feiner {
3552266791SPeter Feiner 	const void *return_addrs[MAX_DEPTH];
3652266791SPeter Feiner 	int depth;
3752266791SPeter Feiner 
3852266791SPeter Feiner 	depth = backtrace(return_addrs, MAX_DEPTH);
3952266791SPeter Feiner 	print_stack(&return_addrs[1], depth ? depth - 1 : 0, true);
4052266791SPeter Feiner }
4152266791SPeter Feiner 
4252266791SPeter Feiner void dump_frame_stack(const void *instruction, const void *frame)
4352266791SPeter Feiner {
4452266791SPeter Feiner 	const void *return_addrs[MAX_DEPTH];
4552266791SPeter Feiner 	int depth;
4652266791SPeter Feiner 
4752266791SPeter Feiner 	return_addrs[0] = instruction;
4852266791SPeter Feiner 	depth = backtrace_frame(frame, &return_addrs[1], MAX_DEPTH - 1);
4952266791SPeter Feiner 	print_stack(return_addrs, depth + 1, false);
5052266791SPeter Feiner }
5152266791SPeter Feiner 
5252266791SPeter Feiner #ifndef HAVE_ARCH_BACKTRACE
5352266791SPeter Feiner int backtrace(const void **return_addrs, int max_depth)
5452266791SPeter Feiner {
5552266791SPeter Feiner 	static int walking;
5652266791SPeter Feiner 	int depth = 0;
5752266791SPeter Feiner 	void *addr;
5852266791SPeter Feiner 
5952266791SPeter Feiner 	if (walking) {
6052266791SPeter Feiner 		printf("RECURSIVE STACK WALK!!!\n");
6152266791SPeter Feiner 		return 0;
6252266791SPeter Feiner 	}
6352266791SPeter Feiner 	walking = 1;
6452266791SPeter Feiner 
6552266791SPeter Feiner 	/* __builtin_return_address requires a compile-time constant argument */
6652266791SPeter Feiner #define GET_RETURN_ADDRESS(i)						\
6752266791SPeter Feiner 	if (max_depth == i)						\
6852266791SPeter Feiner 		goto done;						\
6952266791SPeter Feiner 	addr = __builtin_return_address(i);				\
7052266791SPeter Feiner 	if (!addr)							\
7152266791SPeter Feiner 		goto done;						\
7252266791SPeter Feiner 	return_addrs[i] = __builtin_extract_return_addr(addr);		\
7352266791SPeter Feiner 	depth = i + 1;							\
7452266791SPeter Feiner 
7552266791SPeter Feiner 	GET_RETURN_ADDRESS(0)
7652266791SPeter Feiner 	GET_RETURN_ADDRESS(1)
7752266791SPeter Feiner 	GET_RETURN_ADDRESS(2)
7852266791SPeter Feiner 	GET_RETURN_ADDRESS(3)
7952266791SPeter Feiner 	GET_RETURN_ADDRESS(4)
8052266791SPeter Feiner 	GET_RETURN_ADDRESS(5)
8152266791SPeter Feiner 	GET_RETURN_ADDRESS(6)
8252266791SPeter Feiner 	GET_RETURN_ADDRESS(7)
8352266791SPeter Feiner 	GET_RETURN_ADDRESS(8)
8452266791SPeter Feiner 	GET_RETURN_ADDRESS(9)
8552266791SPeter Feiner 	GET_RETURN_ADDRESS(10)
8652266791SPeter Feiner 	GET_RETURN_ADDRESS(11)
8752266791SPeter Feiner 	GET_RETURN_ADDRESS(12)
8852266791SPeter Feiner 	GET_RETURN_ADDRESS(13)
8952266791SPeter Feiner 	GET_RETURN_ADDRESS(14)
9052266791SPeter Feiner 	GET_RETURN_ADDRESS(15)
9152266791SPeter Feiner 	GET_RETURN_ADDRESS(16)
9252266791SPeter Feiner 	GET_RETURN_ADDRESS(17)
9352266791SPeter Feiner 	GET_RETURN_ADDRESS(18)
9452266791SPeter Feiner 	GET_RETURN_ADDRESS(19)
9552266791SPeter Feiner 	GET_RETURN_ADDRESS(20)
9652266791SPeter Feiner 
9752266791SPeter Feiner #undef GET_RETURN_ADDRESS
9852266791SPeter Feiner 
9952266791SPeter Feiner done:
10052266791SPeter Feiner 	walking = 0;
10152266791SPeter Feiner 	return depth;
10252266791SPeter Feiner }
10352266791SPeter Feiner #endif  /* HAVE_ARCH_BACKTRACE */
104