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
36static bfd_vma unw_rlen = 0;
37
38static void unw_print_brmask (char *, unsigned int);
39static void unw_print_grmask (char *, unsigned int);
40static void unw_print_frmask (char *, unsigned int);
41static void unw_print_abreg (char *, unsigned int);
42static void unw_print_xyreg (char *, unsigned int, unsigned int);
43
44static void
45unw_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
65static void
66unw_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
86static void
87unw_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
113static void
114unw_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
143static void
144unw_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
173typedef 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
543static unw_word
544unw_decode_uleb128 (const unsigned char **dpp, const unsigned char * end)
545{
546  unsigned shift = 0;
547  int status = 1;
548  unw_word byte, result = 0;
549  const unsigned char *bp = *dpp;
550
551  while (bp < end)
552    {
553      byte = *bp++;
554      if (shift < sizeof (result) * 8)
555	{
556	  result |= (byte & 0x7f) << shift;
557	  if ((result >> shift) != (byte & 0x7f))
558	    /* Overflow.  */
559	    status |= 2;
560	  shift += 7;
561	}
562      else if ((byte & 0x7f) != 0)
563	status |= 2;
564
565      if ((byte & 0x80) == 0)
566	{
567	  status &= ~1;
568	  break;
569	}
570    }
571
572  *dpp = bp;
573  if (status != 0)
574    printf (_("Bad uleb128\n"));
575
576  return result;
577}
578
579static const unsigned char *
580unw_decode_x1 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
581	       void *arg ATTRIBUTE_UNUSED, const unsigned char * end)
582{
583  unsigned char byte1, abreg;
584  unw_word t, off;
585
586  if ((end - dp) < 3)
587    {
588      printf (_("\t<corrupt X1>\n"));
589      return end;
590    }
591
592  byte1 = *dp++;
593  t = unw_decode_uleb128 (&dp, end);
594  off = unw_decode_uleb128 (&dp, end);
595  abreg = (byte1 & 0x7f);
596  if (byte1 & 0x80)
597    UNW_DEC_SPILL_SPREL ("X1", t, abreg, off, arg);
598  else
599    UNW_DEC_SPILL_PSPREL ("X1", t, abreg, off, arg);
600  return dp;
601}
602
603static const unsigned char *
604unw_decode_x2 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
605	       void *arg ATTRIBUTE_UNUSED, const unsigned char * end)
606{
607  unsigned char byte1, byte2, abreg, x, ytreg;
608  unw_word t;
609
610  if ((end - dp) < 3)
611    {
612      printf (_("\t<corrupt X2>\n"));
613      return end;
614    }
615
616  byte1 = *dp++;
617  byte2 = *dp++;
618  t = unw_decode_uleb128 (&dp, end);
619  abreg = (byte1 & 0x7f);
620  ytreg = byte2;
621  x = (byte1 >> 7) & 1;
622  if ((byte1 & 0x80) == 0 && ytreg == 0)
623    UNW_DEC_RESTORE ("X2", t, abreg, arg);
624  else
625    UNW_DEC_SPILL_REG ("X2", t, abreg, x, ytreg, arg);
626  return dp;
627}
628
629static const unsigned char *
630unw_decode_x3 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
631	       void *arg ATTRIBUTE_UNUSED, const unsigned char * end)
632{
633  unsigned char byte1, byte2, abreg, qp;
634  unw_word t, off;
635
636  if ((end - dp) < 4)
637    {
638      printf (_("\t<corrupt X3>\n"));
639      return end;
640    }
641
642  byte1 = *dp++;
643  byte2 = *dp++;
644  t = unw_decode_uleb128 (&dp, end);
645  off = unw_decode_uleb128 (&dp, end);
646
647  qp = (byte1 & 0x3f);
648  abreg = (byte2 & 0x7f);
649
650  if (byte1 & 0x80)
651    UNW_DEC_SPILL_SPREL_P ("X3", qp, t, abreg, off, arg);
652  else
653    UNW_DEC_SPILL_PSPREL_P ("X3", qp, t, abreg, off, arg);
654  return dp;
655}
656
657static const unsigned char *
658unw_decode_x4 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
659	       void *arg ATTRIBUTE_UNUSED, const unsigned char * end)
660{
661  unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
662  unw_word t;
663
664  if ((end - dp) < 4)
665    {
666      printf (_("\t<corrupt X4>\n"));
667      return end;
668    }
669
670  byte1 = *dp++;
671  byte2 = *dp++;
672  byte3 = *dp++;
673  t = unw_decode_uleb128 (&dp, end);
674
675  qp = (byte1 & 0x3f);
676  abreg = (byte2 & 0x7f);
677  x = (byte2 >> 7) & 1;
678  ytreg = byte3;
679
680  if ((byte2 & 0x80) == 0 && byte3 == 0)
681    UNW_DEC_RESTORE_P ("X4", qp, t, abreg, arg);
682  else
683    UNW_DEC_SPILL_REG_P ("X4", qp, t, abreg, x, ytreg, arg);
684  return dp;
685}
686
687static const unsigned char *
688unw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg,
689	       const unsigned char * end ATTRIBUTE_UNUSED)
690{
691  int body = (code & 0x20) != 0;
692  unw_word rlen;
693
694  rlen = (code & 0x1f);
695  UNW_DEC_PROLOGUE ("R1", body, rlen, arg);
696  return dp;
697}
698
699static const unsigned char *
700unw_decode_r2 (const unsigned char *dp, unsigned int code, void *arg,
701	       const unsigned char * end)
702{
703  unsigned char byte1, mask, grsave;
704  unw_word rlen;
705
706  if ((end - dp) < 2)
707    {
708      printf (_("\t<corrupt R2>\n"));
709      return end;
710    }
711
712  byte1 = *dp++;
713
714  mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
715  grsave = (byte1 & 0x7f);
716  rlen = unw_decode_uleb128 (& dp, end);
717  UNW_DEC_PROLOGUE_GR ("R2", rlen, mask, grsave, arg);
718  return dp;
719}
720
721static const unsigned char *
722unw_decode_r3 (const unsigned char *dp, unsigned int code, void *arg,
723	       const unsigned char * end)
724{
725  unw_word rlen;
726
727  rlen = unw_decode_uleb128 (& dp, end);
728  UNW_DEC_PROLOGUE ("R3", ((code & 0x3) == 1), rlen, arg);
729  return dp;
730}
731
732static const unsigned char *
733unw_decode_p1 (const unsigned char *dp, unsigned int code,
734	       void *arg ATTRIBUTE_UNUSED,
735	       const unsigned char * end ATTRIBUTE_UNUSED)
736{
737  unsigned char brmask = (code & 0x1f);
738
739  UNW_DEC_BR_MEM ("P1", brmask, arg);
740  return dp;
741}
742
743static const unsigned char *
744unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
745		  void *arg ATTRIBUTE_UNUSED,
746		  const unsigned char * end)
747{
748  if ((code & 0x10) == 0)
749    {
750      unsigned char byte1;
751
752      if ((end - dp) < 1)
753	{
754	  printf (_("\t<corrupt P2>\n"));
755	  return end;
756	}
757
758      byte1 = *dp++;
759
760      UNW_DEC_BR_GR ("P2", ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
761		     (byte1 & 0x7f), arg);
762    }
763  else if ((code & 0x08) == 0)
764    {
765      unsigned char byte1, r, dst;
766
767      if ((end - dp) < 1)
768	{
769	  printf (_("\t<corrupt P3>\n"));
770	  return end;
771	}
772
773      byte1 = *dp++;
774
775      r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
776      dst = (byte1 & 0x7f);
777      switch (r)
778	{
779	case 0:
780	  UNW_DEC_REG_GR ("P3", UNW_REG_PSP, dst, arg);
781	  break;
782	case 1:
783	  UNW_DEC_REG_GR ("P3", UNW_REG_RP, dst, arg);
784	  break;
785	case 2:
786	  UNW_DEC_REG_GR ("P3", UNW_REG_PFS, dst, arg);
787	  break;
788	case 3:
789	  UNW_DEC_REG_GR ("P3", UNW_REG_PR, dst, arg);
790	  break;
791	case 4:
792	  UNW_DEC_REG_GR ("P3", UNW_REG_UNAT, dst, arg);
793	  break;
794	case 5:
795	  UNW_DEC_REG_GR ("P3", UNW_REG_LC, dst, arg);
796	  break;
797	case 6:
798	  UNW_DEC_RP_BR ("P3", dst, arg);
799	  break;
800	case 7:
801	  UNW_DEC_REG_GR ("P3", UNW_REG_RNAT, dst, arg);
802	  break;
803	case 8:
804	  UNW_DEC_REG_GR ("P3", UNW_REG_BSP, dst, arg);
805	  break;
806	case 9:
807	  UNW_DEC_REG_GR ("P3", UNW_REG_BSPSTORE, dst, arg);
808	  break;
809	case 10:
810	  UNW_DEC_REG_GR ("P3", UNW_REG_FPSR, dst, arg);
811	  break;
812	case 11:
813	  UNW_DEC_PRIUNAT_GR ("P3", dst, arg);
814	  break;
815	default:
816	  UNW_DEC_BAD_CODE (r);
817	  break;
818	}
819    }
820  else if ((code & 0x7) == 0)
821    UNW_DEC_SPILL_MASK ("P4", dp, arg, end);
822  else if ((code & 0x7) == 1)
823    {
824      unw_word grmask, frmask, byte1, byte2, byte3;
825
826      if ((end - dp) < 3)
827	{
828	  printf (_("\t<corrupt P5>\n"));
829	  return end;
830	}
831      byte1 = *dp++;
832      byte2 = *dp++;
833      byte3 = *dp++;
834      grmask = ((byte1 >> 4) & 0xf);
835      frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
836      UNW_DEC_FRGR_MEM ("P5", grmask, frmask, arg);
837    }
838  else
839    UNW_DEC_BAD_CODE (code);
840
841  return dp;
842}
843
844static const unsigned char *
845unw_decode_p6 (const unsigned char *dp, unsigned int code,
846	       void *arg ATTRIBUTE_UNUSED,
847	       const unsigned char * end ATTRIBUTE_UNUSED)
848{
849  int gregs = (code & 0x10) != 0;
850  unsigned char mask = (code & 0x0f);
851
852  if (gregs)
853    UNW_DEC_GR_MEM ("P6", mask, arg);
854  else
855    UNW_DEC_FR_MEM ("P6", mask, arg);
856  return dp;
857}
858
859static const unsigned char *
860unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg,
861		   const unsigned char * end)
862{
863  unsigned char r, byte1, byte2;
864  unw_word t, size;
865
866  if ((code & 0x10) == 0)
867    {
868      r = (code & 0xf);
869      t = unw_decode_uleb128 (&dp, end);
870      switch (r)
871	{
872	case 0:
873	  size = unw_decode_uleb128 (&dp, end);
874	  UNW_DEC_MEM_STACK_F ("P7", t, size, arg);
875	  break;
876
877	case 1:
878	  UNW_DEC_MEM_STACK_V ("P7", t, arg);
879	  break;
880	case 2:
881	  UNW_DEC_SPILL_BASE ("P7", t, arg);
882	  break;
883	case 3:
884	  UNW_DEC_REG_SPREL ("P7", UNW_REG_PSP, t, arg);
885	  break;
886	case 4:
887	  UNW_DEC_REG_WHEN ("P7", UNW_REG_RP, t, arg);
888	  break;
889	case 5:
890	  UNW_DEC_REG_PSPREL ("P7", UNW_REG_RP, t, arg);
891	  break;
892	case 6:
893	  UNW_DEC_REG_WHEN ("P7", UNW_REG_PFS, t, arg);
894	  break;
895	case 7:
896	  UNW_DEC_REG_PSPREL ("P7", UNW_REG_PFS, t, arg);
897	  break;
898	case 8:
899	  UNW_DEC_REG_WHEN ("P7", UNW_REG_PR, t, arg);
900	  break;
901	case 9:
902	  UNW_DEC_REG_PSPREL ("P7", UNW_REG_PR, t, arg);
903	  break;
904	case 10:
905	  UNW_DEC_REG_WHEN ("P7", UNW_REG_LC, t, arg);
906	  break;
907	case 11:
908	  UNW_DEC_REG_PSPREL ("P7", UNW_REG_LC, t, arg);
909	  break;
910	case 12:
911	  UNW_DEC_REG_WHEN ("P7", UNW_REG_UNAT, t, arg);
912	  break;
913	case 13:
914	  UNW_DEC_REG_PSPREL ("P7", UNW_REG_UNAT, t, arg);
915	  break;
916	case 14:
917	  UNW_DEC_REG_WHEN ("P7", UNW_REG_FPSR, t, arg);
918	  break;
919	case 15:
920	  UNW_DEC_REG_PSPREL ("P7", UNW_REG_FPSR, t, arg);
921	  break;
922	default:
923	  UNW_DEC_BAD_CODE (r);
924	  break;
925	}
926    }
927  else
928    {
929      switch (code & 0xf)
930	{
931	case 0x0:		/* p8 */
932	  {
933	    if ((end - dp) < 2)
934	      {
935		printf (_("\t<corrupt P8>\n"));
936		return end;
937	      }
938
939	    r = *dp++;
940	    t = unw_decode_uleb128 (&dp, end);
941	    switch (r)
942	      {
943	      case 1:
944		UNW_DEC_REG_SPREL ("P8", UNW_REG_RP, t, arg);
945		break;
946	      case 2:
947		UNW_DEC_REG_SPREL ("P8", UNW_REG_PFS, t, arg);
948		break;
949	      case 3:
950		UNW_DEC_REG_SPREL ("P8", UNW_REG_PR, t, arg);
951		break;
952	      case 4:
953		UNW_DEC_REG_SPREL ("P8", UNW_REG_LC, t, arg);
954		break;
955	      case 5:
956		UNW_DEC_REG_SPREL ("P8", UNW_REG_UNAT, t, arg);
957		break;
958	      case 6:
959		UNW_DEC_REG_SPREL ("P8", UNW_REG_FPSR, t, arg);
960		break;
961	      case 7:
962		UNW_DEC_REG_WHEN ("P8", UNW_REG_BSP, t, arg);
963		break;
964	      case 8:
965		UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSP, t, arg);
966		break;
967	      case 9:
968		UNW_DEC_REG_SPREL ("P8", UNW_REG_BSP, t, arg);
969		break;
970	      case 10:
971		UNW_DEC_REG_WHEN ("P8", UNW_REG_BSPSTORE, t, arg);
972		break;
973	      case 11:
974		UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSPSTORE, t, arg);
975		break;
976	      case 12:
977		UNW_DEC_REG_SPREL ("P8", UNW_REG_BSPSTORE, t, arg);
978		break;
979	      case 13:
980		UNW_DEC_REG_WHEN ("P8", UNW_REG_RNAT, t, arg);
981		break;
982	      case 14:
983		UNW_DEC_REG_PSPREL ("P8", UNW_REG_RNAT, t, arg);
984		break;
985	      case 15:
986		UNW_DEC_REG_SPREL ("P8", UNW_REG_RNAT, t, arg);
987		break;
988	      case 16:
989		UNW_DEC_PRIUNAT_WHEN_GR ("P8", t, arg);
990		break;
991	      case 17:
992		UNW_DEC_PRIUNAT_PSPREL ("P8", t, arg);
993		break;
994	      case 18:
995		UNW_DEC_PRIUNAT_SPREL ("P8", t, arg);
996		break;
997	      case 19:
998		UNW_DEC_PRIUNAT_WHEN_MEM ("P8", t, arg);
999		break;
1000	      default:
1001		UNW_DEC_BAD_CODE (r);
1002		break;
1003	      }
1004	  }
1005	  break;
1006
1007	case 0x1:
1008	  if ((end - dp) < 2)
1009	    {
1010	      printf (_("\t<corrupt P9>\n"));
1011	      return end;
1012	    }
1013
1014	  byte1 = *dp++;
1015	  byte2 = *dp++;
1016	  UNW_DEC_GR_GR ("P9", (byte1 & 0xf), (byte2 & 0x7f), arg);
1017	  break;
1018
1019	case 0xf:		/* p10 */
1020	  if ((end - dp) < 2)
1021	    {
1022	      printf (_("\t<corrupt P10>\n"));
1023	      return end;
1024	    }
1025
1026	  byte1 = *dp++;
1027	  byte2 = *dp++;
1028	  UNW_DEC_ABI ("P10", byte1, byte2, arg);
1029	  break;
1030
1031	case 0x9:
1032	  return unw_decode_x1 (dp, code, arg, end);
1033
1034	case 0xa:
1035	  return unw_decode_x2 (dp, code, arg, end);
1036
1037	case 0xb:
1038	  return unw_decode_x3 (dp, code, arg, end);
1039
1040	case 0xc:
1041	  return unw_decode_x4 (dp, code, arg, end);
1042
1043	default:
1044	  UNW_DEC_BAD_CODE (code);
1045	  break;
1046	}
1047    }
1048  return dp;
1049}
1050
1051static const unsigned char *
1052unw_decode_b1 (const unsigned char *dp, unsigned int code,
1053	       void *arg ATTRIBUTE_UNUSED,
1054	       const unsigned char * end ATTRIBUTE_UNUSED)
1055{
1056  unw_word label = (code & 0x1f);
1057
1058  if ((code & 0x20) != 0)
1059    UNW_DEC_COPY_STATE ("B1", label, arg);
1060  else
1061    UNW_DEC_LABEL_STATE ("B1", label, arg);
1062  return dp;
1063}
1064
1065static const unsigned char *
1066unw_decode_b2 (const unsigned char *dp, unsigned int code,
1067	       void *arg ATTRIBUTE_UNUSED,
1068	       const unsigned char * end)
1069{
1070  unw_word t;
1071
1072  t = unw_decode_uleb128 (& dp, end);
1073  UNW_DEC_EPILOGUE ("B2", t, (code & 0x1f), arg);
1074  return dp;
1075}
1076
1077static const unsigned char *
1078unw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg,
1079		  const unsigned char * end)
1080{
1081  unw_word t, ecount, label;
1082
1083  if ((code & 0x10) == 0)
1084    {
1085      t = unw_decode_uleb128 (&dp, end);
1086      ecount = unw_decode_uleb128 (&dp, end);
1087      UNW_DEC_EPILOGUE ("B3", t, ecount, arg);
1088    }
1089  else if ((code & 0x07) == 0)
1090    {
1091      label = unw_decode_uleb128 (&dp, end);
1092      if ((code & 0x08) != 0)
1093	UNW_DEC_COPY_STATE ("B4", label, arg);
1094      else
1095	UNW_DEC_LABEL_STATE ("B4", label, arg);
1096    }
1097  else
1098    switch (code & 0x7)
1099      {
1100      case 1:
1101	return unw_decode_x1 (dp, code, arg, end);
1102      case 2:
1103	return unw_decode_x2 (dp, code, arg, end);
1104      case 3:
1105	return unw_decode_x3 (dp, code, arg, end);
1106      case 4:
1107	return unw_decode_x4 (dp, code, arg, end);
1108      default:
1109	UNW_DEC_BAD_CODE (code);
1110	break;
1111      }
1112  return dp;
1113}
1114
1115typedef const unsigned char *(*unw_decoder)
1116  (const unsigned char *, unsigned int, void *, const unsigned char *);
1117
1118static const unw_decoder unw_decode_table[2][8] =
1119  {
1120    /* prologue table: */
1121    {
1122      unw_decode_r1,		/* 0 */
1123      unw_decode_r1,
1124      unw_decode_r2,
1125      unw_decode_r3,
1126      unw_decode_p1,		/* 4 */
1127      unw_decode_p2_p5,
1128      unw_decode_p6,
1129      unw_decode_p7_p10
1130    },
1131    {
1132      unw_decode_r1,		/* 0 */
1133      unw_decode_r1,
1134      unw_decode_r2,
1135      unw_decode_r3,
1136      unw_decode_b1,		/* 4 */
1137      unw_decode_b1,
1138      unw_decode_b2,
1139      unw_decode_b3_x4
1140    }
1141  };
1142
1143/* Decode one descriptor and return address of next descriptor.  */
1144const unsigned char *
1145unw_decode (const unsigned char *dp, int inside_body,
1146	    void *ptr_inside_body, const unsigned char * end)
1147{
1148  unw_decoder decoder;
1149  unsigned char code;
1150
1151  if ((end - dp) < 1)
1152    {
1153      printf (_("\t<corrupt IA64 descriptor>\n"));
1154      return end;
1155    }
1156
1157  code = *dp++;
1158  decoder = unw_decode_table[inside_body][code >> 5];
1159  return (*decoder) (dp, code, ptr_inside_body, end);
1160}
1161