machdata.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  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. /*
  10. * Debugger utilities shared by at least two architectures
  11. */
  12. #include <u.h>
  13. #include <libc.h>
  14. #include <bio.h>
  15. #include <mach.h>
  16. #define STARTSYM "_main"
  17. #define PROFSYM "_mainp"
  18. #define FRAMENAME ".frame"
  19. extern Machdata mipsmach;
  20. int asstype = AMIPS; /* disassembler type */
  21. Machdata *machdata; /* machine-dependent functions */
  22. int
  23. localaddr(Map *map, char *fn, char *var, uint64_t *r, Rgetter rget)
  24. {
  25. Symbol s;
  26. uint64_t fp, pc, sp, link;
  27. if (!lookup(fn, 0, &s)) {
  28. werrstr("function not found");
  29. return -1;
  30. }
  31. pc = rget(map, mach->pc);
  32. sp = rget(map, mach->sp);
  33. if(mach->link)
  34. link = rget(map, mach->link);
  35. else
  36. link = 0;
  37. fp = machdata->findframe(map, s.value, pc, sp, link);
  38. if (fp == 0) {
  39. werrstr("stack frame not found");
  40. return -1;
  41. }
  42. if (!var || !var[0]) {
  43. *r = fp;
  44. return 1;
  45. }
  46. if (findlocal(&s, var, &s) == 0) {
  47. werrstr("local variable not found");
  48. return -1;
  49. }
  50. switch (s.class) {
  51. case CAUTO:
  52. *r = fp - s.value;
  53. break;
  54. case CPARAM: /* assume address size is stack width */
  55. *r = fp + s.value + mach->szaddr;
  56. break;
  57. default:
  58. werrstr("local variable not found: %d", s.class);
  59. return -1;
  60. }
  61. return 1;
  62. }
  63. /*
  64. * Print value v as s.name[+offset] if possible, or just v.
  65. */
  66. int
  67. symoff(char *buf, int n, uint64_t v, int space)
  68. {
  69. Symbol s;
  70. int r;
  71. int32_t delta;
  72. r = delta = 0; /* to shut compiler up */
  73. if (v) {
  74. r = findsym(v, space, &s);
  75. if (r)
  76. delta = v-s.value;
  77. if (delta < 0)
  78. delta = -delta;
  79. }
  80. if (v == 0 || r == 0)
  81. return snprint(buf, n, "%llux", v);
  82. if (s.type != 't' && s.type != 'T' && delta >= 4096)
  83. return snprint(buf, n, "%llux", v);
  84. else if (delta)
  85. return snprint(buf, n, "%s+%lx", s.name, delta);
  86. else
  87. return snprint(buf, n, "%s", s.name);
  88. }
  89. /*
  90. * Format floating point registers
  91. *
  92. * Register codes in format field:
  93. * 'X' - print as 32-bit hexadecimal value
  94. * 'F' - 64-bit double register when modif == 'F'; else 32-bit single reg
  95. * 'f' - 32-bit ieee float
  96. * '8' - big endian 80-bit ieee extended float
  97. * '3' - little endian 80-bit ieee extended float with hole in bytes 8&9
  98. */
  99. int
  100. fpformat(Map *map, Reglist *rp, char *buf, int n, int modif)
  101. {
  102. char reg[12];
  103. uint32_t r;
  104. switch(rp->rformat)
  105. {
  106. case 'X':
  107. if (get4(map, rp->roffs, &r) < 0)
  108. return -1;
  109. snprint(buf, n, "%lx", r);
  110. break;
  111. case 'F': /* first reg of double reg pair */
  112. if (modif == 'F')
  113. if ((rp->rformat=='F') || (((rp+1)->rflags&RFLT) && (rp+1)->rformat == 'f')) {
  114. if (get1(map, rp->roffs, (uint8_t *)reg, 8) < 0)
  115. return -1;
  116. machdata->dftos(buf, n, reg);
  117. if (rp->rformat == 'F')
  118. return 1;
  119. return 2;
  120. }
  121. /* treat it like 'f' */
  122. if (get1(map, rp->roffs, (uint8_t *)reg, 4) < 0)
  123. return -1;
  124. machdata->sftos(buf, n, reg);
  125. break;
  126. case 'f': /* 32 bit float */
  127. if (get1(map, rp->roffs, (uint8_t *)reg, 4) < 0)
  128. return -1;
  129. machdata->sftos(buf, n, reg);
  130. break;
  131. case '3': /* little endian ieee 80 with hole in bytes 8&9 */
  132. if (get1(map, rp->roffs, (uint8_t *)reg, 10) < 0)
  133. return -1;
  134. memmove(reg+10, reg+8, 2); /* open hole */
  135. memset(reg+8, 0, 2); /* fill it */
  136. leieee80ftos(buf, n, reg);
  137. break;
  138. case '8': /* big-endian ieee 80 */
  139. if (get1(map, rp->roffs, (uint8_t *)reg, 10) < 0)
  140. return -1;
  141. beieee80ftos(buf, n, reg);
  142. break;
  143. default: /* unknown */
  144. break;
  145. }
  146. return 1;
  147. }
  148. char *
  149. _hexify(char *buf, uint32_t p, int zeros)
  150. {
  151. uint32_t d;
  152. d = p/16;
  153. if(d)
  154. buf = _hexify(buf, d, zeros-1);
  155. else
  156. while(zeros--)
  157. *buf++ = '0';
  158. *buf++ = "0123456789abcdef"[p&0x0f];
  159. return buf;
  160. }
  161. /*
  162. * These routines assume that if the number is representable
  163. * in IEEE floating point, it will be representable in the native
  164. * double format. Naive but workable, probably.
  165. */
  166. int
  167. ieeedftos(char *buf, int n, uint32_t h, uint32_t l)
  168. {
  169. double fr;
  170. int exp;
  171. if (n <= 0)
  172. return 0;
  173. if(h & (1L<<31)){
  174. *buf++ = '-';
  175. h &= ~(1L<<31);
  176. }else
  177. *buf++ = ' ';
  178. n--;
  179. if(l == 0 && h == 0)
  180. return snprint(buf, n, "0.");
  181. exp = (h>>20) & ((1L<<11)-1L);
  182. if(exp == 0)
  183. return snprint(buf, n, "DeN(%.8lux%.8lux)", h, l);
  184. if(exp == ((1L<<11)-1L)){
  185. if(l==0 && (h&((1L<<20)-1L)) == 0)
  186. return snprint(buf, n, "Inf");
  187. else
  188. return snprint(buf, n, "NaN(%.8lux%.8lux)", h&((1L<<20)-1L), l);
  189. }
  190. exp -= (1L<<10) - 2L;
  191. fr = l & ((1L<<16)-1L);
  192. fr /= 1L<<16;
  193. fr += (l>>16) & ((1L<<16)-1L);
  194. fr /= 1L<<16;
  195. fr += (h & (1L<<20)-1L) | (1L<<20);
  196. fr /= 1L<<21;
  197. fr = ldexp(fr, exp);
  198. return snprint(buf, n, "%.18g", fr);
  199. }
  200. int
  201. ieeesftos(char *buf, int n, uint32_t h)
  202. {
  203. double fr;
  204. int exp;
  205. if (n <= 0)
  206. return 0;
  207. if(h & (1L<<31)){
  208. *buf++ = '-';
  209. h &= ~(1L<<31);
  210. }else
  211. *buf++ = ' ';
  212. n--;
  213. if(h == 0)
  214. return snprint(buf, n, "0.");
  215. exp = (h>>23) & ((1L<<8)-1L);
  216. if(exp == 0)
  217. return snprint(buf, n, "DeN(%.8lux)", h);
  218. if(exp == ((1L<<8)-1L)){
  219. if((h&((1L<<23)-1L)) == 0)
  220. return snprint(buf, n, "Inf");
  221. else
  222. return snprint(buf, n, "NaN(%.8lux)", h&((1L<<23)-1L));
  223. }
  224. exp -= (1L<<7) - 2L;
  225. fr = (h & ((1L<<23)-1L)) | (1L<<23);
  226. fr /= 1L<<24;
  227. fr = ldexp(fr, exp);
  228. return snprint(buf, n, "%.9g", fr);
  229. }
  230. int
  231. beieeesftos(char *buf, int n, void *s)
  232. {
  233. return ieeesftos(buf, n, beswal(*(uint32_t*)s));
  234. }
  235. int
  236. beieeedftos(char *buf, int n, void *s)
  237. {
  238. return ieeedftos(buf, n, beswal(*(uint32_t*)s),
  239. beswal(((uint32_t*)(s))[1]));
  240. }
  241. int
  242. leieeesftos(char *buf, int n, void *s)
  243. {
  244. return ieeesftos(buf, n, leswal(*(uint32_t*)s));
  245. }
  246. int
  247. leieeedftos(char *buf, int n, void *s)
  248. {
  249. return ieeedftos(buf, n, leswal(((uint32_t*)(s))[1]),
  250. leswal(*(uint32_t*)s));
  251. }
  252. /* packed in 12 bytes, with s[2]==s[3]==0; mantissa starts at s[4]*/
  253. int
  254. beieee80ftos(char *buf, int n, void *s)
  255. {
  256. uint8_t *reg = (uint8_t*)s;
  257. int i;
  258. uint32_t x;
  259. uint8_t ieee[8+8]; /* room for slop */
  260. uint8_t *p, *q;
  261. memset(ieee, 0, sizeof(ieee));
  262. /* sign */
  263. if(reg[0] & 0x80)
  264. ieee[0] |= 0x80;
  265. /* exponent */
  266. x = ((reg[0]&0x7F)<<8) | reg[1];
  267. if(x == 0) /* number is ±0 */
  268. goto done;
  269. if(x == 0x7FFF){
  270. if(memcmp(reg+4, ieee+1, 8) == 0){ /* infinity */
  271. x = 2047;
  272. }else{ /* NaN */
  273. x = 2047;
  274. ieee[7] = 0x1; /* make sure */
  275. }
  276. ieee[0] |= x>>4;
  277. ieee[1] |= (x&0xF)<<4;
  278. goto done;
  279. }
  280. x -= 0x3FFF; /* exponent bias */
  281. x += 1023;
  282. if(x >= (1<<11) || ((reg[4]&0x80)==0 && x!=0))
  283. return snprint(buf, n, "not in range");
  284. ieee[0] |= x>>4;
  285. ieee[1] |= (x&0xF)<<4;
  286. /* mantissa */
  287. p = reg+4;
  288. q = ieee+1;
  289. for(i=0; i<56; i+=8, p++, q++){ /* move one byte */
  290. x = (p[0]&0x7F) << 1;
  291. if(p[1] & 0x80)
  292. x |= 1;
  293. q[0] |= x>>4;
  294. q[1] |= (x&0xF)<<4;
  295. }
  296. done:
  297. return beieeedftos(buf, n, (void*)ieee);
  298. }
  299. int
  300. leieee80ftos(char *buf, int n, void *s)
  301. {
  302. int i;
  303. char *cp;
  304. char b[12];
  305. cp = (char*) s;
  306. for(i=0; i<12; i++)
  307. b[11-i] = *cp++;
  308. return beieee80ftos(buf, n, b);
  309. }
  310. int
  311. cisctrace(Map *map, uint64_t pc, uint64_t sp, uint64_t link, Tracer trace)
  312. {
  313. Symbol s;
  314. int found, i;
  315. uint64_t opc, moved;
  316. USED(link);
  317. i = 0;
  318. opc = 0;
  319. while(pc && opc != pc) {
  320. moved = pc2sp(pc);
  321. if (moved == ~0)
  322. break;
  323. found = findsym(pc, CTEXT, &s);
  324. if (!found)
  325. break;
  326. if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
  327. break;
  328. sp += moved;
  329. opc = pc;
  330. if (geta(map, sp, &pc) < 0)
  331. break;
  332. (*trace)(map, pc, sp, &s);
  333. sp += mach->szaddr; /*assumes address size = stack width*/
  334. if(++i > 40)
  335. break;
  336. }
  337. return i;
  338. }
  339. int
  340. risctrace(Map *map, uint64_t pc, uint64_t sp, uint64_t link, Tracer trace)
  341. {
  342. int i;
  343. Symbol s, f;
  344. uint64_t oldpc;
  345. i = 0;
  346. while(findsym(pc, CTEXT, &s)) {
  347. if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
  348. break;
  349. if(pc == s.value) /* at first instruction */
  350. f.value = 0;
  351. else if(findlocal(&s, FRAMENAME, &f) == 0)
  352. break;
  353. oldpc = pc;
  354. if(s.type == 'L' || s.type == 'l' || pc <= s.value+mach->pcquant)
  355. pc = link;
  356. else
  357. if (geta(map, sp, &pc) < 0)
  358. break;
  359. if(pc == 0 || (pc == oldpc && f.value == 0))
  360. break;
  361. sp += f.value;
  362. (*trace)(map, pc-8, sp, &s);
  363. if(++i > 40)
  364. break;
  365. }
  366. return i;
  367. }
  368. uint64_t
  369. ciscframe(Map *map, uint64_t addr, uint64_t pc, uint64_t sp, uint64_t link)
  370. {
  371. Symbol s;
  372. uint64_t moved;
  373. USED(link);
  374. for(;;) {
  375. moved = pc2sp(pc);
  376. if (moved == ~0)
  377. break;
  378. sp += moved;
  379. findsym(pc, CTEXT, &s);
  380. if (addr == s.value)
  381. return sp;
  382. if (geta(map, sp, &pc) < 0)
  383. break;
  384. sp += mach->szaddr; /*assumes sizeof(addr) = stack width*/
  385. }
  386. return 0;
  387. }
  388. uint64_t
  389. riscframe(Map *map, uint64_t addr, uint64_t pc, uint64_t sp, uint64_t link)
  390. {
  391. Symbol s, f;
  392. while (findsym(pc, CTEXT, &s)) {
  393. if(strcmp(STARTSYM, s.name) == 0 || strcmp(PROFSYM, s.name) == 0)
  394. break;
  395. if(pc == s.value) /* at first instruction */
  396. f.value = 0;
  397. else
  398. if(findlocal(&s, FRAMENAME, &f) == 0)
  399. break;
  400. sp += f.value;
  401. if (s.value == addr)
  402. return sp;
  403. if (s.type == 'L' || s.type == 'l' || pc-s.value <= mach->szaddr*2)
  404. pc = link;
  405. else
  406. if (geta(map, sp-f.value, &pc) < 0)
  407. break;
  408. }
  409. return 0;
  410. }