aboutsummaryrefslogtreecommitdiff
path: root/man/man3/mach-stack.html
blob: d08258bdd622f5596ed2108fe0434b44a0e51da1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
<head>
<title>mach-stack(3) - Plan 9 from User Space</title>
<meta content="text/html; charset=utf-8" http-equiv=Content-Type>
</head>
<body bgcolor=#ffffff>
<table border=0 cellpadding=0 cellspacing=0 width=100%>
<tr height=10><td>
<tr><td width=20><td>
<tr><td width=20><td><b>MACH-STACK(3)</b><td align=right><b>MACH-STACK(3)</b>
<tr><td width=20><td colspan=2>
    <br>
<p><font size=+1><b>NAME     </b></font><br>

<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

    stacktrace, localaddr, unwindframe, windindex, windreglocs &ndash; stack
    traces<br>
    
</table>
<p><font size=+1><b>SYNOPSIS     </b></font><br>

<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

    <tt><font size=+1>#include &lt;u.h&gt;<br>
    #include &lt;libc.h&gt;<br>
    #include &lt;mach.h&gt; 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    </font></tt>
    int &nbsp;&nbsp;&nbsp;&nbsp;stacktrace(Map *map, Rgetter rget, Tracer trace) 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    int &nbsp;&nbsp;&nbsp;&nbsp;localaddr(Map *map, Regs *regs, char *fn, char *val, ulong
    *val) 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    int &nbsp;&nbsp;&nbsp;&nbsp;unwindframe(Map *map, Regs *regs, ulong *next, Symbol *sym)
    
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    int &nbsp;&nbsp;&nbsp;&nbsp;windindex(char *regname) 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    Loc* &nbsp;&nbsp;&nbsp;windreglocs(void)<br>
    
</table>
<p><font size=+1><b>DESCRIPTION     </b></font><br>

<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

    <i>Stacktrace</i> provides machine-independent implementations of process
    stack traces. They must retrieve data and register contents from
    an executing image. Sometimes the desired registers are not the
    current registers but rather a set of saved registers stored elsewhere
    in memory. The caller may specify an initial
    register set in the form of an <i>Rgetter</i> function, of the form 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    
    <table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

        <tt><font size=+1>ulong rget(Map *map, char *name)<br>
        
        <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
        </font></tt>
        
    </table>
    It returns the contents of a register when given a map and a register
    name. It is usually sufficient for the register function to return
    meaningful values only for <tt><font size=+1>SP</font></tt> and <tt><font size=+1>PC</font></tt>, and for the link register
    (usually <tt><font size=+1>LR</font></tt>) on CISC machines. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    Given the map and the rgetter, <i>stacktrace</i> unwinds the stack starting
    at the innermost function. At each level in the trace, it calls
    the tracer function, which has the form 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    
    <table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

        <tt><font size=+1>int trace(Map *map, ulong pc, ulong callerpc,<br>
        
        <table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

            Rgetter rget, Symbol *s)<br>
            
            <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
            
        </table>
        </font></tt>
        <table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

            
            
        </table>
        
    </table>
    The tracer is passed the map, the current program counter, the
    program counter of the caller (zero if the caller is unknown),
    a new <i>rget</i> function, and a symbol (see <a href="../man3/mach-symbol.html"><i>mach-symbol</i>(3)</a>) describing
    the current function (nil if no symbol is known). The value returned
    by the tracer controls whether the stack trace continues: a
    zero or negative return value stops the trace, while a positive
    return value continues it. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    The rgetter passed to the tracer is not the rgetter passed to
    <tt><font size=+1>stacktrace</font></tt> itself. Instead, it is a function returning the register
    values at the time of the call, to the extent that they can be
    reconstructed. The most common use for this rgetter is as an argument
    to <i>lget4</i>, etc., when evaluating the locations of local
    variables. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    <i>Localaddr</i> uses <i>stacktrace</i> to walk up the stack looking for the
    innermost instance of a function named <i>fn ;</i> once it finds the
    function, it looks for the parameter or local variable <i>var</i>, storing
    the address of the variable in <i>val</i>. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    <i>Unwindframe</i> is the low-level function on which <i>stacktrace</i> is built.
    Given the current memory image in <i>map</i> and the current register
    set in <i>regs , unwindframe</i> fills in <i>next</i> with the values of the
    register set at the time of the call to the function in the current
    program counter. <i>Sym</i> should be the symbol corresponding to
    the current function, if available. 
    <table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
    
    The <i>next</i> array holds only the <i>winding registers</i>, typically the
    caller-save registers and the program counter and stack pointer.
    The order of registers in the array is called the <i>winding order</i>.
    The winding set can be found in the array <i>mach</i><tt><font size=+1>&#8722;&gt;</font></tt><i>windreg</i>, which
    has <i>mach</i><tt><font size=+1>&#8722;&gt;</font></tt><i>nwindreg</i> entries. <i>Windindex</i> returns the index of
    the named register in the winding order. <i>Windreglocs</i> returns an
    array of <i>Loc</i> structures corresponding to the winding registers,
    in the winding order.<br>
    
