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, &fdeInfo,
    160                                &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=%" PRIu64 "\n",
    227             (uint64_t)length);
    228   pint_t stack[100];
    229   pint_t *sp = stack;
    230   *(++sp) = initialStackValue;
    231 
    232   while (p < expressionEnd) {
    233     if (log) {
    234       for (pint_t *t = sp; t > stack; --t) {
    235         fprintf(stderr, "sp[] = 0x%" PRIx64 "\n", (uint64_t)(*t));
    236       }
    237     }
    238     uint8_t opcode = addressSpace.get8(p++);
    239     sint_t svalue, svalue2;
    240     pint_t value;
    241     uint32_t reg;
    242     switch (opcode) {
    243     case DW_OP_addr:
    244       // push immediate address sized value
    245       value = addressSpace.getP(p);
    246       p += sizeof(pint_t);
    247       *(++sp) = value;
    248       if (log)
    249         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
    250       break;
    251 
    252     case DW_OP_deref:
    253       // pop stack, dereference, push result
    254       value = *sp--;
    255       *(++sp) = addressSpace.getP(value);
    256       if (log)
    257         fprintf(stderr, "dereference 0x%" PRIx64 "\n", (uint64_t)value);
    258       break;
    259 
    260     case DW_OP_const1u:
    261       // push immediate 1 byte value
    262       value = addressSpace.get8(p);
    263       p += 1;
    264       *(++sp) = value;
    265       if (log)
    266         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
    267       break;
    268 
    269     case DW_OP_const1s:
    270       // push immediate 1 byte signed value
    271       svalue = (int8_t) addressSpace.get8(p);
    272       p += 1;
    273       *(++sp) = (pint_t)svalue;
    274       if (log)
    275         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
    276       break;
    277 
    278     case DW_OP_const2u:
    279       // push immediate 2 byte value
    280       value = addressSpace.get16(p);
    281       p += 2;
    282       *(++sp) = value;
    283       if (log)
    284         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
    285       break;
    286 
    287     case DW_OP_const2s:
    288       // push immediate 2 byte signed value
    289       svalue = (int16_t) addressSpace.get16(p);
    290       p += 2;
    291       *(++sp) = (pint_t)svalue;
    292       if (log)
    293         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
    294       break;
    295 
    296     case DW_OP_const4u:
    297       // push immediate 4 byte value
    298       value = addressSpace.get32(p);
    299       p += 4;
    300       *(++sp) = value;
    301       if (log)
    302         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
    303       break;
    304 
    305     case DW_OP_const4s:
    306       // push immediate 4 byte signed value
    307       svalue = (int32_t)addressSpace.get32(p);
    308       p += 4;
    309       *(++sp) = (pint_t)svalue;
    310       if (log)
    311         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
    312       break;
    313 
    314     case DW_OP_const8u:
    315       // push immediate 8 byte value
    316       value = (pint_t)addressSpace.get64(p);
    317       p += 8;
    318       *(++sp) = value;
    319       if (log)
    320         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
    321       break;
    322 
    323     case DW_OP_const8s:
    324       // push immediate 8 byte signed value
    325       value = (pint_t)addressSpace.get64(p);
    326       p += 8;
    327       *(++sp) = value;
    328       if (log)
    329         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
    330       break;
    331 
    332     case DW_OP_constu:
    333       // push immediate ULEB128 value
    334       value = (pint_t)addressSpace.getULEB128(p, expressionEnd);
    335       *(++sp) = value;
    336       if (log)
    337         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)value);
    338       break;
    339 
    340     case DW_OP_consts:
    341       // push immediate SLEB128 value
    342       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
    343       *(++sp) = (pint_t)svalue;
    344       if (log)
    345         fprintf(stderr, "push 0x%" PRIx64 "\n", (uint64_t)svalue);
    346       break;
    347 
    348     case DW_OP_dup:
    349       // push top of stack
    350       value = *sp;
    351       *(++sp) = value;
    352       if (log)
    353         fprintf(stderr, "duplicate top of stack\n");
    354       break;
    355 
    356     case DW_OP_drop:
    357       // pop
    358       --sp;
    359       if (log)
    360         fprintf(stderr, "pop top of stack\n");
    361       break;
    362 
    363     case DW_OP_over:
    364       // dup second
    365       value = sp[-1];
    366       *(++sp) = value;
    367       if (log)
    368         fprintf(stderr, "duplicate second in stack\n");
    369       break;
    370 
    371     case DW_OP_pick:
    372       // pick from
    373       reg = addressSpace.get8(p);
    374       p += 1;
    375       value = sp[-reg];
    376       *(++sp) = value;
    377       if (log)
    378         fprintf(stderr, "duplicate %d in stack\n", reg);
    379       break;
    380 
    381     case DW_OP_swap:
    382       // swap top two
    383       value = sp[0];
    384       sp[0] = sp[-1];
    385       sp[-1] = value;
    386       if (log)
    387         fprintf(stderr, "swap top of stack\n");
    388       break;
    389 
    390     case DW_OP_rot:
    391       // rotate top three
    392       value = sp[0];
    393       sp[0] = sp[-1];
    394       sp[-1] = sp[-2];
    395       sp[-2] = value;
    396       if (log)
    397         fprintf(stderr, "rotate top three of stack\n");
    398       break;
    399 
    400     case DW_OP_xderef:
    401       // pop stack, dereference, push result
    402       value = *sp--;
    403       *sp = *((pint_t*)value);
    404       if (log)
    405         fprintf(stderr, "x-dereference 0x%" PRIx64 "\n", (uint64_t)value);
    406       break;
    407 
    408     case DW_OP_abs:
    409       svalue = (sint_t)*sp;
    410       if (svalue < 0)
    411         *sp = (pint_t)(-svalue);
    412       if (log)
    413         fprintf(stderr, "abs\n");
    414       break;
    415 
    416     case DW_OP_and:
    417       value = *sp--;
    418       *sp &= value;
    419       if (log)
    420         fprintf(stderr, "and\n");
    421       break;
    422 
    423     case DW_OP_div:
    424       svalue = (sint_t)(*sp--);
    425       svalue2 = (sint_t)*sp;
    426       *sp = (pint_t)(svalue2 / svalue);
    427       if (log)
    428         fprintf(stderr, "div\n");
    429       break;
    430 
    431     case DW_OP_minus:
    432       value = *sp--;
    433       *sp = *sp - value;
    434       if (log)
    435         fprintf(stderr, "minus\n");
    436       break;
    437 
    438     case DW_OP_mod:
    439       svalue = (sint_t)(*sp--);
    440       svalue2 = (sint_t)*sp;
    441       *sp = (pint_t)(svalue2 % svalue);
    442       if (log)
    443         fprintf(stderr, "module\n");
    444       break;
    445 
    446     case DW_OP_mul:
    447       svalue = (sint_t)(*sp--);
    448       svalue2 = (sint_t)*sp;
    449       *sp = (pint_t)(svalue2 * svalue);
    450       if (log)
    451         fprintf(stderr, "mul\n");
    452       break;
    453 
    454     case DW_OP_neg:
    455       *sp = 0 - *sp;
    456       if (log)
    457         fprintf(stderr, "neg\n");
    458       break;
    459 
    460     case DW_OP_not:
    461       svalue = (sint_t)(*sp);
    462       *sp = (pint_t)(~svalue);
    463       if (log)
    464         fprintf(stderr, "not\n");
    465       break;
    466 
    467     case DW_OP_or:
    468       value = *sp--;
    469       *sp |= value;
    470       if (log)
    471         fprintf(stderr, "or\n");
    472       break;
    473 
    474     case DW_OP_plus:
    475       value = *sp--;
    476       *sp += value;
    477       if (log)
    478         fprintf(stderr, "plus\n");
    479       break;
    480 
    481     case DW_OP_plus_uconst:
    482       // pop stack, add uelb128 constant, push result
    483       *sp += addressSpace.getULEB128(p, expressionEnd);
    484       if (log)
    485         fprintf(stderr, "add constant\n");
    486       break;
    487 
    488     case DW_OP_shl:
    489       value = *sp--;
    490       *sp = *sp << value;
    491       if (log)
    492         fprintf(stderr, "shift left\n");
    493       break;
    494 
    495     case DW_OP_shr:
    496       value = *sp--;
    497       *sp = *sp >> value;
    498       if (log)
    499         fprintf(stderr, "shift left\n");
    500       break;
    501 
    502     case DW_OP_shra:
    503       value = *sp--;
    504       svalue = (sint_t)*sp;
    505       *sp = (pint_t)(svalue >> value);
    506       if (log)
    507         fprintf(stderr, "shift left arithmetric\n");
    508       break;
    509 
    510     case DW_OP_xor:
    511       value = *sp--;
    512       *sp ^= value;
    513       if (log)
    514         fprintf(stderr, "xor\n");
    515       break;
    516 
    517     case DW_OP_skip:
    518       svalue = (int16_t) addressSpace.get16(p);
    519       p += 2;
    520       p = (pint_t)((sint_t)p + svalue);
    521       if (log)
    522         fprintf(stderr, "skip %" PRIu64 "\n", (uint64_t)svalue);
    523       break;
    524 
    525     case DW_OP_bra:
    526       svalue = (int16_t) addressSpace.get16(p);
    527       p += 2;
    528       if (*sp--)
    529         p = (pint_t)((sint_t)p + svalue);
    530       if (log)
    531         fprintf(stderr, "bra %" PRIu64 "\n", (uint64_t)svalue);
    532       break;
    533 
    534     case DW_OP_eq:
    535       value = *sp--;
    536       *sp = (*sp == value);
    537       if (log)
    538         fprintf(stderr, "eq\n");
    539       break;
    540 
    541     case DW_OP_ge:
    542       value = *sp--;
    543       *sp = (*sp >= value);
    544       if (log)
    545         fprintf(stderr, "ge\n");
    546       break;
    547 
    548     case DW_OP_gt:
    549       value = *sp--;
    550       *sp = (*sp > value);
    551       if (log)
    552         fprintf(stderr, "gt\n");
    553       break;
    554 
    555     case DW_OP_le:
    556       value = *sp--;
    557       *sp = (*sp <= value);
    558       if (log)
    559         fprintf(stderr, "le\n");
    560       break;
    561 
    562     case DW_OP_lt:
    563       value = *sp--;
    564       *sp = (*sp < value);
    565       if (log)
    566         fprintf(stderr, "lt\n");
    567       break;
    568 
    569     case DW_OP_ne:
    570       value = *sp--;
    571       *sp = (*sp != value);
    572       if (log)
    573         fprintf(stderr, "ne\n");
    574       break;
    575 
    576     case DW_OP_lit0:
    577     case DW_OP_lit1:
    578     case DW_OP_lit2:
    579     case DW_OP_lit3:
    580     case DW_OP_lit4:
    581     case DW_OP_lit5:
    582     case DW_OP_lit6:
    583     case DW_OP_lit7:
    584     case DW_OP_lit8:
    585     case DW_OP_lit9:
    586     case DW_OP_lit10:
    587     case DW_OP_lit11:
    588     case DW_OP_lit12:
    589     case DW_OP_lit13:
    590     case DW_OP_lit14:
    591     case DW_OP_lit15:
    592     case DW_OP_lit16:
    593     case DW_OP_lit17:
    594     case DW_OP_lit18:
    595     case DW_OP_lit19:
    596     case DW_OP_lit20:
    597     case DW_OP_lit21:
    598     case DW_OP_lit22:
    599     case DW_OP_lit23:
    600     case DW_OP_lit24:
    601     case DW_OP_lit25:
    602     case DW_OP_lit26:
    603     case DW_OP_lit27:
    604     case DW_OP_lit28:
    605     case DW_OP_lit29:
    606     case DW_OP_lit30:
    607     case DW_OP_lit31:
    608       value = static_cast<pint_t>(opcode - DW_OP_lit0);
    609       *(++sp) = value;
    610       if (log)
    611         fprintf(stderr, "push literal 0x%" PRIx64 "\n", (uint64_t)value);
    612       break;
    613 
    614     case DW_OP_reg0:
    615     case DW_OP_reg1:
    616     case DW_OP_reg2:
    617     case DW_OP_reg3:
    618     case DW_OP_reg4:
    619     case DW_OP_reg5:
    620     case DW_OP_reg6:
    621     case DW_OP_reg7:
    622     case DW_OP_reg8:
    623     case DW_OP_reg9:
    624     case DW_OP_reg10:
    625     case DW_OP_reg11:
    626     case DW_OP_reg12:
    627     case DW_OP_reg13:
    628     case DW_OP_reg14:
    629     case DW_OP_reg15:
    630     case DW_OP_reg16:
    631     case DW_OP_reg17:
    632     case DW_OP_reg18:
    633     case DW_OP_reg19:
    634     case DW_OP_reg20:
    635     case DW_OP_reg21:
    636     case DW_OP_reg22:
    637     case DW_OP_reg23:
    638     case DW_OP_reg24:
    639     case DW_OP_reg25:
    640     case DW_OP_reg26:
    641     case DW_OP_reg27:
    642     case DW_OP_reg28:
    643     case DW_OP_reg29:
    644     case DW_OP_reg30:
    645     case DW_OP_reg31:
    646       reg = static_cast<uint32_t>(opcode - DW_OP_reg0);
    647       *(++sp) = registers.getRegister((int)reg);
    648       if (log)
    649         fprintf(stderr, "push reg %d\n", reg);
    650       break;
    651 
    652     case DW_OP_regx:
    653       reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
    654       *(++sp) = registers.getRegister((int)reg);
    655       if (log)
    656         fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
    657       break;
    658 
    659     case DW_OP_breg0:
    660     case DW_OP_breg1:
    661     case DW_OP_breg2:
    662     case DW_OP_breg3:
    663     case DW_OP_breg4:
    664     case DW_OP_breg5:
    665     case DW_OP_breg6:
    666     case DW_OP_breg7:
    667     case DW_OP_breg8:
    668     case DW_OP_breg9:
    669     case DW_OP_breg10:
    670     case DW_OP_breg11:
    671     case DW_OP_breg12:
    672     case DW_OP_breg13:
    673     case DW_OP_breg14:
    674     case DW_OP_breg15:
    675     case DW_OP_breg16:
    676     case DW_OP_breg17:
    677     case DW_OP_breg18:
    678     case DW_OP_breg19:
    679     case DW_OP_breg20:
    680     case DW_OP_breg21:
    681     case DW_OP_breg22:
    682     case DW_OP_breg23:
    683     case DW_OP_breg24:
    684     case DW_OP_breg25:
    685     case DW_OP_breg26:
    686     case DW_OP_breg27:
    687     case DW_OP_breg28:
    688     case DW_OP_breg29:
    689     case DW_OP_breg30:
    690     case DW_OP_breg31:
    691       reg = static_cast<uint32_t>(opcode - DW_OP_breg0);
    692       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
    693       svalue += static_cast<sint_t>(registers.getRegister((int)reg));
    694       *(++sp) = (pint_t)(svalue);
    695       if (log)
    696         fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
    697       break;
    698 
    699     case DW_OP_bregx:
    700       reg = static_cast<uint32_t>(addressSpace.getULEB128(p, expressionEnd));
    701       svalue = (sint_t)addressSpace.getSLEB128(p, expressionEnd);
    702       svalue += static_cast<sint_t>(registers.getRegister((int)reg));
    703       *(++sp) = (pint_t)(svalue);
    704       if (log)
    705         fprintf(stderr, "push reg %d + 0x%" PRIx64 "\n", reg, (uint64_t)svalue);
    706       break;
    707 
    708     case DW_OP_fbreg:
    709       _LIBUNWIND_ABORT("DW_OP_fbreg not implemented");
    710       break;
    711 
    712     case DW_OP_piece:
    713       _LIBUNWIND_ABORT("DW_OP_piece not implemented");
    714       break;
    715 
    716     case DW_OP_deref_size:
    717       // pop stack, dereference, push result
    718       value = *sp--;
    719       switch (addressSpace.get8(p++)) {
    720       case 1:
    721         value = addressSpace.get8(value);
    722         break;
    723       case 2:
    724         value = addressSpace.get16(value);
    725         break;
    726       case 4:
    727         value = addressSpace.get32(value);
    728         break;
    729       case 8:
    730         value = (pint_t)addressSpace.get64(value);
    731         break;
    732       default:
    733         _LIBUNWIND_ABORT("DW_OP_deref_size with bad size");
    734       }
    735       *(++sp) = value;
    736       if (log)
    737         fprintf(stderr, "sized dereference 0x%" PRIx64 "\n", (uint64_t)value);
    738       break;
    739 
    740     case DW_OP_xderef_size:
    741     case DW_OP_nop:
    742     case DW_OP_push_object_addres:
    743     case DW_OP_call2:
    744     case DW_OP_call4:
    745     case DW_OP_call_ref:
    746     default:
    747       _LIBUNWIND_ABORT("dwarf opcode not implemented");
    748     }
    749 
    750   }
    751   if (log)
    752     fprintf(stderr, "expression evaluates to 0x%" PRIx64 "\n", (uint64_t)*sp);
    753   return *sp;
    754 }
    755 
    756 
    757 
    758 } // namespace libunwind
    759 
    760 #endif // __DWARF_INSTRUCTIONS_HPP__
    761