unwind-ia64.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074
  1. /* unwind-ia64.c -- utility routines to dump IA-64 unwind info for readelf.
  2. Copyright (C) 2000-2015 Free Software Foundation, Inc.
  3. Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
  4. This file is part of GNU Binutils.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3, or (at your option)
  8. any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, 51 Franklin Street - Fifth Floor, Boston,
  16. MA 02110-1301, USA. */
  17. #include "config.h"
  18. #include "unwind-ia64.h"
  19. #include <stdio.h>
  20. #include <string.h>
  21. #if __GNUC__ >= 2
  22. /* Define BFD64 here, even if our default architecture is 32 bit ELF
  23. as this will allow us to read in and parse 64bit and 32bit ELF files.
  24. Only do this if we believe that the compiler can support a 64 bit
  25. data type. For now we only rely on GCC being able to do this. */
  26. #define BFD64
  27. #endif
  28. #include "bfd.h"
  29. static bfd_vma unw_rlen = 0;
  30. static void unw_print_brmask (char *, unsigned int);
  31. static void unw_print_grmask (char *, unsigned int);
  32. static void unw_print_frmask (char *, unsigned int);
  33. static void unw_print_abreg (char *, unsigned int);
  34. static void unw_print_xyreg (char *, unsigned int, unsigned int);
  35. static void
  36. unw_print_brmask (char *cp, unsigned int mask)
  37. {
  38. int sep = 0;
  39. int i;
  40. for (i = 0; mask && (i < 5); ++i)
  41. {
  42. if (mask & 1)
  43. {
  44. if (sep)
  45. *cp++ = ',';
  46. *cp++ = 'b';
  47. *cp++ = i + 1 + '0';
  48. sep = 1;
  49. }
  50. mask >>= 1;
  51. }
  52. *cp = '\0';
  53. }
  54. static void
  55. unw_print_grmask (char *cp, unsigned int mask)
  56. {
  57. int sep = 0;
  58. int i;
  59. for (i = 0; i < 4; ++i)
  60. {
  61. if (mask & 1)
  62. {
  63. if (sep)
  64. *cp++ = ',';
  65. *cp++ = 'r';
  66. *cp++ = i + 4 + '0';
  67. sep = 1;
  68. }
  69. mask >>= 1;
  70. }
  71. *cp = '\0';
  72. }
  73. static void
  74. unw_print_frmask (char *cp, unsigned int mask)
  75. {
  76. int sep = 0;
  77. int i;
  78. for (i = 0; i < 20; ++i)
  79. {
  80. if (mask & 1)
  81. {
  82. if (sep)
  83. *cp++ = ',';
  84. *cp++ = 'f';
  85. if (i < 4)
  86. *cp++ = i + 2 + '0';
  87. else
  88. {
  89. *cp++ = (i + 2) / 10 + 1 + '0';
  90. *cp++ = (i + 2) % 10 + '0';
  91. }
  92. sep = 1;
  93. }
  94. mask >>= 1;
  95. }
  96. *cp = '\0';
  97. }
  98. static void
  99. unw_print_abreg (char *cp, unsigned int abreg)
  100. {
  101. static const char * const special_reg[16] =
  102. {
  103. "pr", "psp", "@priunat", "rp", "ar.bsp", "ar.bspstore", "ar.rnat",
  104. "ar.unat", "ar.fpsr", "ar.pfs", "ar.lc",
  105. "Unknown11", "Unknown12", "Unknown13", "Unknown14", "Unknown15"
  106. };
  107. switch ((abreg >> 5) & 0x3)
  108. {
  109. case 0: /* gr */
  110. sprintf (cp, "r%u", (abreg & 0x1f));
  111. break;
  112. case 1: /* fr */
  113. sprintf (cp, "f%u", (abreg & 0x1f));
  114. break;
  115. case 2: /* br */
  116. sprintf (cp, "b%u", (abreg & 0x1f));
  117. break;
  118. case 3: /* special */
  119. strcpy (cp, special_reg[abreg & 0xf]);
  120. break;
  121. }
  122. }
  123. static void
  124. unw_print_xyreg (char *cp, unsigned int x, unsigned int ytreg)
  125. {
  126. switch ((x << 1) | ((ytreg >> 7) & 1))
  127. {
  128. case 0: /* gr */
  129. sprintf (cp, "r%u", (ytreg & 0x1f));
  130. break;
  131. case 1: /* fr */
  132. sprintf (cp, "f%u", (ytreg & 0x1f));
  133. break;
  134. case 2: /* br */
  135. sprintf (cp, "b%u", (ytreg & 0x1f));
  136. break;
  137. }
  138. }
  139. #define UNW_REG_BSP "bsp"
  140. #define UNW_REG_BSPSTORE "bspstore"
  141. #define UNW_REG_FPSR "fpsr"
  142. #define UNW_REG_LC "lc"
  143. #define UNW_REG_PFS "pfs"
  144. #define UNW_REG_PR "pr"
  145. #define UNW_REG_PSP "psp"
  146. #define UNW_REG_RNAT "rnat"
  147. #define UNW_REG_RP "rp"
  148. #define UNW_REG_UNAT "unat"
  149. typedef bfd_vma unw_word;
  150. #define UNW_DEC_BAD_CODE(code) \
  151. printf ("Unknown code 0x%02x\n", code)
  152. #define UNW_DEC_PROLOGUE(fmt, body, rlen, arg) \
  153. do \
  154. { \
  155. unw_rlen = rlen; \
  156. *(int *)arg = body; \
  157. printf (" %s:%s(rlen=%lu)\n", \
  158. fmt, body ? "body" : "prologue", (unsigned long) rlen); \
  159. } \
  160. while (0)
  161. #define UNW_DEC_PROLOGUE_GR(fmt, rlen, mask, grsave, arg) \
  162. do \
  163. { \
  164. char regname[16], maskstr[64], *sep; \
  165. \
  166. unw_rlen = rlen; \
  167. *(int *)arg = 0; \
  168. \
  169. maskstr[0] = '\0'; \
  170. sep = ""; \
  171. if (mask & 0x8) \
  172. { \
  173. strcat (maskstr, "rp"); \
  174. sep = ","; \
  175. } \
  176. if (mask & 0x4) \
  177. { \
  178. strcat (maskstr, sep); \
  179. strcat (maskstr, "ar.pfs"); \
  180. sep = ","; \
  181. } \
  182. if (mask & 0x2) \
  183. { \
  184. strcat (maskstr, sep); \
  185. strcat (maskstr, "psp"); \
  186. sep = ","; \
  187. } \
  188. if (mask & 0x1) \
  189. { \
  190. strcat (maskstr, sep); \
  191. strcat (maskstr, "pr"); \
  192. } \
  193. sprintf (regname, "r%u", grsave); \
  194. printf (" %s:prologue_gr(mask=[%s],grsave=%s,rlen=%lu)\n", \
  195. fmt, maskstr, regname, (unsigned long) rlen); \
  196. } \
  197. while (0)
  198. #define UNW_DEC_FR_MEM(fmt, frmask, arg) \
  199. do \
  200. { \
  201. char frstr[200]; \
  202. \
  203. unw_print_frmask (frstr, frmask); \
  204. printf ("\t%s:fr_mem(frmask=[%s])\n", fmt, frstr); \
  205. } \
  206. while (0)
  207. #define UNW_DEC_GR_MEM(fmt, grmask, arg) \
  208. do \
  209. { \
  210. char grstr[200]; \
  211. \
  212. unw_print_grmask (grstr, grmask); \
  213. printf ("\t%s:gr_mem(grmask=[%s])\n", fmt, grstr); \
  214. } \
  215. while (0)
  216. #define UNW_DEC_FRGR_MEM(fmt, grmask, frmask, arg) \
  217. do \
  218. { \
  219. char frstr[200], grstr[20]; \
  220. \
  221. unw_print_grmask (grstr, grmask); \
  222. unw_print_frmask (frstr, frmask); \
  223. printf ("\t%s:frgr_mem(grmask=[%s],frmask=[%s])\n", fmt, grstr, frstr); \
  224. } \
  225. while (0)
  226. #define UNW_DEC_BR_MEM(fmt, brmask, arg) \
  227. do \
  228. { \
  229. char brstr[20]; \
  230. \
  231. unw_print_brmask (brstr, brmask); \
  232. printf ("\t%s:br_mem(brmask=[%s])\n", fmt, brstr); \
  233. } \
  234. while (0)
  235. #define UNW_DEC_BR_GR(fmt, brmask, gr, arg) \
  236. do \
  237. { \
  238. char brstr[20]; \
  239. \
  240. unw_print_brmask (brstr, brmask); \
  241. printf ("\t%s:br_gr(brmask=[%s],gr=r%u)\n", fmt, brstr, gr); \
  242. } \
  243. while (0)
  244. #define UNW_DEC_REG_GR(fmt, src, dst, arg) \
  245. printf ("\t%s:%s_gr(reg=r%u)\n", fmt, src, dst)
  246. #define UNW_DEC_RP_BR(fmt, dst, arg) \
  247. printf ("\t%s:rp_br(reg=b%u)\n", fmt, dst)
  248. #define UNW_DEC_REG_WHEN(fmt, reg, t, arg) \
  249. printf ("\t%s:%s_when(t=%lu)\n", fmt, reg, (unsigned long) t)
  250. #define UNW_DEC_REG_SPREL(fmt, reg, spoff, arg) \
  251. printf ("\t%s:%s_sprel(spoff=0x%lx)\n", \
  252. fmt, reg, 4*(unsigned long)spoff)
  253. #define UNW_DEC_REG_PSPREL(fmt, reg, pspoff, arg) \
  254. printf ("\t%s:%s_psprel(pspoff=0x10-0x%lx)\n", \
  255. fmt, reg, 4*(unsigned long)pspoff)
  256. #define UNW_DEC_GR_GR(fmt, grmask, gr, arg) \
  257. do \
  258. { \
  259. char grstr[20]; \
  260. \
  261. unw_print_grmask (grstr, grmask); \
  262. printf ("\t%s:gr_gr(grmask=[%s],r%u)\n", fmt, grstr, gr); \
  263. } \
  264. while (0)
  265. #define UNW_DEC_ABI(fmt, abi, context, arg) \
  266. do \
  267. { \
  268. static const char * const abiname[] = \
  269. { \
  270. "@svr4", "@hpux", "@nt" \
  271. }; \
  272. char buf[20]; \
  273. const char *abistr = buf; \
  274. \
  275. if (abi < 3) \
  276. abistr = abiname[abi]; \
  277. else \
  278. sprintf (buf, "0x%x", abi); \
  279. printf ("\t%s:unwabi(abi=%s,context=0x%02x)\n", \
  280. fmt, abistr, context); \
  281. } \
  282. while (0)
  283. #define UNW_DEC_PRIUNAT_GR(fmt, r, arg) \
  284. printf ("\t%s:priunat_gr(reg=r%u)\n", fmt, r)
  285. #define UNW_DEC_PRIUNAT_WHEN_GR(fmt, t, arg) \
  286. printf ("\t%s:priunat_when_gr(t=%lu)\n", fmt, (unsigned long) t)
  287. #define UNW_DEC_PRIUNAT_WHEN_MEM(fmt, t, arg) \
  288. printf ("\t%s:priunat_when_mem(t=%lu)\n", fmt, (unsigned long) t)
  289. #define UNW_DEC_PRIUNAT_PSPREL(fmt, pspoff, arg) \
  290. printf ("\t%s:priunat_psprel(pspoff=0x10-0x%lx)\n", \
  291. fmt, 4*(unsigned long)pspoff)
  292. #define UNW_DEC_PRIUNAT_SPREL(fmt, spoff, arg) \
  293. printf ("\t%s:priunat_sprel(spoff=0x%lx)\n", \
  294. fmt, 4*(unsigned long)spoff)
  295. #define UNW_DEC_MEM_STACK_F(fmt, t, size, arg) \
  296. printf ("\t%s:mem_stack_f(t=%lu,size=%lu)\n", \
  297. fmt, (unsigned long) t, 16*(unsigned long)size)
  298. #define UNW_DEC_MEM_STACK_V(fmt, t, arg) \
  299. printf ("\t%s:mem_stack_v(t=%lu)\n", fmt, (unsigned long) t)
  300. #define UNW_DEC_SPILL_BASE(fmt, pspoff, arg) \
  301. printf ("\t%s:spill_base(pspoff=0x10-0x%lx)\n", \
  302. fmt, 4*(unsigned long)pspoff)
  303. #define UNW_DEC_SPILL_MASK(fmt, dp, arg, end) \
  304. do \
  305. { \
  306. static const char *spill_type = "-frb"; \
  307. unsigned const char *imaskp = dp; \
  308. unsigned char mask = 0; \
  309. bfd_vma insn = 0; \
  310. \
  311. /* PR 18420. */ \
  312. if ((dp + (unw_rlen / 4)) > end) \
  313. { \
  314. printf ("\nERROR: unwind length too long (0x%lx > 0x%lx)\n\n",\
  315. (long) (unw_rlen / 4), (long)(end - dp)); \
  316. /* FIXME: Should we reset unw_rlen ? */ \
  317. break; \
  318. } \
  319. printf ("\t%s:spill_mask(imask=[", fmt); \
  320. for (insn = 0; insn < unw_rlen; ++insn) \
  321. { \
  322. if ((insn % 4) == 0) \
  323. mask = *imaskp++; \
  324. if (insn > 0 && (insn % 3) == 0) \
  325. putchar (','); \
  326. putchar (spill_type[(mask >> (2 * (3 - (insn & 0x3)))) & 0x3]); \
  327. } \
  328. printf ("])\n"); \
  329. dp = imaskp; \
  330. } \
  331. while (0)
  332. #define UNW_DEC_SPILL_SPREL(fmt, t, abreg, spoff, arg) \
  333. do \
  334. { \
  335. char regname[20]; \
  336. \
  337. unw_print_abreg (regname, abreg); \
  338. printf ("\t%s:spill_sprel(reg=%s,t=%lu,spoff=0x%lx)\n", \
  339. fmt, regname, (unsigned long) t, 4*(unsigned long)off); \
  340. } \
  341. while (0)
  342. #define UNW_DEC_SPILL_PSPREL(fmt, t, abreg, pspoff, arg) \
  343. do \
  344. { \
  345. char regname[20]; \
  346. \
  347. unw_print_abreg (regname, abreg); \
  348. printf ("\t%s:spill_psprel(reg=%s,t=%lu,pspoff=0x10-0x%lx)\n", \
  349. fmt, regname, (unsigned long) t, 4*(unsigned long)pspoff); \
  350. } \
  351. while (0)
  352. #define UNW_DEC_RESTORE(fmt, t, abreg, arg) \
  353. do \
  354. { \
  355. char regname[20]; \
  356. \
  357. unw_print_abreg (regname, abreg); \
  358. printf ("\t%s:restore(t=%lu,reg=%s)\n", \
  359. fmt, (unsigned long) t, regname); \
  360. } \
  361. while (0)
  362. #define UNW_DEC_SPILL_REG(fmt, t, abreg, x, ytreg, arg) \
  363. do \
  364. { \
  365. char abregname[20], tregname[20]; \
  366. \
  367. unw_print_abreg (abregname, abreg); \
  368. unw_print_xyreg (tregname, x, ytreg); \
  369. printf ("\t%s:spill_reg(t=%lu,reg=%s,treg=%s)\n", \
  370. fmt, (unsigned long) t, abregname, tregname); \
  371. } \
  372. while (0)
  373. #define UNW_DEC_SPILL_SPREL_P(fmt, qp, t, abreg, spoff, arg) \
  374. do \
  375. { \
  376. char regname[20]; \
  377. \
  378. unw_print_abreg (regname, abreg); \
  379. printf ("\t%s:spill_sprel_p(qp=p%u,t=%lu,reg=%s,spoff=0x%lx)\n", \
  380. fmt, qp, (unsigned long) t, regname, 4 * (unsigned long)spoff); \
  381. } \
  382. while (0)
  383. #define UNW_DEC_SPILL_PSPREL_P(fmt, qp, t, abreg, pspoff, arg) \
  384. do \
  385. { \
  386. char regname[20]; \
  387. \
  388. unw_print_abreg (regname, abreg); \
  389. printf ("\t%s:spill_psprel_p(qp=p%u,t=%lu,reg=%s,pspoff=0x10-0x%lx)\n",\
  390. fmt, qp, (unsigned long) t, regname, 4*(unsigned long)pspoff);\
  391. } \
  392. while (0)
  393. #define UNW_DEC_RESTORE_P(fmt, qp, t, abreg, arg) \
  394. do \
  395. { \
  396. char regname[20]; \
  397. \
  398. unw_print_abreg (regname, abreg); \
  399. printf ("\t%s:restore_p(qp=p%u,t=%lu,reg=%s)\n", \
  400. fmt, qp, (unsigned long) t, regname); \
  401. } \
  402. while (0)
  403. #define UNW_DEC_SPILL_REG_P(fmt, qp, t, abreg, x, ytreg, arg) \
  404. do \
  405. { \
  406. char regname[20], tregname[20]; \
  407. \
  408. unw_print_abreg (regname, abreg); \
  409. unw_print_xyreg (tregname, x, ytreg); \
  410. printf ("\t%s:spill_reg_p(qp=p%u,t=%lu,reg=%s,treg=%s)\n", \
  411. fmt, qp, (unsigned long) t, regname, tregname); \
  412. } \
  413. while (0)
  414. #define UNW_DEC_LABEL_STATE(fmt, label, arg) \
  415. printf ("\t%s:label_state(label=%lu)\n", fmt, (unsigned long) label)
  416. #define UNW_DEC_COPY_STATE(fmt, label, arg) \
  417. printf ("\t%s:copy_state(label=%lu)\n", fmt, (unsigned long) label)
  418. #define UNW_DEC_EPILOGUE(fmt, t, ecount, arg) \
  419. printf ("\t%s:epilogue(t=%lu,ecount=%lu)\n", \
  420. fmt, (unsigned long) t, (unsigned long) ecount)
  421. /*
  422. * Generic IA-64 unwind info decoder.
  423. *
  424. * This file is used both by the Linux kernel and objdump. Please
  425. * keep the two copies of this file in sync (modulo differences in the
  426. * prototypes...).
  427. *
  428. * You need to customize the decoder by defining the following
  429. * macros/constants before including this file:
  430. *
  431. * Types:
  432. * unw_word Unsigned integer type with at least 64 bits
  433. *
  434. * Register names:
  435. * UNW_REG_BSP
  436. * UNW_REG_BSPSTORE
  437. * UNW_REG_FPSR
  438. * UNW_REG_LC
  439. * UNW_REG_PFS
  440. * UNW_REG_PR
  441. * UNW_REG_RNAT
  442. * UNW_REG_PSP
  443. * UNW_REG_RP
  444. * UNW_REG_UNAT
  445. *
  446. * Decoder action macros:
  447. * UNW_DEC_BAD_CODE(code)
  448. * UNW_DEC_ABI(fmt,abi,context,arg)
  449. * UNW_DEC_BR_GR(fmt,brmask,gr,arg)
  450. * UNW_DEC_BR_MEM(fmt,brmask,arg)
  451. * UNW_DEC_COPY_STATE(fmt,label,arg)
  452. * UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
  453. * UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
  454. * UNW_DEC_FR_MEM(fmt,frmask,arg)
  455. * UNW_DEC_GR_GR(fmt,grmask,gr,arg)
  456. * UNW_DEC_GR_MEM(fmt,grmask,arg)
  457. * UNW_DEC_LABEL_STATE(fmt,label,arg)
  458. * UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
  459. * UNW_DEC_MEM_STACK_V(fmt,t,arg)
  460. * UNW_DEC_PRIUNAT_GR(fmt,r,arg)
  461. * UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
  462. * UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
  463. * UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
  464. * UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
  465. * UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
  466. * UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
  467. * UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
  468. * UNW_DEC_REG_REG(fmt,src,dst,arg)
  469. * UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
  470. * UNW_DEC_REG_WHEN(fmt,reg,t,arg)
  471. * UNW_DEC_RESTORE(fmt,t,abreg,arg)
  472. * UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
  473. * UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
  474. * UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
  475. * UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
  476. * UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
  477. * UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
  478. * UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
  479. * UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
  480. * UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
  481. */
  482. static unw_word
  483. unw_decode_uleb128 (const unsigned char **dpp)
  484. {
  485. unsigned shift = 0;
  486. unw_word byte, result = 0;
  487. const unsigned char *bp = *dpp;
  488. while (1)
  489. {
  490. byte = *bp++;
  491. result |= (byte & 0x7f) << shift;
  492. if ((byte & 0x80) == 0)
  493. break;
  494. shift += 7;
  495. }
  496. *dpp = bp;
  497. return result;
  498. }
  499. static const unsigned char *
  500. unw_decode_x1 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
  501. void *arg ATTRIBUTE_UNUSED)
  502. {
  503. unsigned char byte1, abreg;
  504. unw_word t, off;
  505. byte1 = *dp++;
  506. t = unw_decode_uleb128 (&dp);
  507. off = unw_decode_uleb128 (&dp);
  508. abreg = (byte1 & 0x7f);
  509. if (byte1 & 0x80)
  510. UNW_DEC_SPILL_SPREL ("X1", t, abreg, off, arg);
  511. else
  512. UNW_DEC_SPILL_PSPREL ("X1", t, abreg, off, arg);
  513. return dp;
  514. }
  515. static const unsigned char *
  516. unw_decode_x2 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
  517. void *arg ATTRIBUTE_UNUSED)
  518. {
  519. unsigned char byte1, byte2, abreg, x, ytreg;
  520. unw_word t;
  521. byte1 = *dp++;
  522. byte2 = *dp++;
  523. t = unw_decode_uleb128 (&dp);
  524. abreg = (byte1 & 0x7f);
  525. ytreg = byte2;
  526. x = (byte1 >> 7) & 1;
  527. if ((byte1 & 0x80) == 0 && ytreg == 0)
  528. UNW_DEC_RESTORE ("X2", t, abreg, arg);
  529. else
  530. UNW_DEC_SPILL_REG ("X2", t, abreg, x, ytreg, arg);
  531. return dp;
  532. }
  533. static const unsigned char *
  534. unw_decode_x3 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
  535. void *arg ATTRIBUTE_UNUSED)
  536. {
  537. unsigned char byte1, byte2, abreg, qp;
  538. unw_word t, off;
  539. byte1 = *dp++;
  540. byte2 = *dp++;
  541. t = unw_decode_uleb128 (&dp);
  542. off = unw_decode_uleb128 (&dp);
  543. qp = (byte1 & 0x3f);
  544. abreg = (byte2 & 0x7f);
  545. if (byte1 & 0x80)
  546. UNW_DEC_SPILL_SPREL_P ("X3", qp, t, abreg, off, arg);
  547. else
  548. UNW_DEC_SPILL_PSPREL_P ("X3", qp, t, abreg, off, arg);
  549. return dp;
  550. }
  551. static const unsigned char *
  552. unw_decode_x4 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
  553. void *arg ATTRIBUTE_UNUSED)
  554. {
  555. unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
  556. unw_word t;
  557. byte1 = *dp++;
  558. byte2 = *dp++;
  559. byte3 = *dp++;
  560. t = unw_decode_uleb128 (&dp);
  561. qp = (byte1 & 0x3f);
  562. abreg = (byte2 & 0x7f);
  563. x = (byte2 >> 7) & 1;
  564. ytreg = byte3;
  565. if ((byte2 & 0x80) == 0 && byte3 == 0)
  566. UNW_DEC_RESTORE_P ("X4", qp, t, abreg, arg);
  567. else
  568. UNW_DEC_SPILL_REG_P ("X4", qp, t, abreg, x, ytreg, arg);
  569. return dp;
  570. }
  571. static const unsigned char *
  572. unw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg,
  573. const unsigned char * end ATTRIBUTE_UNUSED)
  574. {
  575. int body = (code & 0x20) != 0;
  576. unw_word rlen;
  577. rlen = (code & 0x1f);
  578. UNW_DEC_PROLOGUE ("R1", body, rlen, arg);
  579. return dp;
  580. }
  581. static const unsigned char *
  582. unw_decode_r2 (const unsigned char *dp, unsigned int code, void *arg,
  583. const unsigned char * end ATTRIBUTE_UNUSED)
  584. {
  585. unsigned char byte1, mask, grsave;
  586. unw_word rlen;
  587. byte1 = *dp++;
  588. mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
  589. grsave = (byte1 & 0x7f);
  590. rlen = unw_decode_uleb128 (& dp);
  591. UNW_DEC_PROLOGUE_GR ("R2", rlen, mask, grsave, arg);
  592. return dp;
  593. }
  594. static const unsigned char *
  595. unw_decode_r3 (const unsigned char *dp, unsigned int code, void *arg,
  596. const unsigned char * end ATTRIBUTE_UNUSED)
  597. {
  598. unw_word rlen;
  599. rlen = unw_decode_uleb128 (& dp);
  600. UNW_DEC_PROLOGUE ("R3", ((code & 0x3) == 1), rlen, arg);
  601. return dp;
  602. }
  603. static const unsigned char *
  604. unw_decode_p1 (const unsigned char *dp, unsigned int code,
  605. void *arg ATTRIBUTE_UNUSED,
  606. const unsigned char * end ATTRIBUTE_UNUSED)
  607. {
  608. unsigned char brmask = (code & 0x1f);
  609. UNW_DEC_BR_MEM ("P1", brmask, arg);
  610. return dp;
  611. }
  612. static const unsigned char *
  613. unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
  614. void *arg ATTRIBUTE_UNUSED,
  615. const unsigned char * end)
  616. {
  617. if ((code & 0x10) == 0)
  618. {
  619. unsigned char byte1 = *dp++;
  620. UNW_DEC_BR_GR ("P2", ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
  621. (byte1 & 0x7f), arg);
  622. }
  623. else if ((code & 0x08) == 0)
  624. {
  625. unsigned char byte1 = *dp++, r, dst;
  626. r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
  627. dst = (byte1 & 0x7f);
  628. switch (r)
  629. {
  630. case 0:
  631. UNW_DEC_REG_GR ("P3", UNW_REG_PSP, dst, arg);
  632. break;
  633. case 1:
  634. UNW_DEC_REG_GR ("P3", UNW_REG_RP, dst, arg);
  635. break;
  636. case 2:
  637. UNW_DEC_REG_GR ("P3", UNW_REG_PFS, dst, arg);
  638. break;
  639. case 3:
  640. UNW_DEC_REG_GR ("P3", UNW_REG_PR, dst, arg);
  641. break;
  642. case 4:
  643. UNW_DEC_REG_GR ("P3", UNW_REG_UNAT, dst, arg);
  644. break;
  645. case 5:
  646. UNW_DEC_REG_GR ("P3", UNW_REG_LC, dst, arg);
  647. break;
  648. case 6:
  649. UNW_DEC_RP_BR ("P3", dst, arg);
  650. break;
  651. case 7:
  652. UNW_DEC_REG_GR ("P3", UNW_REG_RNAT, dst, arg);
  653. break;
  654. case 8:
  655. UNW_DEC_REG_GR ("P3", UNW_REG_BSP, dst, arg);
  656. break;
  657. case 9:
  658. UNW_DEC_REG_GR ("P3", UNW_REG_BSPSTORE, dst, arg);
  659. break;
  660. case 10:
  661. UNW_DEC_REG_GR ("P3", UNW_REG_FPSR, dst, arg);
  662. break;
  663. case 11:
  664. UNW_DEC_PRIUNAT_GR ("P3", dst, arg);
  665. break;
  666. default:
  667. UNW_DEC_BAD_CODE (r);
  668. break;
  669. }
  670. }
  671. else if ((code & 0x7) == 0)
  672. UNW_DEC_SPILL_MASK ("P4", dp, arg, end);
  673. else if ((code & 0x7) == 1)
  674. {
  675. unw_word grmask, frmask, byte1, byte2, byte3;
  676. byte1 = *dp++;
  677. byte2 = *dp++;
  678. byte3 = *dp++;
  679. grmask = ((byte1 >> 4) & 0xf);
  680. frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
  681. UNW_DEC_FRGR_MEM ("P5", grmask, frmask, arg);
  682. }
  683. else
  684. UNW_DEC_BAD_CODE (code);
  685. return dp;
  686. }
  687. static const unsigned char *
  688. unw_decode_p6 (const unsigned char *dp, unsigned int code,
  689. void *arg ATTRIBUTE_UNUSED,
  690. const unsigned char * end ATTRIBUTE_UNUSED)
  691. {
  692. int gregs = (code & 0x10) != 0;
  693. unsigned char mask = (code & 0x0f);
  694. if (gregs)
  695. UNW_DEC_GR_MEM ("P6", mask, arg);
  696. else
  697. UNW_DEC_FR_MEM ("P6", mask, arg);
  698. return dp;
  699. }
  700. static const unsigned char *
  701. unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg,
  702. const unsigned char * end ATTRIBUTE_UNUSED)
  703. {
  704. unsigned char r, byte1, byte2;
  705. unw_word t, size;
  706. if ((code & 0x10) == 0)
  707. {
  708. r = (code & 0xf);
  709. t = unw_decode_uleb128 (&dp);
  710. switch (r)
  711. {
  712. case 0:
  713. size = unw_decode_uleb128 (&dp);
  714. UNW_DEC_MEM_STACK_F ("P7", t, size, arg);
  715. break;
  716. case 1:
  717. UNW_DEC_MEM_STACK_V ("P7", t, arg);
  718. break;
  719. case 2:
  720. UNW_DEC_SPILL_BASE ("P7", t, arg);
  721. break;
  722. case 3:
  723. UNW_DEC_REG_SPREL ("P7", UNW_REG_PSP, t, arg);
  724. break;
  725. case 4:
  726. UNW_DEC_REG_WHEN ("P7", UNW_REG_RP, t, arg);
  727. break;
  728. case 5:
  729. UNW_DEC_REG_PSPREL ("P7", UNW_REG_RP, t, arg);
  730. break;
  731. case 6:
  732. UNW_DEC_REG_WHEN ("P7", UNW_REG_PFS, t, arg);
  733. break;
  734. case 7:
  735. UNW_DEC_REG_PSPREL ("P7", UNW_REG_PFS, t, arg);
  736. break;
  737. case 8:
  738. UNW_DEC_REG_WHEN ("P7", UNW_REG_PR, t, arg);
  739. break;
  740. case 9:
  741. UNW_DEC_REG_PSPREL ("P7", UNW_REG_PR, t, arg);
  742. break;
  743. case 10:
  744. UNW_DEC_REG_WHEN ("P7", UNW_REG_LC, t, arg);
  745. break;
  746. case 11:
  747. UNW_DEC_REG_PSPREL ("P7", UNW_REG_LC, t, arg);
  748. break;
  749. case 12:
  750. UNW_DEC_REG_WHEN ("P7", UNW_REG_UNAT, t, arg);
  751. break;
  752. case 13:
  753. UNW_DEC_REG_PSPREL ("P7", UNW_REG_UNAT, t, arg);
  754. break;
  755. case 14:
  756. UNW_DEC_REG_WHEN ("P7", UNW_REG_FPSR, t, arg);
  757. break;
  758. case 15:
  759. UNW_DEC_REG_PSPREL ("P7", UNW_REG_FPSR, t, arg);
  760. break;
  761. default:
  762. UNW_DEC_BAD_CODE (r);
  763. break;
  764. }
  765. }
  766. else
  767. {
  768. switch (code & 0xf)
  769. {
  770. case 0x0: /* p8 */
  771. {
  772. r = *dp++;
  773. t = unw_decode_uleb128 (&dp);
  774. switch (r)
  775. {
  776. case 1:
  777. UNW_DEC_REG_SPREL ("P8", UNW_REG_RP, t, arg);
  778. break;
  779. case 2:
  780. UNW_DEC_REG_SPREL ("P8", UNW_REG_PFS, t, arg);
  781. break;
  782. case 3:
  783. UNW_DEC_REG_SPREL ("P8", UNW_REG_PR, t, arg);
  784. break;
  785. case 4:
  786. UNW_DEC_REG_SPREL ("P8", UNW_REG_LC, t, arg);
  787. break;
  788. case 5:
  789. UNW_DEC_REG_SPREL ("P8", UNW_REG_UNAT, t, arg);
  790. break;
  791. case 6:
  792. UNW_DEC_REG_SPREL ("P8", UNW_REG_FPSR, t, arg);
  793. break;
  794. case 7:
  795. UNW_DEC_REG_WHEN ("P8", UNW_REG_BSP, t, arg);
  796. break;
  797. case 8:
  798. UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSP, t, arg);
  799. break;
  800. case 9:
  801. UNW_DEC_REG_SPREL ("P8", UNW_REG_BSP, t, arg);
  802. break;
  803. case 10:
  804. UNW_DEC_REG_WHEN ("P8", UNW_REG_BSPSTORE, t, arg);
  805. break;
  806. case 11:
  807. UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSPSTORE, t, arg);
  808. break;
  809. case 12:
  810. UNW_DEC_REG_SPREL ("P8", UNW_REG_BSPSTORE, t, arg);
  811. break;
  812. case 13:
  813. UNW_DEC_REG_WHEN ("P8", UNW_REG_RNAT, t, arg);
  814. break;
  815. case 14:
  816. UNW_DEC_REG_PSPREL ("P8", UNW_REG_RNAT, t, arg);
  817. break;
  818. case 15:
  819. UNW_DEC_REG_SPREL ("P8", UNW_REG_RNAT, t, arg);
  820. break;
  821. case 16:
  822. UNW_DEC_PRIUNAT_WHEN_GR ("P8", t, arg);
  823. break;
  824. case 17:
  825. UNW_DEC_PRIUNAT_PSPREL ("P8", t, arg);
  826. break;
  827. case 18:
  828. UNW_DEC_PRIUNAT_SPREL ("P8", t, arg);
  829. break;
  830. case 19:
  831. UNW_DEC_PRIUNAT_WHEN_MEM ("P8", t, arg);
  832. break;
  833. default:
  834. UNW_DEC_BAD_CODE (r);
  835. break;
  836. }
  837. }
  838. break;
  839. case 0x1:
  840. byte1 = *dp++;
  841. byte2 = *dp++;
  842. UNW_DEC_GR_GR ("P9", (byte1 & 0xf), (byte2 & 0x7f), arg);
  843. break;
  844. case 0xf: /* p10 */
  845. byte1 = *dp++;
  846. byte2 = *dp++;
  847. UNW_DEC_ABI ("P10", byte1, byte2, arg);
  848. break;
  849. case 0x9:
  850. return unw_decode_x1 (dp, code, arg);
  851. case 0xa:
  852. return unw_decode_x2 (dp, code, arg);
  853. case 0xb:
  854. return unw_decode_x3 (dp, code, arg);
  855. case 0xc:
  856. return unw_decode_x4 (dp, code, arg);
  857. default:
  858. UNW_DEC_BAD_CODE (code);
  859. break;
  860. }
  861. }
  862. return dp;
  863. }
  864. static const unsigned char *
  865. unw_decode_b1 (const unsigned char *dp, unsigned int code,
  866. void *arg ATTRIBUTE_UNUSED,
  867. const unsigned char * end ATTRIBUTE_UNUSED)
  868. {
  869. unw_word label = (code & 0x1f);
  870. if ((code & 0x20) != 0)
  871. UNW_DEC_COPY_STATE ("B1", label, arg);
  872. else
  873. UNW_DEC_LABEL_STATE ("B1", label, arg);
  874. return dp;
  875. }
  876. static const unsigned char *
  877. unw_decode_b2 (const unsigned char *dp, unsigned int code,
  878. void *arg ATTRIBUTE_UNUSED,
  879. const unsigned char * end ATTRIBUTE_UNUSED)
  880. {
  881. unw_word t;
  882. t = unw_decode_uleb128 (& dp);
  883. UNW_DEC_EPILOGUE ("B2", t, (code & 0x1f), arg);
  884. return dp;
  885. }
  886. static const unsigned char *
  887. unw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg,
  888. const unsigned char * end ATTRIBUTE_UNUSED)
  889. {
  890. unw_word t, ecount, label;
  891. if ((code & 0x10) == 0)
  892. {
  893. t = unw_decode_uleb128 (&dp);
  894. ecount = unw_decode_uleb128 (&dp);
  895. UNW_DEC_EPILOGUE ("B3", t, ecount, arg);
  896. }
  897. else if ((code & 0x07) == 0)
  898. {
  899. label = unw_decode_uleb128 (&dp);
  900. if ((code & 0x08) != 0)
  901. UNW_DEC_COPY_STATE ("B4", label, arg);
  902. else
  903. UNW_DEC_LABEL_STATE ("B4", label, arg);
  904. }
  905. else
  906. switch (code & 0x7)
  907. {
  908. case 1:
  909. return unw_decode_x1 (dp, code, arg);
  910. case 2:
  911. return unw_decode_x2 (dp, code, arg);
  912. case 3:
  913. return unw_decode_x3 (dp, code, arg);
  914. case 4:
  915. return unw_decode_x4 (dp, code, arg);
  916. default:
  917. UNW_DEC_BAD_CODE (code);
  918. break;
  919. }
  920. return dp;
  921. }
  922. typedef const unsigned char *(*unw_decoder)
  923. (const unsigned char *, unsigned int, void *, const unsigned char *);
  924. static const unw_decoder unw_decode_table[2][8] =
  925. {
  926. /* prologue table: */
  927. {
  928. unw_decode_r1, /* 0 */
  929. unw_decode_r1,
  930. unw_decode_r2,
  931. unw_decode_r3,
  932. unw_decode_p1, /* 4 */
  933. unw_decode_p2_p5,
  934. unw_decode_p6,
  935. unw_decode_p7_p10
  936. },
  937. {
  938. unw_decode_r1, /* 0 */
  939. unw_decode_r1,
  940. unw_decode_r2,
  941. unw_decode_r3,
  942. unw_decode_b1, /* 4 */
  943. unw_decode_b1,
  944. unw_decode_b2,
  945. unw_decode_b3_x4
  946. }
  947. };
  948. /* Decode one descriptor and return address of next descriptor. */
  949. const unsigned char *
  950. unw_decode (const unsigned char *dp, int inside_body,
  951. void *ptr_inside_body, const unsigned char * end)
  952. {
  953. unw_decoder decoder;
  954. unsigned char code;
  955. code = *dp++;
  956. decoder = unw_decode_table[inside_body][code >> 5];
  957. return (*decoder) (dp, code, ptr_inside_body, end);
  958. }