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