Index: include/llvm/DebugInfo/DWARF/DWARFUnit.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -165,6 +165,25 @@ uint64_t SectionIndex; }; +/// Represents a unit's contribution to the string offsets table. +struct StrOffsetsContributionDescriptor { + uint64_t Base = 0; + uint64_t Size = 0; + /// Format and version. + DWARFFormParams FormParams = {0, 0, dwarf::DwarfFormat::DWARF32}; + /// False for an ill-formed or non-existent contribution. + bool Valid = false; + uint8_t getVersion() const { return FormParams.Version; } + dwarf::DwarfFormat getFormat() const { return FormParams.Format; } + uint8_t getDwarfOffsetByteSize() const { + return FormParams.getDwarfOffsetByteSize(); + } + /// Determine whether a contribution to the string offsets table is + /// consistent with the relevant section size and that its length is + /// a multiple of the size of one of its entries. + void validateContributionSize(DWARFDataExtractor &DA); +}; + class DWARFUnit { DWARFContext &Context; /// Section containing this DWARFUnit. @@ -176,7 +195,6 @@ const DWARFSection &LineSection; StringRef StringSection; const DWARFSection &StringOffsetSection; - uint64_t StringOffsetSectionBase = 0; const DWARFSection *AddrOffsetSection; uint32_t AddrOffsetSectionBase = 0; bool isLittleEndian; @@ -185,6 +203,9 @@ // Version, address size, and DWARF format. DWARFFormParams FormParams; + /// Start, length, and DWARF format of the unit's contribution to the string + /// offsets table (DWARF v5). It is initially invalid. + StrOffsetsContributionDescriptor StringOffsetsTableContribution; uint32_t Offset; uint32_t Length; @@ -219,6 +240,19 @@ /// Size in bytes of the unit header. virtual uint32_t getHeaderSize() const { return getVersion() <= 4 ? 11 : 12; } + /// Find the unit's contribution to the string offsets table and determine its + /// length and form. The given offset is expected to be derived from the unit + /// DIE's DW_AT_str_offsets_base attribute. + void determineStringOffsetsTableContribution(DWARFDataExtractor &DA, + uint64_t Offset); + + /// Find the unit's contribution to the string offsets table and determine its + /// length and form. The given offset is expected to be either 0 (the start + /// of the string offsets section) or the unit's contribution to it as + /// determined by a dwp file's index table. + void determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA, + uint64_t Offset); + public: DWARFUnit(DWARFContext &Context, const DWARFSection &Section, const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS, @@ -272,6 +306,10 @@ uint32_t getNextUnitOffset() const { return Offset + Length + 4; } uint32_t getLength() const { return Length; } + const StrOffsetsContributionDescriptor & + getStringOffsetsTableContribution() const { + return StringOffsetsTableContribution; + } const DWARFFormParams &getFormParams() const { return FormParams; } uint16_t getVersion() const { return FormParams.Version; } dwarf::DwarfFormat getFormat() const { return FormParams.Format; } @@ -281,6 +319,14 @@ return FormParams.getDwarfOffsetByteSize(); } + uint8_t getDwarfStringOffsetsByteSize() const { + return StringOffsetsTableContribution.getDwarfOffsetByteSize(); + } + + uint64_t getStringOffsetsBase() const { + return StringOffsetsTableContribution.Base; + } + const DWARFAbbreviationDeclarationSet *getAbbreviations() const; uint8_t getUnitType() const { return UnitType; } Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -88,70 +88,97 @@ } } -static void -dumpDWARFv5StringOffsetsSection(raw_ostream &OS, StringRef SectionName, - const DWARFObject &Obj, - const DWARFSection &StringOffsetsSection, - StringRef StringSection, bool LittleEndian) { +using ContributionCollection = std::vector; + +// Collect all the contributions to the string offsets table from all units, +// sort them by their starting offsets and remove duplicates (some units may +// share contributions). +static ContributionCollection +collectContributionData(DWARFContext::cu_iterator_range CUs, + DWARFContext::tu_section_iterator_range TUSs) { + ContributionCollection Contributions; + for (const auto &CU : CUs) + Contributions.push_back(CU->getStringOffsetsTableContribution()); + for (const auto &TUS : TUSs) + for (const auto &TU : TUS) + Contributions.push_back(TU->getStringOffsetsTableContribution()); + + std::sort(Contributions.begin(), Contributions.end(), + [](const StrOffsetsContributionDescriptor &L, + const StrOffsetsContributionDescriptor &R) { + return L.Base < R.Base; + }); + + Contributions.erase( + std::unique(Contributions.begin(), Contributions.end(), + [](const StrOffsetsContributionDescriptor &L, + const StrOffsetsContributionDescriptor &R) { + return L.Base == R.Base && L.Size == R.Size; + }), + Contributions.end()); + return std::move(Contributions); +} + +static void dumpDWARFv5StringOffsetsSection( + raw_ostream &OS, StringRef SectionName, const DWARFObject &Obj, + const DWARFSection &StringOffsetsSection, StringRef StringSection, + DWARFContext::cu_iterator_range CUs, + DWARFContext::tu_section_iterator_range TUSs, bool LittleEndian) { + auto Contributions = collectContributionData(CUs, TUSs); DWARFDataExtractor StrOffsetExt(Obj, StringOffsetsSection, LittleEndian, 0); - uint32_t Offset = 0; + DataExtractor StrData(StringSection, LittleEndian, 0); uint64_t SectionSize = StringOffsetsSection.Data.size(); - - while (Offset < SectionSize) { - unsigned Version = 0; - DwarfFormat Format = DWARF32; - unsigned EntrySize = 4; - // Perform validation and extract the segment size from the header. - if (!StrOffsetExt.isValidOffsetForDataOfSize(Offset, 4)) { + uint32_t Offset = 0; + for (auto &Contribution : Contributions) { + // Ignore contributions with a base that is completely outside of the + // string offsets section. This may result from an invalid DW_AT_str_offsets + // attribute. + if (Contribution.Base >= SectionSize) + continue; + // Report an ill-formed contribution. + if (!Contribution.Valid) { OS << "error: invalid contribution to string offsets table in section ." << SectionName << ".\n"; return; } - uint32_t ContributionStart = Offset; - uint64_t ContributionSize = StrOffsetExt.getU32(&Offset); - // A contribution size of 0xffffffff indicates DWARF64, with the actual size - // in the following 8 bytes. Otherwise, the DWARF standard mandates that - // the contribution size must be at most 0xfffffff0. - if (ContributionSize == 0xffffffff) { - if (!StrOffsetExt.isValidOffsetForDataOfSize(Offset, 8)) { - OS << "error: invalid contribution to string offsets table in section ." - << SectionName << ".\n"; - return; - } - Format = DWARF64; - EntrySize = 8; - ContributionSize = StrOffsetExt.getU64(&Offset); - } else if (ContributionSize > 0xfffffff0) { - OS << "error: invalid contribution to string offsets table in section ." + + dwarf::DwarfFormat Format = Contribution.getFormat(); + uint16_t Version = Contribution.getVersion(); + uint64_t ContributionHeader = Contribution.Base; + // In DWARF v5 there is a contribution header that immediately precedes + // the string offsets base (the location we have previously retrieved from + // the CU DIE's DW_AT_str_offsets attribute). The header is located either + // 8 or 16 bytes before the base, depending on the contribution's format. + if (Version >= 5) + ContributionHeader -= Format == DWARF32 ? 8 : 16; + + // Detect overlapping contributions. + if (Offset > ContributionHeader) { + OS << "error: overlapping contributions to string offsets table in " + "section ." << SectionName << ".\n"; return; } - - // We must ensure that we don't read a partial record at the end, so we - // validate for a multiple of EntrySize. Also, we're expecting a version - // number and padding, which adds an additional 4 bytes. - uint64_t ValidationSize = - 4 + ((ContributionSize + EntrySize - 1) & (-(uint64_t)EntrySize)); - if (!StrOffsetExt.isValidOffsetForDataOfSize(Offset, ValidationSize)) { - OS << "error: contribution to string offsets table in section ." - << SectionName << " has invalid length.\n"; - return; + // Report a gap in the table. + if (Offset < ContributionHeader) { + OS << format("0x%8.8x: Gap, length = ", Offset); + OS << (ContributionHeader - Offset) << "\n"; } - - Version = StrOffsetExt.getU16(&Offset); - Offset += 2; - OS << format("0x%8.8x: ", ContributionStart); - OS << "Contribution size = " << ContributionSize + OS << format("0x%8.8x: ", ContributionHeader); + OS << "Contribution size = " << Contribution.Size + << ", Format = " << (Format == DWARF32 ? "DWARF32" : "DWARF64") << ", Version = " << Version << "\n"; - uint32_t ContributionBase = Offset; - DataExtractor StrData(StringSection, LittleEndian, 0); - while (Offset - ContributionBase < ContributionSize) { + Offset = Contribution.Base; + unsigned EntrySize = Contribution.getDwarfOffsetByteSize(); + while (Offset - Contribution.Base < Contribution.Size) { OS << format("0x%8.8x: ", Offset); - // FIXME: We can only extract strings in DWARF32 format at the moment. + // FIXME: We can only extract strings if the offset fits in 32 bits. uint64_t StringOffset = StrOffsetExt.getRelocatedValue(EntrySize, &Offset); - if (Format == DWARF32) { + // Extract the string if we can and display it. Otherwise just report + // the offset. + if (StringOffset <= 0xffffffffULL) { uint32_t StringOffset32 = (uint32_t)StringOffset; OS << format("%8.8x ", StringOffset32); const char *S = StrData.getCStr(&StringOffset32); @@ -162,6 +189,11 @@ OS << "\n"; } } + // Report a gap at the end of the table. + if (Offset < SectionSize) { + OS << format("0x%8.8x: Gap, length = ", Offset); + OS << (SectionSize - Offset) << "\n"; + } } // Dump a DWARF string offsets section. This may be a DWARF v5 formatted @@ -170,17 +202,18 @@ // a header containing size and version number. Alternatively, it may be a // monolithic series of string offsets, as generated by the pre-DWARF v5 // implementation of split DWARF. -static void dumpStringOffsetsSection(raw_ostream &OS, StringRef SectionName, - const DWARFObject &Obj, - const DWARFSection &StringOffsetsSection, - StringRef StringSection, bool LittleEndian, - unsigned MaxVersion) { +static void dumpStringOffsetsSection( + raw_ostream &OS, StringRef SectionName, const DWARFObject &Obj, + const DWARFSection &StringOffsetsSection, StringRef StringSection, + DWARFContext::cu_iterator_range CUs, + DWARFContext::tu_section_iterator_range TUSs, bool LittleEndian, + unsigned MaxVersion) { // If we have at least one (compile or type) unit with DWARF v5 or greater, // we assume that the section is formatted like a DWARF v5 string offsets // section. if (MaxVersion >= 5) dumpDWARFv5StringOffsetsSection(OS, SectionName, Obj, StringOffsetsSection, - StringSection, LittleEndian); + StringSection, CUs, TUSs, LittleEndian); else { DataExtractor strOffsetExt(StringOffsetsSection.Data, LittleEndian, 0); uint32_t offset = 0; @@ -468,12 +501,14 @@ DObj->getStringOffsetSection().Data)) dumpStringOffsetsSection( OS, "debug_str_offsets", *DObj, DObj->getStringOffsetSection(), - DObj->getStringSection(), isLittleEndian(), getMaxVersion()); + DObj->getStringSection(), compile_units(), type_unit_sections(), + isLittleEndian(), getMaxVersion()); if (shouldDump(ExplicitDWO, ".debug_str_offsets.dwo", DIDT_ID_DebugStrOffsets, DObj->getStringOffsetDWOSection().Data)) dumpStringOffsetsSection( OS, "debug_str_offsets.dwo", *DObj, DObj->getStringOffsetDWOSection(), - DObj->getStringDWOSection(), isLittleEndian(), getMaxVersion()); + DObj->getStringDWOSection(), dwo_compile_units(), + dwo_type_unit_sections(), isLittleEndian(), getMaxVersion()); if (shouldDump(Explicit, ".gnu_index", DIDT_ID_GdbIndex, DObj->getGdbIndexSection())) { Index: lib/DebugInfo/DWARF/DWARFUnit.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFUnit.cpp +++ lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -79,8 +79,10 @@ bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index, uint64_t &Result) const { - unsigned ItemSize = getDwarfOffsetByteSize(); - uint32_t Offset = StringOffsetSectionBase + Index * ItemSize; + if (!StringOffsetsTableContribution.Valid) + return false; + unsigned ItemSize = getDwarfStringOffsetsByteSize(); + uint32_t Offset = getStringOffsetsBase() + Index * ItemSize; if (StringOffsetSection.Data.size() < Offset + ItemSize) return false; DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, @@ -251,15 +253,27 @@ RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0); } - // In general, we derive the offset of the unit's contibution to the - // debug_str_offsets{.dwo} section from the unit DIE's - // DW_AT_str_offsets_base attribute. In dwp files we add to it the offset - // we get from the index table. - StringOffsetSectionBase = - toSectionOffset(UnitDie.find(DW_AT_str_offsets_base), 0); + // In general, in DWARF v5 and beyond we derive the start of the unit's + // contribution to the string offsets table from the unit DIE's + // DW_AT_str_offsets_base attribute. Split DWARF units do not use this + // attribute, so we assume that there is a contribution to the string + // offsets table starting at offset 0 of the debug_str_offsets.dwo section. + // In both cases we need to determine the format of the contribution, + // which may differ from the unit's format. + uint64_t StringOffsetsContributionBase = + isDWO ? 0 : toSectionOffset(UnitDie.find(DW_AT_str_offsets_base), 0); if (IndexEntry) if (const auto *C = IndexEntry->getOffset(DW_SECT_STR_OFFSETS)) - StringOffsetSectionBase += C->Offset; + StringOffsetsContributionBase += C->Offset; + + DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, + isLittleEndian, 0); + if (isDWO) + determineStringOffsetsTableContributionDWO(DA, + StringOffsetsContributionBase); + else if (getVersion() >= 5) + determineStringOffsetsTableContribution(DA, + StringOffsetsContributionBase); // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for // skeleton CU DIE, so that DWARF users not aware of it are not broken. @@ -466,3 +480,107 @@ Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset); return Abbrevs; } + +// Determine whether a contribution to the string offsets table is +// consistent with the relevant section size and that its length is +// a multiple of the size of one of its entries. +void StrOffsetsContributionDescriptor::validateContributionSize( + DWARFDataExtractor &DA) { + if (!Valid) + return; + uint8_t EntrySize = getDwarfOffsetByteSize(); + // In order to ensure that we don't read a partial record at the end of + // the section we validate for a multiple of the entry size. + uint64_t ValidationSize = (Size + EntrySize - 1) & (-(uint64_t)EntrySize); + uint32_t ValidationOffset = (uint32_t)Base; + if (!DA.isValidOffsetForDataOfSize(ValidationOffset, ValidationSize)) + Valid = false; +} + +// Look for a DWARF64-formatted contribution to the string offsets table +// starting at a given offset and record it in a descriptor. +static bool parseDWARF64StringOffsetsTableHeader( + DWARFDataExtractor &DA, uint32_t &Offset, + StrOffsetsContributionDescriptor &Descriptor) { + assert(!Descriptor.Valid && "Expected a string offsets contribution " + "descriptor to be initialized to invalid"); + if (!DA.isValidOffsetForDataOfSize(Offset, 16)) { + return false; + } + + if (DA.getU32(&Offset) != 0xffffffff) { + return false; + } + + Descriptor.Size = DA.getU64(&Offset); + Descriptor.FormParams.Version = DA.getU16(&Offset); + (void)DA.getU16(&Offset); // padding + Descriptor.FormParams.Format = DWARF64; + Descriptor.Valid = true; + return true; +} + +// Look for a DWARF32-formatted contribution to the string offsets table +// starting at a given offset and record it in a descriptor. +static bool parseDWARF32StringOffsetsTableHeader( + DWARFDataExtractor &DA, uint32_t &Offset, + StrOffsetsContributionDescriptor &Descriptor) { + assert(!Descriptor.Valid && "Expected a string offsets contribution " + "descriptor to be initialized to invalid"); + if (!DA.isValidOffsetForDataOfSize(Offset, 8)) { + return false; + } + uint32_t ContributionSize = DA.getU32(&Offset); + if (ContributionSize >= 0xfffffff0) { + return false; + } + Descriptor.Size = ContributionSize; + Descriptor.FormParams.Version = DA.getU16(&Offset); + (void)DA.getU16(&Offset); // padding + Descriptor.FormParams.Format = DWARF32; + Descriptor.Valid = true; + return true; +} + +void DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA, + uint64_t Offset) { + StrOffsetsContributionDescriptor Descriptor; + Descriptor.Base = Offset; + + // Attempt to find a DWARF64 contribution 16 bytes before the base. + uint32_t HeaderOffset = (uint32_t)Descriptor.Base - 16; + if (!parseDWARF64StringOffsetsTableHeader(DA, HeaderOffset, Descriptor)) { + // Try again for a DWARF32 contribution 8 bytes before the base. + HeaderOffset = (uint32_t)Descriptor.Base - 8; + parseDWARF32StringOffsetsTableHeader(DA, HeaderOffset, Descriptor); + } + Descriptor.validateContributionSize(DA); + StringOffsetsTableContribution = Descriptor; +} + +void DWARFUnit::determineStringOffsetsTableContributionDWO( + DWARFDataExtractor &DA, uint64_t Offset) { + StrOffsetsContributionDescriptor Descriptor; + Descriptor.Base = Offset; + if (getVersion() >= 5) { + uint32_t HeaderOffset = (uint32_t)Offset; + // Look for a valid contribution at the given offset. + if (!parseDWARF64StringOffsetsTableHeader(DA, HeaderOffset, Descriptor)) { + HeaderOffset = (uint32_t)Offset; + parseDWARF32StringOffsetsTableHeader(DA, HeaderOffset, Descriptor); + } + Descriptor.Base = HeaderOffset; + Descriptor.validateContributionSize(DA); + } else { + Descriptor.FormParams.Version = 4; + Descriptor.Valid = true; + // Prior to DWARF v5, we derive the contribution size from the + // index table (in a package file). In a .dwo file it is simply + // the length of the string offsets section. + if (!IndexEntry) + Descriptor.Size = StringOffsetSection.Data.size(); + else if (const auto *C = IndexEntry->getOffset(DW_SECT_STR_OFFSETS)) + Descriptor.Size = C->Length; + } + StringOffsetsTableContribution = Descriptor; +} Index: test/DebugInfo/X86/dwarfdump-str-offsets-dwp.s =================================================================== --- test/DebugInfo/X86/dwarfdump-str-offsets-dwp.s +++ test/DebugInfo/X86/dwarfdump-str-offsets-dwp.s @@ -2,9 +2,10 @@ # RUN: llvm-dwarfdump -v %t.o | FileCheck %s # Test object to verify that dwarfdump handles dwp files with DWARF v5 string -# offset tables. We have 2 CUs and 2 TUs, where it is assumed that +# offset tables. We have 3 CUs and 2 TUs, where it is assumed that # CU1 and TU1 came from one object file, CU2 and TU2 from a second object -# file. +# file, and CU3 from a third object file that was compiled with +# -gdwarf-4. # .section .debug_str.dwo,"MS",@progbits,1 str_producer: @@ -25,56 +26,50 @@ .asciz "Type_Unit_2" str_TU2_type: .asciz "MyStruct_2" +str_CU3: + .asciz "Compile_Unit_3" +str_CU3_dir: + .asciz "/home/test/CU3" .section .debug_str_offsets.dwo,"",@progbits # Object files 1's portion of the .debug_str_offsets.dwo section. -.debug_str_offsets_object_file1: - -# CU1's contribution (from object file 1) -.debug_str_offsets_start_CU1: - .long .debug_str_offsets_end_CU1-.debug_str_offsets_base_CU1 +# CU1 and TU1 share a contribution to the string offsets table. +.debug_str_offsets_object_file1_start: + .long .debug_str_offsets_object_file1_end-.debug_str_offsets_base_1 .short 5 # DWARF version .short 0 # Padding -.debug_str_offsets_base_CU1: +.debug_str_offsets_base_1: .long str_producer-.debug_str.dwo .long str_CU1-.debug_str.dwo .long str_CU1_dir-.debug_str.dwo -.debug_str_offsets_end_CU1: - -# TU1's contribution (from object file 1) -.debug_str_offsets_start_TU1: - .long .debug_str_offsets_end_TU1-.debug_str_offsets_base_TU1 - .short 5 # DWARF version - .short 0 # Padding -.debug_str_offsets_base_TU1: .long str_TU1-.debug_str.dwo .long str_TU1_type-.debug_str.dwo -.debug_str_offsets_end_TU1: +.debug_str_offsets_object_file1_end: # Object files 2's portion of the .debug_str_offsets.dwo section. -.debug_str_offsets_object_file2: - -# CU2's contribution (from object file 2) -.debug_str_offsets_start_CU2: - .long .debug_str_offsets_end_CU2-.debug_str_offsets_base_CU2 +# CU2 and TU2 share a contribution to the string offsets table. +.debug_str_offsets_object_file2_start: + .long .debug_str_offsets_object_file2_end-.debug_str_offsets_base_2 .short 5 # DWARF version .short 0 # Padding -.debug_str_offsets_base_CU2: +.debug_str_offsets_base_2: .long str_producer-.debug_str.dwo .long str_CU2-.debug_str.dwo .long str_CU2_dir-.debug_str.dwo -.debug_str_offsets_end_CU2: - -# TU2's contribution (from object file 2) -.debug_str_offsets_start_TU2: - .long .debug_str_offsets_end_TU2-.debug_str_offsets_base_TU2 - .short 5 # DWARF version - .short 0 # Padding -.debug_str_offsets_base_TU2: .long str_TU2-.debug_str.dwo .long str_TU2_type-.debug_str.dwo -.debug_str_offsets_end_TU2: +.debug_str_offsets_object_file2_end: +# Object files 3's portion of the .debug_str_offsets.dwo section. +# This file is assumed to have been compiled with -gdwarf-4 and +# therefore contains a version 4 CU and a GNU format contribution +# to the .debug_str_offsets section. +.debug_str_offsets_object_file3_start: +.debug_str_offsets_base_3: + .long str_producer-.debug_str.dwo + .long str_CU3-.debug_str.dwo + .long str_CU3_dir-.debug_str.dwo +.debug_str_offsets_object_file3_end: # Abbrevs are shared for all compile and type units .section .debug_abbrev.dwo,"",@progbits @@ -85,8 +80,6 @@ .byte 0x1a # DW_FORM_strx .byte 0x03 # DW_AT_name .byte 0x1a # DW_FORM_strx - .byte 0x72 # DW_AT_str_offsets_base - .byte 0x17 # DW_FORM_sec_offset .byte 0x03 # DW_AT_name .byte 0x1a # DW_FORM_strx .byte 0x00 # EOM(1) @@ -96,8 +89,6 @@ .byte 0x01 # DW_CHILDREN_yes .byte 0x03 # DW_AT_name .byte 0x1a # DW_FORM_strx - .byte 0x72 # DW_AT_str_offsets_base - .byte 0x17 # DW_FORM_sec_offset .byte 0x00 # EOM(1) .byte 0x00 # EOM(2) .byte 0x03 # Abbrev code @@ -107,6 +98,17 @@ .byte 0x1a # DW_FORM_strx .byte 0x00 # EOM(1) .byte 0x00 # EOM(2) + .byte 0x04 # Abbrev code + .byte 0x11 # DW_TAG_compile_unit + .byte 0x00 # DW_CHILDREN_no + .byte 0x25 # DW_AT_producer + .short 0x3e82 # DW_FORM_GNU_str_index + .byte 0x03 # DW_AT_name + .short 0x3e82 # DW_FORM_GNU_str_index + .byte 0x03 # DW_AT_name + .short 0x3e82 # DW_FORM_GNU_str_index + .byte 0x00 # EOM(1) + .byte 0x00 # EOM(2) .byte 0x00 # EOM(3) abbrev_end: @@ -120,15 +122,11 @@ .byte 1 # DWARF Unit Type .byte 8 # Address Size (in bytes) .long .debug_abbrev.dwo # Offset Into Abbrev. Section -# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name, -# DW_AT_str_offsets and DW_AT_compdir. +# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name +# and DW_AT_compdir. .byte 1 # Abbreviation code .byte 0 # The index of the producer string .byte 1 # The index of the CU name string -# The DW_AT_str_offsets_base attribute for CU1 contains the offset of CU1's -# contribution relative to the start of object file 1's portion of the -# .debug_str_offsets section. - .long .debug_str_offsets_base_CU1-.debug_str_offsets_object_file1 .byte 2 # The index of the comp dir string .byte 0 # NULL CU1_5_end: @@ -140,19 +138,30 @@ .byte 1 # DWARF Unit Type .byte 8 # Address Size (in bytes) .long .debug_abbrev.dwo # Offset Into Abbrev. Section -# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name, -# DW_AT_str_offsets and DW_AT_compdir. +# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name +# and DW_AT_compdir. .byte 1 # Abbreviation code .byte 0 # The index of the producer string .byte 1 # The index of the CU name string -# The DW_AT_str_offsets_base attribute for CU2 contains the offset of CU2's -# contribution relative to the start of object file 2's portion of the -# .debug_str_offsets section. - .long .debug_str_offsets_base_CU2-.debug_str_offsets_object_file2 .byte 2 # The index of the comp dir string .byte 0 # NULL CU2_5_end: +CU3_4_start: + .long CU3_4_end-CU3_4_version # Length of Unit +CU3_4_version: + .short 4 # DWARF version number + .long .debug_abbrev.dwo # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) +# The compile-unit DIE, which has a DW_AT_producer, DW_AT_name +# and DW_AT_compdir. + .byte 4 # Abbreviation code + .byte 0 # The index of the producer string + .byte 1 # The index of the CU name string + .byte 2 # The index of the comp dir string + .byte 0 # NULL +CU3_4_end: + .section .debug_types.dwo,"",@progbits # DWARF v5 Type unit header. TU1_5_start: @@ -166,15 +175,11 @@ .long TU1_5_type-TU1_5_start # Type offset # The type-unit DIE, which has a name. .byte 2 # Abbreviation code - .byte 0 # Index of the unit type name string -# The DW_AT_str_offsets_base attribute for TU1 contains the offset of TU1's -# contribution relative to the start of object file 1's portion of the -# .debug_str_offsets section. - .long .debug_str_offsets_base_TU1-.debug_str_offsets_object_file1 + .byte 3 # Index of the unit type name string # The type DIE, which has a name. TU1_5_type: .byte 3 # Abbreviation code - .byte 1 # Index of the type name string + .byte 4 # Index of the type name string .byte 0 # NULL .byte 0 # NULL TU1_5_end: @@ -190,15 +195,11 @@ .long TU2_5_type-TU2_5_start # Type offset # The type-unit DIE, which has a name. .byte 2 # Abbreviation code - .byte 0 # Index of the unit type name string -# The DW_AT_str_offsets_base attribute for TU2 contains the offset of TU2's -# contribution relative to the start of object file 2's portion of the -# .debug_str_offsets section. - .long .debug_str_offsets_base_TU2-.debug_str_offsets_object_file2 + .byte 3 # Index of the unit type name string # The type DIE, which has a name. TU2_5_type: .byte 3 # Abbreviation code - .byte 1 # Index of the type name string + .byte 4 # Index of the type name string .byte 0 # NULL .byte 0 # NULL TU2_5_end: @@ -207,37 +208,45 @@ # The index header .long 2 # Version .long 3 # Columns of contribution matrix - .long 2 # number of units - .long 2 # number of hash buckets in table + .long 3 # number of units + .long 3 # number of hash buckets in table - # The signatures for both CUs. + # The signatures for all CUs. .quad 0xddeeaaddbbaabbee # signature 1 .quad 0xff00ffeeffaaff00 # signature 2 + .quad 0xf00df00df00df00d # signature 2 # The indexes for both CUs. .long 1 # index 1 .long 2 # index 2 - # The sections to which both CUs contribute. + .long 3 # index 3 + # The sections to which all CUs contribute. .long 1 # DW_SECT_INFO .long 3 # DW_SECT_ABBREV .long 6 # DW_SECT_STR_OFFSETS - # The starting offsets of both CU's contributions to info, + # The starting offsets of all CU's contributions to info, # abbrev and string offsets table. .long CU1_5_start-.debug_info.dwo .long 0 - .long .debug_str_offsets_object_file1-.debug_str_offsets.dwo + .long .debug_str_offsets_object_file1_start-.debug_str_offsets.dwo .long CU2_5_start-.debug_info.dwo .long 0 - .long .debug_str_offsets_object_file2-.debug_str_offsets.dwo + .long .debug_str_offsets_object_file2_start-.debug_str_offsets.dwo + .long CU3_4_start-.debug_info.dwo + .long 0 + .long .debug_str_offsets_object_file3_start-.debug_str_offsets.dwo - # The lengths of both CU's contributions to info, abbrev and + # The lengths of all CU's contributions to info, abbrev and # string offsets table. .long CU1_5_end-CU1_5_start .long abbrev_end-.debug_abbrev.dwo - .long .debug_str_offsets_end_CU1-.debug_str_offsets_start_CU1 + .long .debug_str_offsets_object_file1_end-.debug_str_offsets_object_file1_start .long CU2_5_end-CU2_5_start .long abbrev_end-.debug_abbrev.dwo - .long .debug_str_offsets_end_CU2-.debug_str_offsets_start_CU2 + .long .debug_str_offsets_object_file2_end-.debug_str_offsets_object_file2_start + .long CU3_4_end-CU3_4_start + .long abbrev_end-.debug_abbrev.dwo + .long .debug_str_offsets_object_file3_end-.debug_str_offsets_object_file3_start .section .debug_tu_index,"",@progbits # The index header @@ -261,19 +270,19 @@ # abbrev and string offsets table. .long TU1_5_start-.debug_types.dwo .long 0 - .long .debug_str_offsets_object_file1-.debug_str_offsets.dwo + .long .debug_str_offsets_object_file1_start-.debug_str_offsets.dwo .long TU2_5_start-.debug_types.dwo .long 0 - .long .debug_str_offsets_object_file2-.debug_str_offsets.dwo + .long .debug_str_offsets_object_file2_start-.debug_str_offsets.dwo # The lengths of both TU's contributions to info, abbrev and # string offsets table. .long TU1_5_end-TU1_5_start .long abbrev_end-.debug_abbrev.dwo - .long .debug_str_offsets_end_TU1-.debug_str_offsets_start_TU1 + .long .debug_str_offsets_object_file1_end-.debug_str_offsets_object_file1_start .long TU2_5_end-TU2_5_start .long abbrev_end-.debug_abbrev.dwo - .long .debug_str_offsets_end_TU2-.debug_str_offsets_start_TU2 + .long .debug_str_offsets_object_file2_end-.debug_str_offsets_object_file2_start # Verify that the correct strings from each unit are displayed and that the @@ -284,7 +293,6 @@ # CHECK: DW_TAG_compile_unit # CHECK-NEXT: DW_AT_producer [DW_FORM_strx] ( indexed (00000000) string = "Handmade DWARF producer") # CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "Compile_Unit_1") -# CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008) # CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000002) string = "/home/test/CU1") # CHECK-NOT: NULL @@ -293,26 +301,23 @@ # CHECK: DW_TAG_compile_unit # CHECK-NEXT: DW_AT_producer [DW_FORM_strx] ( indexed (00000000) string = "Handmade DWARF producer") # CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "Compile_Unit_2") -# CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008) # CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000002) string = "/home/test/CU2") # # CHECK: Type Unit # CHECK-NOT: NULL # CHECK: DW_TAG_type_unit -# CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000000) string = "Type_Unit_1") -# CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x0000001c) +# CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000003) string = "Type_Unit_1") # CHECK-NOT: NULL # CHECK: DW_TAG_structure_type -# CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "MyStruct_1") +# CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000004) string = "MyStruct_1") # # CHECK: Type Unit # CHECK-NOT: NULL # CHECK: DW_TAG_type_unit -# CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000000) string = "Type_Unit_2") -# CHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x0000001c) +# CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000003) string = "Type_Unit_2") # CHECK-NOT: NULL # CHECK: DW_TAG_structure_type -# CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "MyStruct_2") +# CHECK-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000004) string = "MyStruct_2") # Verify the correct offets of the compile and type units contributions in the # index tables. @@ -322,11 +327,11 @@ # CHECK: 1 0xddeeaaddbbaabbee [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) # CHECK-SAME: [0x00000000 # CHECK-NEXT: 2 0xff00ffeeffaaff00 [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) -# CHECK-SAME: [0x00000024 +# CHECK-SAME: [0x0000001c # CHECK: .debug_tu_index contents: # CHECK-NOT: contents: # CHECK: 1 0xeeaaddbbaabbeedd [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) # CHECK-SAME: [0x00000000 # CHECK-NEXT: 2 0x00ffeeffaaff00ff [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) [{{0x[0-9a-f]*, 0x[0-9a-f]*}}) -# CHECK: [0x00000024 +# CHECK: [0x0000001c Index: test/DebugInfo/X86/dwarfdump-str-offsets-invalid-3.s =================================================================== --- test/DebugInfo/X86/dwarfdump-str-offsets-invalid-3.s +++ test/DebugInfo/X86/dwarfdump-str-offsets-invalid-3.s @@ -37,6 +37,8 @@ .byte 0x01 # Abbrev code .byte 0x11 # DW_TAG_compile_unit .byte 0x00 # DW_CHILDREN_no + .byte 0x72 # DW_AT_str_offsets_base + .byte 0x17 # DW_FORM_sec_offset .byte 0x00 # EOM(1) .byte 0x00 # EOM(2) .byte 0x00 # EOM(3) @@ -54,13 +56,13 @@ .long .debug_abbrev # Offset Into Abbrev. Section # A compile-unit DIE, which has no attributes. .byte 1 # Abbreviation code + .long .debug_str_offsets_base0 CU1_5_end: .section .debug_str_offsets,"",@progbits # CU1's contribution # Invalid length .long 0xfffffffe - .long .debug_str_offsets_segment0_end-.debug_str_offsets_base0 .short 5 # DWARF version .short 0 # Padding .debug_str_offsets_base0: Index: test/DebugInfo/X86/dwarfdump-str-offsets-invalid-4.s =================================================================== --- test/DebugInfo/X86/dwarfdump-str-offsets-invalid-4.s +++ test/DebugInfo/X86/dwarfdump-str-offsets-invalid-4.s @@ -15,6 +15,8 @@ .byte 0x01 # Abbrev code .byte 0x11 # DW_TAG_compile_unit .byte 0x00 # DW_CHILDREN_no + .byte 0x72 # DW_AT_str_offsets_base + .byte 0x17 # DW_FORM_sec_offset .byte 0x00 # EOM(1) .byte 0x00 # EOM(2) .byte 0x00 # EOM(3) @@ -32,6 +34,7 @@ .long .debug_abbrev # Offset Into Abbrev. Section # A compile-unit DIE, which has no attributes. .byte 1 # Abbreviation code + .long .debug_str_offsets_base0 CU1_5_end: # Every unit contributes to the string_offsets table. @@ -50,4 +53,4 @@ # INVALIDLENGTH: .debug_str_offsets contents: # INVALIDLENGTH-NOT: contents: -# INVALIDLENGTH: error: contribution to string offsets table in section .debug_str_offsets has invalid length. +# INVALIDLENGTH: error: invalid contribution to string offsets table in section .debug_str_offsets. Index: test/DebugInfo/X86/dwarfdump-str-offsets-invalid-6.s =================================================================== --- test/DebugInfo/X86/dwarfdump-str-offsets-invalid-6.s +++ test/DebugInfo/X86/dwarfdump-str-offsets-invalid-6.s @@ -0,0 +1,94 @@ +# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t.o +# RUN: llvm-dwarfdump -v %t.o | FileCheck --check-prefix=OVERLAP %s +# +# Test object to verify that llvm-dwarfdump handles an invalid string offsets +# table with overlapping contributions. + + .section .debug_str,"MS",@progbits,1 +str_producer: + .asciz "Handmade DWARF producer" +str_CU1: + .asciz "Compile_Unit_1" +str_CU1_dir: + .asciz "/home/test/CU1" +str_CU2: + .asciz "Compile_Unit_2" +str_CU2_dir: + .asciz "/home/test/CU2" +str_TU: + .asciz "Type_Unit" +str_TU_type: + .asciz "MyStruct" + + .section .debug_str.dwo,"MS",@progbits,1 +dwo_str_CU_5_producer: + .asciz "Handmade split DWARF producer" +dwo_str_CU_5_name: + .asciz "V5_split_compile_unit" +dwo_str_CU_5_comp_dir: + .asciz "/home/test/splitCU" +dwo_str_TU_5: + .asciz "V5_split_type_unit" +dwo_str_TU_5_type: + .asciz "V5_split_Mystruct" + +# A rudimentary abbrev section. + .section .debug_abbrev,"",@progbits + .byte 0x01 # Abbrev code + .byte 0x11 # DW_TAG_compile_unit + .byte 0x00 # DW_CHILDREN_no + .byte 0x72 # DW_AT_str_offsets_base + .byte 0x17 # DW_FORM_sec_offset + .byte 0x00 # EOM(1) + .byte 0x00 # EOM(2) + .byte 0x00 # EOM(3) + + .section .debug_info,"",@progbits +# DWARF v5 CU header. + .long CU1_5_end-CU1_5_version # Length of Unit +CU1_5_version: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section +# A compile-unit DIE, which has no attributes. + .byte 1 # Abbreviation code + .long .debug_str_offsets_base0 +CU1_5_end: + +# DWARF v5 CU header. + .long CU2_5_end-CU2_5_version # Length of Unit +CU2_5_version: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section +# A compile-unit DIE, which has no attributes. + .byte 1 # Abbreviation code + .long .debug_str_offsets_base1 +CU2_5_end: + + .section .debug_str_offsets,"",@progbits +# CU1's contribution + .long .debug_str_offsets_segment1_end-.debug_str_offsets_base0 + .short 5 # DWARF version + .short 0 # Padding +.debug_str_offsets_base0: + .long str_producer + .long str_CU1 + .long str_CU1_dir +.debug_str_offsets_segment0_end: +# CU2's contribution +# Overlapping with CU1's contribution + .long .debug_str_offsets_segment1_end-.debug_str_offsets_base1 + .short 5 # DWARF version + .short 0 # Padding +.debug_str_offsets_base1: + .long str_producer + .long str_CU2 + .long str_CU2_dir +.debug_str_offsets_segment1_end: + +# OVERLAP: .debug_str_offsets contents: +# OVERLAP-NOT: contents: +# OVERLAP: error: overlapping contributions to string offsets table in section .debug_str_offsets. Index: test/DebugInfo/X86/dwarfdump-str-offsets-macho.s =================================================================== --- test/DebugInfo/X86/dwarfdump-str-offsets-macho.s +++ test/DebugInfo/X86/dwarfdump-str-offsets-macho.s @@ -43,14 +43,17 @@ .long str_Variable2 .long str_Variable3 Ldebug_str_offsets_segment0_end: -# CU2's contribution - .long Ldebug_str_offsets_segment1_end-Ldebug_str_offsets_base1 +# A 4-byte gap. + .long 0 +# CU2's contribution (DWARF64 format) + .long 0xffffffff + .quad Ldebug_str_offsets_segment1_end-Ldebug_str_offsets_base1 .short 5 # DWARF version .short 0 # Padding Ldebug_str_offsets_base1: - .long str_producer - .long str_CU2 - .long str_CU2_dir + .quad str_producer + .quad str_CU2 + .quad str_CU2_dir Ldebug_str_offsets_segment1_end: # The TU's contribution .long Ldebug_str_offsets_segment2_end-Ldebug_str_offsets_base2 @@ -234,20 +237,20 @@ # COMMON: DW_TAG_compile_unit # COMMON-NEXT: DW_AT_producer [DW_FORM_strx] ( indexed (00000000) string = "Handmade DWARF producer") # COMMON-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "Compile_Unit_2") -# COMMON-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x0000002c) +# COMMON-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000038) # COMMON-NEXT: DW_AT_comp_dir [DW_FORM_strx] ( indexed (00000002) string = "/home/test/CU2") # # The type unit # COMMON: .debug_types contents: # COMMON: DW_TAG_type_unit # COMMON-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000000) string = "Type_Unit") -# COMMON-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000040) +# COMMON-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000058) # COMMON: DW_TAG_structure_type # COMMON-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "MyStruct") # # The .debug_str_offsets section # COMMON: .debug_str_offsets contents: -# COMMON-NEXT: 0x00000000: Contribution size = 28, Version = 5 +# COMMON-NEXT: 0x00000000: Contribution size = 28, Format = DWARF32, Version = 5 # COMMON-NEXT: 0x00000008: 00000000 "Handmade DWARF producer" # COMMON-NEXT: 0x0000000c: 00000018 "Compile_Unit_1" # COMMON-NEXT: 0x00000010: 00000027 "/home/test/CU1" @@ -255,10 +258,11 @@ # COMMON-NEXT: 0x00000018: 0000006e "MyVar1" # COMMON-NEXT: 0x0000001c: 00000075 "MyVar2" # COMMON-NEXT: 0x00000020: 0000007c "MyVar3" -# COMMON-NEXT: 0x00000024: Contribution size = 12, Version = 5 -# COMMON-NEXT: 0x0000002c: 00000000 "Handmade DWARF producer" -# COMMON-NEXT: 0x00000030: 00000036 "Compile_Unit_2" -# COMMON-NEXT: 0x00000034: 00000045 "/home/test/CU2" -# COMMON-NEXT: 0x00000038: Contribution size = 8, Version = 5 -# COMMON-NEXT: 0x00000040: 00000054 "Type_Unit" -# COMMON-NEXT: 0x00000044: 0000005e "MyStruct" +# COMMON-NEXT: 0x00000024: Gap, length = 4 +# COMMON-NEXT: 0x00000028: Contribution size = 24, Format = DWARF64, Version = 5 +# COMMON-NEXT: 0x00000038: 00000000 "Handmade DWARF producer" +# COMMON-NEXT: 0x00000040: 00000036 "Compile_Unit_2" +# COMMON-NEXT: 0x00000048: 00000045 "/home/test/CU2" +# COMMON-NEXT: 0x00000050: Contribution size = 8, Format = DWARF32, Version = 5 +# COMMON-NEXT: 0x00000058: 00000054 "Type_Unit" +# COMMON-NEXT: 0x0000005c: 0000005e "MyStruct" Index: test/DebugInfo/X86/dwarfdump-str-offsets.s =================================================================== --- test/DebugInfo/X86/dwarfdump-str-offsets.s +++ test/DebugInfo/X86/dwarfdump-str-offsets.s @@ -44,14 +44,17 @@ .long str_Variable2 .long str_Variable3 .debug_str_offsets_segment0_end: -# CU2's contribution - .long .debug_str_offsets_segment1_end-.debug_str_offsets_base1 +# A 4-byte gap. + .long 0 +# CU2's contribution in DWARF64 format + .long 0xffffffff + .quad .debug_str_offsets_segment1_end-.debug_str_offsets_base1 .short 5 # DWARF version .short 0 # Padding .debug_str_offsets_base1: - .long str_producer - .long str_CU2 - .long str_CU2_dir + .quad str_producer + .quad str_CU2 + .quad str_CU2_dir .debug_str_offsets_segment1_end: # The TU's contribution .long .debug_str_offsets_segment2_end-.debug_str_offsets_base2 @@ -75,7 +78,7 @@ .asciz "V5_split_Mystruct" .section .debug_str_offsets.dwo,"",@progbits -# The split CU's contribution +# One contribution only in a .dwo file .long .debug_dwo_str_offsets_segment0_end-.debug_dwo_str_offsets_base0 .short 5 # DWARF version .short 0 # Padding @@ -83,15 +86,9 @@ .long dwo_str_CU_5_producer-.debug_str.dwo .long dwo_str_CU_5_name-.debug_str.dwo .long dwo_str_CU_5_comp_dir-.debug_str.dwo -.debug_dwo_str_offsets_segment0_end: -# The split TU's contribution - .long .debug_dwo_str_offsets_segment1_end-.debug_dwo_str_offsets_base1 - .short 5 # DWARF version - .short 0 # Padding -.debug_dwo_str_offsets_base1: .long dwo_str_TU_5-.debug_str.dwo .long dwo_str_TU_5_type-.debug_str.dwo -.debug_dwo_str_offsets_segment1_end: +.debug_dwo_str_offsets_segment0_end: # All CUs/TUs use the same abbrev section for simplicity. .section .debug_abbrev,"",@progbits @@ -163,8 +160,6 @@ .byte 0x1a # DW_FORM_strx .byte 0x03 # DW_AT_name .byte 0x1a # DW_FORM_strx - .byte 0x72 # DW_AT_str_offsets_base - .byte 0x17 # DW_FORM_sec_offset .byte 0x1b # DW_AT_comp_dir .byte 0x1a # DW_FORM_strx .byte 0x00 # EOM(1) @@ -174,8 +169,6 @@ .byte 0x01 # DW_CHILDREN_yes .byte 0x03 # DW_AT_name .byte 0x1a # DW_FORM_strx - .byte 0x72 # DW_AT_str_offsets_base - .byte 0x17 # DW_FORM_sec_offset .byte 0x00 # EOM(1) .byte 0x00 # EOM(2) .byte 0x03 # Abbrev code @@ -275,7 +268,6 @@ .byte 1 # Abbreviation code .byte 0 # The index of the producer string .byte 1 # The index of the CU name string - .long .debug_dwo_str_offsets_base0-.debug_str_offsets.dwo .byte 2 # The index of the comp dir string .byte 0 # NULL CU_split_5_end: @@ -294,12 +286,11 @@ .long TU_split_5_type-TU_split_5_start # Type offset # The type-unit DIE, which has a name. .byte 2 # Abbreviation code - .byte 0 # The index of the type unit name string - .long .debug_dwo_str_offsets_base1-.debug_str_offsets.dwo + .byte 3 # The index of the type unit name string # The type DIE, which has a name. TU_split_5_type: .byte 3 # Abbreviation code - .byte 1 # The index of the type name string + .byte 4 # The index of the type name string .byte 0 # NULL .byte 0 # NULL TU_split_5_end: @@ -340,7 +331,7 @@ # COMMON: DW_TAG_compile_unit # COMMON-NEXT: DW_AT_producer [DW_FORM_strx] ( indexed (00000000) string = "Handmade DWARF producer") # COMMON-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "Compile_Unit_2") -# COMMON-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x0000002c) +# COMMON-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000038) # COMMON-NEXT: DW_AT_comp_dir [DW_FORM_strx] ( indexed (00000002) string = "/home/test/CU2") # # The split CU @@ -349,28 +340,25 @@ # SPLIT: DW_TAG_compile_unit # SPLIT-NEXT: DW_AT_producer [DW_FORM_strx] ( indexed (00000000) string = "Handmade split DWARF producer") # SPLIT-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "V5_split_compile_unit") -# SPLIT-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000008) # SPLIT-NEXT: DW_AT_comp_dir [DW_FORM_strx] ( indexed (00000002) string = "/home/test/splitCU") # # The type unit # COMMON: .debug_types contents: # COMMON: DW_TAG_type_unit # COMMON-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000000) string = "Type_Unit") -# COMMON-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000040) # COMMON: DW_TAG_structure_type # COMMON-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "MyStruct") # # The split type unit # SPLIT: .debug_types.dwo contents: # SPLIT: DW_TAG_type_unit -# SPLIT-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000000) string = "V5_split_type_unit") -# SPLIT-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x0000001c) +# SPLIT-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000003) string = "V5_split_type_unit") # SPLIT: DW_TAG_structure_type -# SPLIT-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000001) string = "V5_split_Mystruct") +# SPLIT-NEXT: DW_AT_name [DW_FORM_strx] ( indexed (00000004) string = "V5_split_Mystruct") # # The .debug_str_offsets section # COMMON: .debug_str_offsets contents: -# COMMON-NEXT: 0x00000000: Contribution size = 28, Version = 5 +# COMMON-NEXT: 0x00000000: Contribution size = 28, Format = DWARF32, Version = 5 # COMMON-NEXT: 0x00000008: 00000000 "Handmade DWARF producer" # COMMON-NEXT: 0x0000000c: 00000018 "Compile_Unit_1" # COMMON-NEXT: 0x00000010: 00000027 "/home/test/CU1" @@ -378,19 +366,19 @@ # COMMON-NEXT: 0x00000018: 0000006e "MyVar1" # COMMON-NEXT: 0x0000001c: 00000075 "MyVar2" # COMMON-NEXT: 0x00000020: 0000007c "MyVar3" -# COMMON-NEXT: 0x00000024: Contribution size = 12, Version = 5 -# COMMON-NEXT: 0x0000002c: 00000000 "Handmade DWARF producer" -# COMMON-NEXT: 0x00000030: 00000036 "Compile_Unit_2" -# COMMON-NEXT: 0x00000034: 00000045 "/home/test/CU2" -# COMMON-NEXT: 0x00000038: Contribution size = 8, Version = 5 -# COMMON-NEXT: 0x00000040: 00000054 "Type_Unit" -# COMMON-NEXT: 0x00000044: 0000005e "MyStruct" +# COMMON-NEXT: Gap, length = 4 +# COMMON-NEXT: 0x00000028: Contribution size = 24, Format = DWARF64, Version = 5 +# COMMON-NEXT: 0x00000038: 00000000 "Handmade DWARF producer" +# COMMON-NEXT: 0x00000040: 00000036 "Compile_Unit_2" +# COMMON-NEXT: 0x00000048: 00000045 "/home/test/CU2" +# COMMON-NEXT: 0x00000050: Contribution size = 8, Format = DWARF32, Version = 5 +# COMMON-NEXT: 0x00000058: 00000054 "Type_Unit" +# COMMON-NEXT: 0x0000005c: 0000005e "MyStruct" # # SPLIT: .debug_str_offsets.dwo contents: -# SPLIT-NEXT: 0x00000000: Contribution size = 12, Version = 5 +# SPLIT-NEXT: 0x00000000: Contribution size = 20, Format = DWARF32, Version = 5 # SPLIT-NEXT: 0x00000008: 00000000 "Handmade split DWARF producer" # SPLIT-NEXT: 0x0000000c: 0000001e "V5_split_compile_unit" # SPLIT-NEXT: 0x00000010: 00000034 "/home/test/splitCU" -# SPLIT-NEXT: 0x00000014: Contribution size = 8, Version = 5 -# SPLIT-NEXT: 0x0000001c: 00000047 "V5_split_type_unit" -# SPLIT-NEXT: 0x00000020: 0000005a "V5_split_Mystruct" +# SPLIT-NEXT: 0x00000014: 00000047 "V5_split_type_unit" +# SPLIT-NEXT: 0x00000018: 0000005a "V5_split_Mystruct"