cmd.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <mach.h>
  5. #include <ctype.h>
  6. #define Extern extern
  7. #include "mips.h"
  8. char buf[128], lastcmd[128];
  9. char fmt = 'X';
  10. int width = 60;
  11. int inc;
  12. ulong expr(char*);
  13. ulong expr1(char*);
  14. char* term(char*, ulong*);
  15. char *
  16. nextc(char *p)
  17. {
  18. while(*p && (*p == ' ' || *p == '\t') && *p != '\n')
  19. p++;
  20. if(*p == '\n')
  21. *p = '\0';
  22. return p;
  23. }
  24. char *
  25. numsym(char *addr, ulong *val)
  26. {
  27. char tsym[128], *t;
  28. static char *delim = "`'<>/\\@*|-~+-/=?\n";
  29. Symbol s;
  30. char c;
  31. t = tsym;
  32. while(c = *addr) {
  33. if(strchr(delim, c))
  34. break;
  35. *t++ = c;
  36. addr++;
  37. }
  38. t[0] = '\0';
  39. if(strcmp(tsym, ".") == 0) {
  40. *val = dot;
  41. return addr;
  42. }
  43. if(lookup(0, tsym, &s))
  44. *val = s.value;
  45. else {
  46. if(tsym[0] == '#')
  47. *val = strtoul(tsym+1, 0, 16);
  48. else
  49. *val = strtoul(tsym, 0, 0);
  50. }
  51. return addr;
  52. }
  53. ulong
  54. expr(char *addr)
  55. {
  56. ulong t, t2;
  57. char op;
  58. if(*addr == '\0')
  59. return dot;
  60. addr = numsym(addr, &t);
  61. if(*addr == '\0')
  62. return t;
  63. addr = nextc(addr);
  64. op = *addr++;
  65. numsym(addr, &t2);
  66. switch(op) {
  67. default:
  68. Bprint(bioout, "expr syntax\n");
  69. return 0;
  70. case '+':
  71. t += t2;
  72. break;
  73. case '-':
  74. t -= t2;
  75. break;
  76. case '%':
  77. t /= t2;
  78. break;
  79. case '&':
  80. t &= t2;
  81. break;
  82. case '|':
  83. t |= t2;
  84. break;
  85. }
  86. return t;
  87. }
  88. int
  89. buildargv(char *str, char **args, int max)
  90. {
  91. int na = 0;
  92. while (na < max) {
  93. while((*str == ' ' || *str == '\t' || *str == '\n') && *str != '\0')
  94. str++;
  95. if(*str == '\0')
  96. return na;
  97. args[na++] = str;
  98. while(!(*str == ' ' || *str == '\t'|| *str == '\n') && *str != '\0')
  99. str++;
  100. if(*str == '\n')
  101. *str = '\0';
  102. if(*str == '\0')
  103. break;
  104. *str++ = '\0';
  105. }
  106. return na;
  107. }
  108. void
  109. colon(char *addr, char *cp)
  110. {
  111. int argc;
  112. char *argv[100];
  113. char tbuf[512];
  114. cp = nextc(cp);
  115. switch(*cp) {
  116. default:
  117. Bprint(bioout, "?\n");
  118. return;
  119. case 'b':
  120. breakpoint(addr, cp+1);
  121. return;
  122. case 'd':
  123. delbpt(addr);
  124. return;
  125. /* These fall through to print the stopped address */
  126. case 'r':
  127. reset();
  128. argc = buildargv(cp+1, argv, 100);
  129. initstk(argc, argv);
  130. count = 0;
  131. atbpt = 0;
  132. run();
  133. break;
  134. case 'c':
  135. count = 0;
  136. atbpt = 0;
  137. run();
  138. break;
  139. case 's':
  140. cp = nextc(cp+1);
  141. count = 0;
  142. if(*cp)
  143. count = strtoul(cp, 0, 0);
  144. if(count == 0)
  145. count = 1;
  146. atbpt = 0;
  147. run();
  148. break;
  149. }
  150. dot = reg.pc;
  151. Bprint(bioout, "%s at #%lux ", atbpt ? "breakpoint" : "stopped", dot);
  152. symoff(tbuf, sizeof(tbuf), dot, CTEXT);
  153. Bprint(bioout, tbuf);
  154. if(fmt == 'z')
  155. printsource(dot);
  156. Bprint(bioout, "\n");
  157. }
  158. void
  159. dollar(char *cp)
  160. {
  161. int nr;
  162. cp = nextc(cp);
  163. switch(*cp) {
  164. default:
  165. Bprint(bioout, "?\n");
  166. break;
  167. case 'c':
  168. stktrace(*cp);
  169. break;
  170. case 'C':
  171. stktrace(*cp);
  172. break;
  173. case 'b':
  174. dobplist();
  175. break;
  176. case 'r':
  177. dumpreg();
  178. break;
  179. case 'R':
  180. dumpreg();
  181. case 'f':
  182. dumpfreg();
  183. break;
  184. case 'F':
  185. dumpdreg();
  186. break;
  187. case 'q':
  188. exits(0);
  189. break;
  190. case 'Q':
  191. isum();
  192. tlbsum();
  193. segsum();
  194. break;
  195. case 't':
  196. cp++;
  197. switch(*cp) {
  198. default:
  199. Bprint(bioout, "$t[0sicr#]\n");
  200. break;
  201. case '\0':
  202. trace = 1;
  203. break;
  204. case '0':
  205. trace = 0;
  206. sysdbg = 0;
  207. calltree = 0;
  208. break;
  209. case 's':
  210. sysdbg = 1;
  211. break;
  212. case 'i':
  213. trace = 1;
  214. break;
  215. case 'c':
  216. calltree = 1;
  217. break;
  218. case 'r':
  219. nr = atoi(cp+1);
  220. if(nr < 0 || nr > 31) {
  221. print("bad register\n");
  222. break;
  223. }
  224. rtrace ^= (1<<nr);
  225. print("%.8ux\n", rtrace);
  226. break;
  227. }
  228. break;
  229. case 'i':
  230. cp++;
  231. switch(*cp) {
  232. default:
  233. Bprint(bioout, "$i[itsa]\n");
  234. break;
  235. case 'i':
  236. isum();
  237. break;
  238. case 't':
  239. tlbsum();
  240. break;
  241. case 's':
  242. segsum();
  243. break;
  244. case 'a':
  245. isum();
  246. tlbsum();
  247. segsum();
  248. iprofile();
  249. break;
  250. case 'p':
  251. iprofile();
  252. break;
  253. }
  254. }
  255. }
  256. int
  257. pfmt(char fmt, int mem, ulong val)
  258. {
  259. int c, i;
  260. Symbol s;
  261. char *p, ch, str[1024];
  262. c = 0;
  263. switch(fmt) {
  264. default:
  265. Bprint(bioout, "bad modifier\n");
  266. return 0;
  267. case 'o':
  268. c = Bprint(bioout, "%-4lo ", mem ? (ushort)getmem_2(dot) : val);
  269. inc = 2;
  270. break;
  271. case 'O':
  272. c = Bprint(bioout, "%-8lo ", mem ? getmem_4(dot) : val);
  273. inc = 4;
  274. break;
  275. case 'q':
  276. c = Bprint(bioout, "%-4lo ", mem ? (short)getmem_2(dot) : val);
  277. inc = 2;
  278. break;
  279. case 'Q':
  280. c = Bprint(bioout, "%-8lo ", mem ? (long)getmem_4(dot) : val);
  281. inc = 4;
  282. break;
  283. case 'd':
  284. c = Bprint(bioout, "%-5ld ", mem ? (short)getmem_2(dot) : val);
  285. inc = 2;
  286. break;
  287. case 'D':
  288. c = Bprint(bioout, "%-8ld ", mem ? (long)getmem_4(dot) : val);
  289. inc = 4;
  290. break;
  291. case 'x':
  292. c = Bprint(bioout, "#%-4lux ", mem ? (long)getmem_2(dot) : val);
  293. inc = 2;
  294. break;
  295. case 'X':
  296. c = Bprint(bioout, "#%-8lux ", mem ? (long)getmem_4(dot) : val);
  297. inc = 4;
  298. break;
  299. case 'u':
  300. c = Bprint(bioout, "%-5ld ", mem ? (ushort)getmem_2(dot) : val);
  301. inc = 2;
  302. break;
  303. case 'U':
  304. c = Bprint(bioout, "%-8ld ", mem ? (ulong)getmem_4(dot) : val);
  305. inc = 4;
  306. break;
  307. case 'b':
  308. c = Bprint(bioout, "%-3ld ", mem ? getmem_b(dot) : val);
  309. inc = 1;
  310. break;
  311. case 'c':
  312. c = Bprint(bioout, "%c ", (int)(mem ? getmem_b(dot) : val));
  313. inc = 1;
  314. break;
  315. case 'C':
  316. ch = mem ? getmem_b(dot) : val;
  317. if(isprint(ch))
  318. c = Bprint(bioout, "%c ", ch);
  319. else
  320. c = Bprint(bioout, "\\x%.2x ", ch);
  321. inc = 1;
  322. break;
  323. case 's':
  324. i = 0;
  325. while(ch = getmem_b(dot+i))
  326. str[i++] = ch;
  327. str[i] = '\0';
  328. dot += i;
  329. c = Bprint(bioout, "%s", str);
  330. inc = 0;
  331. break;
  332. case 'S':
  333. i = 0;
  334. while(ch = getmem_b(dot+i))
  335. str[i++] = ch;
  336. str[i] = '\0';
  337. dot += i;
  338. for(p = str; *p; p++)
  339. if(isprint(*p))
  340. c += Bprint(bioout, "%c", *p);
  341. else
  342. c += Bprint(bioout, "\\x%.2ux", *p);
  343. inc = 0;
  344. break;
  345. case 'Y':
  346. p = ctime(mem ? getmem_b(dot) : val);
  347. p[30] = '\0';
  348. c = Bprint(bioout, "%s", p);
  349. inc = 4;
  350. break;
  351. case 'a':
  352. symoff(str, sizeof(str), dot, CTEXT);
  353. c = Bprint(bioout, str);
  354. inc = 0;
  355. break;
  356. case 'e':
  357. for (i = 0; globalsym(&s, i); i++)
  358. Bprint(bioout, "%-15s #%lux\n", s.name, getmem_4(s.value));
  359. inc = 0;
  360. break;
  361. case 'i':
  362. inc = _mipscoinst(symmap, dot, str, sizeof(str));
  363. if (inc < 0) {
  364. Bprint(bioout, "vi: %r\n");
  365. return 0;
  366. }
  367. c = Bprint(bioout, str);
  368. break;
  369. case 'n':
  370. c = width+1;
  371. inc = 0;
  372. break;
  373. case '-':
  374. c = 0;
  375. inc = -1;
  376. break;
  377. case '+':
  378. c = 0;
  379. inc = 1;
  380. break;
  381. case '^':
  382. c = 0;
  383. if(inc > 0)
  384. inc = -inc;
  385. break;
  386. case 'z':
  387. if (findsym(dot, CTEXT, &s))
  388. Bprint(bioout, " %s() ", s.name);
  389. printsource(dot);
  390. inc = 0;
  391. break;
  392. }
  393. return c;
  394. }
  395. void
  396. eval(char *addr, char *p)
  397. {
  398. ulong val;
  399. val = expr(addr);
  400. p = nextc(p);
  401. if(*p == '\0') {
  402. p[0] = fmt;
  403. p[1] = '\0';
  404. }
  405. pfmt(*p, 0, val);
  406. Bprint(bioout, "\n");
  407. }
  408. void
  409. quesie(char *p)
  410. {
  411. int c, count, i;
  412. char tbuf[512];
  413. c = 0;
  414. symoff(tbuf, sizeof(tbuf), dot, CTEXT);
  415. Bprint(bioout, "%s?\t", tbuf);
  416. while(*p) {
  417. p = nextc(p);
  418. if(*p == '"') {
  419. for(p++; *p && *p != '"'; p++) {
  420. Bputc(bioout, *p);
  421. c++;
  422. }
  423. if(*p)
  424. p++;
  425. continue;
  426. }
  427. count = 0;
  428. while(*p >= '0' && *p <= '9')
  429. count = count*10 + (*p++ - '0');
  430. if(count == 0)
  431. count = 1;
  432. p = nextc(p);
  433. if(*p == '\0') {
  434. p[0] = fmt;
  435. p[1] = '\0';
  436. }
  437. for(i = 0; i < count; i++) {
  438. c += pfmt(*p, 1, 0);
  439. dot += inc;
  440. if(c > width) {
  441. Bprint(bioout, "\n");
  442. symoff(tbuf, sizeof(tbuf), dot, CTEXT);
  443. Bprint(bioout, "%s?\t", tbuf);
  444. c = 0;
  445. }
  446. }
  447. fmt = *p++;
  448. p = nextc(p);
  449. }
  450. Bprint(bioout, "\n");
  451. }
  452. void
  453. catcher(void *a, char *msg)
  454. {
  455. USED(a);
  456. if(strcmp(msg, "interrupt") != 0)
  457. noted(NDFLT);
  458. count = 1;
  459. print("vi\n");
  460. noted(NCONT);
  461. }
  462. void
  463. setreg(char *addr, char *cp)
  464. {
  465. int rn;
  466. dot = expr(addr);
  467. cp = nextc(cp);
  468. if(strcmp(cp, "pc") == 0) {
  469. reg.pc = dot;
  470. return;
  471. }
  472. if(strcmp(cp, "sp") == 0) {
  473. reg.r[29] = dot;
  474. return;
  475. }
  476. if(strcmp(cp, "mh") == 0) {
  477. reg.mhi = dot;
  478. return;
  479. }
  480. if(strcmp(cp, "ml") == 0) {
  481. reg.mlo = dot;
  482. return;
  483. }
  484. if(*cp++ == 'r') {
  485. rn = strtoul(cp, 0, 10);
  486. if(rn > 0 && rn < 32) {
  487. reg.r[rn] = dot;
  488. return;
  489. }
  490. }
  491. Bprint(bioout, "bad register\n");
  492. }
  493. void
  494. cmd(void)
  495. {
  496. char *p, *a, *cp, *gotint;
  497. char addr[128];
  498. static char *cmdlet = ":$?/=>";
  499. int n, i;
  500. notify(catcher);
  501. dot = reg.pc;
  502. setjmp(errjmp);
  503. for(;;) {
  504. Bflush(bioout);
  505. p = buf;
  506. n = 0;
  507. for(;;) {
  508. i = Bgetc(bin);
  509. if(i < 0)
  510. exits(0);
  511. *p++ = i;
  512. n++;
  513. if(i == '\n')
  514. break;
  515. }
  516. if(buf[0] == '\n')
  517. strcpy(buf, lastcmd);
  518. else {
  519. buf[n-1] = '\0';
  520. strcpy(lastcmd, buf);
  521. }
  522. p = buf;
  523. a = addr;
  524. for(;;) {
  525. p = nextc(p);
  526. if(*p == 0 || strchr(cmdlet, *p))
  527. break;
  528. *a++ = *p++;
  529. }
  530. *a = '\0';
  531. cmdcount = 1;
  532. cp = strchr(addr, ',');
  533. if(cp != 0) {
  534. if(cp[1] == '#')
  535. cmdcount = strtoul(cp+2, &gotint, 16);
  536. else
  537. cmdcount = strtoul(cp+1, &gotint, 0);
  538. *cp = '\0';
  539. }
  540. switch(*p) {
  541. case '$':
  542. dollar(p+1);
  543. break;
  544. case ':':
  545. colon(addr, p+1);
  546. break;
  547. case '/':
  548. case '?':
  549. dot = expr(addr);
  550. for(i = 0; i < cmdcount; i++)
  551. quesie(p+1);
  552. break;
  553. case '=':
  554. eval(addr, p+1);
  555. break;
  556. case '>':
  557. setreg(addr, p+1);
  558. break;
  559. default:
  560. Bprint(bioout, "?\n");
  561. break;
  562. }
  563. }
  564. }