tmach-stack.3 - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tmach-stack.3 (4342B)
       ---
            1 .TH MACH-STACK 3
            2 .SH NAME
            3 stacktrace, localaddr, unwindframe, windindex, windreglocs \- stack traces
            4 .SH SYNOPSIS
            5 .B #include <u.h>
            6 .br
            7 .B #include <libc.h>
            8 .br
            9 .B #include <mach.h>
           10 .PP
           11 .ft B
           12 .ta \w'\fBxxxxxx'u +\w'\fBxxxxxx'u
           13 int        stacktrace(Map *map, Rgetter rget, Tracer trace)
           14 .PP
           15 .ft B
           16 int        localaddr(Map *map, Regs *regs, char *fn, char *val, ulong *val)
           17 .PP
           18 .ft B
           19 int        unwindframe(Map *map, Regs *regs, ulong *next, Symbol *sym)
           20 .PP
           21 .ft B
           22 int        windindex(char *regname)
           23 .PP
           24 .ft B
           25 Loc*        windreglocs(void)
           26 .SH DESCRIPTION
           27 .I Stacktrace
           28 provides machine-independent
           29 implementations of process stack traces.
           30 They must retrieve data and register contents from an executing
           31 image.  Sometimes the desired registers are not the current
           32 registers but rather a set of saved registers stored elsewhere
           33 in memory.
           34 The caller may specify an initial register set in the form of an
           35 .I Rgetter
           36 function, of the form
           37 .PP
           38 .RS
           39 .B "ulong rget(Map *map, char *name)
           40 .RE
           41 .PP
           42 It returns the contents of a register when given a map
           43 and a register name.
           44 It is usually sufficient for the register function
           45 to return meaningful values only for 
           46 .BR SP
           47 and
           48 .BR PC ,
           49 and for the link register
           50 (usually
           51 .BR LR )
           52 on CISC machines.
           53 .PP
           54 Given the map and the rgetter,
           55 .I stacktrace
           56 unwinds the stack starting at the innermost function.
           57 At each level in the trace, it calls the tracer function, which has the form
           58 .PP
           59 .RS
           60 .B "int trace(Map *map, ulong pc, ulong callerpc,
           61 .br
           62 .B "        Rgetter rget, Symbol *s)
           63 .RE
           64 .PP
           65 The tracer is passed the map, the current program counter,
           66 the program counter of the caller (zero if the caller is unknown),
           67 a new
           68 .I rget
           69 function, and a symbol 
           70 (see
           71 .MR mach-symbol (3) )
           72 describing the current function
           73 (nil if no symbol is known).
           74 The value returned by the tracer
           75 controls whether the stack trace continues:
           76 a zero or negative return value stops the trace,
           77 while a positive return value continues it.
           78 .PP
           79 The rgetter passed to the tracer is not the rgetter
           80 passed to
           81 .B stacktrace
           82 itself.
           83 Instead, it is a function returning the register values
           84 at the time of the call, to the extent that they can be
           85 reconstructed.
           86 The most common use for this rgetter
           87 is as an argument to
           88 .IR lget4 ,
           89 etc., when evaluating the locations of local variables.
           90 .PP
           91 .I Localaddr
           92 uses
           93 .I stacktrace
           94 to walk up the stack looking for the innermost instance of a function named
           95 .I fn ;
           96 once it finds the function,
           97 it looks for the parameter or local variable
           98 .IR var ,
           99 storing the address of the variable in
          100 .IR val .
          101 .PP
          102 .I Unwindframe
          103 is the low-level function on which
          104 .I stacktrace
          105 is built.
          106 Given the current memory image in
          107 .I map
          108 and the current register set in
          109 .I regs ,
          110 .I unwindframe
          111 fills in
          112 .I next
          113 with the values of the register set 
          114 at the time of the call to the function in the current program counter.
          115 .I Sym
          116 should be the symbol corresponding to the current function,
          117 if available.
          118 .PP
          119 The
          120 .I next
          121 array holds only the
          122 .IR "winding registers" ,
          123 typically the caller-save registers and the program counter and stack pointer.
          124 The order of registers in the array is called the
          125 .IR "winding order" .
          126 The winding set can be found in the array
          127 .IB mach -> windreg \fR,
          128 which has
          129 .IB mach -> nwindreg
          130 entries.
          131 .I Windindex
          132 returns the index of the named register
          133 in the winding order.
          134 .I Windreglocs
          135 returns an array of
          136 .I Loc
          137 structures corresponding to the winding registers,
          138 in the winding order.
          139 .SH EXAMPLE
          140 The following code writes a simple stack trace to standard output,
          141 stopping after at most 20 stack frames.
          142 .RS
          143 .ft B
          144 .nf
          145 .ta \w'xxxx'u +\w'xxxx'u +\w'xxxx'u +\w'xxxx'u +\w'xxxx'u
          146 static int
          147 trace(Map *map, ulong pc, ulong callerpc,
          148         Rgetter rget, Symbol *s, int depth)
          149 {
          150         char buf[512];
          151         int i, first;
          152         u32int v;
          153         Symbol s2;
          154 
          155         if(sym)
          156                 print("%s+%lx", s->name, pc - loceval(s->loc));
          157         else
          158                 print("%lux", pc);
          159         print("(");
          160         first = 0;
          161         for(i=0; indexlsym(s, &i, &s2)>=0; i++){
          162                 if(s.class != CPARAM)
          163                         continue;
          164                 if(first++)
          165                         print(", ");
          166                 if(lget4(map, rget, s->loc, &v) >= 0)
          167                         print("%s=%#lux", s->name, (ulong)v);
          168                 else
          169                         print("%s=???", s->name);
          170         }
          171         print(") called from ");
          172         symoff(buf, sizeof buf, callerpc, CTEXT);
          173         print("%s\en", buf);
          174         return depth < 20;
          175 }
          176 
          177         if(stacktrace(map, nil, trace) <= 0)
          178                 print("no stack frame\n");
          179 .RE
          180 .SH SOURCE
          181 .B \*9/src/libmach
          182 .SH SEE ALSO
          183 .MR mach (3)
          184 .SH BUGS
          185 Need to talk about Regs