Blame


1 bf8a59fa 2004-04-11 devnull .TH MACH-STACK 3
2 bf8a59fa 2004-04-11 devnull .SH NAME
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>
6 bf8a59fa 2004-04-11 devnull .br
7 bf8a59fa 2004-04-11 devnull .B #include <libc.h>
8 bf8a59fa 2004-04-11 devnull .br
9 bf8a59fa 2004-04-11 devnull .B #include <mach.h>
10 bf8a59fa 2004-04-11 devnull .PP
11 bf8a59fa 2004-04-11 devnull .ft B
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)
14 bf8a59fa 2004-04-11 devnull .PP
15 bf8a59fa 2004-04-11 devnull .ft B
16 058b0118 2005-01-03 devnull int localaddr(Map *map, Regs *regs, char *fn, char *val, ulong *val)
17 058b0118 2005-01-03 devnull .PP
18 058b0118 2005-01-03 devnull .ft B
19 058b0118 2005-01-03 devnull int unwindframe(Map *map, Regs *regs, ulong *next, Symbol *sym)
20 058b0118 2005-01-03 devnull .PP
21 058b0118 2005-01-03 devnull .ft B
22 058b0118 2005-01-03 devnull int windindex(char *regname)
23 058b0118 2005-01-03 devnull .PP
24 058b0118 2005-01-03 devnull .ft B
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
37 bf8a59fa 2004-04-11 devnull .PP
38 bf8a59fa 2004-04-11 devnull .RS
39 bf8a59fa 2004-04-11 devnull .B "ulong rget(Map *map, char *name)
40 bf8a59fa 2004-04-11 devnull .RE
41 bf8a59fa 2004-04-11 devnull .PP
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
46 bf8a59fa 2004-04-11 devnull .BR SP
47 bf8a59fa 2004-04-11 devnull and
48 bf8a59fa 2004-04-11 devnull .BR PC ,
49 bf8a59fa 2004-04-11 devnull and for the link register
50 bf8a59fa 2004-04-11 devnull (usually
51 bf8a59fa 2004-04-11 devnull .BR LR )
52 bf8a59fa 2004-04-11 devnull on CISC machines.
53 bf8a59fa 2004-04-11 devnull .PP
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
58 bf8a59fa 2004-04-11 devnull .PP
59 bf8a59fa 2004-04-11 devnull .RS
60 bf8a59fa 2004-04-11 devnull .B "int trace(Map *map, ulong pc, ulong callerpc,
61 bf8a59fa 2004-04-11 devnull .br
62 bf8a59fa 2004-04-11 devnull .B " Rgetter rget, Symbol *s)
63 bf8a59fa 2004-04-11 devnull .RE
64 bf8a59fa 2004-04-11 devnull .PP
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),
67 bf8a59fa 2004-04-11 devnull a new
68 bf8a59fa 2004-04-11 devnull .I rget
69 bf8a59fa 2004-04-11 devnull function, and a symbol
70 bf8a59fa 2004-04-11 devnull (see
71 d32deab1 2020-08-16 rsc .MR 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.
78 bf8a59fa 2004-04-11 devnull .PP
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
82 bf8a59fa 2004-04-11 devnull itself.
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.
90 bf8a59fa 2004-04-11 devnull .PP
91 058b0118 2005-01-03 devnull .I Localaddr
92 bf8a59fa 2004-04-11 devnull uses
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
95 bf8a59fa 2004-04-11 devnull .I fn ;
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 .
101 058b0118 2005-01-03 devnull .PP
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
107 058b0118 2005-01-03 devnull .I map
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
112 058b0118 2005-01-03 devnull .I next
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.
115 058b0118 2005-01-03 devnull .I Sym
116 058b0118 2005-01-03 devnull should be the symbol corresponding to the current function,
117 058b0118 2005-01-03 devnull if available.
118 058b0118 2005-01-03 devnull .PP
119 058b0118 2005-01-03 devnull The
120 058b0118 2005-01-03 devnull .I next
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
136 058b0118 2005-01-03 devnull .I Loc
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.
142 bf8a59fa 2004-04-11 devnull .RS
143 bf8a59fa 2004-04-11 devnull .ft B
144 bf8a59fa 2004-04-11 devnull .nf
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)
149 bf8a59fa 2004-04-11 devnull {
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;
154 bf8a59fa 2004-04-11 devnull
155 bf8a59fa 2004-04-11 devnull if(sym)
156 bf8a59fa 2004-04-11 devnull print("%s+%lx", s->name, pc - loceval(s->loc));
157 bf8a59fa 2004-04-11 devnull else
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);
168 bf8a59fa 2004-04-11 devnull else
169 bf8a59fa 2004-04-11 devnull print("%s=???", s->name);
170 bf8a59fa 2004-04-11 devnull }
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;
175 bf8a59fa 2004-04-11 devnull }
176 bf8a59fa 2004-04-11 devnull
177 bf8a59fa 2004-04-11 devnull if(stacktrace(map, nil, trace) <= 0)
178 bf8a59fa 2004-04-11 devnull print("no stack frame\n");
179 bf8a59fa 2004-04-11 devnull .RE
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 d32deab1 2020-08-16 rsc .MR mach (3)
184 058b0118 2005-01-03 devnull .SH BUGS
185 058b0118 2005-01-03 devnull Need to talk about Regs