diff options
Diffstat (limited to 'lib/DebugInfo/DWARFDebugFrame.cpp')
| -rw-r--r-- | lib/DebugInfo/DWARFDebugFrame.cpp | 374 | 
1 files changed, 0 insertions, 374 deletions
diff --git a/lib/DebugInfo/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARFDebugFrame.cpp deleted file mode 100644 index 968a0ce01c9f4..0000000000000 --- a/lib/DebugInfo/DWARFDebugFrame.cpp +++ /dev/null @@ -1,374 +0,0 @@ -//===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/DWARFDebugFrame.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" -#include <string> -#include <vector> - -using namespace llvm; -using namespace dwarf; - - -/// \brief Abstract frame entry defining the common interface concrete -/// entries implement. -class llvm::FrameEntry { -public: -  enum FrameKind {FK_CIE, FK_FDE}; -  FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length) -      : Kind(K), Offset(Offset), Length(Length) {} - -  virtual ~FrameEntry() { -  } - -  FrameKind getKind() const { return Kind; } -  virtual uint64_t getOffset() const { return Offset; } - -  /// \brief Parse and store a sequence of CFI instructions from Data, -  /// starting at *Offset and ending at EndOffset. If everything -  /// goes well, *Offset should be equal to EndOffset when this method -  /// returns. Otherwise, an error occurred. -  virtual void parseInstructions(DataExtractor Data, uint32_t *Offset, -                                 uint32_t EndOffset); - -  /// \brief Dump the entry header to the given output stream. -  virtual void dumpHeader(raw_ostream &OS) const = 0; - -  /// \brief Dump the entry's instructions to the given output stream. -  virtual void dumpInstructions(raw_ostream &OS) const; - -protected: -  const FrameKind Kind; - -  /// \brief Offset of this entry in the section. -  uint64_t Offset; - -  /// \brief Entry length as specified in DWARF. -  uint64_t Length; - -  /// An entry may contain CFI instructions. An instruction consists of an -  /// opcode and an optional sequence of operands. -  typedef std::vector<uint64_t> Operands; -  struct Instruction { -    Instruction(uint8_t Opcode) -      : Opcode(Opcode) -    {} - -    uint8_t Opcode; -    Operands Ops; -  }; - -  std::vector<Instruction> Instructions; - -  /// Convenience methods to add a new instruction with the given opcode and -  /// operands to the Instructions vector. -  void addInstruction(uint8_t Opcode) { -    Instructions.push_back(Instruction(Opcode)); -  } - -  void addInstruction(uint8_t Opcode, uint64_t Operand1) { -    Instructions.push_back(Instruction(Opcode)); -    Instructions.back().Ops.push_back(Operand1); -  } - -  void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) { -    Instructions.push_back(Instruction(Opcode)); -    Instructions.back().Ops.push_back(Operand1); -    Instructions.back().Ops.push_back(Operand2); -  } -}; - - -// See DWARF standard v3, section 7.23 -const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0; -const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f; - -void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset, -                                   uint32_t EndOffset) { -  while (*Offset < EndOffset) { -    uint8_t Opcode = Data.getU8(Offset); -    // Some instructions have a primary opcode encoded in the top bits. -    uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK; - -    if (Primary) { -      // If it's a primary opcode, the first operand is encoded in the bottom -      // bits of the opcode itself. -      uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK; -      switch (Primary) { -        default: llvm_unreachable("Impossible primary CFI opcode"); -        case DW_CFA_advance_loc: -        case DW_CFA_restore: -          addInstruction(Primary, Op1); -          break; -        case DW_CFA_offset: -          addInstruction(Primary, Op1, Data.getULEB128(Offset)); -          break; -      } -    } else { -      // Extended opcode - its value is Opcode itself. -      switch (Opcode) { -        default: llvm_unreachable("Invalid extended CFI opcode"); -        case DW_CFA_nop: -        case DW_CFA_remember_state: -        case DW_CFA_restore_state: -        case DW_CFA_GNU_window_save: -          // No operands -          addInstruction(Opcode); -          break; -        case DW_CFA_set_loc: -          // Operands: Address -          addInstruction(Opcode, Data.getAddress(Offset)); -          break; -        case DW_CFA_advance_loc1: -          // Operands: 1-byte delta -          addInstruction(Opcode, Data.getU8(Offset)); -          break; -        case DW_CFA_advance_loc2: -          // Operands: 2-byte delta -          addInstruction(Opcode, Data.getU16(Offset)); -          break; -        case DW_CFA_advance_loc4: -          // Operands: 4-byte delta -          addInstruction(Opcode, Data.getU32(Offset)); -          break; -        case DW_CFA_restore_extended: -        case DW_CFA_undefined: -        case DW_CFA_same_value: -        case DW_CFA_def_cfa_register: -        case DW_CFA_def_cfa_offset: -          // Operands: ULEB128 -          addInstruction(Opcode, Data.getULEB128(Offset)); -          break; -        case DW_CFA_def_cfa_offset_sf: -          // Operands: SLEB128 -          addInstruction(Opcode, Data.getSLEB128(Offset)); -          break; -        case DW_CFA_offset_extended: -        case DW_CFA_register: -        case DW_CFA_def_cfa: -        case DW_CFA_val_offset: -          // Operands: ULEB128, ULEB128 -          addInstruction(Opcode, Data.getULEB128(Offset), -                                 Data.getULEB128(Offset)); -          break; -        case DW_CFA_offset_extended_sf: -        case DW_CFA_def_cfa_sf: -        case DW_CFA_val_offset_sf: -          // Operands: ULEB128, SLEB128 -          addInstruction(Opcode, Data.getULEB128(Offset), -                                 Data.getSLEB128(Offset)); -          break; -        case DW_CFA_def_cfa_expression: -        case DW_CFA_expression: -        case DW_CFA_val_expression: -          // TODO: implement this -          report_fatal_error("Values with expressions not implemented yet!"); -      } -    } -  } -} - - -void FrameEntry::dumpInstructions(raw_ostream &OS) const { -  // TODO: at the moment only instruction names are dumped. Expand this to -  // dump operands as well. -  for (const auto &Instr : Instructions) { -    uint8_t Opcode = Instr.Opcode; -    if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) -      Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK; -    OS << "  " << CallFrameString(Opcode) << ":\n"; -  } -} - - -namespace { -/// \brief DWARF Common Information Entry (CIE) -class CIE : public FrameEntry { -public: -  // CIEs (and FDEs) are simply container classes, so the only sensible way to -  // create them is by providing the full parsed contents in the constructor. -  CIE(uint64_t Offset, uint64_t Length, uint8_t Version, -      SmallString<8> Augmentation, uint64_t CodeAlignmentFactor, -      int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister) -      : FrameEntry(FK_CIE, Offset, Length), Version(Version), -        Augmentation(std::move(Augmentation)), -        CodeAlignmentFactor(CodeAlignmentFactor), -        DataAlignmentFactor(DataAlignmentFactor), -        ReturnAddressRegister(ReturnAddressRegister) {} - -  ~CIE() { -  } - -  void dumpHeader(raw_ostream &OS) const override { -    OS << format("%08x %08x %08x CIE", -                 (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID) -       << "\n"; -    OS << format("  Version:               %d\n", Version); -    OS << "  Augmentation:          \"" << Augmentation << "\"\n"; -    OS << format("  Code alignment factor: %u\n", -                 (uint32_t)CodeAlignmentFactor); -    OS << format("  Data alignment factor: %d\n", -                 (int32_t)DataAlignmentFactor); -    OS << format("  Return address column: %d\n", -                 (int32_t)ReturnAddressRegister); -    OS << "\n"; -  } - -  static bool classof(const FrameEntry *FE) { -    return FE->getKind() == FK_CIE; -  } - -private: -  /// The following fields are defined in section 6.4.1 of the DWARF standard v3 -  uint8_t Version; -  SmallString<8> Augmentation; -  uint64_t CodeAlignmentFactor; -  int64_t DataAlignmentFactor; -  uint64_t ReturnAddressRegister; -}; - - -/// \brief DWARF Frame Description Entry (FDE) -class FDE : public FrameEntry { -public: -  // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with -  // an offset to the CIE (provided by parsing the FDE header). The CIE itself -  // is obtained lazily once it's actually required. -  FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset, -      uint64_t InitialLocation, uint64_t AddressRange) -      : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset), -        InitialLocation(InitialLocation), AddressRange(AddressRange), -        LinkedCIE(nullptr) {} - -  ~FDE() { -  } - -  void dumpHeader(raw_ostream &OS) const override { -    OS << format("%08x %08x %08x FDE ", -                 (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset); -    OS << format("cie=%08x pc=%08x...%08x\n", -                 (int32_t)LinkedCIEOffset, -                 (uint32_t)InitialLocation, -                 (uint32_t)InitialLocation + (uint32_t)AddressRange); -    if (LinkedCIE) { -      OS << format("%p\n", LinkedCIE); -    } -  } - -  static bool classof(const FrameEntry *FE) { -    return FE->getKind() == FK_FDE; -  } - -private: -  /// The following fields are defined in section 6.4.1 of the DWARF standard v3 -  uint64_t LinkedCIEOffset; -  uint64_t InitialLocation; -  uint64_t AddressRange; -  CIE *LinkedCIE; -}; -} // end anonymous namespace - - -DWARFDebugFrame::DWARFDebugFrame() { -} - -DWARFDebugFrame::~DWARFDebugFrame() { -} - -static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, -                                              uint32_t Offset, int Length) { -  errs() << "DUMP: "; -  for (int i = 0; i < Length; ++i) { -    uint8_t c = Data.getU8(&Offset); -    errs().write_hex(c); errs() << " "; -  } -  errs() << "\n"; -} - - -void DWARFDebugFrame::parse(DataExtractor Data) { -  uint32_t Offset = 0; - -  while (Data.isValidOffset(Offset)) { -    uint32_t StartOffset = Offset; - -    bool IsDWARF64 = false; -    uint64_t Length = Data.getU32(&Offset); -    uint64_t Id; - -    if (Length == UINT32_MAX) { -      // DWARF-64 is distinguished by the first 32 bits of the initial length -      // field being 0xffffffff. Then, the next 64 bits are the actual entry -      // length. -      IsDWARF64 = true; -      Length = Data.getU64(&Offset); -    } - -    // At this point, Offset points to the next field after Length. -    // Length is the structure size excluding itself. Compute an offset one -    // past the end of the structure (needed to know how many instructions to -    // read). -    // TODO: For honest DWARF64 support, DataExtractor will have to treat -    //       offset_ptr as uint64_t* -    uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length); - -    // The Id field's size depends on the DWARF format -    Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4); -    bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID); - -    if (IsCIE) { -      // Note: this is specifically DWARFv3 CIE header structure. It was -      // changed in DWARFv4. We currently don't support reading DWARFv4 -      // here because LLVM itself does not emit it (and LLDB doesn't -      // support it either). -      uint8_t Version = Data.getU8(&Offset); -      const char *Augmentation = Data.getCStr(&Offset); -      uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset); -      int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); -      uint64_t ReturnAddressRegister = Data.getULEB128(&Offset); - -      Entries.emplace_back(new CIE(StartOffset, Length, Version, -                                   StringRef(Augmentation), CodeAlignmentFactor, -                                   DataAlignmentFactor, ReturnAddressRegister)); -    } else { -      // FDE -      uint64_t CIEPointer = Id; -      uint64_t InitialLocation = Data.getAddress(&Offset); -      uint64_t AddressRange = Data.getAddress(&Offset); - -      Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer, -                                   InitialLocation, AddressRange)); -    } - -    Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset); - -    if (Offset != EndStructureOffset) { -      std::string Str; -      raw_string_ostream OS(Str); -      OS << format("Parsing entry instructions at %lx failed", StartOffset); -      report_fatal_error(Str); -    } -  } -} - - -void DWARFDebugFrame::dump(raw_ostream &OS) const { -  OS << "\n"; -  for (const auto &Entry : Entries) { -    Entry->dumpHeader(OS); -    Entry->dumpInstructions(OS); -    OS << "\n"; -  } -} -  | 
