Home | History | Annotate | Download | only in ia64
      1 /* libunwind - a platform-independent unwind library
      2    Copyright (C) 2001-2002 Hewlett-Packard Co
      3 	Contributed by David Mosberger-Tang <davidm (at) hpl.hp.com>
      4 
      5 This file is part of libunwind.
      6 
      7 Permission is hereby granted, free of charge, to any person obtaining
      8 a copy of this software and associated documentation files (the
      9 "Software"), to deal in the Software without restriction, including
     10 without limitation the rights to use, copy, modify, merge, publish,
     11 distribute, sublicense, and/or sell copies of the Software, and to
     12 permit persons to whom the Software is furnished to do so, subject to
     13 the following conditions:
     14 
     15 The above copyright notice and this permission notice shall be
     16 included in all copies or substantial portions of the Software.
     17 
     18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
     25 
     26 /*
     27  * Generic IA-64 unwind info decoder.
     28  *
     29  * This file is used both by the Linux kernel and objdump.  Please keep
     30  * the two copies of this file in sync.
     31  *
     32  * You need to customize the decoder by defining the following
     33  * macros/constants before including this file:
     34  *
     35  *  Types:
     36  *	unw_word	Unsigned integer type with at least 64 bits
     37  *
     38  *  Register names:
     39  *	UNW_REG_BSP
     40  *	UNW_REG_BSPSTORE
     41  *	UNW_REG_FPSR
     42  *	UNW_REG_LC
     43  *	UNW_REG_PFS
     44  *	UNW_REG_PR
     45  *	UNW_REG_RNAT
     46  *	UNW_REG_PSP
     47  *	UNW_REG_RP
     48  *	UNW_REG_UNAT
     49  *
     50  *  Decoder action macros:
     51  *	UNW_DEC_BAD_CODE(code)
     52  *	UNW_DEC_ABI(fmt,abi,context,arg)
     53  *	UNW_DEC_BR_GR(fmt,brmask,gr,arg)
     54  *	UNW_DEC_BR_MEM(fmt,brmask,arg)
     55  *	UNW_DEC_COPY_STATE(fmt,label,arg)
     56  *	UNW_DEC_EPILOGUE(fmt,t,ecount,arg)
     57  *	UNW_DEC_FRGR_MEM(fmt,grmask,frmask,arg)
     58  *	UNW_DEC_FR_MEM(fmt,frmask,arg)
     59  *	UNW_DEC_GR_GR(fmt,grmask,gr,arg)
     60  *	UNW_DEC_GR_MEM(fmt,grmask,arg)
     61  *	UNW_DEC_LABEL_STATE(fmt,label,arg)
     62  *	UNW_DEC_MEM_STACK_F(fmt,t,size,arg)
     63  *	UNW_DEC_MEM_STACK_V(fmt,t,arg)
     64  *	UNW_DEC_PRIUNAT_GR(fmt,r,arg)
     65  *	UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg)
     66  *	UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg)
     67  *	UNW_DEC_PRIUNAT_WHEN_PSPREL(fmt,pspoff,arg)
     68  *	UNW_DEC_PRIUNAT_WHEN_SPREL(fmt,spoff,arg)
     69  *	UNW_DEC_PROLOGUE(fmt,body,rlen,arg)
     70  *	UNW_DEC_PROLOGUE_GR(fmt,rlen,mask,grsave,arg)
     71  *	UNW_DEC_REG_PSPREL(fmt,reg,pspoff,arg)
     72  *	UNW_DEC_REG_REG(fmt,src,dst,arg)
     73  *	UNW_DEC_REG_SPREL(fmt,reg,spoff,arg)
     74  *	UNW_DEC_REG_WHEN(fmt,reg,t,arg)
     75  *	UNW_DEC_RESTORE(fmt,t,abreg,arg)
     76  *	UNW_DEC_RESTORE_P(fmt,qp,t,abreg,arg)
     77  *	UNW_DEC_SPILL_BASE(fmt,pspoff,arg)
     78  *	UNW_DEC_SPILL_MASK(fmt,imaskp,arg)
     79  *	UNW_DEC_SPILL_PSPREL(fmt,t,abreg,pspoff,arg)
     80  *	UNW_DEC_SPILL_PSPREL_P(fmt,qp,t,abreg,pspoff,arg)
     81  *	UNW_DEC_SPILL_REG(fmt,t,abreg,x,ytreg,arg)
     82  *	UNW_DEC_SPILL_REG_P(fmt,qp,t,abreg,x,ytreg,arg)
     83  *	UNW_DEC_SPILL_SPREL(fmt,t,abreg,spoff,arg)
     84  *	UNW_DEC_SPILL_SPREL_P(fmt,qp,t,abreg,pspoff,arg)
     85  */
     86 
     87 static unw_word
     88 unw_decode_uleb128 (unsigned char **dpp)
     89 {
     90   unsigned shift = 0;
     91   unw_word byte, result = 0;
     92   unsigned char *bp = *dpp;
     93 
     94   while (1)
     95     {
     96       byte = *bp++;
     97       result |= (byte & 0x7f) << shift;
     98       if ((byte & 0x80) == 0)
     99 	break;
    100       shift += 7;
    101     }
    102   *dpp = bp;
    103   return result;
    104 }
    105 
    106 static unsigned char *
    107 unw_decode_x1 (unsigned char *dp, unsigned char code, void *arg)
    108 {
    109   unsigned char byte1, abreg;
    110   unw_word t, off;
    111 
    112   byte1 = *dp++;
    113   t = unw_decode_uleb128 (&dp);
    114   off = unw_decode_uleb128 (&dp);
    115   abreg = (byte1 & 0x7f);
    116   if (byte1 & 0x80)
    117 	  UNW_DEC_SPILL_SPREL(X1, t, abreg, off, arg);
    118   else
    119 	  UNW_DEC_SPILL_PSPREL(X1, t, abreg, off, arg);
    120   return dp;
    121 }
    122 
    123 static unsigned char *
    124 unw_decode_x2 (unsigned char *dp, unsigned char code, void *arg)
    125 {
    126   unsigned char byte1, byte2, abreg, x, ytreg;
    127   unw_word t;
    128 
    129   byte1 = *dp++; byte2 = *dp++;
    130   t = unw_decode_uleb128 (&dp);
    131   abreg = (byte1 & 0x7f);
    132   ytreg = byte2;
    133   x = (byte1 >> 7) & 1;
    134   if ((byte1 & 0x80) == 0 && ytreg == 0)
    135     UNW_DEC_RESTORE(X2, t, abreg, arg);
    136   else
    137     UNW_DEC_SPILL_REG(X2, t, abreg, x, ytreg, arg);
    138   return dp;
    139 }
    140 
    141 static unsigned char *
    142 unw_decode_x3 (unsigned char *dp, unsigned char code, void *arg)
    143 {
    144   unsigned char byte1, byte2, abreg, qp;
    145   unw_word t, off;
    146 
    147   byte1 = *dp++; byte2 = *dp++;
    148   t = unw_decode_uleb128 (&dp);
    149   off = unw_decode_uleb128 (&dp);
    150 
    151   qp = (byte1 & 0x3f);
    152   abreg = (byte2 & 0x7f);
    153 
    154   if (byte1 & 0x80)
    155     UNW_DEC_SPILL_SPREL_P(X3, qp, t, abreg, off, arg);
    156   else
    157     UNW_DEC_SPILL_PSPREL_P(X3, qp, t, abreg, off, arg);
    158   return dp;
    159 }
    160 
    161 static unsigned char *
    162 unw_decode_x4 (unsigned char *dp, unsigned char code, void *arg)
    163 {
    164   unsigned char byte1, byte2, byte3, qp, abreg, x, ytreg;
    165   unw_word t;
    166 
    167   byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
    168   t = unw_decode_uleb128 (&dp);
    169 
    170   qp = (byte1 & 0x3f);
    171   abreg = (byte2 & 0x7f);
    172   x = (byte2 >> 7) & 1;
    173   ytreg = byte3;
    174 
    175   if ((byte2 & 0x80) == 0 && byte3 == 0)
    176     UNW_DEC_RESTORE_P(X4, qp, t, abreg, arg);
    177   else
    178     UNW_DEC_SPILL_REG_P(X4, qp, t, abreg, x, ytreg, arg);
    179   return dp;
    180 }
    181 
    182 static inline unsigned char *
    183 unw_decode_r1 (unsigned char *dp, unsigned char code, void *arg)
    184 {
    185   int body = (code & 0x20) != 0;
    186   unw_word rlen;
    187 
    188   rlen = (code & 0x1f);
    189   UNW_DEC_PROLOGUE(R1, body, rlen, arg);
    190   return dp;
    191 }
    192 
    193 static inline unsigned char *
    194 unw_decode_r2 (unsigned char *dp, unsigned char code, void *arg)
    195 {
    196   unsigned char byte1, mask, grsave;
    197   unw_word rlen;
    198 
    199   byte1 = *dp++;
    200 
    201   mask = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
    202   grsave = (byte1 & 0x7f);
    203   rlen = unw_decode_uleb128 (&dp);
    204   UNW_DEC_PROLOGUE_GR(R2, rlen, mask, grsave, arg);
    205   return dp;
    206 }
    207 
    208 static inline unsigned char *
    209 unw_decode_r3 (unsigned char *dp, unsigned char code, void *arg)
    210 {
    211   unw_word rlen;
    212 
    213   rlen = unw_decode_uleb128 (&dp);
    214   UNW_DEC_PROLOGUE(R3, ((code & 0x3) == 1), rlen, arg);
    215   return dp;
    216 }
    217 
    218 static inline unsigned char *
    219 unw_decode_p1 (unsigned char *dp, unsigned char code, void *arg)
    220 {
    221   unsigned char brmask = (code & 0x1f);
    222 
    223   UNW_DEC_BR_MEM(P1, brmask, arg);
    224   return dp;
    225 }
    226 
    227 static inline unsigned char *
    228 unw_decode_p2_p5 (unsigned char *dp, unsigned char code, void *arg)
    229 {
    230   if ((code & 0x10) == 0)
    231     {
    232       unsigned char byte1 = *dp++;
    233 
    234       UNW_DEC_BR_GR(P2, ((code & 0xf) << 1) | ((byte1 >> 7) & 1),
    235 		    (byte1 & 0x7f), arg);
    236     }
    237   else if ((code & 0x08) == 0)
    238     {
    239       unsigned char byte1 = *dp++, r, dst;
    240 
    241       r = ((code & 0x7) << 1) | ((byte1 >> 7) & 1);
    242       dst = (byte1 & 0x7f);
    243       switch (r)
    244 	{
    245 	case 0: UNW_DEC_REG_GR(P3, UNW_REG_PSP, dst, arg); break;
    246 	case 1: UNW_DEC_REG_GR(P3, UNW_REG_RP, dst, arg); break;
    247 	case 2: UNW_DEC_REG_GR(P3, UNW_REG_PFS, dst, arg); break;
    248 	case 3: UNW_DEC_REG_GR(P3, UNW_REG_PR, dst, arg); break;
    249 	case 4: UNW_DEC_REG_GR(P3, UNW_REG_UNAT, dst, arg); break;
    250 	case 5: UNW_DEC_REG_GR(P3, UNW_REG_LC, dst, arg); break;
    251 	case 6: UNW_DEC_RP_BR(P3, dst, arg); break;
    252 	case 7: UNW_DEC_REG_GR(P3, UNW_REG_RNAT, dst, arg); break;
    253 	case 8: UNW_DEC_REG_GR(P3, UNW_REG_BSP, dst, arg); break;
    254 	case 9: UNW_DEC_REG_GR(P3, UNW_REG_BSPSTORE, dst, arg); break;
    255 	case 10: UNW_DEC_REG_GR(P3, UNW_REG_FPSR, dst, arg); break;
    256 	case 11: UNW_DEC_PRIUNAT_GR(P3, dst, arg); break;
    257 	default: UNW_DEC_BAD_CODE(r); break;
    258 	}
    259     }
    260   else if ((code & 0x7) == 0)
    261     UNW_DEC_SPILL_MASK(P4, dp, arg);
    262   else if ((code & 0x7) == 1)
    263     {
    264       unw_word grmask, frmask, byte1, byte2, byte3;
    265 
    266       byte1 = *dp++; byte2 = *dp++; byte3 = *dp++;
    267       grmask = ((byte1 >> 4) & 0xf);
    268       frmask = ((byte1 & 0xf) << 16) | (byte2 << 8) | byte3;
    269       UNW_DEC_FRGR_MEM(P5, grmask, frmask, arg);
    270     }
    271   else
    272     UNW_DEC_BAD_CODE(code);
    273   return dp;
    274 }
    275 
    276 static inline unsigned char *
    277 unw_decode_p6 (unsigned char *dp, unsigned char code, void *arg)
    278 {
    279   int gregs = (code & 0x10) != 0;
    280   unsigned char mask = (code & 0x0f);
    281 
    282   if (gregs)
    283     UNW_DEC_GR_MEM(P6, mask, arg);
    284   else
    285     UNW_DEC_FR_MEM(P6, mask, arg);
    286   return dp;
    287 }
    288 
    289 static inline unsigned char *
    290 unw_decode_p7_p10 (unsigned char *dp, unsigned char code, void *arg)
    291 {
    292   unsigned char r, byte1, byte2;
    293   unw_word t, size;
    294 
    295   if ((code & 0x10) == 0)
    296     {
    297       r = (code & 0xf);
    298       t = unw_decode_uleb128 (&dp);
    299       switch (r)
    300 	{
    301 	case 0:
    302 	  size = unw_decode_uleb128 (&dp);
    303 	  UNW_DEC_MEM_STACK_F(P7, t, size, arg);
    304 	  break;
    305 
    306 	case 1: UNW_DEC_MEM_STACK_V(P7, t, arg); break;
    307 	case 2: UNW_DEC_SPILL_BASE(P7, t, arg); break;
    308 	case 3: UNW_DEC_REG_SPREL(P7, UNW_REG_PSP, t, arg); break;
    309 	case 4: UNW_DEC_REG_WHEN(P7, UNW_REG_RP, t, arg); break;
    310 	case 5: UNW_DEC_REG_PSPREL(P7, UNW_REG_RP, t, arg); break;
    311 	case 6: UNW_DEC_REG_WHEN(P7, UNW_REG_PFS, t, arg); break;
    312 	case 7: UNW_DEC_REG_PSPREL(P7, UNW_REG_PFS, t, arg); break;
    313 	case 8: UNW_DEC_REG_WHEN(P7, UNW_REG_PR, t, arg); break;
    314 	case 9: UNW_DEC_REG_PSPREL(P7, UNW_REG_PR, t, arg); break;
    315 	case 10: UNW_DEC_REG_WHEN(P7, UNW_REG_LC, t, arg); break;
    316 	case 11: UNW_DEC_REG_PSPREL(P7, UNW_REG_LC, t, arg); break;
    317 	case 12: UNW_DEC_REG_WHEN(P7, UNW_REG_UNAT, t, arg); break;
    318 	case 13: UNW_DEC_REG_PSPREL(P7, UNW_REG_UNAT, t, arg); break;
    319 	case 14: UNW_DEC_REG_WHEN(P7, UNW_REG_FPSR, t, arg); break;
    320 	case 15: UNW_DEC_REG_PSPREL(P7, UNW_REG_FPSR, t, arg); break;
    321 	default: UNW_DEC_BAD_CODE(r); break;
    322 	}
    323     }
    324   else
    325     {
    326       switch (code & 0xf)
    327 	{
    328 	case 0x0: /* p8 */
    329 	  {
    330 	    r = *dp++;
    331 	    t = unw_decode_uleb128 (&dp);
    332 	    switch (r)
    333 	      {
    334 	      case  1: UNW_DEC_REG_SPREL(P8, UNW_REG_RP, t, arg); break;
    335 	      case  2: UNW_DEC_REG_SPREL(P8, UNW_REG_PFS, t, arg); break;
    336 	      case  3: UNW_DEC_REG_SPREL(P8, UNW_REG_PR, t, arg); break;
    337 	      case  4: UNW_DEC_REG_SPREL(P8, UNW_REG_LC, t, arg); break;
    338 	      case  5: UNW_DEC_REG_SPREL(P8, UNW_REG_UNAT, t, arg); break;
    339 	      case  6: UNW_DEC_REG_SPREL(P8, UNW_REG_FPSR, t, arg); break;
    340 	      case  7: UNW_DEC_REG_WHEN(P8, UNW_REG_BSP, t, arg); break;
    341 	      case  8: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSP, t, arg); break;
    342 	      case  9: UNW_DEC_REG_SPREL(P8, UNW_REG_BSP, t, arg); break;
    343 	      case 10: UNW_DEC_REG_WHEN(P8, UNW_REG_BSPSTORE, t, arg); break;
    344 	      case 11: UNW_DEC_REG_PSPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
    345 	      case 12: UNW_DEC_REG_SPREL(P8, UNW_REG_BSPSTORE, t, arg); break;
    346 	      case 13: UNW_DEC_REG_WHEN(P8, UNW_REG_RNAT, t, arg); break;
    347 	      case 14: UNW_DEC_REG_PSPREL(P8, UNW_REG_RNAT, t, arg); break;
    348 	      case 15: UNW_DEC_REG_SPREL(P8, UNW_REG_RNAT, t, arg); break;
    349 	      case 16: UNW_DEC_PRIUNAT_WHEN_GR(P8, t, arg); break;
    350 	      case 17: UNW_DEC_PRIUNAT_PSPREL(P8, t, arg); break;
    351 	      case 18: UNW_DEC_PRIUNAT_SPREL(P8, t, arg); break;
    352 	      case 19: UNW_DEC_PRIUNAT_WHEN_MEM(P8, t, arg); break;
    353 	      default: UNW_DEC_BAD_CODE(r); break;
    354 	    }
    355 	  }
    356 	  break;
    357 
    358 	case 0x1:
    359 	  byte1 = *dp++; byte2 = *dp++;
    360 	  UNW_DEC_GR_GR(P9, (byte1 & 0xf), (byte2 & 0x7f), arg);
    361 	  break;
    362 
    363 	case 0xf: /* p10 */
    364 	  byte1 = *dp++; byte2 = *dp++;
    365 	  UNW_DEC_ABI(P10, byte1, byte2, arg);
    366 	  break;
    367 
    368 	case 0x9:
    369 	  return unw_decode_x1 (dp, code, arg);
    370 
    371 	case 0xa:
    372 	  return unw_decode_x2 (dp, code, arg);
    373 
    374 	case 0xb:
    375 	  return unw_decode_x3 (dp, code, arg);
    376 
    377 	case 0xc:
    378 	  return unw_decode_x4 (dp, code, arg);
    379 
    380 	default:
    381 	  UNW_DEC_BAD_CODE(code);
    382 	  break;
    383 	}
    384     }
    385   return dp;
    386 }
    387 
    388 static inline unsigned char *
    389 unw_decode_b1 (unsigned char *dp, unsigned char code, void *arg)
    390 {
    391   unw_word label = (code & 0x1f);
    392 
    393   if ((code & 0x20) != 0)
    394     UNW_DEC_COPY_STATE(B1, label, arg);
    395   else
    396     UNW_DEC_LABEL_STATE(B1, label, arg);
    397   return dp;
    398 }
    399 
    400 static inline unsigned char *
    401 unw_decode_b2 (unsigned char *dp, unsigned char code, void *arg)
    402 {
    403   unw_word t;
    404 
    405   t = unw_decode_uleb128 (&dp);
    406   UNW_DEC_EPILOGUE(B2, t, (code & 0x1f), arg);
    407   return dp;
    408 }
    409 
    410 static inline unsigned char *
    411 unw_decode_b3_x4 (unsigned char *dp, unsigned char code, void *arg)
    412 {
    413   unw_word t, ecount, label;
    414 
    415   if ((code & 0x10) == 0)
    416     {
    417       t = unw_decode_uleb128 (&dp);
    418       ecount = unw_decode_uleb128 (&dp);
    419       UNW_DEC_EPILOGUE(B3, t, ecount, arg);
    420     }
    421   else if ((code & 0x07) == 0)
    422     {
    423       label = unw_decode_uleb128 (&dp);
    424       if ((code & 0x08) != 0)
    425 	UNW_DEC_COPY_STATE(B4, label, arg);
    426       else
    427 	UNW_DEC_LABEL_STATE(B4, label, arg);
    428     }
    429   else
    430     switch (code & 0x7)
    431       {
    432       case 1: return unw_decode_x1 (dp, code, arg);
    433       case 2: return unw_decode_x2 (dp, code, arg);
    434       case 3: return unw_decode_x3 (dp, code, arg);
    435       case 4: return unw_decode_x4 (dp, code, arg);
    436       default: UNW_DEC_BAD_CODE(code); break;
    437       }
    438   return dp;
    439 }
    440 
    441 typedef unsigned char *(*unw_decoder) (unsigned char *, unsigned char, void *);
    442 
    443 /*
    444  * Decode one descriptor and return address of next descriptor.
    445  */
    446 static inline unsigned char *
    447 unw_decode (unsigned char *dp, int inside_body, void *arg)
    448 {
    449   unsigned char code, primary;
    450 
    451   code = *dp++;
    452   primary = code >> 5;
    453 
    454   if (primary < 2)
    455     dp = unw_decode_r1 (dp, code, arg);
    456   else if (primary == 2)
    457     dp = unw_decode_r2 (dp, code, arg);
    458   else if (primary == 3)
    459     dp = unw_decode_r3 (dp, code, arg);
    460   else if (inside_body)
    461     switch (primary)
    462       {
    463       case 4:
    464       case 5: dp = unw_decode_b1 (dp, code, arg); break;
    465       case 6: dp = unw_decode_b2 (dp, code, arg); break;
    466       case 7: dp = unw_decode_b3_x4 (dp, code, arg); break;
    467       }
    468   else
    469     switch (primary)
    470       {
    471       case 4: dp = unw_decode_p1 (dp, code, arg); break;
    472       case 5: dp = unw_decode_p2_p5 (dp, code, arg); break;
    473       case 6: dp = unw_decode_p6 (dp, code, arg); break;
    474       case 7: dp = unw_decode_p7_p10 (dp, code, arg); break;
    475       }
    476   return dp;
    477 }
    478