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 void
30 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 }ARGEND
73 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));
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);
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();
136 stacked = 0;
138 Bprint(bout, "acid; ");
140 if(yyparse() != 1)
141 die();
142 restartio();
144 unwind();
146 Bputc(bout, '\n');
147 exits(0);
150 static int
151 attachfiles(int argc, char **argv)
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;
176 if(corhdr){
177 fprint(2, "already have core %s; ignoring pid %d\n", corfil, pid);
178 continue;
180 pid = atoi(argv[i]);
181 continue;
183 if((hdr = crackhdr(argv[i], omode)) == nil){
184 fprint(2, "crackhdr %s: %r\n", argv[i]);
185 continue;
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;
194 if(corhdr){
195 fprint(2, "already have core %s; ignoring core %s\n", corfil, argv[i]);
196 uncrackhdr(hdr);
197 continue;
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;
207 symhdr = hdr;
208 symfil = argv[i];
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;
220 /* XXX pull command from core */
222 if((symhdr = crackhdr(symfil, omode)) == nil){
223 fprint(2, "crackhdr %s: %r\n", symfil);
224 symfil = nil;
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);
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;
284 void
285 setcore(Fhdr *hdr)
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;
300 void
301 die(void)
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);
315 exits(0);
318 void
319 userinit(void)
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);
334 interactive = 0;
335 if(setjmp(err)) {
336 unwind();
337 return;
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);
348 void
349 loadmodule(char *s)
351 interactive = 0;
352 if(setjmp(err)) {
353 unwind();
354 return;
356 pushfile(s);
357 silent = 0;
358 yyparse();
359 popio();
360 return;
363 Node*
364 an(int op, Node *l, Node *r)
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;
378 List*
379 al(int t)
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;
391 Node*
392 con(int v)
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;
403 void
404 fatal(char *fmt, ...)
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);
416 void
417 yyerror(char *fmt, ...)
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;
426 va_start(arg, fmt);
427 vseprint(buf, buf+sizeof(buf), fmt, arg);
428 va_end(arg);
429 print("%Z: %s\n", buf);
432 void
433 marktree(Node *n)
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;
459 void
460 marklist(List *l)
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;
475 l = l->next;
479 void
480 gc(void)
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;
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 */
525 else
526 p = &m->gclink;
530 void*
531 gmalloc(long l)
533 void *p;
535 dogc += l;
536 p = malloc(l);
537 if(p == 0)
538 fatal("out of memory");
539 return p;
542 void
543 checkqid(int f1, int pid)
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;
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;
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);
575 free(d1);
576 free(d2);
579 void
580 catcher(void *junk, char *s)
582 USED(junk);
584 if(strstr(s, "interrupt")) {
585 gotint = 1;
586 noted(NCONT);
588 if(strstr(s, "child"))
589 noted(NCONT);
590 fprint(2, "note: %s\n", s);
591 noted(NDFLT);
594 char*
595 system(void)
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);
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);
610 else{
611 p++;
612 q = strchr(p, ' ');
613 if(q)
614 *q = 0;
615 sprint(kernel, "/%s/9%s", cpu, p);
617 return kernel;
620 int
621 isnumeric(char *s)
623 while(*s) {
624 if(*s < '0' || *s > '9')
625 return 0;
626 s++;
628 return 1;
631 int
632 xfmt(Fmt *f)
634 f->flags ^= FmtSharp;
635 return __ifmt(f);