120253Sjoerg/* unwind-ia64.c -- utility routines to dump IA-64 unwind info for readelf. 220302Sjoerg Copyright (C) 2000-2017 Free Software Foundation, Inc. 320302Sjoerg 420253Sjoerg Contributed by David Mosberger-Tang <davidm@hpl.hp.com> 520253Sjoerg 620253Sjoerg This file is part of GNU Binutils. 720253Sjoerg 820253Sjoerg This program is free software; you can redistribute it and/or modify 920302Sjoerg it under the terms of the GNU General Public License as published by 1020253Sjoerg the Free Software Foundation; either version 3, or (at your option) 1120253Sjoerg any later version. 1220253Sjoerg 1320253Sjoerg This program is distributed in the hope that it will be useful, 1420302Sjoerg but WITHOUT ANY WARRANTY; without even the implied warranty of 1520253Sjoerg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1620253Sjoerg GNU General Public License for more details. 1720302Sjoerg 1820253Sjoerg You should have received a copy of the GNU General Public License 1920253Sjoerg along with this program; if not, write to the Free Software 2020253Sjoerg Foundation, 51 Franklin Street - Fifth Floor, Boston, 2120253Sjoerg MA 02110-1301, USA. */ 2220253Sjoerg 2320253Sjoerg#include "config.h" 2420253Sjoerg#include "unwind-ia64.h" 2544229Sdavidn#include <stdio.h> 2620253Sjoerg#include <string.h> 2720253Sjoerg 2830259Scharnier#if __GNUC__ >= 2 2930259Scharnier/* Define BFD64 here, even if our default architecture is 32 bit ELF 3050479Speter as this will allow us to read in and parse 64bit and 32bit ELF files. 3130259Scharnier Only do this if we believe that the compiler can support a 64 bit 3230259Scharnier data type. For now we only rely on GCC being able to do this. */ 33287084Sbapt#define BFD64 34287084Sbapt#endif 35287084Sbapt#include "bfd.h" 36287084Sbapt 37287084Sbaptstatic bfd_vma unw_rlen = 0; 38319267Sasomers 3930259Scharnierstatic void unw_print_brmask (char *, unsigned int); 40287084Sbaptstatic void unw_print_grmask (char *, unsigned int); 4130259Scharnierstatic void unw_print_frmask (char *, unsigned int); 42287084Sbaptstatic void unw_print_abreg (char *, unsigned int); 4320253Sjoergstatic void unw_print_xyreg (char *, unsigned int, unsigned int); 44287084Sbapt 45287084Sbaptstatic void 46287084Sbaptunw_print_brmask (char *cp, unsigned int mask) 47287084Sbapt{ 4830259Scharnier int sep = 0; 49287084Sbapt int i; 50287084Sbapt 5120253Sjoerg for (i = 0; mask && (i < 5); ++i) 52287084Sbapt { 53287084Sbapt if (mask & 1) 5420253Sjoerg { 5520253Sjoerg if (sep) 56287084Sbapt *cp++ = ','; 5720253Sjoerg *cp++ = 'b'; 5823318Sache *cp++ = i + 1 + '0'; 5922394Sdavidn sep = 1; 6052512Sdavidn } 6124214Sache mask >>= 1; 62287084Sbapt } 63287084Sbapt *cp = '\0'; 64287084Sbapt} 65287084Sbapt 66287084Sbaptstatic void 67287084Sbaptunw_print_grmask (char *cp, unsigned int mask) 68287084Sbapt{ 69287084Sbapt int sep = 0; 70287084Sbapt int i; 71287084Sbapt 72287084Sbapt for (i = 0; i < 4; ++i) 73287084Sbapt { 74287084Sbapt if (mask & 1) 7520253Sjoerg { 76287084Sbapt if (sep) 77287084Sbapt *cp++ = ','; 78287084Sbapt *cp++ = 'r'; 79287084Sbapt *cp++ = i + 4 + '0'; 80287084Sbapt sep = 1; 81287084Sbapt } 82287084Sbapt mask >>= 1; 83287084Sbapt } 84287084Sbapt *cp = '\0'; 85287084Sbapt} 86287084Sbapt 87287084Sbaptstatic void 88287084Sbaptunw_print_frmask (char *cp, unsigned int mask) 89285092Sbapt{ 90287084Sbapt int sep = 0; 91285092Sbapt int i; 92287084Sbapt 93287084Sbapt for (i = 0; i < 20; ++i) 94285092Sbapt { 95287084Sbapt if (mask & 1) 96287084Sbapt { 97285092Sbapt if (sep) 98287084Sbapt *cp++ = ','; 99285092Sbapt *cp++ = 'f'; 100287084Sbapt if (i < 4) 101287084Sbapt *cp++ = i + 2 + '0'; 102287084Sbapt else 103287084Sbapt { 10420267Sjoerg *cp++ = (i + 2) / 10 + 1 + '0'; 10520267Sjoerg *cp++ = (i + 2) % 10 + '0'; 106287084Sbapt } 107287084Sbapt sep = 1; 108287084Sbapt } 10920253Sjoerg mask >>= 1; 110287084Sbapt } 111293684Sbapt *cp = '\0'; 112293684Sbapt} 113287084Sbapt 114293684Sbaptstatic void 115287084Sbaptunw_print_abreg (char *cp, unsigned int abreg) 11621052Sdavidn{ 11721052Sdavidn static const char * const special_reg[16] = 118287084Sbapt { 119287084Sbapt "pr", "psp", "@priunat", "rp", "ar.bsp", "ar.bspstore", "ar.rnat", 120287084Sbapt "ar.unat", "ar.fpsr", "ar.pfs", "ar.lc", 121287084Sbapt "Unknown11", "Unknown12", "Unknown13", "Unknown14", "Unknown15" 12221052Sdavidn }; 123287084Sbapt 124287084Sbapt switch ((abreg >> 5) & 0x3) 125287084Sbapt { 126287084Sbapt case 0: /* gr */ 127287084Sbapt sprintf (cp, "r%u", (abreg & 0x1f)); 128287084Sbapt break; 129287084Sbapt 13020253Sjoerg case 1: /* fr */ 131287084Sbapt sprintf (cp, "f%u", (abreg & 0x1f)); 13220253Sjoerg break; 133287084Sbapt 134287084Sbapt case 2: /* br */ 135287084Sbapt sprintf (cp, "b%u", (abreg & 0x1f)); 136287084Sbapt break; 137287084Sbapt 138287084Sbapt case 3: /* special */ 139287084Sbapt strcpy (cp, special_reg[abreg & 0xf]); 14020253Sjoerg break; 141287084Sbapt } 14220253Sjoerg} 14320253Sjoerg 144287084Sbaptstatic void 145287084Sbaptunw_print_xyreg (char *cp, unsigned int x, unsigned int ytreg) 146287084Sbapt{ 147287084Sbapt switch ((x << 1) | ((ytreg >> 7) & 1)) 14820253Sjoerg { 14952527Sdavidn case 0: /* gr */ 150287084Sbapt sprintf (cp, "r%u", (ytreg & 0x1f)); 151287084Sbapt break; 15220253Sjoerg 153287084Sbapt case 1: /* fr */ 154287084Sbapt sprintf (cp, "f%u", (ytreg & 0x1f)); 155287084Sbapt break; 156287084Sbapt 157287084Sbapt case 2: /* br */ 15820253Sjoerg sprintf (cp, "b%u", (ytreg & 0x1f)); 159287084Sbapt break; 160287084Sbapt } 16152527Sdavidn} 162287084Sbapt 163287084Sbapt#define UNW_REG_BSP "bsp" 164287084Sbapt#define UNW_REG_BSPSTORE "bspstore" 165287084Sbapt#define UNW_REG_FPSR "fpsr" 16620253Sjoerg#define UNW_REG_LC "lc" 16752527Sdavidn#define UNW_REG_PFS "pfs" 168287084Sbapt#define UNW_REG_PR "pr" 169287084Sbapt#define UNW_REG_PSP "psp" 170287084Sbapt#define UNW_REG_RNAT "rnat" 171287084Sbapt#define UNW_REG_RP "rp" 172287084Sbapt#define UNW_REG_UNAT "unat" 17320253Sjoerg 174287084Sbapttypedef bfd_vma unw_word; 175287084Sbapt 176287084Sbapt#define UNW_DEC_BAD_CODE(code) \ 177287084Sbapt printf ("Unknown code 0x%02x\n", code) 178287084Sbapt 179287084Sbapt#define UNW_DEC_PROLOGUE(fmt, body, rlen, arg) \ 180287084Sbapt do \ 181287084Sbapt { \ 18220253Sjoerg unw_rlen = rlen; \ 183287084Sbapt *(int *)arg = body; \ 184287084Sbapt printf (" %s:%s(rlen=%lu)\n", \ 185287084Sbapt fmt, body ? "body" : "prologue", (unsigned long) rlen); \ 186287084Sbapt } \ 18720253Sjoerg while (0) 188287084Sbapt 189287084Sbapt#define UNW_DEC_PROLOGUE_GR(fmt, rlen, mask, grsave, arg) \ 19052527Sdavidn do \ 191287084Sbapt { \ 192287084Sbapt char regname[16], maskstr[64], *sep; \ 193287084Sbapt \ 194287084Sbapt unw_rlen = rlen; \ 195287084Sbapt *(int *)arg = 0; \ 196287084Sbapt \ 197287084Sbapt maskstr[0] = '\0'; \ 198287084Sbapt sep = ""; \ 199287084Sbapt if (mask & 0x8) \ 200287084Sbapt { \ 201287084Sbapt strcat (maskstr, "rp"); \ 202287084Sbapt sep = ","; \ 20320253Sjoerg } \ 204287084Sbapt if (mask & 0x4) \ 205287084Sbapt { \ 206287084Sbapt strcat (maskstr, sep); \ 207287084Sbapt strcat (maskstr, "ar.pfs"); \ 208287084Sbapt sep = ","; \ 209287084Sbapt } \ 210287084Sbapt if (mask & 0x2) \ 21152527Sdavidn { \ 212287084Sbapt strcat (maskstr, sep); \ 213287084Sbapt strcat (maskstr, "psp"); \ 214287084Sbapt sep = ","; \ 215287084Sbapt } \ 216287084Sbapt if (mask & 0x1) \ 217287084Sbapt { \ 218287084Sbapt strcat (maskstr, sep); \ 219287084Sbapt strcat (maskstr, "pr"); \ 220287084Sbapt } \ 221287084Sbapt sprintf (regname, "r%u", grsave); \ 222287084Sbapt printf (" %s:prologue_gr(mask=[%s],grsave=%s,rlen=%lu)\n", \ 223287084Sbapt fmt, maskstr, regname, (unsigned long) rlen); \ 224287084Sbapt } \ 22520253Sjoerg while (0) 22664918Sgreen 227287084Sbapt#define UNW_DEC_FR_MEM(fmt, frmask, arg) \ 228287084Sbapt do \ 22964918Sgreen { \ 23064918Sgreen char frstr[200]; \ 231287084Sbapt \ 23220253Sjoerg unw_print_frmask (frstr, frmask); \ 233287084Sbapt printf ("\t%s:fr_mem(frmask=[%s])\n", fmt, frstr); \ 234287084Sbapt } \ 23520253Sjoerg while (0) 236287084Sbapt 237287084Sbapt#define UNW_DEC_GR_MEM(fmt, grmask, arg) \ 238287084Sbapt do \ 239287084Sbapt { \ 240287084Sbapt char grstr[200]; \ 24120253Sjoerg \ 242287084Sbapt unw_print_grmask (grstr, grmask); \ 243287084Sbapt printf ("\t%s:gr_mem(grmask=[%s])\n", fmt, grstr); \ 244287084Sbapt } \ 24520253Sjoerg while (0) 246287084Sbapt 247287084Sbapt#define UNW_DEC_FRGR_MEM(fmt, grmask, frmask, arg) \ 248287084Sbapt do \ 249287084Sbapt { \ 250287084Sbapt char frstr[200], grstr[20]; \ 25120253Sjoerg \ 252287084Sbapt unw_print_grmask (grstr, grmask); \ 253287084Sbapt unw_print_frmask (frstr, frmask); \ 254285092Sbapt printf ("\t%s:frgr_mem(grmask=[%s],frmask=[%s])\n", fmt, grstr, frstr); \ 255287084Sbapt } \ 256285092Sbapt while (0) 257287084Sbapt 258287084Sbapt#define UNW_DEC_BR_MEM(fmt, brmask, arg) \ 25921330Sdavidn do \ 260287084Sbapt { \ 26121330Sdavidn char brstr[20]; \ 262287084Sbapt \ 263287084Sbapt unw_print_brmask (brstr, brmask); \ 264287084Sbapt printf ("\t%s:br_mem(brmask=[%s])\n", fmt, brstr); \ 265287084Sbapt } \ 266287084Sbapt while (0) 267287084Sbapt 268287084Sbapt#define UNW_DEC_BR_GR(fmt, brmask, gr, arg) \ 269287084Sbapt do \ 270287084Sbapt { \ 271287084Sbapt char brstr[20]; \ 272287084Sbapt \ 273287084Sbapt unw_print_brmask (brstr, brmask); \ 274287084Sbapt printf ("\t%s:br_gr(brmask=[%s],gr=r%u)\n", fmt, brstr, gr); \ 275287084Sbapt } \ 276287084Sbapt while (0) 277287084Sbapt 278292025Sbapt#define UNW_DEC_REG_GR(fmt, src, dst, arg) \ 27920253Sjoerg printf ("\t%s:%s_gr(reg=r%u)\n", fmt, src, dst) 280287084Sbapt 281287084Sbapt#define UNW_DEC_RP_BR(fmt, dst, arg) \ 282274082Sbapt printf ("\t%s:rp_br(reg=b%u)\n", fmt, dst) 283287084Sbapt 284287084Sbapt#define UNW_DEC_REG_WHEN(fmt, reg, t, arg) \ 285242349Sbapt printf ("\t%s:%s_when(t=%lu)\n", fmt, reg, (unsigned long) t) 286292025Sbapt 287292025Sbapt#define UNW_DEC_REG_SPREL(fmt, reg, spoff, arg) \ 288292025Sbapt printf ("\t%s:%s_sprel(spoff=0x%lx)\n", \ 289242349Sbapt fmt, reg, 4*(unsigned long)spoff) 290292025Sbapt 291292025Sbapt#define UNW_DEC_REG_PSPREL(fmt, reg, pspoff, arg) \ 292292025Sbapt printf ("\t%s:%s_psprel(pspoff=0x10-0x%lx)\n", \ 293292025Sbapt fmt, reg, 4*(unsigned long)pspoff) 294292025Sbapt 295292025Sbapt#define UNW_DEC_GR_GR(fmt, grmask, gr, arg) \ 29661759Sdavidn do \ 297292025Sbapt { \ 298292025Sbapt char grstr[20]; \ 299287084Sbapt \ 30061759Sdavidn unw_print_grmask (grstr, grmask); \ 30120253Sjoerg printf ("\t%s:gr_gr(grmask=[%s],r%u)\n", fmt, grstr, gr); \ 302287084Sbapt } \ 303287084Sbapt while (0) 30420253Sjoerg 305287084Sbapt#define UNW_DEC_ABI(fmt, abi, context, arg) \ 306287084Sbapt do \ 307287084Sbapt { \ 308287084Sbapt static const char * const abiname[] = \ 309287084Sbapt { \ 310287084Sbapt "@svr4", "@hpux", "@nt" \ 311287084Sbapt }; \ 312287084Sbapt char buf[20]; \ 313287084Sbapt const char *abistr = buf; \ 314287084Sbapt \ 315287084Sbapt if (abi < 3) \ 316287084Sbapt abistr = abiname[abi]; \ 317287084Sbapt else \ 318287084Sbapt sprintf (buf, "0x%x", abi); \ 31920253Sjoerg printf ("\t%s:unwabi(abi=%s,context=0x%02x)\n", \ 32052527Sdavidn fmt, abistr, context); \ 321287084Sbapt } \ 322287084Sbapt while (0) 32352527Sdavidn 324287084Sbapt#define UNW_DEC_PRIUNAT_GR(fmt, r, arg) \ 32520253Sjoerg printf ("\t%s:priunat_gr(reg=r%u)\n", fmt, r) 32620253Sjoerg 327287084Sbapt#define UNW_DEC_PRIUNAT_WHEN_GR(fmt, t, arg) \ 328287084Sbapt printf ("\t%s:priunat_when_gr(t=%lu)\n", fmt, (unsigned long) t) 32920253Sjoerg 33020253Sjoerg#define UNW_DEC_PRIUNAT_WHEN_MEM(fmt, t, arg) \ 331287084Sbapt printf ("\t%s:priunat_when_mem(t=%lu)\n", fmt, (unsigned long) t) 33220253Sjoerg 33320253Sjoerg#define UNW_DEC_PRIUNAT_PSPREL(fmt, pspoff, arg) \ 33420253Sjoerg printf ("\t%s:priunat_psprel(pspoff=0x10-0x%lx)\n", \ 33520253Sjoerg fmt, 4*(unsigned long)pspoff) 33620253Sjoerg 337285536Sbapt#define UNW_DEC_PRIUNAT_SPREL(fmt, spoff, arg) \ 338285092Sbapt printf ("\t%s:priunat_sprel(spoff=0x%lx)\n", \ 33920253Sjoerg fmt, 4*(unsigned long)spoff) 340285092Sbapt 341287084Sbapt#define UNW_DEC_MEM_STACK_F(fmt, t, size, arg) \ 342287084Sbapt printf ("\t%s:mem_stack_f(t=%lu,size=%lu)\n", \ 343287084Sbapt fmt, (unsigned long) t, 16*(unsigned long)size) 344287084Sbapt 345287084Sbapt#define UNW_DEC_MEM_STACK_V(fmt, t, arg) \ 346287084Sbapt printf ("\t%s:mem_stack_v(t=%lu)\n", fmt, (unsigned long) t) 347287084Sbapt 348287084Sbapt#define UNW_DEC_SPILL_BASE(fmt, pspoff, arg) \ 349287084Sbapt printf ("\t%s:spill_base(pspoff=0x10-0x%lx)\n", \ 350287084Sbapt fmt, 4*(unsigned long)pspoff) 351287084Sbapt 352287084Sbapt#define UNW_DEC_SPILL_MASK(fmt, dp, arg, end) \ 353287084Sbapt do \ 354287084Sbapt { \ 355287084Sbapt static const char *spill_type = "-frb"; \ 35620253Sjoerg unsigned const char *imaskp = dp; \ 357287084Sbapt unsigned char mask = 0; \ 358287084Sbapt bfd_vma insn = 0; \ 359287084Sbapt \ 360287084Sbapt /* PR 18420. */ \ 361287084Sbapt if ((dp + (unw_rlen / 4)) > end) \ 362287084Sbapt { \ 363287084Sbapt printf ("\nERROR: unwind length too long (0x%lx > 0x%lx)\n\n",\ 364287084Sbapt (long) (unw_rlen / 4), (long)(end - dp)); \ 36520253Sjoerg /* FIXME: Should we reset unw_rlen ? */ \ 366287084Sbapt break; \ 367287084Sbapt } \ 368287084Sbapt printf ("\t%s:spill_mask(imask=[", fmt); \ 369287084Sbapt for (insn = 0; insn < unw_rlen; ++insn) \ 370287084Sbapt { \ 37120253Sjoerg if ((insn % 4) == 0) \ 372287084Sbapt mask = *imaskp++; \ 373287084Sbapt if (insn > 0 && (insn % 3) == 0) \ 374287084Sbapt putchar (','); \ 375287084Sbapt putchar (spill_type[(mask >> (2 * (3 - (insn & 0x3)))) & 0x3]); \ 376287084Sbapt } \ 377287084Sbapt printf ("])\n"); \ 378287084Sbapt dp = imaskp; \ 37920253Sjoerg } \ 38020253Sjoerg while (0) 381287084Sbapt 382287084Sbapt#define UNW_DEC_SPILL_SPREL(fmt, t, abreg, spoff, arg) \ 38320253Sjoerg do \ 38420253Sjoerg { \ 38520253Sjoerg char regname[20]; \ 38620253Sjoerg \ 38720253Sjoerg unw_print_abreg (regname, abreg); \ 38820253Sjoerg printf ("\t%s:spill_sprel(reg=%s,t=%lu,spoff=0x%lx)\n", \ 38920253Sjoerg fmt, regname, (unsigned long) t, 4*(unsigned long)off); \ 39044229Sdavidn } \ 391287084Sbapt while (0) 392287084Sbapt 393287084Sbapt#define UNW_DEC_SPILL_PSPREL(fmt, t, abreg, pspoff, arg) \ 394287084Sbapt do \ 39520253Sjoerg { \ 39620253Sjoerg char regname[20]; \ 397272192Sdteske \ 398272192Sdteske unw_print_abreg (regname, abreg); \ 39920267Sjoerg printf ("\t%s:spill_psprel(reg=%s,t=%lu,pspoff=0x10-0x%lx)\n", \ 40020253Sjoerg fmt, regname, (unsigned long) t, 4*(unsigned long)pspoff); \ 401287084Sbapt } \ 40220253Sjoerg while (0) 40320253Sjoerg 40420253Sjoerg#define UNW_DEC_RESTORE(fmt, t, abreg, arg) \ 40520253Sjoerg do \ 40620253Sjoerg { \ 40720253Sjoerg char regname[20]; \ 40820253Sjoerg \ 40920253Sjoerg unw_print_abreg (regname, abreg); \ 41020253Sjoerg printf ("\t%s:restore(t=%lu,reg=%s)\n", \ 41120253Sjoerg fmt, (unsigned long) t, regname); \ 412285536Sbapt } \ 413285536Sbapt while (0) 414287084Sbapt 415287084Sbapt#define UNW_DEC_SPILL_REG(fmt, t, abreg, x, ytreg, arg) \ 416287084Sbapt do \ 417287084Sbapt { \ 418287084Sbapt char abregname[20], tregname[20]; \ 419287084Sbapt \ 42044229Sdavidn unw_print_abreg (abregname, abreg); \ 42120267Sjoerg unw_print_xyreg (tregname, x, ytreg); \ 42220267Sjoerg printf ("\t%s:spill_reg(t=%lu,reg=%s,treg=%s)\n", \ 42320253Sjoerg fmt, (unsigned long) t, abregname, tregname); \ 42444229Sdavidn } \ 425287084Sbapt while (0) 42620253Sjoerg 42720253Sjoerg#define UNW_DEC_SPILL_SPREL_P(fmt, qp, t, abreg, spoff, arg) \ 428287084Sbapt do \ 429287084Sbapt { \ 43020253Sjoerg char regname[20]; \ 431285092Sbapt \ 43220253Sjoerg unw_print_abreg (regname, abreg); \ 433287084Sbapt printf ("\t%s:spill_sprel_p(qp=p%u,t=%lu,reg=%s,spoff=0x%lx)\n", \ 434287084Sbapt fmt, qp, (unsigned long) t, regname, 4 * (unsigned long)spoff); \ 43520253Sjoerg } \ 436285092Sbapt while (0) 437285092Sbapt 438285092Sbapt#define UNW_DEC_SPILL_PSPREL_P(fmt, qp, t, abreg, pspoff, arg) \ 439285092Sbapt do \ 440285092Sbapt { \ 44120253Sjoerg char regname[20]; \ 44220253Sjoerg \ 443287084Sbapt unw_print_abreg (regname, abreg); \ 44420253Sjoerg printf ("\t%s:spill_psprel_p(qp=p%u,t=%lu,reg=%s,pspoff=0x10-0x%lx)\n",\ 44520253Sjoerg fmt, qp, (unsigned long) t, regname, 4*(unsigned long)pspoff);\ 44620253Sjoerg } \ 44720253Sjoerg while (0) 44820253Sjoerg 44920253Sjoerg#define UNW_DEC_RESTORE_P(fmt, qp, t, abreg, arg) \ 45020253Sjoerg do \ 45120253Sjoerg { \ 45220253Sjoerg char regname[20]; \ 45320253Sjoerg \ 45420253Sjoerg unw_print_abreg (regname, abreg); \ 455130633Srobert printf ("\t%s:restore_p(qp=p%u,t=%lu,reg=%s)\n", \ 45620253Sjoerg fmt, qp, (unsigned long) t, regname); \ 45720253Sjoerg } \ 45820253Sjoerg while (0) 45920253Sjoerg 46020253Sjoerg#define UNW_DEC_SPILL_REG_P(fmt, qp, t, abreg, x, ytreg, arg) \ 461285092Sbapt do \ 46220253Sjoerg { \ 46320253Sjoerg char regname[20], tregname[20]; \ 46420253Sjoerg \ 46520253Sjoerg unw_print_abreg (regname, abreg); \ 466285092Sbapt unw_print_xyreg (tregname, x, ytreg); \ 46720253Sjoerg printf ("\t%s:spill_reg_p(qp=p%u,t=%lu,reg=%s,treg=%s)\n", \ 46820253Sjoerg fmt, qp, (unsigned long) t, regname, tregname); \ 46920253Sjoerg } \ 47020253Sjoerg while (0) 47120253Sjoerg 47230259Scharnier#define UNW_DEC_LABEL_STATE(fmt, label, arg) \ 47330259Scharnier printf ("\t%s:label_state(label=%lu)\n", fmt, (unsigned long) label) 47420253Sjoerg 47520253Sjoerg#define UNW_DEC_COPY_STATE(fmt, label, arg) \ 47620253Sjoerg printf ("\t%s:copy_state(label=%lu)\n", fmt, (unsigned long) label) 47720253Sjoerg 478287084Sbapt#define UNW_DEC_EPILOGUE(fmt, t, ecount, arg) \ 479287084Sbapt printf ("\t%s:epilogue(t=%lu,ecount=%lu)\n", \ 48020253Sjoerg fmt, (unsigned long) t, (unsigned long) ecount) 48120253Sjoerg 482287084Sbapt/* 48320253Sjoerg * Generic IA-64 unwind info decoder. 48420253Sjoerg * 485179365Santoine * This file is used both by the Linux kernel and objdump. Please 48620253Sjoerg * keep the two copies of this file in sync (modulo differences in the 487179365Santoine * prototypes...). 488179365Santoine * 489287084Sbapt * You need to customize the decoder by defining the following 49020253Sjoerg * macros/constants before including this file: 49120253Sjoerg * 49220253Sjoerg * Types: 493179365Santoine * unw_word Unsigned integer type with at least 64 bits 494231994Skevlo * 49520253Sjoerg * Register names: 496319267Sasomers * UNW_REG_BSP 49720253Sjoerg * UNW_REG_BSPSTORE 49820253Sjoerg * UNW_REG_FPSR 49920253Sjoerg * UNW_REG_LC 50020253Sjoerg * UNW_REG_PFS 501179365Santoine * UNW_REG_PR 502181785Sache * UNW_REG_RNAT 503179365Santoine * UNW_REG_PSP 50420253Sjoerg * UNW_REG_RP 505231994Skevlo * UNW_REG_UNAT 506231994Skevlo * 507231994Skevlo * Decoder action macros: 508319267Sasomers * UNW_DEC_BAD_CODE(code) 509319267Sasomers * UNW_DEC_ABI(fmt,abi,context,arg) 510319267Sasomers * UNW_DEC_BR_GR(fmt,brmask,gr,arg) 51120253Sjoerg * UNW_DEC_BR_MEM(fmt,brmask,arg) 51220253Sjoerg * UNW_DEC_COPY_STATE(fmt,label,arg) 513287084Sbapt * UNW_DEC_EPILOGUE(fmt,t,ecount,arg) 514287084Sbapt * UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg) 51520253Sjoerg * UNW_DEC_FR_MEM(fmt,frmask,arg) 51620253Sjoerg * UNW_DEC_GR_GR(fmt,grmask,gr,arg) 51720253Sjoerg * UNW_DEC_GR_MEM(fmt,grmask,arg) 51820253Sjoerg * UNW_DEC_LABEL_STATE(fmt,label,arg) 51920253Sjoerg * UNW_DEC_MEM_STACK_F(fmt,t,size,arg) 520326849Seugen * UNW_DEC_MEM_STACK_V(fmt,t,arg) 521326849Seugen * UNW_DEC_PRIUNAT_GR(fmt,r,arg) 522326849Seugen * UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) 52373563Skris * UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) 52420253Sjoerg * UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg) 525181785Sache * UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg) 52620253Sjoerg * UNW_DEC_PROLOGUE(fmt,body,rlen,arg) 52720253Sjoerg * UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg) 52820253Sjoerg * UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg) 52920253Sjoerg * UNW_DEC_REG_REG(fmt,src,dst,arg) 53020253Sjoerg * UNW_DEC_REG_SPREL(fmt,reg,spoff,arg) 531287084Sbapt * UNW_DEC_REG_WHEN(fmt,reg,t,arg) 53261957Sache * UNW_DEC_RESTORE(fmt,t,abreg,arg) 53320712Sdavidn * UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg) 53420253Sjoerg * UNW_DEC_SPILL_BASE(fmt,pspoff,arg) 53520253Sjoerg * UNW_DEC_SPILL_MASK(fmt,imaskp,arg) 53620253Sjoerg * UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg) 53720253Sjoerg * UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg) 538326849Seugen * UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg) 539326849Seugen * UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg) 540326849Seugen * UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg) 541326849Seugen * UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg) 542326849Seugen */ 54320253Sjoerg 54420253Sjoergstatic unw_word 54520253Sjoergunw_decode_uleb128 (const unsigned char **dpp) 54620253Sjoerg{ 54720253Sjoerg unsigned shift = 0; 54820253Sjoerg unw_word byte, result = 0; 549285092Sbapt const unsigned char *bp = *dpp; 550287084Sbapt 551285092Sbapt while (1) 552287084Sbapt { 553287084Sbapt byte = *bp++; 554287084Sbapt result |= (byte & 0x7f) << shift; 555287084Sbapt 556287084Sbapt if ((byte & 0x80) == 0) 557287084Sbapt break; 558287084Sbapt 55920253Sjoerg shift += 7; 560287084Sbapt } 561287084Sbapt 562287084Sbapt *dpp = bp; 563287084Sbapt 564287084Sbapt return result; 565287084Sbapt} 566285092Sbapt 567287084Sbaptstatic const unsigned char * 568287084Sbaptunw_decode_x1 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED, 569287084Sbapt void *arg ATTRIBUTE_UNUSED) 570287084Sbapt{ 571287084Sbapt unsigned char byte1, abreg; 572287084Sbapt unw_word t, off; 573287084Sbapt 574287084Sbapt byte1 = *dp++; 575287084Sbapt t = unw_decode_uleb128 (&dp); 576287084Sbapt off = unw_decode_uleb128 (&dp); 577285092Sbapt abreg = (byte1 & 0x7f); 578285092Sbapt if (byte1 & 0x80) 579285092Sbapt UNW_DEC_SPILL_SPREL ("X1", t, abreg, off, arg); 580287084Sbapt else 581285092Sbapt UNW_DEC_SPILL_PSPREL ("X1", t, abreg, off, arg); 582287084Sbapt return dp; 583287084Sbapt} 584287084Sbapt 585285092Sbaptstatic const unsigned char * 586287084Sbaptunw_decode_x2 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED, 587287084Sbapt void *arg ATTRIBUTE_UNUSED) 588287084Sbapt{ 589285092Sbapt unsigned char byte1, byte2, abreg, x, ytreg; 590287084Sbapt unw_word t; 591287084Sbapt 592360326Sdim byte1 = *dp++; 593287084Sbapt byte2 = *dp++; 594287084Sbapt t = unw_decode_uleb128 (&dp); 595287084Sbapt abreg = (byte1 & 0x7f); 596287084Sbapt ytreg = byte2; 597287084Sbapt x = (byte1 >> 7) & 1; 598287084Sbapt if ((byte1 & 0x80) == 0 && ytreg == 0) 599287084Sbapt UNW_DEC_RESTORE ("X2", t, abreg, arg); 600287084Sbapt else 601287084Sbapt UNW_DEC_SPILL_REG ("X2", t, abreg, x, ytreg, arg); 602287084Sbapt return dp; 603287084Sbapt} 604287084Sbapt 605287084Sbaptstatic const unsigned char * 606287084Sbaptunw_decode_x3 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED, 607287084Sbapt void *arg ATTRIBUTE_UNUSED) 608287084Sbapt{ 609287084Sbapt unsigned char byte1, byte2, abreg, qp; 610287084Sbapt unw_word t, off; 611287084Sbapt 612287084Sbapt byte1 = *dp++; 613287084Sbapt byte2 = *dp++; 61420267Sjoerg t = unw_decode_uleb128 (&dp); 615287084Sbapt off = unw_decode_uleb128 (&dp); 61620267Sjoerg 61720267Sjoerg qp = (byte1 & 0x3f); 61820253Sjoerg abreg = (byte2 & 0x7f); 619287084Sbapt 620287084Sbapt if (byte1 & 0x80) 621287084Sbapt UNW_DEC_SPILL_SPREL_P ("X3", qp, t, abreg, off, arg); 62220253Sjoerg else 62320253Sjoerg UNW_DEC_SPILL_PSPREL_P ("X3", qp, t, abreg, off, arg); 624285092Sbapt return dp; 625285092Sbapt} 62620253Sjoerg 627109961Sgadstatic const unsigned char * 628285092Sbaptunw_decode_x4 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED, 629109961Sgad void *arg ATTRIBUTE_UNUSED) 63020253Sjoerg{ 631109961Sgad unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg; 632109961Sgad unw_word t; 633109961Sgad 634109961Sgad byte1 = *dp++; 635330695Sdab byte2 = *dp++; 636109961Sgad byte3 = *dp++; 637109961Sgad t = unw_decode_uleb128 (&dp); 638109961Sgad 639109961Sgad qp = (byte1 & 0x3f); 640109961Sgad abreg = (byte2 & 0x7f); 641109961Sgad x = (byte2 >> 7) & 1; 642109961Sgad ytreg = byte3; 643109961Sgad 64420253Sjoerg if ((byte2 & 0x80) == 0 && byte3 == 0) 645109961Sgad UNW_DEC_RESTORE_P ("X4", qp, t, abreg, arg); 646109961Sgad else 647292026Sbapt UNW_DEC_SPILL_REG_P ("X4", qp, t, abreg, x, ytreg, arg); 648292026Sbapt return dp; 649109961Sgad} 650109961Sgad 651109961Sgadstatic const unsigned char * 652109961Sgadunw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg, 653109961Sgad const unsigned char * end ATTRIBUTE_UNUSED) 654109961Sgad{ 655109961Sgad int body = (code & 0x20) != 0; 656109961Sgad unw_word rlen; 657109961Sgad 658109961Sgad rlen = (code & 0x1f); 659109961Sgad UNW_DEC_PROLOGUE ("R1", body, rlen, arg); 660109961Sgad return dp; 661109961Sgad} 662109961Sgad 663109961Sgadstatic const unsigned char * 664109961Sgadunw_decode_r2 (const unsigned char *dp, unsigned int code, void *arg, 665109961Sgad const unsigned char * end ATTRIBUTE_UNUSED) 666109961Sgad{ 667109961Sgad unsigned char byte1, mask, grsave; 668109961Sgad unw_word rlen; 669109961Sgad 670109961Sgad byte1 = *dp++; 671109961Sgad 672109961Sgad mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1); 673109961Sgad grsave = (byte1 & 0x7f); 674228673Sdim rlen = unw_decode_uleb128 (& dp); 675109961Sgad UNW_DEC_PROLOGUE_GR ("R2", rlen, mask, grsave, arg); 676109961Sgad return dp; 677109961Sgad} 678287084Sbapt 679109961Sgadstatic const unsigned char * 680285092Sbaptunw_decode_r3 (const unsigned char *dp, unsigned int code, void *arg, 681285092Sbapt const unsigned char * end ATTRIBUTE_UNUSED) 68220253Sjoerg{ 68320253Sjoerg unw_word rlen; 68420253Sjoerg 68520253Sjoerg rlen = unw_decode_uleb128 (& dp); 68620253Sjoerg UNW_DEC_PROLOGUE ("R3", ((code & 0x3) == 1), rlen, arg); 68720253Sjoerg return dp; 68820253Sjoerg} 68920253Sjoerg 69020253Sjoergstatic const unsigned char * 69120253Sjoergunw_decode_p1 (const unsigned char *dp, unsigned int code, 69220253Sjoerg void *arg ATTRIBUTE_UNUSED, 69320253Sjoerg const unsigned char * end ATTRIBUTE_UNUSED) 69420253Sjoerg{ 69520253Sjoerg unsigned char brmask = (code & 0x1f); 69620253Sjoerg 69720253Sjoerg UNW_DEC_BR_MEM ("P1", brmask, arg); 69820253Sjoerg return dp; 69920253Sjoerg} 70020253Sjoerg 701287084Sbaptstatic const unsigned char * 702287084Sbaptunw_decode_p2_p5 (const unsigned char *dp, unsigned int code, 70320253Sjoerg void *arg ATTRIBUTE_UNUSED, 70420253Sjoerg const unsigned char * end) 70520253Sjoerg{ 70620253Sjoerg if ((code & 0x10) == 0) 70720253Sjoerg { 70820253Sjoerg unsigned char byte1 = *dp++; 70920747Sdavidn 71020747Sdavidn UNW_DEC_BR_GR ("P2", ((code & 0xf) << 1) | ((byte1 >> 7) & 1), 71185145Sache (byte1 & 0x7f), arg); 71220747Sdavidn } 713287084Sbapt else if ((code & 0x08) == 0) 714287084Sbapt { 715287084Sbapt unsigned char byte1 = *dp++, r, dst; 716287084Sbapt 717287084Sbapt r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1); 718287084Sbapt dst = (byte1 & 0x7f); 719287084Sbapt switch (r) 720287084Sbapt { 72120747Sdavidn case 0: 722287084Sbapt UNW_DEC_REG_GR ("P3", UNW_REG_PSP, dst, arg); 723287084Sbapt break; 72420747Sdavidn case 1: 725287084Sbapt UNW_DEC_REG_GR ("P3", UNW_REG_RP, dst, arg); 726287084Sbapt break; 727287084Sbapt case 2: 728287084Sbapt UNW_DEC_REG_GR ("P3", UNW_REG_PFS, dst, arg); 729287084Sbapt break; 730287084Sbapt case 3: 731287084Sbapt UNW_DEC_REG_GR ("P3", UNW_REG_PR, dst, arg); 732287084Sbapt break; 733287084Sbapt case 4: 734287084Sbapt UNW_DEC_REG_GR ("P3", UNW_REG_UNAT, dst, arg); 735287084Sbapt break; 736287084Sbapt case 5: 737287084Sbapt UNW_DEC_REG_GR ("P3", UNW_REG_LC, dst, arg); 738287084Sbapt break; 739287084Sbapt case 6: 740287084Sbapt UNW_DEC_RP_BR ("P3", dst, arg); 741287084Sbapt break; 742287084Sbapt case 7: 743287084Sbapt UNW_DEC_REG_GR ("P3", UNW_REG_RNAT, dst, arg); 744287084Sbapt break; 745287084Sbapt case 8: 746287084Sbapt UNW_DEC_REG_GR ("P3", UNW_REG_BSP, dst, arg); 747287084Sbapt break; 748287084Sbapt case 9: 749287084Sbapt UNW_DEC_REG_GR ("P3", UNW_REG_BSPSTORE, dst, arg); 750287084Sbapt break; 751287084Sbapt case 10: 752287084Sbapt UNW_DEC_REG_GR ("P3", UNW_REG_FPSR, dst, arg); 753287084Sbapt break; 754287084Sbapt case 11: 755287084Sbapt UNW_DEC_PRIUNAT_GR ("P3", dst, arg); 756287084Sbapt break; 757287084Sbapt default: 758287084Sbapt UNW_DEC_BAD_CODE (r); 759287084Sbapt break; 760287084Sbapt } 761287084Sbapt } 762287084Sbapt else if ((code & 0x7) == 0) 763287084Sbapt UNW_DEC_SPILL_MASK ("P4", dp, arg, end); 764287084Sbapt else if ((code & 0x7) == 1) 765287084Sbapt { 766287084Sbapt unw_word grmask, frmask, byte1, byte2, byte3; 767287084Sbapt 768287084Sbapt byte1 = *dp++; 769287084Sbapt byte2 = *dp++; 770287084Sbapt byte3 = *dp++; 771287084Sbapt grmask = ((byte1 >> 4) & 0xf); 772287084Sbapt frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3; 773287084Sbapt UNW_DEC_FRGR_MEM ("P5", grmask, frmask, arg); 774287084Sbapt } 775287084Sbapt else 776287084Sbapt UNW_DEC_BAD_CODE (code); 777287084Sbapt 778287084Sbapt return dp; 779287084Sbapt} 780287084Sbapt 781287084Sbaptstatic const unsigned char * 782287084Sbaptunw_decode_p6 (const unsigned char *dp, unsigned int code, 783287084Sbapt void *arg ATTRIBUTE_UNUSED, 784287084Sbapt const unsigned char * end ATTRIBUTE_UNUSED) 785287084Sbapt{ 786287084Sbapt int gregs = (code & 0x10) != 0; 787287084Sbapt unsigned char mask = (code & 0x0f); 788287084Sbapt 789287084Sbapt if (gregs) 790287084Sbapt UNW_DEC_GR_MEM ("P6", mask, arg); 791287084Sbapt else 792287084Sbapt UNW_DEC_FR_MEM ("P6", mask, arg); 793287084Sbapt return dp; 794287084Sbapt} 795287084Sbapt 796287084Sbaptstatic const unsigned char * 797287084Sbaptunw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg, 798287084Sbapt const unsigned char * end ATTRIBUTE_UNUSED) 799287084Sbapt{ 800287084Sbapt unsigned char r, byte1, byte2; 801287084Sbapt unw_word t, size; 802287084Sbapt 803287084Sbapt if ((code & 0x10) == 0) 804287084Sbapt { 805287084Sbapt r = (code & 0xf); 806287084Sbapt t = unw_decode_uleb128 (&dp); 807287084Sbapt switch (r) 808287084Sbapt { 809287084Sbapt case 0: 810287084Sbapt size = unw_decode_uleb128 (&dp); 811287084Sbapt UNW_DEC_MEM_STACK_F ("P7", t, size, arg); 812287084Sbapt break; 813287084Sbapt 814287084Sbapt case 1: 815287084Sbapt UNW_DEC_MEM_STACK_V ("P7", t, arg); 816293682Sbapt break; 817287084Sbapt case 2: 818287084Sbapt UNW_DEC_SPILL_BASE ("P7", t, arg); 819287084Sbapt break; 820287084Sbapt case 3: 821287084Sbapt UNW_DEC_REG_SPREL ("P7", UNW_REG_PSP, t, arg); 822287084Sbapt break; 823287084Sbapt case 4: 824287084Sbapt UNW_DEC_REG_WHEN ("P7", UNW_REG_RP, t, arg); 825287084Sbapt break; 826287084Sbapt case 5: 827287084Sbapt UNW_DEC_REG_PSPREL ("P7", UNW_REG_RP, t, arg); 828287084Sbapt break; 829287084Sbapt case 6: 830287084Sbapt UNW_DEC_REG_WHEN ("P7", UNW_REG_PFS, t, arg); 831287084Sbapt break; 832287084Sbapt case 7: 833287084Sbapt UNW_DEC_REG_PSPREL ("P7", UNW_REG_PFS, t, arg); 834287084Sbapt break; 835287084Sbapt case 8: 836287084Sbapt UNW_DEC_REG_WHEN ("P7", UNW_REG_PR, t, arg); 837287084Sbapt break; 838287084Sbapt case 9: 839287084Sbapt UNW_DEC_REG_PSPREL ("P7", UNW_REG_PR, t, arg); 840287084Sbapt break; 841287084Sbapt case 10: 842287084Sbapt UNW_DEC_REG_WHEN ("P7", UNW_REG_LC, t, arg); 843287084Sbapt break; 844287084Sbapt case 11: 845287084Sbapt UNW_DEC_REG_PSPREL ("P7", UNW_REG_LC, t, arg); 846287084Sbapt break; 847287084Sbapt case 12: 848287084Sbapt UNW_DEC_REG_WHEN ("P7", UNW_REG_UNAT, t, arg); 849287084Sbapt break; 850287084Sbapt case 13: 851287084Sbapt UNW_DEC_REG_PSPREL ("P7", UNW_REG_UNAT, t, arg); 852287084Sbapt break; 853287084Sbapt case 14: 854287084Sbapt UNW_DEC_REG_WHEN ("P7", UNW_REG_FPSR, t, arg); 855287084Sbapt break; 856287084Sbapt case 15: 857287084Sbapt UNW_DEC_REG_PSPREL ("P7", UNW_REG_FPSR, t, arg); 858287084Sbapt break; 859287084Sbapt default: 860287084Sbapt UNW_DEC_BAD_CODE (r); 861287084Sbapt break; 862287084Sbapt } 863287084Sbapt } 864287084Sbapt else 865287084Sbapt { 866287084Sbapt switch (code & 0xf) 867287084Sbapt { 868287084Sbapt case 0x0: /* p8 */ 869287084Sbapt { 870287084Sbapt r = *dp++; 871287084Sbapt t = unw_decode_uleb128 (&dp); 872287084Sbapt switch (r) 873287084Sbapt { 874287084Sbapt case 1: 875287084Sbapt UNW_DEC_REG_SPREL ("P8", UNW_REG_RP, t, arg); 876287084Sbapt break; 877287084Sbapt case 2: 878287084Sbapt UNW_DEC_REG_SPREL ("P8", UNW_REG_PFS, t, arg); 879287084Sbapt break; 880287084Sbapt case 3: 881287084Sbapt UNW_DEC_REG_SPREL ("P8", UNW_REG_PR, t, arg); 882287084Sbapt break; 883287084Sbapt case 4: 884287084Sbapt UNW_DEC_REG_SPREL ("P8", UNW_REG_LC, t, arg); 885287084Sbapt break; 886287084Sbapt case 5: 887287084Sbapt UNW_DEC_REG_SPREL ("P8", UNW_REG_UNAT, t, arg); 888287084Sbapt break; 889287084Sbapt case 6: 890287084Sbapt UNW_DEC_REG_SPREL ("P8", UNW_REG_FPSR, t, arg); 891287084Sbapt break; 892287084Sbapt case 7: 893287084Sbapt UNW_DEC_REG_WHEN ("P8", UNW_REG_BSP, t, arg); 894287084Sbapt break; 895287084Sbapt case 8: 896287084Sbapt UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSP, t, arg); 897287084Sbapt break; 898287084Sbapt case 9: 899287084Sbapt UNW_DEC_REG_SPREL ("P8", UNW_REG_BSP, t, arg); 900287084Sbapt break; 901287084Sbapt case 10: 902287084Sbapt UNW_DEC_REG_WHEN ("P8", UNW_REG_BSPSTORE, t, arg); 903287084Sbapt break; 904287084Sbapt case 11: 905287084Sbapt UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSPSTORE, t, arg); 906287084Sbapt break; 907287084Sbapt case 12: 908287084Sbapt UNW_DEC_REG_SPREL ("P8", UNW_REG_BSPSTORE, t, arg); 909287084Sbapt break; 910287084Sbapt case 13: 911287084Sbapt UNW_DEC_REG_WHEN ("P8", UNW_REG_RNAT, t, arg); 912287084Sbapt break; 913287084Sbapt case 14: 914287084Sbapt UNW_DEC_REG_PSPREL ("P8", UNW_REG_RNAT, t, arg); 915287084Sbapt break; 916287084Sbapt case 15: 917287084Sbapt UNW_DEC_REG_SPREL ("P8", UNW_REG_RNAT, t, arg); 918287084Sbapt break; 919287084Sbapt case 16: 920287084Sbapt UNW_DEC_PRIUNAT_WHEN_GR ("P8", t, arg); 921287084Sbapt break; 922287084Sbapt case 17: 923287084Sbapt UNW_DEC_PRIUNAT_PSPREL ("P8", t, arg); 924287084Sbapt break; 925287084Sbapt case 18: 926287084Sbapt UNW_DEC_PRIUNAT_SPREL ("P8", t, arg); 927287084Sbapt break; 928287084Sbapt case 19: 929287084Sbapt UNW_DEC_PRIUNAT_WHEN_MEM ("P8", t, arg); 930287084Sbapt break; 931287084Sbapt default: 932287084Sbapt UNW_DEC_BAD_CODE (r); 933287084Sbapt break; 934287084Sbapt } 935287084Sbapt } 936287084Sbapt break; 937287084Sbapt 938287084Sbapt case 0x1: 939287084Sbapt byte1 = *dp++; 940287084Sbapt byte2 = *dp++; 941287084Sbapt UNW_DEC_GR_GR ("P9", (byte1 & 0xf), (byte2 & 0x7f), arg); 942287084Sbapt break; 943287084Sbapt 944287084Sbapt case 0xf: /* p10 */ 945287084Sbapt byte1 = *dp++; 946287084Sbapt byte2 = *dp++; 947287084Sbapt UNW_DEC_ABI ("P10", byte1, byte2, arg); 948287084Sbapt break; 949287084Sbapt 950287084Sbapt case 0x9: 951287084Sbapt return unw_decode_x1 (dp, code, arg); 952287084Sbapt 953287084Sbapt case 0xa: 954287084Sbapt return unw_decode_x2 (dp, code, arg); 955287084Sbapt 956287084Sbapt case 0xb: 957287084Sbapt return unw_decode_x3 (dp, code, arg); 958287084Sbapt 959287084Sbapt case 0xc: 960287084Sbapt return unw_decode_x4 (dp, code, arg); 961287084Sbapt 962287084Sbapt default: 963287084Sbapt UNW_DEC_BAD_CODE (code); 964287084Sbapt break; 965287084Sbapt } 966287084Sbapt } 967287084Sbapt return dp; 968287084Sbapt} 969287084Sbapt 970287084Sbaptstatic const unsigned char * 971287084Sbaptunw_decode_b1 (const unsigned char *dp, unsigned int code, 972287084Sbapt void *arg ATTRIBUTE_UNUSED, 973287084Sbapt const unsigned char * end ATTRIBUTE_UNUSED) 974287084Sbapt{ 975287084Sbapt unw_word label = (code & 0x1f); 976287084Sbapt 977287084Sbapt if ((code & 0x20) != 0) 978287084Sbapt UNW_DEC_COPY_STATE ("B1", label, arg); 979287084Sbapt else 980287084Sbapt UNW_DEC_LABEL_STATE ("B1", label, arg); 981287084Sbapt return dp; 982287084Sbapt} 983287084Sbapt 984287084Sbaptstatic const unsigned char * 985287084Sbaptunw_decode_b2 (const unsigned char *dp, unsigned int code, 986287084Sbapt void *arg ATTRIBUTE_UNUSED, 987287084Sbapt const unsigned char * end ATTRIBUTE_UNUSED) 988287084Sbapt{ 989287084Sbapt unw_word t; 990287084Sbapt 991287084Sbapt t = unw_decode_uleb128 (& dp); 992287084Sbapt UNW_DEC_EPILOGUE ("B2", t, (code & 0x1f), arg); 993287084Sbapt return dp; 994287084Sbapt} 995287084Sbapt 996287084Sbaptstatic const unsigned char * 997287084Sbaptunw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg, 998287084Sbapt const unsigned char * end ATTRIBUTE_UNUSED) 999287084Sbapt{ 1000287084Sbapt unw_word t, ecount, label; 1001287084Sbapt 1002287084Sbapt if ((code & 0x10) == 0) 1003287084Sbapt { 1004287084Sbapt t = unw_decode_uleb128 (&dp); 1005287084Sbapt ecount = unw_decode_uleb128 (&dp); 1006287084Sbapt UNW_DEC_EPILOGUE ("B3", t, ecount, arg); 1007287084Sbapt } 1008287084Sbapt else if ((code & 0x07) == 0) 1009287084Sbapt { 1010287084Sbapt label = unw_decode_uleb128 (&dp); 1011287084Sbapt if ((code & 0x08) != 0) 1012287084Sbapt UNW_DEC_COPY_STATE ("B4", label, arg); 1013287084Sbapt else 1014287084Sbapt UNW_DEC_LABEL_STATE ("B4", label, arg); 1015287084Sbapt } 1016287084Sbapt else 1017287084Sbapt switch (code & 0x7) 1018287084Sbapt { 1019287084Sbapt case 1: 1020287084Sbapt return unw_decode_x1 (dp, code, arg); 1021287084Sbapt case 2: 1022287084Sbapt return unw_decode_x2 (dp, code, arg); 1023287084Sbapt case 3: 1024287084Sbapt return unw_decode_x3 (dp, code, arg); 1025287084Sbapt case 4: 1026287084Sbapt return unw_decode_x4 (dp, code, arg); 1027287084Sbapt default: 1028287084Sbapt UNW_DEC_BAD_CODE (code); 1029287084Sbapt break; 1030287084Sbapt } 1031287084Sbapt return dp; 1032287084Sbapt} 1033287084Sbapt 1034287084Sbapttypedef const unsigned char *(*unw_decoder) 1035287084Sbapt (const unsigned char *, unsigned int, void *, const unsigned char *); 1036287084Sbapt 1037287084Sbaptstatic const unw_decoder unw_decode_table[2][8] = 1038287084Sbapt { 1039287084Sbapt /* prologue table: */ 1040287084Sbapt { 1041287084Sbapt unw_decode_r1, /* 0 */ 1042287084Sbapt unw_decode_r1, 1043287084Sbapt unw_decode_r2, 1044287084Sbapt unw_decode_r3, 1045287084Sbapt unw_decode_p1, /* 4 */ 1046287084Sbapt unw_decode_p2_p5, 1047287084Sbapt unw_decode_p6, 1048287084Sbapt unw_decode_p7_p10 1049287084Sbapt }, 1050287084Sbapt { 1051287084Sbapt unw_decode_r1, /* 0 */ 1052287084Sbapt unw_decode_r1, 1053287084Sbapt unw_decode_r2, 1054287084Sbapt unw_decode_r3, 1055287084Sbapt unw_decode_b1, /* 4 */ 1056287084Sbapt unw_decode_b1, 1057287084Sbapt unw_decode_b2, 1058287084Sbapt unw_decode_b3_x4 1059287084Sbapt } 1060287084Sbapt }; 1061287084Sbapt 1062287084Sbapt/* Decode one descriptor and return address of next descriptor. */ 1063287084Sbaptconst unsigned char * 1064287084Sbaptunw_decode (const unsigned char *dp, int inside_body, 1065287084Sbapt void *ptr_inside_body, const unsigned char * end) 1066287084Sbapt{ 1067287084Sbapt unw_decoder decoder; 1068287084Sbapt unsigned char code; 1069287084Sbapt 1070287084Sbapt code = *dp++; 1071287084Sbapt decoder = unw_decode_table[inside_body][code >> 5]; 1072287084Sbapt return (*decoder) (dp, code, ptr_inside_body, end); 1073287084Sbapt} 1074287084Sbapt