cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

unwind_decoder.c (12329B)


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