Bug 6580 - revamp backtrace-related tapset functions
Summary: revamp backtrace-related tapset functions
Status: RESOLVED FIXED
Alias: None
Product: systemtap
Classification: Unclassified
Component: tapsets (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Frank Ch. Eigler
URL:
Keywords:
: 13094 (view as bug list)
Depends on: 5951 6866
Blocks:
  Show dependency treegraph
 
Reported: 2008-05-29 17:02 UTC by Frank Ch. Eigler
Modified: 2012-09-25 15:48 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Frank Ch. Eigler 2008-05-29 17:02:09 UTC
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)), ....) }
Comment 1 Mark Wielaard 2008-09-01 12:32:34 UTC
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())); } }'
Comment 2 Mark Wielaard 2008-09-02 10:14:04 UTC
(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.
Comment 3 Mark Wielaard 2009-04-27 10:13:17 UTC
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
Comment 4 Roland McGrath 2009-09-18 08:28:03 UTC
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.
Comment 5 Mark Wielaard 2010-01-05 09:38:10 UTC
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.
Comment 6 Mark Wielaard 2011-09-08 17:11:15 UTC
*** Bug 13094 has been marked as a duplicate of this bug. ***
Comment 7 Serguei Makarov 2012-09-25 15:48:21 UTC
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.