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