Index: llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -11,6 +11,7 @@ #define LLVM_DEBUGINFO_DWARFDEBUGLINE_H #include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/Support/DataExtractor.h" #include @@ -42,10 +43,10 @@ /// 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 @@ -70,15 +71,18 @@ std::vector IncludeDirectories; std::vector FileNames; - bool IsDWARF64; + const DWARFFormParams getFormParams() const { return FormParams; } + uint16_t getVersion() const { return FormParams.getVersion(); } + uint8_t getAddressSize() const { return FormParams.getAddressByteSize(); } + bool isDWARF64() const { return FormParams.getFormat() == 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(); } Index: llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h +++ llvm/include/llvm/DebugInfo/DWARF/DWARFFormValue.h @@ -19,9 +19,49 @@ namespace llvm { +class DWARFDebugLine; class DWARFUnit; class raw_ostream; +/// A helper class 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. +class DWARFFormParams { + uint16_t Version = 0; + uint8_t AddrSize = 0; + dwarf::DwarfFormat Format = dwarf::DWARF32; + + // DWARFUnit and DWARFDebugLine use this as a data member initialized while + // parsing the unit or line table, respectively. + friend DWARFUnit; + friend DWARFDebugLine; + DWARFFormParams() = default; + +public: + DWARFFormParams(uint16_t V, uint8_t A, llvm::dwarf::DwarfFormat F) + : Version(V), AddrSize(A), Format(F) {} + + uint16_t getVersion() const { return Version; } + uint8_t getAddressByteSize() const { return AddrSize; } + dwarf::DwarfFormat getFormat() const { return Format; } + + 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"); + } +}; + class DWARFFormValue { public: enum FormClass { @@ -104,79 +144,48 @@ /// 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. + /// If the form always has a fixed byte size that doesn't depend on the + /// DWARF version, DWARF format, or address size, then an Optional with a + /// value will be returned. If the form's size depends on one of the + /// above-mentioned factors, and the caller provided them, 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 FormParams If non-null, 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 or a DWARFUnit wasn't supplied - /// and was needed to calculate the byte size. - static Optional getFixedByteSize(dwarf::Form Form, - const DWARFUnit *U = nullptr); + /// \p Form doesn't have a known fixed byte size. + static Optional + getFixedByteSize(dwarf::Form Form, + const DWARFFormParams *FormParams = nullptr); - /// Get the fixed byte size for a given form. + /// Skip a form's value in \p DebugInfoData at offset specified by + /// \p OffsetPtr. /// - /// 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. + /// Skips the bytes for the current form and updates the offset. /// - /// \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. - /// \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); - - /// 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 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 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; Index: llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h =================================================================== --- llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ llvm/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" @@ -128,12 +129,13 @@ 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 @@ 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 @@ 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 @@ 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.getVersion(); } + dwarf::DwarfFormat getFormat() const { return FormParams.getFormat(); } + uint8_t getAddressByteSize() const { return FormParams.getAddressByteSize(); } + uint8_t getRefAddrByteSize() const { return FormParams.getRefAddrByteSize(); } + uint8_t getDwarfOffsetByteSize() const { + return FormParams.getDwarfOffsetByteSize(); } const DWARFAbbreviationDeclarationSet *getAbbreviations() const { @@ -231,19 +238,6 @@ } 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; } Index: llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp @@ -186,7 +186,8 @@ 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 +212,8 @@ 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; Index: llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -59,7 +59,7 @@ // 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; Index: llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -38,11 +38,11 @@ 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(); StandardOpcodeLengths.clear(); IncludeDirectories.clear(); FileNames.clear(); @@ -51,12 +51,13 @@ 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) @@ -137,6 +138,7 @@ 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. @@ -159,7 +161,7 @@ IncludeDirectories.push_back(Value.getAsCString().getValue()); break; default: - if (!Value.skipValue(DebugLineData, OffsetPtr, nullptr)) + if (!Value.skipValue(DebugLineData, OffsetPtr, FormParams)) return false; } } @@ -211,24 +213,26 @@ 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); @@ -241,9 +245,9 @@ 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" Index: llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -59,47 +59,13 @@ 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(); + if (Params) + return Params->getAddressByteSize(); return None; case DW_FORM_block: // ULEB128 length L followed by L bytes. @@ -121,8 +87,8 @@ return None; case DW_FORM_ref_addr: - if (U) - return U->getRefAddrByteSize(); + if (Params) + return Params->getRefAddrByteSize(); return None; case DW_FORM_flag: @@ -154,8 +120,8 @@ case DW_FORM_line_strp: case DW_FORM_sec_offset: case DW_FORM_strp_sup: - if (U) - return U->getDwarfOffsetByteSize(); + if (Params) + return Params->getDwarfOffsetByteSize(); return None; case DW_FORM_data8: @@ -181,9 +147,9 @@ 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 +209,8 @@ 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 +244,6 @@ 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 +402,6 @@ 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; Index: llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -64,11 +64,13 @@ 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; } @@ -94,15 +96,15 @@ bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) { Length = debug_info.getU32(offset_ptr); - Version = debug_info.getU16(offset_ptr); + FormParams.Version = debug_info.getU16(offset_ptr); uint64_t AbbrOffset; - if (Version >= 5) { + if (getVersion() >= 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) @@ -117,14 +119,14 @@ } 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; @@ -150,7 +152,8 @@ 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); @@ -159,9 +162,8 @@ void DWARFUnit::clear() { Offset = 0; Length = 0; - Version = 0; Abbrevs = nullptr; - AddrSize = 0; + FormParams = DWARFFormParams(); BaseAddr = 0; RangeSectionBase = 0; AddrOffsetSectionBase = 0; Index: llvm/tools/dsymutil/DwarfLinker.cpp =================================================================== --- llvm/tools/dsymutil/DwarfLinker.cpp +++ llvm/tools/dsymutil/DwarfLinker.cpp @@ -2063,10 +2063,12 @@ 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 @@ 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 @@ 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 @@ // 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."); Index: llvm/tools/llvm-dwp/llvm-dwp.cpp =================================================================== --- llvm/tools/llvm-dwp/llvm-dwp.cpp +++ llvm/tools/llvm-dwp/llvm-dwp.cpp @@ -158,6 +158,7 @@ uint32_t Name; dwarf::Form Form; CompileUnitIdentifiers ID; + DWARFFormParams FormParams(Version, AddrSize, Format); while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) | (Form = static_cast(AbbrevData.getULEB128(&AbbrevOffset))) && (Name != 0 || Form != 0)) { @@ -182,8 +183,7 @@ ID.Signature = InfoData.getU64(&Offset); break; default: - DWARFFormValue::skipValue(Form, InfoData, &Offset, Version, AddrSize, - Format); + DWARFFormValue::skipValue(Form, InfoData, &Offset, FormParams); } } return ID; Index: llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp =================================================================== --- llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp +++ llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp @@ -23,43 +23,52 @@ 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); }