diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h index e6a589c2b929..4d624812f186 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -12,6 +12,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/Support/DataExtractor.h" #include @@ -43,10 +44,10 @@ class DWARFDebugLine { /// The size in bytes of the statement information for this compilation unit /// (not including the total_length field itself). uint64_t TotalLength; - /// Version identifier for the statement information format. - uint16_t Version; - /// In v5, size in bytes of an address (or segment offset). - uint8_t AddressSize; + /// Version, address size (starting in v5), and DWARF32/64 format; these + /// parameters affect interpretation of forms (used in the directory and + /// file tables starting with v5). + DWARFFormParams FormParams; /// In v5, size in bytes of a segment selector. uint8_t SegSelectorSize; /// The number of bytes following the prologue_length field to the beginning @@ -71,15 +72,18 @@ class DWARFDebugLine { std::vector IncludeDirectories; std::vector FileNames; - bool IsDWARF64; + const DWARFFormParams getFormParams() const { return FormParams; } + uint16_t getVersion() const { return FormParams.Version; } + uint8_t getAddressSize() const { return FormParams.AddrSize; } + bool isDWARF64() const { return FormParams.Format == dwarf::DWARF64; } - uint32_t sizeofTotalLength() const { return IsDWARF64 ? 12 : 4; } + uint32_t sizeofTotalLength() const { return isDWARF64() ? 12 : 4; } - uint32_t sizeofPrologueLength() const { return IsDWARF64 ? 8 : 4; } + uint32_t sizeofPrologueLength() const { return isDWARF64() ? 8 : 4; } /// Length of the prologue in bytes. uint32_t getLength() const { - return PrologueLength + sizeofTotalLength() + sizeof(Version) + + return PrologueLength + sizeofTotalLength() + sizeof(getVersion()) + sizeofPrologueLength(); } diff --git a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h index d6a3b52f2fe1..471663113075 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -22,6 +22,35 @@ namespace llvm { class DWARFUnit; class raw_ostream; +/// A helper struct for DWARFFormValue methods, providing information that +/// allows it to know the byte size of DW_FORM values that vary in size +/// depending on the DWARF version, address byte size, or DWARF32/DWARF64. +struct DWARFFormParams { + uint16_t Version; + uint8_t AddrSize; + dwarf::DwarfFormat Format; + + /// The definition of the size of form DW_FORM_ref_addr depends on the + /// version. In DWARF v2 it's the size of an address; after that, it's the + /// size of a reference. + uint8_t getRefAddrByteSize() const { + if (Version == 2) + return AddrSize; + return getDwarfOffsetByteSize(); + } + + /// The size of a reference is determined by the DWARF 32/64-bit format. + uint8_t getDwarfOffsetByteSize() const { + switch (Format) { + case dwarf::DwarfFormat::DWARF32: + return 4; + case dwarf::DwarfFormat::DWARF64: + return 8; + } + llvm_unreachable("Invalid Format value"); + } +}; + class DWARFFormValue { public: enum FormClass { @@ -104,79 +133,43 @@ class DWARFFormValue { /// Get the fixed byte size for a given form. /// - /// If the form always has a fixed valid byte size that doesn't depend on a - /// DWARFUnit, then an Optional with a value will be returned. If the form - /// can vary in size depending on the DWARFUnit (DWARF version, address byte - /// size, or DWARF 32/64) and the DWARFUnit is valid, then an Optional with a - /// valid value is returned. If the form is always encoded using a variable - /// length storage format (ULEB or SLEB numbers or blocks) or the size - /// depends on a DWARFUnit and the DWARFUnit is NULL, then None will be - /// returned. - /// \param Form The DWARF form to get the fixed byte size for - /// \param U The DWARFUnit that can be used to help determine the byte size. - /// - /// \returns Optional value with the fixed byte size or None if - /// \p Form doesn't have a fixed byte size or a DWARFUnit wasn't supplied - /// and was needed to calculate the byte size. - static Optional getFixedByteSize(dwarf::Form Form, - const DWARFUnit *U = nullptr); - - /// Get the fixed byte size for a given form. - /// - /// If the form has a fixed byte size given a valid DWARF version and address - /// byte size, then an Optional with a valid value is returned. If the form - /// is always encoded using a variable length storage format (ULEB or SLEB - /// numbers or blocks) then None will be returned. + /// If the form has a fixed byte size, then an Optional with a value will be + /// returned. If the form is always encoded using a variable length storage + /// format (ULEB or SLEB numbers or blocks) then None will be returned. /// - /// \param Form DWARF form to get the fixed byte size for - /// \param Version DWARF version number. - /// \param AddrSize size of an address in bytes. - /// \param Format enum value from llvm::dwarf::DwarfFormat. + /// \param Form DWARF form to get the fixed byte size for. + /// \param FormParams DWARF parameters to help interpret forms. /// \returns Optional value with the fixed byte size or None if /// \p Form doesn't have a fixed byte size. - static Optional getFixedByteSize(dwarf::Form Form, uint16_t Version, - uint8_t AddrSize, - llvm::dwarf::DwarfFormat Format); + static Optional getFixedByteSize(dwarf::Form Form, + const DWARFFormParams &FormParams); - /// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr. + /// Skip a form's value in \p DebugInfoData at the offset specified by + /// \p OffsetPtr. /// - /// Skips the bytes for this form in the debug info and updates the offset. + /// Skips the bytes for the current form and updates the offset. /// - /// \param DebugInfoData the .debug_info data to use to skip the value. - /// \param OffsetPtr a reference to the offset that will be updated. - /// \param U the DWARFUnit to use when skipping the form in case the form - /// size differs according to data in the DWARFUnit. + /// \param DebugInfoData The data where we want to skip the value. + /// \param OffsetPtr A reference to the offset that will be updated. + /// \param Params DWARF parameters to help interpret forms. /// \returns true on success, false if the form was not skipped. bool skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr, - const DWARFUnit *U) const; - - /// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr. - /// - /// Skips the bytes for this form in the debug info and updates the offset. - /// - /// \param Form the DW_FORM enumeration that indicates the form to skip. - /// \param DebugInfoData the .debug_info data to use to skip the value. - /// \param OffsetPtr a reference to the offset that will be updated. - /// \param U the DWARFUnit to use when skipping the form in case the form - /// size differs according to data in the DWARFUnit. - /// \returns true on success, false if the form was not skipped. - static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData, - uint32_t *OffsetPtr, const DWARFUnit *U); + const DWARFFormParams &Params) const { + return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, Params); + } - /// Skip a form in \p DebugInfoData at offset specified by \p OffsetPtr. + /// Skip a form's value in \p DebugInfoData at the offset specified by + /// \p OffsetPtr. /// - /// Skips the bytes for this form in the debug info and updates the offset. + /// Skips the bytes for the specified form and updates the offset. /// - /// \param Form the DW_FORM enumeration that indicates the form to skip. - /// \param DebugInfoData the .debug_info data to use to skip the value. - /// \param OffsetPtr a reference to the offset that will be updated. - /// \param Version DWARF version number. - /// \param AddrSize size of an address in bytes. - /// \param Format enum value from llvm::dwarf::DwarfFormat. + /// \param Form The DW_FORM enumeration that indicates the form to skip. + /// \param DebugInfoData The data where we want to skip the value. + /// \param OffsetPtr A reference to the offset that will be updated. + /// \param FormParams DWARF parameters to help interpret forms. /// \returns true on success, false if the form was not skipped. static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData, - uint32_t *OffsetPtr, uint16_t Version, uint8_t AddrSize, - llvm::dwarf::DwarfFormat Format); + uint32_t *OffsetPtr, const DWARFFormParams &FormParams); private: void dumpString(raw_ostream &OS) const; diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h index fd276062ba4a..d7ccaf82bc9a 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -19,6 +19,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" @@ -127,12 +128,13 @@ class DWARFUnit { bool isDWO; const DWARFUnitSectionBase &UnitSection; + // Version, address size, and DWARF format. + DWARFFormParams FormParams; + uint32_t Offset; uint32_t Length; const DWARFAbbreviationDeclarationSet *Abbrevs; - uint16_t Version; uint8_t UnitType; - uint8_t AddrSize; uint64_t BaseAddr; /// The compile unit debug information entry items. std::vector DieArray; @@ -159,7 +161,7 @@ class DWARFUnit { virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr); /// Size in bytes of the unit header. - virtual uint32_t getHeaderSize() const { return Version <= 4 ? 11 : 12; } + virtual uint32_t getHeaderSize() const { return getVersion() <= 4 ? 11 : 12; } public: DWARFUnit(DWARFContext &Context, const DWARFSection &Section, @@ -197,7 +199,8 @@ class DWARFUnit { uint64_t getStringOffsetSectionRelocation(uint32_t Index) const; DataExtractor getDebugInfoExtractor() const { - return DataExtractor(InfoSection.Data, isLittleEndian, AddrSize); + return DataExtractor(InfoSection.Data, isLittleEndian, + getAddressByteSize()); } DataExtractor getStringExtractor() const { @@ -220,10 +223,14 @@ class DWARFUnit { uint32_t getOffset() const { return Offset; } uint32_t getNextUnitOffset() const { return Offset + Length + 4; } uint32_t getLength() const { return Length; } - uint16_t getVersion() const { return Version; } - dwarf::DwarfFormat getFormat() const { - return dwarf::DwarfFormat::DWARF32; // FIXME: Support DWARF64. + const DWARFFormParams &getFormParams() const { return FormParams; } + uint16_t getVersion() const { return FormParams.Version; } + dwarf::DwarfFormat getFormat() const { return FormParams.Format; } + uint8_t getAddressByteSize() const { return FormParams.AddrSize; } + uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); } + uint8_t getDwarfOffsetByteSize() const { + return FormParams.getDwarfOffsetByteSize(); } const DWARFAbbreviationDeclarationSet *getAbbreviations() const { @@ -231,19 +238,6 @@ class DWARFUnit { } uint8_t getUnitType() const { return UnitType; } - uint8_t getAddressByteSize() const { return AddrSize; } - - uint8_t getRefAddrByteSize() const { - if (Version == 2) - return AddrSize; - return getDwarfOffsetByteSize(); - } - - uint8_t getDwarfOffsetByteSize() const { - if (getFormat() == dwarf::DwarfFormat::DWARF64) - return 8; - return 4; - } uint64_t getBaseAddress() const { return BaseAddr; } diff --git a/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp index 57eac91f8c19..bb475a669efb 100644 --- a/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp +++ b/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp @@ -65,46 +65,52 @@ DWARFAbbreviationDeclaration::extract(DataExtractor Data, if (A && F) { Optional V; bool IsImplicitConst = (F == DW_FORM_implicit_const); - if (IsImplicitConst) + if (IsImplicitConst) { V = Data.getSLEB128(OffsetPtr); - else if (auto Size = DWARFFormValue::getFixedByteSize(F)) - V = *Size; - AttributeSpecs.push_back(AttributeSpec(A, F, V)); - if (IsImplicitConst) + AttributeSpecs.push_back(AttributeSpec(A, F, V)); continue; + } // If this abbrevation still has a fixed byte size, then update the // FixedAttributeSize as needed. - if (FixedAttributeSize) { - if (V) - FixedAttributeSize->NumBytes += *V; - else { - switch (F) { - case DW_FORM_addr: - ++FixedAttributeSize->NumAddrs; - break; - - case DW_FORM_ref_addr: - ++FixedAttributeSize->NumRefAddrs; - break; - - case DW_FORM_strp: - case DW_FORM_GNU_ref_alt: - case DW_FORM_GNU_strp_alt: - case DW_FORM_line_strp: - case DW_FORM_sec_offset: - case DW_FORM_strp_sup: - ++FixedAttributeSize->NumDwarfOffsets; - break; - - default: - // Indicate we no longer have a fixed byte size for this - // abbreviation by clearing the FixedAttributeSize optional value - // so it doesn't have a value. - FixedAttributeSize.reset(); - break; - } + switch (F) { + case DW_FORM_addr: + if (FixedAttributeSize) + ++FixedAttributeSize->NumAddrs; + break; + + case DW_FORM_ref_addr: + if (FixedAttributeSize) + ++FixedAttributeSize->NumRefAddrs; + break; + + case DW_FORM_strp: + case DW_FORM_GNU_ref_alt: + case DW_FORM_GNU_strp_alt: + case DW_FORM_line_strp: + case DW_FORM_sec_offset: + case DW_FORM_strp_sup: + if (FixedAttributeSize) + ++FixedAttributeSize->NumDwarfOffsets; + break; + + default: + // The form has a byte size that doesn't depend on Params. + // If it's a fixed size, keep track of it. + if (auto Size = + DWARFFormValue::getFixedByteSize(F, DWARFFormParams())) { + V = *Size; + if (FixedAttributeSize) + FixedAttributeSize->NumBytes += *V; + break; } + // Indicate we no longer have a fixed byte size for this + // abbreviation by clearing the FixedAttributeSize optional value + // so it doesn't have a value. + FixedAttributeSize.reset(); + break; } + // Record this attribute and its fixed size if it has one. + AttributeSpecs.push_back(AttributeSpec(A, F, V)); } else if (A == 0 && F == 0) { // We successfully reached the end of this abbreviation declaration // since both attribute and form are zero. @@ -186,7 +192,8 @@ Optional DWARFAbbreviationDeclaration::getAttributeValue( if (auto FixedSize = Spec.getByteSize(U)) Offset += *FixedSize; else - DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset, &U); + DWARFFormValue::skipValue(Spec.Form, DebugInfoData, &Offset, + U.getFormParams()); ++AttrIndex; } return None; @@ -211,7 +218,8 @@ Optional DWARFAbbreviationDeclaration::AttributeSpec::getByteSize( if (ByteSizeOrValue) return ByteSizeOrValue; Optional S; - auto FixedByteSize = DWARFFormValue::getFixedByteSize(Form, &U); + auto FixedByteSize = + DWARFFormValue::getFixedByteSize(Form, U.getFormParams()); if (FixedByteSize) S = *FixedByteSize; return S; diff --git a/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp index dbcc64fc0832..1551974b822a 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -59,7 +59,7 @@ bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint32_t *OffsetPtr, // Attribute byte size if fixed, just add the size to the offset. *OffsetPtr += *FixedSize; } else if (!DWARFFormValue::skipValue(AttrSpec.Form, DebugInfoData, - OffsetPtr, &U)) { + OffsetPtr, U.getFormParams())) { // We failed to skip this attribute's value, restore the original offset // and return the failure status. *OffsetPtr = Offset; diff --git a/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/lib/DebugInfo/DWARF/DWARFDebugLine.cpp index 72d8760751d8..ad5647f3e03d 100644 --- a/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -44,11 +44,11 @@ using ContentDescriptors = SmallVector; DWARFDebugLine::Prologue::Prologue() { clear(); } void DWARFDebugLine::Prologue::clear() { - TotalLength = Version = PrologueLength = 0; - AddressSize = SegSelectorSize = 0; + TotalLength = PrologueLength = 0; + SegSelectorSize = 0; MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0; OpcodeBase = 0; - IsDWARF64 = false; + FormParams = DWARFFormParams({0, 0, DWARF32}); StandardOpcodeLengths.clear(); IncludeDirectories.clear(); FileNames.clear(); @@ -57,12 +57,13 @@ void DWARFDebugLine::Prologue::clear() { void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const { OS << "Line table prologue:\n" << format(" total_length: 0x%8.8" PRIx64 "\n", TotalLength) - << format(" version: %u\n", Version) - << format(Version >= 5 ? " address_size: %u\n" : "", AddressSize) - << format(Version >= 5 ? " seg_select_size: %u\n" : "", SegSelectorSize) - << format(" prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength) + << format(" version: %u\n", getVersion()); + if (getVersion() >= 5) + OS << format(" address_size: %u\n", getAddressSize()) + << format(" seg_select_size: %u\n", SegSelectorSize); + OS << format(" prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength) << format(" min_inst_length: %u\n", MinInstLength) - << format(Version >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst) + << format(getVersion() >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst) << format(" default_is_stmt: %u\n", DefaultIsStmt) << format(" line_base: %i\n", LineBase) << format(" line_range: %u\n", LineRange) @@ -143,6 +144,7 @@ parseV5EntryFormat(DataExtractor DebugLineData, uint32_t *OffsetPtr, static bool parseV5DirFileTables(DataExtractor DebugLineData, uint32_t *OffsetPtr, uint64_t EndPrologueOffset, + const DWARFFormParams &FormParams, std::vector &IncludeDirectories, std::vector &FileNames) { // Get the directory entry description. @@ -165,7 +167,7 @@ parseV5DirFileTables(DataExtractor DebugLineData, uint32_t *OffsetPtr, IncludeDirectories.push_back(Value.getAsCString().getValue()); break; default: - if (!Value.skipValue(DebugLineData, OffsetPtr, nullptr)) + if (!Value.skipValue(DebugLineData, OffsetPtr, FormParams)) return false; } } @@ -217,24 +219,26 @@ bool DWARFDebugLine::Prologue::parse(DataExtractor DebugLineData, clear(); TotalLength = DebugLineData.getU32(OffsetPtr); if (TotalLength == UINT32_MAX) { - IsDWARF64 = true; + FormParams.Format = dwarf::DWARF64; TotalLength = DebugLineData.getU64(OffsetPtr); - } else if (TotalLength > 0xffffff00) { + } else if (TotalLength >= 0xffffff00) { return false; } - Version = DebugLineData.getU16(OffsetPtr); - if (Version < 2) + FormParams.Version = DebugLineData.getU16(OffsetPtr); + if (getVersion() < 2) return false; - if (Version >= 5) { - AddressSize = DebugLineData.getU8(OffsetPtr); + if (getVersion() >= 5) { + FormParams.AddrSize = DebugLineData.getU8(OffsetPtr); + assert(getAddressSize() == DebugLineData.getAddressSize() && + "Line table header and data extractor disagree"); SegSelectorSize = DebugLineData.getU8(OffsetPtr); } PrologueLength = DebugLineData.getUnsigned(OffsetPtr, sizeofPrologueLength()); const uint64_t EndPrologueOffset = PrologueLength + *OffsetPtr; MinInstLength = DebugLineData.getU8(OffsetPtr); - if (Version >= 4) + if (getVersion() >= 4) MaxOpsPerInst = DebugLineData.getU8(OffsetPtr); DefaultIsStmt = DebugLineData.getU8(OffsetPtr); LineBase = DebugLineData.getU8(OffsetPtr); @@ -247,9 +251,9 @@ bool DWARFDebugLine::Prologue::parse(DataExtractor DebugLineData, StandardOpcodeLengths.push_back(OpLen); } - if (Version >= 5) { + if (getVersion() >= 5) { if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset, - IncludeDirectories, FileNames)) { + getFormParams(), IncludeDirectories, FileNames)) { fprintf(stderr, "warning: parsing line table prologue at 0x%8.8" PRIx64 " found an invalid directory or file table description at" diff --git a/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/lib/DebugInfo/DWARF/DWARFFormValue.cpp index 39c1f5fd5c51..dda4a0cdb316 100644 --- a/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ b/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -59,48 +59,13 @@ static const DWARFFormValue::FormClass DWARF4FormClasses[] = { DWARFFormValue::FC_Flag, // 0x19 DW_FORM_flag_present }; -namespace { - -/// A helper class that can be used in DWARFFormValue.cpp functions that need -/// to know the byte size of DW_FORM values that vary in size depending on the -/// DWARF version, address byte size, or DWARF32 or DWARF64. -class FormSizeHelper { - uint16_t Version; - uint8_t AddrSize; - llvm::dwarf::DwarfFormat Format; - -public: - FormSizeHelper(uint16_t V, uint8_t A, llvm::dwarf::DwarfFormat F) - : Version(V), AddrSize(A), Format(F) {} - - uint8_t getAddressByteSize() const { return AddrSize; } - - uint8_t getRefAddrByteSize() const { - if (Version == 2) - return AddrSize; - return getDwarfOffsetByteSize(); - } - - uint8_t getDwarfOffsetByteSize() const { - switch (Format) { - case dwarf::DwarfFormat::DWARF32: - return 4; - case dwarf::DwarfFormat::DWARF64: - return 8; - } - llvm_unreachable("Invalid Format value"); - } -}; - -} // end anonymous namespace - -template -static Optional getFixedByteSize(dwarf::Form Form, const T *U) { +Optional +DWARFFormValue::getFixedByteSize(dwarf::Form Form, + const DWARFFormParams &Params) { switch (Form) { case DW_FORM_addr: - if (U) - return U->getAddressByteSize(); - return None; + assert(Params.Version && Params.AddrSize && "Invalid Params for form"); + return Params.AddrSize; case DW_FORM_block: // ULEB128 length L followed by L bytes. case DW_FORM_block1: // 1 byte length L followed by L bytes. @@ -121,9 +86,8 @@ static Optional getFixedByteSize(dwarf::Form Form, const T *U) { return None; case DW_FORM_ref_addr: - if (U) - return U->getRefAddrByteSize(); - return None; + assert(Params.Version && Params.AddrSize && "Invalid Params for form"); + return Params.getRefAddrByteSize(); case DW_FORM_flag: case DW_FORM_data1: @@ -154,9 +118,8 @@ static Optional getFixedByteSize(dwarf::Form Form, const T *U) { case DW_FORM_line_strp: case DW_FORM_sec_offset: case DW_FORM_strp_sup: - if (U) - return U->getDwarfOffsetByteSize(); - return None; + assert(Params.Version && Params.AddrSize && "Invalid Params for form"); + return Params.getDwarfOffsetByteSize(); case DW_FORM_data8: case DW_FORM_ref8: @@ -181,9 +144,9 @@ static Optional getFixedByteSize(dwarf::Form Form, const T *U) { return None; } -template -static bool skipFormValue(dwarf::Form Form, const DataExtractor &DebugInfoData, - uint32_t *OffsetPtr, const T *U) { +bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, + uint32_t *OffsetPtr, + const DWARFFormParams &Params) { bool Indirect = false; do { switch (Form) { @@ -243,7 +206,8 @@ static bool skipFormValue(dwarf::Form Form, const DataExtractor &DebugInfoData, case DW_FORM_line_strp: case DW_FORM_GNU_ref_alt: case DW_FORM_GNU_strp_alt: - if (Optional FixedSize = ::getFixedByteSize(Form, U)) { + if (Optional FixedSize = + DWARFFormValue::getFixedByteSize(Form, Params)) { *OffsetPtr += *FixedSize; return true; } @@ -277,19 +241,6 @@ static bool skipFormValue(dwarf::Form Form, const DataExtractor &DebugInfoData, return true; } -Optional DWARFFormValue::getFixedByteSize(dwarf::Form Form, - const DWARFUnit *U) { - return ::getFixedByteSize(Form, U); -} - -Optional -DWARFFormValue::getFixedByteSize(dwarf::Form Form, uint16_t Version, - uint8_t AddrSize, - llvm::dwarf::DwarfFormat Format) { - FormSizeHelper FSH(Version, AddrSize, Format); - return ::getFixedByteSize(Form, &FSH); -} - bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const { // First, check DWARF4 form classes. if (Form < makeArrayRef(DWARF4FormClasses).size() && @@ -448,24 +399,6 @@ bool DWARFFormValue::extractValue(const DataExtractor &Data, return true; } -bool DWARFFormValue::skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr, - const DWARFUnit *U) const { - return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U); -} - -bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, - uint32_t *OffsetPtr, const DWARFUnit *U) { - return skipFormValue(Form, DebugInfoData, OffsetPtr, U); -} - -bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData, - uint32_t *OffsetPtr, uint16_t Version, - uint8_t AddrSize, - llvm::dwarf::DwarfFormat Format) { - FormSizeHelper FSH(Version, AddrSize, Format); - return skipFormValue(Form, DebugInfoData, OffsetPtr, &FSH); -} - void DWARFFormValue::dump(raw_ostream &OS) const { uint64_t UValue = Value.uval; bool CURelativeOffset = false; diff --git a/lib/DebugInfo/DWARF/DWARFUnit.cpp b/lib/DebugInfo/DWARF/DWARFUnit.cpp index ded9b2abf64c..fd9c7c2b1d46 100644 --- a/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -62,11 +62,13 @@ DWARFUnit::~DWARFUnit() = default; bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const { - uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize; - if (AddrOffsetSection->Data.size() < Offset + AddrSize) + uint32_t Offset = AddrOffsetSectionBase + Index * getAddressByteSize(); + if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize()) return false; - DataExtractor DA(AddrOffsetSection->Data, isLittleEndian, AddrSize); - Result = getRelocatedValue(DA, AddrSize, &Offset, &AddrOffsetSection->Relocs); + DataExtractor DA(AddrOffsetSection->Data, isLittleEndian, + getAddressByteSize()); + Result = getRelocatedValue(DA, getAddressByteSize(), &Offset, + &AddrOffsetSection->Relocs); return true; } @@ -92,15 +94,17 @@ uint64_t DWARFUnit::getStringOffsetSectionRelocation(uint32_t Index) const { bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) { Length = debug_info.getU32(offset_ptr); - Version = debug_info.getU16(offset_ptr); + // FIXME: Support DWARF64. + FormParams.Format = DWARF32; + FormParams.Version = debug_info.getU16(offset_ptr); uint64_t AbbrOffset; - if (Version >= 5) { + if (FormParams.Version >= 5) { UnitType = debug_info.getU8(offset_ptr); - AddrSize = debug_info.getU8(offset_ptr); + FormParams.AddrSize = debug_info.getU8(offset_ptr); AbbrOffset = debug_info.getU32(offset_ptr); } else { AbbrOffset = debug_info.getU32(offset_ptr); - AddrSize = debug_info.getU8(offset_ptr); + FormParams.AddrSize = debug_info.getU8(offset_ptr); } if (IndexEntry) { if (AbbrOffset) @@ -115,14 +119,14 @@ bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) { } bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); - bool VersionOK = DWARFContext::isSupportedVersion(Version); - bool AddrSizeOK = AddrSize == 4 || AddrSize == 8; + bool VersionOK = DWARFContext::isSupportedVersion(getVersion()); + bool AddrSizeOK = getAddressByteSize() == 4 || getAddressByteSize() == 8; if (!LengthOK || !VersionOK || !AddrSizeOK) return false; // Keep track of the highest DWARF version we encounter across all units. - Context.setMaxVersionIfGreater(Version); + Context.setMaxVersionIfGreater(getVersion()); Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset); return Abbrevs != nullptr; @@ -148,7 +152,8 @@ bool DWARFUnit::extractRangeList(uint32_t RangeListOffset, DWARFDebugRangeList &RangeList) const { // Require that compile unit is extracted. assert(!DieArray.empty()); - DataExtractor RangesData(RangeSection->Data, isLittleEndian, AddrSize); + DataExtractor RangesData(RangeSection->Data, isLittleEndian, + getAddressByteSize()); uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; return RangeList.extract(RangesData, &ActualRangeListOffset, RangeSection->Relocs); @@ -157,9 +162,8 @@ bool DWARFUnit::extractRangeList(uint32_t RangeListOffset, void DWARFUnit::clear() { Offset = 0; Length = 0; - Version = 0; Abbrevs = nullptr; - AddrSize = 0; + FormParams = DWARFFormParams({0, 0, DWARF32}); BaseAddr = 0; RangeSectionBase = 0; AddrOffsetSectionBase = 0; diff --git a/tools/dsymutil/DwarfLinker.cpp b/tools/dsymutil/DwarfLinker.cpp index 88de2706544e..ba5c63846b50 100644 --- a/tools/dsymutil/DwarfLinker.cpp +++ b/tools/dsymutil/DwarfLinker.cpp @@ -2063,10 +2063,12 @@ getAttributeOffsets(const DWARFAbbreviationDeclaration *Abbrev, unsigned Idx, DataExtractor Data = Unit.getDebugInfoExtractor(); for (unsigned i = 0; i < Idx; ++i) - DWARFFormValue::skipValue(Abbrev->getFormByIndex(i), Data, &Offset, &Unit); + DWARFFormValue::skipValue(Abbrev->getFormByIndex(i), Data, &Offset, + Unit.getFormParams()); uint32_t End = Offset; - DWARFFormValue::skipValue(Abbrev->getFormByIndex(Idx), Data, &End, &Unit); + DWARFFormValue::skipValue(Abbrev->getFormByIndex(Idx), Data, &End, + Unit.getFormParams()); return std::make_pair(Offset, End); } @@ -2219,7 +2221,8 @@ void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr, DWARFFormValue Val(AttrSpec.Form); if (!Val.isFormClass(DWARFFormValue::FC_Reference)) { - DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, &Unit); + DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, + Unit.getFormParams()); continue; } @@ -2779,7 +2782,8 @@ DIE *DwarfLinker::DIECloner::cloneDIE( for (const auto &AttrSpec : Abbrev->attributes()) { if (shouldSkipAttribute(AttrSpec, Die->getTag(), Info.InDebugMap, Flags & TF_SkipPC, Flags & TF_InFunctionScope)) { - DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, &U); + DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset, + U.getFormParams()); // FIXME: dsymutil-classic keeps the old abbreviation around // even if it's not used. We can remove this (and the copyAbbrev // helper) as soon as bit-for-bit compatibility is not a goal anymore. @@ -3077,7 +3081,7 @@ void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit, // prologue over and that works because we act as both producer and // consumer. It would be nicer to have a real configurable line // table emitter. - if (LineTable.Prologue.Version != 2 || + if (LineTable.Prologue.getVersion() != 2 || LineTable.Prologue.DefaultIsStmt != DWARF2_LINE_DEFAULT_IS_STMT || LineTable.Prologue.OpcodeBase > 13) reportWarning("line table parameters mismatch. Cannot emit."); diff --git a/tools/llvm-dwp/llvm-dwp.cpp b/tools/llvm-dwp/llvm-dwp.cpp index f8d00b3b5534..7a6922d8a3fc 100644 --- a/tools/llvm-dwp/llvm-dwp.cpp +++ b/tools/llvm-dwp/llvm-dwp.cpp @@ -182,8 +182,8 @@ static Expected getCUIdentifiers(StringRef Abbrev, ID.Signature = InfoData.getU64(&Offset); break; default: - DWARFFormValue::skipValue(Form, InfoData, &Offset, Version, AddrSize, - Format); + DWARFFormValue::skipValue(Form, InfoData, &Offset, + DWARFFormParams({Version, AddrSize, Format})); } } return ID; diff --git a/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp b/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp index da7f43e721aa..621796b684d6 100644 --- a/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp +++ b/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp @@ -23,43 +23,52 @@ namespace { TEST(DWARFFormValue, FixedFormSizes) { Optional RefSize; Optional AddrSize; + // Test 32 bit DWARF version 2 with 4 byte addresses. - RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 4, DWARF32); - AddrSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 4, DWARF32); + DWARFFormParams Params_2_4_32 = {2, 4, DWARF32}; + RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_2_4_32); + AddrSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_2_4_32); EXPECT_TRUE(RefSize.hasValue()); EXPECT_TRUE(AddrSize.hasValue()); EXPECT_EQ(*RefSize, *AddrSize); // Test 32 bit DWARF version 2 with 8 byte addresses. - RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 8, DWARF32); - AddrSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 2, 8, DWARF32); + DWARFFormParams Params_2_8_32 = {2, 8, DWARF32}; + RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_2_8_32); + AddrSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_2_8_32); EXPECT_TRUE(RefSize.hasValue()); EXPECT_TRUE(AddrSize.hasValue()); EXPECT_EQ(*RefSize, *AddrSize); // DW_FORM_ref_addr is 4 bytes in DWARF 32 in DWARF version 3 and beyond. - RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 3, 4, DWARF32); + DWARFFormParams Params_3_4_32 = {3, 4, DWARF32}; + RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_3_4_32); EXPECT_TRUE(RefSize.hasValue()); EXPECT_EQ(*RefSize, 4); - RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 4, 4, DWARF32); + DWARFFormParams Params_4_4_32 = {4, 4, DWARF32}; + RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_4_4_32); EXPECT_TRUE(RefSize.hasValue()); EXPECT_EQ(*RefSize, 4); - RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 5, 4, DWARF32); + DWARFFormParams Params_5_4_32 = {5, 4, DWARF32}; + RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_5_4_32); EXPECT_TRUE(RefSize.hasValue()); EXPECT_EQ(*RefSize, 4); // DW_FORM_ref_addr is 8 bytes in DWARF 64 in DWARF version 3 and beyond. - RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 3, 8, DWARF64); + DWARFFormParams Params_3_8_64 = {3, 8, DWARF64}; + RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_3_8_64); EXPECT_TRUE(RefSize.hasValue()); EXPECT_EQ(*RefSize, 8); - RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 4, 8, DWARF64); + DWARFFormParams Params_4_8_64 = {4, 8, DWARF64}; + RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_4_8_64); EXPECT_TRUE(RefSize.hasValue()); EXPECT_EQ(*RefSize, 8); - RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, 5, 8, DWARF64); + DWARFFormParams Params_5_8_64 = {5, 8, DWARF64}; + RefSize = DWARFFormValue::getFixedByteSize(DW_FORM_ref_addr, Params_5_8_64); EXPECT_TRUE(RefSize.hasValue()); EXPECT_EQ(*RefSize, 8); }