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