From 6aa8b3491f866eadfa0b7e9aef21a416fac466f9 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Wed, 7 Mar 2018 22:29:48 +0000 Subject: [PATCH] Revert r326932: [DebugInfo] Support DWARF expressions in eh_frame This reverts commit rr326932 because it broke lld/test/ELF/eh-frame-hdr-augmentation.s. llvm-svn: 326953 --- .../llvm/DebugInfo/DWARF/DWARFDataExtractor.h | 7 - .../include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h | 278 +---------- .../include/llvm/DebugInfo/DWARF/DWARFExpression.h | 14 +- llvm/include/llvm/Support/ScopedPrinter.h | 2 - llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 12 +- llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp | 69 --- llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp | 545 ++++++++++++++------- llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp | 5 +- llvm/lib/ObjectYAML/ELFYAML.cpp | 1 - .../Inputs/dwarf-exprs.exe-x86-64.yaml | 46 -- llvm/test/tools/llvm-readobj/unwind.test | 170 ------- llvm/tools/llvm-readobj/CMakeLists.txt | 1 - llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h | 244 --------- llvm/tools/llvm-readobj/ELFDumper.cpp | 6 - 14 files changed, 389 insertions(+), 1011 deletions(-) delete mode 100644 llvm/test/tools/llvm-readobj/Inputs/dwarf-exprs.exe-x86-64.yaml delete mode 100644 llvm/test/tools/llvm-readobj/unwind.test delete mode 100644 llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h index 10e146b..a379d9c 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h @@ -44,13 +44,6 @@ public: uint64_t getRelocatedAddress(uint32_t *Off, uint64_t *SecIx = nullptr) const { return getRelocatedValue(getAddressSize(), Off, SecIx); } - - /// Extracts a DWARF-encoded pointer in \p Offset using \p Encoding. - /// There is a DWARF encoding that uses a PC-relative adjustment. - /// For these values, \p AbsPosOffset is used to fix them, which should - /// reflect the absolute address of this pointer. - Optional getEncodedPointer(uint32_t *Offset, uint8_t Encoding, - uint64_t AbsPosOffset = 0) const; }; } // end namespace llvm diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h index ff1c7fb..a711fb2 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h @@ -10,290 +10,40 @@ #ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H #define LLVM_DEBUGINFO_DWARF_DWARFDEBUGFRAME_H -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/iterator.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" -#include "llvm/Support/Error.h" +#include "llvm/Support/DataExtractor.h" #include #include namespace llvm { +class FrameEntry; class raw_ostream; -namespace dwarf { - -/// Represent a sequence of Call Frame Information instructions that, when read -/// in order, construct a table mapping PC to frame state. This can also be -/// referred to as "CFI rules" in DWARF literature to avoid confusion with -/// computer programs in the broader sense, and in this context each instruction -/// would be a rule to establish the mapping. Refer to pg. 172 in the DWARF5 -/// manual, "6.4.1 Structure of Call Frame Information". -class CFIProgram { -public: - typedef SmallVector Operands; - - /// An instruction consists of a DWARF CFI opcode and an optional sequence of - /// operands. If it refers to an expression, then this expression has its own - /// sequence of operations and operands handled separately by DWARFExpression. - struct Instruction { - Instruction(uint8_t Opcode) : Opcode(Opcode) {} - - uint8_t Opcode; - Operands Ops; - // Associated DWARF expression in case this instruction refers to one - Optional Expression; - }; - - using InstrList = std::vector; - using iterator = InstrList::iterator; - using const_iterator = InstrList::const_iterator; - - iterator begin() { return Instructions.begin(); } - const_iterator begin() const { return Instructions.begin(); } - iterator end() { return Instructions.end(); } - const_iterator end() const { return Instructions.end(); } - - unsigned size() const { return (unsigned)Instructions.size(); } - bool empty() const { return Instructions.empty(); } - - CFIProgram(uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor) - : CodeAlignmentFactor(CodeAlignmentFactor), - DataAlignmentFactor(DataAlignmentFactor) {} - - /// Parse and store a sequence of CFI instructions from Data, - /// starting at *Offset and ending at EndOffset. *Offset is updated - /// to EndOffset upon successful parsing, or indicates the offset - /// where a problem occurred in case an error is returned. - Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset); - - void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, - unsigned IndentLevel = 1) const; - -private: - std::vector Instructions; - const uint64_t CodeAlignmentFactor; - const int64_t DataAlignmentFactor; - - /// Convenience method to add a new instruction with the given opcode. - void addInstruction(uint8_t Opcode) { - Instructions.push_back(Instruction(Opcode)); - } - - /// Add a new single-operand instruction. - void addInstruction(uint8_t Opcode, uint64_t Operand1) { - Instructions.push_back(Instruction(Opcode)); - Instructions.back().Ops.push_back(Operand1); - } - - /// Add a new instruction that has two operands. - 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); - } - - /// Types of operands to CFI instructions - /// In DWARF, this type is implicitly tied to a CFI instruction opcode and - /// thus this type doesn't need to be explictly written to the file (this is - /// not a DWARF encoding). The relationship of instrs to operand types can - /// be obtained from getOperandTypes() and is only used to simplify - /// instruction printing. - enum OperandType { - OT_Unset, - OT_None, - OT_Address, - OT_Offset, - OT_FactoredCodeOffset, - OT_SignedFactDataOffset, - OT_UnsignedFactDataOffset, - OT_Register, - OT_Expression - }; - - /// Retrieve the array describing the types of operands according to the enum - /// above. This is indexed by opcode. - static ArrayRef getOperandTypes(); - - /// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. - void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, - const Instruction &Instr, unsigned OperandIdx, - uint64_t Operand) const; -}; - -/// An entry in either debug_frame or eh_frame. This entry can be a CIE or an -/// FDE. -class FrameEntry { -public: - enum FrameKind { FK_CIE, FK_FDE }; - - FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign, - int64_t DataAlign) - : Kind(K), Offset(Offset), Length(Length), CFIs(CodeAlign, DataAlign) {} - - virtual ~FrameEntry() {} - - FrameKind getKind() const { return Kind; } - uint64_t getOffset() const { return Offset; } - uint64_t getLength() const { return Length; } - const CFIProgram &cfis() const { return CFIs; } - CFIProgram &cfis() { return CFIs; } - - /// Dump the instructions in this CFI fragment - virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI, - bool IsEH) const = 0; - -protected: - const FrameKind Kind; - - /// Offset of this entry in the section. - const uint64_t Offset; - - /// Entry length as specified in DWARF. - const uint64_t Length; - - CFIProgram CFIs; -}; - -/// 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, uint8_t AddressSize, - uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor, - int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister, - SmallString<8> AugmentationData, uint32_t FDEPointerEncoding, - uint32_t LSDAPointerEncoding, Optional Personality, - Optional PersonalityEnc) - : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor, - DataAlignmentFactor), - Version(Version), Augmentation(std::move(Augmentation)), - AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize), - CodeAlignmentFactor(CodeAlignmentFactor), - DataAlignmentFactor(DataAlignmentFactor), - ReturnAddressRegister(ReturnAddressRegister), - AugmentationData(std::move(AugmentationData)), - FDEPointerEncoding(FDEPointerEncoding), - LSDAPointerEncoding(LSDAPointerEncoding), Personality(Personality), - PersonalityEnc(PersonalityEnc) {} - - static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_CIE; } - - StringRef getAugmentationString() const { return Augmentation; } - uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; } - int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; } - uint8_t getVersion() const { return Version; } - uint64_t getReturnAddressRegister() const { return ReturnAddressRegister; } - Optional getPersonalityAddress() const { return Personality; } - Optional getPersonalityEncoding() const { return PersonalityEnc; } - - uint32_t getFDEPointerEncoding() const { return FDEPointerEncoding; } - - uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; } - - void dump(raw_ostream &OS, const MCRegisterInfo *MRI, - bool IsEH) const override; - -private: - /// The following fields are defined in section 6.4.1 of the DWARF standard v4 - const uint8_t Version; - const SmallString<8> Augmentation; - const uint8_t AddressSize; - const uint8_t SegmentDescriptorSize; - const uint64_t CodeAlignmentFactor; - const int64_t DataAlignmentFactor; - const uint64_t ReturnAddressRegister; - - // The following are used when the CIE represents an EH frame entry. - const SmallString<8> AugmentationData; - const uint32_t FDEPointerEncoding; - const uint32_t LSDAPointerEncoding; - const Optional Personality; - const Optional PersonalityEnc; -}; - -/// 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, CIE *Cie, - Optional LSDAAddress) - : FrameEntry(FK_FDE, Offset, Length, - Cie ? Cie->getCodeAlignmentFactor() : 0, - Cie ? Cie->getDataAlignmentFactor() : 0), - LinkedCIEOffset(LinkedCIEOffset), InitialLocation(InitialLocation), - AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {} - - ~FDE() override = default; - - const CIE *getLinkedCIE() const { return LinkedCIE; } - uint64_t getInitialLocation() const { return InitialLocation; } - uint64_t getAddressRange() const { return AddressRange; } - Optional getLSDAAddress() const { return LSDAAddress; } - - void dump(raw_ostream &OS, const MCRegisterInfo *MRI, - bool IsEH) const override; - - 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 - const uint64_t LinkedCIEOffset; - const uint64_t InitialLocation; - const uint64_t AddressRange; - const CIE *LinkedCIE; - const Optional LSDAAddress; -}; - -} // end namespace dwarf - -/// A parsed .debug_frame or .eh_frame section +/// \brief A parsed .debug_frame or .eh_frame section +/// class DWARFDebugFrame { // True if this is parsing an eh_frame section. - const bool IsEH; - // Not zero for sane pointer values coming out of eh_frame - const uint64_t EHFrameAddress; - - std::vector> Entries; - using iterator = pointee_iterator; - - /// Return the entry at the given offset or nullptr. - dwarf::FrameEntry *getEntryAtOffset(uint64_t Offset) const; + bool IsEH; public: - // If IsEH is true, assume it is a .eh_frame section. Otherwise, - // it is a .debug_frame section. EHFrameAddress should be different - // than zero for correct parsing of .eh_frame addresses when they - // use a PC-relative encoding. - DWARFDebugFrame(bool IsEH = false, uint64_t EHFrameAddress = 0); + DWARFDebugFrame(bool IsEH); ~DWARFDebugFrame(); /// Dump the section data into the given stream. - void dump(raw_ostream &OS, const MCRegisterInfo *MRI, - Optional Offset) const; + void dump(raw_ostream &OS, Optional Offset) const; - /// Parse the section from raw data. \p Data is assumed to contain the whole - /// frame section contents to be parsed. - void parse(DWARFDataExtractor Data); + /// \brief Parse the section from raw data. + /// data is assumed to be pointing to the beginning of the section. + void parse(DataExtractor Data); /// Return whether the section has any entries. bool empty() const { return Entries.empty(); } - /// DWARF Frame entries accessors - iterator begin() const { return Entries.begin(); } - iterator end() const { return Entries.end(); } - iterator_range entries() const { - return iterator_range(Entries.begin(), Entries.end()); - } + /// Return the entry at the given offset or nullptr. + FrameEntry *getEntryAtOffset(uint64_t Offset) const; - uint64_t getEHFrameAddress() const { return EHFrameAddress; } +private: + std::vector> Entries; }; } // end namespace llvm diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h index 3fad68a..dcd486f 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h @@ -93,13 +93,12 @@ public: /// An iterator to go through the expression operations. class iterator - : public iterator_facade_base { + : public iterator_facade_base { friend class DWARFExpression; - const DWARFExpression *Expr; + DWARFExpression *Expr; uint32_t Offset; Operation Op; - iterator(const DWARFExpression *Expr, uint32_t Offset) + iterator(DWARFExpression *Expr, uint32_t Offset) : Expr(Expr), Offset(Offset) { Op.Error = Offset >= Expr->Data.getData().size() || @@ -128,11 +127,10 @@ public: assert(AddressSize == 8 || AddressSize == 4); } - iterator begin() const { return iterator(this, 0); } - iterator end() const { return iterator(this, Data.getData().size()); } + iterator begin() { return iterator(this, 0); } + iterator end() { return iterator(this, Data.getData().size()); } - void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, - bool IsEH = false) const; + void print(raw_ostream &OS, const MCRegisterInfo *RegInfo); private: DataExtractor Data; diff --git a/llvm/include/llvm/Support/ScopedPrinter.h b/llvm/include/llvm/Support/ScopedPrinter.h index 964d254..1c22da6 100644 --- a/llvm/include/llvm/Support/ScopedPrinter.h +++ b/llvm/include/llvm/Support/ScopedPrinter.h @@ -80,8 +80,6 @@ public: void resetIndent() { IndentLevel = 0; } - int getIndentLevel() { return IndentLevel; } - void setPrefix(StringRef P) { Prefix = P; } void printIndent() { diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index 2b1c91e..de7ef66 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -349,11 +349,11 @@ void DWARFContext::dump( if (shouldDump(Explicit, ".debug_frame", DIDT_ID_DebugFrame, DObj->getDebugFrameSection())) - getDebugFrame()->dump(OS, getRegisterInfo(), DumpOffset); + getDebugFrame()->dump(OS, DumpOffset); if (shouldDump(Explicit, ".eh_frame", DIDT_ID_DebugFrame, DObj->getEHFrameSection())) - getEHFrame()->dump(OS, getRegisterInfo(), DumpOffset); + getEHFrame()->dump(OS, DumpOffset); if (DumpType & DIDT_DebugMacro) { if (Explicit || !getDebugMacro()->empty()) { @@ -712,8 +712,8 @@ const DWARFDebugFrame *DWARFContext::getDebugFrame() { // provides this information). This problem is fixed in DWARFv4 // See this dwarf-discuss discussion for more details: // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html - DWARFDataExtractor debugFrameData(DObj->getDebugFrameSection(), - isLittleEndian(), DObj->getAddressSize()); + DataExtractor debugFrameData(DObj->getDebugFrameSection(), isLittleEndian(), + DObj->getAddressSize()); DebugFrame.reset(new DWARFDebugFrame(false /* IsEH */)); DebugFrame->parse(debugFrameData); return DebugFrame.get(); @@ -723,8 +723,8 @@ const DWARFDebugFrame *DWARFContext::getEHFrame() { if (EHFrame) return EHFrame.get(); - DWARFDataExtractor debugFrameData(DObj->getEHFrameSection(), isLittleEndian(), - DObj->getAddressSize()); + DataExtractor debugFrameData(DObj->getEHFrameSection(), isLittleEndian(), + DObj->getAddressSize()); DebugFrame.reset(new DWARFDebugFrame(true /* IsEH */)); DebugFrame->parse(debugFrameData); return DebugFrame.get(); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp index 03e3174..861dd31 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" -#include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" using namespace llvm; @@ -26,71 +25,3 @@ uint64_t DWARFDataExtractor::getRelocatedValue(uint32_t Size, uint32_t *Off, *SecNdx = Rel->SectionIndex; return getUnsigned(Off, Size) + Rel->Value; } - -Optional -DWARFDataExtractor::getEncodedPointer(uint32_t *Offset, uint8_t Encoding, - uint64_t PCRelOffset) const { - if (Encoding == dwarf::DW_EH_PE_omit) - return None; - - uint64_t Result = 0; - uint32_t OldOffset = *Offset; - // First get value - switch (Encoding & 0x0F) { - case dwarf::DW_EH_PE_absptr: - switch (getAddressSize()) { - case 2: - case 4: - case 8: - Result = getUnsigned(Offset, getAddressSize()); - break; - default: - return None; - } - break; - case dwarf::DW_EH_PE_uleb128: - Result = getULEB128(Offset); - break; - case dwarf::DW_EH_PE_sleb128: - Result = getSLEB128(Offset); - break; - case dwarf::DW_EH_PE_udata2: - Result = getUnsigned(Offset, 2); - break; - case dwarf::DW_EH_PE_udata4: - Result = getUnsigned(Offset, 4); - break; - case dwarf::DW_EH_PE_udata8: - Result = getUnsigned(Offset, 8); - break; - case dwarf::DW_EH_PE_sdata2: - Result = getSigned(Offset, 2); - break; - case dwarf::DW_EH_PE_sdata4: - Result = getSigned(Offset, 4); - break; - case dwarf::DW_EH_PE_sdata8: - Result = getSigned(Offset, 8); - break; - default: - return None; - } - // Then add relative offset, if required - switch (Encoding & 0x70) { - case dwarf::DW_EH_PE_absptr: - // do nothing - break; - case dwarf::DW_EH_PE_pcrel: - Result += PCRelOffset; - break; - case dwarf::DW_EH_PE_datarel: - case dwarf::DW_EH_PE_textrel: - case dwarf::DW_EH_PE_funcrel: - case dwarf::DW_EH_PE_aligned: - default: - *Offset = OldOffset; - return None; - } - - return Result; -} diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index b9dc215..3312da6 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -8,8 +8,10 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/Dwarf.h" @@ -29,13 +31,87 @@ 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() = default; + + FrameKind getKind() const { return Kind; } + virtual uint64_t getOffset() const { return Offset; } + + /// 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); + + /// Dump the entry header to the given output stream. + virtual void dumpHeader(raw_ostream &OS) const = 0; + + /// Dump the entry's instructions to the given output stream. + virtual void dumpInstructions(raw_ostream &OS) const; + + /// Dump the entire entry to the given output stream. + void dump(raw_ostream &OS) const { + dumpHeader(OS); + dumpInstructions(OS); + OS << "\n"; + } + +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. + using Operands = std::vector; + struct Instruction { + Instruction(uint8_t Opcode) + : Opcode(Opcode) + {} + + uint8_t Opcode; + Operands Ops; + }; + + std::vector 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; -Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset, - uint32_t EndOffset) { +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. @@ -46,73 +122,67 @@ Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset, // bits of the opcode itself. uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK; switch (Primary) { - default: - return make_error( - "Invalid primary CFI opcode", - std::make_error_code(std::errc::illegal_byte_sequence)); - case DW_CFA_advance_loc: - case DW_CFA_restore: - addInstruction(Primary, Op1); - break; - case DW_CFA_offset: - addInstruction(Primary, Op1, Data.getULEB128(Offset)); - break; + 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: - return make_error( - "Invalid extended CFI opcode", - std::make_error_code(std::errc::illegal_byte_sequence)); - 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: - case DW_CFA_GNU_args_size: - // 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 - // Note: We can not embed getULEB128 directly into function - // argument list. getULEB128 changes Offset and order of evaluation - // for arguments is unspecified. - auto op1 = Data.getULEB128(Offset); - auto op2 = Data.getULEB128(Offset); - addInstruction(Opcode, op1, op2); - break; + 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: + case DW_CFA_GNU_args_size: + // 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 + // Note: We can not embed getULEB128 directly into function + // argument list. getULEB128 changes Offset and order of evaluation + // for arguments is unspecified. + auto op1 = Data.getULEB128(Offset); + auto op2 = Data.getULEB128(Offset); + addInstruction(Opcode, op1, op2); + break; } case DW_CFA_offset_extended_sf: case DW_CFA_def_cfa_sf: @@ -124,49 +194,162 @@ Error CFIProgram::parse(DataExtractor Data, uint32_t *Offset, addInstruction(Opcode, op1, op2); break; } - case DW_CFA_def_cfa_expression: { - uint32_t ExprLength = Data.getULEB128(Offset); - addInstruction(Opcode, 0); - DataExtractor Extractor( - Data.getData().slice(*Offset, *Offset + ExprLength), - Data.isLittleEndian(), Data.getAddressSize()); - Instructions.back().Expression = DWARFExpression( - Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION); - *Offset += ExprLength; + case DW_CFA_def_cfa_expression: + // FIXME: Parse the actual instruction. + *Offset += Data.getULEB128(Offset); break; - } case DW_CFA_expression: case DW_CFA_val_expression: { - auto RegNum = Data.getULEB128(Offset); - auto BlockLength = Data.getULEB128(Offset); - addInstruction(Opcode, RegNum, 0); - DataExtractor Extractor( - Data.getData().slice(*Offset, *Offset + BlockLength), - Data.isLittleEndian(), Data.getAddressSize()); - Instructions.back().Expression = DWARFExpression( - Extractor, Data.getAddressSize(), dwarf::DWARF_VERSION); - *Offset += BlockLength; + // FIXME: Parse the actual instruction. + Data.getULEB128(Offset); + *Offset += Data.getULEB128(Offset); break; } } } } - - return Error::success(); } 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, uint8_t AddressSize, + uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor, + int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister, + SmallString<8> AugmentationData, uint32_t FDEPointerEncoding, + uint32_t LSDAPointerEncoding) + : FrameEntry(FK_CIE, Offset, Length), Version(Version), + Augmentation(std::move(Augmentation)), AddressSize(AddressSize), + SegmentDescriptorSize(SegmentDescriptorSize), + CodeAlignmentFactor(CodeAlignmentFactor), + DataAlignmentFactor(DataAlignmentFactor), + ReturnAddressRegister(ReturnAddressRegister), + AugmentationData(std::move(AugmentationData)), + FDEPointerEncoding(FDEPointerEncoding), + LSDAPointerEncoding(LSDAPointerEncoding) {} + + ~CIE() override = default; + + StringRef getAugmentationString() const { return Augmentation; } + uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; } + int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; } + + uint32_t getFDEPointerEncoding() const { + return FDEPointerEncoding; + } + + uint32_t getLSDAPointerEncoding() const { + return LSDAPointerEncoding; + } + + 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"; + if (Version >= 4) { + OS << format(" Address size: %u\n", + (uint32_t)AddressSize); + OS << format(" Segment desc size: %u\n", + (uint32_t)SegmentDescriptorSize); + } + 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); + if (!AugmentationData.empty()) { + OS << " Augmentation data: "; + for (uint8_t Byte : AugmentationData) + OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf); + OS << "\n"; + } + 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 v4 + uint8_t Version; + SmallString<8> Augmentation; + uint8_t AddressSize; + uint8_t SegmentDescriptorSize; + uint64_t CodeAlignmentFactor; + int64_t DataAlignmentFactor; + uint64_t ReturnAddressRegister; + + // The following are used when the CIE represents an EH frame entry. + SmallString<8> AugmentationData; + uint32_t FDEPointerEncoding; + uint32_t LSDAPointerEncoding; +}; + +/// \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, + CIE *Cie) + : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset), + InitialLocation(InitialLocation), AddressRange(AddressRange), + LinkedCIE(Cie) {} + + ~FDE() override = default; + + CIE *getLinkedCIE() const { return LinkedCIE; } + + 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); + } + + 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; +}; + +/// \brief Types of operands to CF instructions. +enum OperandType { + OT_Unset, + OT_None, + OT_Address, + OT_Offset, + OT_FactoredCodeOffset, + OT_SignedFactDataOffset, + OT_UnsignedFactDataOffset, + OT_Register, + OT_Expression +}; } // end anonymous namespace -ArrayRef CFIProgram::getOperandTypes() { +/// \brief Initialize the array describing the types of operands. +static ArrayRef getOperandTypes() { static OperandType OpTypes[DW_CFA_restore+1][2]; - static bool Initialized = false; - if (Initialized) { - return ArrayRef(&OpTypes[0], DW_CFA_restore+1); - } - Initialized = true; #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \ do { \ @@ -213,13 +396,15 @@ ArrayRef CFIProgram::getOperandTypes() { return ArrayRef(&OpTypes[0], DW_CFA_restore+1); } -/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand. -void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, - bool IsEH, const Instruction &Instr, - unsigned OperandIdx, uint64_t Operand) const { +static ArrayRef OpTypes = getOperandTypes(); + +/// \brief Print \p Opcode's operand number \p OperandIdx which has +/// value \p Operand. +static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned OperandIdx, + uint64_t Operand, uint64_t CodeAlignmentFactor, + int64_t DataAlignmentFactor) { assert(OperandIdx < 2); - uint8_t Opcode = Instr.Opcode; - OperandType Type = getOperandTypes()[Opcode][OperandIdx]; + OperandType Type = OpTypes[Opcode][OperandIdx]; switch (Type) { case OT_Unset: { @@ -264,68 +449,36 @@ void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, OS << format(" reg%" PRId64, Operand); break; case OT_Expression: - assert(Instr.Expression && "missing DWARFExpression object"); - OS << " "; - Instr.Expression->print(OS, MRI, IsEH); + OS << " expression"; break; } } -void CFIProgram::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH, - unsigned IndentLevel) const { +void FrameEntry::dumpInstructions(raw_ostream &OS) const { + uint64_t CodeAlignmentFactor = 0; + int64_t DataAlignmentFactor = 0; + const CIE *Cie = dyn_cast(this); + + if (!Cie) + Cie = cast(this)->getLinkedCIE(); + if (Cie) { + CodeAlignmentFactor = Cie->getCodeAlignmentFactor(); + DataAlignmentFactor = Cie->getDataAlignmentFactor(); + } + for (const auto &Instr : Instructions) { uint8_t Opcode = Instr.Opcode; if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK; - OS.indent(2 * IndentLevel); - OS << CallFrameString(Opcode) << ":"; + OS << " " << CallFrameString(Opcode) << ":"; for (unsigned i = 0; i < Instr.Ops.size(); ++i) - printOperand(OS, MRI, IsEH, Instr, i, Instr.Ops[i]); + printOperand(OS, Opcode, i, Instr.Ops[i], CodeAlignmentFactor, + DataAlignmentFactor); OS << '\n'; } } -void CIE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { - 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"; - if (Version >= 4) { - OS << format(" Address size: %u\n", (uint32_t)AddressSize); - OS << format(" Segment desc size: %u\n", - (uint32_t)SegmentDescriptorSize); - } - 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); - if (Personality) - OS << format(" Personality Address: %08x\n", *Personality); - if (!AugmentationData.empty()) { - OS << " Augmentation data: "; - for (uint8_t Byte : AugmentationData) - OS << ' ' << hexdigit(Byte >> 4) << hexdigit(Byte & 0xf); - OS << "\n"; - } - OS << "\n"; - CFIs.dump(OS, MRI, IsEH); - OS << "\n"; -} - -void FDE::dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH) const { - 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 (LSDAAddress) - OS << format(" LSDA Address: %08x\n", *LSDAAddress); - CFIs.dump(OS, MRI, IsEH); - OS << "\n"; -} - -DWARFDebugFrame::DWARFDebugFrame(bool IsEH, uint64_t EHFrameAddress) - : IsEH(IsEH), EHFrameAddress(EHFrameAddress) {} +DWARFDebugFrame::DWARFDebugFrame(bool IsEH) : IsEH(IsEH) {} DWARFDebugFrame::~DWARFDebugFrame() = default; @@ -339,6 +492,40 @@ static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data, errs() << "\n"; } +static unsigned getSizeForEncoding(const DataExtractor &Data, + unsigned symbolEncoding) { + unsigned format = symbolEncoding & 0x0f; + switch (format) { + default: llvm_unreachable("Unknown Encoding"); + case DW_EH_PE_absptr: + case DW_EH_PE_signed: + return Data.getAddressSize(); + case DW_EH_PE_udata2: + case DW_EH_PE_sdata2: + return 2; + case DW_EH_PE_udata4: + case DW_EH_PE_sdata4: + return 4; + case DW_EH_PE_udata8: + case DW_EH_PE_sdata8: + return 8; + } +} + +static uint64_t readPointer(const DataExtractor &Data, uint32_t &Offset, + unsigned Encoding) { + switch (getSizeForEncoding(Data, Encoding)) { + case 2: + return Data.getU16(&Offset); + case 4: + return Data.getU32(&Offset); + case 8: + return Data.getU64(&Offset); + default: + llvm_unreachable("Illegal data size"); + } +} + // This is a workaround for old compilers which do not allow // noreturn attribute usage in lambdas. Once the support for those // compilers are phased out, we can remove this and return back to @@ -352,7 +539,7 @@ static void LLVM_ATTRIBUTE_NORETURN ReportError(uint32_t StartOffset, report_fatal_error(Str); } -void DWARFDebugFrame::parse(DWARFDataExtractor Data) { +void DWARFDebugFrame::parse(DataExtractor Data) { uint32_t Offset = 0; DenseMap CIEs; @@ -382,8 +569,9 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { // The Id field's size depends on the DWARF format Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4); - bool IsCIE = - ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID || (IsEH && !Id)); + bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || + Id == DW_CIE_ID || + (IsEH && !Id)); if (IsCIE) { uint8_t Version = Data.getU8(&Offset); @@ -401,9 +589,10 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { StringRef AugmentationData(""); uint32_t FDEPointerEncoding = DW_EH_PE_omit; uint32_t LSDAPointerEncoding = DW_EH_PE_omit; - Optional Personality; - Optional PersonalityEncoding; if (IsEH) { + Optional PersonalityEncoding; + Optional Personality; + Optional AugmentationLength; uint32_t StartAugmentationOffset; uint32_t EndAugmentationOffset; @@ -422,9 +611,7 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { ReportError(StartOffset, "Duplicate personality in entry at %lx"); PersonalityEncoding = Data.getU8(&Offset); - Personality = Data.getEncodedPointer( - &Offset, *PersonalityEncoding, - EHFrameAddress ? EHFrameAddress + Offset : 0); + Personality = readPointer(Data, Offset, *PersonalityEncoding); break; } case 'R': @@ -452,11 +639,14 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { } } - auto Cie = llvm::make_unique( - StartOffset, Length, Version, AugmentationString, AddressSize, - SegmentDescriptorSize, CodeAlignmentFactor, DataAlignmentFactor, - ReturnAddressRegister, AugmentationData, FDEPointerEncoding, - LSDAPointerEncoding, Personality, PersonalityEncoding); + auto Cie = llvm::make_unique(StartOffset, Length, Version, + AugmentationString, AddressSize, + SegmentDescriptorSize, + CodeAlignmentFactor, + DataAlignmentFactor, + ReturnAddressRegister, + AugmentationData, FDEPointerEncoding, + LSDAPointerEncoding); CIEs[StartOffset] = Cie.get(); Entries.emplace_back(std::move(Cie)); } else { @@ -464,7 +654,6 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { uint64_t CIEPointer = Id; uint64_t InitialLocation = 0; uint64_t AddressRange = 0; - Optional LSDAAddress; CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer]; if (IsEH) { @@ -473,15 +662,10 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { ReportError(StartOffset, "Parsing FDE data at %lx failed due to missing CIE"); - if (auto Val = Data.getEncodedPointer( - &Offset, Cie->getFDEPointerEncoding(), - EHFrameAddress ? EHFrameAddress + Offset : 0)) { - InitialLocation = *Val; - } - if (auto Val = Data.getEncodedPointer( - &Offset, Cie->getFDEPointerEncoding(), 0)) { - AddressRange = *Val; - } + InitialLocation = readPointer(Data, Offset, + Cie->getFDEPointerEncoding()); + AddressRange = readPointer(Data, Offset, + Cie->getFDEPointerEncoding()); StringRef AugmentationString = Cie->getAugmentationString(); if (!AugmentationString.empty()) { @@ -492,11 +676,8 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { Offset + static_cast(AugmentationLength); // Decode the LSDA if the CIE augmentation string said we should. - if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) { - LSDAAddress = Data.getEncodedPointer( - &Offset, Cie->getLSDAPointerEncoding(), - EHFrameAddress ? Offset + EHFrameAddress : 0); - } + if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit) + readPointer(Data, Offset, Cie->getLSDAPointerEncoding()); if (Offset != EndAugmentationOffset) ReportError(StartOffset, "Parsing augmentation data at %lx failed"); @@ -508,13 +689,10 @@ void DWARFDebugFrame::parse(DWARFDataExtractor Data) { Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer, InitialLocation, AddressRange, - Cie, LSDAAddress)); + Cie)); } - if (Error E = - Entries.back()->cfis().parse(Data, &Offset, EndStructureOffset)) { - report_fatal_error(toString(std::move(E))); - } + Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset); if (Offset != EndStructureOffset) ReportError(StartOffset, "Parsing entry instructions at %lx failed"); @@ -531,15 +709,14 @@ FrameEntry *DWARFDebugFrame::getEntryAtOffset(uint64_t Offset) const { return nullptr; } -void DWARFDebugFrame::dump(raw_ostream &OS, const MCRegisterInfo *MRI, - Optional Offset) const { +void DWARFDebugFrame::dump(raw_ostream &OS, Optional Offset) const { if (Offset) { if (auto *Entry = getEntryAtOffset(*Offset)) - Entry->dump(OS, MRI, IsEH); + Entry->dump(OS); return; } OS << "\n"; for (const auto &Entry : Entries) - Entry->dump(OS, MRI, IsEH); + Entry->dump(OS); } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp index a9ea26c..c704c29 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp @@ -258,10 +258,9 @@ bool DWARFExpression::Operation::print(raw_ostream &OS, return true; } -void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo *RegInfo, - bool IsEH) const { +void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo *RegInfo) { for (auto &Op : *this) { - if (!Op.print(OS, this, RegInfo, IsEH)) { + if (!Op.print(OS, this, RegInfo, /* isEH */ false)) { uint32_t FailOffset = Op.getEndOffset(); while (FailOffset < Data.getData().size()) OS << format(" %02x", Data.getU8(&FailOffset)); diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index 642a89f..928b7b2 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -50,7 +50,6 @@ void ScalarEnumerationTraits::enumeration( ECase(PT_SHLIB); ECase(PT_PHDR); ECase(PT_TLS); - ECase(PT_GNU_EH_FRAME); #undef ECase IO.enumFallback(Value); } diff --git a/llvm/test/tools/llvm-readobj/Inputs/dwarf-exprs.exe-x86-64.yaml b/llvm/test/tools/llvm-readobj/Inputs/dwarf-exprs.exe-x86-64.yaml deleted file mode 100644 index 5b8f367..0000000 --- a/llvm/test/tools/llvm-readobj/Inputs/dwarf-exprs.exe-x86-64.yaml +++ /dev/null @@ -1,46 +0,0 @@ ---- !ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_EXEC - Machine: EM_X86_64 - Entry: 0x0000000000400000 -Sections: - - Name: .text - Type: SHT_PROGBITS - Flags: [ SHF_ALLOC, SHF_EXECINSTR ] - Address: 0x0000000000400000 - AddressAlign: 16 - Content: 50C704240020400031C05AC3 - - Name: .eh_frame_hdr - Type: SHT_PROGBITS - Flags: [ SHF_ALLOC ] - Address: 0x00000000004013c0 - AddressAlign: 4 - Content: 011B033B3C00000006000000E0F0FFFF8800000010F1FFFF58000000F6F1FFFFB000000010F2FFFFD000000090FEFFFF0001000000FFFFFF30010000 - - Name: .eh_frame - Type: SHT_PROGBITS - Flags: [ SHF_ALLOC ] - Address: 0x0000000000401400 - AddressAlign: 8 - Content: 1400000000000000017A5200017810011B0C070890010710140000001C000000B0F0FFFF2A00000000000000000000001400000000000000017A5200017810011B0C070890010000240000001C00000050F0FFFF20000000000E10460E184A0F0B770880003F1A3B2A332422000000001C000000440000003EF1FFFF1000000000410E108602430D064B0C07080000002C0000006400000038F1FFFF7F0C000000450C0A00491006027600450F0376780603660C0C0A00450C070800000000002C0000009400000088FDFFFF6600000000410E108602430D06428F03458E04478D058C06488307024B0C07080000000014000000C4000000C8FDFFFF01000000000000000000000000000000 -Symbols: - Global: - - Name: myfunc - Type: STT_FUNC - Section: .text - Value: 0x0000000000400000 -ProgramHeaders: - - Type: PT_LOAD - Flags: [ PF_X, PF_R ] - VAddr: 0x00400000 - PAddr: 0x00400000 - Sections: - - Section: .text - - Type: PT_GNU_EH_FRAME - Flags: [ PF_X, PF_R ] - VAddr: 0x004013C0 - PAddr: 0x004013C0 - Sections: - - Section: .eh_frame_hdr -... diff --git a/llvm/test/tools/llvm-readobj/unwind.test b/llvm/test/tools/llvm-readobj/unwind.test deleted file mode 100644 index 72c5910..0000000 --- a/llvm/test/tools/llvm-readobj/unwind.test +++ /dev/null @@ -1,170 +0,0 @@ -RUN: yaml2obj %p/Inputs/dwarf-exprs.exe-x86-64.yaml > %t.exe -RUN: llvm-readobj -unwind %t.exe | FileCheck %s - -CHECK: EH_FRAME Header [ -CHECK-NEXT: Address: 0x4013c0 -CHECK-NEXT: Offset: 0x27c -CHECK-NEXT: Size: 0x3c -CHECK-NEXT: Corresponding Section: .eh_frame_hdr -CHECK-NEXT: Header { -CHECK-NEXT: version: 1 -CHECK-NEXT: eh_frame_ptr_enc: 0x1b -CHECK-NEXT: fde_count_enc: 0x3 -CHECK-NEXT: table_enc: 0x3b -CHECK-NEXT: eh_frame_ptr: 0x401400 -CHECK-NEXT: fde_count: 6 -CHECK-NEXT: entry 0 { -CHECK-NEXT: initial_location: 0x4004a0 -CHECK-NEXT: address: 0x401448 -CHECK-NEXT: } -CHECK-NEXT: entry 1 { -CHECK-NEXT: initial_location: 0x4004d0 -CHECK-NEXT: address: 0x401418 -CHECK-NEXT: } -CHECK-NEXT: entry 2 { -CHECK-NEXT: initial_location: 0x4005b6 -CHECK-NEXT: address: 0x401470 -CHECK-NEXT: } -CHECK-NEXT: entry 3 { -CHECK-NEXT: initial_location: 0x4005d0 -CHECK-NEXT: address: 0x401490 -CHECK-NEXT: } -CHECK-NEXT: entry 4 { -CHECK-NEXT: initial_location: 0x401250 -CHECK-NEXT: address: 0x4014c0 -CHECK-NEXT: } -CHECK-NEXT: entry 5 { -CHECK-NEXT: initial_location: 0x4012c0 -CHECK-NEXT: address: 0x4014f0 -CHECK-NEXT: } -CHECK-NEXT: } -CHECK-NEXT:] - -CHECK: .eh_frame section at offset 0x2b8 address 0x401400: -CHECK-NEXT: [0x401400] CIE length=20 -CHECK-NEXT: version: 1 -CHECK-NEXT: augmentation: zR -CHECK-NEXT: code_alignment_factor: 1 -CHECK-NEXT: data_alignment_factor: -8 -CHECK-NEXT: return_address_register: 16 - -CHECK: Program: -CHECK-NEXT: DW_CFA_def_cfa: reg7 +8 -CHECK-NEXT: DW_CFA_offset: reg16 -8 -CHECK-NEXT: DW_CFA_undefined: reg16 - -CHECK: [0x401418] FDE length=20 cie=[0x401400] -CHECK-NEXT: initial_location: 0x4004d0 -CHECK-NEXT: address_range: 0x2a (end : 0x4004fa) - -CHECK: Program: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: - -CHECK: [0x401430] CIE length=20 -CHECK-NEXT: version: 1 -CHECK-NEXT: augmentation: zR -CHECK-NEXT: code_alignment_factor: 1 -CHECK-NEXT: data_alignment_factor: -8 -CHECK-NEXT: return_address_register: 16 - -CHECK: Program: -CHECK-NEXT: DW_CFA_def_cfa: reg7 +8 -CHECK-NEXT: DW_CFA_offset: reg16 -8 -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: - -CHECK: [0x401448] FDE length=36 cie=[0x401430] -CHECK-NEXT: initial_location: 0x4004a0 -CHECK-NEXT: address_range: 0x20 (end : 0x4004c0) - -CHECK: Program: -CHECK-NEXT: DW_CFA_def_cfa_offset: +16 -CHECK-NEXT: DW_CFA_advance_loc: 6 -CHECK-NEXT: DW_CFA_def_cfa_offset: +24 -CHECK-NEXT: DW_CFA_advance_loc: 10 -CHECK-NEXT: DW_CFA_def_cfa_expression: DW_OP_breg7 +8, DW_OP_breg16 +0, DW_OP_lit15, DW_OP_and, DW_OP_lit11, DW_OP_ge, DW_OP_lit3, DW_OP_shl, DW_OP_plus -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: - -CHECK: [0x401470] FDE length=28 cie=[0x401430] -CHECK-NEXT: initial_location: 0x4005b6 -CHECK-NEXT: address_range: 0x10 (end : 0x4005c6) - -CHECK: Program: -CHECK-NEXT: DW_CFA_advance_loc: 1 -CHECK-NEXT: DW_CFA_def_cfa_offset: +16 -CHECK-NEXT: DW_CFA_offset: reg6 -16 -CHECK-NEXT: DW_CFA_advance_loc: 3 -CHECK-NEXT: DW_CFA_def_cfa_register: reg6 -CHECK-NEXT: DW_CFA_advance_loc: 11 -CHECK-NEXT: DW_CFA_def_cfa: reg7 +8 -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: - -CHECK: [0x401490] FDE length=44 cie=[0x401430] -CHECK-NEXT: initial_location: 0x4005d0 -CHECK-NEXT: address_range: 0xc7f (end : 0x40124f) - -CHECK: Program: -CHECK-NEXT: DW_CFA_advance_loc: 5 -CHECK-NEXT: DW_CFA_def_cfa: reg10 +0 -CHECK-NEXT: DW_CFA_advance_loc: 9 -CHECK-NEXT: DW_CFA_expression: reg6 DW_OP_breg6 +0 -CHECK-NEXT: DW_CFA_advance_loc: 5 -CHECK-NEXT: DW_CFA_def_cfa_expression: DW_OP_breg6 -8, DW_OP_deref -CHECK-NEXT: DW_CFA_advance_loc2: 3174 -CHECK-NEXT: DW_CFA_def_cfa: reg10 +0 -CHECK-NEXT: DW_CFA_advance_loc: 5 -CHECK-NEXT: DW_CFA_def_cfa: reg7 +8 -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: - -CHECK: [0x4014c0] FDE length=44 cie=[0x401430] -CHECK-NEXT: initial_location: 0x401250 -CHECK-NEXT: address_range: 0x66 (end : 0x4012b6) - -CHECK: Program: -CHECK-NEXT: DW_CFA_advance_loc: 1 -CHECK-NEXT: DW_CFA_def_cfa_offset: +16 -CHECK-NEXT: DW_CFA_offset: reg6 -16 -CHECK-NEXT: DW_CFA_advance_loc: 3 -CHECK-NEXT: DW_CFA_def_cfa_register: reg6 -CHECK-NEXT: DW_CFA_advance_loc: 2 -CHECK-NEXT: DW_CFA_offset: reg15 -24 -CHECK-NEXT: DW_CFA_advance_loc: 5 -CHECK-NEXT: DW_CFA_offset: reg14 -32 -CHECK-NEXT: DW_CFA_advance_loc: 7 -CHECK-NEXT: DW_CFA_offset: reg13 -40 -CHECK-NEXT: DW_CFA_offset: reg12 -48 -CHECK-NEXT: DW_CFA_advance_loc: 8 -CHECK-NEXT: DW_CFA_offset: reg3 -56 -CHECK-NEXT: DW_CFA_advance_loc1: 75 -CHECK-NEXT: DW_CFA_def_cfa: reg7 +8 -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: - -CHECK: [0x4014f0] FDE length=20 cie=[0x401430] -CHECK-NEXT: initial_location: 0x4012c0 -CHECK-NEXT: address_range: 0x1 (end : 0x4012c1) - -CHECK: Program: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: -CHECK-NEXT: DW_CFA_nop: diff --git a/llvm/tools/llvm-readobj/CMakeLists.txt b/llvm/tools/llvm-readobj/CMakeLists.txt index b0550f3..dafc9e1 100644 --- a/llvm/tools/llvm-readobj/CMakeLists.txt +++ b/llvm/tools/llvm-readobj/CMakeLists.txt @@ -1,6 +1,5 @@ set(LLVM_LINK_COMPONENTS DebugInfoCodeView - DebugInfoDWARF Object BinaryFormat Support diff --git a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h deleted file mode 100644 index 928ac58..0000000 --- a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h +++ /dev/null @@ -1,244 +0,0 @@ -//===--- DwarfCFIEHPrinter.h - DWARF-based Unwind Information Printer -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H -#define LLVM_TOOLS_LLVM_READOBJ_DWARFCFIEHPRINTER_H - -#include "Error.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/Object/ELF.h" -#include "llvm/Object/ELFTypes.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ScopedPrinter.h" -#include "llvm/Support/Debug.h" -#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/type_traits.h" - -namespace llvm { -namespace DwarfCFIEH { - -template -class PrinterContext { - ScopedPrinter &W; - const object::ELFFile *Obj; - - void printEHFrameHdr(uint64_t Offset, uint64_t Address, uint64_t Size) const; - - void printEHFrame(const typename ELFT::Shdr *EHFrameShdr) const; - -public: - PrinterContext(ScopedPrinter &W, const object::ELFFile *Obj) - : W(W), Obj(Obj) {} - - void printUnwindInformation() const; -}; - -template -static const typename ELFO::Elf_Shdr *findSectionByAddress(const ELFO *Obj, - uint64_t Addr) { - auto Sections = Obj->sections(); - if (Error E = Sections.takeError()) - reportError(toString(std::move(E))); - - for (const auto &Shdr : *Sections) - if (Shdr.sh_addr == Addr) - return &Shdr; - return nullptr; -} - -template -void PrinterContext::printUnwindInformation() const { - const typename ELFT::Phdr *EHFramePhdr = nullptr; - - auto PHs = Obj->program_headers(); - if (Error E = PHs.takeError()) - reportError(toString(std::move(E))); - - for (const auto &Phdr : *PHs) { - if (Phdr.p_type == ELF::PT_GNU_EH_FRAME) { - EHFramePhdr = &Phdr; - if (Phdr.p_memsz != Phdr.p_filesz) - reportError("p_memsz does not match p_filesz for GNU_EH_FRAME"); - break; - } - } - - if (EHFramePhdr) - printEHFrameHdr(EHFramePhdr->p_offset, EHFramePhdr->p_vaddr, - EHFramePhdr->p_memsz); - - auto Sections = Obj->sections(); - if (Error E = Sections.takeError()) - reportError(toString(std::move(E))); - - for (const auto &Shdr : *Sections) { - auto SectionName = Obj->getSectionName(&Shdr); - if (Error E = SectionName.takeError()) - reportError(toString(std::move(E))); - - if (*SectionName == ".eh_frame") - printEHFrame(&Shdr); - } -} - -template -void PrinterContext::printEHFrameHdr(uint64_t EHFrameHdrOffset, - uint64_t EHFrameHdrAddress, - uint64_t EHFrameHdrSize) const { - ListScope L(W, "EH_FRAME Header"); - W.startLine() << format("Address: 0x%" PRIx64 "\n", EHFrameHdrAddress); - W.startLine() << format("Offset: 0x%" PRIx64 "\n", EHFrameHdrOffset); - W.startLine() << format("Size: 0x%" PRIx64 "\n", EHFrameHdrSize); - - const auto *EHFrameHdrShdr = findSectionByAddress(Obj, EHFrameHdrAddress); - if (EHFrameHdrShdr) { - auto SectionName = Obj->getSectionName(EHFrameHdrShdr); - if (Error E = SectionName.takeError()) - reportError(toString(std::move(E))); - - W.printString("Corresponding Section", *SectionName); - } - - DataExtractor DE( - StringRef(reinterpret_cast(Obj->base()) + EHFrameHdrOffset, - EHFrameHdrSize), - ELFT::TargetEndianness == support::endianness::little, - ELFT::Is64Bits ? 8 : 4); - - DictScope D(W, "Header"); - uint32_t Offset = 0; - - auto Version = DE.getU8(&Offset); - W.printNumber("version", Version); - if (Version != 1) - reportError("only version 1 of .eh_frame_hdr is supported"); - - auto EHFramePtrEnc = DE.getU8(&Offset); - W.startLine() << format("eh_frame_ptr_enc: 0x%" PRIx64 "\n", EHFramePtrEnc); - if (EHFramePtrEnc != (dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4)) - reportError("unexpected encoding eh_frame_ptr_enc"); - - auto FDECountEnc = DE.getU8(&Offset); - W.startLine() << format("fde_count_enc: 0x%" PRIx64 "\n", FDECountEnc); - if (FDECountEnc != dwarf::DW_EH_PE_udata4) - reportError("unexpected encoding fde_count_enc"); - - auto TableEnc = DE.getU8(&Offset); - W.startLine() << format("table_enc: 0x%" PRIx64 "\n", TableEnc); - if (TableEnc != (dwarf::DW_EH_PE_datarel | dwarf::DW_EH_PE_sdata4)) - reportError("unexpected encoding table_enc"); - - auto EHFramePtr = DE.getSigned(&Offset, 4) + EHFrameHdrAddress + 4; - W.startLine() << format("eh_frame_ptr: 0x%" PRIx64 "\n", EHFramePtr); - - auto FDECount = DE.getUnsigned(&Offset, 4); - W.printNumber("fde_count", FDECount); - - unsigned NumEntries = 0; - uint64_t PrevPC = 0; - while (Offset + 8 <= EHFrameHdrSize && NumEntries < FDECount) { - DictScope D(W, std::string("entry ") + std::to_string(NumEntries)); - - auto InitialPC = DE.getSigned(&Offset, 4) + EHFrameHdrAddress; - W.startLine() << format("initial_location: 0x%" PRIx64 "\n", InitialPC); - auto Address = DE.getSigned(&Offset, 4) + EHFrameHdrAddress; - W.startLine() << format("address: 0x%" PRIx64 "\n", Address); - - if (InitialPC < PrevPC) - reportError("initial_location is out of order"); - - PrevPC = InitialPC; - ++NumEntries; - } -} - -template -void PrinterContext::printEHFrame( - const typename ELFT::Shdr *EHFrameShdr) const { - uint64_t Address = EHFrameShdr->sh_addr; - uint64_t ShOffset = EHFrameShdr->sh_offset; - W.startLine() << format(".eh_frame section at offset 0x%" PRIx64 - " address 0x%" PRIx64 ":\n", - ShOffset, Address); - W.indent(); - - auto Result = Obj->getSectionContents(EHFrameShdr); - if (Error E = Result.takeError()) - reportError(toString(std::move(E))); - - auto Contents = Result.get(); - DWARFDataExtractor DE( - StringRef(reinterpret_cast(Contents.data()), - Contents.size()), - ELFT::TargetEndianness == support::endianness::little, - ELFT::Is64Bits ? 8 : 4); - DWARFDebugFrame EHFrame(/*IsEH=*/true, /*EHFrameAddress=*/Address); - EHFrame.parse(DE); - - for (const auto &Entry : EHFrame) { - if (const auto *CIE = dyn_cast(&Entry)) { - W.startLine() << format("[0x%" PRIx64 "] CIE length=%" PRIu64 "\n", - Address + CIE->getOffset(), - CIE->getLength()); - W.indent(); - - W.printNumber("version", CIE->getVersion()); - W.printString("augmentation", CIE->getAugmentationString()); - W.printNumber("code_alignment_factor", CIE->getCodeAlignmentFactor()); - W.printNumber("data_alignment_factor", CIE->getDataAlignmentFactor()); - W.printNumber("return_address_register", CIE->getReturnAddressRegister()); - - W.getOStream() << "\n"; - W.startLine() << "Program:\n"; - W.indent(); - CIE->cfis().dump(W.getOStream(), nullptr, W.getIndentLevel()); - W.unindent(); - - W.unindent(); - W.getOStream() << "\n"; - - } else if (const auto *FDE = dyn_cast(&Entry)) { - W.startLine() << format("[0x%" PRIx64 "] FDE length=%" PRIu64 - " cie=[0x%" PRIx64 "]\n", - Address + FDE->getOffset(), - FDE->getLength(), - Address + FDE->getLinkedCIE()->getOffset()); - W.indent(); - - W.startLine() << format("initial_location: 0x%" PRIx64 "\n", - FDE->getInitialLocation()); - W.startLine() - << format("address_range: 0x%" PRIx64 " (end : 0x%" PRIx64 ")\n", - FDE->getAddressRange(), - FDE->getInitialLocation() + FDE->getAddressRange()); - - W.getOStream() << "\n"; - W.startLine() << "Program:\n"; - W.indent(); - FDE->cfis().dump(W.getOStream(), nullptr, W.getIndentLevel()); - W.unindent(); - - W.unindent(); - W.getOStream() << "\n"; - } else { - llvm_unreachable("unexpected DWARF frame kind"); - } - } - - W.unindent(); -} - -} -} - -#endif diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 6b6582b..36cda45 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// #include "ARMEHABIPrinter.h" -#include "DwarfCFIEHPrinter.h" #include "Error.h" #include "ObjDumper.h" #include "StackMapPrinter.h" @@ -1809,11 +1808,6 @@ void ELFDumper::printValue(uint64_t Type, uint64_t Value) { template void ELFDumper::printUnwindInfo() { - const unsigned Machine = Obj->getHeader()->e_machine; - if (Machine == EM_386 || Machine == EM_X86_64) { - DwarfCFIEH::PrinterContext Ctx(W, Obj); - return Ctx.printUnwindInformation(); - } W.startLine() << "UnwindInfo not implemented.\n"; } -- 2.7.4