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