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