</table>
<p><font size=+1><b>EXAMPLE     </b></font><br>

<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

    The following code writes a simple stack trace to standard output,
    stopping after at most 20 stack frames.<br>
    
    <table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

        static int<br>
        trace(Map *map, ulong pc, ulong callerpc,<br>
        
        <table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

            Rgetter rget, Symbol *s, int depth)<br>
            
        </table>
        {<br>
        
        <table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

            char buf[512];<br>
            int i, first;<br>
            u32int v;<br>
            Symbol s2;<br>
            if(sym)<br>
             print(&quot;%s+%lx&quot;, s-&gt;name, pc - loceval(s-&gt;loc));<br>
            else<br>
             print(&quot;%lux&quot;, pc);<br>
            print(&quot;(&quot;);<br>
            first = 0;<br>
            for(i=0; indexlsym(s, &amp;i, &amp;s2)&gt;=0; i++){<br>
             if(s.class != CPARAM)<br>
              continue;<br>
             if(first++)<br>
              print(&quot;, &quot;);<br>
             if(lget4(map, rget, s-&gt;loc, &amp;v) &gt;= 0)<br>
              print(&quot;%s=%#lux&quot;, s-&gt;name, (ulong)v);<br>
             else<br>
              print(&quot;%s=???&quot;, s-&gt;name);<br>
            }<br>
            print(&quot;) called from &quot;);<br>
            symoff(buf, sizeof buf, callerpc, CTEXT);<br>
            print(&quot;%s\n&quot;, buf);<br>
            return depth &lt; 20;<br>
            
        </table>
        }<br>
        
        <table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

            if(stacktrace(map, nil, trace) &lt;= 0)<br>
             print(&quot;no stack frame0);<br>
            
        </table>
        
    </table>
    
</table>
<p><font size=+1><b>SOURCE     </b></font><br>

<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

    <tt><font size=+1>/usr/local/plan9/src/libmach<br>
    </font></tt>
</table>
<p><font size=+1><b>SEE ALSO    </b></font><br>

<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

    <a href="../man3/mach.html"><i>mach</i>(3)</a><br>
    
</table>
<p><font size=+1><b>BUGS     </b></font><br>

<table border=0 cellpadding=0 cellspacing=0><tr height=2><td><tr><td width=20><td>

    Need to talk about Regs<br>
    
</table>

<td width=20>
<tr height=20><td>
</table>
<!-- TRAILER -->
<table border=0 cellpadding=0 cellspacing=0 width=100%>
<tr height=15><td width=10><td><td width=10>
<tr><td><td>
<center>
<a href="../../"><img src="../../dist/spaceglenda100.png" alt="Space Glenda" border=1></a>
</center>
</table>
<!-- TRAILER -->
</body></html>