cmd.c 9.4 KB

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