1 bf8a59fa 2004-04-11 devnull .TH MACH-STACK 3
3 058b0118 2005-01-03 devnull stacktrace, localaddr, unwindframe, windindex, windreglocs \- stack traces
4 bf8a59fa 2004-04-11 devnull .SH SYNOPSIS
5 bf8a59fa 2004-04-11 devnull .B #include <u.h>
7 bf8a59fa 2004-04-11 devnull .B #include <libc.h>
9 bf8a59fa 2004-04-11 devnull .B #include <mach.h>
12 bf8a59fa 2004-04-11 devnull .ta \w'\fBxxxxxx'u +\w'\fBxxxxxx'u
13 bf8a59fa 2004-04-11 devnull int stacktrace(Map *map, Rgetter rget, Tracer trace)
16 058b0118 2005-01-03 devnull int localaddr(Map *map, Regs *regs, char *fn, char *val, ulong *val)
19 058b0118 2005-01-03 devnull int unwindframe(Map *map, Regs *regs, ulong *next, Symbol *sym)
22 058b0118 2005-01-03 devnull int windindex(char *regname)
25 058b0118 2005-01-03 devnull Loc* windreglocs(void)
26 bf8a59fa 2004-04-11 devnull .SH DESCRIPTION
27 bf8a59fa 2004-04-11 devnull .I Stacktrace
28 bf8a59fa 2004-04-11 devnull provides machine-independent
29 bf8a59fa 2004-04-11 devnull implementations of process stack traces.
30 bf8a59fa 2004-04-11 devnull They must retrieve data and register contents from an executing
31 bf8a59fa 2004-04-11 devnull image. Sometimes the desired registers are not the current
32 bf8a59fa 2004-04-11 devnull registers but rather a set of saved registers stored elsewhere
33 bf8a59fa 2004-04-11 devnull in memory.
34 bf8a59fa 2004-04-11 devnull The caller may specify an initial register set in the form of an
35 bf8a59fa 2004-04-11 devnull .I Rgetter
36 bf8a59fa 2004-04-11 devnull function, of the form
39 bf8a59fa 2004-04-11 devnull .B "ulong rget(Map *map, char *name)
42 bf8a59fa 2004-04-11 devnull It returns the contents of a register when given a map
43 bf8a59fa 2004-04-11 devnull and a register name.
44 bf8a59fa 2004-04-11 devnull It is usually sufficient for the register function
45 bf8a59fa 2004-04-11 devnull to return meaningful values only for
49 bf8a59fa 2004-04-11 devnull and for the link register
52 bf8a59fa 2004-04-11 devnull on CISC machines.
54 bf8a59fa 2004-04-11 devnull Given the map and the rgetter,
55 bf8a59fa 2004-04-11 devnull .I stacktrace
56 bf8a59fa 2004-04-11 devnull unwinds the stack starting at the innermost function.
57 bf8a59fa 2004-04-11 devnull At each level in the trace, it calls the tracer function, which has the form
60 bf8a59fa 2004-04-11 devnull .B "int trace(Map *map, ulong pc, ulong callerpc,
62 bf8a59fa 2004-04-11 devnull .B " Rgetter rget, Symbol *s)
65 bf8a59fa 2004-04-11 devnull The tracer is passed the map, the current program counter,
66 bf8a59fa 2004-04-11 devnull the program counter of the caller (zero if the caller is unknown),
69 bf8a59fa 2004-04-11 devnull function, and a symbol
71 bf8a59fa 2004-04-11 devnull .IR mach-symbol (3))
72 bf8a59fa 2004-04-11 devnull describing the current function
73 bf8a59fa 2004-04-11 devnull (nil if no symbol is known).
74 bf8a59fa 2004-04-11 devnull The value returned by the tracer
75 bf8a59fa 2004-04-11 devnull controls whether the stack trace continues:
76 bf8a59fa 2004-04-11 devnull a zero or negative return value stops the trace,
77 bf8a59fa 2004-04-11 devnull while a positive return value continues it.
79 bf8a59fa 2004-04-11 devnull The rgetter passed to the tracer is not the rgetter
80 bf8a59fa 2004-04-11 devnull passed to
81 bf8a59fa 2004-04-11 devnull .B stacktrace
83 bf8a59fa 2004-04-11 devnull Instead, it is a function returning the register values
84 bf8a59fa 2004-04-11 devnull at the time of the call, to the extent that they can be
85 bf8a59fa 2004-04-11 devnull reconstructed.
86 bf8a59fa 2004-04-11 devnull The most common use for this rgetter
87 bf8a59fa 2004-04-11 devnull is as an argument to
88 bf8a59fa 2004-04-11 devnull .IR lget4 ,
89 bf8a59fa 2004-04-11 devnull etc., when evaluating the locations of local variables.
91 058b0118 2005-01-03 devnull .I Localaddr
93 bf8a59fa 2004-04-11 devnull .I stacktrace
94 bf8a59fa 2004-04-11 devnull to walk up the stack looking for the innermost instance of a function named
96 bf8a59fa 2004-04-11 devnull once it finds the function,
97 bf8a59fa 2004-04-11 devnull it looks for the parameter or local variable
98 bf8a59fa 2004-04-11 devnull .IR var ,
99 058b0118 2005-01-03 devnull storing the address of the variable in
100 058b0118 2005-01-03 devnull .IR val .
102 058b0118 2005-01-03 devnull .I Unwindframe
103 058b0118 2005-01-03 devnull is the low-level function on which
104 058b0118 2005-01-03 devnull .I stacktrace
105 058b0118 2005-01-03 devnull is built.
106 058b0118 2005-01-03 devnull Given the current memory image in
108 058b0118 2005-01-03 devnull and the current register set in
109 058b0118 2005-01-03 devnull .I regs ,
110 058b0118 2005-01-03 devnull .I unwindframe
111 058b0118 2005-01-03 devnull fills in
113 058b0118 2005-01-03 devnull with the values of the register set
114 058b0118 2005-01-03 devnull at the time of the call to the function in the current program counter.
116 058b0118 2005-01-03 devnull should be the symbol corresponding to the current function,
117 058b0118 2005-01-03 devnull if available.
121 058b0118 2005-01-03 devnull array holds only the
122 058b0118 2005-01-03 devnull .IR "winding registers" ,
123 058b0118 2005-01-03 devnull typically the caller-save registers and the program counter and stack pointer.
124 058b0118 2005-01-03 devnull The order of registers in the array is called the
125 058b0118 2005-01-03 devnull .IR "winding order" .
126 058b0118 2005-01-03 devnull The winding set can be found in the array
127 058b0118 2005-01-03 devnull .IB mach -> windreg \fR,
128 058b0118 2005-01-03 devnull which has
129 058b0118 2005-01-03 devnull .IB mach -> nwindreg
130 058b0118 2005-01-03 devnull entries.
131 058b0118 2005-01-03 devnull .I Windindex
132 058b0118 2005-01-03 devnull returns the index of the named register
133 058b0118 2005-01-03 devnull in the winding order.
134 058b0118 2005-01-03 devnull .I Windreglocs
135 058b0118 2005-01-03 devnull returns an array of
137 058b0118 2005-01-03 devnull structures corresponding to the winding registers,
138 058b0118 2005-01-03 devnull in the winding order.
139 bf8a59fa 2004-04-11 devnull .SH EXAMPLE
140 bf8a59fa 2004-04-11 devnull The following code writes a simple stack trace to standard output,
141 bf8a59fa 2004-04-11 devnull stopping after at most 20 stack frames.
145 bf8a59fa 2004-04-11 devnull .ta \w'xxxx'u +\w'xxxx'u +\w'xxxx'u +\w'xxxx'u +\w'xxxx'u
146 bf8a59fa 2004-04-11 devnull static int
147 bf8a59fa 2004-04-11 devnull trace(Map *map, ulong pc, ulong callerpc,
148 bf8a59fa 2004-04-11 devnull Rgetter rget, Symbol *s, int depth)
150 bf8a59fa 2004-04-11 devnull char buf[512];
151 bf8a59fa 2004-04-11 devnull int i, first;
152 bf8a59fa 2004-04-11 devnull u32int v;
153 bf8a59fa 2004-04-11 devnull Symbol s2;
156 bf8a59fa 2004-04-11 devnull print("%s+%lx", s->name, pc - loceval(s->loc));
158 bf8a59fa 2004-04-11 devnull print("%lux", pc);
159 bf8a59fa 2004-04-11 devnull print("(");
160 bf8a59fa 2004-04-11 devnull first = 0;
161 bf8a59fa 2004-04-11 devnull for(i=0; indexlsym(s, &i, &s2)>=0; i++){
162 bf8a59fa 2004-04-11 devnull if(s.class != CPARAM)
163 bf8a59fa 2004-04-11 devnull continue;
164 bf8a59fa 2004-04-11 devnull if(first++)
165 bf8a59fa 2004-04-11 devnull print(", ");
166 bf8a59fa 2004-04-11 devnull if(lget4(map, rget, s->loc, &v) >= 0)
167 bf8a59fa 2004-04-11 devnull print("%s=%#lux", s->name, (ulong)v);
169 bf8a59fa 2004-04-11 devnull print("%s=???", s->name);
171 bf8a59fa 2004-04-11 devnull print(") called from ");
172 bf8a59fa 2004-04-11 devnull symoff(buf, sizeof buf, callerpc, CTEXT);
173 bf8a59fa 2004-04-11 devnull print("%s\en", buf);
174 bf8a59fa 2004-04-11 devnull return depth < 20;
177 bf8a59fa 2004-04-11 devnull if(stacktrace(map, nil, trace) <= 0)
178 bf8a59fa 2004-04-11 devnull print("no stack frame\n");
180 bf8a59fa 2004-04-11 devnull .SH SOURCE
181 c3674de4 2005-01-11 devnull .B \*9/src/libmach
182 bf8a59fa 2004-04-11 devnull .SH SEE ALSO
183 bf8a59fa 2004-04-11 devnull .IR mach (3)
184 058b0118 2005-01-03 devnull .SH BUGS
185 058b0118 2005-01-03 devnull Need to talk about Regs