summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/runtime.h10
-rw-r--r--runtime/stack-i386.c2
-rw-r--r--runtime/stack-x86_64.c2
-rw-r--r--runtime/stack.c22
-rw-r--r--runtime/sym.c24
-rw-r--r--tapset/ucontext-unwind.stp18
-rw-r--r--testsuite/systemtap.context/fib.c31
-rw-r--r--testsuite/systemtap.context/fib.exp37
-rw-r--r--testsuite/systemtap.context/fib.stp17
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--
+}