main.c 8.4 KB

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