aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/sh/include/asm/dwarf.h5
-rw-r--r--arch/sh/include/asm/ftrace.h50
-rw-r--r--arch/sh/kernel/Makefile1
-rw-r--r--arch/sh/kernel/return_address.c54
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 36extern 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
41static 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
12obj-y := debugtraps.o dumpstack.o idle.o io.o io_generic.o irq.o \ 12obj-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
16void *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
49void *return_address(unsigned int depth)
50{
51 return NULL;
52}
53
54#endif