1 /*#include <u.h>*/ 2 #include <lib9.h> 3 #include <bio.h> 4 #include "mach.h" 5 #define Extern 6 #include "acid.h" 7 #include "y.tab.h" 8 9 char *argv0; 10 char *acidlib; 11 static Biobuf bioout; 12 static char prog[128]; 13 static char* lm[16]; 14 static int nlm; 15 static char* mtype; 16 17 static int attachfiles(char*, int); 18 int xfmt(Fmt*); 19 extern int gfltconv(Fmt*), _ifmt(Fmt*); 20 int isnumeric(char*); 21 void die(void); 22 23 void 24 usage(void) 25 { 26 fprint(2, "usage: acid [-l module] [-m machine] [-qrw] [-k] [-d flag] [-R tty] [pid] [file]\n"); 27 exits("usage"); 28 } 29 30 void 31 main(int argc, char *argv[]) 32 { 33 Dir *db; 34 Lsym *l; 35 Node *n; 36 char buf[128], *s; 37 int pid, i; 38 char *p; 39 char afile[512]; 40 41 argv0 = argv[0]; 42 pid = 0; 43 aout = "v.out"; 44 quiet = 1; 45 /* turn off all debugging */ 46 protodebug = 0; 47 48 mtype = 0; 49 ARGBEGIN{ 50 case 'm': 51 mtype = ARGF(); 52 break; 53 case 'w': 54 wtflag = 1; 55 break; 56 case 'l': 57 s = ARGF(); 58 if(s == 0) 59 usage(); 60 lm[nlm++] = s; 61 break; 62 case 'd': 63 p = ARGF(); 64 if (p == 0) 65 usage(); 66 while (*p) { 67 setdbg_opt(*p, 0); /* don't print set message */ 68 p++; 69 } 70 break; 71 case 'k': 72 kernel++; 73 break; 74 case 'q': 75 quiet = 0; 76 break; 77 case 'r': 78 pid = 1; 79 remote++; 80 kernel++; 81 break; 82 case 'R': 83 pid = 1; 84 rdebug++; 85 s = ARGF(); 86 if(s == 0) 87 usage(); 88 remfd = opentty(s, 0); 89 if(remfd < 0){ 90 fprint(2, "acid: can't open %s: %r\n", s); 91 exits("open"); 92 } 93 break; 94 default: 95 usage(); 96 }ARGEND 97 98 if(argc > 0) { 99 if(remote || rdebug) 100 aout = argv[0]; 101 else 102 if(isnumeric(argv[0])) { 103 pid = atoi(argv[0]); 104 sprint(prog, "/proc/%d/text", pid); 105 aout = prog; 106 if(argc > 1) 107 aout = argv[1]; 108 else if(kernel) 109 aout = mysystem(); 110 } 111 else { 112 if(kernel) { 113 print("-k requires a pid"); 114 kernel = 0; 115 } 116 aout = argv[0]; 117 } 118 } else if(rdebug) 119 aout = "/386/bpc"; 120 else if(remote) 121 aout = "/mips/bcarrera"; 122 123 fmtinstall('x', xfmt); 124 fmtinstall('L', Lfmt); 125 fmtinstall('f', gfltconv); 126 fmtinstall('F', gfltconv); 127 fmtinstall('g', gfltconv); 128 fmtinstall('G', gfltconv); 129 fmtinstall('e', gfltconv); 130 fmtinstall('E', gfltconv); 131 Binit(&bioout, 1, OWRITE); 132 bout = &bioout; 133 134 kinit(); 135 initialising = 1; 136 pushfile(0); 137 loadvars(); 138 installbuiltin(); 139 140 if(mtype && machbyname(mtype) == 0) 141 print("unknown machine %s", mtype); 142 143 if (attachfiles(aout, pid) < 0) 144 varreg(); /* use default register set on error */ 145 146 acidlib = getenv("ACIDLIB"); 147 if(acidlib == nil){ 148 p = getenv("ROOT"); 149 if(p == nil) 150 p = "/usr/inferno"; 151 snprint(afile, sizeof(afile)-1, "%s/lib/acid", p); 152 acidlib = strdup(afile); 153 } 154 155 snprint(afile, sizeof(afile)-1, "%s/port", acidlib); 156 loadmodule(afile); 157 for(i = 0; i < nlm; i++) { 158 if((db = dirstat(lm[i])) != nil) { 159 free(db); 160 loadmodule(lm[i]); 161 } else { 162 sprint(buf, "%s/%s", acidlib, lm[i]); 163 loadmodule(buf); 164 } 165 } 166 167 userinit(); 168 varsym(); 169 170 l = look("acidmap"); 171 if(l && l->proc) { 172 n = an(ONAME, ZN, ZN); 173 n->sym = l; 174 n = an(OCALL, n, ZN); 175 execute(n); 176 } 177 178 interactive = 1; 179 initialising = 0; 180 line = 1; 181 182 setup_os_notify(); 183 184 for(;;) { 185 if(setjmp(err)) { 186 Binit(&bioout, 1, OWRITE); 187 unwind(); 188 } 189 stacked = 0; 190 191 Bprint(bout, "acid: "); 192 193 if(yyparse() != 1) 194 die(); 195 restartio(); 196 197 unwind(); 198 } 199 /* not reached */ 200 } 201 202 static int 203 attachfiles(char *aout, int pid) 204 { 205 interactive = 0; 206 if(setjmp(err)) 207 return -1; 208 209 if(aout) { /* executable given */ 210 if(wtflag) 211 text = open(aout, ORDWR); 212 else 213 text = open(aout, OREAD); 214 215 if(text < 0) 216 error("%s: can't open %s: %r\n", argv0, aout); 217 readtext(aout); 218 } 219 if(pid) /* pid given */ 220 sproc(pid); 221 return 0; 222 } 223 224 void 225 die(void) 226 { 227 Lsym *s; 228 List *f; 229 230 Bprint(bout, "\n"); 231 232 s = look("proclist"); 233 if(!rdebug && s && s->v->type == TLIST) { 234 for(f = s->v->vstore.u0.sl; f; f = f->next) 235 Bprint(bout, "echo kill > /proc/%d/ctl\n", (int)f->lstore.u0.sival); 236 } 237 exits(0); 238 } 239 240 void 241 userinit(void) 242 { 243 Lsym *l; 244 Node *n; 245 char buf[512], *p; 246 247 248 p = getenv("home"); 249 if(p == 0) 250 p = getenv("HOME"); 251 if(p != 0) { 252 snprint(buf, sizeof(buf)-1, "%s/lib/acid", p); 253 silent = 1; 254 loadmodule(buf); 255 } 256 257 if(rdebug){ 258 snprint(buf, sizeof(buf)-1, "%s/rdebug", acidlib); 259 loadmodule(buf); 260 } 261 262 snprint(buf, sizeof(buf)-1, "%s/%s", acidlib, mach->name); 263 loadmodule(buf); 264 265 interactive = 0; 266 if(setjmp(err)) { 267 unwind(); 268 return; 269 } 270 l = look("acidinit"); 271 if(l && l->proc) { 272 n = an(ONAME, ZN, ZN); 273 n->sym = l; 274 n = an(OCALL, n, ZN); 275 execute(n); 276 } 277 } 278 279 void 280 loadmodule(char *s) 281 { 282 interactive = 0; 283 if(setjmp(err)) { 284 unwind(); 285 return; 286 } 287 pushfile(s); 288 silent = 0; 289 yyparse(); 290 popio(); 291 return; 292 } 293 294 void 295 readtext(char *s) 296 { 297 Dir *d; 298 Lsym *l; 299 Value *v; 300 Symbol sym; 301 ulong length; 302 extern Machdata mipsmach; 303 304 if(mtype != 0){ 305 symmap = newmap(0, 1); 306 if(symmap == 0) 307 print("%s: (error) loadmap: cannot make symbol map\n", argv0); 308 length = 1<<24; 309 d = dirfstat(text); 310 if(d != nil) { 311 length = d->length; 312 free(d); 313 } 314 setmap(symmap, text, 0, length, 0, "binary"); 315 free(d); 316 return; 317 } 318 319 machdata = &mipsmach; 320 321 if(!crackhdr(text, &fhdr)) { 322 print("can't decode file header\n"); 323 return; 324 } 325 326 symmap = loadmap(0, text, &fhdr); 327 if(symmap == 0) 328 print("%s: (error) loadmap: cannot make symbol map\n", argv0); 329 330 if(syminit(text, &fhdr) < 0) { 331 print("%s: (error) syminit: %r\n", argv0); 332 return; 333 } 334 print("%s:%s\n\n", s, fhdr.name); 335 336 if(mach->sbreg && lookup(0, mach->sbreg, &sym)) { 337 mach->sb = sym.value; 338 l = enter("SB", Tid); 339 l->v->vstore.fmt = 'X'; 340 l->v->vstore.u0.sival = mach->sb; 341 l->v->type = TINT; 342 l->v->set = 1; 343 } 344 345 l = mkvar("objtype"); 346 v = l->v; 347 v->vstore.fmt = 's'; 348 v->set = 1; 349 v->vstore.u0.sstring = strnode(mach->name); 350 v->type = TSTRING; 351 352 l = mkvar("textfile"); 353 v = l->v; 354 v->vstore.fmt = 's'; 355 v->set = 1; 356 v->vstore.u0.sstring = strnode(s); 357 v->type = TSTRING; 358 359 machbytype(fhdr.type); 360 varreg(); 361 } 362 363 Node* 364 an(int op, Node *l, Node *r) 365 { 366 Node *n; 367 368 n = gmalloc(sizeof(Node)); 369 n->ngc.gclink = gcl; 370 gcl = &n->ngc; 371 n->op = op; 372 n->left = l; 373 n->right = r; 374 return n; 375 } 376 377 List* 378 al(int t) 379 { 380 List *l; 381 382 l = gmalloc(sizeof(List)); 383 l->type = t; 384 l->lgc.gclink = gcl; 385 gcl = &l->lgc; 386 return l; 387 } 388 389 Node* 390 con(int v) 391 { 392 Node *n; 393 394 n = an(OCONST, ZN, ZN); 395 n->nstore.u0.sival = v; 396 n->nstore.fmt = 'X'; 397 n->type = TINT; 398 return n; 399 } 400 401 void 402 fatal(char *fmt, ...) 403 { 404 char buf[128]; 405 va_list arg; 406 407 va_start(arg, fmt); 408 vseprint(buf, buf+sizeof(buf), fmt, arg); 409 va_end(arg); 410 fprint(2, "%s: %L (fatal problem) %s\n", argv0, buf); 411 exits(buf); 412 } 413 414 void 415 yyerror(char *fmt, ...) 416 { 417 char buf[128]; 418 va_list arg; 419 420 if(strcmp(fmt, "syntax error") == 0) { 421 yyerror("syntax error, near symbol '%s'", symbol); 422 return; 423 } 424 va_start(arg, fmt); 425 vseprint(buf, buf+sizeof(buf), fmt, arg); 426 va_end(arg); 427 print("%L: %s\n", buf); 428 } 429 430 void 431 marktree(Node *n) 432 { 433 434 if(n == 0) 435 return; 436 437 marktree(n->left); 438 marktree(n->right); 439 440 n->ngc.gcmark = 1; 441 if(n->op != OCONST) 442 return; 443 444 switch(n->type) { 445 case TSTRING: 446 n->nstore.u0.sstring->sgc.gcmark = 1; 447 break; 448 case TLIST: 449 marklist(n->nstore.u0.sl); 450 break; 451 case TCODE: 452 marktree(n->nstore.u0.scc); 453 break; 454 } 455 } 456 457 void 458 marklist(List *l) 459 { 460 while(l) { 461 l->lgc.gcmark = 1; 462 switch(l->type) { 463 case TSTRING: 464 l->lstore.u0.sstring->sgc.gcmark = 1; 465 break; 466 case TLIST: 467 marklist(l->lstore.u0.sl); 468 break; 469 case TCODE: 470 marktree(l->lstore.u0.scc); 471 break; 472 } 473 l = l->next; 474 } 475 } 476 477 void 478 gc(void) 479 { 480 int i; 481 Lsym *f; 482 Value *v; 483 Gc *m, **p, *next; 484 485 if(dogc < Mempergc) 486 return; 487 dogc = 0; 488 489 /* Mark */ 490 for(m = gcl; m; m = m->gclink) 491 m->gcmark = 0; 492 493 /* Scan */ 494 for(i = 0; i < Hashsize; i++) { 495 for(f = hash[i]; f; f = f->hash) { 496 marktree(f->proc); 497 if(f->lexval != Tid) 498 continue; 499 for(v = f->v; v; v = v->pop) { 500 switch(v->type) { 501 case TSTRING: 502 v->vstore.u0.sstring->sgc.gcmark = 1; 503 break; 504 case TLIST: 505 marklist(v->vstore.u0.sl); 506 break; 507 case TCODE: 508 marktree(v->vstore.u0.scc); 509 break; 510 } 511 } 512 } 513 } 514 515 /* Free */ 516 p = &gcl; 517 for(m = gcl; m; m = next) { 518 next = m->gclink; 519 if(m->gcmark == 0) { 520 *p = next; 521 free(m); /* Sleazy reliance on my malloc */ 522 } 523 else 524 p = &m->gclink; 525 } 526 } 527 528 void* 529 gmalloc(long l) 530 { 531 void *p; 532 533 dogc += l; 534 p = malloc(l); 535 if(p == 0) 536 fatal("out of memory"); 537 memset(p, 0, l); 538 return p; 539 } 540 541 void 542 checkqid(int f1, int pid) 543 { 544 int fd; 545 Dir *d1, *d2; 546 char buf[128]; 547 548 if(kernel || rdebug) 549 return; 550 551 d1 = dirfstat(f1); 552 if(d1 == nil) 553 fatal("checkqid: (qid not checked) dirfstat: %r"); 554 555 sprint(buf, "/proc/%d/text", pid); 556 fd = open(buf, OREAD); 557 if(fd < 0 || (d2 = dirfstat(fd)) == nil){ 558 fatal("checkqid: (qid not checked) dirstat %s: %r", buf); 559 return; /* not reached */ 560 } 561 562 close(fd); 563 564 if(d1->qid.path != d2->qid.path || d1->qid.vers != d2->qid.vers || d1->qid.type != d2->qid.type){ 565 print("path %llux %llux vers %lud %lud type %d %d\n", 566 d1->qid.path, d2->qid.path, d1->qid.vers, d2->qid.vers, d1->qid.type, d2->qid.type); 567 print("warning: image does not match text for pid %d\n", pid); 568 } 569 free(d1); 570 free(d2); 571 } 572 573 char* 574 mysystem(void) 575 { 576 char *cpu, *p, *q; 577 static char kernel[128]; 578 579 cpu = getenv("cputype"); 580 if(cpu == 0) { 581 cpu = "mips"; 582 print("$cputype not set; assuming %s\n", cpu); 583 } 584 p = getenv("terminal"); 585 if(p == 0 || (p=strchr(p, ' ')) == 0 || p[1] == ' ' || p[1] == 0) { 586 p = "9power"; 587 print("missing or bad $terminal; assuming %s\n", p); 588 } 589 else{ 590 p++; 591 q = strchr(p, ' '); 592 if(q) 593 *q = 0; 594 sprint(kernel, "/%s/b%s", cpu, p); 595 } 596 return kernel; 597 } 598 599 int 600 isnumeric(char *s) 601 { 602 while(*s) { 603 if(*s < '0' || *s > '9') 604 return 0; 605 s++; 606 } 607 return 1; 608 } 609 610 int 611 xfmt(Fmt *f) 612 { 613 f->flags ^= FmtSharp; 614 return _ifmt(f); 615 } 616