LCOV - code coverage report
Current view: top level - lib/DebugInfo - DWARFDebugFrame.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 99 120 82.5 %
Date: 2015-01-30 11:55:44 Functions: 14 16 87.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "llvm/DebugInfo/DWARFDebugFrame.h"
      11             : #include "llvm/ADT/SmallString.h"
      12             : #include "llvm/Support/DataTypes.h"
      13             : #include "llvm/Support/Dwarf.h"
      14             : #include "llvm/Support/ErrorHandling.h"
      15             : #include "llvm/Support/Format.h"
      16             : #include "llvm/Support/raw_ostream.h"
      17             : #include <string>
      18             : #include <vector>
      19             : 
      20             : using namespace llvm;
      21             : using namespace dwarf;
      22             : 
      23             : 
      24             : /// \brief Abstract frame entry defining the common interface concrete
      25             : /// entries implement.
      26             : class llvm::FrameEntry {
      27             : public:
      28             :   enum FrameKind {FK_CIE, FK_FDE};
      29             :   FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length)
      30          39 :       : Kind(K), Offset(Offset), Length(Length) {}
      31             : 
      32          39 :   virtual ~FrameEntry() {
      33          39 :   }
      34             : 
      35             :   FrameKind getKind() const { return Kind; }
      36           0 :   virtual uint64_t getOffset() const { return Offset; }
      37             : 
      38             :   /// \brief Parse and store a sequence of CFI instructions from Data,
      39             :   /// starting at *Offset and ending at EndOffset. If everything
      40             :   /// goes well, *Offset should be equal to EndOffset when this method
      41             :   /// returns. Otherwise, an error occurred.
      42             :   virtual void parseInstructions(DataExtractor Data, uint32_t *Offset,
      43             :                                  uint32_t EndOffset);
      44             : 
      45             :   /// \brief Dump the entry header to the given output stream.
      46             :   virtual void dumpHeader(raw_ostream &OS) const = 0;
      47             : 
      48             :   /// \brief Dump the entry's instructions to the given output stream.
      49             :   virtual void dumpInstructions(raw_ostream &OS) const;
      50             : 
      51             : protected:
      52             :   const FrameKind Kind;
      53             : 
      54             :   /// \brief Offset of this entry in the section.
      55             :   uint64_t Offset;
      56             : 
      57             :   /// \brief Entry length as specified in DWARF.
      58             :   uint64_t Length;
      59             : 
      60             :   /// An entry may contain CFI instructions. An instruction consists of an
      61             :   /// opcode and an optional sequence of operands.
      62             :   typedef std::vector<uint64_t> Operands;
      63        1415 :   struct Instruction {
      64             :     Instruction(uint8_t Opcode)
      65         175 :       : Opcode(Opcode)
      66             :     {}
      67             : 
      68             :     uint8_t Opcode;
      69             :     Operands Ops;
      70             :   };
      71             : 
      72             :   std::vector<Instruction> Instructions;
      73             : 
      74             :   /// Convenience methods to add a new instruction with the given opcode and
      75             :   /// operands to the Instructions vector.
      76          86 :   void addInstruction(uint8_t Opcode) {
      77         258 :     Instructions.push_back(Instruction(Opcode));
      78          86 :   }
      79             : 
      80          45 :   void addInstruction(uint8_t Opcode, uint64_t Operand1) {
      81         135 :     Instructions.push_back(Instruction(Opcode));
      82          90 :     Instructions.back().Ops.push_back(Operand1);
      83          45 :   }
      84             : 
      85          44 :   void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
      86         132 :     Instructions.push_back(Instruction(Opcode));
      87          88 :     Instructions.back().Ops.push_back(Operand1);
      88          88 :     Instructions.back().Ops.push_back(Operand2);
      89          44 :   }
      90             : };
      91             : 
      92             : 
      93             : // See DWARF standard v3, section 7.23
      94             : const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
      95             : const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
      96             : 
      97          39 : void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset,
      98             :                                    uint32_t EndOffset) {
      99         253 :   while (*Offset < EndOffset) {
     100         175 :     uint8_t Opcode = Data.getU8(Offset);
     101             :     // Some instructions have a primary opcode encoded in the top bits.
     102         175 :     uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;
     103             : 
     104         175 :     if (Primary) {
     105             :       // If it's a primary opcode, the first operand is encoded in the bottom
     106             :       // bits of the opcode itself.
     107          46 :       uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
     108          46 :       switch (Primary) {
     109           0 :         default: llvm_unreachable("Impossible primary CFI opcode");
     110             :         case DW_CFA_advance_loc:
     111             :         case DW_CFA_restore:
     112          23 :           addInstruction(Primary, Op1);
     113          23 :           break;
     114             :         case DW_CFA_offset:
     115          23 :           addInstruction(Primary, Op1, Data.getULEB128(Offset));
     116          23 :           break;
     117             :       }
     118             :     } else {
     119             :       // Extended opcode - its value is Opcode itself.
     120         129 :       switch (Opcode) {
     121           0 :         default: llvm_unreachable("Invalid extended CFI opcode");
     122             :         case DW_CFA_nop:
     123             :         case DW_CFA_remember_state:
     124             :         case DW_CFA_restore_state:
     125             :         case DW_CFA_GNU_window_save:
     126             :           // No operands
     127          86 :           addInstruction(Opcode);
     128          86 :           break;
     129             :         case DW_CFA_set_loc:
     130             :           // Operands: Address
     131           0 :           addInstruction(Opcode, Data.getAddress(Offset));
     132           0 :           break;
     133             :         case DW_CFA_advance_loc1:
     134             :           // Operands: 1-byte delta
     135           0 :           addInstruction(Opcode, Data.getU8(Offset));
     136           0 :           break;
     137             :         case DW_CFA_advance_loc2:
     138             :           // Operands: 2-byte delta
     139           0 :           addInstruction(Opcode, Data.getU16(Offset));
     140           0 :           break;
     141             :         case DW_CFA_advance_loc4:
     142             :           // Operands: 4-byte delta
     143           0 :           addInstruction(Opcode, Data.getU32(Offset));
     144           0 :           break;
     145             :         case DW_CFA_restore_extended:
     146             :         case DW_CFA_undefined:
     147             :         case DW_CFA_same_value:
     148             :         case DW_CFA_def_cfa_register:
     149             :         case DW_CFA_def_cfa_offset:
     150             :           // Operands: ULEB128
     151          22 :           addInstruction(Opcode, Data.getULEB128(Offset));
     152          22 :           break;
     153             :         case DW_CFA_def_cfa_offset_sf:
     154             :           // Operands: SLEB128
     155           0 :           addInstruction(Opcode, Data.getSLEB128(Offset));
     156           0 :           break;
     157             :         case DW_CFA_offset_extended:
     158             :         case DW_CFA_register:
     159             :         case DW_CFA_def_cfa:
     160             :         case DW_CFA_val_offset:
     161             :           // Operands: ULEB128, ULEB128
     162             :           addInstruction(Opcode, Data.getULEB128(Offset),
     163          21 :                                  Data.getULEB128(Offset));
     164          21 :           break;
     165             :         case DW_CFA_offset_extended_sf:
     166             :         case DW_CFA_def_cfa_sf:
     167             :         case DW_CFA_val_offset_sf:
     168             :           // Operands: ULEB128, SLEB128
     169             :           addInstruction(Opcode, Data.getULEB128(Offset),
     170           0 :                                  Data.getSLEB128(Offset));
     171           0 :           break;
     172             :         case DW_CFA_def_cfa_expression:
     173             :         case DW_CFA_expression:
     174             :         case DW_CFA_val_expression:
     175             :           // TODO: implement this
     176           0 :           report_fatal_error("Values with expressions not implemented yet!");
     177             :       }
     178             :     }
     179             :   }
     180          39 : }
     181             : 
     182             : 
     183          39 : void FrameEntry::dumpInstructions(raw_ostream &OS) const {
     184             :   // TODO: at the moment only instruction names are dumped. Expand this to
     185             :   // dump operands as well.
     186         331 :   for (const auto &Instr : Instructions) {
     187         175 :     uint8_t Opcode = Instr.Opcode;
     188         175 :     if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
     189          46 :       Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
     190         175 :     OS << "  " << CallFrameString(Opcode) << ":\n";
     191             :   }
     192          39 : }
     193             : 
     194             : 
     195             : namespace {
     196             : /// \brief DWARF Common Information Entry (CIE)
     197             : class CIE : public FrameEntry {
     198             : public:
     199             :   // CIEs (and FDEs) are simply container classes, so the only sensible way to
     200             :   // create them is by providing the full parsed contents in the constructor.
     201             :   CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
     202             :       SmallString<8> Augmentation, uint64_t CodeAlignmentFactor,
     203             :       int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister)
     204             :       : FrameEntry(FK_CIE, Offset, Length), Version(Version),
     205             :         Augmentation(std::move(Augmentation)),
     206             :         CodeAlignmentFactor(CodeAlignmentFactor),
     207             :         DataAlignmentFactor(DataAlignmentFactor),
     208          57 :         ReturnAddressRegister(ReturnAddressRegister) {}
     209             : 
     210          57 :   ~CIE() {
     211          38 :   }
     212             : 
     213          19 :   void dumpHeader(raw_ostream &OS) const override {
     214             :     OS << format("%08x %08x %08x CIE",
     215          57 :                  (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID)
     216          19 :        << "\n";
     217          57 :     OS << format("  Version:               %d\n", Version);
     218          38 :     OS << "  Augmentation:          \"" << Augmentation << "\"\n";
     219             :     OS << format("  Code alignment factor: %u\n",
     220          57 :                  (uint32_t)CodeAlignmentFactor);
     221             :     OS << format("  Data alignment factor: %d\n",
     222          57 :                  (int32_t)DataAlignmentFactor);
     223             :     OS << format("  Return address column: %d\n",
     224          57 :                  (int32_t)ReturnAddressRegister);
     225          19 :     OS << "\n";
     226          19 :   }
     227             : 
     228             :   static bool classof(const FrameEntry *FE) {
     229             :     return FE->getKind() == FK_CIE;
     230             :   }
     231             : 
     232             : private:
     233             :   /// The following fields are defined in section 6.4.1 of the DWARF standard v3
     234             :   uint8_t Version;
     235             :   SmallString<8> Augmentation;
     236             :   uint64_t CodeAlignmentFactor;
     237             :   int64_t DataAlignmentFactor;
     238             :   uint64_t ReturnAddressRegister;
     239             : };
     240             : 
     241             : 
     242             : /// \brief DWARF Frame Description Entry (FDE)
     243             : class FDE : public FrameEntry {
     244             : public:
     245             :   // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
     246             :   // an offset to the CIE (provided by parsing the FDE header). The CIE itself
     247             :   // is obtained lazily once it's actually required.
     248             :   FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
     249             :       uint64_t InitialLocation, uint64_t AddressRange)
     250             :       : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
     251             :         InitialLocation(InitialLocation), AddressRange(AddressRange),
     252          40 :         LinkedCIE(nullptr) {}
     253             : 
     254          20 :   ~FDE() {
     255          20 :   }
     256             : 
     257          20 :   void dumpHeader(raw_ostream &OS) const override {
     258             :     OS << format("%08x %08x %08x FDE ",
     259          60 :                  (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset);
     260             :     OS << format("cie=%08x pc=%08x...%08x\n",
     261             :                  (int32_t)LinkedCIEOffset,
     262             :                  (uint32_t)InitialLocation,
     263          60 :                  (uint32_t)InitialLocation + (uint32_t)AddressRange);
     264          20 :     if (LinkedCIE) {
     265           0 :       OS << format("%p\n", LinkedCIE);
     266             :     }
     267          20 :   }
     268             : 
     269             :   static bool classof(const FrameEntry *FE) {
     270             :     return FE->getKind() == FK_FDE;
     271             :   }
     272             : 
     273             : private:
     274             :   /// The following fields are defined in section 6.4.1 of the DWARF standard v3
     275             :   uint64_t LinkedCIEOffset;
     276             :   uint64_t InitialLocation;
     277             :   uint64_t AddressRange;
     278             :   CIE *LinkedCIE;
     279             : };
     280             : } // end anonymous namespace
     281             : 
     282             : 
     283          95 : DWARFDebugFrame::DWARFDebugFrame() {
     284          95 : }
     285             : 
     286          95 : DWARFDebugFrame::~DWARFDebugFrame() {
     287          95 : }
     288             : 
     289             : static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
     290             :                                               uint32_t Offset, int Length) {
     291             :   errs() << "DUMP: ";
     292             :   for (int i = 0; i < Length; ++i) {
     293             :     uint8_t c = Data.getU8(&Offset);
     294             :     errs().write_hex(c); errs() << " ";
     295             :   }
     296             :   errs() << "\n";
     297             : }
     298             : 
     299             : 
     300          95 : void DWARFDebugFrame::parse(DataExtractor Data) {
     301          95 :   uint32_t Offset = 0;
     302             : 
     303         363 :   while (Data.isValidOffset(Offset)) {
     304          39 :     uint32_t StartOffset = Offset;
     305             : 
     306          39 :     bool IsDWARF64 = false;
     307          39 :     uint64_t Length = Data.getU32(&Offset);
     308             :     uint64_t Id;
     309             : 
     310          39 :     if (Length == UINT32_MAX) {
     311             :       // DWARF-64 is distinguished by the first 32 bits of the initial length
     312             :       // field being 0xffffffff. Then, the next 64 bits are the actual entry
     313             :       // length.
     314           0 :       IsDWARF64 = true;
     315           0 :       Length = Data.getU64(&Offset);
     316             :     }
     317             : 
     318             :     // At this point, Offset points to the next field after Length.
     319             :     // Length is the structure size excluding itself. Compute an offset one
     320             :     // past the end of the structure (needed to know how many instructions to
     321             :     // read).
     322             :     // TODO: For honest DWARF64 support, DataExtractor will have to treat
     323             :     //       offset_ptr as uint64_t*
     324          39 :     uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
     325             : 
     326             :     // The Id field's size depends on the DWARF format
     327          39 :     Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4);
     328          39 :     bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID);
     329             : 
     330          39 :     if (IsCIE) {
     331             :       // Note: this is specifically DWARFv3 CIE header structure. It was
     332             :       // changed in DWARFv4. We currently don't support reading DWARFv4
     333             :       // here because LLVM itself does not emit it (and LLDB doesn't
     334             :       // support it either).
     335          19 :       uint8_t Version = Data.getU8(&Offset);
     336          19 :       const char *Augmentation = Data.getCStr(&Offset);
     337          19 :       uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
     338          19 :       int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
     339          19 :       uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
     340             : 
     341             :       Entries.emplace_back(new CIE(StartOffset, Length, Version,
     342             :                                    StringRef(Augmentation), CodeAlignmentFactor,
     343          57 :                                    DataAlignmentFactor, ReturnAddressRegister));
     344             :     } else {
     345             :       // FDE
     346          20 :       uint64_t CIEPointer = Id;
     347          20 :       uint64_t InitialLocation = Data.getAddress(&Offset);
     348          20 :       uint64_t AddressRange = Data.getAddress(&Offset);
     349             : 
     350             :       Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
     351          40 :                                    InitialLocation, AddressRange));
     352             :     }
     353             : 
     354         117 :     Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);
     355             : 
     356          39 :     if (Offset != EndStructureOffset) {
     357             :       std::string Str;
     358             :       raw_string_ostream OS(Str);
     359           0 :       OS << format("Parsing entry instructions at %lx failed", StartOffset);
     360           0 :       report_fatal_error(Str);
     361             :     }
     362             :   }
     363          95 : }
     364             : 
     365             : 
     366          95 : void DWARFDebugFrame::dump(raw_ostream &OS) const {
     367          95 :   OS << "\n";
     368         419 :   for (const auto &Entry : Entries) {
     369          39 :     Entry->dumpHeader(OS);
     370          39 :     Entry->dumpInstructions(OS);
     371          39 :     OS << "\n";
     372             :   }
     373          95 : }
     374             : 

Generated by: LCOV version 1.11