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 fc51e66f238..d985148af19 100644 --- a/arch/sh/include/asm/dwarf.h +++ b/arch/sh/include/asm/dwarf.h @@ -194,6 +194,11 @@ #define DWARF_ARCH_RA_REG 17 #ifndef __ASSEMBLY__ + +#include <linux/compiler.h> +#include <linux/bug.h> +#include <linux/list.h> + /* * Read either the frame pointer (r14) or the stack pointer (r15). * NOTE: this MUST be inlined. diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h index 5ea9030725c..28875a3e411 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) return addr; } - -#ifdef CONFIG_DWARF_UNWINDER -#include <asm/dwarf.h> +/* arch/sh/kernel/return_address.c */ +extern void *return_address(unsigned int); #define HAVE_ARCH_CALLER_ADDR -static inline unsigned long dwarf_return_address(int depth) -{ - struct dwarf_frame *frame; - unsigned long ra; - int i; - - for (i = 0, frame = NULL, ra = 0; i <= depth; i++) { - struct dwarf_frame *tmp; - - tmp = dwarf_unwind_stack(ra, frame); - - if (frame) - dwarf_free_frame(frame); - - frame = tmp; - - if (!frame || !frame->return_addr) - break; - - ra = frame->return_addr; - } - - /* Failed to unwind the stack to the specified depth. */ - WARN_ON(i != depth + 1); - - if (frame) - dwarf_free_frame(frame); - - return ra; -} - #define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0)) -#define CALLER_ADDR1 dwarf_return_address(1) -#define CALLER_ADDR2 dwarf_return_address(2) -#define CALLER_ADDR3 dwarf_return_address(3) -#define CALLER_ADDR4 dwarf_return_address(4) -#define CALLER_ADDR5 dwarf_return_address(5) -#define CALLER_ADDR6 dwarf_return_address(6) - -#endif /* CONFIG_DWARF_UNWINDER */ +#define CALLER_ADDR1 ((unsigned long)return_address(1)) +#define CALLER_ADDR2 ((unsigned long)return_address(2)) +#define CALLER_ADDR3 ((unsigned long)return_address(3)) +#define CALLER_ADDR4 ((unsigned long)return_address(4)) +#define CALLER_ADDR5 ((unsigned long)return_address(5)) +#define CALLER_ADDR6 ((unsigned long)return_address(6)) #endif /* __ASSEMBLY__ */ #endif /* CONFIG_FUNCTION_TRACER */ diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index a2d0a40f384..18a1e279b43 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile @@ -11,6 +11,7 @@ endif obj-y := debugtraps.o dumpstack.o idle.o io.o io_generic.o irq.o \ machvec.o nmi_debug.o process_$(BITS).o ptrace_$(BITS).o \ + return_address.o \ setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o \ syscalls_$(BITS).o time.o topology.o traps.o \ 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 00000000000..df3ab581107 --- /dev/null +++ b/arch/sh/kernel/return_address.c @@ -0,0 +1,54 @@ +/* + * arch/sh/kernel/return_address.c + * + * Copyright (C) 2009 Matt Fleming + * Copyright (C) 2009 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include <linux/kernel.h> +#include <asm/dwarf.h> + +#ifdef CONFIG_DWARF_UNWINDER + +void *return_address(unsigned int depth) +{ + struct dwarf_frame *frame; + unsigned long ra; + int i; + + for (i = 0, frame = NULL, ra = 0; i <= depth; i++) { + struct dwarf_frame *tmp; + + tmp = dwarf_unwind_stack(ra, frame); + + if (frame) + dwarf_free_frame(frame); + + frame = tmp; + + if (!frame || !frame->return_addr) + break; + + ra = frame->return_addr; + } + + /* Failed to unwind the stack to the specified depth. */ + WARN_ON(i != depth + 1); + + if (frame) + dwarf_free_frame(frame); + + return (void *)ra; +} + +#else + +void *return_address(unsigned int depth) +{ + return NULL; +} + +#endif |