diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2016-05-02 14:38:29 +0200 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2016-05-04 16:29:45 +0200 |
commit | 5606330627ab680f5e6b7549d14ec3ffdae58c15 (patch) | |
tree | 5766fa5aa8375263757f24819219175ccf8cfaa5 /arch | |
parent | e18eb2d1eb03fa06ccb7823a44d7ceea621e2bbb (diff) | |
download | op-kernel-dev-5606330627ab680f5e6b7549d14ec3ffdae58c15.zip op-kernel-dev-5606330627ab680f5e6b7549d14ec3ffdae58c15.tar.gz |
s390/dumpstack: implement and use return_address()
Implement return_address() and use it instead of __builtin_return_address(n).
__builtin_return_address(n) is not guaranteed to work for n > 0,
therefore implement a private return_address() function which walks
the stack frames and returns the proper return address.
This way we get also rid of a compile warning which gcc 6.1 emits and
look like all other architectures.
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/s390/include/asm/ftrace.h | 4 | ||||
-rw-r--r-- | arch/s390/kernel/dumpstack.c | 24 |
2 files changed, 27 insertions, 1 deletions
diff --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h index 836c562..64053d9 100644 --- a/arch/s390/include/asm/ftrace.h +++ b/arch/s390/include/asm/ftrace.h @@ -12,7 +12,9 @@ #ifndef __ASSEMBLY__ -#define ftrace_return_address(n) __builtin_return_address(n) +unsigned long return_address(int depth); + +#define ftrace_return_address(n) return_address(n) void _mcount(void); void ftrace_caller(void); diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c index 1b6081c..69f9908 100644 --- a/arch/s390/kernel/dumpstack.c +++ b/arch/s390/kernel/dumpstack.c @@ -89,6 +89,30 @@ void dump_trace(dump_trace_func_t func, void *data, struct task_struct *task, } EXPORT_SYMBOL_GPL(dump_trace); +struct return_address_data { + unsigned long address; + int depth; +}; + +static int __return_address(void *data, unsigned long address) +{ + struct return_address_data *rd = data; + + if (rd->depth--) + return 0; + rd->address = address; + return 1; +} + +unsigned long return_address(int depth) +{ + struct return_address_data rd = { .depth = depth + 2 }; + + dump_trace(__return_address, &rd, NULL, current_stack_pointer()); + return rd.address; +} +EXPORT_SYMBOL_GPL(return_address); + static int show_address(void *data, unsigned long address) { printk("([<%016lx>] %pSR)\n", address, (void *)address); |