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