Home | History | Annotate | Line # | Download | only in libunwind
DwarfParser.hpp revision 1.3
      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 <cstdint>
     17 #include <cstdlib>
     18 
     19 #include "dwarf2.h"
     20 #include "AddressSpace.hpp"
     21 
     22 namespace _Unwind {
     23 
     24 /// CFI_Parser does basic parsing of a CFI (Call Frame Information) records.
     25 /// See Dwarf Spec for details:
     26 ///    http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
     27 ///
     28 template <typename A, typename R> class CFI_Parser {
     29 public:
     30   typedef typename A::pint_t pint_t;
     31 
     32   /// Information encoded in a CIE (Common Information Entry)
     33   struct CIE_Info {
     34     pint_t cieStart;
     35     pint_t cieLength;
     36     pint_t cieInstructions;
     37     pint_t personality;
     38     uint32_t codeAlignFactor;
     39     int dataAlignFactor;
     40     uint8_t pointerEncoding;
     41     uint8_t lsdaEncoding;
     42     uint8_t personalityEncoding;
     43     uint8_t personalityOffsetInCIE;
     44     bool isSignalFrame;
     45     bool fdesHaveAugmentationData;
     46   };
     47 
     48   /// Information about an FDE (Frame Description Entry)
     49   struct FDE_Info {
     50     pint_t fdeStart;
     51     pint_t fdeLength;
     52     pint_t fdeInstructions;
     53     pint_t pcStart;
     54     pint_t pcEnd;
     55     pint_t lsda;
     56   };
     57 
     58   /// Information about a frame layout and registers saved determined
     59   /// by "running" the DWARF FDE "instructions"
     60   enum {
     61     kMaxRegisterNumber = R::LAST_REGISTER + 1
     62   };
     63   enum RegisterSavedWhere {
     64     kRegisterUnused,
     65     kRegisterInCFA,
     66     kRegisterOffsetFromCFA,
     67     kRegisterInRegister,
     68     kRegisterAtExpression,
     69     kRegisterIsExpression,
     70   };
     71   struct RegisterLocation {
     72     RegisterSavedWhere location;
     73     int64_t value;
     74   };
     75   struct PrologInfo {
     76     uint32_t cfaRegister;
     77     int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset
     78     int64_t cfaExpression;     // CFA = expression
     79     uint32_t spExtraArgSize;
     80     uint32_t codeOffsetAtStackDecrement;
     81     RegisterLocation savedRegisters[kMaxRegisterNumber];
     82   };
     83 
     84   struct PrologInfoStackEntry {
     85     PrologInfoStackEntry(PrologInfoStackEntry *n, const PrologInfo &i)
     86         : next(n), info(i) {}
     87     PrologInfoStackEntry *next;
     88     PrologInfo info;
     89   };
     90 
     91   static void findPCRange(A &, pint_t, pint_t &, pint_t &);
     92 
     93   static bool decodeFDE(A &, pint_t, FDE_Info *, CIE_Info *,
     94                         unw_proc_info_t *ctx);
     95   static bool parseFDEInstructions(A &, const FDE_Info &, const CIE_Info &,
     96                                    pint_t, PrologInfo *, unw_proc_info_t *ctx);
     97 
     98   static bool parseCIE(A &, pint_t, CIE_Info *);
     99 
    100 private:
    101   static bool parseInstructions(A &, pint_t, pint_t, const CIE_Info &, pint_t,
    102                                 PrologInfoStackEntry *&, PrologInfo *,
    103                                 unw_proc_info_t *ctx);
    104 };
    105 
    106 ///
    107 /// Parse a FDE and return the last PC it covers.
    108 ///
    109 template <typename A, typename R>
    110 void CFI_Parser<A, R>::findPCRange(A &addressSpace, pint_t fde, pint_t &pcStart,
    111                                    pint_t &pcEnd) {
    112   pcStart = 0;
    113   pcEnd = 0;
    114   pint_t p = fde;
    115   uint64_t cfiLength = addressSpace.get32(p);
    116   p += 4;
    117   if (cfiLength == 0xffffffff) {
    118     // 0xffffffff means length is really the next 8 Bytes.
    119     cfiLength = addressSpace.get64(p);
    120     p += 8;
    121   }
    122   if (cfiLength == 0)
    123     return;
    124   uint32_t ciePointer = addressSpace.get32(p);
    125   if (ciePointer == 0)
    126     return;
    127   pint_t nextCFI = p + cfiLength;
    128   pint_t cieStart = p - ciePointer;
    129   typename CFI_Parser<A, R>::CIE_Info cieInfo;
    130   if (!parseCIE(addressSpace, cieStart, &cieInfo))
    131     return;
    132   p += 4;
    133   // Parse pc begin and range.
    134   pcStart = addressSpace.getEncodedP(p, nextCFI, cieInfo.pointerEncoding, NULL);
    135   pcEnd = pcStart + addressSpace.getEncodedP(
    136                         p, nextCFI, cieInfo.pointerEncoding & 0x0F, NULL);
    137 }
    138 
    139 ///
    140 /// Parse a FDE into a CIE_Info and an FDE_Info
    141 ///
    142 template <typename A, typename R>
    143 bool CFI_Parser<A, R>::decodeFDE(A &addressSpace, pint_t fdeStart,
    144                                  FDE_Info *fdeInfo, CIE_Info *cieInfo,
    145                                  unw_proc_info_t *ctx) {
    146   pint_t p = fdeStart;
    147   uint64_t cfiLength = addressSpace.get32(p);
    148   p += 4;
    149   if (cfiLength == 0xffffffff) {
    150     // 0xffffffff means length is really the next 8 Bytes.
    151     cfiLength = addressSpace.get64(p);
    152     p += 8;
    153   }
    154   if (cfiLength == 0)
    155     return false;
    156   uint32_t ciePointer = addressSpace.get32(p);
    157   if (ciePointer == 0)
    158     return false;
    159   pint_t nextCFI = p + cfiLength;
    160   pint_t cieStart = p - ciePointer;
    161   if (!parseCIE(addressSpace, cieStart, cieInfo))
    162     return false;
    163   p += 4;
    164   // Parse pc begin and range.
    165   pint_t pcStart =
    166       addressSpace.getEncodedP(p, nextCFI, cieInfo->pointerEncoding, ctx);
    167   pint_t pcRange = addressSpace.getEncodedP(
    168       p, nextCFI, cieInfo->pointerEncoding & 0x0F, ctx);
    169   // Parse rest of info.
    170   fdeInfo->lsda = 0;
    171   // Check for augmentation length
    172   if (cieInfo->fdesHaveAugmentationData) {
    173     uintptr_t augLen = addressSpace.getULEB128(p, nextCFI);
    174     pint_t endOfAug = p + augLen;
    175     if (cieInfo->lsdaEncoding != DW_EH_PE_omit) {
    176       // Peek at value (without indirection).  Zero means no LSDA.
    177       pint_t lsdaStart = p;
    178       if (addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding & 0x0F,
    179                                    ctx) != 0) {
    180         // Reset pointer and re-parse LSDA address.
    181         p = lsdaStart;
    182         fdeInfo->lsda =
    183             addressSpace.getEncodedP(p, nextCFI, cieInfo->lsdaEncoding, ctx);
    184       }
    185     }
    186     p = endOfAug;
    187   }
    188   fdeInfo->fdeStart = fdeStart;
    189   fdeInfo->fdeLength = nextCFI - fdeStart;
    190   fdeInfo->fdeInstructions = p;
    191   fdeInfo->pcStart = pcStart;
    192   fdeInfo->pcEnd = pcStart + pcRange;
    193   return true;
    194 }
    195 
    196 /// Extract info from a CIE
    197 template <typename A, typename R>
    198 bool CFI_Parser<A, R>::parseCIE(A &addressSpace, pint_t cie,
    199                                 CIE_Info *cieInfo) {
    200   cieInfo->pointerEncoding = 0;
    201   cieInfo->lsdaEncoding = DW_EH_PE_omit;
    202   cieInfo->personalityEncoding = 0;
    203   cieInfo->personalityOffsetInCIE = 0;
    204   cieInfo->personality = 0;
    205   cieInfo->codeAlignFactor = 0;
    206   cieInfo->dataAlignFactor = 0;
    207   cieInfo->isSignalFrame = false;
    208   cieInfo->fdesHaveAugmentationData = false;
    209   cieInfo->cieStart = cie;
    210   pint_t p = cie;
    211   uint64_t cieLength = addressSpace.get32(p);
    212   p += 4;
    213   pint_t cieContentEnd = p + cieLength;
    214   if (cieLength == 0xffffffff) {
    215     // 0xffffffff means length is really the next 8 Bytes.
    216     cieLength = addressSpace.get64(p);
    217     p += 8;
    218     cieContentEnd = p + cieLength;
    219   }
    220   if (cieLength == 0)
    221     return true;
    222   // CIE ID is always 0
    223   if (addressSpace.get32(p) != 0)
    224     return false;
    225   p += 4;
    226   // Version is always 1 or 3
    227   uint8_t version = addressSpace.get8(p);
    228   if (version != 1 && version != 3)
    229     return false;
    230   ++p;
    231   // Save start of augmentation string and find end.
    232   pint_t strStart = p;
    233   while (addressSpace.get8(p) != 0)
    234     ++p;
    235   ++p;
    236   // Parse code aligment factor
    237   cieInfo->codeAlignFactor = addressSpace.getULEB128(p, cieContentEnd);
    238   // Parse data alignment factor
    239   cieInfo->dataAlignFactor = addressSpace.getSLEB128(p, cieContentEnd);
    240   // Parse return address register
    241   addressSpace.getULEB128(p, cieContentEnd);
    242   // Parse augmentation data based on augmentation string.
    243   if (addressSpace.get8(strStart) == 'z') {
    244     // parse augmentation data length
    245     addressSpace.getULEB128(p, cieContentEnd);
    246     for (pint_t s = strStart; addressSpace.get8(s) != '\0'; ++s) {
    247       switch (addressSpace.get8(s)) {
    248       case 'z':
    249         cieInfo->fdesHaveAugmentationData = true;
    250         break;
    251       case 'P':
    252         cieInfo->personalityEncoding = addressSpace.get8(p);
    253         ++p;
    254         cieInfo->personalityOffsetInCIE = p - cie;
    255         cieInfo->personality = addressSpace.getEncodedP(
    256             p, cieContentEnd, cieInfo->personalityEncoding, NULL);
    257         break;
    258       case 'L':
    259         cieInfo->lsdaEncoding = addressSpace.get8(p);
    260         ++p;
    261         break;
    262       case 'R':
    263         cieInfo->pointerEncoding = addressSpace.get8(p);
    264         ++p;
    265         break;
    266       case 'S':
    267         cieInfo->isSignalFrame = true;
    268         break;
    269       default:
    270         // ignore unknown letters
    271         break;
    272       }
    273     }
    274   }
    275   cieInfo->cieLength = cieContentEnd - cieInfo->cieStart;
    276   cieInfo->cieInstructions = p;
    277   return true;
    278 }
    279 
    280 /// "Run" the dwarf instructions and create the abstact PrologInfo for an FDE.
    281 template <typename A, typename R>
    282 bool CFI_Parser<A, R>::parseFDEInstructions(A &addressSpace,
    283                                             const FDE_Info &fdeInfo,
    284                                             const CIE_Info &cieInfo,
    285                                             pint_t upToPC, PrologInfo *results,
    286                                             unw_proc_info_t *ctx) {
    287   // Clear results.
    288   memset(results, 0, sizeof(*results));
    289   PrologInfoStackEntry *rememberStack = NULL;
    290 
    291   // First parse the CIE then FDE instructions.
    292   if (!parseInstructions(addressSpace, cieInfo.cieInstructions,
    293                          cieInfo.cieStart + cieInfo.cieLength, cieInfo,
    294                          (pint_t)(-1), rememberStack, results, ctx))
    295     return false;
    296   return parseInstructions(addressSpace, fdeInfo.fdeInstructions,
    297                            fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo,
    298                            upToPC - fdeInfo.pcStart, rememberStack, results,
    299                            ctx);
    300 }
    301 
    302 /// "Run" the DWARF instructions.
    303 template <typename A, typename R>
    304 bool
    305 CFI_Parser<A, R>::parseInstructions(A &addressSpace, pint_t instructions,
    306                                     pint_t instructionsEnd,
    307                                     const CIE_Info &cieInfo, pint_t pcoffset,
    308                                     PrologInfoStackEntry *&rememberStack,
    309                                     PrologInfo *results, unw_proc_info_t *ctx) {
    310   pint_t p = instructions;
    311   uint32_t codeOffset = 0;
    312   PrologInfo initialState = *results;
    313 
    314   // See Dwarf Spec, section 6.4.2 for details on unwind opcodes.
    315   while (p < instructionsEnd && codeOffset < pcoffset) {
    316     uint64_t reg;
    317     uint64_t reg2;
    318     int64_t offset;
    319     uint64_t length;
    320     uint8_t opcode = addressSpace.get8(p);
    321     uint8_t operand;
    322     PrologInfoStackEntry *entry;
    323     ++p;
    324     switch (opcode) {
    325     case DW_CFA_nop:
    326       break;
    327     case DW_CFA_set_loc:
    328       codeOffset = addressSpace.getEncodedP(p, instructionsEnd,
    329                                             cieInfo.pointerEncoding, ctx);
    330       break;
    331     case DW_CFA_advance_loc1:
    332       codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor);
    333       p += 1;
    334       break;
    335     case DW_CFA_advance_loc2:
    336       codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor);
    337       p += 2;
    338       break;
    339     case DW_CFA_advance_loc4:
    340       codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor);
    341       p += 4;
    342       break;
    343     case DW_CFA_offset_extended:
    344       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
    345       offset =
    346           addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
    347       if (reg > kMaxRegisterNumber)
    348         return false;
    349       results->savedRegisters[reg].location = kRegisterInCFA;
    350       results->savedRegisters[reg].value = offset;
    351       break;
    352     case DW_CFA_restore_extended:
    353       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
    354       if (reg > kMaxRegisterNumber)
    355         return false;
    356       results->savedRegisters[reg] = initialState.savedRegisters[reg];
    357       break;
    358     case DW_CFA_undefined:
    359       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
    360       if (reg > kMaxRegisterNumber)
    361         return false;
    362       results->savedRegisters[reg].location = kRegisterUnused;
    363       break;
    364     case DW_CFA_same_value:
    365       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
    366       if (reg > kMaxRegisterNumber)
    367         return false;
    368       // "same value" means register was stored in frame, but its current
    369       // value has not changed, so no need to restore from frame.
    370       // We model this as if the register was never saved.
    371       results->savedRegisters[reg].location = kRegisterUnused;
    372       break;
    373     case DW_CFA_register:
    374       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
    375       reg2 = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
    376       if (reg > kMaxRegisterNumber)
    377         return false;
    378       if (reg2 > kMaxRegisterNumber)
    379         return false;
    380       results->savedRegisters[reg].location = kRegisterInRegister;
    381       results->savedRegisters[reg].value = reg2;
    382       break;
    383     case DW_CFA_remember_state:
    384       // avoid operator new, because that would be an upward dependency
    385       entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry));
    386       if (entry == NULL)
    387         return false;
    388 
    389       entry->next = rememberStack;
    390       entry->info = *results;
    391       rememberStack = entry;
    392       break;
    393     case DW_CFA_restore_state:
    394       if (rememberStack == NULL)
    395         return false;
    396       {
    397         PrologInfoStackEntry *top = rememberStack;
    398         *results = top->info;
    399         rememberStack = top->next;
    400         free((char *)top);
    401       }
    402       break;
    403     case DW_CFA_def_cfa:
    404       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
    405       offset = addressSpace.getULEB128(p, instructionsEnd);
    406       if (reg > kMaxRegisterNumber)
    407         return false;
    408       results->cfaRegister = reg;
    409       results->cfaRegisterOffset = offset;
    410       break;
    411     case DW_CFA_def_cfa_register:
    412       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
    413       if (reg > kMaxRegisterNumber)
    414         return false;
    415       results->cfaRegister = reg;
    416       break;
    417     case DW_CFA_def_cfa_offset:
    418       results->cfaRegisterOffset = addressSpace.getULEB128(p, instructionsEnd);
    419       results->codeOffsetAtStackDecrement = codeOffset;
    420       break;
    421     case DW_CFA_def_cfa_expression:
    422       results->cfaRegister = 0;
    423       results->cfaExpression = p;
    424       length = addressSpace.getULEB128(p, instructionsEnd);
    425       p += length;
    426       break;
    427     case DW_CFA_expression:
    428       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
    429       if (reg > kMaxRegisterNumber)
    430         return false;
    431       results->savedRegisters[reg].location = kRegisterAtExpression;
    432       results->savedRegisters[reg].value = p;
    433       length = addressSpace.getULEB128(p, instructionsEnd);
    434       p += length;
    435       break;
    436     case DW_CFA_offset_extended_sf:
    437       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
    438       if (reg > kMaxRegisterNumber)
    439         return false;
    440       offset =
    441           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
    442       results->savedRegisters[reg].location = kRegisterInCFA;
    443       results->savedRegisters[reg].value = offset;
    444       break;
    445     case DW_CFA_def_cfa_sf:
    446       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
    447       offset =
    448           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
    449       if (reg > kMaxRegisterNumber)
    450         return false;
    451       results->cfaRegister = reg;
    452       results->cfaRegisterOffset = offset;
    453       break;
    454     case DW_CFA_def_cfa_offset_sf:
    455       results->cfaRegisterOffset =
    456           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
    457       results->codeOffsetAtStackDecrement = codeOffset;
    458       break;
    459     case DW_CFA_val_offset:
    460       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
    461       offset =
    462           addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
    463       results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
    464       results->savedRegisters[reg].value = offset;
    465       break;
    466     case DW_CFA_val_offset_sf:
    467       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
    468       if (reg > kMaxRegisterNumber)
    469         return false;
    470       offset =
    471           addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
    472       results->savedRegisters[reg].location = kRegisterOffsetFromCFA;
    473       results->savedRegisters[reg].value = offset;
    474       break;
    475     case DW_CFA_val_expression:
    476       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
    477       if (reg > kMaxRegisterNumber)
    478         return false;
    479       results->savedRegisters[reg].location = kRegisterIsExpression;
    480       results->savedRegisters[reg].value = p;
    481       length = addressSpace.getULEB128(p, instructionsEnd);
    482       p += length;
    483       break;
    484     case DW_CFA_GNU_window_save:
    485 #if defined(__sparc__)
    486       for (reg = 8; reg < 16; ++reg) {
    487         results->savedRegisters[reg].location = kRegisterInRegister;
    488         results->savedRegisters[reg].value = reg + 16;
    489       }
    490       for (reg = 16; reg < 32; ++reg) {
    491         results->savedRegisters[reg].location = kRegisterInCFA;
    492         results->savedRegisters[reg].value = (reg - 16) * sizeof(typename R::reg_t);
    493       }
    494       break;
    495 #else
    496       return false;
    497 #endif
    498     case DW_CFA_GNU_args_size:
    499       offset = addressSpace.getULEB128(p, instructionsEnd);
    500       results->spExtraArgSize = offset;
    501       break;
    502     case DW_CFA_GNU_negative_offset_extended:
    503       reg = R::dwarf2regno(addressSpace.getULEB128(p, instructionsEnd));
    504       if (reg > kMaxRegisterNumber)
    505         return false;
    506       offset =
    507           addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor;
    508       results->savedRegisters[reg].location = kRegisterInCFA;
    509       results->savedRegisters[reg].value = -offset;
    510       break;
    511     default:
    512       operand = opcode & 0x3F;
    513       switch (opcode & 0xC0) {
    514       case DW_CFA_offset:
    515         reg = R::dwarf2regno(operand);
    516         if (reg > kMaxRegisterNumber)
    517           return false;
    518         offset = addressSpace.getULEB128(p, instructionsEnd) *
    519                  cieInfo.dataAlignFactor;
    520         results->savedRegisters[reg].location = kRegisterInCFA;
    521         results->savedRegisters[reg].value = offset;
    522         break;
    523       case DW_CFA_advance_loc:
    524         codeOffset += operand * cieInfo.codeAlignFactor;
    525         break;
    526       case DW_CFA_restore:
    527         reg = R::dwarf2regno(operand);
    528         if (reg > kMaxRegisterNumber)
    529           return false;
    530         results->savedRegisters[reg] = initialState.savedRegisters[reg];
    531         break;
    532       default:
    533         return false;
    534       }
    535     }
    536   }
    537 
    538   return true;
    539 }
    540 
    541 } // namespace _Unwind
    542 
    543 #endif // __DWARF_PARSER_HPP__
    544