1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <mach.h> 5 #include <ctype.h> 6 7 static int rtrace(ulong, ulong, ulong); 8 static int ctrace(ulong, ulong, ulong); 9 static int i386trace(ulong, ulong, ulong); 10 static ulong getval(ulong); 11 static void inithdr(int); 12 static void fatal(char*, ...); 13 static void readstack(void); 14 15 static Fhdr fhdr; 16 static int interactive; 17 18 #define FRAMENAME ".frame" 19 20 static void 21 usage(void) 22 { 23 fprint(2, "usage: ktrace [-i] kernel pc sp [link]\n"); 24 exits("usage"); 25 } 26 27 static void 28 printaddr(char *addr, ulong pc) 29 { 30 int i; 31 char *p; 32 33 /* 34 * reformat the following. 35 * 36 * foo+1a1 -> src(foo+0x1a1); 37 * 10101010 -> src(0x10101010); 38 */ 39 40 if(strlen(addr) == 8 && strchr(addr, '+') == nil){ 41 for(i=0; i<8; i++) 42 if(!isxdigit(addr[i])) 43 break; 44 if(i == 8){ 45 print("src(0x%.8lux); // 0x%s\n", pc, addr); 46 return; 47 } 48 } 49 50 if(p=strchr(addr, '+')){ 51 *p++ = 0; 52 print("src(0x%.8lux); // %s+0x%s\n", pc, addr, p); 53 }else 54 print("src(0x%.8lux); // %s\n", pc, addr); 55 } 56 57 static void (*fmt)(char*, ulong) = printaddr; 58 59 void 60 main(int argc, char *argv[]) 61 { 62 int (*t)(ulong, ulong, ulong); 63 ulong pc, sp, link; 64 int fd; 65 66 ARGBEGIN{ 67 case 'i': 68 interactive++; 69 break; 70 default: 71 usage(); 72 }ARGEND 73 74 link = 0; 75 t = ctrace; 76 switch(argc){ 77 case 4: 78 t = rtrace; 79 link = strtoul(argv[3], 0, 16); 80 break; 81 case 3: 82 break; 83 default: 84 usage(); 85 } 86 pc = strtoul(argv[1], 0, 16); 87 sp = strtoul(argv[2], 0, 16); 88 if(!interactive) 89 readstack(); 90 91 fd = open(argv[0], OREAD); 92 if(fd < 0) 93 fatal("can't open %s: %r", argv[0]); 94 inithdr(fd); 95 switch(fhdr.magic){ 96 case I_MAGIC: /* intel 386 */ 97 t = i386trace; 98 break; 99 case A_MAGIC: /* 68020 */ 100 case J_MAGIC: /* intel 960 */ 101 t = ctrace; 102 break; 103 case K_MAGIC: /* sparc */ 104 case D_MAGIC: /* amd 29000 */ 105 case V_MAGIC: /* mips 3000 */ 106 case M_MAGIC: /* mips 4000 */ 107 case E_MAGIC: /* arm 7-something */ 108 case Q_MAGIC: /* powerpc */ 109 case N_MAGIC: /* mips 4000 LE */ 110 case L_MAGIC: /* dec alpha */ 111 t = rtrace; 112 break; 113 case X_MAGIC: /* att dsp 3210 */ 114 sysfatal("can't ktrace %s\n", argv[0]); 115 break; 116 default: 117 fprint(2, "%s: warning: can't tell what type of stack %s uses; assuming it's %s\n", 118 argv0, argv[0], argc == 4 ? "risc" : "cisc"); 119 break; 120 } 121 (*t)(pc, sp, link); 122 exits(0); 123 } 124 125 static void 126 inithdr(int fd) 127 { 128 seek(fd, 0, 0); 129 if(!crackhdr(fd, &fhdr)) 130 fatal("read text header"); 131 132 if(syminit(fd, &fhdr) < 0) 133 fatal("%r\n"); 134 } 135 136 static int 137 rtrace(ulong pc, ulong sp, ulong link) 138 { 139 Symbol s, f; 140 char buf[128]; 141 ulong oldpc; 142 int i; 143 144 i = 0; 145 while(findsym(pc, CTEXT, &s)) { 146 if(pc == s.value) /* at first instruction */ 147 f.value = 0; 148 else if(findlocal(&s, FRAMENAME, &f) == 0) 149 break; 150 151 symoff(buf, sizeof buf, pc, CANY); 152 fmt(buf, pc); 153 154 oldpc = pc; 155 if(s.type == 'L' || s.type == 'l' || pc <= s.value+mach->pcquant){ 156 if(link == 0) 157 fprint(2, "%s: need to supply a valid link register\n", argv0); 158 pc = link; 159 }else{ 160 pc = getval(sp); 161 if(pc == 0) 162 break; 163 } 164 165 if(pc == 0 || (pc == oldpc && f.value == 0)) 166 break; 167 168 sp += f.value; 169 170 if(++i > 40) 171 break; 172 } 173 return i; 174 } 175 176 static int 177 ctrace(ulong pc, ulong sp, ulong link) 178 { 179 Symbol s; 180 char buf[128]; 181 int found; 182 ulong opc; 183 long moved, j; 184 185 USED(link); 186 j = 0; 187 opc = 0; 188 while(pc && opc != pc) { 189 moved = pc2sp(pc); 190 if (moved == -1){ 191 print("pc2sp(%.8lux) = -1 %r\n", pc); 192 break; 193 } 194 found = findsym(pc, CTEXT, &s); 195 if (!found){ 196 print("findsym fails\n"); 197 break; 198 } 199 symoff(buf, sizeof buf, pc, CANY); 200 fmt(buf, pc); 201 202 sp += moved; 203 opc = pc; 204 pc = getval(sp); 205 if(pc == 0) 206 break; 207 sp += mach->szaddr; /*assumes address size = stack width*/ 208 if(++j > 40) 209 break; 210 } 211 return j; 212 } 213 214 static int 215 i386trace(ulong pc, ulong sp, ulong link) 216 { 217 int i; 218 ulong osp; 219 Symbol s, f; 220 char buf[128]; 221 222 USED(link); 223 i = 0; 224 osp = 0; 225 while(findsym(pc, CTEXT, &s)) { 226 227 symoff(buf, sizeof buf, pc, CANY); 228 fmt(buf, pc); 229 230 if(pc != s.value) { /* not at first instruction */ 231 if(findlocal(&s, FRAMENAME, &f) == 0) 232 break; 233 sp += f.value-mach->szaddr; 234 }else if(strcmp(s.name, "forkret") == 0){ 235 print("//passing interrupt frame; last pc found at sp=%lux\n", osp); 236 sp += 15 * mach->szaddr; /* pop interrupt frame */ 237 } 238 239 pc = getval(sp); 240 if(pc == 0 && strcmp(s.name, "forkret") == 0){ 241 sp += 3 * mach->szaddr; /* pop iret eip, cs, eflags */ 242 print("//guessing call through invalid pointer, try again at sp=%lux\n", sp); 243 s.name = ""; 244 pc = getval(sp); 245 } 246 if(pc == 0) { 247 print("//didn't find pc at sp=%lux, last pc found at sp=%lux\n", sp, osp); 248 break; 249 } 250 osp = sp; 251 252 sp += mach->szaddr; 253 if(strcmp(s.name, "forkret") == 0) 254 sp += 2 * mach->szaddr; /* pop iret cs, eflags */ 255 256 if(++i > 40) 257 break; 258 } 259 return i; 260 } 261 262 int naddr; 263 ulong addr[1024]; 264 ulong val[1024]; 265 266 static void 267 putval(ulong a, ulong v) 268 { 269 if(naddr < nelem(addr)){ 270 addr[naddr] = a; 271 val[naddr] = v; 272 naddr++; 273 } 274 } 275 276 static void 277 readstack(void) 278 { 279 Biobuf b; 280 char *p; 281 char *f[64]; 282 int nf, i; 283 284 Binit(&b, 0, OREAD); 285 while(p=Brdline(&b, '\n')){ 286 p[Blinelen(&b)-1] = 0; 287 nf = tokenize(p, f, nelem(f)); 288 for(i=0; i<nf; i++){ 289 if(p=strchr(f[i], '=')){ 290 *p++ = 0; 291 putval(strtoul(f[i], 0, 16), strtoul(p, 0, 16)); 292 } 293 } 294 } 295 } 296 297 static ulong 298 getval(ulong a) 299 { 300 char buf[256]; 301 int i, n; 302 303 if(interactive){ 304 print("// data at 0x%8.8lux? ", a); 305 n = read(0, buf, sizeof(buf)-1); 306 if(n <= 0) 307 return 0; 308 buf[n] = '\0'; 309 return strtoul(buf, 0, 16); 310 }else{ 311 for(i=0; i<naddr; i++) 312 if(addr[i] == a) 313 return val[i]; 314 return 0; 315 } 316 } 317 318 static void 319 fatal(char *fmt, ...) 320 { 321 char buf[4096]; 322 va_list arg; 323 324 va_start(arg, fmt); 325 vseprint(buf, buf+sizeof(buf), fmt, arg); 326 va_end(arg); 327 fprint(2, "ktrace: %s\n", buf); 328 exits(buf); 329 } 330