cmd.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662
  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 <ctype.h>
  12. #include <bio.h>
  13. #include <mach.h>
  14. #define Extern extern
  15. #include "power.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. cp = nextc(cp);
  170. switch(*cp) {
  171. default:
  172. Bprint(bioout, "?\n");
  173. break;
  174. case 'c':
  175. case 'C':
  176. stktrace(*cp);
  177. break;
  178. case 'b':
  179. dobplist();
  180. break;
  181. case 'r':
  182. dumpreg();
  183. break;
  184. case 'R':
  185. dumpreg();
  186. /* fall through */
  187. case 'f':
  188. dumpfreg();
  189. break;
  190. case 'F':
  191. dumpdreg();
  192. break;
  193. case 'q':
  194. exits(0);
  195. break;
  196. case 'Q':
  197. isum();
  198. segsum();
  199. break;
  200. case 't':
  201. cp++;
  202. switch(*cp) {
  203. default:
  204. Bprint(bioout, ":t[0sic]\n");
  205. break;
  206. case '\0':
  207. trace = 1;
  208. break;
  209. case '0':
  210. trace = 0;
  211. sysdbg = 0;
  212. calltree = 0;
  213. break;
  214. case 's':
  215. sysdbg = 1;
  216. break;
  217. case 'i':
  218. trace = 1;
  219. break;
  220. case 'c':
  221. calltree = 1;
  222. break;
  223. }
  224. break;
  225. case 'i':
  226. cp++;
  227. switch(*cp) {
  228. default:
  229. Bprint(bioout, "$i[isa]\n");
  230. break;
  231. case 'i':
  232. isum();
  233. break;
  234. case 's':
  235. segsum();
  236. break;
  237. case 'a':
  238. isum();
  239. segsum();
  240. iprofile();
  241. break;
  242. case 'p':
  243. iprofile();
  244. break;
  245. }
  246. }
  247. }
  248. int
  249. pfmt(char fmt, int mem, uint32_t val)
  250. {
  251. int c, i;
  252. Symbol s;
  253. char *p, ch, str[1024];
  254. c = 0;
  255. switch(fmt) {
  256. default:
  257. Bprint(bioout, "bad modifier\n");
  258. return 0;
  259. case 'o':
  260. c = Bprint(bioout, "%-4lo ",
  261. mem ? (uint16_t)getmem_2(dot) : val);
  262. inc = 2;
  263. break;
  264. case 'O':
  265. c = Bprint(bioout, "%-8lo ", mem ? getmem_4(dot) : val);
  266. inc = 4;
  267. break;
  268. case 'q':
  269. c = Bprint(bioout, "%-4lo ",
  270. mem ? (int16_t)getmem_2(dot) : val);
  271. inc = 2;
  272. break;
  273. case 'Q':
  274. c = Bprint(bioout, "%-8lo ",
  275. mem ? (int32_t)getmem_4(dot) : val);
  276. inc = 4;
  277. break;
  278. case 'd':
  279. c = Bprint(bioout, "%-5ld ",
  280. mem ? (int16_t)getmem_2(dot) : val);
  281. inc = 2;
  282. break;
  283. case 'D':
  284. c = Bprint(bioout, "%-8ld ",
  285. mem ? (int32_t)getmem_4(dot) : val);
  286. inc = 4;
  287. break;
  288. case 'x':
  289. c = Bprint(bioout, "#%-4lux ",
  290. mem ? (int32_t)getmem_2(dot) : val);
  291. inc = 2;
  292. break;
  293. case 'X':
  294. c = Bprint(bioout, "#%-8lux ",
  295. mem ? (int32_t)getmem_4(dot) : val);
  296. inc = 4;
  297. break;
  298. case 'u':
  299. c = Bprint(bioout, "%-5ld ",
  300. mem ? (uint16_t)getmem_2(dot) : val);
  301. inc = 2;
  302. break;
  303. case 'U':
  304. c = Bprint(bioout, "%-8ld ",
  305. mem ? (uint32_t)getmem_4(dot) : val);
  306. inc = 4;
  307. break;
  308. case 'b':
  309. c = Bprint(bioout, "%-3ld ", mem ? getmem_b(dot) : val);
  310. inc = 1;
  311. break;
  312. case 'c':
  313. c = Bprint(bioout, "%c ", (int)(mem ? getmem_b(dot) : val));
  314. inc = 1;
  315. break;
  316. case 'C':
  317. ch = mem ? getmem_b(dot) : val;
  318. if(isprint(ch))
  319. c = Bprint(bioout, "%c ", ch);
  320. else
  321. c = Bprint(bioout, "\\x%.2x ", ch);
  322. inc = 1;
  323. break;
  324. case 's':
  325. i = 0;
  326. while(ch = getmem_b(dot+i))
  327. str[i++] = ch;
  328. str[i] = '\0';
  329. dot += i;
  330. c = Bprint(bioout, "%s", str);
  331. inc = 0;
  332. break;
  333. case 'S':
  334. i = 0;
  335. while(ch = getmem_b(dot+i))
  336. str[i++] = ch;
  337. str[i] = '\0';
  338. dot += i;
  339. for(p = str; *p; p++)
  340. if(isprint(*p))
  341. c += Bprint(bioout, "%c", *p);
  342. else
  343. c += Bprint(bioout, "\\x%.2ux", *p);
  344. inc = 0;
  345. break;
  346. case 'Y':
  347. p = ctime(mem ? getmem_b(dot) : val);
  348. p[30] = '\0';
  349. c = Bprint(bioout, "%s", p);
  350. inc = 4;
  351. break;
  352. case 'a':
  353. symoff(str, sizeof(str), dot, CTEXT);
  354. Bprint(bioout, "%s", str);
  355. inc = 0;
  356. break;
  357. case 'e':
  358. for (i = 0; globalsym(&s, i); i++)
  359. Bprint(bioout, "%-15s #%lux\n", s.name, getmem_4(s.value));
  360. inc = 0;
  361. break;
  362. case 'I':
  363. case 'i':
  364. inc = machdata->das(symmap, dot, fmt, str, sizeof(str));
  365. if (inc < 0) {
  366. Bprint(bioout, "qi: %r\n");
  367. return 0;
  368. }
  369. c = Bprint(bioout, "\t%s", str);
  370. break;
  371. case 'n':
  372. c = width+1;
  373. inc = 0;
  374. break;
  375. case '-':
  376. c = 0;
  377. inc = -1;
  378. break;
  379. case '+':
  380. c = 0;
  381. inc = 1;
  382. break;
  383. case '^':
  384. c = 0;
  385. if(inc > 0)
  386. inc = -inc;
  387. break;
  388. case 'z':
  389. if (findsym(dot, CTEXT, &s))
  390. Bprint(bioout, " %s() ", s.name);
  391. printsource(dot);
  392. inc = 0;
  393. break;
  394. }
  395. return c;
  396. }
  397. void
  398. eval(char *addr, char *p)
  399. {
  400. uint32_t val;
  401. val = expr(addr);
  402. p = nextc(p);
  403. if(*p == '\0') {
  404. p[0] = fmt;
  405. p[1] = '\0';
  406. }
  407. pfmt(*p, 0, val);
  408. Bprint(bioout, "\n");
  409. }
  410. void
  411. quesie(char *p)
  412. {
  413. int c, count, i;
  414. char tbuf[512];
  415. c = 0;
  416. symoff(tbuf, sizeof(tbuf), dot, CTEXT);
  417. Bprint(bioout, "%s?\t", tbuf);
  418. while(*p) {
  419. p = nextc(p);
  420. if(*p == '"') {
  421. for(p++; *p && *p != '"'; p++) {
  422. Bputc(bioout, *p);
  423. c++;
  424. }
  425. if(*p)
  426. p++;
  427. continue;
  428. }
  429. count = 0;
  430. while(*p >= '0' && *p <= '9')
  431. count = count*10 + (*p++ - '0');
  432. if(count == 0)
  433. count = 1;
  434. p = nextc(p);
  435. if(*p == '\0') {
  436. p[0] = fmt;
  437. p[1] = '\0';
  438. }
  439. for(i = 0; i < count; i++) {
  440. c += pfmt(*p, 1, 0);
  441. dot += inc;
  442. if(c > width) {
  443. Bprint(bioout, "\n");
  444. symoff(tbuf, sizeof(tbuf), dot, CTEXT);
  445. Bprint(bioout, "%s?\t", tbuf);
  446. c = 0;
  447. }
  448. }
  449. fmt = *p++;
  450. p = nextc(p);
  451. }
  452. Bprint(bioout, "\n");
  453. }
  454. void
  455. catcher(void *a, char *msg)
  456. {
  457. USED(a);
  458. if(strcmp(msg, "interrupt") != 0)
  459. noted(NDFLT);
  460. count = 1;
  461. print("qi\n");
  462. noted(NCONT);
  463. }
  464. void
  465. setreg(char *addr, char *cp)
  466. {
  467. int rn;
  468. dot = expr(addr);
  469. cp = nextc(cp);
  470. if(strcmp(cp, "pc") == 0) {
  471. reg.pc = dot;
  472. return;
  473. }
  474. if(strcmp(cp, "sp") == 0) {
  475. reg.r[1] = dot;
  476. return;
  477. }
  478. if(strcmp(cp, "lr") == 0) {
  479. reg.lr = dot;
  480. return;
  481. }
  482. if(strcmp(cp, "ctr") == 0) {
  483. reg.ctr = dot;
  484. return;
  485. }
  486. if(strcmp(cp, "fpscr") == 0) {
  487. reg.fpscr = dot;
  488. return;
  489. }
  490. if(strcmp(cp, "xer") == 0) {
  491. reg.xer = dot;
  492. return;
  493. }
  494. if(strcmp(cp, "cr") == 0) {
  495. reg.cr = dot;
  496. return;
  497. }
  498. if(*cp++ == 'r') {
  499. rn = strtoul(cp, 0, 10);
  500. if(rn > 0 && rn < 32) {
  501. reg.r[rn] = dot;
  502. return;
  503. }
  504. }
  505. Bprint(bioout, "bad register\n");
  506. }
  507. void
  508. cmd(void)
  509. {
  510. char *p, *a, *cp, *gotint;
  511. char addr[128];
  512. static char *cmdlet = ":$?/=>";
  513. int n, i;
  514. notify(catcher);
  515. dot = reg.pc;
  516. setjmp(errjmp);
  517. for(;;) {
  518. Bflush(bioout);
  519. p = buf;
  520. n = 0;
  521. for(;;) {
  522. i = Bgetc(bin);
  523. if(i < 0)
  524. exits(0);
  525. *p++ = i;
  526. n++;
  527. if(i == '\n')
  528. break;
  529. }
  530. if(buf[0] == '\n')
  531. strcpy(buf, lastcmd);
  532. else {
  533. buf[n-1] = '\0';
  534. strcpy(lastcmd, buf);
  535. }
  536. p = buf;
  537. a = addr;
  538. for(;;) {
  539. p = nextc(p);
  540. if(*p == 0 || strchr(cmdlet, *p))
  541. break;
  542. *a++ = *p++;
  543. }
  544. *a = '\0';
  545. cmdcount = 1;
  546. cp = strchr(addr, ',');
  547. if(cp != 0) {
  548. if(cp[1] == '#')
  549. cmdcount = strtoul(cp+2, &gotint, 16);
  550. else
  551. cmdcount = strtoul(cp+1, &gotint, 0);
  552. *cp = '\0';
  553. }
  554. switch(*p) {
  555. case '$':
  556. dollar(p+1);
  557. break;
  558. case ':':
  559. colon(addr, p+1);
  560. break;
  561. case '/':
  562. case '?':
  563. dot = expr(addr);
  564. for(i = 0; i < cmdcount; i++)
  565. quesie(p+1);
  566. break;
  567. case '=':
  568. eval(addr, p+1);
  569. break;
  570. case '>':
  571. setreg(addr, p+1);
  572. break;
  573. default:
  574. Bprint(bioout, "?\n");
  575. break;
  576. }
  577. }
  578. }