diff options
-rw-r--r-- | arch/sh/include/asm/dwarf.h | 5 | ||||
-rw-r--r-- | arch/sh/include/asm/ftrace.h | 50 | ||||
-rw-r--r-- | arch/sh/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/sh/kernel/return_address.c | 54 |
4 files changed, 68 insertions, 42 deletions
diff --git a/arch/sh/include/asm/dwarf.h b/arch/sh/include/asm/dwarf.h index fc51e66f2380..d985148af19f 100644 --- a/arch/sh/include/asm/dwarf.h +++ b/arch/sh/include/asm/dwarf.h | |||
@@ -194,6 +194,11 @@ | |||
194 | #define DWARF_ARCH_RA_REG 17 | 194 | #define DWARF_ARCH_RA_REG 17 |
195 | 195 | ||
196 | #ifndef __ASSEMBLY__ | 196 | #ifndef __ASSEMBLY__ |
197 | |||
198 | #include <linux/compiler.h> | ||
199 | #include <linux/bug.h> | ||
200 | #include <linux/list.h> | ||
201 | |||
197 | /* | 202 | /* |
198 | * Read either the frame pointer (r14) or the stack pointer (r15). | 203 | * Read either the frame pointer (r14) or the stack pointer (r15). |
199 | * NOTE: this MUST be inlined. | 204 | * NOTE: this MUST be inlined. |
diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h index 5ea9030725c0..28875a3e4116 100644 --- a/arch/sh/include/asm/ftrace.h +++ b/arch/sh/include/asm/ftrace.h | |||
@@ -32,52 +32,18 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr) | |||
32 | return addr; | 32 | return addr; |
33 | } | 33 | } |
34 | 34 | ||
35 | 35 | /* arch/sh/kernel/return_address.c */ | |
36 | #ifdef CONFIG_DWARF_UNWINDER | 36 | extern void *return_address(unsigned int); |
37 | #include <asm/dwarf.h> | ||
38 | 37 | ||
39 | #define HAVE_ARCH_CALLER_ADDR | 38 | #define HAVE_ARCH_CALLER_ADDR |
40 | 39 | ||
41 | static inline unsigned long dwarf_return_address(int depth) | ||
42 | { | ||
43 | struct dwarf_frame *frame; | ||
44 | unsigned long ra; | ||
45 | int i; | ||
46 | |||
47 | for (i = 0, frame = NULL, ra = 0; i <= depth; i++) { | ||
48 | struct dwarf_frame *tmp; | ||
49 | |||
50 | tmp = dwarf_unwind_stack(ra, frame); | ||
51 | |||
52 | if (frame) | ||
53 | dwarf_free_frame(frame); | ||
54 | |||
55 | frame = tmp; | ||
56 | |||
57 | if (!frame || !frame->return_addr) | ||
58 | break; | ||
59 | |||
60 | ra = frame->return_addr; | ||
61 | } | ||
62 | |||
63 | /* Failed to unwind the stack to the specified depth. */ | ||
64 | WARN_ON(i != depth + 1); | ||
65 | |||
66 | if (frame) | ||
67 | dwarf_free_frame(frame); | ||
68 | |||
69 | return ra; | ||
70 | } | ||
71 | |||
72 | #define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0)) | 40 | #define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0)) |
73 | #define CALLER_ADDR1 dwarf_return_address(1) | 41 | #define CALLER_ADDR1 ((unsigned long)return_address(1)) |
74 | #define CALLER_ADDR2 dwarf_return_address(2) | 42 | #define CALLER_ADDR2 ((unsigned long)return_address(2)) |
75 | #define CALLER_ADDR3 dwarf_return_address(3) | 43 | #define CALLER_ADDR3 ((unsigned long)return_address(3)) |
76 | #define CALLER_ADDR4 dwarf_return_address(4) | 44 | #define CALLER_ADDR4 ((unsigned long)return_address(4)) |
77 | #define CALLER_ADDR5 dwarf_return_address(5) | 45 | #define CALLER_ADDR5 ((unsigned long)return_address(5)) |
78 | #define CALLER_ADDR6 dwarf_return_address(6) | 46 | #define CALLER_ADDR6 ((unsigned long)return_address(6)) |
79 | |||
80 | #endif /* CONFIG_DWARF_UNWINDER */ | ||
81 | 47 | ||
82 | #endif /* __ASSEMBLY__ */ | 48 | #endif /* __ASSEMBLY__ */ |
83 | #endif /* CONFIG_FUNCTION_TRACER */ | 49 | #endif /* CONFIG_FUNCTION_TRACER */ |
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index a2d0a40f3848..18a1e279b430 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile | |||
@@ -11,6 +11,7 @@ endif | |||
11 | 11 | ||
12 | obj-y := debugtraps.o dumpstack.o idle.o io.o io_generic.o irq.o \ | 12 | obj-y := debugtraps.o dumpstack.o idle.o io.o io_generic.o irq.o \ |
13 | machvec.o nmi_debug.o process_$(BITS).o ptrace_$(BITS).o \ | 13 | machvec.o nmi_debug.o process_$(BITS).o ptrace_$(BITS).o \ |
14 | return_address.o \ | ||
14 | setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o \ | 15 | setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o \ |
15 | syscalls_$(BITS).o time.o topology.o traps.o \ | 16 | syscalls_$(BITS).o time.o topology.o traps.o \ |
16 | traps_$(BITS).o unwinder.o | 17 | traps_$(BITS).o unwinder.o |
diff --git a/arch/sh/kernel/return_address.c b/arch/sh/kernel/return_address.c new file mode 100644 index 000000000000..df3ab5811074 --- /dev/null +++ b/arch/sh/kernel/return_address.c | |||
@@ -0,0 +1,54 @@ | |||
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 <asm/dwarf.h> | ||
13 | |||
14 | #ifdef CONFIG_DWARF_UNWINDER | ||
15 | |||
16 | void *return_address(unsigned int depth) | ||
17 | { | ||
18 | struct dwarf_frame *frame; | ||
19 | unsigned long ra; | ||
20 | int i; | ||
21 | |||
22 | for (i = 0, frame = NULL, ra = 0; i <= depth; i++) { | ||
23 | struct dwarf_frame *tmp; | ||
24 | |||
25 | tmp = dwarf_unwind_stack(ra, frame); | ||
26 | |||
27 | if (frame) | ||
28 | dwarf_free_frame(frame); | ||
29 | |||
30 | frame = tmp; | ||
31 | |||
32 | if (!frame || !frame->return_addr) | ||
33 | break; | ||
34 | |||
35 | ra = frame->return_addr; | ||
36 | } | ||
37 | |||
38 | /* Failed to unwind the stack to the specified depth. */ | ||
39 | WARN_ON(i != depth + 1); | ||
40 | |||
41 | if (frame) | ||
42 | dwarf_free_frame(frame); | ||
43 | |||
44 | return (void *)ra; | ||
45 | } | ||
46 | |||
47 | #else | ||
48 | |||
49 | void *return_address(unsigned int depth) | ||
50 | { | ||
51 | return NULL; | ||
52 | } | ||
53 | |||
54 | #endif | ||