Blob


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"
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 void
23 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 void
53 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 }ARGEND
96 fmtinstall('x', xfmt);
97 fmtinstall('Z', Zfmt);
98 fmtinstall('L', locfmt);
99 Binit(&bioout, 1, OWRITE);
100 bout = &bioout;
102 initexpr();
103 initprint();
104 kinit();
105 initialising = 1;
106 pushfile(0);
107 loadvars();
108 installbuiltin();
109 acidregs = mallocz(sizeof *acidregs, 1);
110 acidregs->rw = acidregsrw;
112 if(mtype && machbyname(mtype) == 0)
113 print("unknown machine %s", mtype);
115 if (attachfiles(argc, argv) < 0)
116 varreg(); /* use default register set on error */
117 if(mach == nil)
118 mach = machcpu;
120 symhdr = nil; /* not supposed to use this anymore */
122 l = mkvar("acid");
123 l->v->set = 1;
124 l->v->type = TLIST;
125 l->v->store.u.l = nil;
127 loadmodule(unsharp("#9/acid/port"));
128 for(i = 0; i < nlm; i++) {
129 if(access(lm[i], AREAD) >= 0)
130 loadmodule(lm[i]);
131 else {
132 sprint(buf, "#9/acid/%s", lm[i]);
133 loadmodule(unsharp(buf));
137 userinit();
138 varsym();
140 l = look("acidmap");
141 if(l && l->proc) {
142 if(setjmp(err) == 0){
143 n = an(ONAME, ZN, ZN);
144 n->sym = l;
145 n = an(OCALL, n, ZN);
146 execute(n);
150 interactive = 1;
151 initialising = 0;
152 line = 1;
154 notify(catcher);
156 for(;;) {
157 if(setjmp(err)) {
158 Binit(&bioout, 1, OWRITE);
159 unwind();
161 stacked = 0;
163 Bprint(bout, "acid; ");
165 if(yyparse() != 1)
166 die();
167 restartio();
169 unwind();
171 /*
172 Bputc(bout, '\n');
173 exits(0);
174 */
177 void
178 setstring(char *var, char *s)
180 Lsym *l;
181 Value *v;
183 l = mkvar(var);
184 v = l->v;
185 v->store.fmt = 's';
186 v->set = 1;
187 v->store.u.string = strnode(s ? s : "");
188 v->type = TSTRING;
191 static int
192 attachfiles(int argc, char **argv)
194 int fd;
195 volatile int pid;
196 char *s, *t;
197 int i, omode;
198 Fhdr *hdr;
199 Lsym *l;
201 pid = 0;
202 interactive = 0;
203 if(setjmp(err))
204 return -1;
206 /*
207 * Unix and Plan 9 differ on what the right order of pid, text, and core is.
208 * I never remember anyway. Let's just accept them in any order.
209 */
210 omode = wtflag ? ORDWR : OREAD;
211 for(i=0; i<argc; i++){
212 if(isnumeric(argv[i])){
213 if(pid){
214 fprint(2, "already have pid %d; ignoring pid %d\n", pid, argv[i]);
215 continue;
217 if(corhdr){
218 fprint(2, "already have core %s; ignoring pid %d\n", corfil, pid);
219 continue;
221 pid = atoi(argv[i]);
222 continue;
224 if((hdr = crackhdr(argv[i], omode)) == nil){
225 fprint(2, "crackhdr %s: %r\n", argv[i]);
226 if(argc == 1 && (fd = open(argv[i], omode)) > 0){
227 fprint(2, "loading %s direct mapped\n", argv[i]);
228 symmap = dumbmap(fd);
229 cormap = dumbmap(fd);
230 symfil = argv[i];
231 corfil = argv[i];
232 goto Run;
234 continue;
236 fprint(2, "%s: %s %s %s\n", argv[i], hdr->aname, hdr->mname, hdr->fname);
237 if(hdr->ftype == FCORE){
238 if(pid){
239 fprint(2, "already have pid %d; ignoring core %s\n", pid, argv[i]);
240 uncrackhdr(hdr);
241 continue;
243 if(corhdr){
244 fprint(2, "already have core %s; ignoring core %s\n", corfil, argv[i]);
245 uncrackhdr(hdr);
246 continue;
248 corhdr = hdr;
249 corfil = argv[i];
250 }else{
251 if(symhdr){
252 fprint(2, "already have text %s; ignoring text %s\n", symfil, argv[i]);
253 uncrackhdr(hdr);
254 continue;
256 symhdr = hdr;
257 symfil = argv[i];
261 if(symhdr==nil){
262 symfil = "a.out";
263 if(pid){
264 if((s = proctextfile(pid)) != nil){
265 fprint(2, "pid %d: text %s\n", pid, s);
266 symfil = s;
269 if(corhdr){
270 /*
271 * prog gives only the basename of the command,
272 * so try the command line for a path.
273 */
274 if((s = strdup(corhdr->cmdline)) != nil){
275 t = strchr(s, ' ');
276 if(t)
277 *t = 0;
278 if((t = searchpath(s)) != nil){
279 fprint(2, "core: text %s\n", t);
280 symfil = t;
282 free(s);
286 if((symhdr = crackhdr(symfil, omode)) == nil){
287 fprint(2, "crackhdr %s: %r\n", symfil);
288 symfil = nil;
289 }else
290 fprint(2, "%s: %s %s %s\n", symfil, symhdr->aname, symhdr->mname, symhdr->fname);
293 if(symhdr)
294 symopen(symhdr);
296 if(!mach)
297 mach = machcpu;
299 /*
300 * Set up maps.
301 */
302 symmap = allocmap();
303 cormap = allocmap();
304 if(symmap == nil || cormap == nil)
305 sysfatal("allocating maps: %r");
307 if(symhdr){
308 if(mapfile(symhdr, 0, symmap, nil) < 0)
309 fprint(2, "mapping %s: %r\n", symfil);
310 mapfile(symhdr, 0, cormap, nil);
313 Run:
314 setstring("objtype", mach->name);
315 setstring("textfile", symfil);
316 setstring("systype", symhdr ? symhdr->aname : "");
317 setstring("corefile", corfil);
319 l = mkvar("pids");
320 l->v->set = 1;
321 l->v->type = TLIST;
322 l->v->store.u.l = nil;
324 if(pid)
325 sproc(pid);
326 if(corhdr)
327 setcore(corhdr);
328 varreg();
329 return 0;
332 void
333 setcore(Fhdr *hdr)
335 int i;
336 Lsym *l;
337 Value *v;
338 List **tail, *tl;
340 unmapproc(cormap);
341 unmapfile(corhdr, cormap);
342 free(correg);
343 correg = nil;
345 if(hdr == nil)
346 error("no core");
347 if(mapfile(hdr, 0, cormap, &correg) < 0)
348 error("mapfile %s: %r", hdr->filename);
349 corhdr = hdr;
350 corfil = hdr->filename;
352 l = mkvar("pid");
353 v = l->v;
354 v->store.fmt = 'D';
355 v->set = 1;
356 v->store.u.ival = hdr->pid;
358 setstring("corefile", corfil);
359 setstring("cmdline", hdr->cmdline);
361 l = mkvar("pids");
362 l->v->set = 1;
363 l->v->type = TLIST;
364 l->v->store.u.l = nil;
365 tail = &l->v->store.u.l;
366 for(i=0; i<hdr->nthread; i++){
367 tl = al(TINT);
368 tl->store.u.ival = hdr->thread[i].id;
369 tl->store.fmt = 'X';
370 *tail = tl;
371 tail = &tl->next;
374 if(hdr->nthread)
375 sproc(hdr->thread[0].id);
378 void
379 die(void)
381 Lsym *s;
382 List *f;
383 int first;
385 Bprint(bout, "\n");
387 first = 1;
388 s = look("proclist");
389 if(s && s->v->type == TLIST) {
390 for(f = s->v->store.u.l; f; f = f->next){
391 detachproc((int)f->store.u.ival);
392 Bprint(bout, "%s %d", first ? "/bin/kill -9" : "", (int)f->store.u.ival);
393 first = 0;
396 if(!first)
397 Bprint(bout, "\n");
398 exits(0);
401 void
402 userinit(void)
404 Lsym *l;
405 Node *n;
406 char buf[128], *p;
408 sprint(buf, "#9/acid/%s", mach->name);
409 loadmodule(unsharp(buf));
410 p = getenv("HOME");
411 if(p != 0) {
412 sprint(buf, "%s/lib/acid", p);
413 silent = 1;
414 loadmodule(buf);
417 interactive = 0;
418 if(setjmp(err)) {
419 unwind();
420 return;
422 l = look("acidinit");
423 if(l && l->proc) {
424 n = an(ONAME, ZN, ZN);
425 n->sym = l;
426 n = an(OCALL, n, ZN);
427 execute(n);
431 void
432 loadmodule(char *s)
434 interactive = 0;
435 if(setjmp(err)) {
436 unwind();
437 return;
439 pushfile(s);
440 silent = 0;
441 yyparse();
442 popio();
443 return;
446 Node*
447 an(int op, Node *l, Node *r)
449 Node *n;
451 n = gmalloc(sizeof(Node));
452 memset(n, 0, sizeof(Node));
453 n->gc.gclink = gcl;
454 gcl = (Gc*)n;
455 n->op = op;
456 n->left = l;
457 n->right = r;
458 return n;
461 List*
462 al(int t)
464 List *l;
466 l = gmalloc(sizeof(List));
467 memset(l, 0, sizeof(List));
468 l->type = t;
469 l->gc.gclink = gcl;
470 gcl = (Gc*)l;
471 return l;
474 Node*
475 con(int v)
477 Node *n;
479 n = an(OCONST, ZN, ZN);
480 n->store.u.ival = v;
481 n->store.fmt = 'X';
482 n->type = TINT;
483 return n;
486 void
487 fatal(char *fmt, ...)
489 char buf[128];
490 va_list arg;
492 va_start(arg, fmt);
493 vseprint(buf, buf+sizeof(buf), fmt, arg);
494 va_end(arg);
495 fprint(2, "%s: %Z (fatal problem) %s\n", argv0, buf);
496 exits(buf);
499 void
500 yyerror(char *fmt, ...)
502 char buf[128];
503 va_list arg;
505 if(strcmp(fmt, "syntax error") == 0) {
506 yyerror("syntax error, near symbol '%s'", symbol);
507 return;
509 va_start(arg, fmt);
510 vseprint(buf, buf+sizeof(buf), fmt, arg);
511 va_end(arg);
512 print("%Z: %s\n", buf);
515 void
516 marktree(Node *n)
519 if(n == 0)
520 return;
522 marktree(n->left);
523 marktree(n->right);
525 n->gc.gcmark = 1;
526 if(n->op != OCONST)
527 return;
529 switch(n->type) {
530 case TSTRING:
531 n->store.u.string->gc.gcmark = 1;
532 break;
533 case TLIST:
534 marklist(n->store.u.l);
535 break;
536 case TCODE:
537 marktree(n->store.u.cc);
538 break;
542 void
543 marklist(List *l)
545 while(l) {
546 l->gc.gcmark = 1;
547 switch(l->type) {
548 case TSTRING:
549 l->store.u.string->gc.gcmark = 1;
550 break;
551 case TLIST:
552 marklist(l->store.u.l);
553 break;
554 case TCODE:
555 marktree(l->store.u.cc);
556 break;
558 l = l->next;
562 void
563 gc(void)
565 int i;
566 Lsym *f;
567 Value *v;
568 Gc *m, **p, *next;
570 if(dogc < Mempergc)
571 return;
572 dogc = 0;
574 /* Mark */
575 for(m = gcl; m; m = m->gclink)
576 m->gcmark = 0;
578 /* Scan */
579 for(i = 0; i < Hashsize; i++) {
580 for(f = hash[i]; f; f = f->hash) {
581 marktree(f->proc);
582 if(f->lexval != Tid)
583 continue;
584 for(v = f->v; v; v = v->pop) {
585 switch(v->type) {
586 case TSTRING:
587 v->store.u.string->gc.gcmark = 1;
588 break;
589 case TLIST:
590 marklist(v->store.u.l);
591 break;
592 case TCODE:
593 marktree(v->store.u.cc);
594 break;
595 case TCON:
596 marktree(v->store.u.con);
597 break;
603 /* Free */
604 p = &gcl;
605 for(m = gcl; m; m = next) {
606 next = m->gclink;
607 if(m->gcmark == 0) {
608 *p = next;
609 free(m); /* Sleazy reliance on my malloc */
611 else
612 p = &m->gclink;
616 void*
617 gmalloc(long l)
619 void *p;
621 dogc += l;
622 p = malloc(l);
623 if(p == 0)
624 fatal("out of memory");
625 return p;
628 void
629 checkqid(int f1, int pid)
631 int fd;
632 Dir *d1, *d2;
633 char buf[128];
635 if(kernel)
636 return;
638 d1 = dirfstat(f1);
639 if(d1 == nil){
640 print("checkqid: (qid not checked) dirfstat: %r\n");
641 return;
644 sprint(buf, "/proc/%d/text", pid);
645 fd = open(buf, OREAD);
646 if(fd < 0 || (d2 = dirfstat(fd)) == nil){
647 print("checkqid: (qid not checked) dirstat %s: %r\n", buf);
648 free(d1);
649 if(fd >= 0)
650 close(fd);
651 return;
654 close(fd);
656 if(d1->qid.path != d2->qid.path || d1->qid.vers != d2->qid.vers || d1->qid.type != d2->qid.type){
657 print("path %llux %llux vers %lud %lud type %d %d\n",
658 d1->qid.path, d2->qid.path, d1->qid.vers, d2->qid.vers, d1->qid.type, d2->qid.type);
659 print("warning: image does not match text for pid %d\n", pid);
661 free(d1);
662 free(d2);
665 void
666 catcher(void *junk, char *s)
668 USED(junk);
670 if(strstr(s, "interrupt")) {
671 gotint = 1;
672 noted(NCONT);
674 if(strstr(s, "child"))
675 noted(NCONT);
676 fprint(2, "note: %s\n", s);
677 noted(NDFLT);
680 char*
681 system(void)
683 char *cpu, *p, *q;
684 static char kernel[128];
686 cpu = getenv("cputype");
687 if(cpu == 0) {
688 cpu = "mips";
689 print("$cputype not set; assuming %s\n", cpu);
691 p = getenv("terminal");
692 if(p == 0 || (p=strchr(p, ' ')) == 0 || p[1] == ' ' || p[1] == 0) {
693 p = "9power";
694 print("missing or bad $terminal; assuming %s\n", p);
696 else{
697 p++;
698 q = strchr(p, ' ');
699 if(q)
700 *q = 0;
701 sprint(kernel, "/%s/9%s", cpu, p);
703 return kernel;
706 int
707 isnumeric(char *s)
709 while(*s) {
710 if(*s < '0' || *s > '9')
711 return 0;
712 s++;
714 return 1;
717 int
718 xfmt(Fmt *f)
720 f->flags ^= FmtSharp;
721 return __ifmt(f);