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 Map*30 dumbmap(int fd)31 {32 Map *dumb;33 Seg s;35 dumb = allocmap();36 memset(&s, 0, sizeof s);37 s.fd = fd;38 s.base = 0;39 s.offset = 0;40 s.size = 0xFFFFFFFF;41 s.name = "data";42 s.file = "<dumb>";43 if(addseg(dumb, s) < 0){44 freemap(dumb);45 return nil;46 }47 if(mach == nil)48 mach = machcpu;49 return dumb;50 }52 void53 main(int argc, char *argv[])54 {55 Lsym *volatile l;56 Node *n;57 char buf[128], *s;58 int pid, i;60 argv0 = argv[0];61 pid = 0;62 quiet = 1;64 mtype = 0;65 ARGBEGIN{66 case 'A':67 abort();68 break;69 case 'm':70 mtype = ARGF();71 break;72 case 'w':73 wtflag = 1;74 break;75 case 'l':76 s = ARGF();77 if(s == 0)78 usage();79 lm[nlm++] = s;80 break;81 case 'k':82 kernel++;83 break;84 case 'q':85 quiet = 0;86 break;87 case 'r':88 pid = 1;89 remote++;90 kernel++;91 break;92 default:93 usage();94 }ARGEND96 USED(pid);98 fmtinstall('Z', Zfmt);99 fmtinstall('L', locfmt);100 Binit(&bioout, 1, OWRITE);101 bout = &bioout;103 initexpr();104 initprint();105 kinit();106 initialising = 1;107 pushfile(0);108 loadvars();109 installbuiltin();110 acidregs = mallocz(sizeof *acidregs, 1);111 acidregs->rw = acidregsrw;113 if(mtype && machbyname(mtype) == 0)114 print("unknown machine %s", mtype);116 if (attachfiles(argc, argv) < 0)117 varreg(); /* use default register set on error */118 if(mach == nil)119 mach = machcpu;121 symhdr = nil; /* not supposed to use this anymore */123 l = mkvar("acid");124 l->v->set = 1;125 l->v->type = TLIST;126 l->v->store.u.l = nil;128 loadmodule(unsharp("#9/acid/port"));129 for(i = 0; i < nlm; i++) {130 if(access(lm[i], AREAD) >= 0)131 loadmodule(lm[i]);132 else {133 sprint(buf, "#9/acid/%s", lm[i]);134 loadmodule(unsharp(buf));135 }136 }138 userinit();139 varsym();141 l = look("acidmap");142 if(l && l->proc) {143 if(setjmp(err) == 0){144 n = an(ONAME, ZN, ZN);145 n->sym = l;146 n = an(OCALL, n, ZN);147 execute(n);148 }149 }151 interactive = 1;152 initialising = 0;153 line = 1;155 notify(catcher);157 for(;;) {158 if(setjmp(err)) {159 Binit(&bioout, 1, OWRITE);160 unwind();161 }162 stacked = 0;164 Bprint(bout, "acid; ");166 if(yyparse() != 1)167 die();168 restartio();170 unwind();171 }172 /*173 Bputc(bout, '\n');174 exits(0);175 */176 }178 void179 setstring(char *var, char *s)180 {181 Lsym *l;182 Value *v;184 l = mkvar(var);185 v = l->v;186 v->store.fmt = 's';187 v->set = 1;188 v->store.u.string = strnode(s ? s : "");189 v->type = TSTRING;190 }192 static int193 attachfiles(int argc, char **argv)194 {195 volatile int pid;196 Lsym *l;198 pid = 0;199 interactive = 0;200 USED(pid);202 if(setjmp(err))203 return -1;205 attachargs(argc, argv, wtflag?ORDWR:OREAD, 1);207 setstring("objtype", mach->name);208 setstring("textfile", symfil);209 setstring("systype", symhdr ? symhdr->aname : "");210 setstring("corefile", corfil);212 l = mkvar("pids");213 l->v->set = 1;214 l->v->type = TLIST;215 l->v->store.u.l = nil;217 if(corpid)218 sproc(corpid);219 if(corhdr)220 setcore(corhdr);221 varreg();222 return 0;223 }225 void226 setcore(Fhdr *hdr)227 {228 int i;229 Lsym *l;230 Value *v;231 List **tail, *tl;233 unmapproc(cormap);234 unmapfile(corhdr, cormap);235 free(correg);236 correg = nil;238 if(hdr == nil)239 error("no core");240 if(mapfile(hdr, 0, cormap, &correg) < 0)241 error("mapfile %s: %r", hdr->filename);242 corhdr = hdr;243 corfil = hdr->filename;245 l = mkvar("pid");246 v = l->v;247 v->store.fmt = 'D';248 v->set = 1;249 v->store.u.ival = hdr->pid;251 setstring("corefile", corfil);252 setstring("cmdline", hdr->cmdline);254 l = mkvar("pids");255 l->v->set = 1;256 l->v->type = TLIST;257 l->v->store.u.l = nil;258 tail = &l->v->store.u.l;259 for(i=0; i<hdr->nthread; i++){260 tl = al(TINT);261 tl->store.u.ival = hdr->thread[i].id;262 tl->store.fmt = 'X';263 *tail = tl;264 tail = &tl->next;265 }267 if(hdr->nthread)268 sproc(hdr->thread[0].id);269 }271 void272 die(void)273 {274 Lsym *s;275 List *f;276 int first;278 Bprint(bout, "\n");280 first = 1;281 s = look("proclist");282 if(s && s->v->type == TLIST) {283 for(f = s->v->store.u.l; f; f = f->next){284 detachproc((int)f->store.u.ival);285 Bprint(bout, "%s %d", first ? "/bin/kill -9" : "", (int)f->store.u.ival);286 first = 0;287 }288 }289 if(!first)290 Bprint(bout, "\n");291 exits(0);292 }294 void295 userinit(void)296 {297 Lsym *l;298 Node *n;299 char buf[128], *p;301 sprint(buf, "#9/acid/%s", mach->name);302 loadmodule(unsharp(buf));303 p = getenv("HOME");304 if(p != 0) {305 sprint(buf, "%s/lib/acid", p);306 silent = 1;307 loadmodule(buf);308 }310 interactive = 0;311 if(setjmp(err)) {312 unwind();313 return;314 }315 l = look("acidinit");316 if(l && l->proc) {317 n = an(ONAME, ZN, ZN);318 n->sym = l;319 n = an(OCALL, n, ZN);320 execute(n);321 }322 }324 void325 loadmodule(char *s)326 {327 interactive = 0;328 if(setjmp(err)) {329 unwind();330 return;331 }332 pushfile(s);333 silent = 0;334 yyparse();335 popio();336 return;337 }339 Node*340 an(int op, Node *l, Node *r)341 {342 Node *n;344 n = gmalloc(sizeof(Node));345 memset(n, 0, sizeof(Node));346 n->gc.gclink = gcl;347 gcl = (Gc*)n;348 n->op = op;349 n->left = l;350 n->right = r;351 return n;352 }354 List*355 al(int t)356 {357 List *l;359 l = gmalloc(sizeof(List));360 memset(l, 0, sizeof(List));361 l->type = t;362 l->gc.gclink = gcl;363 gcl = (Gc*)l;364 return l;365 }367 Node*368 con(s64int v)369 {370 Node *n;372 n = an(OCONST, ZN, ZN);373 n->store.u.ival = v;374 n->store.fmt = 'X';375 n->type = TINT;376 return n;377 }379 void380 fatal(char *fmt, ...)381 {382 char buf[128];383 va_list arg;385 va_start(arg, fmt);386 vseprint(buf, buf+sizeof(buf), fmt, arg);387 va_end(arg);388 fprint(2, "%s: %Z (fatal problem) %s\n", argv0, buf);389 exits(buf);390 }392 void393 yyerror(char *fmt, ...)394 {395 char buf[128];396 va_list arg;398 if(strcmp(fmt, "syntax error") == 0) {399 yyerror("syntax error, near symbol '%s'", symbol);400 return;401 }402 va_start(arg, fmt);403 vseprint(buf, buf+sizeof(buf), fmt, arg);404 va_end(arg);405 print("%Z: %s\n", buf);406 }408 void409 marktree(Node *n)410 {412 if(n == 0)413 return;415 marktree(n->left);416 marktree(n->right);418 n->gc.gcmark = 1;419 if(n->op != OCONST)420 return;422 switch(n->type) {423 case TSTRING:424 n->store.u.string->gc.gcmark = 1;425 break;426 case TLIST:427 marklist(n->store.u.l);428 break;429 case TCODE:430 marktree(n->store.u.cc);431 break;432 }433 }435 void436 marklist(List *l)437 {438 while(l) {439 l->gc.gcmark = 1;440 switch(l->type) {441 case TSTRING:442 l->store.u.string->gc.gcmark = 1;443 break;444 case TLIST:445 marklist(l->store.u.l);446 break;447 case TCODE:448 marktree(l->store.u.cc);449 break;450 }451 l = l->next;452 }453 }455 void456 gc(void)457 {458 int i;459 Lsym *f;460 Value *v;461 Gc *m, **p, *next;463 if(dogc < Mempergc)464 return;465 dogc = 0;467 /* Mark */468 for(m = gcl; m; m = m->gclink)469 m->gcmark = 0;471 /* Scan */472 for(i = 0; i < Hashsize; i++) {473 for(f = hash[i]; f; f = f->hash) {474 marktree(f->proc);475 if(f->lexval != Tid)476 continue;477 for(v = f->v; v; v = v->pop) {478 switch(v->type) {479 case TSTRING:480 v->store.u.string->gc.gcmark = 1;481 break;482 case TLIST:483 marklist(v->store.u.l);484 break;485 case TCODE:486 marktree(v->store.u.cc);487 break;488 case TCON:489 marktree(v->store.u.con);490 break;491 }492 }493 }494 }496 /* Free */497 p = &gcl;498 for(m = gcl; m; m = next) {499 next = m->gclink;500 if(m->gcmark == 0) {501 *p = next;502 free(m); /* Sleazy reliance on my malloc */503 }504 else505 p = &m->gclink;506 }507 }509 void*510 gmalloc(long l)511 {512 void *p;514 dogc += l;515 p = malloc(l);516 if(p == 0)517 fatal("out of memory");518 return p;519 }521 void522 checkqid(int f1, int pid)523 {524 int fd;525 Dir *d1, *d2;526 char buf[128];528 if(kernel)529 return;531 d1 = dirfstat(f1);532 if(d1 == nil){533 print("checkqid: (qid not checked) dirfstat: %r\n");534 return;535 }537 sprint(buf, "/proc/%d/text", pid);538 fd = open(buf, OREAD);539 if(fd < 0 || (d2 = dirfstat(fd)) == nil){540 print("checkqid: (qid not checked) dirstat %s: %r\n", buf);541 free(d1);542 if(fd >= 0)543 close(fd);544 return;545 }547 close(fd);549 if(d1->qid.path != d2->qid.path || d1->qid.vers != d2->qid.vers || d1->qid.type != d2->qid.type){550 print("path %#llux %#llux vers %lud %lud type %d %d\n",551 d1->qid.path, d2->qid.path, d1->qid.vers, d2->qid.vers, d1->qid.type, d2->qid.type);552 print("warning: image does not match text for pid %d\n", pid);553 }554 free(d1);555 free(d2);556 }558 void559 catcher(void *junk, char *s)560 {561 USED(junk);563 if(strstr(s, "interrupt")) {564 gotint = 1;565 noted(NCONT);566 }567 if(strstr(s, "child"))568 noted(NCONT);569 fprint(2, "note: %s\n", s);570 noted(NDFLT);571 }573 char*574 system(void)575 {576 char *cpu, *p, *q;577 static char kernel[128];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/9%s", cpu, p);595 }596 return kernel;597 }599 int600 isnumeric(char *s)601 {602 while(*s) {603 if(*s < '0' || *s > '9')604 return 0;605 s++;606 }607 return 1;608 }