machdata.c 8.6 KB

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