1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <mach.h> 5 #include <ctype.h> 6 #include "arm.h" 7 8 char buf[128], lastcmd[128]; 9 char fmt = 'X'; 10 int width = 60; 11 int inc; 12 13 ulong expr(char*); 14 ulong expr1(char*); 15 char* term(char*, ulong*); 16 17 char* 18 nextc(char *p) 19 { 20 while(*p && (*p == ' ' || *p == '\t') && *p != '\n') 21 p++; 22 23 if(*p == '\n') 24 *p = '\0'; 25 26 return p; 27 } 28 29 char* 30 numsym(char *addr, ulong *val) 31 { 32 char tsym[128], *t; 33 static char *delim = "`'<>/\\@*|-~+-/=?\n"; 34 Symbol s; 35 char c; 36 37 t = tsym; 38 while(c = *addr) { 39 if(strchr(delim, c)) 40 break; 41 *t++ = c; 42 addr++; 43 } 44 t[0] = '\0'; 45 46 if(strcmp(tsym, ".") == 0) { 47 *val = dot; 48 return addr; 49 } 50 51 if(lookup(0, tsym, &s)) 52 *val = s.value; 53 else { 54 if(tsym[0] == '#') 55 *val = strtoul(tsym+1, 0, 16); 56 else 57 *val = strtoul(tsym, 0, 0); 58 } 59 return addr; 60 } 61 62 ulong 63 expr(char *addr) 64 { 65 ulong t, t2; 66 char op; 67 68 if(*addr == '\0') 69 return dot; 70 71 addr = numsym(addr, &t); 72 73 if(*addr == '\0') 74 return t; 75 76 addr = nextc(addr); 77 op = *addr++; 78 numsym(addr, &t2); 79 switch(op) { 80 default: 81 Bprint(bioout, "expr syntax\n"); 82 return 0; 83 case '+': 84 t += t2; 85 break; 86 case '-': 87 t -= t2; 88 break; 89 case '%': 90 t /= t2; 91 break; 92 case '&': 93 t &= t2; 94 break; 95 case '|': 96 t |= t2; 97 break; 98 } 99 100 return t; 101 } 102 103 int 104 buildargv(char *str, char **args, int max) 105 { 106 int na = 0; 107 108 while (na < max) { 109 while((*str == ' ' || *str == '\t' || *str == '\n') && *str != '\0') 110 str++; 111 112 if(*str == '\0') 113 return na; 114 115 args[na++] = str; 116 while(!(*str == ' ' || *str == '\t'|| *str == '\n') && *str != '\0') 117 str++; 118 119 if(*str == '\n') 120 *str = '\0'; 121 122 if(*str == '\0') 123 break; 124 125 *str++ = '\0'; 126 } 127 return na; 128 } 129 130 void 131 colon(char *addr, char *cp) 132 { 133 int argc; 134 char *argv[100]; 135 char tbuf[512]; 136 137 cp = nextc(cp); 138 switch(*cp) { 139 default: 140 Bprint(bioout, "?\n"); 141 return; 142 case 'b': 143 breakpoint(addr, cp+1); 144 return; 145 146 case 'd': 147 delbpt(addr); 148 return; 149 150 /* These fall through to print the stopped address */ 151 case 'r': 152 reset(); 153 argc = buildargv(cp+1, argv, 100); 154 initstk(argc, argv); 155 count = 0; 156 atbpt = 0; 157 run(); 158 break; 159 case 'c': 160 count = 0; 161 atbpt = 0; 162 run(); 163 break; 164 case 's': 165 cp = nextc(cp+1); 166 count = 0; 167 if(*cp) 168 count = strtoul(cp, 0, 0); 169 if(count == 0) 170 count = 1; 171 atbpt = 0; 172 run(); 173 break; 174 } 175 176 dot = reg.r[15]; 177 Bprint(bioout, "%s at #%lux ", atbpt? "breakpoint": "stopped", dot); 178 symoff(tbuf, sizeof(tbuf), dot, CTEXT); 179 Bprint(bioout, tbuf); 180 if(fmt == 'z') 181 printsource(dot); 182 183 Bprint(bioout, "\n"); 184 } 185 186 187 void 188 dollar(char *cp) 189 { 190 cp = nextc(cp); 191 switch(*cp) { 192 default: 193 Bprint(bioout, "?\n"); 194 break; 195 196 case 'c': 197 stktrace(*cp); 198 break; 199 200 case 'C': 201 stktrace(*cp); 202 break; 203 204 case 'b': 205 dobplist(); 206 break; 207 208 case 'r': 209 dumpreg(); 210 break; 211 212 case 'R': 213 dumpreg(); 214 215 case 'f': 216 dumpfreg(); 217 break; 218 219 case 'F': 220 dumpdreg(); 221 break; 222 223 case 'q': 224 exits(0); 225 break; 226 227 case 'Q': 228 isum(); 229 tlbsum(); 230 segsum(); 231 break; 232 233 case 't': 234 cp++; 235 switch(*cp) { 236 default: 237 Bprint(bioout, ":t[0sic]\n"); 238 break; 239 case '\0': 240 trace = 1; 241 break; 242 case '0': 243 trace = 0; 244 sysdbg = 0; 245 calltree = 0; 246 break; 247 case 's': 248 sysdbg = 1; 249 break; 250 case 'i': 251 trace = 1; 252 break; 253 case 'c': 254 calltree = 1; 255 break; 256 } 257 break; 258 259 case 'i': 260 cp++; 261 switch(*cp) { 262 default: 263 Bprint(bioout, "$i[itsa]\n"); 264 break; 265 case 'i': 266 isum(); 267 break; 268 case 't': 269 tlbsum(); 270 break; 271 case 's': 272 segsum(); 273 break; 274 case 'a': 275 isum(); 276 tlbsum(); 277 segsum(); 278 iprofile(); 279 break; 280 case 'p': 281 iprofile(); 282 break; 283 } 284 } 285 } 286 287 int 288 pfmt(char fmt, int mem, ulong val) 289 { 290 int c, i; 291 Symbol s; 292 char *p, ch, str[1024]; 293 294 c = 0; 295 switch(fmt) { 296 default: 297 Bprint(bioout, "bad modifier\n"); 298 return 0; 299 case 'o': 300 c = Bprint(bioout, "%-4lo ", mem? (ushort)getmem_2(dot): val); 301 inc = 2; 302 break; 303 304 case 'O': 305 c = Bprint(bioout, "%-8lo ", mem? getmem_4(dot): val); 306 inc = 4; 307 break; 308 309 case 'q': 310 c = Bprint(bioout, "%-4lo ", mem? (short)getmem_2(dot): val); 311 inc = 2; 312 break; 313 314 case 'Q': 315 c = Bprint(bioout, "%-8lo ", mem? (long)getmem_4(dot): val); 316 inc = 4; 317 break; 318 319 case 'd': 320 c = Bprint(bioout, "%-5ld ", mem? (short)getmem_2(dot): val); 321 inc = 2; 322 break; 323 324 325 case 'D': 326 c = Bprint(bioout, "%-8ld ", mem? (long)getmem_4(dot): val); 327 inc = 4; 328 break; 329 330 case 'x': 331 c = Bprint(bioout, "#%-4lux ", mem? (long)getmem_2(dot): val); 332 inc = 2; 333 break; 334 335 case 'X': 336 c = Bprint(bioout, "#%-8lux ", mem? (long)getmem_4(dot): val); 337 inc = 4; 338 break; 339 340 case 'u': 341 c = Bprint(bioout, "%-5ld ", mem? (ushort)getmem_2(dot): val); 342 inc = 2; 343 break; 344 345 case 'U': 346 c = Bprint(bioout, "%-8ld ", mem? (ulong)getmem_4(dot): val); 347 inc = 4; 348 break; 349 350 case 'b': 351 c = Bprint(bioout, "%-3ld ", mem? getmem_b(dot): val); 352 inc = 1; 353 break; 354 355 case 'c': 356 c = Bprint(bioout, "%c ", (int)(mem? getmem_b(dot): val)); 357 inc = 1; 358 break; 359 360 case 'C': 361 ch = mem? getmem_b(dot): val; 362 if(isprint(ch)) 363 c = Bprint(bioout, "%c ", ch); 364 else 365 c = Bprint(bioout, "\\x%.2x ", ch); 366 inc = 1; 367 break; 368 369 case 's': 370 i = 0; 371 while(ch = getmem_b(dot+i)) 372 str[i++] = ch; 373 str[i] = '\0'; 374 dot += i; 375 c = Bprint(bioout, "%s", str); 376 inc = 0; 377 break; 378 379 case 'S': 380 i = 0; 381 while(ch = getmem_b(dot+i)) 382 str[i++] = ch; 383 str[i] = '\0'; 384 dot += i; 385 for(p = str; *p; p++) 386 if(isprint(*p)) 387 c += Bprint(bioout, "%c", *p); 388 else 389 c += Bprint(bioout, "\\x%.2ux", *p); 390 inc = 0; 391 break; 392 393 case 'Y': 394 p = ctime(mem? getmem_b(dot): val); 395 p[30] = '\0'; 396 c = Bprint(bioout, "%s", p); 397 inc = 4; 398 break; 399 400 case 'a': 401 symoff(str, sizeof(str), dot, CTEXT); 402 c = Bprint(bioout, str); 403 inc = 0; 404 break; 405 406 case 'e': 407 for(i = 0; globalsym(&s, i); i++) 408 Bprint(bioout, "%-15s #%lux\n", s.name, getmem_4(s.value)); 409 inc = 0; 410 break; 411 412 case 'I': 413 case 'i': 414 inc = machdata->das(symmap, dot, fmt, str, sizeof(str)); 415 if(inc < 0) { 416 Bprint(bioout, "5i: %r\n"); 417 return 0; 418 } 419 c = Bprint(bioout, "\t%s", str); 420 break; 421 422 case 'n': 423 c = width+1; 424 inc = 0; 425 break; 426 427 case '-': 428 c = 0; 429 inc = -1; 430 break; 431 432 case '+': 433 c = 0; 434 inc = 1; 435 break; 436 437 case '^': 438 c = 0; 439 if(inc > 0) 440 inc = -inc; 441 break; 442 443 case 'z': 444 if(findsym(dot, CTEXT, &s)) 445 Bprint(bioout, " %s() ", s.name); 446 printsource(dot); 447 inc = 0; 448 break; 449 } 450 return c; 451 } 452 453 void 454 eval(char *addr, char *p) 455 { 456 ulong val; 457 458 val = expr(addr); 459 p = nextc(p); 460 if(*p == '\0') { 461 p[0] = fmt; 462 p[1] = '\0'; 463 } 464 pfmt(*p, 0, val); 465 Bprint(bioout, "\n"); 466 } 467 468 void 469 quesie(char *p) 470 { 471 int c, count, i; 472 char tbuf[512]; 473 474 c = 0; 475 symoff(tbuf, sizeof(tbuf), dot, CTEXT); 476 Bprint(bioout, "%s?\t", tbuf); 477 478 while(*p) { 479 p = nextc(p); 480 if(*p == '"') { 481 for(p++; *p && *p != '"'; p++) { 482 Bputc(bioout, *p); 483 c++; 484 } 485 if(*p) 486 p++; 487 continue; 488 } 489 count = 0; 490 while(*p >= '0' && *p <= '9') 491 count = count*10 + (*p++ - '0'); 492 if(count == 0) 493 count = 1; 494 p = nextc(p); 495 if(*p == '\0') { 496 p[0] = fmt; 497 p[1] = '\0'; 498 } 499 for(i = 0; i < count; i++) { 500 c += pfmt(*p, 1, 0); 501 dot += inc; 502 if(c > width) { 503 Bprint(bioout, "\n"); 504 symoff(tbuf, sizeof(tbuf), dot, CTEXT); 505 Bprint(bioout, "%s?\t", tbuf); 506 c = 0; 507 } 508 } 509 fmt = *p++; 510 p = nextc(p); 511 } 512 Bprint(bioout, "\n"); 513 } 514 515 void 516 catcher(void *a, char *msg) 517 { 518 static int hit = 0; 519 520 hit++; 521 if(hit > 5) 522 exits(0); 523 USED(a); 524 if(strcmp(msg, "interrupt") != 0) 525 noted(NDFLT); 526 527 count = 1; 528 print("5i\n"); 529 noted(NCONT); 530 } 531 532 void 533 setreg(char *addr, char *cp) 534 { 535 int rn; 536 537 dot = expr(addr); 538 cp = nextc(cp); 539 if(strcmp(cp, "pc") == 0) { 540 reg.r[15] = dot; 541 return; 542 } 543 if(strcmp(cp, "sp") == 0) { 544 reg.r[13] = dot; 545 return; 546 } 547 if(*cp++ == 'r') { 548 rn = strtoul(cp, 0, 10); 549 if(rn > 0 && rn < 16) { 550 reg.r[rn] = dot; 551 return; 552 } 553 } 554 Bprint(bioout, "bad register\n"); 555 } 556 557 void 558 cmd(void) 559 { 560 char *p, *a, *cp, *gotint; 561 char addr[128]; 562 static char *cmdlet = ":$?/=>"; 563 int n, i; 564 565 notify(catcher); 566 567 dot = reg.r[15]; 568 setjmp(errjmp); 569 570 for(;;) { 571 Bflush(bioout); 572 p = buf; 573 n = 0; 574 for(;;) { 575 i = Bgetc(bin); 576 if(i < 0) 577 exits(0); 578 *p++ = i; 579 n++; 580 if(i == '\n') 581 break; 582 } 583 584 if(buf[0] == '\n') 585 strcpy(buf, lastcmd); 586 else { 587 buf[n-1] = '\0'; 588 strcpy(lastcmd, buf); 589 } 590 p = buf; 591 a = addr; 592 593 for(;;) { 594 p = nextc(p); 595 if(*p == 0 || strchr(cmdlet, *p)) 596 break; 597 *a++ = *p++; 598 } 599 600 *a = '\0'; 601 cmdcount = 1; 602 cp = strchr(addr, ','); 603 if(cp != 0) { 604 if(cp[1] == '#') 605 cmdcount = strtoul(cp+2, &gotint, 16); 606 else 607 cmdcount = strtoul(cp+1, &gotint, 0); 608 *cp = '\0'; 609 } 610 611 switch(*p) { 612 case '$': 613 dollar(p+1); 614 break; 615 case ':': 616 colon(addr, p+1); 617 break; 618 case '/': 619 case '?': 620 dot = expr(addr); 621 for(i = 0; i < cmdcount; i++) 622 quesie(p+1); 623 break; 624 case '=': 625 eval(addr, p+1); 626 break; 627 case '>': 628 setreg(addr, p+1); 629 break; 630 default: 631 Bprint(bioout, "?\n"); 632 break; 633 } 634 } 635 } 636