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 R_MAGIC: /* arm64 */
113 case Q_MAGIC: /* powerpc */
114 case N_MAGIC: /* mips 4000 LE */
115 case L_MAGIC: /* dec alpha */
118 case X_MAGIC: /* att dsp 3210 */
119 sysfatal("can't ktrace %s", argv[0]);
122 fprint(2, "%s: warning: can't tell what type of stack %s uses; assuming it's %s\n",
123 argv0, argv[0], argc == 4 ? "risc" : "cisc");
134 if(!crackhdr(fd, &fhdr))
135 fatal("read text header");
137 if(syminit(fd, &fhdr) < 0)
142 rtrace(uvlong pc, uvlong sp, uvlong link)
150 while(findsym(pc, CTEXT, &s)) {
151 if(pc == s.value) /* at first instruction */
153 else if(findlocal(&s, FRAMENAME, &f) == 0)
156 symoff(buf, sizeof buf, pc, CANY);
160 if(s.type == 'L' || s.type == 'l' || pc <= s.value+mach->pcquant){
162 fprint(2, "%s: need to supply a valid link register\n", argv0);
170 if(pc == 0 || (pc == oldpc && f.value == 0))
182 ctrace(uvlong pc, uvlong sp, uvlong link)
193 while(pc && opc != pc) {
196 print("pc2sp(%#.8llux) = -1 %r\n", pc);
199 found = findsym(pc, CTEXT, &s);
201 print("findsym fails\n");
204 symoff(buf, sizeof buf, pc, CANY);
212 sp += mach->szaddr; /*assumes address size = stack width*/
220 i386trace(uvlong pc, uvlong sp, uvlong link)
230 while(findsym(pc, CTEXT, &s)) {
232 symoff(buf, sizeof buf, pc, CANY);
235 //XXX s.value &= ~(uintptr)0;
236 if(pc != s.value) { /* not at first instruction */
237 if(findlocal(&s, FRAMENAME, &f) == 0)
239 sp += f.value-mach->szaddr;
240 }else if(strcmp(s.name, "forkret") == 0){
242 print("//passing interrupt frame; last pc found at sp=%#llux\n", osp);
244 sp += 15 * mach->szaddr; /* pop interrupt frame */
249 if(pc == 0 && strcmp(s.name, "forkret") == 0){
250 sp += 3 * mach->szaddr; /* pop iret eip, cs, eflags */
251 print("//guessing call through invalid pointer, try again at sp=%#llux\n", sp);
256 print("//didn't find pc at sp=%#llux, last pc found at sp=%#llux\n", sp, osp);
263 if(strcmp(s.name, "forkret") == 0)
264 sp += 2 * mach->szaddr; /* pop iret cs, eflags */
273 amd64trace(uvlong pc, uvlong sp, uvlong link)
283 while(findsym(pc, CTEXT, &s)) {
285 symoff(buf, sizeof buf, pc, CANY);
288 if(strcmp(s.name, "_intrr") == 0)
292 if(pc != s.value) { /* not at first instruction */
293 if(findlocal(&s, FRAMENAME, &f) == 0)
295 sp += f.value-mach->szaddr;
298 print("//passing interrupt frame; last pc found at sp=%#llux\n", osp);
300 * Pop interrupt frame (ureg.h) up to the IP value.
302 sp += 19 * mach->szaddr;
306 if(pc == 0 && isintrr){
308 * Pop IP, CS and FLAGS to get to the SP.
309 * The AMD64 aligns the interrupt stack on
310 * a 16-byte boundary so have the get the
311 * SP from the saved frame.
313 sp += 3 * mach->szaddr;
314 print("//guessing call through invalid pointer; try again at sp=%#llux\n", sp);
320 print("//didn't find pc at sp=%#llux, last pc found at sp=%#llux\n", sp, osp);
339 putval(uvlong a, uvlong v)
341 if(naddr < nelem(addr)){
357 while(p=Brdline(&b, '\n')){
358 p[Blinelen(&b)-1] = 0;
359 nf = tokenize(p, f, nelem(f));
361 if(p=strchr(f[i], '=')){
363 putval(strtoull(f[i], 0, 16), strtoull(p, 0, 16));
377 print("// data at %#8.8llux? ", a);
378 n = read(0, buf, sizeof(buf)-1);
382 r = strtoull(buf, 0, 16);
388 m = 0xffffffff00000000ULL;
393 for(i=0; i<naddr; i++)
400 r = (long)r; // sign extend
409 fatal(char *fmt, ...)
415 vseprint(buf, buf+sizeof(buf), fmt, arg);
417 fprint(2, "ktrace: %s\n", buf);