Back to index

cell-binutils  2.17cvs20070401
unwind-ia64.c
Go to the documentation of this file.
00001 /* unwind-ia64.c -- utility routines to dump IA-64 unwind info for readelf.
00002    Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
00003        Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
00004 
00005 This file is part of GNU Binutils.
00006 
00007 This program is free software; you can redistribute it and/or modify
00008 it under the terms of the GNU General Public License as published by
00009 the Free Software Foundation; either version 2, or (at your option)
00010 any later version.
00011 
00012 This program is distributed in the hope that it will be useful,
00013 but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with this program; if not, write to the Free Software
00019 Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00020 
00021 #include "unwind-ia64.h"
00022 #include <stdio.h>
00023 #include <string.h>
00024 
00025 #if __GNUC__ >= 2
00026 /* Define BFD64 here, even if our default architecture is 32 bit ELF
00027    as this will allow us to read in and parse 64bit and 32bit ELF files.
00028    Only do this if we believe that the compiler can support a 64 bit
00029    data type.  For now we only rely on GCC being able to do this.  */
00030 #define BFD64
00031 #endif
00032 #include "bfd.h"
00033 
00034 static bfd_vma unw_rlen = 0;
00035 
00036 static void unw_print_brmask (char *, unsigned int);
00037 static void unw_print_grmask (char *, unsigned int);
00038 static void unw_print_frmask (char *, unsigned int);
00039 static void unw_print_abreg (char *, unsigned int);
00040 static void unw_print_xyreg (char *, unsigned int, unsigned int);
00041 
00042 static void
00043 unw_print_brmask (char *cp, unsigned int mask)
00044 {
00045   int sep = 0;
00046   int i;
00047 
00048   for (i = 0; mask && (i < 5); ++i)
00049     {
00050       if (mask & 1)
00051        {
00052          if (sep)
00053            *cp++ = ',';
00054          *cp++ = 'b';
00055          *cp++ = i + 1 + '0';
00056          sep = 1;
00057        }
00058       mask >>= 1;
00059     }
00060   *cp = '\0';
00061 }
00062 
00063 static void
00064 unw_print_grmask (char *cp, unsigned int mask)
00065 {
00066   int sep = 0;
00067   int i;
00068 
00069   for (i = 0; i < 4; ++i)
00070     {
00071       if (mask & 1)
00072        {
00073          if (sep)
00074            *cp++ = ',';
00075          *cp++ = 'r';
00076          *cp++ = i + 4 + '0';
00077          sep = 1;
00078        }
00079       mask >>= 1;
00080     }
00081   *cp = '\0';
00082 }
00083 
00084 static void
00085 unw_print_frmask (char *cp, unsigned int mask)
00086 {
00087   int sep = 0;
00088   int i;
00089 
00090   for (i = 0; i < 20; ++i)
00091     {
00092       if (mask & 1)
00093        {
00094          if (sep)
00095            *cp++ = ',';
00096          *cp++ = 'f';
00097          if (i < 4)
00098            *cp++ = i + 2 + '0';
00099          else
00100            {
00101              *cp++ = (i + 2) / 10 + 1 + '0';
00102              *cp++ = (i + 2) % 10 + '0';
00103            }
00104          sep = 1;
00105        }
00106       mask >>= 1;
00107     }
00108   *cp = '\0';
00109 }
00110 
00111 static void
00112 unw_print_abreg (char *cp, unsigned int abreg)
00113 {
00114   static const char *special_reg[16] =
00115   {
00116     "pr", "psp", "@priunat", "rp", "ar.bsp", "ar.bspstore", "ar.rnat",
00117     "ar.unat", "ar.fpsr", "ar.pfs", "ar.lc",
00118     "Unknown11", "Unknown12", "Unknown13", "Unknown14", "Unknown15"
00119   };
00120 
00121   switch ((abreg >> 5) & 0x3)
00122     {
00123     case 0: /* gr */
00124       sprintf (cp, "r%u", (abreg & 0x1f));
00125       break;
00126 
00127     case 1: /* fr */
00128       sprintf (cp, "f%u", (abreg & 0x1f));
00129       break;
00130 
00131     case 2: /* br */
00132       sprintf (cp, "b%u", (abreg & 0x1f));
00133       break;
00134 
00135     case 3: /* special */
00136       strcpy (cp, special_reg[abreg & 0xf]);
00137       break;
00138     }
00139 }
00140 
00141 static void
00142 unw_print_xyreg (char *cp, unsigned int x, unsigned int ytreg)
00143 {
00144   switch ((x << 1) | ((ytreg >> 7) & 1))
00145     {
00146     case 0: /* gr */
00147       sprintf (cp, "r%u", (ytreg & 0x1f));
00148       break;
00149 
00150     case 1: /* fr */
00151       sprintf (cp, "f%u", (ytreg & 0x1f));
00152       break;
00153 
00154     case 2: /* br */
00155       sprintf (cp, "b%u", (ytreg & 0x1f));
00156       break;
00157     }
00158 }
00159 
00160 #define UNW_REG_BSP         "bsp"
00161 #define UNW_REG_BSPSTORE    "bspstore"
00162 #define UNW_REG_FPSR        "fpsr"
00163 #define UNW_REG_LC          "lc"
00164 #define UNW_REG_PFS         "pfs"
00165 #define UNW_REG_PR          "pr"
00166 #define UNW_REG_PSP         "psp"
00167 #define UNW_REG_RNAT        "rnat"
00168 #define UNW_REG_RP          "rp"
00169 #define UNW_REG_UNAT        "unat"
00170 
00171 typedef bfd_vma unw_word;
00172 
00173 #define UNW_DEC_BAD_CODE(code)                   \
00174     printf ("Unknown code 0x%02x\n", code)
00175 
00176 #define UNW_DEC_PROLOGUE(fmt, body, rlen, arg)                               \
00177   do                                                                  \
00178     {                                                                 \
00179       unw_rlen = rlen;                                                       \
00180       *(int *)arg = body;                                             \
00181       printf ("    %s:%s(rlen=%lu)\n",                                       \
00182              fmt, body ? "body" : "prologue", (unsigned long) rlen);         \
00183     }                                                                 \
00184   while (0)
00185 
00186 #define UNW_DEC_PROLOGUE_GR(fmt, rlen, mask, grsave, arg)                    \
00187   do                                                                  \
00188     {                                                                 \
00189       char regname[16], maskstr[64], *sep;                                   \
00190                                                                       \
00191       unw_rlen = rlen;                                                       \
00192       *(int *)arg = 0;                                                       \
00193                                                                       \
00194       maskstr[0] = '\0';                                              \
00195       sep = "";                                                              \
00196       if (mask & 0x8)                                                        \
00197        {                                                              \
00198          strcat (maskstr, "rp");                                      \
00199          sep = ",";                                                   \
00200        }                                                              \
00201       if (mask & 0x4)                                                        \
00202        {                                                              \
00203          strcat (maskstr, sep);                                       \
00204          strcat (maskstr, "ar.pfs");                                         \
00205          sep = ",";                                                   \
00206        }                                                              \
00207       if (mask & 0x2)                                                        \
00208        {                                                              \
00209          strcat (maskstr, sep);                                       \
00210          strcat (maskstr, "psp");                                     \
00211          sep = ",";                                                   \
00212        }                                                              \
00213       if (mask & 0x1)                                                        \
00214        {                                                              \
00215          strcat (maskstr, sep);                                       \
00216          strcat (maskstr, "pr");                                      \
00217        }                                                              \
00218       sprintf (regname, "r%u", grsave);                                      \
00219       printf ("    %s:prologue_gr(mask=[%s],grsave=%s,rlen=%lu)\n",          \
00220              fmt, maskstr, regname, (unsigned long) rlen);                   \
00221     }                                                                 \
00222   while (0)
00223 
00224 #define UNW_DEC_FR_MEM(fmt, frmask, arg)                \
00225   do                                                    \
00226     {                                                   \
00227       char frstr[200];                                         \
00228                                                         \
00229       unw_print_frmask (frstr, frmask);                        \
00230       printf ("\t%s:fr_mem(frmask=[%s])\n", fmt, frstr);       \
00231     }                                                   \
00232   while (0)
00233 
00234 #define UNW_DEC_GR_MEM(fmt, grmask, arg)                \
00235   do                                                    \
00236     {                                                   \
00237       char grstr[200];                                         \
00238                                                         \
00239       unw_print_grmask (grstr, grmask);                        \
00240       printf ("\t%s:gr_mem(grmask=[%s])\n", fmt, grstr);       \
00241     }                                                   \
00242   while (0)
00243 
00244 #define UNW_DEC_FRGR_MEM(fmt, grmask, frmask, arg)                           \
00245   do                                                                  \
00246     {                                                                 \
00247       char frstr[200], grstr[20];                                     \
00248                                                                       \
00249       unw_print_grmask (grstr, grmask);                                      \
00250       unw_print_frmask (frstr, frmask);                                      \
00251       printf ("\t%s:frgr_mem(grmask=[%s],frmask=[%s])\n", fmt, grstr, frstr);       \
00252     }                                                                 \
00253   while (0)
00254 
00255 #define UNW_DEC_BR_MEM(fmt, brmask, arg)                       \
00256   do                                                           \
00257     {                                                          \
00258       char brstr[20];                                                 \
00259                                                                \
00260       unw_print_brmask (brstr, brmask);                               \
00261       printf ("\t%s:br_mem(brmask=[%s])\n", fmt, brstr);              \
00262     }                                                          \
00263   while (0)
00264 
00265 #define UNW_DEC_BR_GR(fmt, brmask, gr, arg)                           \
00266   do                                                           \
00267     {                                                          \
00268       char brstr[20];                                                 \
00269                                                                \
00270       unw_print_brmask (brstr, brmask);                               \
00271       printf ("\t%s:br_gr(brmask=[%s],gr=r%u)\n", fmt, brstr, gr);    \
00272     }                                                          \
00273   while (0)
00274 
00275 #define UNW_DEC_REG_GR(fmt, src, dst, arg)              \
00276   printf ("\t%s:%s_gr(reg=r%u)\n", fmt, src, dst)
00277 
00278 #define UNW_DEC_RP_BR(fmt, dst, arg)             \
00279   printf ("\t%s:rp_br(reg=b%u)\n", fmt, dst)
00280 
00281 #define UNW_DEC_REG_WHEN(fmt, reg, t, arg)                            \
00282   printf ("\t%s:%s_when(t=%lu)\n", fmt, reg, (unsigned long) t)
00283 
00284 #define UNW_DEC_REG_SPREL(fmt, reg, spoff, arg)         \
00285   printf ("\t%s:%s_sprel(spoff=0x%lx)\n",        \
00286          fmt, reg, 4*(unsigned long)spoff)
00287 
00288 #define UNW_DEC_REG_PSPREL(fmt, reg, pspoff, arg)              \
00289   printf ("\t%s:%s_psprel(pspoff=0x10-0x%lx)\n",        \
00290          fmt, reg, 4*(unsigned long)pspoff)
00291 
00292 #define UNW_DEC_GR_GR(fmt, grmask, gr, arg)                           \
00293   do                                                           \
00294     {                                                          \
00295       char grstr[20];                                                 \
00296                                                                \
00297       unw_print_grmask (grstr, grmask);                               \
00298       printf ("\t%s:gr_gr(grmask=[%s],r%u)\n", fmt, grstr, gr);              \
00299     }                                                          \
00300   while (0)
00301 
00302 #define UNW_DEC_ABI(fmt, abi, context, arg)                    \
00303   do                                                    \
00304     {                                                   \
00305       static const char *abiname[] =                           \
00306       {                                                        \
00307        "@svr4", "@hpux", "@nt"                                 \
00308       };                                                \
00309       char buf[20];                                     \
00310       const char *abistr = buf;                                \
00311                                                         \
00312       if (abi < 3)                                      \
00313        abistr = abiname[abi];                                  \
00314       else                                              \
00315        sprintf (buf, "0x%x", abi);                      \
00316       printf ("\t%s:unwabi(abi=%s,context=0x%02x)\n",          \
00317              fmt, abistr, context);                            \
00318     }                                                   \
00319   while (0)
00320 
00321 #define UNW_DEC_PRIUNAT_GR(fmt, r, arg)          \
00322   printf ("\t%s:priunat_gr(reg=r%u)\n", fmt, r)
00323 
00324 #define UNW_DEC_PRIUNAT_WHEN_GR(fmt, t, arg)                          \
00325   printf ("\t%s:priunat_when_gr(t=%lu)\n", fmt, (unsigned long) t)
00326 
00327 #define UNW_DEC_PRIUNAT_WHEN_MEM(fmt, t, arg)                         \
00328   printf ("\t%s:priunat_when_mem(t=%lu)\n", fmt, (unsigned long) t)
00329 
00330 #define UNW_DEC_PRIUNAT_PSPREL(fmt, pspoff, arg)        \
00331   printf ("\t%s:priunat_psprel(pspoff=0x10-0x%lx)\n",          \
00332          fmt, 4*(unsigned long)pspoff)
00333 
00334 #define UNW_DEC_PRIUNAT_SPREL(fmt, spoff, arg)          \
00335   printf ("\t%s:priunat_sprel(spoff=0x%lx)\n",          \
00336          fmt, 4*(unsigned long)spoff)
00337 
00338 #define UNW_DEC_MEM_STACK_F(fmt, t, size, arg)          \
00339   printf ("\t%s:mem_stack_f(t=%lu,size=%lu)\n",         \
00340          fmt, (unsigned long) t, 16*(unsigned long)size)
00341 
00342 #define UNW_DEC_MEM_STACK_V(fmt, t, arg)                       \
00343   printf ("\t%s:mem_stack_v(t=%lu)\n", fmt, (unsigned long) t)
00344 
00345 #define UNW_DEC_SPILL_BASE(fmt, pspoff, arg)                   \
00346   printf ("\t%s:spill_base(pspoff=0x10-0x%lx)\n",              \
00347          fmt, 4*(unsigned long)pspoff)
00348 
00349 #define UNW_DEC_SPILL_MASK(fmt, dp, arg)                              \
00350   do                                                                  \
00351     {                                                                 \
00352       static const char *spill_type = "-frb";                                \
00353       unsigned const char *imaskp = dp;                               \
00354       unsigned char mask = 0;                                                \
00355       bfd_vma insn = 0;                                                      \
00356                                                                       \
00357       printf ("\t%s:spill_mask(imask=[", fmt);                               \
00358       for (insn = 0; insn < unw_rlen; ++insn)                                \
00359        {                                                              \
00360          if ((insn % 4) == 0)                                                \
00361            mask = *imaskp++;                                                 \
00362          if (insn > 0 && (insn % 3) == 0)                             \
00363            putchar (',');                                             \
00364          putchar (spill_type[(mask >> (2 * (3 - (insn & 0x3)))) & 0x3]);     \
00365        }                                                              \
00366       printf ("])\n");                                                       \
00367       dp = imaskp;                                                    \
00368     }                                                                 \
00369   while (0)
00370 
00371 #define UNW_DEC_SPILL_SPREL(fmt, t, abreg, spoff, arg)                       \
00372   do                                                                  \
00373     {                                                                 \
00374       char regname[20];                                                      \
00375                                                                       \
00376       unw_print_abreg (regname, abreg);                                      \
00377       printf ("\t%s:spill_sprel(reg=%s,t=%lu,spoff=0x%lx)\n",                \
00378              fmt, regname, (unsigned long) t, 4*(unsigned long)off);         \
00379     }                                                                 \
00380   while (0)
00381 
00382 #define UNW_DEC_SPILL_PSPREL(fmt, t, abreg, pspoff, arg)                     \
00383   do                                                                  \
00384     {                                                                 \
00385       char regname[20];                                                      \
00386                                                                       \
00387       unw_print_abreg (regname, abreg);                                      \
00388       printf ("\t%s:spill_psprel(reg=%s,t=%lu,pspoff=0x10-0x%lx)\n",         \
00389              fmt, regname, (unsigned long) t, 4*(unsigned long)pspoff);      \
00390     }                                                                 \
00391   while (0)
00392 
00393 #define UNW_DEC_RESTORE(fmt, t, abreg, arg)                    \
00394   do                                                    \
00395     {                                                   \
00396       char regname[20];                                        \
00397                                                         \
00398       unw_print_abreg (regname, abreg);                        \
00399       printf ("\t%s:restore(t=%lu,reg=%s)\n",                  \
00400              fmt, (unsigned long) t, regname);                 \
00401     }                                                   \
00402   while (0)
00403 
00404 #define UNW_DEC_SPILL_REG(fmt, t, abreg, x, ytreg, arg)        \
00405   do                                                    \
00406     {                                                   \
00407       char abregname[20], tregname[20];                        \
00408                                                         \
00409       unw_print_abreg (abregname, abreg);               \
00410       unw_print_xyreg (tregname, x, ytreg);                    \
00411       printf ("\t%s:spill_reg(t=%lu,reg=%s,treg=%s)\n",        \
00412              fmt, (unsigned long) t, abregname, tregname);     \
00413     }                                                   \
00414   while (0)
00415 
00416 #define UNW_DEC_SPILL_SPREL_P(fmt, qp, t, abreg, spoff, arg)                     \
00417   do                                                                      \
00418     {                                                                     \
00419       char regname[20];                                                          \
00420                                                                           \
00421       unw_print_abreg (regname, abreg);                                          \
00422       printf ("\t%s:spill_sprel_p(qp=p%u,t=%lu,reg=%s,spoff=0x%lx)\n",                  \
00423              fmt, qp, (unsigned long) t, regname, 4 * (unsigned long)spoff);     \
00424     }                                                                     \
00425   while (0)
00426 
00427 #define UNW_DEC_SPILL_PSPREL_P(fmt, qp, t, abreg, pspoff, arg)        \
00428   do                                                           \
00429     {                                                          \
00430       char regname[20];                                               \
00431                                                                \
00432       unw_print_abreg (regname, abreg);                               \
00433       printf ("\t%s:spill_psprel_p(qp=p%u,t=%lu,reg=%s,pspoff=0x10-0x%lx)\n",\
00434              fmt, qp, (unsigned long) t, regname, 4*(unsigned long)pspoff);\
00435     }                                                          \
00436   while (0)
00437 
00438 #define UNW_DEC_RESTORE_P(fmt, qp, t, abreg, arg)                     \
00439   do                                                           \
00440     {                                                          \
00441       char regname[20];                                               \
00442                                                                \
00443       unw_print_abreg (regname, abreg);                               \
00444       printf ("\t%s:restore_p(qp=p%u,t=%lu,reg=%s)\n",                \
00445              fmt, qp, (unsigned long) t, regname);                    \
00446     }                                                          \
00447   while (0)
00448 
00449 #define UNW_DEC_SPILL_REG_P(fmt, qp, t, abreg, x, ytreg, arg)         \
00450   do                                                           \
00451     {                                                          \
00452       char regname[20], tregname[20];                                 \
00453                                                                \
00454       unw_print_abreg (regname, abreg);                               \
00455       unw_print_xyreg (tregname, x, ytreg);                           \
00456       printf ("\t%s:spill_reg_p(qp=p%u,t=%lu,reg=%s,treg=%s)\n",      \
00457              fmt, qp, (unsigned long) t, regname, tregname);          \
00458     }                                                          \
00459   while (0)
00460 
00461 #define UNW_DEC_LABEL_STATE(fmt, label, arg)                          \
00462   printf ("\t%s:label_state(label=%lu)\n", fmt, (unsigned long) label)
00463 
00464 #define UNW_DEC_COPY_STATE(fmt, label, arg)                           \
00465   printf ("\t%s:copy_state(label=%lu)\n", fmt, (unsigned long) label)
00466 
00467 #define UNW_DEC_EPILOGUE(fmt, t, ecount, arg)           \
00468   printf ("\t%s:epilogue(t=%lu,ecount=%lu)\n",          \
00469          fmt, (unsigned long) t, (unsigned long) ecount)
00470 
00471 /*
00472  * Generic IA-64 unwind info decoder.
00473  *
00474  * This file is used both by the Linux kernel and objdump.  Please
00475  * keep the two copies of this file in sync (modulo differences in the
00476  * prototypes...).
00477  *
00478  * You need to customize the decoder by defining the following
00479  * macros/constants before including this file:
00480  *
00481  *  Types:
00482  *     unw_word      Unsigned integer type with at least 64 bits
00483  *
00484  *  Register names:
00485  *     UNW_REG_BSP
00486  *     UNW_REG_BSPSTORE
00487  *     UNW_REG_FPSR
00488  *     UNW_REG_LC
00489  *     UNW_REG_PFS
00490  *     UNW_REG_PR
00491  *     UNW_REG_RNAT
00492  *     UNW_REG_PSP
00493  *     UNW_REG_RP
00494  *     UNW_REG_UNAT
00495  *
00496  *  Decoder action macros:
00497  *     UNW_DEC_BAD_CODE(code)
00498  *     UNW_DEC_ABI(fmt,abi,context,arg)
00499  *     UNW_DEC_BR_GR(fmt,brmask,gr,arg)
00500  *     UNW_DEC_BR_MEM(fmt,brmask,arg)
00501  *     UNW_DEC_COPY_STATE(fmt,label,arg)
00502  *     UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
00503  *     UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
00504  *     UNW_DEC_FR_MEM(fmt,frmask,arg)
00505  *     UNW_DEC_GR_GR(fmt,grmask,gr,arg)
00506  *     UNW_DEC_GR_MEM(fmt,grmask,arg)
00507  *     UNW_DEC_LABEL_STATE(fmt,label,arg)
00508  *     UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
00509  *     UNW_DEC_MEM_STACK_V(fmt,t,arg)
00510  *     UNW_DEC_PRIUNAT_GR(fmt,r,arg)
00511  *     UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
00512  *     UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
00513  *     UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
00514  *     UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
00515  *     UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
00516  *     UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
00517  *     UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
00518  *     UNW_DEC_REG_REG(fmt,src,dst,arg)
00519  *     UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
00520  *     UNW_DEC_REG_WHEN(fmt,reg,t,arg)
00521  *     UNW_DEC_RESTORE(fmt,t,abreg,arg)
00522  *     UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
00523  *     UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
00524  *     UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
00525  *     UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
00526  *     UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
00527  *     UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
00528  *     UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
00529  *     UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
00530  *     UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
00531  */
00532 
00533 static unw_word unw_decode_uleb128 (const unsigned char **);
00534 static const unsigned char *unw_decode_x1
00535   (const unsigned char *, unsigned int, void *);
00536 static const unsigned char *unw_decode_x2
00537   (const unsigned char *, unsigned int, void *);
00538 static const unsigned char *unw_decode_x3
00539   (const unsigned char *, unsigned int, void *);
00540 static const unsigned char *unw_decode_x4
00541   (const unsigned char *, unsigned int, void *);
00542 static const unsigned char *unw_decode_r1
00543   (const unsigned char *, unsigned int, void *);
00544 static const unsigned char *unw_decode_r2
00545   (const unsigned char *, unsigned int, void *);
00546 static const unsigned char *unw_decode_r3
00547   (const unsigned char *, unsigned int, void *);
00548 static const unsigned char *unw_decode_p1
00549   (const unsigned char *, unsigned int, void *);
00550 static const unsigned char *unw_decode_p2_p5
00551   (const unsigned char *, unsigned int, void *);
00552 static const unsigned char *unw_decode_p6
00553   (const unsigned char *, unsigned int, void *);
00554 static const unsigned char *unw_decode_p7_p10
00555   (const unsigned char *, unsigned int, void *);
00556 static const unsigned char *unw_decode_b1
00557   (const unsigned char *, unsigned int, void *);
00558 static const unsigned char *unw_decode_b2
00559   (const unsigned char *, unsigned int, void *);
00560 static const unsigned char *unw_decode_b3_x4
00561   (const unsigned char *, unsigned int, void *);
00562 
00563 static unw_word
00564 unw_decode_uleb128 (const unsigned char **dpp)
00565 {
00566   unsigned shift = 0;
00567   unw_word byte, result = 0;
00568   const unsigned char *bp = *dpp;
00569 
00570   while (1)
00571     {
00572       byte = *bp++;
00573       result |= (byte & 0x7f) << shift;
00574 
00575       if ((byte & 0x80) == 0)
00576        break;
00577 
00578       shift += 7;
00579     }
00580 
00581   *dpp = bp;
00582 
00583   return result;
00584 }
00585 
00586 static const unsigned char *
00587 unw_decode_x1 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
00588               void *arg ATTRIBUTE_UNUSED)
00589 {
00590   unsigned char byte1, abreg;
00591   unw_word t, off;
00592 
00593   byte1 = *dp++;
00594   t = unw_decode_uleb128 (&dp);
00595   off = unw_decode_uleb128 (&dp);
00596   abreg = (byte1 & 0x7f);
00597   if (byte1 & 0x80)
00598     UNW_DEC_SPILL_SPREL ("X1", t, abreg, off, arg);
00599   else
00600     UNW_DEC_SPILL_PSPREL ("X1", t, abreg, off, arg);
00601   return dp;
00602 }
00603 
00604 static const unsigned char *
00605 unw_decode_x2 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
00606               void *arg ATTRIBUTE_UNUSED)
00607 {
00608   unsigned char byte1, byte2, abreg, x, ytreg;
00609   unw_word t;
00610 
00611   byte1 = *dp++;
00612   byte2 = *dp++;
00613   t = unw_decode_uleb128 (&dp);
00614   abreg = (byte1 & 0x7f);
00615   ytreg = byte2;
00616   x = (byte1 >> 7) & 1;
00617   if ((byte1 & 0x80) == 0 && ytreg == 0)
00618     UNW_DEC_RESTORE ("X2", t, abreg, arg);
00619   else
00620     UNW_DEC_SPILL_REG ("X2", t, abreg, x, ytreg, arg);
00621   return dp;
00622 }
00623 
00624 static const unsigned char *
00625 unw_decode_x3 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
00626               void *arg ATTRIBUTE_UNUSED)
00627 {
00628   unsigned char byte1, byte2, abreg, qp;
00629   unw_word t, off;
00630 
00631   byte1 = *dp++;
00632   byte2 = *dp++;
00633   t = unw_decode_uleb128 (&dp);
00634   off = unw_decode_uleb128 (&dp);
00635 
00636   qp = (byte1 & 0x3f);
00637   abreg = (byte2 & 0x7f);
00638 
00639   if (byte1 & 0x80)
00640     UNW_DEC_SPILL_SPREL_P ("X3", qp, t, abreg, off, arg);
00641   else
00642     UNW_DEC_SPILL_PSPREL_P ("X3", qp, t, abreg, off, arg);
00643   return dp;
00644 }
00645 
00646 static const unsigned char *
00647 unw_decode_x4 (const unsigned char *dp, unsigned int code ATTRIBUTE_UNUSED,
00648               void *arg ATTRIBUTE_UNUSED)
00649 {
00650   unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
00651   unw_word t;
00652 
00653   byte1 = *dp++;
00654   byte2 = *dp++;
00655   byte3 = *dp++;
00656   t = unw_decode_uleb128 (&dp);
00657 
00658   qp = (byte1 & 0x3f);
00659   abreg = (byte2 & 0x7f);
00660   x = (byte2 >> 7) & 1;
00661   ytreg = byte3;
00662 
00663   if ((byte2 & 0x80) == 0 && byte3 == 0)
00664     UNW_DEC_RESTORE_P ("X4", qp, t, abreg, arg);
00665   else
00666     UNW_DEC_SPILL_REG_P ("X4", qp, t, abreg, x, ytreg, arg);
00667   return dp;
00668 }
00669 
00670 static const unsigned char *
00671 unw_decode_r1 (const unsigned char *dp, unsigned int code, void *arg)
00672 {
00673   int body = (code & 0x20) != 0;
00674   unw_word rlen;
00675 
00676   rlen = (code & 0x1f);
00677   UNW_DEC_PROLOGUE ("R1", body, rlen, arg);
00678   return dp;
00679 }
00680 
00681 static const unsigned char *
00682 unw_decode_r2 (const unsigned char *dp, unsigned int code, void *arg)
00683 {
00684   unsigned char byte1, mask, grsave;
00685   unw_word rlen;
00686 
00687   byte1 = *dp++;
00688 
00689   mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
00690   grsave = (byte1 & 0x7f);
00691   rlen = unw_decode_uleb128 (& dp);
00692   UNW_DEC_PROLOGUE_GR ("R2", rlen, mask, grsave, arg);
00693   return dp;
00694 }
00695 
00696 static const unsigned char *
00697 unw_decode_r3 (const unsigned char *dp, unsigned int code, void *arg)
00698 {
00699   unw_word rlen;
00700 
00701   rlen = unw_decode_uleb128 (& dp);
00702   UNW_DEC_PROLOGUE ("R3", ((code & 0x3) == 1), rlen, arg);
00703   return dp;
00704 }
00705 
00706 static const unsigned char *
00707 unw_decode_p1 (const unsigned char *dp, unsigned int code,
00708               void *arg ATTRIBUTE_UNUSED)
00709 {
00710   unsigned char brmask = (code & 0x1f);
00711 
00712   UNW_DEC_BR_MEM ("P1", brmask, arg);
00713   return dp;
00714 }
00715 
00716 static const unsigned char *
00717 unw_decode_p2_p5 (const unsigned char *dp, unsigned int code,
00718                 void *arg ATTRIBUTE_UNUSED)
00719 {
00720   if ((code & 0x10) == 0)
00721     {
00722       unsigned char byte1 = *dp++;
00723 
00724       UNW_DEC_BR_GR ("P2", ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
00725                    (byte1 & 0x7f), arg);
00726     }
00727   else if ((code & 0x08) == 0)
00728     {
00729       unsigned char byte1 = *dp++, r, dst;
00730 
00731       r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
00732       dst = (byte1 & 0x7f);
00733       switch (r)
00734        {
00735        case 0:
00736          UNW_DEC_REG_GR ("P3", UNW_REG_PSP, dst, arg);
00737          break;
00738        case 1:
00739          UNW_DEC_REG_GR ("P3", UNW_REG_RP, dst, arg);
00740          break;
00741        case 2:
00742          UNW_DEC_REG_GR ("P3", UNW_REG_PFS, dst, arg);
00743          break;
00744        case 3:
00745          UNW_DEC_REG_GR ("P3", UNW_REG_PR, dst, arg);
00746          break;
00747        case 4:
00748          UNW_DEC_REG_GR ("P3", UNW_REG_UNAT, dst, arg);
00749          break;
00750        case 5:
00751          UNW_DEC_REG_GR ("P3", UNW_REG_LC, dst, arg);
00752          break;
00753        case 6:
00754          UNW_DEC_RP_BR ("P3", dst, arg);
00755          break;
00756        case 7:
00757          UNW_DEC_REG_GR ("P3", UNW_REG_RNAT, dst, arg);
00758          break;
00759        case 8:
00760          UNW_DEC_REG_GR ("P3", UNW_REG_BSP, dst, arg);
00761          break;
00762        case 9:
00763          UNW_DEC_REG_GR ("P3", UNW_REG_BSPSTORE, dst, arg);
00764          break;
00765        case 10:
00766          UNW_DEC_REG_GR ("P3", UNW_REG_FPSR, dst, arg);
00767          break;
00768        case 11:
00769          UNW_DEC_PRIUNAT_GR ("P3", dst, arg);
00770          break;
00771        default:
00772          UNW_DEC_BAD_CODE (r);
00773          break;
00774        }
00775     }
00776   else if ((code & 0x7) == 0)
00777     UNW_DEC_SPILL_MASK ("P4", dp, arg);
00778   else if ((code & 0x7) == 1)
00779     {
00780       unw_word grmask, frmask, byte1, byte2, byte3;
00781 
00782       byte1 = *dp++;
00783       byte2 = *dp++;
00784       byte3 = *dp++;
00785       grmask = ((byte1 >> 4) & 0xf);
00786       frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
00787       UNW_DEC_FRGR_MEM ("P5", grmask, frmask, arg);
00788     }
00789   else
00790     UNW_DEC_BAD_CODE (code);
00791 
00792   return dp;
00793 }
00794 
00795 static const unsigned char *
00796 unw_decode_p6 (const unsigned char *dp, unsigned int code,
00797               void *arg ATTRIBUTE_UNUSED)
00798 {
00799   int gregs = (code & 0x10) != 0;
00800   unsigned char mask = (code & 0x0f);
00801 
00802   if (gregs)
00803     UNW_DEC_GR_MEM ("P6", mask, arg);
00804   else
00805     UNW_DEC_FR_MEM ("P6", mask, arg);
00806   return dp;
00807 }
00808 
00809 static const unsigned char *
00810 unw_decode_p7_p10 (const unsigned char *dp, unsigned int code, void *arg)
00811 {
00812   unsigned char r, byte1, byte2;
00813   unw_word t, size;
00814 
00815   if ((code & 0x10) == 0)
00816     {
00817       r = (code & 0xf);
00818       t = unw_decode_uleb128 (&dp);
00819       switch (r)
00820        {
00821        case 0:
00822          size = unw_decode_uleb128 (&dp);
00823          UNW_DEC_MEM_STACK_F ("P7", t, size, arg);
00824          break;
00825 
00826        case 1:
00827          UNW_DEC_MEM_STACK_V ("P7", t, arg);
00828          break;
00829        case 2:
00830          UNW_DEC_SPILL_BASE ("P7", t, arg);
00831          break;
00832        case 3:
00833          UNW_DEC_REG_SPREL ("P7", UNW_REG_PSP, t, arg);
00834          break;
00835        case 4:
00836          UNW_DEC_REG_WHEN ("P7", UNW_REG_RP, t, arg);
00837          break;
00838        case 5:
00839          UNW_DEC_REG_PSPREL ("P7", UNW_REG_RP, t, arg);
00840          break;
00841        case 6:
00842          UNW_DEC_REG_WHEN ("P7", UNW_REG_PFS, t, arg);
00843          break;
00844        case 7:
00845          UNW_DEC_REG_PSPREL ("P7", UNW_REG_PFS, t, arg);
00846          break;
00847        case 8:
00848          UNW_DEC_REG_WHEN ("P7", UNW_REG_PR, t, arg);
00849          break;
00850        case 9:
00851          UNW_DEC_REG_PSPREL ("P7", UNW_REG_PR, t, arg);
00852          break;
00853        case 10:
00854          UNW_DEC_REG_WHEN ("P7", UNW_REG_LC, t, arg);
00855          break;
00856        case 11:
00857          UNW_DEC_REG_PSPREL ("P7", UNW_REG_LC, t, arg);
00858          break;
00859        case 12:
00860          UNW_DEC_REG_WHEN ("P7", UNW_REG_UNAT, t, arg);
00861          break;
00862        case 13:
00863          UNW_DEC_REG_PSPREL ("P7", UNW_REG_UNAT, t, arg);
00864          break;
00865        case 14:
00866          UNW_DEC_REG_WHEN ("P7", UNW_REG_FPSR, t, arg);
00867          break;
00868        case 15:
00869          UNW_DEC_REG_PSPREL ("P7", UNW_REG_FPSR, t, arg);
00870          break;
00871        default:
00872          UNW_DEC_BAD_CODE (r);
00873          break;
00874        }
00875     }
00876   else
00877     {
00878       switch (code & 0xf)
00879        {
00880        case 0x0:            /* p8 */
00881          {
00882            r = *dp++;
00883            t = unw_decode_uleb128 (&dp);
00884            switch (r)
00885              {
00886              case 1:
00887               UNW_DEC_REG_SPREL ("P8", UNW_REG_RP, t, arg);
00888               break;
00889              case 2:
00890               UNW_DEC_REG_SPREL ("P8", UNW_REG_PFS, t, arg);
00891               break;
00892              case 3:
00893               UNW_DEC_REG_SPREL ("P8", UNW_REG_PR, t, arg);
00894               break;
00895              case 4:
00896               UNW_DEC_REG_SPREL ("P8", UNW_REG_LC, t, arg);
00897               break;
00898              case 5:
00899               UNW_DEC_REG_SPREL ("P8", UNW_REG_UNAT, t, arg);
00900               break;
00901              case 6:
00902               UNW_DEC_REG_SPREL ("P8", UNW_REG_FPSR, t, arg);
00903               break;
00904              case 7:
00905               UNW_DEC_REG_WHEN ("P8", UNW_REG_BSP, t, arg);
00906               break;
00907              case 8:
00908               UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSP, t, arg);
00909               break;
00910              case 9:
00911               UNW_DEC_REG_SPREL ("P8", UNW_REG_BSP, t, arg);
00912               break;
00913              case 10:
00914               UNW_DEC_REG_WHEN ("P8", UNW_REG_BSPSTORE, t, arg);
00915               break;
00916              case 11:
00917               UNW_DEC_REG_PSPREL ("P8", UNW_REG_BSPSTORE, t, arg);
00918               break;
00919              case 12:
00920               UNW_DEC_REG_SPREL ("P8", UNW_REG_BSPSTORE, t, arg);
00921               break;
00922              case 13:
00923               UNW_DEC_REG_WHEN ("P8", UNW_REG_RNAT, t, arg);
00924               break;
00925              case 14:
00926               UNW_DEC_REG_PSPREL ("P8", UNW_REG_RNAT, t, arg);
00927               break;
00928              case 15:
00929               UNW_DEC_REG_SPREL ("P8", UNW_REG_RNAT, t, arg);
00930               break;
00931              case 16:
00932               UNW_DEC_PRIUNAT_WHEN_GR ("P8", t, arg);
00933               break;
00934              case 17:
00935               UNW_DEC_PRIUNAT_PSPREL ("P8", t, arg);
00936               break;
00937              case 18:
00938               UNW_DEC_PRIUNAT_SPREL ("P8", t, arg);
00939               break;
00940              case 19:
00941               UNW_DEC_PRIUNAT_WHEN_MEM ("P8", t, arg);
00942               break;
00943              default:
00944               UNW_DEC_BAD_CODE (r);
00945               break;
00946              }
00947          }
00948          break;
00949 
00950        case 0x1:
00951          byte1 = *dp++;
00952          byte2 = *dp++;
00953          UNW_DEC_GR_GR ("P9", (byte1 & 0xf), (byte2 & 0x7f), arg);
00954          break;
00955 
00956        case 0xf:            /* p10 */
00957          byte1 = *dp++;
00958          byte2 = *dp++;
00959          UNW_DEC_ABI ("P10", byte1, byte2, arg);
00960          break;
00961 
00962        case 0x9:
00963          return unw_decode_x1 (dp, code, arg);
00964 
00965        case 0xa:
00966          return unw_decode_x2 (dp, code, arg);
00967 
00968        case 0xb:
00969          return unw_decode_x3 (dp, code, arg);
00970 
00971        case 0xc:
00972          return unw_decode_x4 (dp, code, arg);
00973 
00974        default:
00975          UNW_DEC_BAD_CODE (code);
00976          break;
00977        }
00978     }
00979   return dp;
00980 }
00981 
00982 static const unsigned char *
00983 unw_decode_b1 (const unsigned char *dp, unsigned int code,
00984               void *arg ATTRIBUTE_UNUSED)
00985 {
00986   unw_word label = (code & 0x1f);
00987 
00988   if ((code & 0x20) != 0)
00989     UNW_DEC_COPY_STATE ("B1", label, arg);
00990   else
00991     UNW_DEC_LABEL_STATE ("B1", label, arg);
00992   return dp;
00993 }
00994 
00995 static const unsigned char *
00996 unw_decode_b2 (const unsigned char *dp, unsigned int code,
00997               void *arg ATTRIBUTE_UNUSED)
00998 {
00999   unw_word t;
01000 
01001   t = unw_decode_uleb128 (& dp);
01002   UNW_DEC_EPILOGUE ("B2", t, (code & 0x1f), arg);
01003   return dp;
01004 }
01005 
01006 static const unsigned char *
01007 unw_decode_b3_x4 (const unsigned char *dp, unsigned int code, void *arg)
01008 {
01009   unw_word t, ecount, label;
01010 
01011   if ((code & 0x10) == 0)
01012     {
01013       t = unw_decode_uleb128 (&dp);
01014       ecount = unw_decode_uleb128 (&dp);
01015       UNW_DEC_EPILOGUE ("B3", t, ecount, arg);
01016     }
01017   else if ((code & 0x07) == 0)
01018     {
01019       label = unw_decode_uleb128 (&dp);
01020       if ((code & 0x08) != 0)
01021        UNW_DEC_COPY_STATE ("B4", label, arg);
01022       else
01023        UNW_DEC_LABEL_STATE ("B4", label, arg);
01024     }
01025   else
01026     switch (code & 0x7)
01027       {
01028       case 1:
01029        return unw_decode_x1 (dp, code, arg);
01030       case 2:
01031        return unw_decode_x2 (dp, code, arg);
01032       case 3:
01033        return unw_decode_x3 (dp, code, arg);
01034       case 4:
01035        return unw_decode_x4 (dp, code, arg);
01036       default:
01037        UNW_DEC_BAD_CODE (code);
01038        break;
01039       }
01040   return dp;
01041 }
01042 
01043 typedef const unsigned char *(*unw_decoder)
01044      (const unsigned char *, unsigned int, void *);
01045 
01046 static unw_decoder unw_decode_table[2][8] =
01047   {
01048     /* prologue table: */
01049     {
01050       unw_decode_r1,        /* 0 */
01051       unw_decode_r1,
01052       unw_decode_r2,
01053       unw_decode_r3,
01054       unw_decode_p1,        /* 4 */
01055       unw_decode_p2_p5,
01056       unw_decode_p6,
01057       unw_decode_p7_p10
01058     },
01059     {
01060       unw_decode_r1,        /* 0 */
01061       unw_decode_r1,
01062       unw_decode_r2,
01063       unw_decode_r3,
01064       unw_decode_b1,        /* 4 */
01065       unw_decode_b1,
01066       unw_decode_b2,
01067       unw_decode_b3_x4
01068     }
01069   };
01070 
01071 /* Decode one descriptor and return address of next descriptor.  */
01072 const unsigned char *
01073 unw_decode (const unsigned char *dp, int inside_body,
01074            void *ptr_inside_body)
01075 {
01076   unw_decoder decoder;
01077   unsigned char code;
01078 
01079   code = *dp++;
01080   decoder = unw_decode_table[inside_body][code >> 5];
01081   return (*decoder) (dp, code, ptr_inside_body);
01082 }