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