machdata.c 8.6 KB

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