232 lines
9.2 KiB
HTML
232 lines
9.2 KiB
HTML
<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 – 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 <u.h><br>
|
|
#include <libc.h><br>
|
|
#include <mach.h>
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
|
</font></tt>
|
|
int stacktrace(Map *map, Rgetter rget, Tracer trace)
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
|
|
|
int localaddr(Map *map, Regs *regs, char *fn, char *val, ulong
|
|
*val)
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
|
|
|
int unwindframe(Map *map, Regs *regs, ulong *next, Symbol *sym)
|
|
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
|
|
|
int windindex(char *regname)
|
|
<table border=0 cellpadding=0 cellspacing=0><tr height=5><td></table>
|
|
|
|
Loc* 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>−></font></tt><i>windreg</i>, which
|
|
has <i>mach</i><tt><font size=+1>−></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("%s+%lx", s->name, pc - loceval(s->loc));<br>
|
|
else<br>
|
|
print("%lux", pc);<br>
|
|
print("(");<br>
|
|
first = 0;<br>
|
|
for(i=0; indexlsym(s, &i, &s2)>=0; i++){<br>
|
|
if(s.class != CPARAM)<br>
|
|
continue;<br>
|
|
if(first++)<br>
|
|
print(", ");<br>
|
|
if(lget4(map, rget, s->loc, &v) >= 0)<br>
|
|
print("%s=%#lux", s->name, (ulong)v);<br>
|
|
else<br>
|
|
print("%s=???", s->name);<br>
|
|
}<br>
|
|
print(") called from ");<br>
|
|
symoff(buf, sizeof buf, callerpc, CTEXT);<br>
|
|
print("%s\n", buf);<br>
|
|
return depth < 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) <= 0)<br>
|
|
print("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>
|