Home | History | Annotate | Download | only in src
      1 //===-------------------------- DwarfInstructions.hpp ---------------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //
      8 //  Processor specific interpretation of DWARF unwind info.
      9 //
     10 //===----------------------------------------------------------------------===//
     11 
     12 #ifndef __DWARF_INSTRUCTIONS_HPP__
     13 #define __DWARF_INSTRUCTIONS_HPP__
     14 
     15 #include <stdint.h>
     16 #include <stdio.h>
     17 #include <stdlib.h>
     18 
     19 #include "dwarf2.h"
     20 #include "Registers.hpp"
     21 #include "DwarfParser.hpp"
     22 #include "config.h"
     23 
     24 
     25 namespace libunwind {
     26 
     27 
     28 /// DwarfInstructions maps abtract DWARF unwind instructions to a particular
     29 /// architecture
     30 template <typename A, typename R>
     31 class DwarfInstructions {
     32 public:
     33   typedef typename A::pint_t pint_t;
     34   typedef typename A::sint_t sint_t;
     35 
     36   static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
     37                            R &registers);
     38 
     39 private:
     40 
     41   enum {
     42     DW_X86_64_RET_ADDR = 16
     43   };
     44 
     45   enum {
     46     DW_X86_RET_ADDR = 8
     47   };
     48 
     49   typedef typename CFI_Parser<A>::RegisterLocation  RegisterLocation;
     50   typedef typename CFI_Parser<A>::PrologInfo        PrologInfo;
     51   typedef typename CFI_Parser<A>::FDE_Info          FDE_Info;
     52   typedef typename CFI_Parser<A>::CIE_Info          CIE_Info;
     53 
     54   static pint_t evaluateExpression(pint_t expression, A &addressSpace,
     55                                    const R &registers,
     56                                    pint_t initialStackValue);
     57   static pint_t getSavedRegister(A &addressSpace, const R &registers,
     58                                  pint_t cfa, const RegisterLocation &savedReg);
     59   static double getSavedFloatRegister(A &addressSpace, const R &registers,
     60                                   pint_t cfa, const RegisterLocation &savedReg);
     61   static v128 getSavedVectorRegister(A &addressSpace, const R &registers,
     62                                   pint_t cfa, const RegisterLocation &savedReg);
     63 
     64   static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
     65                        const R &registers) {
     66     if (prolog.cfaRegister != 0)
     67       return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
     68              prolog.cfaRegisterOffset);
     69     if (prolog.cfaExpression != 0)
     70       return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
     71                                 registers, 0);
     72     assert(0 && "getCFA(): unknown location");
     73     __builtin_unreachable();
     74   }
     75 };
     76 
     77 
     78 template <typename A, typename R>
     79 typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
     80     A &addressSpace, const R &registers, pint_t cfa,
     81     const RegisterLocation &savedReg) {
     82   switch (savedReg.location) {
     83   case CFI_Parser<A>::kRegisterInCFA:
     84     return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value);
     85 
     86   case CFI_Parser<A>::kRegisterAtExpression:
     87     return (pint_t)addressSpace.getRegister(evaluateExpression(
     88         (pint_t)savedReg.value, addressSpace, registers, cfa));
     89 
     90   case CFI_Parser<A>::kRegisterIsExpression:
     91     return evaluateExpression((pint_t)savedReg.value, addressSpace,
     92                               registers, cfa);
     93 
     94   case CFI_Parser<A>::kRegisterInRegister:
     95     return registers.getRegister((int)savedReg.value);
     96 
     97   case CFI_Parser<A>::kRegisterUnused:
     98   case CFI_Parser<A>::kRegisterOffsetFromCFA:
     99     // FIX ME
    100     break;
    101   }
    102   _LIBUNWIND_ABORT("unsupported restore location for register");
    103 }
    104 
    105 template <typename A, typename R>
    106 double DwarfInstructions<A, R>::getSavedFloatRegister(
    107     A &addressSpace, const R &registers, pint_t cfa,
    108     const RegisterLocation &savedReg) {
    109   switch (savedReg.location) {
    110   case CFI_Parser<A>::kRegisterInCFA:
    111     return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
    112 
    113   case CFI_Parser<A>::kRegisterAtExpression:
    114     return addressSpace.getDouble(
    115         evaluateExpression((pint_t)savedReg.value, addressSpace,
    116                             registers, cfa));
    117 
    118   case CFI_Parser<A>::kRegisterIsExpression:
    119   case CFI_Parser<A>::kRegisterUnused:
    120   case CFI_Parser<A>::kRegisterOffsetFromCFA:
    121   case CFI_Parser<A>::kRegisterInRegister:
    122     // FIX ME
    123     break;
    124   }
    125   _LIBUNWIND_ABORT("unsupported restore location for float register");
    126 }
    127 
    128 template <typename A, typename R>
    129 v128 DwarfInstructions<A, R>::getSavedVectorRegister(
    130     A &addressSpace, const R &registers, pint_t cfa,
    131     const RegisterLocation &savedReg) {
    132   switch (savedReg.location) {
    133   case CFI_Parser<A>::kRegisterInCFA:
    134     return addressSpace.getVector(cfa + (pint_t)savedReg.value);
    135 
    136   case CFI_Parser<A>::kRegisterAtExpression:
    137     return addressSpace.getVector(
    138         evaluateExpression((pint_t)savedReg.value, addressSpace,
    139                             registers, cfa));
    140 
    141   case CFI_Parser<A>::kRegisterIsExpression:
    142   case CFI_Parser<A>::kRegisterUnused:
    143   case CFI_Parser<A>::kRegisterOffsetFromCFA:
    144   case CFI_Parser<A>::kRegisterInRegister:
    145     // FIX ME
    146     break;
    147   }
    148   _LIBUNWIND_ABORT("unsupported restore location for vector register");
    149 }
    150 
    151 template <typename A, typename R>
    152 int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
    153                                            pint_t fdeStart, R &registers) {
    154   FDE_Info fdeInfo;
    155   CIE_Info cieInfo;
    156   if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,
    157                                &cieInfo) == NULL) {
    158     PrologInfo prolog;
    159     if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
    160                                             R::getArch(), &prolog)) {
    161       // get pointer to cfa (architecture specific)
    162       pint_t cfa = getCFA(addressSpace, prolog, registers);
    163 
    164        // restore registers that DWARF says were saved
    165       R newRegisters = registers;
    166       pint_t returnAddress = 0;
    167       const int lastReg = R::lastDwarfRegNum();
    168       assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg &&
    169              "register range too large");
    170       assert(lastReg >= (int)cieInfo.returnAddressRegister &&
    171              "register range does not contain return address register");
    172       for (int i = 0; i <= lastReg; ++i) {
    173         if (prolog.savedRegisters[i].location !=
    174             CFI_Parser<A>::kRegisterUnused) {
    175           if (registers.validFloatRegister(i))
    176             newRegisters.setFloatRegister(
    177                 i, getSavedFloatRegister(addressSpace, registers, cfa,
    178                                          prolog.savedRegisters[i]));
    179           else if (registers.validVectorRegister(i))
    180             newRegisters.setVectorRegister(
    181                 i, getSavedVectorRegister(addressSpace, registers, cfa,
    182                                           prolog.savedRegisters[i]));
    183           else if (i == (int)cieInfo.returnAddressRegister)
    184             returnAddress = getSavedRegister(addressSpace, registers, cfa,
    185                                              prolog.savedRegisters[i]);
    186           else if (registers.validRegister(i))
    187             newRegisters.setRegister(
    188                 i, getSavedRegister(addressSpace, registers, cfa,
    189                                     prolog.savedRegisters[i]));
    190           else
    191             return UNW_EBADREG;
    192         }
    193       }
    194 
    195       // By definition, the CFA is the stack pointer at the call site, so
    196       // restoring SP means setting it to CFA.
    197       newRegisters.setSP(cfa);
    198 
    199 #if defined(_LIBUNWIND_TARGET_AARCH64)
    200       // If the target is aarch64 then the return address may have been signed
    201       // using the v8.3 pointer authentication extensions. The original
    202       // return address needs to be authenticated before the return address is
    203       // restored. autia1716 is used instead of autia as autia1716 assembles
    204       // to a NOP on pre-v8.3a architectures.
    205       if ((R::getArch() == REGISTERS_ARM64) &&
    206           prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value) {
    207 #if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
    208         return UNW_ECROSSRASIGNING;
    209 #else
    210         register unsigned long long x17 __asm("x17") = returnAddress;
    211         register unsigned long long x16 __asm("x16") = cfa;
    212 
    213         // These are the autia1716/autib1716 instructions. The hint instructions
    214         // are used here as gcc does not assemble autia1716/autib1716 for pre
    215         // armv8.3a targets.
    216         if (cieInfo.addressesSignedWithBKey)
    217           asm("hint 0xe" : "+r"(x17) : "r"(x16)); // autib1716
    218         else
    219           asm("hint 0xc" : "+r"(x17) : "r"(x16)); // autia1716
    220         returnAddress = x17;
    221 #endif
    222       }
    223 #endif
    224 
    225 #if defined(_LIBUNWIND_TARGET_SPARC)
    226       if (R::getArch() == REGISTERS_SPARC) {
    227         // Skip call site instruction and delay slot
    228         returnAddress += 8;
    229         // Skip unimp instruction if function returns a struct
    230         if ((addressSpace.get32(returnAddress) & 0xC1C00000) == 0)
    231           returnAddress += 4;
    232       }
    233 #endif
    234 
    235       // Return address is address after call site instruction, so setting IP to
    236       // that does simualates a return.
    237       newRegisters.setIP(returnAddress);
    238 
    239       // Simulate the step by replacing the register set with the new ones.
    240       registers = newRegisters;
    241 
    242       return UNW_STEP_SUCCESS;
    243     }
    244   }
    245   return UNW_EBADFRAME;
    246 }
    247 
    248 template <typename A, typename R>
    249 typename A::pint_t
    250 DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
    251                                             const R &registers,
    252                                             pint_t initialStackValue) {
    253   const bool log = false;
    254   pint_t p = expression;
    255   pint_t expressionEnd = expression + 20; // temp, until len read
    256   pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
    257   expressionEnd = p + length;
    258   if (log)
    259     fprintf(stderr, "evaluateExpression(): length=%" PRIu64 "\n",
    260             (uint64_t)length);
    261   pint_t stack[100];
    262   pint_t *sp = stack;
    263   *(++sp) = initialStackValue;
    264 
    265   while (p < expressionEnd) {
    266     if (log) {
    267       for (pint_t *t = sp; t > stack; --t) {
    268         fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));
    269       }
    270     }
    271     uint8_t opcode = addressSpace.get8(p++);
    272     sint_t svalue, svalue2;
    273     pint_t value;
    274     uint32_t reg;
    275     switch (opcode) {
    276     case DW_OP_addr:
    277       // push immediate address sized value
    278       value = addressSpace.getP(p);
    279       p += sizeof(pint_t);
    280       *(++sp) = value;
    281       if (log)
    282         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
    283       break;
    284 
    285     case DW_OP_deref:
    286       // pop stack, dereference, push result
    287       value = *sp--;
    288       *(++sp) = addressSpace.getP(value);
    289       if (log)
    290         fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);
    291       break;
    292 
    293     case DW_OP_const1u:
    294       // push immediate 1 byte value
    295       value = addressSpace.get8(p);
    296       p += 1;
    297       *(++sp) = value;
    298       if (log)
    299         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
    300       break;
    301 
    302     case DW_OP_const1s:
    303       // push immediate 1 byte signed value
    304       svalue = (int8_t) addressSpace.get8(p);
    305       p += 1;
    306       *(++sp) = (pint_t)svalue;
    307       if (log)
    308         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
    309       break;
    310 
    311     case DW_OP_const2u:
    312       // push immediate 2 byte value
    313       value = addressSpace.get16(p);
    314       p += 2;
    315       *(++sp) = value;
    316       if (log)
    317         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
    318       break;
    319 
    320     case DW_OP_const2s:
    321       // push immediate 2 byte signed value
    322       svalue = (int16_t) addressSpace.get16(p);
    323       p += 2;
    324       *(++sp) = (pint_t)svalue;
    325       if (log)
    326         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
    327       break;
    328 
    329     case DW_OP_const4u:
    330       // push immediate 4 byte value
    331       value = addressSpace.get32(p);
    332       p += 4;
    333       *(++sp) = value;
    334       if (log)
    335         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
    336       break;
    337 
    338     case DW_OP_const4s:
    339       // push immediate 4 byte signed value
    340       svalue = (int32_t)addressSpace.get32(p);
    341       p += 4;
    342       *(++sp) = (pint_t)svalue;
    343       if (log)
    344         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
    345       break;
    346 
    347     case DW_OP_const8u:
    348       // push immediate 8 byte value
    349       value = (pint_t)addressSpace.get64(p);
    350       p += 8;
    351       *(++sp) = value;
    352       if (log)
    353         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
    354       break;
    355 
    356     case DW_OP_const8s:
    357       // push immediate 8 byte signed value
    358       value = (pint_t)addressSpace.get64(p);
    359       p += 8;
    360       *(++sp) = value;
    361       if (log)
    362         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
    363       break;
    364 
    365     case DW_OP_constu:
    366       // push immediate ULEB128 value
    367       value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
    368       *(++sp) = value;
    369       if (log)
    370         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
    371       break;
    372 
    373     case DW_OP_consts:
    374       // push immediate SLEB128 value
    375       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
    376       *(++sp) = (pint_t)svalue;
    377       if (log)
    378         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
    379       break;
    380 
    381     case DW_OP_dup:
    382       // push top of stack
    383       value = *sp;
    384       *(++sp) = value;
    385       if (log)
    386         fprintf(stderr, "duplicate top of stack\n");
    387       break;
    388 
    389     case DW_OP_drop:
    390       // pop
    391       --sp;
    392       if (log)
    393         fprintf(stderr, "pop top of stack\n");
    394       break;
    395 
    396     case DW_OP_over:
    397       // dup second
    398       value = sp[-1];
    399       *(++sp) = value;
    400       if (log)
    401         fprintf(stderr, "duplicate second in stack\n");
    402       break;
    403 
    404     case DW_OP_pick:
    405       // pick from
    406       reg = addressSpace.get8(p);
    407       p += 1;
    408       value = sp[-reg];
    409       *(++sp) = value;
    410       if (log)
    411         fprintf(stderr, "duplicate %d in stack\n", reg);
    412       break;
    413 
    414     case DW_OP_swap:
    415       // swap top two
    416       value = sp[0];
    417       sp[0] = sp[-1];
    418       sp[-1] = value;
    419       if (log)
    420         fprintf(stderr, "swap top of stack\n");
    421       break;
    422 
    423     case DW_OP_rot:
    424       // rotate top three
    425       value = sp[0];
    426       sp[0] = sp[-1];
    427       sp[-1] = sp[-2];
    428       sp[-2] = value;
    429       if (log)
    430         fprintf(stderr, "rotate top three of stack\n");
    431       break;
    432 
    433     case DW_OP_xderef:
    434       // pop stack, dereference, push result
    435       value = *sp--;
    436       *sp = *((pint_t*)value);
    437       if (log)
    438         fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);
    439       break;
    440 
    441     case DW_OP_abs:
    442       svalue = (sint_t)*sp;
    443       if (svalue < 0)
    444         *sp = (pint_t)(-svalue);
    445       if (log)
    446         fprintf(stderr, "abs\n");
    447       break;
    448 
    449     case DW_OP_and:
    450       value = *sp--;
    451       *sp &= value;
    452       if (log)
    453         fprintf(stderr, "and\n");
    454       break;
    455 
    456     case DW_OP_div:
    457       svalue = (sint_t)(*sp--);
    458       svalue2 = (sint_t)*sp;
    459       *sp = (pint_t)(svalue2 / svalue);
    460       if (log)
    461         fprintf(stderr, "div\n");
    462       break;
    463 
    464     case DW_OP_minus:
    465       value = *sp--;
    466       *sp = *sp - value;
    467       if (log)
    468         fprintf(stderr, "minus\n");
    469       break;
    470 
    471     case DW_OP_mod:
    472       svalue = (sint_t)(*sp--);
    473       svalue2 = (sint_t)*sp;
    474       *sp = (pint_t)(svalue2 % svalue);
    475       if (log)
    476         fprintf(stderr, "module\n");
    477       break;
    478 
    479     case DW_OP_mul:
    480       svalue = (sint_t)(*sp--);
    481       svalue2 = (sint_t)*sp;
    482       *sp = (pint_t)(svalue2 * svalue);
    483       if (log)
    484         fprintf(stderr, "mul\n");
    485       break;
    486 
    487     case DW_OP_neg:
    488       *sp = 0 - *sp;
    489       if (log)
    490         fprintf(stderr, "neg\n");
    491       break;
    492 
    493     case DW_OP_not:
    494       svalue = (sint_t)(*sp);
    495       *sp = (pint_t)(~svalue);
    496       if (log)
    497         fprintf(stderr, "not\n");
    498       break;
    499 
    500     case DW_OP_or:
    501       value = *sp--;
    502       *sp |= value;
    503       if (log)
    504         fprintf(stderr, "or\n");
    505       break;
    506 
    507     case DW_OP_plus:
    508       value = *sp--;
    509       *sp += value;
    510       if (log)
    511         fprintf(stderr, "plus\n");
    512       break;
    513 
    514     case DW_OP_plus_uconst:
    515       // pop stack, add uelb128 constant, push result
    516       *sp += static_cast<pint_t>(addressSpace.getULEB128(p, expressionEnd));
    517       if (log)
    518         fprintf(stderr, "add constant\n");
    519       break;
    520 
    521     case DW_OP_shl:
    522       value = *sp--;
    523       *sp = *sp << value;
    524       if (log)
    525         fprintf(stderr, "shift left\n");
    526       break;
    527 
    528     case DW_OP_shr:
    529       value = *sp--;
    530       *sp = *sp >> value;
    531       if (log)
    532         fprintf(stderr, "shift left\n");
    533       break;
    534 
    535     case DW_OP_shra:
    536       value = *sp--;
    537       svalue = (sint_t)*sp;
    538       *sp = (pint_t)(svalue >> value);
    539       if (log)
    540         fprintf(stderr, "shift left arithmetric\n");
    541       break;
    542 
    543     case DW_OP_xor:
    544       value = *sp--;
    545       *sp ^= value;
    546       if (log)
    547         fprintf(stderr, "xor\n");
    548       break;
    549 
    550     case DW_OP_skip:
    551       svalue = (int16_t) addressSpace.get16(p);
    552       p += 2;
    553       p = (pint_t)((sint_t)p + svalue);
    554       if (log)
    555         fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);
    556       break;
    557 
    558     case DW_OP_bra:
    559       svalue = (int16_t) addressSpace.get16(p);
    560       p += 2;
    561       if (*sp--)
    562         p = (pint_t)((sint_t)p + svalue);
    563       if (log)
    564         fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);
    565       break;
    566 
    567     case DW_OP_eq:
    568       value = *sp--;
    569       *sp = (*sp == value);
    570       if (log)
    571         fprintf(stderr, "eq\n");
    572       break;
    573 
    574     case DW_OP_ge:
    575       value = *sp--;
    576       *sp = (*sp >= value);
    577       if (log)
    578         fprintf(stderr, "ge\n");
    579       break;
    580 
    581     case DW_OP_gt:
    582       value = *sp--;
    583       *sp = (*sp > value);
    584       if (log)
    585         fprintf(stderr, "gt\n");
    586       break;
    587 
    588     case DW_OP_le:
    589       value = *sp--;
    590       *sp = (*sp <= value);
    591       if (log)
    592         fprintf(stderr, "le\n");
    593       break;
    594 
    595     case DW_OP_lt:
    596       value = *sp--;
    597       *sp = (*sp < value);
    598       if (log)
    599         fprintf(stderr, "lt\n");
    600       break;
    601 
    602     case DW_OP_ne:
    603       value = *sp--;
    604       *sp = (*sp != value);
    605       if (log)
    606         fprintf(stderr, "ne\n");
    607       break;
    608 
    609     case DW_OP_lit0:
    610     case DW_OP_lit1:
    611     case DW_OP_lit2:
    612     case DW_OP_lit3:
    613     case DW_OP_lit4:
    614     case DW_OP_lit5:
    615     case DW_OP_lit6:
    616     case DW_OP_lit7:
    617     case DW_OP_lit8:
    618     case DW_OP_lit9:
    619     case DW_OP_lit10:
    620     case DW_OP_lit11:
    621     case DW_OP_lit12:
    622     case DW_OP_lit13:
    623     case DW_OP_lit14:
    624     case DW_OP_lit15:
    625     case DW_OP_lit16:
    626     case DW_OP_lit17:
    627     case DW_OP_lit18:
    628     case DW_OP_lit19:
    629     case DW_OP_lit20:
    630     case DW_OP_lit21:
    631     case DW_OP_lit22:
    632     case DW_OP_lit23:
    633     case DW_OP_lit24:
    634     case DW_OP_lit25:
    635     case DW_OP_lit26:
    636     case DW_OP_lit27:
    637     case DW_OP_lit28:
    638     case DW_OP_lit29:
    639     case DW_OP_lit30:
    640     case DW_OP_lit31:
    641       value = static_cast<pint_t>(opcode - DW_OP_lit0);
    642       *(++sp) = value;
    643       if (log)
    644         fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);
    645       break;
    646 
    647     case DW_OP_reg0:
    648     case DW_OP_reg1:
    649     case DW_OP_reg2:
    650     case DW_OP_reg3:
    651     case DW_OP_reg4:
    652     case DW_OP_reg5:
    653     case DW_OP_reg6:
    654     case DW_OP_reg7:
    655     case DW_OP_reg8:
    656     case DW_OP_reg9:
    657     case DW_OP_reg10:
    658     case DW_OP_reg11:
    659     case DW_OP_reg12:
    660     case DW_OP_reg13:
    661     case DW_OP_reg14:
    662     case DW_OP_reg15:
    663     case DW_OP_reg16:
    664     case DW_OP_reg17:
    665     case DW_OP_reg18:
    666     case DW_OP_reg19:
    667     case DW_OP_reg20:
    668     case DW_OP_reg21:
    669     case DW_OP_reg22:
    670     case DW_OP_reg23:
    671     case DW_OP_reg24:
    672     case DW_OP_reg25:
    673     case DW_OP_reg26:
    674     case DW_OP_reg27:
    675     case DW_OP_reg28:
    676     case DW_OP_reg29:
    677     case DW_OP_reg30:
    678     case DW_OP_reg31:
    679       reg = static_cast<uint32_t>(opcode - DW_OP_reg0);
    680       *(++sp) = registers.getRegister((int)reg);
    681       if (log)
    682         fprintf(stderr, "push reg %d\n", reg);
    683       break;
    684 
    685     case DW_OP_regx:
    686       reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
    687       *(++sp) = registers.getRegister((int)reg);
    688       if (log)
    689         fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
    690       break;
    691 
    692     case DW_OP_breg0:
    693     case DW_OP_breg1:
    694     case DW_OP_breg2:
    695     case DW_OP_breg3:
    696     case DW_OP_breg4:
    697     case DW_OP_breg5:
    698     case DW_OP_breg6:
    699     case DW_OP_breg7:
    700     case DW_OP_breg8:
    701     case DW_OP_breg9:
    702     case DW_OP_breg10:
    703     case DW_OP_breg11:
    704     case DW_OP_breg12:
    705     case DW_OP_breg13:
    706     case DW_OP_breg14:
    707     case DW_OP_breg15:
    708     case DW_OP_breg16:
    709     case DW_OP_breg17:
    710     case DW_OP_breg18:
    711     case DW_OP_breg19:
    712     case DW_OP_breg20:
    713     case DW_OP_breg21:
    714     case DW_OP_breg22:
    715     case DW_OP_breg23:
    716     case DW_OP_breg24:
    717     case DW_OP_breg25:
    718     case DW_OP_breg26:
    719     case DW_OP_breg27:
    720     case DW_OP_breg28:
    721     case DW_OP_breg29:
    722     case DW_OP_breg30:
    723     case DW_OP_breg31:
    724       reg = static_cast<uint32_t>(opcode - DW_OP_breg0);
    725       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
    726       svalue += static_cast<sint_t>(registers.getRegister((int)reg));
    727       *(++sp) = (pint_t)(svalue);
    728       if (log)
    729         fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
    730       break;
    731 
    732     case DW_OP_bregx:
    733       reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
    734       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
    735       svalue += static_cast<sint_t>(registers.getRegister((int)reg));
    736       *(++sp) = (pint_t)(svalue);
    737       if (log)
    738         fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
    739       break;
    740 
    741     case DW_OP_fbreg:
    742       _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
    743       break;
    744 
    745     case DW_OP_piece:
    746       _LIBUNWIND_ABORT("DW_OP_piece not implemented");
    747       break;
    748 
    749     case DW_OP_deref_size:
    750       // pop stack, dereference, push result
    751       value = *sp--;
    752       switch (addressSpace.get8(p++)) {
    753       case 1:
    754         value = addressSpace.get8(value);
    755         break;
    756       case 2:
    757         value = addressSpace.get16(value);
    758         break;
    759       case 4:
    760         value = addressSpace.get32(value);
    761         break;
    762       case 8:
    763         value = (pint_t)addressSpace.get64(value);
    764         break;
    765       default:
    766         _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
    767       }
    768       *(++sp) = value;
    769       if (log)
    770         fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);
    771       break;
    772 
    773     case DW_OP_xderef_size:
    774     case DW_OP_nop:
    775     case DW_OP_push_object_addres:
    776     case DW_OP_call2:
    777     case DW_OP_call4:
    778     case DW_OP_call_ref:
    779     default:
    780       _LIBUNWIND_ABORT("DWARF opcode not implemented");
    781     }
    782 
    783   }
    784   if (log)
    785     fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);
    786   return *sp;
    787 }
    788 
    789 
    790 
    791 } // namespace libunwind
    792 
    793 #endif // __DWARF_INSTRUCTIONS_HPP__
    794