7 static int rtrace(uvlong, uvlong, uvlong);
8 static int ctrace(uvlong, uvlong, uvlong);
9 static int i386trace(uvlong, uvlong, uvlong);
10 static int amd64trace(uvlong, uvlong, uvlong);
11 static uvlong getval(uvlong);
12 static void inithdr(int);
13 static void fatal(char*, ...);
14 static void readstack(void);
17 static int interactive;
19 #define FRAMENAME ".frame"
24 fprint(2, "usage: ktrace [-i] kernel pc sp [link]\n");
29 printaddr(char *addr, uvlong pc)
35 * reformat the following.
37 * foo+1a1 -> src(foo+0x1a1);
38 * 10101010 -> src(0x10101010);
41 if(strlen(addr) == 8 && strchr(addr, '+') == nil){
43 if(!isxdigit(addr[i]))
46 print("src(%#.8llux); // 0x%s\n", pc, addr);
51 if(p=strchr(addr, '+')){
53 print("src(%#.8llux); // %s+0x%s\n", pc, addr, p);
55 print("src(%#.8llux); // %s\n", pc, addr);
58 static void (*fmt)(char*, uvlong) = printaddr;
61 main(int argc, char *argv[])
63 int (*t)(uvlong, uvlong, uvlong);
80 link = strtoull(argv[3], 0, 16);
87 pc = strtoull(argv[1], 0, 16);
88 sp = strtoull(argv[2], 0, 16);
92 fd = open(argv[0], OREAD);
94 fatal("can't open %s: %r", argv[0]);
97 case I_MAGIC: /* intel 386 */
100 case S_MAGIC: /* amd64 */
103 case A_MAGIC: /* 68020 */
104 case J_MAGIC: /* intel 960 */
107 case K_MAGIC: /* sparc */
108 case D_MAGIC: /* amd 29000 */
109 case V_MAGIC: /* mips 3000 */
110 case M_MAGIC: /* mips 4000 */
111 case E_MAGIC: /* arm 7-something */
112 case Q_MAGIC: /* powerpc */
113 case N_MAGIC: /* mips 4000 LE */
114 case L_MAGIC: /* dec alpha */
117 case X_MAGIC: /* att dsp 3210 */
118 sysfatal("can't ktrace %s", argv[0]);
121 fprint(2, "%s: warning: can't tell what type of stack %s uses; assuming it's %s\n",
122 argv0, argv[0], argc == 4 ? "risc" : "cisc");
133 if(!crackhdr(fd, &fhdr))
134 fatal("read text header");
136 if(syminit(fd, &fhdr) < 0)
141 rtrace(uvlong pc, uvlong sp, uvlong link)
149 while(findsym(pc, CTEXT, &s)) {
150 if(pc == s.value) /* at first instruction */
152 else if(findlocal(&s, FRAMENAME, &f) == 0)
155 symoff(buf, sizeof buf, pc, CANY);
159 if(s.type == 'L' || s.type == 'l' || pc <= s.value+mach->pcquant){
161 fprint(2, "%s: need to supply a valid link register\n", argv0);
169 if(pc == 0 || (pc == oldpc && f.value == 0))
181 ctrace(uvlong pc, uvlong sp, uvlong link)
192 while(pc && opc != pc) {
195 print("pc2sp(%#.8llux) = -1 %r\n", pc);
198 found = findsym(pc, CTEXT, &s);
200 print("findsym fails\n");
203 symoff(buf, sizeof buf, pc, CANY);
211 sp += mach->szaddr; /*assumes address size = stack width*/
219 i386trace(uvlong pc, uvlong sp, uvlong link)
229 while(findsym(pc, CTEXT, &s)) {
231 symoff(buf, sizeof buf, pc, CANY);
234 //XXX s.value &= ~(uintptr)0;
235 if(pc != s.value) { /* not at first instruction */
236 if(findlocal(&s, FRAMENAME, &f) == 0)
238 sp += f.value-mach->szaddr;
239 }else if(strcmp(s.name, "forkret") == 0){
241 print("//passing interrupt frame; last pc found at sp=%#llux\n", osp);
243 sp += 15 * mach->szaddr; /* pop interrupt frame */
248 if(pc == 0 && strcmp(s.name, "forkret") == 0){
249 sp += 3 * mach->szaddr; /* pop iret eip, cs, eflags */
250 print("//guessing call through invalid pointer, try again at sp=%#llux\n", sp);
255 print("//didn't find pc at sp=%#llux, last pc found at sp=%#llux\n", sp, osp);
262 if(strcmp(s.name, "forkret") == 0)
263 sp += 2 * mach->szaddr; /* pop iret cs, eflags */
272 amd64trace(uvlong pc, uvlong sp, uvlong link)
282 while(findsym(pc, CTEXT, &s)) {
284 symoff(buf, sizeof buf, pc, CANY);
287 if(strcmp(s.name, "_intrr") == 0)
291 if(pc != s.value) { /* not at first instruction */
292 if(findlocal(&s, FRAMENAME, &f) == 0)
294 sp += f.value-mach->szaddr;
297 print("//passing interrupt frame; last pc found at sp=%#llux\n", osp);
299 * Pop interrupt frame (ureg.h) up to the IP value.
301 sp += 19 * mach->szaddr;
305 if(pc == 0 && isintrr){
307 * Pop IP, CS and FLAGS to get to the SP.
308 * The AMD64 aligns the interrupt stack on
309 * a 16-byte boundary so have the get the
310 * SP from the saved frame.
312 sp += 3 * mach->szaddr;
313 print("//guessing call through invalid pointer; try again at sp=%#llux\n", sp);
319 print("//didn't find pc at sp=%#llux, last pc found at sp=%#llux\n", sp, osp);
338 putval(uvlong a, uvlong v)
340 if(naddr < nelem(addr)){
356 while(p=Brdline(&b, '\n')){
357 p[Blinelen(&b)-1] = 0;
358 nf = tokenize(p, f, nelem(f));
360 if(p=strchr(f[i], '=')){
362 putval(strtoull(f[i], 0, 16), strtoull(p, 0, 16));
376 print("// data at %#8.8llux? ", a);
377 n = read(0, buf, sizeof(buf)-1);
381 r = strtoull(buf, 0, 16);
386 m = 0xffffffff00000000ULL;
391 for(i=0; i<naddr; i++)
397 r = (long)r; // sign extend
406 fatal(char *fmt, ...)
412 vseprint(buf, buf+sizeof(buf), fmt, arg);
414 fprint(2, "ktrace: %s\n", buf);