diff options
-rw-r--r-- | runtime/runtime.h | 10 | ||||
-rw-r--r-- | runtime/stack-i386.c | 2 | ||||
-rw-r--r-- | runtime/stack-x86_64.c | 2 | ||||
-rw-r--r-- | runtime/stack.c | 22 | ||||
-rw-r--r-- | runtime/sym.c | 24 | ||||
-rw-r--r-- | tapset/ucontext-unwind.stp | 18 | ||||
-rw-r--r-- | testsuite/systemtap.context/fib.c | 31 | ||||
-rw-r--r-- | testsuite/systemtap.context/fib.exp | 37 | ||||
-rw-r--r-- | testsuite/systemtap.context/fib.stp | 17 |
9 files changed, 149 insertions, 14 deletions
diff --git a/runtime/runtime.h b/runtime/runtime.h index a7ee962c..0fd2a380 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -126,6 +126,16 @@ static struct #endif #endif +#ifndef SYM_VERBOSE_NO +#define SYM_VERBOSE_NO 0 +#endif +#ifndef SYM_VERBOSE_FULL +#define SYM_VERBOSE_FULL 1 +#endif +#ifndef SYM_VERBOSE_BRIEF +#define SYM_VERBOSE_BRIEF 2 +#endif + #include "alloc.c" #include "print.c" #include "string.c" diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c index fef11871..4bd3cc53 100644 --- a/runtime/stack-i386.c +++ b/runtime/stack-i386.c @@ -63,6 +63,7 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels, while (levels && (tsk || !arch_unw_user_mode(&info))) { int ret = unwind(&info, tsk); +#if UPROBES_API_VERSION > 1 unsigned long maybe_pc = 0; if (ri) { maybe_pc = uprobe_get_pc(ri, UNW_PC(&info), @@ -72,6 +73,7 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels, else UNW_PC(&info) = maybe_pc; } +#endif dbug_unwind(1, "ret=%d PC=%lx SP=%lx\n", ret, UNW_PC(&info), UNW_SP(&info)); if (ret == 0) { _stp_func_print(UNW_PC(&info), verbose, 1, tsk); diff --git a/runtime/stack-x86_64.c b/runtime/stack-x86_64.c index 3fc203f7..80ebd3e7 100644 --- a/runtime/stack-x86_64.c +++ b/runtime/stack-x86_64.c @@ -38,6 +38,7 @@ static void __stp_stack_print(struct pt_regs *regs, int verbose, int levels, while (levels && (tsk || !arch_unw_user_mode(&info))) { int ret = unwind(&info, tsk); +#if UPROBES_API_VERSION > 1 unsigned long maybe_pc = 0; if (ri) { maybe_pc = uprobe_get_pc(ri, UNW_PC(&info), @@ -47,6 +48,7 @@ static void __stp_stack_print(struct pt_regs *regs, int verbose, int levels, else UNW_PC(&info) = maybe_pc; } +#endif dbug_unwind(1, "ret=%d PC=%lx SP=%lx\n", ret, UNW_PC(&info), UNW_SP(&info)); if (ret == 0) { _stp_func_print(UNW_PC(&info), verbose, 1, tsk); diff --git a/runtime/stack.c b/runtime/stack.c index 27abee7e..3d907a7f 100644 --- a/runtime/stack.c +++ b/runtime/stack.c @@ -112,15 +112,20 @@ static void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe if (verbose) { /* print the current address */ if (pi) { - _stp_print("Returning from: "); - _stp_symbol_print((unsigned long)_stp_probe_addr_r(pi)); - _stp_print("\nReturning to : "); + if (verbose == SYM_VERBOSE_FULL) { + _stp_print("Returning from: "); + _stp_symbol_print((unsigned long)_stp_probe_addr_r(pi)); + _stp_print("\nReturning to : "); + } _stp_symbol_print((unsigned long)_stp_ret_addr_r(pi)); } else if (ri) { - _stp_print("Returning from: "); - _stp_usymbol_print(ri->rp->u.vaddr, tsk); - _stp_print("\nReturning to : "); - _stp_usymbol_print(ri->ret_addr, tsk); + if (verbose == SYM_VERBOSE_FULL) { + _stp_print("Returning from: "); + _stp_usymbol_print(ri->rp->u.vaddr, tsk); + _stp_print("\nReturning to : "); + _stp_usymbol_print(ri->ret_addr, tsk); + } else + _stp_func_print(ri->ret_addr, verbose, 0, tsk); } else { _stp_print_char(' '); if (tsk) @@ -128,7 +133,8 @@ static void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe else _stp_symbol_print(REG_IP(regs)); } - _stp_print_char('\n'); + if (verbose != SYM_VERBOSE_BRIEF) + _stp_print_char('\n'); } else if (pi) _stp_printf("%p %p ", (int64_t)(long)_stp_ret_addr_r(pi), (int64_t) REG_IP(regs)); else diff --git a/runtime/sym.c b/runtime/sym.c index 953161bc..cd0c8a71 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -374,19 +374,31 @@ static int _stp_func_print(unsigned long address, int verbose, int exact, else exstr = " (inexact)"; - name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, task); + name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, + task); if (name) { - if (verbose) { + switch (verbose) { + case SYM_VERBOSE_FULL: if (modname && *modname) _stp_printf(" %p : %s+%#lx/%#lx [%s]%s\n", - (int64_t) address, name, offset, size, modname, exstr); + (int64_t) address, name, offset, + size, modname, exstr); else - _stp_printf(" %p : %s+%#lx/%#lx%s\n", (int64_t) address, name, offset, size, exstr); - } else + _stp_printf(" %p : %s+%#lx/%#lx%s\n", + (int64_t) address, name, offset, size, + exstr); + break; + case SYM_VERBOSE_BRIEF: + _stp_printf("%s+%#lx\n", name, offset); + break; + case SYM_VERBOSE_NO: + default: _stp_printf("%p ", (int64_t) address); + } return 1; - } + } else if (verbose == SYM_VERBOSE_BRIEF) + _stp_printf("%p\n", (int64_t) address); return 0; } diff --git a/tapset/ucontext-unwind.stp b/tapset/ucontext-unwind.stp index e0d883b8..399ce0c5 100644 --- a/tapset/ucontext-unwind.stp +++ b/tapset/ucontext-unwind.stp @@ -35,6 +35,24 @@ function print_ubacktrace () %{ /* unprivileged */ %} /** + * sfunction print_ubacktrace_brief- Print stack back trace for current task. EXPERIMENTAL! + * + * Equivalent to print_ubacktrace(), but output for each symbol is + * shorter (just name and offset), and the function address is + * printed if it can't be mapped to a name. + */ + +function print_ubacktrace_brief () %{ /* unprivileged */ + assert_is_myproc(); + if (CONTEXT->regs) { + _stp_stack_print(CONTEXT->regs, SYM_VERBOSE_BRIEF, CONTEXT->pi, + MAXTRACE, current, CONTEXT->ri); + } else { + _stp_printf("Systemtap probe: %s\n", CONTEXT->probe_point); + } +%} + +/** * sfunction ubacktrace - Hex backtrace of current task stack. EXPERIMENTAL! * * Return a string of hex addresses that are a backtrace of the diff --git a/testsuite/systemtap.context/fib.c b/testsuite/systemtap.context/fib.c new file mode 100644 index 00000000..61fee0a7 --- /dev/null +++ b/testsuite/systemtap.context/fib.c @@ -0,0 +1,31 @@ +#include <stdlib.h> +#include <stdio.h> + +long fib(int x) +{ + if (x == 0 || x == 1) + return 1; + else + return fib(x - 1) + fib(x - 2); +} + +int main(int argc, char **argv) +{ + int x = 0; + long result = 0; + + if (argc != 2) + { + printf("0\n"); + return 1; + } + x = atoi(argv[1]); + if (x < 0) + { + printf("0\n"); + return 1; + } + result = fib(x); + printf("%ld\n", result); + return 0; +} diff --git a/testsuite/systemtap.context/fib.exp b/testsuite/systemtap.context/fib.exp new file mode 100644 index 00000000..cc4d75a1 --- /dev/null +++ b/testsuite/systemtap.context/fib.exp @@ -0,0 +1,37 @@ +# Tests backtrace in the classic Fibonacci program + + +set test "fib" + +# Only run on make installcheck and utrace present. +if {! [installtest_p]} { untested "$test"; return } +if {! [utrace_p]} { untested "$test"; return } + +set testpath "$srcdir/$subdir" +set testsrc "$testpath/fib.c" +set testexe "[pwd]/$test" + +# We want debug info and no optimization (is that totally necessary?) +set testflags "additional_flags=-g additional_flags=-O0" +set teststp "$testpath/$test.stp" + +set res [target_compile $testsrc $testexe executable $testflags] +if { $res != "" } { + verbose "target_compile failed: $res" 2 + fail "unable to compile $testsrc" + return +} + +spawn stap -c "$testexe 10" $teststp +set fibcalls 0 +set maincalls 0 +expect { + -timeout 120 + -re {^fib[^\r\n]*[\r\n]} { incr fibcalls; exp_continue } + -re {^main[^\r\n]*[\r\n]} { incr maincalls; exp_continue } + -re {^[^\r\n]*[\r\n]} {exp_continue} + timeout { fail "$test (timeout)" } + eof { } +} +wait +if {$fibcalls == 18 && $maincalls == 2} { pass "$test ($fibcalls $maincalls)" } { fail "$test ($fibcalls $maincalls)" } diff --git a/testsuite/systemtap.context/fib.stp b/testsuite/systemtap.context/fib.stp new file mode 100644 index 00000000..85c2fc1d --- /dev/null +++ b/testsuite/systemtap.context/fib.stp @@ -0,0 +1,17 @@ +global depth = 0 +global max_depth = 0 + +probe process("fib").function("fib").call { + depth++ + if (depth > max_depth) { + max_depth = depth + } +} + +probe process("fib").function("fib").return { + if (depth == max_depth) { + print_ubacktrace_brief() + printf("\n") + } + depth-- +} |