LLVM API Documentation

DWARFDebugFrame.cpp
Go to the documentation of this file.
00001 //===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "DWARFDebugFrame.h"
00011 #include "llvm/ADT/SmallString.h"
00012 #include "llvm/Support/DataTypes.h"
00013 #include "llvm/Support/Dwarf.h"
00014 #include "llvm/Support/ErrorHandling.h"
00015 #include "llvm/Support/Format.h"
00016 #include "llvm/Support/raw_ostream.h"
00017 #include <string>
00018 #include <vector>
00019 
00020 using namespace llvm;
00021 using namespace dwarf;
00022 
00023 
00024 /// \brief Abstract frame entry defining the common interface concrete
00025 /// entries implement.
00026 class llvm::FrameEntry {
00027 public:
00028   enum FrameKind {FK_CIE, FK_FDE};
00029   FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length)
00030       : Kind(K), Offset(Offset), Length(Length) {}
00031 
00032   virtual ~FrameEntry() {
00033   }
00034 
00035   FrameKind getKind() const { return Kind; }
00036   virtual uint64_t getOffset() const { return Offset; }
00037 
00038   /// \brief Parse and store a sequence of CFI instructions from Data,
00039   /// starting at *Offset and ending at EndOffset. If everything
00040   /// goes well, *Offset should be equal to EndOffset when this method
00041   /// returns. Otherwise, an error occurred.
00042   virtual void parseInstructions(DataExtractor Data, uint32_t *Offset,
00043                                  uint32_t EndOffset);
00044 
00045   /// \brief Dump the entry header to the given output stream.
00046   virtual void dumpHeader(raw_ostream &OS) const = 0;
00047 
00048   /// \brief Dump the entry's instructions to the given output stream.
00049   virtual void dumpInstructions(raw_ostream &OS) const;
00050 
00051 protected:
00052   const FrameKind Kind;
00053 
00054   /// \brief Offset of this entry in the section.
00055   uint64_t Offset;
00056 
00057   /// \brief Entry length as specified in DWARF.
00058   uint64_t Length;
00059 
00060   /// An entry may contain CFI instructions. An instruction consists of an
00061   /// opcode and an optional sequence of operands.
00062   typedef std::vector<uint64_t> Operands;
00063   struct Instruction {
00064     Instruction(uint8_t Opcode)
00065       : Opcode(Opcode)
00066     {}
00067 
00068     uint8_t Opcode;
00069     Operands Ops;
00070   };
00071 
00072   std::vector<Instruction> Instructions;
00073 
00074   /// Convenience methods to add a new instruction with the given opcode and
00075   /// operands to the Instructions vector.
00076   void addInstruction(uint8_t Opcode) {
00077     Instructions.push_back(Instruction(Opcode));
00078   }
00079 
00080   void addInstruction(uint8_t Opcode, uint64_t Operand1) {
00081     Instructions.push_back(Instruction(Opcode));
00082     Instructions.back().Ops.push_back(Operand1);
00083   }
00084 
00085   void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
00086     Instructions.push_back(Instruction(Opcode));
00087     Instructions.back().Ops.push_back(Operand1);
00088     Instructions.back().Ops.push_back(Operand2);
00089   }
00090 };
00091 
00092 
00093 // See DWARF standard v3, section 7.23
00094 const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
00095 const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
00096 
00097 void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset,
00098                                    uint32_t EndOffset) {
00099   while (*Offset < EndOffset) {
00100     uint8_t Opcode = Data.getU8(Offset);
00101     // Some instructions have a primary opcode encoded in the top bits.
00102     uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;
00103 
00104     if (Primary) {
00105       // If it's a primary opcode, the first operand is encoded in the bottom
00106       // bits of the opcode itself.
00107       uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
00108       switch (Primary) {
00109         default: llvm_unreachable("Impossible primary CFI opcode");
00110         case DW_CFA_advance_loc:
00111         case DW_CFA_restore:
00112           addInstruction(Primary, Op1);
00113           break;
00114         case DW_CFA_offset:
00115           addInstruction(Primary, Op1, Data.getULEB128(Offset));
00116           break;
00117       }
00118     } else {
00119       // Extended opcode - its value is Opcode itself.
00120       switch (Opcode) {
00121         default: llvm_unreachable("Invalid extended CFI opcode");
00122         case DW_CFA_nop:
00123         case DW_CFA_remember_state:
00124         case DW_CFA_restore_state:
00125         case DW_CFA_GNU_window_save:
00126           // No operands
00127           addInstruction(Opcode);
00128           break;
00129         case DW_CFA_set_loc:
00130           // Operands: Address
00131           addInstruction(Opcode, Data.getAddress(Offset));
00132           break;
00133         case DW_CFA_advance_loc1:
00134           // Operands: 1-byte delta
00135           addInstruction(Opcode, Data.getU8(Offset));
00136           break;
00137         case DW_CFA_advance_loc2:
00138           // Operands: 2-byte delta
00139           addInstruction(Opcode, Data.getU16(Offset));
00140           break;
00141         case DW_CFA_advance_loc4:
00142           // Operands: 4-byte delta
00143           addInstruction(Opcode, Data.getU32(Offset));
00144           break;
00145         case DW_CFA_restore_extended:
00146         case DW_CFA_undefined:
00147         case DW_CFA_same_value:
00148         case DW_CFA_def_cfa_register:
00149         case DW_CFA_def_cfa_offset:
00150           // Operands: ULEB128
00151           addInstruction(Opcode, Data.getULEB128(Offset));
00152           break;
00153         case DW_CFA_def_cfa_offset_sf:
00154           // Operands: SLEB128
00155           addInstruction(Opcode, Data.getSLEB128(Offset));
00156           break;
00157         case DW_CFA_offset_extended:
00158         case DW_CFA_register:
00159         case DW_CFA_def_cfa:
00160         case DW_CFA_val_offset:
00161           // Operands: ULEB128, ULEB128
00162           addInstruction(Opcode, Data.getULEB128(Offset),
00163                                  Data.getULEB128(Offset));
00164           break;
00165         case DW_CFA_offset_extended_sf:
00166         case DW_CFA_def_cfa_sf:
00167         case DW_CFA_val_offset_sf:
00168           // Operands: ULEB128, SLEB128
00169           addInstruction(Opcode, Data.getULEB128(Offset),
00170                                  Data.getSLEB128(Offset));
00171           break;
00172         case DW_CFA_def_cfa_expression:
00173         case DW_CFA_expression:
00174         case DW_CFA_val_expression:
00175           // TODO: implement this
00176           report_fatal_error("Values with expressions not implemented yet!");
00177       }
00178     }
00179   }
00180 }
00181 
00182 
00183 void FrameEntry::dumpInstructions(raw_ostream &OS) const {
00184   // TODO: at the moment only instruction names are dumped. Expand this to
00185   // dump operands as well.
00186   for (const auto &Instr : Instructions) {
00187     uint8_t Opcode = Instr.Opcode;
00188     if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
00189       Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
00190     OS << "  " << CallFrameString(Opcode) << ":\n";
00191   }
00192 }
00193 
00194 
00195 namespace {
00196 /// \brief DWARF Common Information Entry (CIE)
00197 class CIE : public FrameEntry {
00198 public:
00199   // CIEs (and FDEs) are simply container classes, so the only sensible way to
00200   // create them is by providing the full parsed contents in the constructor.
00201   CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
00202       SmallString<8> Augmentation, uint64_t CodeAlignmentFactor,
00203       int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister)
00204       : FrameEntry(FK_CIE, Offset, Length), Version(Version),
00205         Augmentation(Augmentation), CodeAlignmentFactor(CodeAlignmentFactor),
00206         DataAlignmentFactor(DataAlignmentFactor),
00207         ReturnAddressRegister(ReturnAddressRegister) {}
00208 
00209   ~CIE() {
00210   }
00211 
00212   void dumpHeader(raw_ostream &OS) const override {
00213     OS << format("%08x %08x %08x CIE",
00214                  (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID)
00215        << "\n";
00216     OS << format("  Version:               %d\n", Version);
00217     OS << "  Augmentation:          \"" << Augmentation << "\"\n";
00218     OS << format("  Code alignment factor: %u\n",
00219                  (uint32_t)CodeAlignmentFactor);
00220     OS << format("  Data alignment factor: %d\n",
00221                  (int32_t)DataAlignmentFactor);
00222     OS << format("  Return address column: %d\n",
00223                  (int32_t)ReturnAddressRegister);
00224     OS << "\n";
00225   }
00226 
00227   static bool classof(const FrameEntry *FE) {
00228     return FE->getKind() == FK_CIE;
00229   }
00230 
00231 private:
00232   /// The following fields are defined in section 6.4.1 of the DWARF standard v3
00233   uint8_t Version;
00234   SmallString<8> Augmentation;
00235   uint64_t CodeAlignmentFactor;
00236   int64_t DataAlignmentFactor;
00237   uint64_t ReturnAddressRegister;
00238 };
00239 
00240 
00241 /// \brief DWARF Frame Description Entry (FDE)
00242 class FDE : public FrameEntry {
00243 public:
00244   // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
00245   // an offset to the CIE (provided by parsing the FDE header). The CIE itself
00246   // is obtained lazily once it's actually required.
00247   FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
00248       uint64_t InitialLocation, uint64_t AddressRange)
00249       : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
00250         InitialLocation(InitialLocation), AddressRange(AddressRange),
00251         LinkedCIE(nullptr) {}
00252 
00253   ~FDE() {
00254   }
00255 
00256   void dumpHeader(raw_ostream &OS) const override {
00257     OS << format("%08x %08x %08x FDE ",
00258                  (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset);
00259     OS << format("cie=%08x pc=%08x...%08x\n",
00260                  (int32_t)LinkedCIEOffset,
00261                  (uint32_t)InitialLocation,
00262                  (uint32_t)InitialLocation + (uint32_t)AddressRange);
00263     if (LinkedCIE) {
00264       OS << format("%p\n", LinkedCIE);
00265     }
00266   }
00267 
00268   static bool classof(const FrameEntry *FE) {
00269     return FE->getKind() == FK_FDE;
00270   }
00271 
00272 private:
00273   /// The following fields are defined in section 6.4.1 of the DWARF standard v3
00274   uint64_t LinkedCIEOffset;
00275   uint64_t InitialLocation;
00276   uint64_t AddressRange;
00277   CIE *LinkedCIE;
00278 };
00279 } // end anonymous namespace
00280 
00281 
00282 DWARFDebugFrame::DWARFDebugFrame() {
00283 }
00284 
00285 DWARFDebugFrame::~DWARFDebugFrame() {
00286 }
00287 
00288 static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
00289                                               uint32_t Offset, int Length) {
00290   errs() << "DUMP: ";
00291   for (int i = 0; i < Length; ++i) {
00292     uint8_t c = Data.getU8(&Offset);
00293     errs().write_hex(c); errs() << " ";
00294   }
00295   errs() << "\n";
00296 }
00297 
00298 
00299 void DWARFDebugFrame::parse(DataExtractor Data) {
00300   uint32_t Offset = 0;
00301 
00302   while (Data.isValidOffset(Offset)) {
00303     uint32_t StartOffset = Offset;
00304 
00305     bool IsDWARF64 = false;
00306     uint64_t Length = Data.getU32(&Offset);
00307     uint64_t Id;
00308 
00309     if (Length == UINT32_MAX) {
00310       // DWARF-64 is distinguished by the first 32 bits of the initial length
00311       // field being 0xffffffff. Then, the next 64 bits are the actual entry
00312       // length.
00313       IsDWARF64 = true;
00314       Length = Data.getU64(&Offset);
00315     }
00316 
00317     // At this point, Offset points to the next field after Length.
00318     // Length is the structure size excluding itself. Compute an offset one
00319     // past the end of the structure (needed to know how many instructions to
00320     // read).
00321     // TODO: For honest DWARF64 support, DataExtractor will have to treat
00322     //       offset_ptr as uint64_t*
00323     uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
00324 
00325     // The Id field's size depends on the DWARF format
00326     Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4);
00327     bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID);
00328 
00329     if (IsCIE) {
00330       // Note: this is specifically DWARFv3 CIE header structure. It was
00331       // changed in DWARFv4. We currently don't support reading DWARFv4
00332       // here because LLVM itself does not emit it (and LLDB doesn't
00333       // support it either).
00334       uint8_t Version = Data.getU8(&Offset);
00335       const char *Augmentation = Data.getCStr(&Offset);
00336       uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
00337       int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
00338       uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
00339 
00340       Entries.emplace_back(new CIE(StartOffset, Length, Version,
00341                                    StringRef(Augmentation), CodeAlignmentFactor,
00342                                    DataAlignmentFactor, ReturnAddressRegister));
00343     } else {
00344       // FDE
00345       uint64_t CIEPointer = Id;
00346       uint64_t InitialLocation = Data.getAddress(&Offset);
00347       uint64_t AddressRange = Data.getAddress(&Offset);
00348 
00349       Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
00350                                    InitialLocation, AddressRange));
00351     }
00352 
00353     Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);
00354 
00355     if (Offset != EndStructureOffset) {
00356       std::string Str;
00357       raw_string_ostream OS(Str);
00358       OS << format("Parsing entry instructions at %lx failed", StartOffset);
00359       report_fatal_error(Str);
00360     }
00361   }
00362 }
00363 
00364 
00365 void DWARFDebugFrame::dump(raw_ostream &OS) const {
00366   OS << "\n";
00367   for (const auto &Entry : Entries) {
00368     Entry->dumpHeader(OS);
00369     Entry->dumpInstructions(OS);
00370     OS << "\n";
00371   }
00372 }
00373