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 cp = nextc(cp); 192 switch(*cp) { 193 default: 194 Bprint(bioout, "?\n"); 195 break; 196 197 case 'c': 198 stktrace(*cp); 199 break; 200 201 case 'C': 202 stktrace(*cp); 203 break; 204 205 case 'b': 206 dobplist(); 207 break; 208 209 case 'r': 210 dumpreg(); 211 break; 212 213 case 'R': 214 dumpreg(); 215 216 case 'f': 217 dumpfreg(); 218 break; 219 220 case 'F': 221 dumpdreg(); 222 break; 223 224 case 'q': 225 exits(0); 226 break; 227 228 case 'Q': 229 isum(); 230 tlbsum(); 231 segsum(); 232 break; 233 234 case 't': 235 cp++; 236 switch(*cp) { 237 default: 238 Bprint(bioout, ":t[0sic]\n"); 239 break; 240 case '\0': 241 trace = 1; 242 break; 243 case '0': 244 trace = 0; 245 sysdbg = 0; 246 calltree = 0; 247 break; 248 case 's': 249 sysdbg = 1; 250 break; 251 case 'i': 252 trace = 1; 253 break; 254 case 'c': 255 calltree = 1; 256 break; 257 } 258 break; 259 260 case 'i': 261 cp++; 262 switch(*cp) { 263 default: 264 Bprint(bioout, "$i[itsa]\n"); 265 break; 266 case 'i': 267 isum(); 268 break; 269 case 't': 270 tlbsum(); 271 break; 272 case 's': 273 segsum(); 274 break; 275 case 'a': 276 isum(); 277 tlbsum(); 278 segsum(); 279 iprofile(); 280 break; 281 case 'p': 282 iprofile(); 283 break; 284 } 285 } 286 } 287 288 int 289 pfmt(char fmt, int mem, ulong val) 290 { 291 int c, i; 292 Symbol s; 293 char *p, ch, str[1024]; 294 295 c = 0; 296 switch(fmt) { 297 default: 298 Bprint(bioout, "bad modifier\n"); 299 return 0; 300 case 'o': 301 c = Bprint(bioout, "%-4o ", mem ? (ushort)getmem_2(dot) : val); 302 inc = 2; 303 break; 304 305 case 'O': 306 c = Bprint(bioout, "%-8o ", mem ? getmem_4(dot) : val); 307 inc = 4; 308 break; 309 310 case 'q': 311 c = Bprint(bioout, "%-4o ", mem ? (short)getmem_2(dot) : val); 312 inc = 2; 313 break; 314 315 case 'Q': 316 c = Bprint(bioout, "%-8o ", mem ? (long)getmem_4(dot) : val); 317 inc = 4; 318 break; 319 320 case 'd': 321 c = Bprint(bioout, "%-5ld ", mem ? (short)getmem_2(dot) : val); 322 inc = 2; 323 break; 324 325 326 case 'D': 327 c = Bprint(bioout, "%-8ld ", mem ? (long)getmem_4(dot) : val); 328 inc = 4; 329 break; 330 331 case 'x': 332 c = Bprint(bioout, "#%-4lux ", mem ? (long)getmem_2(dot) : val); 333 inc = 2; 334 break; 335 336 case 'X': 337 c = Bprint(bioout, "#%-8lux ", mem ? (long)getmem_4(dot) : val); 338 inc = 4; 339 break; 340 341 case 'u': 342 c = Bprint(bioout, "%-5ld ", mem ? (ushort)getmem_2(dot) : val); 343 inc = 2; 344 break; 345 346 case 'U': 347 c = Bprint(bioout, "%-8ld ", mem ? (ulong)getmem_4(dot) : val); 348 inc = 4; 349 break; 350 351 case 'b': 352 c = Bprint(bioout, "%-3d ", mem ? getmem_b(dot) : val); 353 inc = 1; 354 break; 355 356 case 'c': 357 c = Bprint(bioout, "%c ", mem ? getmem_b(dot) : val); 358 inc = 1; 359 break; 360 361 case 'C': 362 ch = mem ? getmem_b(dot) : val; 363 if(isprint(ch)) 364 c = Bprint(bioout, "%c ", ch); 365 else 366 c = Bprint(bioout, "\\x%.2x ", ch); 367 inc = 1; 368 break; 369 370 case 's': 371 i = 0; 372 while(ch = getmem_b(dot+i)) 373 str[i++] = ch; 374 str[i] = '\0'; 375 dot += i; 376 c = Bprint(bioout, "%s", str); 377 inc = 0; 378 break; 379 380 case 'S': 381 i = 0; 382 while(ch = getmem_b(dot+i)) 383 str[i++] = ch; 384 str[i] = '\0'; 385 dot += i; 386 for(p = str; *p; p++) 387 if(isprint(*p)) 388 c += Bprint(bioout, "%c", *p); 389 else 390 c += Bprint(bioout, "\\x%.2lux", *p); 391 inc = 0; 392 break; 393 394 case 'Y': 395 p = ctime(mem ? getmem_b(dot) : val); 396 p[30] = '\0'; 397 c = Bprint(bioout, "%s", p); 398 inc = 4; 399 break; 400 401 case 'a': 402 symoff(str, sizeof(str), dot, CTEXT); 403 c = Bprint(bioout, str); 404 inc = 0; 405 break; 406 407 case 'e': 408 for (i = 0; globalsym(&s, i); i++) 409 Bprint(bioout, "%-15s #%lux\n", s.name, getmem_4(s.value)); 410 inc = 0; 411 break; 412 413 case 'i': 414 inc = _mipscoinst(symmap, dot, str, sizeof(str)); 415 if (inc < 0) { 416 Bprint(bioout, "vi: %r\n"); 417 return 0; 418 } 419 c = Bprint(bioout, 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 USED(a); 519 if(strcmp(msg, "interrupt") != 0) 520 noted(NDFLT); 521 522 count = 1; 523 print("vi\n"); 524 noted(NCONT); 525 } 526 527 void 528 setreg(char *addr, char *cp) 529 { 530 int rn; 531 532 dot = expr(addr); 533 cp = nextc(cp); 534 if(strcmp(cp, "pc") == 0) { 535 reg.pc = dot; 536 return; 537 } 538 if(strcmp(cp, "sp") == 0) { 539 reg.r[29] = dot; 540 return; 541 } 542 if(strcmp(cp, "mh") == 0) { 543 reg.mhi = dot; 544 return; 545 } 546 if(strcmp(cp, "ml") == 0) { 547 reg.mlo = dot; 548 return; 549 } 550 if(*cp++ == 'r') { 551 rn = strtoul(cp, 0, 10); 552 if(rn > 0 && rn < 32) { 553 reg.r[rn] = dot; 554 return; 555 } 556 } 557 Bprint(bioout, "bad register\n"); 558 } 559 560 void 561 cmd(void) 562 { 563 char *p, *a, *cp, *gotint; 564 char addr[128]; 565 static char *cmdlet = ":$?/=>"; 566 int n, i; 567 568 notify(catcher); 569 570 dot = reg.pc; 571 setjmp(errjmp); 572 573 for(;;) { 574 Bflush(bioout); 575 p = buf; 576 n = 0; 577 for(;;) { 578 i = Bgetc(bin); 579 if(i < 0) 580 exits(0); 581 *p++ = i; 582 n++; 583 if(i == '\n') 584 break; 585 } 586 587 if(buf[0] == '\n') 588 strcpy(buf, lastcmd); 589 else { 590 buf[n-1] = '\0'; 591 strcpy(lastcmd, buf); 592 } 593 p = buf; 594 a = addr; 595 596 for(;;) { 597 p = nextc(p); 598 if(*p == 0 || strchr(cmdlet, *p)) 599 break; 600 *a++ = *p++; 601 } 602 603 *a = '\0'; 604 cmdcount = 1; 605 cp = strchr(addr, ','); 606 if(cp != 0) { 607 if(cp[1] == '#') 608 cmdcount = strtoul(cp+2, &gotint, 16); 609 else 610 cmdcount = strtoul(cp+1, &gotint, 0); 611 *cp = '\0'; 612 } 613 614 switch(*p) { 615 case '$': 616 dollar(p+1); 617 break; 618 case ':': 619 colon(addr, p+1); 620 break; 621 case '/': 622 case '?': 623 dot = expr(addr); 624 for(i = 0; i < cmdcount; i++) 625 quesie(p+1); 626 break; 627 case '=': 628 eval(addr, p+1); 629 break; 630 case '>': 631 setreg(addr, p+1); 632 break; 633 default: 634 Bprint(bioout, "?\n"); 635 break; 636 } 637 } 638 } 639