Home | History | Annotate | Download | only in Unwind
      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 "AddressSpace.hpp"
     22 #include "Registers.hpp"
     23 #include "DwarfParser.hpp"
     24 #include "config.h"
     25 
     26 
     27 namespace libunwind {
     28 
     29 
     30 /// DwarfInstructions maps abtract dwarf unwind instructions to a particular
     31 /// architecture
     32 template <typename A, typename R>
     33 class DwarfInstructions {
     34 public:
     35   typedef typename A::pint_t pint_t;
     36   typedef typename A::sint_t sint_t;
     37 
     38   static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
     39                            R &registers);
     40 
     41 private:
     42 
     43   enum {
     44     DW_X86_64_RET_ADDR = 16
     45   };
     46 
     47   enum {
     48     DW_X86_RET_ADDR = 8
     49   };
     50 
     51   typedef typename CFI_Parser<A>::RegisterLocation  RegisterLocation;
     52   typedef typename CFI_Parser<A>::PrologInfo        PrologInfo;
     53   typedef typename CFI_Parser<A>::FDE_Info          FDE_Info;
     54   typedef typename CFI_Parser<A>::CIE_Info          CIE_Info;
     55 
     56   static pint_t evaluateExpression(pint_t expression, A &addressSpace,
     57                                    const R &registers,
     58                                    pint_t initialStackValue);
     59   static pint_t getSavedRegister(A &addressSpace, const R &registers,
     60                                  pint_t cfa, const RegisterLocation &savedReg);
     61   static double getSavedFloatRegister(A &addressSpace, const R &registers,
     62                                   pint_t cfa, const RegisterLocation &savedReg);
     63   static v128 getSavedVectorRegister(A &addressSpace, const R &registers,
     64                                   pint_t cfa, const RegisterLocation &savedReg);
     65 
     66   static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
     67                        const R &registers) {
     68     if (prolog.cfaRegister != 0)
     69       return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
     70              prolog.cfaRegisterOffset);
     71     if (prolog.cfaExpression != 0)
     72       return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
     73                                 registers, 0);
     74     assert(0 && "getCFA(): unknown location");
     75     __builtin_unreachable();
     76   }
     77 };
     78 
     79 
     80 template <typename A, typename R>
     81 typename A::pint_t DwarfInstructions<A, R>::getSavedRegister(
     82     A &addressSpace, const R &registers, pint_t cfa,
     83     const RegisterLocation &savedReg) {
     84   switch (savedReg.location) {
     85   case CFI_Parser<A>::kRegisterInCFA:
     86     return addressSpace.getP(cfa + (pint_t)savedReg.value);
     87 
     88   case CFI_Parser<A>::kRegisterAtExpression:
     89     return addressSpace.getP(
     90         evaluateExpression((pint_t)savedReg.value, addressSpace,
     91                             registers, cfa));
     92 
     93   case CFI_Parser<A>::kRegisterIsExpression:
     94     return evaluateExpression((pint_t)savedReg.value, addressSpace,
     95                               registers, cfa);
     96 
     97   case CFI_Parser<A>::kRegisterInRegister:
     98     return registers.getRegister((int)savedReg.value);
     99 
    100   case CFI_Parser<A>::kRegisterUnused:
    101   case CFI_Parser<A>::kRegisterOffsetFromCFA:
    102     // FIX ME
    103     break;
    104   }
    105   _LIBUNWIND_ABORT("unsupported restore location for register");
    106 }
    107 
    108 template <typename A, typename R>
    109 double DwarfInstructions<A, R>::getSavedFloatRegister(
    110     A &addressSpace, const R &registers, pint_t cfa,
    111     const RegisterLocation &savedReg) {
    112   switch (savedReg.location) {
    113   case CFI_Parser<A>::kRegisterInCFA:
    114     return addressSpace.getDouble(cfa + (pint_t)savedReg.value);
    115 
    116   case CFI_Parser<A>::kRegisterAtExpression:
    117     return addressSpace.getDouble(
    118         evaluateExpression((pint_t)savedReg.value, addressSpace,
    119                             registers, cfa));
    120 
    121   case CFI_Parser<A>::kRegisterIsExpression:
    122   case CFI_Parser<A>::kRegisterUnused:
    123   case CFI_Parser<A>::kRegisterOffsetFromCFA:
    124   case CFI_Parser<A>::kRegisterInRegister:
    125     // FIX ME
    126     break;
    127   }
    128   _LIBUNWIND_ABORT("unsupported restore location for float register");
    129 }
    130 
    131 template <typename A, typename R>
    132 v128 DwarfInstructions<A, R>::getSavedVectorRegister(
    133     A &addressSpace, const R &registers, pint_t cfa,
    134     const RegisterLocation &savedReg) {
    135   switch (savedReg.location) {
    136   case CFI_Parser<A>::kRegisterInCFA:
    137     return addressSpace.getVector(cfa + (pint_t)savedReg.value);
    138 
    139   case CFI_Parser<A>::kRegisterAtExpression:
    140     return addressSpace.getVector(
    141         evaluateExpression((pint_t)savedReg.value, addressSpace,
    142                             registers, cfa));
    143 
    144   case CFI_Parser<A>::kRegisterIsExpression:
    145   case CFI_Parser<A>::kRegisterUnused:
    146   case CFI_Parser<A>::kRegisterOffsetFromCFA:
    147   case CFI_Parser<A>::kRegisterInRegister:
    148     // FIX ME
    149     break;
    150   }
    151   _LIBUNWIND_ABORT("unsupported restore location for vector register");
    152 }
    153 
    154 template <typename A, typename R>
    155 int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
    156                                            pint_t fdeStart, R &registers) {
    157   FDE_Info fdeInfo;
    158   CIE_Info cieInfo;
    159   if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart,
    160                                                   &fdeInfo, &cieInfo) == NULL) {
    161     PrologInfo prolog;
    162     if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
    163                                                                      &prolog)) {
    164       // get pointer to cfa (architecture specific)
    165       pint_t cfa = getCFA(addressSpace, prolog, registers);
    166 
    167        // restore registers that dwarf says were saved
    168       R newRegisters = registers;
    169       pint_t returnAddress = 0;
    170       const int lastReg = R::lastDwarfRegNum();
    171       assert((int)CFI_Parser<A>::kMaxRegisterNumber > lastReg
    172                                                 && "register range too large");
    173       assert(lastReg <= (int)cieInfo.returnAddressRegister
    174                  && "register range does not contain return address register");
    175       for (int i = 0; i <= lastReg; ++i) {
    176          if (prolog.savedRegisters[i].location !=
    177              CFI_Parser<A>::kRegisterUnused) {
    178            if (registers.validFloatRegister(i))
    179             newRegisters.setFloatRegister(
    180                 i, getSavedFloatRegister(addressSpace, registers, cfa,
    181                                          prolog.savedRegisters[i]));
    182           else if (registers.validVectorRegister(i))
    183             newRegisters.setVectorRegister(
    184                 i, getSavedVectorRegister(addressSpace, registers, cfa,
    185                                           prolog.savedRegisters[i]));
    186           else if (i == (int)cieInfo.returnAddressRegister)
    187             returnAddress = getSavedRegister(addressSpace, registers, cfa,
    188                                              prolog.savedRegisters[i]);
    189           else if (registers.validRegister(i))
    190             newRegisters.setRegister(
    191                 i, getSavedRegister(addressSpace, registers, cfa,
    192                                     prolog.savedRegisters[i]));
    193           else
    194             return UNW_EBADREG;
    195         }
    196       }
    197 
    198       // By definition, the CFA is the stack pointer at the call site, so
    199       // restoring SP means setting it to CFA.
    200       newRegisters.setSP(cfa);
    201 
    202       // Return address is address after call site instruction, so setting IP to
    203       // that does simualates a return.
    204       newRegisters.setIP(returnAddress);
    205 
    206       // Simulate the step by replacing the register set with the new ones.
    207       registers = newRegisters;
    208 
    209       return UNW_STEP_SUCCESS;
    210     }
    211   }
    212   return UNW_EBADFRAME;
    213 }
    214 
    215 template <typename A, typename R>
    216 typename A::pint_t
    217 DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
    218                                             const R &registers,
    219                                             pint_t initialStackValue) {
    220   const bool log = false;
    221   pint_t p = expression;
    222   pint_t expressionEnd = expression + 20; // temp, until len read
    223   pint_t length = (pint_t)addressSpace.getULEB128(p, expressionEnd);
    224   expressionEnd = p + length;
    225   if (log)
    226     fprintf(stderr, "evaluateExpression(): length=%llu\n", (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%llX\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%llX\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%llX\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%llX\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%llX\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%llX\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%llX\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%llX\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%llX\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%llX\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%llX\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%llX\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%llX\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%llX\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 += 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 %lld\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 %lld\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 = opcode - DW_OP_lit0;
    608       *(++sp) = value;
    609       if (log)
    610         fprintf(stderr, "push literal 0x%llX\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 = 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 = (uint32_t)addressSpace.getULEB128(p, expressionEnd);
    653       *(++sp) = registers.getRegister((int)reg);
    654       if (log)
    655         fprintf(stderr, "push reg %d + 0x%llX\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 = opcode - DW_OP_breg0;
    691       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
    692       svalue += registers.getRegister((int)reg);
    693       *(++sp) = (pint_t)(svalue);
    694       if (log)
    695         fprintf(stderr, "push reg %d + 0x%llX\n", reg, (uint64_t) svalue);
    696       break;
    697 
    698     case DW_OP_bregx:
    699       reg = (uint32_t)addressSpace.getULEB128(p, expressionEnd);
    700       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
    701       svalue += registers.getRegister((int)reg);
    702       *(++sp) = (pint_t)(svalue);
    703       if (log)
    704         fprintf(stderr, "push reg %d + 0x%llX\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%llX\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%llX\n", (uint64_t) * sp);
    752   return *sp;
    753 }
    754 
    755 
    756 
    757 } // namespace libunwind
    758 
    759 #endif // __DWARF_INSTRUCTIONS_HPP__
    760