mach-stack.3 (4342B)
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) 149 { 150 char buf[512]; 151 int i, first; 152 u32int v; 153 Symbol s2; 154 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); 170 } 171 print(") called from "); 172 symoff(buf, sizeof buf, callerpc, CTEXT); 173 print("%s\en", buf); 174 return depth < 20; 175 } 176 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