print_stack, backtrace, probefunc, print_backtrace, caller* are IMO a mess. Let's rationalize them by deprecating these and adding some new functions: stack:long (n:long) - return PC at stack unwind level N ustack:long (n:long) - return PC at user-space stack unwind level N; useful if kernel-side probe is active callers:string (n:long) - return stack(0) stack(1) ... stack(n) as a string ucallers:string (n:long) - return ustack(0) ustack (1) ... ustack(n) symname:string (addr:long) - return the kernel- or user-space symbol name for the given address symdata:string (addr:long) - likewise, adding [module] +offset/size psyms (callers:string) - print symdata() for all addresses in callers Backward compatibility: function backtrace() { return callers (-1) } function print_stack(s) { psyms (s) } function print_backtrace() { psyms (callers (-1)) } function caller_addr() { return stack (1) } function caller() { return symname (caller_addr()) } function probefunc() { return symname (stack (0)) } function probemod() { return substr(symdata (stack (0)), ....) }
caller()/ucaller() can probably be implemented more efficiently than as full wrappers around the caller(1)/ucaller(1). For example the following currently works to get a quick user space symbol, without need to do a full unwind (a full unwind is necessary for getting anything more). If you just want to get the user address and symbol (for static binaries included with -d only for now): # Returns the address in userspace that the current task was at when the # probe occurred. function uaddr:long () %{ /* pure */ #include <asm/processor.h> struct pt_regs *uregs; uregs = task_pt_regs(current); THIS->__retvalue = (int64_t) REG_IP(uregs); %} # Translates an address to a function symbol. Might be expensive # so use sparingly in probes, try translating only in end probes. function uaddr_symbol:string (uaddr: long) %{ /* pure */ _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->uaddr); %} Can be used with something like the following for a quick and dirty "profiler": stap -d /path/to/my-static-binary -e 'probe timer.ms(100) {t = tid(); if (t != 0) { printf("%s:.%d 0x%xd:%s\n", execname(), tid(), uaddr(), uaddr_symbol(uaddr())); } }'
(In reply to comment #1) > # Translates an address to a function symbol. Might be expensive > # so use sparingly in probes, try translating only in end probes. > function uaddr_symbol:string (uaddr: long) %{ /* pure */ > _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->uaddr); > %} > > Can be used with something like the following for a quick and dirty "profiler": > > stap -d /path/to/my-static-binary -e 'probe timer.ms(100) {t = tid(); if (t != > 0) { printf("%s:.%d 0x%xd:%s\n", execname(), tid(), uaddr(), > uaddr_symbol(uaddr())); } }' Franks pointed out that I should mention that _stp_symbol_snprint() only kind of works by accident for user space and isn't reliable. I filed bug #6866 (Extend stp_symbol_snprintf for user space) with some more explanation and a plan for making it reliable.
There are some additional user space related backtrace tapsets functions now since: commit c45319065d6e3ae91ae833f7afbf0edba6c87d89 Author: Mark Wielaard <mjw@redhat.com> Date: Tue Apr 21 17:16:51 2009 +0200 Add ubacktrace(), print_ustack() and print_ubacktrace(). * runtime/sym.c (_stp_usymbol_print): New function. * tapset/ucontext-unwind.stp (print_ubacktrace): New tapset function. (ubacktrace): Likewise. * tapset/ucontext-symbols.stp (print_ustack): Likewise. * testsuite/buildok/ustack.stp: New test for above three functions. Some design questions about these were posted here: http://sourceware.org/ml/systemtap/2009-q2/msg00364.html
You may want a special-case interface for just one caller. That can be translated statically from the CFI, as if using __builtin_return_address(0) in the probed function.
The split between sym*/backtrace() for kernel side and usym*/ubacktrace() for user side is confusing. We really should deduce from the probe context which one the user wants.
*** Bug 13094 has been marked as a duplicate of this bug. ***
The new functions have been implemented, with an underlying cache mechanism that makes it possible to call stack() &co in any order and as many times as we want without particular performance repercussions. All that remains is to deprecate the old functions whenever that seems necessary. Context sensitivity to avoid having separate user/kernel space tapsets seems to be a whole other can of worms, so should probably be taken care of as a separate PR, if at all. Doing so would make the rare but possible case of a script writer doing user unwind from kernel probes (or vice versa) very unwieldy, though.