| <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> |