xref: /kvm-unit-tests/lib/riscv/stack.c (revision a1f2b0e1efd55056f56d1f77f13eea6646ad72e2)
16fba6b84SAndrew Jones // SPDX-License-Identifier: GPL-2.0-only
26fba6b84SAndrew Jones #include <libcflat.h>
36fba6b84SAndrew Jones #include <stack.h>
46fba6b84SAndrew Jones 
5*a1f2b0e1SAndrew Jones #ifdef CONFIG_RELOC
6*a1f2b0e1SAndrew Jones extern char ImageBase, _text, _etext;
7*a1f2b0e1SAndrew Jones 
8*a1f2b0e1SAndrew Jones bool arch_base_address(const void *rebased_addr, unsigned long *addr)
9*a1f2b0e1SAndrew Jones {
10*a1f2b0e1SAndrew Jones 	unsigned long ra = (unsigned long)rebased_addr;
11*a1f2b0e1SAndrew Jones 	unsigned long base = (unsigned long)&ImageBase;
12*a1f2b0e1SAndrew Jones 	unsigned long start = (unsigned long)&_text;
13*a1f2b0e1SAndrew Jones 	unsigned long end = (unsigned long)&_etext;
14*a1f2b0e1SAndrew Jones 
15*a1f2b0e1SAndrew Jones 	if (ra < start || ra >= end)
16*a1f2b0e1SAndrew Jones 		return false;
17*a1f2b0e1SAndrew Jones 
18*a1f2b0e1SAndrew Jones 	*addr = ra - base;
19*a1f2b0e1SAndrew Jones 	return true;
20*a1f2b0e1SAndrew Jones }
21*a1f2b0e1SAndrew Jones #endif
22*a1f2b0e1SAndrew Jones 
23a8a78d75SAndrew Jones int arch_backtrace_frame(const void *frame, const void **return_addrs,
24a8a78d75SAndrew Jones 			 int max_depth, bool current_frame)
256fba6b84SAndrew Jones {
266fba6b84SAndrew Jones 	static bool walking;
276fba6b84SAndrew Jones 	const unsigned long *fp = (unsigned long *)frame;
286fba6b84SAndrew Jones 	int depth;
296fba6b84SAndrew Jones 
30a8a78d75SAndrew Jones 	if (current_frame)
31a8a78d75SAndrew Jones 		fp = __builtin_frame_address(0);
32a8a78d75SAndrew Jones 
336fba6b84SAndrew Jones 	if (walking) {
346fba6b84SAndrew Jones 		printf("RECURSIVE STACK WALK!!!\n");
356fba6b84SAndrew Jones 		return 0;
366fba6b84SAndrew Jones 	}
376fba6b84SAndrew Jones 	walking = true;
386fba6b84SAndrew Jones 
396fba6b84SAndrew Jones 	for (depth = 0; fp && depth < max_depth; ++depth) {
406fba6b84SAndrew Jones 		return_addrs[depth] = (void *)fp[-1];
416fba6b84SAndrew Jones 		if (return_addrs[depth] == 0)
426fba6b84SAndrew Jones 			break;
436fba6b84SAndrew Jones 		fp = (unsigned long *)fp[-2];
446fba6b84SAndrew Jones 	}
456fba6b84SAndrew Jones 
466fba6b84SAndrew Jones 	walking = false;
476fba6b84SAndrew Jones 	return depth;
486fba6b84SAndrew Jones }
49