1 /*
2  * arch/sh/kernel/return_address.c
3  *
4  * Copyright (C) 2009  Matt Fleming
5  * Copyright (C) 2009  Paul Mundt
6  *
7  * This file is subject to the terms and conditions of the GNU General Public
8  * License.  See the file "COPYING" in the main directory of this archive
9  * for more details.
10  */
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <asm/dwarf.h>
14 
15 #ifdef CONFIG_DWARF_UNWINDER
16 
return_address(unsigned int depth)17 void *return_address(unsigned int depth)
18 {
19 	struct dwarf_frame *frame;
20 	unsigned long ra;
21 	int i;
22 
23 	for (i = 0, frame = NULL, ra = 0; i <= depth; i++) {
24 		struct dwarf_frame *tmp;
25 
26 		tmp = dwarf_unwind_stack(ra, frame);
27 		if (!tmp)
28 			return NULL;
29 
30 		if (frame)
31 			dwarf_free_frame(frame);
32 
33 		frame = tmp;
34 
35 		if (!frame || !frame->return_addr)
36 			break;
37 
38 		ra = frame->return_addr;
39 	}
40 
41 	/* Failed to unwind the stack to the specified depth. */
42 	WARN_ON(i != depth + 1);
43 
44 	if (frame)
45 		dwarf_free_frame(frame);
46 
47 	return (void *)ra;
48 }
49 
50 #else
51 
return_address(unsigned int depth)52 void *return_address(unsigned int depth)
53 {
54 	return NULL;
55 }
56 
57 #endif
58 
59 EXPORT_SYMBOL_GPL(return_address);
60