cmd.c 8.7 KB

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