Home | History | Annotate | Download | only in Unwind
      1 //===--------------------------- DwarfParser.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 //  Parses DWARF CFIs (FDEs and CIEs).
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef __DWARF_PARSER_HPP__
     14 #define __DWARF_PARSER_HPP__
     15 
     16 #include <stdint.h>
     17 #include <stdio.h>
     18 #include <stdlib.h>
     19 
     20 #include <vector>
     21 
     22 #include "libunwind.h"
     23 #include "dwarf2.h"
     24 
     25 #include "AddressSpace.hpp"
     26 
     27 namespace libunwind {
     28 
     29 /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
     30 /// See Dwarf Spec for details:
     31 ///    http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
     32 ///
     33 template <typename A>
     34 class CFI_Parser {
     35 public:
     36   typedef typename A::pint_t pint_t;
     37 
     38   /// Information encoded in a CIE (Common Information Entry)
     39   struct CIE_Info {
     40     pint_t    cieStart;
     41     pint_t    cieLength;
     42     pint_t    cieInstructions;
     43     uint8_t   pointerEncoding;
     44     uint8_t   lsdaEncoding;
     45     uint8_t   personalityEncoding;
     46     uint8_t   personalityOffsetInCIE;
     47     pint_t    personality;
     48     uint32_t  codeAlignFactor;
     49     int       dataAlignFactor;
     50     bool      isSignalFrame;
     51     bool      fdesHaveAugmentationData;
     52     uint8_t   returnAddressRegister;
     53   };
     54 
     55   /// Information about an FDE (Frame Description Entry)
     56   struct FDE_Info {
     57     pint_t  fdeStart;
     58     pint_t  fdeLength;
     59     pint_t  fdeInstructions;
     60     pint_t  pcStart;
     61     pint_t  pcEnd;
     62     pint_t  lsda;
     63   };
     64 
     65   enum {
     66     kMaxRegisterNumber = 120
     67   };
     68   enum RegisterSavedWhere {
     69     kRegisterUnused,
     70     kRegisterInCFA,
     71     kRegisterOffsetFromCFA,
     72     kRegisterInRegister,
     73     kRegisterAtExpression,
     74     kRegisterIsExpression
     75   };
     76   struct RegisterLocation {
     77     RegisterSavedWhere location;
     78     int64_t value;
     79   };
     80   /// Information about a frame layout and registers saved determined
     81   /// by "running" the dwarf FDE "instructions"
     82   struct PrologInfo {
     83     uint32_t          cfaRegister;
     84     int32_t           cfaRegisterOffset;  // CFA = (cfaRegister)+cfaRegisterOffset
     85     int64_t           cfaExpression;      // CFA = expression
     86     uint32_t          spExtraArgSize;
     87     uint32_t          codeOffsetAtStackDecrement;
     88     bool              registersInOtherRegisters;
     89     bool              sameValueUsed;
     90     RegisterLocation  savedRegisters[kMaxRegisterNumber];
     91   };
     92 
     93   struct PrologInfoStackEntry {
     94     PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i)
     95         : next(n), info(i) {}
     96     PrologInfoStackEntry *next;
     97     PrologInfo info;
     98   };
     99 
    100   static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
    101                       uint32_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo,
    102                       CIE_Info *cieInfo);
    103   static const char *decodeFDE(A &addressSpace, pint_t fdeStart,
    104                                FDE_Info *fdeInfo, CIE_Info *cieInfo);
    105   static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo,
    106                                    const CIE_Info &cieInfo, pint_t upToPC,
    107                                    PrologInfo *results);
    108 
    109   static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo);
    110 
    111 private:
    112   static bool parseInstructions(A &addressSpace, pint_t instructions,
    113                                 pint_t instructionsEnd, const CIE_Info &cieInfo,
    114                                 pint_t pcoffset,
    115                                 PrologInfoStackEntry *&rememberStack,
    116                                 PrologInfo *results);
    117 };
    118 
    119 /// Parse a FDE into a CIE_Info and an FDE_Info
    120 template <typename A>
    121 const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart,
    122                                      FDE_Info *fdeInfo, CIE_Info *cieInfo) {
    123   pint_t p = fdeStart;
    124   pint_t cfiLength = (pint_t)addressSpace.get32(p);
    125   p += 4;
    126   if (cfiLength == 0xffffffff) {
    127     // 0xffffffff means length is really next 8 bytes
    128     cfiLength = (pint_t)addressSpace.get64(p);
    129     p += 8;
    130   }
    131   if (cfiLength == 0)
    132     return "FDE has zero length"; // end marker
    133   uint32_t ciePointer = addressSpace.get32(p);
    134   if (ciePointer == 0)
    135     return "FDE is really a CIE"; // this is a CIE not an FDE
    136   pint_t nextCFI = p + cfiLength;
    137   pint_t cieStart = p - ciePointer;
    138   const char *err = parseCIE(addressSpace, cieStart, cieInfo);
    139   if (err != NULL)
    140     return err;
    141   p += 4;
    142   // parse pc begin and range
    143   pint_t pcStart =
    144       addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
    145   pint_t pcRange =
    146       addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding & 0x0F);
    147   // parse rest of info
    148   fdeInfo->lsda = 0;
    149   // check for augmentation length
    150   if (cieInfo->fdesHaveAugmentationData) {
    151     pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
    152     pint_t endOfAug = p + augLen;
    153     if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
    154       // peek at value (without indirection).  Zero means no lsda
    155       pint_t lsdaStart = p;
    156       if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F) !=
    157           0) {
    158         // reset pointer and re-parse lsda address
    159         p = lsdaStart;
    160         fdeInfo->lsda =
    161             addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
    162       }
    163     }
    164     p = endOfAug;
    165   }
    166   fdeInfo->fdeStart = fdeStart;
    167   fdeInfo->fdeLength = nextCFI - fdeStart;
    168   fdeInfo->fdeInstructions = p;
    169   fdeInfo->pcStart = pcStart;
    170   fdeInfo->pcEnd = pcStart + pcRange;
    171   return NULL; // success
    172 }
    173 
    174 /// Scan an eh_frame section to find an FDE for a pc
    175 template <typename A>
    176 bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart,
    177                             uint32_t sectionLength, pint_t fdeHint,
    178                             FDE_Info *fdeInfo, CIE_Info *cieInfo) {
    179   //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc);
    180   pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart;
    181   const pint_t ehSectionEnd = p + sectionLength;
    182   while (p < ehSectionEnd) {
    183     pint_t currentCFI = p;
    184     //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p);
    185     pint_t cfiLength = addressSpace.get32(p);
    186     p += 4;
    187     if (cfiLength == 0xffffffff) {
    188       // 0xffffffff means length is really next 8 bytes
    189       cfiLength = (pint_t)addressSpace.get64(p);
    190       p += 8;
    191     }
    192     if (cfiLength == 0)
    193       return false; // end marker
    194     uint32_t id = addressSpace.get32(p);
    195     if (id == 0) {
    196       // skip over CIEs
    197       p += cfiLength;
    198     } else {
    199       // process FDE to see if it covers pc
    200       pint_t nextCFI = p + cfiLength;
    201       uint32_t ciePointer = addressSpace.get32(p);
    202       pint_t cieStart = p - ciePointer;
    203       // validate pointer to CIE is within section
    204       if ((ehSectionStart <= cieStart) && (cieStart < ehSectionEnd)) {
    205         if (parseCIE(addressSpace, cieStart, cieInfo) == NULL) {
    206           p += 4;
    207           // parse pc begin and range
    208           pint_t pcStart =
    209               addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding);
    210           pint_t pcRange = addressSpace.getEncodedP(
    211               p, nextCFI, cieInfo->pointerEncoding & 0x0F);
    212           // test if pc is within the function this FDE covers
    213           if ((pcStart < pc) && (pc <= pcStart + pcRange)) {
    214             // parse rest of info
    215             fdeInfo->lsda = 0;
    216             // check for augmentation length
    217             if (cieInfo->fdesHaveAugmentationData) {
    218               pint_t augLen = (pint_t)addressSpace.getULEB128(p, nextCFI);
    219               pint_t endOfAug = p + augLen;
    220               if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
    221                 // peek at value (without indirection).  Zero means no lsda
    222                 pint_t lsdaStart = p;
    223                 if (addressSpace.getEncodedP(
    224                         p, nextCFI, cieInfo->lsdaEncoding & 0x0F) != 0) {
    225                   // reset pointer and re-parse lsda address
    226                   p = lsdaStart;
    227                   fdeInfo->lsda = addressSpace
    228                       .getEncodedP(p, nextCFI, cieInfo->lsdaEncoding);
    229                 }
    230               }
    231               p = endOfAug;
    232             }
    233             fdeInfo->fdeStart = currentCFI;
    234             fdeInfo->fdeLength = nextCFI - currentCFI;
    235             fdeInfo->fdeInstructions = p;
    236             fdeInfo->pcStart = pcStart;
    237             fdeInfo->pcEnd = pcStart + pcRange;
    238             return true;
    239           } else {
    240             // pc is not in begin/range, skip this FDE
    241           }
    242         } else {
    243           // malformed CIE, now augmentation describing pc range encoding
    244         }
    245       } else {
    246         // malformed FDE.  CIE is bad
    247       }
    248       p = nextCFI;
    249     }
    250   }
    251   return false;
    252 }
    253 
    254 /// Extract info from a CIE
    255 template <typename A>
    256 const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
    257                                     CIE_Info *cieInfo) {
    258   cieInfo->pointerEncoding = 0;
    259   cieInfo->lsdaEncoding = DW_EH_PE_omit;
    260   cieInfo->personalityEncoding = 0;
    261   cieInfo->personalityOffsetInCIE = 0;
    262   cieInfo->personality = 0;
    263   cieInfo->codeAlignFactor = 0;
    264   cieInfo->dataAlignFactor = 0;
    265   cieInfo->isSignalFrame = false;
    266   cieInfo->fdesHaveAugmentationData = false;
    267   cieInfo->cieStart = cie;
    268   pint_t p = cie;
    269   pint_t cieLength = (pint_t)addressSpace.get32(p);
    270   p += 4;
    271   pint_t cieContentEnd = p + cieLength;
    272   if (cieLength == 0xffffffff) {
    273     // 0xffffffff means length is really next 8 bytes
    274     cieLength = (pint_t)addressSpace.get64(p);
    275     p += 8;
    276     cieContentEnd = p + cieLength;
    277   }
    278   if (cieLength == 0)
    279     return NULL;
    280   // CIE ID is always 0
    281   if (addressSpace.get32(p) != 0)
    282     return "CIE ID is not zero";
    283   p += 4;
    284   // Version is always 1 or 3
    285   uint8_t version = addressSpace.get8(p);
    286   if ((version != 1) && (version != 3))
    287     return "CIE version is not 1 or 3";
    288   ++p;
    289   // save start of augmentation string and find end
    290   pint_t strStart = p;
    291   while (addressSpace.get8(p) != 0)
    292     ++p;
    293   ++p;
    294   // parse code aligment factor
    295   cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd);
    296   // parse data alignment factor
    297   cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd);
    298   // parse return address register
    299   uint64_t raReg = addressSpace.getULEB128(p, cieContentEnd);
    300   assert(raReg < 255 && "return address register too large");
    301   cieInfo->returnAddressRegister = (uint8_t)raReg;
    302   // parse augmentation data based on augmentation string
    303   const char *result = NULL;
    304   if (addressSpace.get8(strStart) == 'z') {
    305     // parse augmentation data length
    306     addressSpace.getULEB128(p, cieContentEnd);
    307     for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) {
    308       switch (addressSpace.get8(s)) {
    309       case 'z':
    310         cieInfo->fdesHaveAugmentationData = true;
    311         break;
    312       case 'P':
    313         cieInfo->personalityEncoding = addressSpace.get8(p);
    314         ++p;
    315         cieInfo->personalityOffsetInCIE = (uint8_t)(p - cie);
    316         cieInfo->personality = addressSpace
    317             .getEncodedP(p, cieContentEnd, cieInfo->personalityEncoding);
    318         break;
    319       case 'L':
    320         cieInfo->lsdaEncoding = addressSpace.get8(p);
    321         ++p;
    322         break;
    323       case 'R':
    324         cieInfo->pointerEncoding = addressSpace.get8(p);
    325         ++p;
    326         break;
    327       case 'S':
    328         cieInfo->isSignalFrame = true;
    329         break;
    330       default:
    331         // ignore unknown letters
    332         break;
    333       }
    334     }
    335   }
    336   cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
    337   cieInfo->cieInstructions = p;
    338   return result;
    339 }
    340 
    341 
    342 /// "run" the dwarf instructions and create the abstact PrologInfo for an FDE
    343 template <typename A>
    344 bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
    345                                          const FDE_Info &fdeInfo,
    346                                          const CIE_Info &cieInfo, pint_t upToPC,
    347                                          PrologInfo *results) {
    348   // clear results
    349   bzero(results, sizeof(PrologInfo));
    350   PrologInfoStackEntry *rememberStack = NULL;
    351 
    352   // parse CIE then FDE instructions
    353   return parseInstructions(addressSpace, cieInfo.cieInstructions,
    354                            cieInfo.cieStart + cieInfo.cieLength, cieInfo,
    355                            (pint_t)(-1), rememberStack, results) &&
    356          parseInstructions(addressSpace, fdeInfo.fdeInstructions,
    357                            fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo,
    358                            upToPC - fdeInfo.pcStart, rememberStack, results);
    359 }
    360 
    361 /// "run" the dwarf instructions
    362 template <typename A>
    363 bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions,
    364                                       pint_t instructionsEnd,
    365                                       const CIE_Info &cieInfo, pint_t pcoffset,
    366                                       PrologInfoStackEntry *&rememberStack,
    367                                       PrologInfo *results) {
    368   const bool logDwarf = false;
    369   pint_t p = instructions;
    370   pint_t codeOffset = 0;
    371   PrologInfo initialState = *results;
    372   if (logDwarf)
    373     fprintf(stderr, "parseInstructions(instructions=0x%0llX)\n",
    374             (uint64_t) instructionsEnd);
    375 
    376   // see Dwarf Spec, section 6.4.2 for details on unwind opcodes
    377   while ((p < instructionsEnd) && (codeOffset < pcoffset)) {
    378     uint64_t reg;
    379     uint64_t reg2;
    380     int64_t offset;
    381     uint64_t length;
    382     uint8_t opcode = addressSpace.get8(p);
    383     uint8_t operand;
    384     PrologInfoStackEntry *entry;
    385     ++p;
    386     switch (opcode) {
    387     case DW_CFA_nop:
    388       if (logDwarf)
    389         fprintf(stderr, "DW_CFA_nop\n");
    390       break;
    391     case DW_CFA_set_loc:
    392       codeOffset =
    393           addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding);
    394       if (logDwarf)
    395         fprintf(stderr, "DW_CFA_set_loc\n");
    396       break;
    397     case DW_CFA_advance_loc1:
    398       codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
    399       p += 1;
    400       if (logDwarf)
    401         fprintf(stderr, "DW_CFA_advance_loc1: new offset=%llu\n",
    402                         (uint64_t)codeOffset);
    403       break;
    404     case DW_CFA_advance_loc2:
    405       codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
    406       p += 2;
    407       if (logDwarf)
    408         fprintf(stderr, "DW_CFA_advance_loc2: new offset=%llu\n",
    409                         (uint64_t)codeOffset);
    410       break;
    411     case DW_CFA_advance_loc4:
    412       codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
    413       p += 4;
    414       if (logDwarf)
    415         fprintf(stderr, "DW_CFA_advance_loc4: new offset=%llu\n",
    416                         (uint64_t)codeOffset);
    417       break;
    418     case DW_CFA_offset_extended:
    419       reg = addressSpace.getULEB128(p, instructionsEnd);
    420       offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
    421                                                   * cieInfo.dataAlignFactor;
    422       if (reg > kMaxRegisterNumber) {
    423         fprintf(stderr,
    424                 "malformed DW_CFA_offset_extended dwarf unwind, reg too big\n");
    425         return false;
    426       }
    427       results->savedRegisters[reg].location = kRegisterInCFA;
    428       results->savedRegisters[reg].value = offset;
    429       if (logDwarf)
    430         fprintf(stderr, "DW_CFA_offset_extended(reg=%lld, offset=%lld)\n", reg,
    431                 offset);
    432       break;
    433     case DW_CFA_restore_extended:
    434       reg = addressSpace.getULEB128(p, instructionsEnd);
    435       ;
    436       if (reg > kMaxRegisterNumber) {
    437         fprintf(
    438             stderr,
    439             "malformed DW_CFA_restore_extended dwarf unwind, reg too big\n");
    440         return false;
    441       }
    442       results->savedRegisters[reg] = initialState.savedRegisters[reg];
    443       if (logDwarf)
    444         fprintf(stderr, "DW_CFA_restore_extended(reg=%lld)\n", reg);
    445       break;
    446     case DW_CFA_undefined:
    447       reg = addressSpace.getULEB128(p, instructionsEnd);
    448       if (reg > kMaxRegisterNumber) {
    449         fprintf(stderr,
    450                 "malformed DW_CFA_undefined dwarf unwind, reg too big\n");
    451         return false;
    452       }
    453       results->savedRegisters[reg].location = kRegisterUnused;
    454       if (logDwarf)
    455         fprintf(stderr, "DW_CFA_undefined(reg=%lld)\n", reg);
    456       break;
    457     case DW_CFA_same_value:
    458       reg = addressSpace.getULEB128(p, instructionsEnd);
    459       if (reg > kMaxRegisterNumber) {
    460         fprintf(stderr,
    461                 "malformed DW_CFA_same_value dwarf unwind, reg too big\n");
    462         return false;
    463       }
    464       // <rdar://problem/8456377> DW_CFA_same_value unsupported
    465       // "same value" means register was stored in frame, but its current
    466       // value has not changed, so no need to restore from frame.
    467       // We model this as if the register was never saved.
    468       results->savedRegisters[reg].location = kRegisterUnused;
    469       // set flag to disable conversion to compact unwind
    470       results->sameValueUsed = true;
    471       if (logDwarf)
    472         fprintf(stderr, "DW_CFA_same_value(reg=%lld)\n", reg);
    473       break;
    474     case DW_CFA_register:
    475       reg = addressSpace.getULEB128(p, instructionsEnd);
    476       reg2 = addressSpace.getULEB128(p, instructionsEnd);
    477       if (reg > kMaxRegisterNumber) {
    478         fprintf(stderr,
    479                 "malformed DW_CFA_register dwarf unwind, reg too big\n");
    480         return false;
    481       }
    482       if (reg2 > kMaxRegisterNumber) {
    483         fprintf(stderr,
    484                 "malformed DW_CFA_register dwarf unwind, reg2 too big\n");
    485         return false;
    486       }
    487       results->savedRegisters[reg].location = kRegisterInRegister;
    488       results->savedRegisters[reg].value = (int64_t)reg2;
    489       // set flag to disable conversion to compact unwind
    490       results->registersInOtherRegisters = true;
    491       if (logDwarf)
    492         fprintf(stderr, "DW_CFA_register(reg=%lld, reg2=%lld)\n", reg, reg2);
    493       break;
    494     case DW_CFA_remember_state:
    495       // avoid operator new, because that would be an upward dependency
    496       entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry));
    497       if (entry != NULL) {
    498         entry->next = rememberStack;
    499         entry->info = *results;
    500         rememberStack = entry;
    501       } else {
    502         return false;
    503       }
    504       if (logDwarf)
    505         fprintf(stderr, "DW_CFA_remember_state\n");
    506       break;
    507     case DW_CFA_restore_state:
    508       if (rememberStack != NULL) {
    509         PrologInfoStackEntry *top = rememberStack;
    510         *results = top->info;
    511         rememberStack = top->next;
    512         free((char *)top);
    513       } else {
    514         return false;
    515       }
    516       if (logDwarf)
    517         fprintf(stderr, "DW_CFA_restore_state\n");
    518       break;
    519     case DW_CFA_def_cfa:
    520       reg = addressSpace.getULEB128(p, instructionsEnd);
    521       offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd);
    522       if (reg > kMaxRegisterNumber) {
    523         fprintf(stderr, "malformed DW_CFA_def_cfa dwarf unwind, reg too big\n");
    524         return false;
    525       }
    526       results->cfaRegister = (uint32_t)reg;
    527       results->cfaRegisterOffset = (int32_t)offset;
    528       if (logDwarf)
    529         fprintf(stderr, "DW_CFA_def_cfa(reg=%lld, offset=%lld)\n", reg, offset);
    530       break;
    531     case DW_CFA_def_cfa_register:
    532       reg = addressSpace.getULEB128(p, instructionsEnd);
    533       if (reg > kMaxRegisterNumber) {
    534         fprintf(
    535             stderr,
    536             "malformed DW_CFA_def_cfa_register dwarf unwind, reg too big\n");
    537         return false;
    538       }
    539       results->cfaRegister = (uint32_t)reg;
    540       if (logDwarf)
    541         fprintf(stderr, "DW_CFA_def_cfa_register(%lld)\n", reg);
    542       break;
    543     case DW_CFA_def_cfa_offset:
    544       results->cfaRegisterOffset = (int32_t)
    545                                   addressSpace.getULEB128(p, instructionsEnd);
    546       results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
    547       if (logDwarf)
    548         fprintf(stderr, "DW_CFA_def_cfa_offset(%d)\n",
    549                 results->cfaRegisterOffset);
    550       break;
    551     case DW_CFA_def_cfa_expression:
    552       results->cfaRegister = 0;
    553       results->cfaExpression = (int64_t)p;
    554       length = addressSpace.getULEB128(p, instructionsEnd);
    555       p += length;
    556       if (logDwarf)
    557         fprintf(stderr,
    558                 "DW_CFA_def_cfa_expression(expression=0x%llX, length=%llu)\n",
    559                 results->cfaExpression, length);
    560       break;
    561     case DW_CFA_expression:
    562       reg = addressSpace.getULEB128(p, instructionsEnd);
    563       if (reg > kMaxRegisterNumber) {
    564         fprintf(stderr,
    565                 "malformed DW_CFA_expression dwarf unwind, reg too big\n");
    566         return false;
    567       }
    568       results->savedRegisters[reg].location = kRegisterAtExpression;
    569       results->savedRegisters[reg].value = (int64_t)p;
    570       length = addressSpace.getULEB128(p, instructionsEnd);
    571       p += length;
    572       if (logDwarf)
    573         fprintf(stderr,
    574                 "DW_CFA_expression(reg=%lld, expression=0x%llX, length=%llu)\n",
    575                 reg, results->savedRegisters[reg].value, length);
    576       break;
    577     case DW_CFA_offset_extended_sf:
    578       reg = addressSpace.getULEB128(p, instructionsEnd);
    579       if (reg > kMaxRegisterNumber) {
    580         fprintf(
    581             stderr,
    582             "malformed DW_CFA_offset_extended_sf dwarf unwind, reg too big\n");
    583         return false;
    584       }
    585       offset =
    586           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
    587       results->savedRegisters[reg].location = kRegisterInCFA;
    588       results->savedRegisters[reg].value = offset;
    589       if (logDwarf)
    590         fprintf(stderr, "DW_CFA_offset_extended_sf(reg=%lld, offset=%lld)\n",
    591                 reg, offset);
    592       break;
    593     case DW_CFA_def_cfa_sf:
    594       reg = addressSpace.getULEB128(p, instructionsEnd);
    595       offset =
    596           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
    597       if (reg > kMaxRegisterNumber) {
    598         fprintf(stderr,
    599                 "malformed DW_CFA_def_cfa_sf dwarf unwind, reg too big\n");
    600         return false;
    601       }
    602       results->cfaRegister = (uint32_t)reg;
    603       results->cfaRegisterOffset = (int32_t)offset;
    604       if (logDwarf)
    605         fprintf(stderr, "DW_CFA_def_cfa_sf(reg=%lld, offset=%lld)\n", reg,
    606                 offset);
    607       break;
    608     case DW_CFA_def_cfa_offset_sf:
    609       results->cfaRegisterOffset = (int32_t)
    610         (addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor);
    611       results->codeOffsetAtStackDecrement = (uint32_t)codeOffset;
    612       if (logDwarf)
    613         fprintf(stderr, "DW_CFA_def_cfa_offset_sf(%d)\n",
    614                 results->cfaRegisterOffset);
    615       break;
    616     case DW_CFA_val_offset:
    617       reg = addressSpace.getULEB128(p, instructionsEnd);
    618       offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
    619                                                     * cieInfo.dataAlignFactor;
    620       results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
    621       results->savedRegisters[reg].value = offset;
    622       if (logDwarf)
    623         fprintf(stderr, "DW_CFA_val_offset(reg=%lld, offset=%lld\n", reg,
    624                 offset);
    625       break;
    626     case DW_CFA_val_offset_sf:
    627       reg = addressSpace.getULEB128(p, instructionsEnd);
    628       if (reg > kMaxRegisterNumber) {
    629         fprintf(stderr,
    630                 "malformed DW_CFA_val_offset_sf dwarf unwind, reg too big\n");
    631         return false;
    632       }
    633       offset =
    634           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
    635       results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
    636       results->savedRegisters[reg].value = offset;
    637       if (logDwarf)
    638         fprintf(stderr, "DW_CFA_val_offset_sf(reg=%lld, offset=%lld\n", reg,
    639                 offset);
    640       break;
    641     case DW_CFA_val_expression:
    642       reg = addressSpace.getULEB128(p, instructionsEnd);
    643       if (reg > kMaxRegisterNumber) {
    644         fprintf(stderr,
    645                 "malformed DW_CFA_val_expression dwarf unwind, reg too big\n");
    646         return false;
    647       }
    648       results->savedRegisters[reg].location = kRegisterIsExpression;
    649       results->savedRegisters[reg].value = (int64_t)p;
    650       length = addressSpace.getULEB128(p, instructionsEnd);
    651       p += length;
    652       if (logDwarf)
    653         fprintf(
    654             stderr,
    655             "DW_CFA_val_expression(reg=%lld, expression=0x%llX, length=%lld)\n",
    656             reg, results->savedRegisters[reg].value, length);
    657       break;
    658     case DW_CFA_GNU_args_size:
    659       length = addressSpace.getULEB128(p, instructionsEnd);
    660       results->spExtraArgSize = (uint32_t)length;
    661       if (logDwarf)
    662         fprintf(stderr, "DW_CFA_GNU_args_size(%lld)\n", length);
    663       break;
    664     case DW_CFA_GNU_negative_offset_extended:
    665       reg = addressSpace.getULEB128(p, instructionsEnd);
    666       if (reg > kMaxRegisterNumber) {
    667         fprintf(stderr, "malformed DW_CFA_GNU_negative_offset_extended dwarf "
    668                         "unwind, reg too big\n");
    669         return false;
    670       }
    671       offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
    672                                                     * cieInfo.dataAlignFactor;
    673       results->savedRegisters[reg].location = kRegisterInCFA;
    674       results->savedRegisters[reg].value = -offset;
    675       if (logDwarf)
    676         fprintf(stderr, "DW_CFA_GNU_negative_offset_extended(%lld)\n", offset);
    677       break;
    678     default:
    679       operand = opcode & 0x3F;
    680       switch (opcode & 0xC0) {
    681       case DW_CFA_offset:
    682         reg = operand;
    683         offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd)
    684                                                     * cieInfo.dataAlignFactor;
    685         results->savedRegisters[reg].location = kRegisterInCFA;
    686         results->savedRegisters[reg].value = offset;
    687         if (logDwarf)
    688           fprintf(stderr, "DW_CFA_offset(reg=%d, offset=%lld)\n", operand,
    689                   offset);
    690         break;
    691       case DW_CFA_advance_loc:
    692         codeOffset += operand * cieInfo.codeAlignFactor;
    693         if (logDwarf)
    694           fprintf(stderr, "DW_CFA_advance_loc: new offset=%llu\n",
    695                                                       (uint64_t)codeOffset);
    696         break;
    697       case DW_CFA_restore:
    698         reg = operand;
    699         results->savedRegisters[reg] = initialState.savedRegisters[reg];
    700         if (logDwarf)
    701           fprintf(stderr, "DW_CFA_restore(reg=%lld)\n", reg);
    702         break;
    703       default:
    704         if (logDwarf)
    705           fprintf(stderr, "unknown CFA opcode 0x%02X\n", opcode);
    706         return false;
    707       }
    708     }
    709   }
    710 
    711   return true;
    712 }
    713 
    714 } // namespace libunwind
    715 
    716 #endif // __DWARF_PARSER_HPP__
    717