main.c 8.4 KB

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