diff options
-rw-r--r-- | runtime/stack-arm.c | 3 | ||||
-rw-r--r-- | runtime/stack-i386.c | 25 | ||||
-rw-r--r-- | runtime/stack-ia64.c | 3 | ||||
-rw-r--r-- | runtime/stack-ppc64.c | 3 | ||||
-rw-r--r-- | runtime/stack-s390.c | 3 | ||||
-rw-r--r-- | runtime/stack-x86_64.c | 23 | ||||
-rw-r--r-- | runtime/stack.c | 34 | ||||
-rw-r--r-- | runtime/sym.c | 31 | ||||
-rw-r--r-- | runtime/unwind.c | 22 | ||||
-rw-r--r-- | tapset/context-symbols.stp | 4 | ||||
-rw-r--r-- | tapset/context-unwind.stp | 4 | ||||
-rw-r--r-- | tapset/ucontext-symbols.stp | 27 | ||||
-rw-r--r-- | tapset/ucontext-unwind.stp | 52 | ||||
-rwxr-xr-x | testsuite/buildok/ustack.stp | 10 | ||||
-rw-r--r-- | testsuite/systemtap.base/uprobes_ustack.exp | 94 | ||||
-rw-r--r-- | testsuite/systemtap.base/uprobes_ustack.stp | 35 | ||||
-rw-r--r-- | testsuite/systemtap.context/backtrace.tcl | 1 |
17 files changed, 311 insertions, 63 deletions
diff --git a/runtime/stack-arm.c b/runtime/stack-arm.c index 9b0b772d..fcff0a3b 100644 --- a/runtime/stack-arm.c +++ b/runtime/stack-arm.c @@ -31,7 +31,8 @@ static int __init find_str_pc_offset(void) } -static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels) +static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels, + struct task_struct *tsk) { #ifdef STP_USE_FRAME_POINTER int pc_offset = find_str_pc_offset(); diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c index 5a18c9d8..69623765 100644 --- a/runtime/stack-i386.c +++ b/runtime/stack-i386.c @@ -23,14 +23,15 @@ static void _stp_stack_print_fallback(unsigned long stack, int verbose, int leve /* cannot access stack. give up. */ return; } - if (_stp_func_print(addr, verbose, 0)) + if (_stp_func_print(addr, verbose, 0, NULL)) levels--; stack++; } } #endif -static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels) +static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels, + struct task_struct *tsk) { unsigned long context = (unsigned long)®_SP(regs) & ~(THREAD_SIZE - 1); @@ -43,7 +44,7 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels) /* cannot access stack. give up. */ return; } - _stp_func_print(addr, verbose, 1); + _stp_func_print(addr, verbose, 1, NULL); if (unlikely(_stp_read_address(next_fp, (unsigned long *)fp, KERNEL_DS))) { /* cannot access stack. give up. */ return; @@ -60,19 +61,23 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels) struct unwind_frame_info info; arch_unw_init_frame_info(&info, regs); - while (levels && !arch_unw_user_mode(&info)) { - int ret = unwind(&info); + while (levels && (tsk || !arch_unw_user_mode(&info))) { + int ret = unwind(&info, tsk); 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); + _stp_func_print(UNW_PC(&info), verbose, 1, tsk); levels--; continue; } - /* If an error happened or we hit a kretprobe trampoline, use fallback backtrace */ - /* FIXME: is there a way to unwind across kretprobe trampolines? */ - if (ret < 0 || (ret > 0 && UNW_PC(&info) == _stp_kretprobe_trampoline)) + /* 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? */ + if ((ret < 0 + || (ret > 0 && UNW_PC(&info) == _stp_kretprobe_trampoline)) + && ! (tsk || arch_unw_user_mode(&info))) _stp_stack_print_fallback(UNW_SP(&info), verbose, levels); - break; + return; } #else /* ! STP_USE_DWARF_UNWINDER */ _stp_stack_print_fallback((unsigned long)®_SP(regs), verbose, levels); diff --git a/runtime/stack-ia64.c b/runtime/stack-ia64.c index ca9d25a6..a04355fa 100644 --- a/runtime/stack-ia64.c +++ b/runtime/stack-ia64.c @@ -48,7 +48,8 @@ static void __stp_show_stack_addr(struct unw_frame_info *info, void *arg) } while (unw_unwind(info) >= 0); } -static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels) +static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels, + struct task_struct *tsk) { unsigned long *stack = (unsigned long *)®_SP(regs); struct dump_para para; diff --git a/runtime/stack-ppc64.c b/runtime/stack-ppc64.c index 3dc38526..3267194e 100644 --- a/runtime/stack-ppc64.c +++ b/runtime/stack-ppc64.c @@ -7,7 +7,8 @@ * later version. */ -static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels) +static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels, + struct task_struct *tsk) { unsigned long ip, newsp, lr = 0; int count = 0; diff --git a/runtime/stack-s390.c b/runtime/stack-s390.c index c9654102..14e9b7d8 100644 --- a/runtime/stack-s390.c +++ b/runtime/stack-s390.c @@ -66,7 +66,8 @@ __stp_show_stack (unsigned long sp, unsigned long low, } static void __stp_stack_print (struct pt_regs *regs, - int verbose, int levels) + int verbose, int levels, + struct task_struct *tsk) { unsigned long *_sp = (unsigned long *)®_SP(regs); unsigned long sp = (unsigned long)_sp; diff --git a/runtime/stack-x86_64.c b/runtime/stack-x86_64.c index 03d88ef0..9afdf38a 100644 --- a/runtime/stack-x86_64.c +++ b/runtime/stack-x86_64.c @@ -19,7 +19,7 @@ static void _stp_stack_print_fallback(unsigned long stack, int verbose, int leve /* cannot access stack. give up. */ return; } - if (_stp_func_print(addr, verbose, 0)) + if (_stp_func_print(addr, verbose, 0, NULL)) levels--; stack++; } @@ -27,26 +27,31 @@ static void _stp_stack_print_fallback(unsigned long stack, int verbose, int leve #endif -static void __stp_stack_print(struct pt_regs *regs, int verbose, int levels) +static void __stp_stack_print(struct pt_regs *regs, int verbose, int levels, + struct task_struct *tsk) { #ifdef STP_USE_DWARF_UNWINDER // FIXME: large stack allocation struct unwind_frame_info info; arch_unw_init_frame_info(&info, regs); - while (levels && !arch_unw_user_mode(&info)) { - int ret = unwind(&info); + while (levels && (tsk || !arch_unw_user_mode(&info))) { + int ret = unwind(&info, tsk); 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); + _stp_func_print(UNW_PC(&info), verbose, 1, tsk); levels--; continue; } - /* If an error happened or we hit a kretprobe trampoline, use fallback backtrace */ - /* FIXME: is there a way to unwind across kretprobe trampolines? */ - if (ret < 0 || (ret > 0 && UNW_PC(&info) == _stp_kretprobe_trampoline)) + /* 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? */ + if ((ret < 0 + || (ret > 0 && UNW_PC(&info) == _stp_kretprobe_trampoline)) + && ! (tsk || arch_unw_user_mode(&info))) _stp_stack_print_fallback(UNW_SP(&info), verbose, levels); - break; + return; } #else /* ! STP_USE_DWARF_UNWINDER */ _stp_stack_print_fallback(REG_SP(regs), verbose, levels); diff --git a/runtime/stack.c b/runtime/stack.c index 68fb9b1f..042f44c7 100644 --- a/runtime/stack.c +++ b/runtime/stack.c @@ -1,6 +1,6 @@ /* -*- linux-c -*- * Stack tracing functions - * Copyright (C) 2005-2008 Red Hat Inc. + * Copyright (C) 2005-2009 Red Hat Inc. * Copyright (C) 2005 Intel Corporation. * * This file is part of systemtap, and is free software. You can @@ -77,7 +77,7 @@ static void print_stack_address(void *data, unsigned long addr, int reliable) { struct print_stack_data *sdata = data; if (sdata->level++ < sdata->max_level) - _stp_func_print(addr,sdata->verbose, 0); + _stp_func_print(addr, sdata->verbose, 0, NULL); } static const struct stacktrace_ops print_stack_ops = { @@ -107,7 +107,7 @@ static void _stp_stack_print_fallback(unsigned long stack, int verbose, int leve * @param regs A pointer to the struct pt_regs. */ -static void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe_instance *pi, int levels) +static void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe_instance *pi, int levels, struct task_struct *tsk) { if (verbose) { /* print the current address */ @@ -118,7 +118,10 @@ static void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe _stp_symbol_print((unsigned long)_stp_ret_addr_r(pi)); } else { _stp_print_char(' '); - _stp_symbol_print(REG_IP(regs)); + if (tsk) + _stp_usymbol_print(REG_IP(regs), tsk); + else + _stp_symbol_print(REG_IP(regs)); } _stp_print_char('\n'); } else if (pi) @@ -126,7 +129,7 @@ static void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe else _stp_printf("%p ", (int64_t) REG_IP(regs)); - __stp_stack_print(regs, verbose, levels); + __stp_stack_print(regs, verbose, levels, tsk); } /** Writes stack backtrace to a string @@ -135,37 +138,20 @@ static void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe * @param regs A pointer to the struct pt_regs. * @returns void */ -static void _stp_stack_snprint(char *str, int size, struct pt_regs *regs, int verbose, struct kretprobe_instance *pi, int levels) +static void _stp_stack_snprint(char *str, int size, struct pt_regs *regs, int verbose, struct kretprobe_instance *pi, int levels, struct task_struct *tsk) { /* To get a string, we use a simple trick. First flush the print buffer, */ /* then call _stp_stack_print, then copy the result into the output string */ /* and clear the print buffer. */ _stp_pbuf *pb = per_cpu_ptr(Stp_pbuf, smp_processor_id()); _stp_print_flush(); - _stp_stack_print(regs, verbose, pi, levels); + _stp_stack_print(regs, verbose, pi, levels, tsk); strlcpy(str, pb->buf, size < (int)pb->len ? size : (int)pb->len); pb->len = 0; } #endif /* CONFIG_KPROBES */ -/** Prints the user stack backtrace - * @param str string - * @returns Same string as was input with trace info appended, - * @note Currently limited to a depth of two. Works from jprobes and kprobes. - */ -#if 0 -static void _stp_ustack_print(char *str) -{ - struct pt_regs *nregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)current->thread_info)) - 1; - _stp_printf("%p : [user]\n", (int64_t) REG_IP(nregs)); - if (REG_SP(nregs)) - _stp_printf("%p : [user]\n", (int64_t) (*(unsigned long *)REG_SP(nregs))); -} -#endif /* 0 */ - -/** @} */ - void _stp_stack_print_tsk(struct task_struct *tsk, int verbose, int levels) { #if defined(STAPCONF_KERNEL_STACKTRACE) diff --git a/runtime/sym.c b/runtime/sym.c index f6f97ac2..013edd0c 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -329,8 +329,35 @@ static void _stp_symbol_print(unsigned long address) } } +/** Print an user space address from a specific task symbolically. + * @param address The address to lookup. + * @param task The address to lookup. + * @note Symbolic lookups should not normally be done within + * a probe because it is too time-consuming. Use at module exit time. + */ + +static void _stp_usymbol_print(unsigned long address, struct task_struct *task) +{ + const char *modname; + const char *name; + unsigned long offset, size; + + name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, + task); + + _stp_printf("%p", (int64_t) address); + + if (name) { + if (modname && *modname) + _stp_printf(" : %s+%#lx/%#lx [%s]", name, offset, size, modname); + else + _stp_printf(" : %s+%#lx/%#lx", name, offset, size); + } +} + /* Like _stp_symbol_print, except only print if the address is a valid function address */ -static int _stp_func_print(unsigned long address, int verbose, int exact) +static int _stp_func_print(unsigned long address, int verbose, int exact, + struct task_struct *task) { const char *modname; const char *name; @@ -342,7 +369,7 @@ static int _stp_func_print(unsigned long address, int verbose, int exact) else exstr = " (inexact)"; - name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, NULL); + name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, task); if (name) { if (verbose) { diff --git a/runtime/unwind.c b/runtime/unwind.c index 41af72a7..aacd56f1 100644 --- a/runtime/unwind.c +++ b/runtime/unwind.c @@ -435,12 +435,18 @@ adjustStartLoc (unsigned long startLoc, struct _stp_module *m, struct _stp_section *s) { - if (startLoc && (strcmp (m->name, "kernel") != 0)) - { - startLoc = _stp_module_relocate (m->name, s->name, - startLoc); - startLoc -= m->dwarf_module_base; - } + /* XXX - some, or all, of this should really be done by + _stp_module_relocate. */ + if (startLoc == 0 + || strcmp (m->name, "kernel") == 0 + || strcmp (s->name, ".absolute") == 0) + return startLoc; + + if (strcmp (s->name, ".dynamic") == 0) + return startLoc + s->addr; + + startLoc = _stp_module_relocate (m->name, s->name, startLoc); + startLoc -= m->dwarf_module_base; return startLoc; } @@ -562,7 +568,7 @@ static char *_stp_eh_enc_name(signed type) /* Unwind to previous to frame. Returns 0 if successful, negative * number in case of an error. A positive return means unwinding is finished; * don't try to fallback to dumping addresses on the stack. */ -static int unwind(struct unwind_frame_info *frame) +static int unwind(struct unwind_frame_info *frame, struct task_struct *tsk) { #define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs]) const u32 *fde, *cie = NULL; @@ -581,7 +587,7 @@ static int unwind(struct unwind_frame_info *frame) if (UNW_PC(frame) == 0) return -EINVAL; - m = _stp_mod_sec_lookup (pc, current, &s); + m = _stp_mod_sec_lookup (pc, tsk, &s); if (unlikely(m == NULL)) { dbug_unwind(1, "No module found for pc=%lx", pc); return -EINVAL; diff --git a/tapset/context-symbols.stp b/tapset/context-symbols.stp index 783f1b7b..e4406d9b 100644 --- a/tapset/context-symbols.stp +++ b/tapset/context-symbols.stp @@ -16,10 +16,10 @@ #define STP_NEED_SYMBOL_DATA 1 #endif %} -// weirdness with print_stack, argument appears in build as undescribed + /** * sfunction print_stack - Print out stack from string. - * @stk: String with list of hexidecimal addresses. (FIXME) + * @stk: String with list of hexidecimal addresses. * * Perform a symbolic lookup of the addresses in the given string, * which is assumed to be the result of a prior call to diff --git a/tapset/context-unwind.stp b/tapset/context-unwind.stp index b3d19e29..f1e99dc8 100644 --- a/tapset/context-unwind.stp +++ b/tapset/context-unwind.stp @@ -28,7 +28,7 @@ */ function print_backtrace () %{ if (CONTEXT->regs) { - _stp_stack_print(CONTEXT->regs, 1, CONTEXT->pi, MAXTRACE); + _stp_stack_print(CONTEXT->regs, 1, CONTEXT->pi, MAXTRACE, NULL); } else { _stp_printf("Systemtap probe: %s\n", CONTEXT->probe_point); } @@ -42,7 +42,7 @@ function print_backtrace () %{ */ function backtrace:string () %{ /* pure */ if (CONTEXT->regs) - _stp_stack_snprint (THIS->__retvalue, MAXSTRINGLEN, CONTEXT->regs, 0, CONTEXT->pi, MAXTRACE); + _stp_stack_snprint (THIS->__retvalue, MAXSTRINGLEN, CONTEXT->regs, 0, CONTEXT->pi, MAXTRACE, NULL); else strlcpy (THIS->__retvalue, "", MAXSTRINGLEN); %} diff --git a/tapset/ucontext-symbols.stp b/tapset/ucontext-symbols.stp index 3813a8bf..5502f5cd 100644 --- a/tapset/ucontext-symbols.stp +++ b/tapset/ucontext-symbols.stp @@ -23,7 +23,7 @@ %} /** - * sfunction usymname - Return the symbol of an address in the current task. + * sfunction usymname - Return the symbol of an address in the current task. EXPERIMENTAL! * @addr: The address to translate. * * Description: Returns the (function) symbol name associated with the @@ -36,7 +36,7 @@ function usymname:string (addr: long) %{ /* pure */ %} /** - * sfunction usymdata - Return the symbol and module offset of an address. + * sfunction usymdata - Return the symbol and module offset of an address. EXPERIMENTAL! * @addr: The address to translate. * * Description: Returns the (function) symbol name associated with the @@ -50,3 +50,26 @@ function usymdata:string (addr: long) %{ /* pure */ _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr, current, 1); %} + +/** + * sfunction print_ustack - Print out stack for the current task from string. EXPERIMENTAL! + * @stk: String with list of hexidecimal addresses for the current task. + * + * Perform a symbolic lookup of the addresses in the given string, + * which is assumed to be the result of a prior call to + * <command>ubacktrace()</command> for the current task. + * + * Print one line per address, including the address, the + * name of the function containing the address, and an estimate of + * its position within that function. Return nothing. + */ +function print_ustack(stk:string) %{ + char *ptr = THIS->stk; + char *tok = strsep(&ptr, " "); + while (tok && *tok) { + _stp_print_char(' '); + _stp_usymbol_print (simple_strtol(tok, NULL, 16), current); + _stp_print_char('\n'); + tok = strsep(&ptr, " "); + } +%} diff --git a/tapset/ucontext-unwind.stp b/tapset/ucontext-unwind.stp new file mode 100644 index 00000000..0801f1c9 --- /dev/null +++ b/tapset/ucontext-unwind.stp @@ -0,0 +1,52 @@ +// User context unwind tapset +// Copyright (C) 2009 Red Hat Inc. +// +// This file is part of systemtap, and is free software. You can +// redistribute it and/or modify it under the terms of the GNU General +// Public License (GPL); either version 2, or (at your option) any +// later version. + +%{ +#ifndef STP_NEED_UNWIND_DATA +#define STP_NEED_UNWIND_DATA 1 +#endif +#ifndef STP_NEED_SYMBOL_DATA +#define STP_NEED_SYMBOL_DATA 1 +#endif +#ifndef STP_NEED_VMA_TRACKER +#define STP_NEED_VMA_TRACKER 1 +#endif +%} + +/** + * sfunction print_ubacktrace - Print stack back trace for current task. EXPERIMENTAL! + * + * Equivalent to <command>print_ustack(ubacktrace())</command>, + * except that deeper stack nesting may be supported. Return nothing. + */ +function print_ubacktrace () %{ + if (CONTEXT->regs) { + _stp_stack_print(CONTEXT->regs, 1, CONTEXT->pi, MAXTRACE, + current); + } 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 + * stack of the current task. Output may be truncated as per maximum + * string length. Returns empty string when current probe point cannot + * determine user backtrace. + */ + +function ubacktrace:string () %{ /* pure */ + if (CONTEXT->regs) + _stp_stack_snprint (THIS->__retvalue, MAXSTRINGLEN, + CONTEXT->regs, 0, CONTEXT->pi, MAXTRACE, + current); + else + strlcpy (THIS->__retvalue, "", MAXSTRINGLEN); +%} diff --git a/testsuite/buildok/ustack.stp b/testsuite/buildok/ustack.stp new file mode 100755 index 00000000..23af0bff --- /dev/null +++ b/testsuite/buildok/ustack.stp @@ -0,0 +1,10 @@ +#! stap -p4 +# +# Test the translatability for ubacktrace(), print_ustack() +# and print_ubacktrace() +# +probe begin +{ + print_ustack(ubacktrace()); + print_ubacktrace(); +} diff --git a/testsuite/systemtap.base/uprobes_ustack.exp b/testsuite/systemtap.base/uprobes_ustack.exp new file mode 100644 index 00000000..f085fc16 --- /dev/null +++ b/testsuite/systemtap.base/uprobes_ustack.exp @@ -0,0 +1,94 @@ +set test "uprobes_ustack" +set testpath "$srcdir/$subdir" +set testsrc "$testpath/uprobes_exe.c" +set testsrclib "$testpath/uprobes_lib.c" +set testexe "./uprobes_exe" +set testlibname "uprobes_lib" +set testlibdir "." +set testso "$testlibdir/lib${testlibname}.so" +set testflags "additional_flags=-g additional_flags=-O" +set testlibflags "$testflags additional_flags=-fPIC additional_flags=-shared" +set maintestflags "$testflags additional_flags=-L$testlibdir additional_flags=-l$testlibname additional_flags=-Wl,-rpath,$testlibdir" + +# Compile our test program and library. +set res [target_compile $testsrclib $testso executable $testlibflags] +if { $res != "" } { + verbose "target_compile for $testso failed: $res" 2 + fail "$test compile $testsrclib" + return +} else { + pass "$test compile $testsrclib" +} + +set res [target_compile $testsrc $testexe executable $maintestflags] +if { $res != "" } { + verbose "target_compile failed: $res" 2 + fail "$test compile $testsrc" + return +} else { + pass "$test compile $testsrc" +} + +set ::result_string {exe: main=main +exe: main_func=main_func +exe: main_func=main_func +exe: main_func=main_func +lib: lib_main=lib_main +lib: lib_func=lib_func +lib: lib_func=lib_func +lib: lib_func=lib_func} + +# Only run on make installcheck +if {! [installtest_p]} { untested "$test"; return } +if {! [utrace_p]} { untested $test; return } + +# Output is: +#print_ubacktrace exe 0 +# 0x080484ba : main_func+0xa/0x29 [.../uprobes_exe] +# 0x080484f6 : main+0x1d/0x37 [.../uprobes_exe] +#print_ustack exe 1 +# 0x080484ba : main_func+0xa/0x29 [.../uprobes_exe] +# 0x080484c9 : main_func+0x19/0x29 [.../uprobes_exe] +# 0x080484f6 : main+0x1d/0x37 [.../uprobes_exe] +#print_ubacktrace lib 2 +# 0x00db2422 : lib_func+0x16/0x2b [.../libuprobes_lib.so] +# 0x00db2455 : lib_main+0x1e/0x29 [.../libuprobes_lib.so] +# 0x080484d0 : main_func+0x20/0x29 [.../uprobes_exe] +# 0x080484c9 : main_func+0x19/0x29 [.../uprobes_exe] +# 0x080484c9 : main_func+0x19/0x29 [.../uprobes_exe] +# 0x080484f6 : main+0x1d/0x37 [.../uprobes_exe] +#print_ustack lib 3 +# 0x00db2422 : lib_func+0x16/0x2b [.../libuprobes_lib.so] +# 0x00db2431 : lib_func+0x25/0x2b [.../libuprobes_lib.so] +# 0x00db2455 : lib_main+0x1e/0x29 [.../libuprobes_lib.so] +# 0x080484d0 : main_func+0x20/0x29 [.../uprobes_exe] +# 0x080484c9 : main_func+0x19/0x29 [.../uprobes_exe] +# 0x080484c9 : main_func+0x19/0x29 [.../uprobes_exe] +# 0x080484f6 : main+0x1d/0x37 [.../uprobes_exe] + +set print 0 +set main 0 +set main_func 0 +set lib_main 0 +set lib_func 0 +spawn stap $srcdir/$subdir/$test.stp -c $testexe + +wait +expect { + -timeout 60 + -re {^print_[^\r\n]+\r\n} {incr print; exp_continue} + -re {^ 0x[a-f0-9]+ : main\+0x[^\r\n]+\r\n} {incr main; exp_continue} + -re {^ 0x[a-f0-9]+ : main_func\+0x[^\r\n]+\r\n} {incr main_func; exp_continue} + -re {^ 0x[a-f0-9]+ : lib_main\+0x[^\r\n]+\r\n} {incr lib_main; exp_continue} + -re {^ 0x[a-f0-9]+ : lib_func\+0x[^\r\n]+\r\n} {incr lib_func; exp_continue} + timeout { fail "$test (timeout)" } + eof { } +} + +if {$print == 4} {pass "$test print"} {fail "$test print ($print)"} +if {$main == 4} {pass "$test main"} {fail "$test main ($main)"} +if {$main_func == 9} {pass "$test main_func"} {fail "$test main_func ($main_func)"} +if {$lib_main == 2} {pass "$test lib_main"} {fail "$test lib_main ($lib_main)"} +if {$lib_func == 3} {pass "$test lib_func"} {fail "$test lib_func ($lib_func)"} + +#exec rm -f $testexe $testso diff --git a/testsuite/systemtap.base/uprobes_ustack.stp b/testsuite/systemtap.base/uprobes_ustack.stp new file mode 100644 index 00000000..6de03b42 --- /dev/null +++ b/testsuite/systemtap.base/uprobes_ustack.stp @@ -0,0 +1,35 @@ +// Prints backtrace from lib through exe twice using diffent ustack functions. + +global hits = 0; + +probe process("uprobes_exe").function("main_func") +{ + if (hits == 0) + { + log("print_ubacktrace exe 0"); + print_ubacktrace(); + hits++; + } + else if (hits == 1) + { + log("print_ustack exe 1"); + print_ustack(ubacktrace()); + hits++; + } +} + +probe process("libuprobes_lib.so").function("lib_func") +{ + if (hits == 2) + { + log("print_ubacktrace lib 2"); + print_ubacktrace(); + hits++; + } + else if (hits == 3) + { + log("print_ustack lib 3"); + print_ustack(ubacktrace()); + hits++; + } +} diff --git a/testsuite/systemtap.context/backtrace.tcl b/testsuite/systemtap.context/backtrace.tcl index 6edda812..975e6c4d 100644 --- a/testsuite/systemtap.context/backtrace.tcl +++ b/testsuite/systemtap.context/backtrace.tcl @@ -5,6 +5,7 @@ set m4 0 set m5 0 set m6 0 +#spawn stap -d kernel -d systemtap_test_module1 -DMAXSTRINGLEN=256 $srcdir/$subdir/backtrace.stp spawn stap -DMAXSTRINGLEN=256 $srcdir/$subdir/backtrace.stp #exp_internal 1 expect { |