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