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