1 bf8a59fa 2004-04-11 devnull .TH MACH-STACK 3
3 bf8a59fa 2004-04-11 devnull stacktrace,
4 bf8a59fa 2004-04-11 devnull localaddr,
5 bf8a59fa 2004-04-11 devnull .SH SYNOPSIS
6 bf8a59fa 2004-04-11 devnull .B #include <u.h>
8 bf8a59fa 2004-04-11 devnull .B #include <libc.h>
10 bf8a59fa 2004-04-11 devnull .B #include <mach.h>
13 bf8a59fa 2004-04-11 devnull .ta \w'\fBxxxxxx'u +\w'\fBxxxxxx'u
14 bf8a59fa 2004-04-11 devnull int stacktrace(Map *map, Rgetter rget, Tracer trace)
17 bf8a59fa 2004-04-11 devnull int localvar(Map *map, char *fn, char *val, Loc *loc)
18 bf8a59fa 2004-04-11 devnull .SH DESCRIPTION
19 bf8a59fa 2004-04-11 devnull .I Stacktrace
20 bf8a59fa 2004-04-11 devnull provides machine-independent
21 bf8a59fa 2004-04-11 devnull implementations of process stack traces.
22 bf8a59fa 2004-04-11 devnull They must retrieve data and register contents from an executing
23 bf8a59fa 2004-04-11 devnull image. Sometimes the desired registers are not the current
24 bf8a59fa 2004-04-11 devnull registers but rather a set of saved registers stored elsewhere
25 bf8a59fa 2004-04-11 devnull in memory.
26 bf8a59fa 2004-04-11 devnull The caller may specify an initial register set in the form of an
27 bf8a59fa 2004-04-11 devnull .I Rgetter
28 bf8a59fa 2004-04-11 devnull function, of the form
31 bf8a59fa 2004-04-11 devnull .B "ulong rget(Map *map, char *name)
34 bf8a59fa 2004-04-11 devnull It returns the contents of a register when given a map
35 bf8a59fa 2004-04-11 devnull and a register name.
36 bf8a59fa 2004-04-11 devnull It is usually sufficient for the register function
37 bf8a59fa 2004-04-11 devnull to return meaningful values only for
41 bf8a59fa 2004-04-11 devnull and for the link register
44 bf8a59fa 2004-04-11 devnull on CISC machines.
46 bf8a59fa 2004-04-11 devnull Given the map and the rgetter,
47 bf8a59fa 2004-04-11 devnull .I stacktrace
48 bf8a59fa 2004-04-11 devnull unwinds the stack starting at the innermost function.
49 bf8a59fa 2004-04-11 devnull At each level in the trace, it calls the tracer function, which has the form
52 bf8a59fa 2004-04-11 devnull .B "int trace(Map *map, ulong pc, ulong callerpc,
54 bf8a59fa 2004-04-11 devnull .B " Rgetter rget, Symbol *s)
57 bf8a59fa 2004-04-11 devnull The tracer is passed the map, the current program counter,
58 bf8a59fa 2004-04-11 devnull the program counter of the caller (zero if the caller is unknown),
61 bf8a59fa 2004-04-11 devnull function, and a symbol
63 bf8a59fa 2004-04-11 devnull .IR mach-symbol (3))
64 bf8a59fa 2004-04-11 devnull describing the current function
65 bf8a59fa 2004-04-11 devnull (nil if no symbol is known).
66 bf8a59fa 2004-04-11 devnull The value returned by the tracer
67 bf8a59fa 2004-04-11 devnull controls whether the stack trace continues:
68 bf8a59fa 2004-04-11 devnull a zero or negative return value stops the trace,
69 bf8a59fa 2004-04-11 devnull while a positive return value continues it.
71 bf8a59fa 2004-04-11 devnull The rgetter passed to the tracer is not the rgetter
72 bf8a59fa 2004-04-11 devnull passed to
73 bf8a59fa 2004-04-11 devnull .B stacktrace
75 bf8a59fa 2004-04-11 devnull Instead, it is a function returning the register values
76 bf8a59fa 2004-04-11 devnull at the time of the call, to the extent that they can be
77 bf8a59fa 2004-04-11 devnull reconstructed.
78 bf8a59fa 2004-04-11 devnull The most common use for this rgetter
79 bf8a59fa 2004-04-11 devnull is as an argument to
80 bf8a59fa 2004-04-11 devnull .IR lget4 ,
81 bf8a59fa 2004-04-11 devnull etc., when evaluating the locations of local variables.
83 bf8a59fa 2004-04-11 devnull .I Localvar
85 bf8a59fa 2004-04-11 devnull .I stacktrace
86 bf8a59fa 2004-04-11 devnull to walk up the stack looking for the innermost instance of a function named
88 bf8a59fa 2004-04-11 devnull once it finds the function,
89 bf8a59fa 2004-04-11 devnull it looks for the parameter or local variable
90 bf8a59fa 2004-04-11 devnull .IR var ,
91 bf8a59fa 2004-04-11 devnull storing the location of the variable in
92 bf8a59fa 2004-04-11 devnull .IR loc .
93 bf8a59fa 2004-04-11 devnull .SH EXAMPLE
94 bf8a59fa 2004-04-11 devnull The following code writes a simple stack trace to standard output,
95 bf8a59fa 2004-04-11 devnull stopping after at most 20 stack frames.
99 bf8a59fa 2004-04-11 devnull .ta \w'xxxx'u +\w'xxxx'u +\w'xxxx'u +\w'xxxx'u +\w'xxxx'u
100 bf8a59fa 2004-04-11 devnull static int
101 bf8a59fa 2004-04-11 devnull trace(Map *map, ulong pc, ulong callerpc,
102 bf8a59fa 2004-04-11 devnull Rgetter rget, Symbol *s, int depth)
104 bf8a59fa 2004-04-11 devnull char buf[512];
105 bf8a59fa 2004-04-11 devnull int i, first;
106 bf8a59fa 2004-04-11 devnull u32int v;
107 bf8a59fa 2004-04-11 devnull Symbol s2;
110 bf8a59fa 2004-04-11 devnull print("%s+%lx", s->name, pc - loceval(s->loc));
112 bf8a59fa 2004-04-11 devnull print("%lux", pc);
113 bf8a59fa 2004-04-11 devnull print("(");
114 bf8a59fa 2004-04-11 devnull first = 0;
115 bf8a59fa 2004-04-11 devnull for(i=0; indexlsym(s, &i, &s2)>=0; i++){
116 bf8a59fa 2004-04-11 devnull if(s.class != CPARAM)
117 bf8a59fa 2004-04-11 devnull continue;
118 bf8a59fa 2004-04-11 devnull if(first++)
119 bf8a59fa 2004-04-11 devnull print(", ");
120 bf8a59fa 2004-04-11 devnull if(lget4(map, rget, s->loc, &v) >= 0)
121 bf8a59fa 2004-04-11 devnull print("%s=%#lux", s->name, (ulong)v);
123 bf8a59fa 2004-04-11 devnull print("%s=???", s->name);
125 bf8a59fa 2004-04-11 devnull print(") called from ");
126 bf8a59fa 2004-04-11 devnull symoff(buf, sizeof buf, callerpc, CTEXT);
127 bf8a59fa 2004-04-11 devnull print("%s\en", buf);
128 bf8a59fa 2004-04-11 devnull return depth < 20;
131 bf8a59fa 2004-04-11 devnull if(stacktrace(map, nil, trace) <= 0)
132 bf8a59fa 2004-04-11 devnull print("no stack frame\n");
134 bf8a59fa 2004-04-11 devnull .SH SOURCE
135 bf8a59fa 2004-04-11 devnull .B /sys/src/libmach
136 bf8a59fa 2004-04-11 devnull .SH SEE ALSO
137 bf8a59fa 2004-04-11 devnull .IR mach (3)