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