diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/stack-i386.c | 7 | ||||
-rw-r--r-- | runtime/stack-x86_64.c | 7 | ||||
-rw-r--r-- | runtime/sym.h | 8 | ||||
-rw-r--r-- | runtime/transport/symbols.c | 8 |
4 files changed, 20 insertions, 10 deletions
diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c index 69623765..b447e495 100644 --- a/runtime/stack-i386.c +++ b/runtime/stack-i386.c @@ -67,14 +67,15 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels, if (ret == 0) { _stp_func_print(UNW_PC(&info), verbose, 1, tsk); levels--; - continue; + if (UNW_PC(&info) != _stp_kretprobe_trampoline) + continue; } /* If an error happened or we hit a kretprobe trampoline, * use fallback backtrace, unless user task backtrace. * FIXME: is there a way to unwind across kretprobe - * trampolines? */ + * trampolines? PR9999. */ if ((ret < 0 - || (ret > 0 && UNW_PC(&info) == _stp_kretprobe_trampoline)) + || UNW_PC(&info) == _stp_kretprobe_trampoline) && ! (tsk || arch_unw_user_mode(&info))) _stp_stack_print_fallback(UNW_SP(&info), verbose, levels); return; diff --git a/runtime/stack-x86_64.c b/runtime/stack-x86_64.c index 9afdf38a..914242e0 100644 --- a/runtime/stack-x86_64.c +++ b/runtime/stack-x86_64.c @@ -41,14 +41,15 @@ static void __stp_stack_print(struct pt_regs *regs, int verbose, int levels, if (ret == 0) { _stp_func_print(UNW_PC(&info), verbose, 1, tsk); levels--; - continue; + if (UNW_PC(&info) != _stp_kretprobe_trampoline) + continue; } /* If an error happened or we hit a kretprobe trampoline, * use fallback backtrace, unless user task backtrace. * FIXME: is there a way to unwind across kretprobe - * trampolines? */ + * trampolines? PR9999. */ if ((ret < 0 - || (ret > 0 && UNW_PC(&info) == _stp_kretprobe_trampoline)) + || UNW_PC(&info) == _stp_kretprobe_trampoline) && ! (tsk || arch_unw_user_mode(&info))) _stp_stack_print_fallback(UNW_SP(&info), verbose, levels); return; diff --git a/runtime/sym.h b/runtime/sym.h index 7e28ebe6..ca69345f 100644 --- a/runtime/sym.h +++ b/runtime/sym.h @@ -61,10 +61,10 @@ struct _stp_module { static struct _stp_module *_stp_modules []; static unsigned _stp_num_modules; - -/* the number of modules in the arrays */ - -static unsigned long _stp_kretprobe_trampoline = 0; +/* Used in the unwinder to special case unwinding through kretprobes. */ +/* Initialized through translator (stap-symbols.h) relative to kernel */ +/* load address, fixup by transport symbols _stp_do_relocation */ +static unsigned long _stp_kretprobe_trampoline; static unsigned long _stp_module_relocate (const char *module, const char *section, unsigned long offset); static struct _stp_module *_stp_get_unwind_info (unsigned long addr); diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c index a329effe..3e6a2fb1 100644 --- a/runtime/transport/symbols.c +++ b/runtime/transport/symbols.c @@ -30,6 +30,14 @@ static void _stp_do_relocation(const char __user *buf, size_t count) dbug_sym(2, "relocate (%s %s 0x%lx)\n", msg.module, msg.reloc, (unsigned long) msg.address); + /* Detect actual kernel load address. */ + if (!strcmp ("kernel", msg.module) + && !strcmp ("_stext", msg.reloc)) { + dbug_sym(2, "found kernel _stext load address: 0x%lx\n", + (unsigned long) msg.address); + if (_stp_kretprobe_trampoline != (unsigned long) -1) + _stp_kretprobe_trampoline += (unsigned long) msg.address; + } /* Save the relocation value. XXX: While keeping the data here is fine for the kernel address space ("kernel" and "*.ko" modules), |