1 /* unwind-ia64.c -- utility routines to dump IA-64 unwind info for readelf.
2    Copyright (C) 2000-2020 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 }
1148