diff options
author | Rui Ueyama <ruiu@google.com> | 2018-03-07 22:29:48 +0000 |
---|---|---|
committer | Rui Ueyama <ruiu@google.com> | 2018-03-07 22:29:48 +0000 |
commit | 6aa8b3491f866eadfa0b7e9aef21a416fac466f9 (patch) | |
tree | cf01742382e9481da9581758b6bad952d8a69294 /llvm/lib/DebugInfo | |
parent | 8e3a659105fc0934841d857193bc1521ae070b39 (diff) | |
download | bcm5719-llvm-6aa8b3491f866eadfa0b7e9aef21a416fac466f9.tar.gz bcm5719-llvm-6aa8b3491f866eadfa0b7e9aef21a416fac466f9.zip |
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
Diffstat (limited to 'llvm/lib/DebugInfo')
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFContext.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp | 69 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp | 545 | ||||
-rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp | 5 |
4 files changed, 369 insertions, 262 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp index 2b1c91ee7b0..de7ef662afb 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 03e31746139..861dd313fb0 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<uint64_t> -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 b9dc2151e06..3312da67804 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<uint64_t>; + 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; -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<StringError>( - "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<StringError>( - "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::OperandType[2]> CFIProgram::getOperandTypes() { +/// \brief Initialize the array describing the types of operands. +static ArrayRef<OperandType[2]> getOperandTypes() { static OperandType OpTypes[DW_CFA_restore+1][2]; - static bool Initialized = false; - if (Initialized) { - return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1); - } - Initialized = true; #define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \ do { \ @@ -213,13 +396,15 @@ ArrayRef<CFIProgram::OperandType[2]> CFIProgram::getOperandTypes() { return ArrayRef<OperandType[2]>(&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<OperandType[2]> 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<CIE>(this); + + if (!Cie) + Cie = cast<FDE>(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<uint32_t, CIE *> 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<uint64_t> Personality; - Optional<uint32_t> PersonalityEncoding; if (IsEH) { + Optional<uint32_t> PersonalityEncoding; + Optional<uint64_t> Personality; + Optional<uint64_t> 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<CIE>( - StartOffset, Length, Version, AugmentationString, AddressSize, - SegmentDescriptorSize, CodeAlignmentFactor, DataAlignmentFactor, - ReturnAddressRegister, AugmentationData, FDEPointerEncoding, - LSDAPointerEncoding, Personality, PersonalityEncoding); + auto Cie = llvm::make_unique<CIE>(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<uint64_t> 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<uint32_t>(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<uint64_t> Offset) const { +void DWARFDebugFrame::dump(raw_ostream &OS, Optional<uint64_t> 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 a9ea26c476c..c704c2901ae 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)); |