main.c 8.3 KB

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