Blob
1 #include <u.h>2 #include <libc.h>3 #include <bio.h>4 #include <mach.h>5 #define Extern6 #include "acid.h"7 #include "y.tab.h"9 extern int __ifmt(Fmt*);11 static Biobuf bioout;12 static char* lm[16];13 static int nlm;14 static char* mtype;16 static int attachfiles(int, char**);17 int xfmt(Fmt*);18 int isnumeric(char*);19 void die(void);20 void setcore(Fhdr*);22 void23 usage(void)24 {25 fprint(2, "usage: acid [-c core] [-l module] [-m machine] [-qrw] [-k] [pid] [file]\n");26 exits("usage");27 }29 void30 main(int argc, char *argv[])31 {32 Lsym *l;33 Node *n;34 char buf[128], *s;35 int pid, i;37 argv0 = argv[0];38 pid = 0;39 quiet = 1;41 mtype = 0;42 ARGBEGIN{43 case 'A':44 abort();45 break;46 case 'm':47 mtype = ARGF();48 break;49 case 'w':50 wtflag = 1;51 break;52 case 'l':53 s = ARGF();54 if(s == 0)55 usage();56 lm[nlm++] = s;57 break;58 case 'k':59 kernel++;60 break;61 case 'q':62 quiet = 0;63 break;64 case 'r':65 pid = 1;66 remote++;67 kernel++;68 break;69 default:70 usage();71 }ARGEND73 fmtinstall('x', xfmt);74 fmtinstall('Z', Zfmt);75 fmtinstall('L', locfmt);76 Binit(&bioout, 1, OWRITE);77 bout = &bioout;79 initexpr();80 initprint();81 kinit();82 initialising = 1;83 pushfile(0);84 loadvars();85 installbuiltin();87 if(mtype && machbyname(mtype) == 0)88 print("unknown machine %s", mtype);90 if (attachfiles(argc, argv) < 0)91 varreg(); /* use default register set on error */92 if(mach == nil)93 mach = machcpu;95 symhdr = nil; /* not supposed to use this anymore */97 l = mkvar("acid");98 l->v->set = 1;99 l->v->type = TLIST;100 l->v->store.u.l = nil;102 loadmodule(unsharp("#9/acid/port"));103 for(i = 0; i < nlm; i++) {104 if(access(lm[i], AREAD) >= 0)105 loadmodule(lm[i]);106 else {107 sprint(buf, "#9/acid/%s", lm[i]);108 loadmodule(unsharp(buf));109 }110 }112 userinit();113 varsym();115 l = look("acidmap");116 if(l && l->proc) {117 if(setjmp(err) == 0){118 n = an(ONAME, ZN, ZN);119 n->sym = l;120 n = an(OCALL, n, ZN);121 execute(n);122 }123 }125 interactive = 1;126 initialising = 0;127 line = 1;129 notify(catcher);131 for(;;) {132 if(setjmp(err)) {133 Binit(&bioout, 1, OWRITE);134 unwind();135 }136 stacked = 0;138 Bprint(bout, "acid; ");140 if(yyparse() != 1)141 die();142 restartio();144 unwind();145 }146 Bputc(bout, '\n');147 exits(0);148 }150 static int151 attachfiles(int argc, char **argv)152 {153 int pid;154 char *s;155 int i, omode;156 Fhdr *hdr;157 Lsym *l;158 Value *v;160 pid = 0;161 interactive = 0;162 if(setjmp(err))163 return -1;165 /*166 * Unix and Plan 9 differ on what the right order of pid, text, and core is.167 * I never remember anyway. Let's just accept them in any order.168 */169 omode = wtflag ? ORDWR : OREAD;170 for(i=0; i<argc; i++){171 if(isnumeric(argv[i])){172 if(pid){173 fprint(2, "already have pid %d; ignoring pid %d\n", pid, argv[i]);174 continue;175 }176 if(corhdr){177 fprint(2, "already have core %s; ignoring pid %d\n", corfil, pid);178 continue;179 }180 pid = atoi(argv[i]);181 continue;182 }183 if((hdr = crackhdr(argv[i], omode)) == nil){184 fprint(2, "crackhdr %s: %r\n", argv[i]);185 continue;186 }187 fprint(2, "%s: %s %s %s\n", argv[i], hdr->aname, hdr->mname, hdr->fname);188 if(hdr->ftype == FCORE){189 if(pid){190 fprint(2, "already have pid %d; ignoring core %s\n", pid, argv[i]);191 uncrackhdr(hdr);192 continue;193 }194 if(corhdr){195 fprint(2, "already have core %s; ignoring core %s\n", corfil, argv[i]);196 uncrackhdr(hdr);197 continue;198 }199 corhdr = hdr;200 corfil = argv[i];201 }else{202 if(symhdr){203 fprint(2, "already have text %s; ignoring text %s\n", symfil, argv[i]);204 uncrackhdr(hdr);205 continue;206 }207 symhdr = hdr;208 symfil = argv[i];209 }210 }212 if(symhdr==nil){213 symfil = "a.out";214 if(pid){215 if((s = proctextfile(pid)) != nil){216 fprint(2, "pid %d: text %s\n", pid, s);217 symfil = s;218 }219 }220 /* XXX pull command from core */222 if((symhdr = crackhdr(symfil, omode)) == nil){223 fprint(2, "crackhdr %s: %r\n", symfil);224 symfil = nil;225 }226 }228 if(symhdr)229 syminit(symhdr);231 if(!mach)232 mach = machcpu;234 /*235 * Set up maps.236 */237 symmap = allocmap();238 cormap = allocmap();239 if(symmap == nil || cormap == nil)240 sysfatal("allocating maps: %r");242 if(symhdr){243 if(mapfile(symhdr, 0, symmap, nil) < 0)244 fprint(2, "mapping %s: %r\n", symfil);245 mapfile(symhdr, 0, cormap, nil);246 }248 l = mkvar("objtype");249 v = l->v;250 v->store.fmt = 's';251 v->set = 1;252 v->store.u.string = strnode(mach->name);253 v->type = TSTRING;255 l = mkvar("textfile");256 v = l->v;257 v->store.fmt = 's';258 v->set = 1;259 v->store.u.string = strnode(symfil ? symfil : "");260 v->type = TSTRING;262 l = mkvar("systype");263 v = l->v;264 v->store.fmt = 's';265 v->set = 1;266 v->store.u.string = strnode(symhdr ? symhdr->aname : "");267 v->type = TSTRING;269 l = mkvar("corefile");270 v = l->v;271 v->store.fmt = 's';272 v->set = 1;273 v->store.u.string = strnode(corfil ? corfil : "");274 v->type = TSTRING;276 if(pid)277 sproc(pid);278 if(corhdr)279 setcore(corhdr);280 varreg();281 return 0;282 }284 void285 setcore(Fhdr *hdr)286 {287 unmapproc(cormap);288 unmapfile(corhdr, cormap);289 free(correg);290 correg = nil;292 if(hdr == nil)293 error("no core");294 if(mapfile(hdr, 0, cormap, &correg) < 0)295 error("mapfile %s: %r", hdr->filename);296 corhdr = hdr;297 corfil = hdr->filename;298 }300 void301 die(void)302 {303 Lsym *s;304 List *f;306 Bprint(bout, "\n");308 s = look("proclist");309 if(s && s->v->type == TLIST) {310 for(f = s->v->store.u.l; f; f = f->next){311 detachproc((int)f->store.u.ival);312 Bprint(bout, "/bin/kill -9 %d\n", (int)f->store.u.ival);313 }314 }315 exits(0);316 }318 void319 userinit(void)320 {321 Lsym *l;322 Node *n;323 char buf[128], *p;325 sprint(buf, "#9/acid/%s", mach->name);326 loadmodule(unsharp(buf));327 p = getenv("home");328 if(p != 0) {329 sprint(buf, "%s/lib/acid", p);330 silent = 1;331 loadmodule(buf);332 }334 interactive = 0;335 if(setjmp(err)) {336 unwind();337 return;338 }339 l = look("acidinit");340 if(l && l->proc) {341 n = an(ONAME, ZN, ZN);342 n->sym = l;343 n = an(OCALL, n, ZN);344 execute(n);345 }346 }348 void349 loadmodule(char *s)350 {351 interactive = 0;352 if(setjmp(err)) {353 unwind();354 return;355 }356 pushfile(s);357 silent = 0;358 yyparse();359 popio();360 return;361 }363 Node*364 an(int op, Node *l, Node *r)365 {366 Node *n;368 n = gmalloc(sizeof(Node));369 memset(n, 0, sizeof(Node));370 n->gc.gclink = gcl;371 gcl = (Gc*)n;372 n->op = op;373 n->left = l;374 n->right = r;375 return n;376 }378 List*379 al(int t)380 {381 List *l;383 l = gmalloc(sizeof(List));384 memset(l, 0, sizeof(List));385 l->type = t;386 l->gc.gclink = gcl;387 gcl = (Gc*)l;388 return l;389 }391 Node*392 con(int v)393 {394 Node *n;396 n = an(OCONST, ZN, ZN);397 n->store.u.ival = v;398 n->store.fmt = 'X';399 n->type = TINT;400 return n;401 }403 void404 fatal(char *fmt, ...)405 {406 char buf[128];407 va_list arg;409 va_start(arg, fmt);410 vseprint(buf, buf+sizeof(buf), fmt, arg);411 va_end(arg);412 fprint(2, "%s: %Z (fatal problem) %s\n", argv0, buf);413 exits(buf);414 }416 void417 yyerror(char *fmt, ...)418 {419 char buf[128];420 va_list arg;422 if(strcmp(fmt, "syntax error") == 0) {423 yyerror("syntax error, near symbol '%s'", symbol);424 return;425 }426 va_start(arg, fmt);427 vseprint(buf, buf+sizeof(buf), fmt, arg);428 va_end(arg);429 print("%Z: %s\n", buf);430 }432 void433 marktree(Node *n)434 {436 if(n == 0)437 return;439 marktree(n->left);440 marktree(n->right);442 n->gc.gcmark = 1;443 if(n->op != OCONST)444 return;446 switch(n->type) {447 case TSTRING:448 n->store.u.string->gc.gcmark = 1;449 break;450 case TLIST:451 marklist(n->store.u.l);452 break;453 case TCODE:454 marktree(n->store.u.cc);455 break;456 }457 }459 void460 marklist(List *l)461 {462 while(l) {463 l->gc.gcmark = 1;464 switch(l->type) {465 case TSTRING:466 l->store.u.string->gc.gcmark = 1;467 break;468 case TLIST:469 marklist(l->store.u.l);470 break;471 case TCODE:472 marktree(l->store.u.cc);473 break;474 }475 l = l->next;476 }477 }479 void480 gc(void)481 {482 int i;483 Lsym *f;484 Value *v;485 Gc *m, **p, *next;487 if(dogc < Mempergc)488 return;489 dogc = 0;491 /* Mark */492 for(m = gcl; m; m = m->gclink)493 m->gcmark = 0;495 /* Scan */496 for(i = 0; i < Hashsize; i++) {497 for(f = hash[i]; f; f = f->hash) {498 marktree(f->proc);499 if(f->lexval != Tid)500 continue;501 for(v = f->v; v; v = v->pop) {502 switch(v->type) {503 case TSTRING:504 v->store.u.string->gc.gcmark = 1;505 break;506 case TLIST:507 marklist(v->store.u.l);508 break;509 case TCODE:510 marktree(v->store.u.cc);511 break;512 }513 }514 }515 }517 /* Free */518 p = &gcl;519 for(m = gcl; m; m = next) {520 next = m->gclink;521 if(m->gcmark == 0) {522 *p = next;523 free(m); /* Sleazy reliance on my malloc */524 }525 else526 p = &m->gclink;527 }528 }530 void*531 gmalloc(long l)532 {533 void *p;535 dogc += l;536 p = malloc(l);537 if(p == 0)538 fatal("out of memory");539 return p;540 }542 void543 checkqid(int f1, int pid)544 {545 int fd;546 Dir *d1, *d2;547 char buf[128];549 if(kernel)550 return;552 d1 = dirfstat(f1);553 if(d1 == nil){554 print("checkqid: (qid not checked) dirfstat: %r\n");555 return;556 }558 sprint(buf, "/proc/%d/text", pid);559 fd = open(buf, OREAD);560 if(fd < 0 || (d2 = dirfstat(fd)) == nil){561 print("checkqid: (qid not checked) dirstat %s: %r\n", buf);562 free(d1);563 if(fd >= 0)564 close(fd);565 return;566 }568 close(fd);570 if(d1->qid.path != d2->qid.path || d1->qid.vers != d2->qid.vers || d1->qid.type != d2->qid.type){571 print("path %llux %llux vers %lud %lud type %d %d\n",572 d1->qid.path, d2->qid.path, d1->qid.vers, d2->qid.vers, d1->qid.type, d2->qid.type);573 print("warning: image does not match text for pid %d\n", pid);574 }575 free(d1);576 free(d2);577 }579 void580 catcher(void *junk, char *s)581 {582 USED(junk);584 if(strstr(s, "interrupt")) {585 gotint = 1;586 noted(NCONT);587 }588 if(strstr(s, "child"))589 noted(NCONT);590 fprint(2, "note: %s\n", s);591 noted(NDFLT);592 }594 char*595 system(void)596 {597 char *cpu, *p, *q;598 static char kernel[128];600 cpu = getenv("cputype");601 if(cpu == 0) {602 cpu = "mips";603 print("$cputype not set; assuming %s\n", cpu);604 }605 p = getenv("terminal");606 if(p == 0 || (p=strchr(p, ' ')) == 0 || p[1] == ' ' || p[1] == 0) {607 p = "9power";608 print("missing or bad $terminal; assuming %s\n", p);609 }610 else{611 p++;612 q = strchr(p, ' ');613 if(q)614 *q = 0;615 sprint(kernel, "/%s/9%s", cpu, p);616 }617 return kernel;618 }620 int621 isnumeric(char *s)622 {623 while(*s) {624 if(*s < '0' || *s > '9')625 return 0;626 s++;627 }628 return 1;629 }631 int632 xfmt(Fmt *f)633 {634 f->flags ^= FmtSharp;635 return __ifmt(f);636 }