Blob


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)
150 char buf[512];
151 int i, first;
152 u32int v;
153 Symbol s2;
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);
171 print(") called from ");
172 symoff(buf, sizeof buf, callerpc, CTEXT);
173 print("%s\en", buf);
174 return depth < 20;
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