|  | 
 NAME     
 |  |  |  | stacktrace, localaddr, unwindframe, windindex, windreglocs – stack
    traces 
 | 
 SYNOPSIS     
 |  |  |  | #include <u.h> #include <libc.h>
 #include <mach.h> 
    
    
    int     stacktrace(Map *map, Rgetter rget, Tracer trace) 
    
    
    int     localaddr(Map *map, Regs *regs, char *fn, char *val, ulong
    *val) 
    
    
    int     unwindframe(Map *map, Regs *regs, ulong *next, Symbol *sym)
    
    
    
    int     windindex(char *regname) 
    
    
    Loc* windreglocs(void)
 
 | 
 DESCRIPTION     
 |  |  |  | Stacktrace provides machine-independent implementations of process
    stack traces. They must retrieve data and register contents from
    an executing image. Sometimes the desired registers are not the
    current registers but rather a set of saved registers stored elsewhere
    in memory. The caller may specify an initial register set in the
    form of an Rgetter
    function, of the form It returns the contents of a register when given a map and a register
    name. It is usually sufficient for the register function to return
    meaningful values only for SP and PC, and for the link register
    (usually LR) on CISC machines. 
    
    
    Given the map and the rgetter, stacktrace unwinds the stack starting
    at the innermost function. At each level in the trace, it calls
    the tracer function, which has the form|  |  |  | ulong rget(Map *map, char *name) 
 | 
 The tracer is passed the map, the current program counter, the
    program counter of the caller (zero if the caller is unknown),
    a new rget function, and a symbol (see mach-symbol(3)) describing
    the current function (nil if no symbol is known). The value returned
    by the tracer controls whether the stack trace continues: a zero
    or negative return value stops
    the trace, while a positive return value continues it. 
    
    
    The rgetter passed to the tracer is not the rgetter passed to
    stacktrace itself. Instead, it is a function returning the register
    values at the time of the call, to the extent that they can be
    reconstructed. The most common use for this rgetter is as an argument
    to lget4, etc., when evaluating the locations of local variables.
    
    
    
    Localaddr uses stacktrace to walk up the stack looking for the
    innermost instance of a function named fn ; once it finds the
    function, it looks for the parameter or local variable var, storing
    the address of the variable in val. 
    
    
    Unwindframe is the low-level function on which stacktrace is built.
    Given the current memory image in map and the current register
    set in regs , unwindframe fills in next with the values of the
    register set at the time of the call to the function in the current
    program counter. Sym should be the symbol corresponding to the
    current function, if available. 
    
    
    The next array holds only the winding registers, typically the
    caller-save registers and the program counter and stack pointer.
    The order of registers in the array is called the winding order.
    The winding set can be found in the array mach−>windreg, which
    has mach−>nwindreg entries. Windindex returns the index of the
    named register in the winding
    order. Windreglocs returns an array of Loc structures corresponding
    to the winding registers, in the winding order.|  |  |  | int trace(Map *map, ulong pc, ulong callerpc, 
 | 
 
 | 
 EXAMPLE     
 |  |  |  | The following code writes a simple stack trace to standard output,
    stopping after at most 20 stack frames. 
 |  |  |  | static int trace(Map *map, ulong pc, ulong callerpc,
 
 {|  |  |  | Rgetter rget, Symbol *s, int depth) 
 | 
 
 }|  |  |  | char buf[512]; int i, first;
 u32int v;
 Symbol s2;
 if(sym)
 print("%s+%lx", s->name, pc - loceval(s->loc));
 else
 print("%lux", pc);
 print("(");
 first = 0;
 for(i=0; indexlsym(s, &i, &s2)>=0; i++){
 if(s.class != CPARAM)
 continue;
 if(first++)
 print(", ");
 if(lget4(map, rget, s->loc, &v) >= 0)
 print("%s=%#lux", s->name, (ulong)v);
 else
 print("%s=???", s->name);
 }
 print(") called from ");
 symoff(buf, sizeof buf, callerpc, CTEXT);
 print("%s\n", buf);
 return depth < 20;
 
 | 
 
 |  |  |  | if(stacktrace(map, nil, trace) <= 0) print("no stack frame0);
 
 | 
 | 
 | 
 SOURCE     
 SEE ALSO    
 BUGS     
 |  |