diff options
Diffstat (limited to 'llvm/tools/llvm-dwp/llvm-dwp.cpp')
-rw-r--r-- | llvm/tools/llvm-dwp/llvm-dwp.cpp | 170 |
1 files changed, 115 insertions, 55 deletions
diff --git a/llvm/tools/llvm-dwp/llvm-dwp.cpp b/llvm/tools/llvm-dwp/llvm-dwp.cpp index c7cb1fc..926df64 100644 --- a/llvm/tools/llvm-dwp/llvm-dwp.cpp +++ b/llvm/tools/llvm-dwp/llvm-dwp.cpp @@ -77,9 +77,10 @@ static uint64_t debugStrOffsetsHeaderSize(DataExtractor StrOffsetsData, return 8; // unit length: 4 bytes, version: 2 bytes, padding: 2 bytes. } -// Holds data for Skeleton and Split Compilation Unit Headers as defined in -// Dwarf 5 specification, 7.5.1.2 and Dwarf 4 specification 7.5.1.1. -struct CompileUnitHeader { +// Holds data for Skeleton, Split Compilation, and Type Unit Headers (only in +// v5) as defined in Dwarf 5 specification, 7.5.1.2, 7.5.1.3 and Dwarf 4 +// specification 7.5.1.1. +struct InfoSectionUnitHeader { // unit_length field. Note that the type is uint64_t even in 32-bit dwarf. uint64_t Length = 0; @@ -108,9 +109,10 @@ struct CompileUnitHeader { uint8_t HeaderSize = 0; }; -// Parse and return the header of the compile unit. -static Expected<CompileUnitHeader> parseCompileUnitHeader(StringRef Info) { - CompileUnitHeader Header; +// Parse and return the header of an info section compile/type unit. +static Expected<InfoSectionUnitHeader> +parseInfoSectionUnitHeader(StringRef Info) { + InfoSectionUnitHeader Header; Error Err = Error::success(); uint64_t Offset = 0; DWARFDataExtractor InfoData(Info, true, 0); @@ -141,15 +143,22 @@ static Expected<CompileUnitHeader> parseCompileUnitHeader(StringRef Info) { MinHeaderLength = 7; } if (Header.Length < MinHeaderLength) { - return make_error<DWPError>( - "compile unit length is too small: expected at least " + - utostr(MinHeaderLength) + " got " + utostr(Header.Length) + "."); + return make_error<DWPError>("unit length is too small: expected at least " + + utostr(MinHeaderLength) + " got " + + utostr(Header.Length) + "."); } if (Header.Version >= 5) { Header.UnitType = InfoData.getU8(&Offset); Header.AddrSize = InfoData.getU8(&Offset); Header.DebugAbbrevOffset = InfoData.getU32(&Offset); Header.Signature = InfoData.getU64(&Offset); + if (Header.UnitType == dwarf::DW_UT_split_type) { + // Type offset. + MinHeaderLength += 4; + if (Header.Length < MinHeaderLength) + return make_error<DWPError>("type unit is missing type offset"); + InfoData.getU32(&Offset); + } } else { // Note that, address_size and debug_abbrev_offset fields have switched // places between dwarf version 4 and 5. @@ -165,7 +174,7 @@ static void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings, MCSection *StrOffsetSection, StringRef CurStrSection, StringRef CurStrOffsetSection, - const CompileUnitHeader &Header) { + const InfoSectionUnitHeader &Header) { // Could possibly produce an error or warning if one of these was non-null but // the other was null. if (CurStrSection.empty() || CurStrOffsetSection.empty()) @@ -259,14 +268,9 @@ getIndexedString(dwarf::Form Form, DataExtractor InfoData, uint64_t &InfoOffset, return StrData.getCStr(&StrOffset); } -static Expected<CompileUnitIdentifiers> getCUIdentifiers(StringRef Abbrev, - StringRef Info, - StringRef StrOffsets, - StringRef Str) { - Expected<CompileUnitHeader> HeaderOrError = parseCompileUnitHeader(Info); - if (!HeaderOrError) - return HeaderOrError.takeError(); - CompileUnitHeader &Header = *HeaderOrError; +static Expected<CompileUnitIdentifiers> +getCUIdentifiers(InfoSectionUnitHeader &Header, StringRef Abbrev, + StringRef Info, StringRef StrOffsets, StringRef Str) { DataExtractor InfoData(Info, true, 0); uint64_t Offset = Header.HeaderSize; if (Header.Version >= 5 && Header.UnitType != dwarf::DW_UT_split_compile) @@ -540,13 +544,14 @@ static Error handleSection( const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections, const MCSection *StrSection, const MCSection *StrOffsetSection, const MCSection *TypesSection, const MCSection *CUIndexSection, - const MCSection *TUIndexSection, const SectionRef &Section, MCStreamer &Out, + const MCSection *TUIndexSection, const MCSection *InfoSection, + const SectionRef &Section, MCStreamer &Out, std::deque<SmallString<32>> &UncompressedSections, uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry, StringRef &CurStrSection, StringRef &CurStrOffsetSection, - std::vector<StringRef> &CurTypesSection, StringRef &InfoSection, - StringRef &AbbrevSection, StringRef &CurCUIndexSection, - StringRef &CurTUIndexSection) { + std::vector<StringRef> &CurTypesSection, + std::vector<StringRef> &CurInfoSection, StringRef &AbbrevSection, + StringRef &CurCUIndexSection, StringRef &CurTUIndexSection) { if (Section.isBSS()) return Error::success(); @@ -574,21 +579,14 @@ static Error handleSection( if (DWARFSectionKind Kind = SectionPair->second.second) { auto Index = getContributionIndex(Kind); - if (Kind != DW_SECT_EXT_TYPES) { + if (Kind != DW_SECT_EXT_TYPES && Kind != DW_SECT_INFO) { CurEntry.Contributions[Index].Offset = ContributionOffsets[Index]; ContributionOffsets[Index] += (CurEntry.Contributions[Index].Length = Contents.size()); } - switch (Kind) { - case DW_SECT_INFO: - InfoSection = Contents; - break; - case DW_SECT_ABBREV: + if (Kind == DW_SECT_ABBREV) { AbbrevSection = Contents; - break; - default: - break; } } @@ -603,6 +601,8 @@ static Error handleSection( CurCUIndexSection = Contents; else if (OutSection == TUIndexSection) CurTUIndexSection = Contents; + else if (OutSection == InfoSection) + CurInfoSection.push_back(Contents); else { Out.SwitchSection(OutSection); Out.emitBytes(Contents); @@ -656,8 +656,9 @@ static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) { MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection(); MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection(); MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection(); + MCSection *const InfoSection = MCOFI.getDwarfInfoDWOSection(); const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = { - {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}}, + {"debug_info.dwo", {InfoSection, DW_SECT_INFO}}, {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}}, {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}}, {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}}, @@ -692,7 +693,7 @@ static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) { StringRef CurStrSection; StringRef CurStrOffsetSection; std::vector<StringRef> CurTypesSection; - StringRef InfoSection; + std::vector<StringRef> CurInfoSection; StringRef AbbrevSection; StringRef CurCUIndexSection; StringRef CurTUIndexSection; @@ -700,41 +701,86 @@ static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) { for (const auto &Section : Obj.sections()) if (auto Err = handleSection( KnownSections, StrSection, StrOffsetSection, TypesSection, - CUIndexSection, TUIndexSection, Section, Out, + CUIndexSection, TUIndexSection, InfoSection, Section, Out, UncompressedSections, ContributionOffsets, CurEntry, - CurStrSection, CurStrOffsetSection, CurTypesSection, InfoSection, - AbbrevSection, CurCUIndexSection, CurTUIndexSection)) + CurStrSection, CurStrOffsetSection, CurTypesSection, + CurInfoSection, AbbrevSection, CurCUIndexSection, + CurTUIndexSection)) return Err; - if (InfoSection.empty()) + if (CurInfoSection.empty()) continue; - Expected<CompileUnitHeader> CompileUnitHeaderOrErr = - parseCompileUnitHeader(InfoSection); - if (!CompileUnitHeaderOrErr) - return CompileUnitHeaderOrErr.takeError(); - CompileUnitHeader &CompileUnitHeader = *CompileUnitHeaderOrErr; + Expected<InfoSectionUnitHeader> HeaderOrErr = + parseInfoSectionUnitHeader(CurInfoSection.front()); + if (!HeaderOrErr) + return HeaderOrErr.takeError(); + InfoSectionUnitHeader &Header = *HeaderOrErr; writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection, - CurStrOffsetSection, CompileUnitHeader); + CurStrOffsetSection, Header); + uint32_t &InfoSectionOffset = + ContributionOffsets[getContributionIndex(DW_SECT_INFO)]; if (CurCUIndexSection.empty()) { - Expected<CompileUnitIdentifiers> EID = getCUIdentifiers( - AbbrevSection, InfoSection, CurStrOffsetSection, CurStrSection); - if (!EID) - return createFileError(Input, EID.takeError()); - const auto &ID = *EID; - auto P = IndexEntries.insert(std::make_pair(ID.Signature, CurEntry)); - if (!P.second) - return buildDuplicateError(*P.first, ID, ""); - P.first->second.Name = ID.Name; - P.first->second.DWOName = ID.DWOName; + bool FoundCUUnit = false; + Out.SwitchSection(InfoSection); + for (StringRef Info : CurInfoSection) { + if (FoundCUUnit) + break; + uint64_t UnitOffset = 0; + while (Info.size() > UnitOffset) { + Expected<InfoSectionUnitHeader> HeaderOrError = + parseInfoSectionUnitHeader(Info.substr(UnitOffset, Info.size())); + if (!HeaderOrError) + return HeaderOrError.takeError(); + InfoSectionUnitHeader &Header = *HeaderOrError; + + UnitIndexEntry Entry = CurEntry; + auto &C = Entry.Contributions[getContributionIndex(DW_SECT_INFO)]; + C.Offset = InfoSectionOffset; + C.Length = Header.Length + 4; + + if (Header.Version < 5 || + Header.UnitType == dwarf::DW_UT_split_compile) { + Expected<CompileUnitIdentifiers> EID = getCUIdentifiers( + Header, AbbrevSection, Info.substr(UnitOffset, C.Length), + CurStrOffsetSection, CurStrSection); + + if (!EID) + return createFileError(Input, EID.takeError()); + const auto &ID = *EID; + auto P = IndexEntries.insert(std::make_pair(ID.Signature, Entry)); + if (!P.second) + return buildDuplicateError(*P.first, ID, ""); + P.first->second.Name = ID.Name; + P.first->second.DWOName = ID.DWOName; + + Out.emitBytes(Info.substr(UnitOffset, C.Length)); + InfoSectionOffset += C.Length; + FoundCUUnit = true; + break; + } + UnitOffset += Header.Length + 4; + } + } + + if (!FoundCUUnit) + return make_error<DWPError>("no compile unit found in file: " + Input); + + // Add types from the .debug_types section from DWARF < 5. addAllTypes(Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry, ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]); + continue; } + if (CurInfoSection.size() != 1) + return make_error<DWPError>("expected exactly one occurrence of a debug " + "info section in a .dwp file"); + StringRef DwpSingleInfoSection = CurInfoSection.front(); + DWARFUnitIndex CUIndex(DW_SECT_INFO); DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0); if (!CUIndex.parse(CUIndexData)) @@ -744,14 +790,23 @@ static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) { "unsupported cu_index version: " + utostr(CUIndex.getVersion()) + " (only version 2 is supported)"); + Out.SwitchSection(InfoSection); for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) { auto *I = E.getContributions(); if (!I) continue; auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry)); + StringRef CUInfoSection = + getSubsection(DwpSingleInfoSection, E, DW_SECT_INFO); + Expected<InfoSectionUnitHeader> HeaderOrError = + parseInfoSectionUnitHeader(CUInfoSection); + if (!HeaderOrError) + return HeaderOrError.takeError(); + InfoSectionUnitHeader &Header = *HeaderOrError; + Expected<CompileUnitIdentifiers> EID = getCUIdentifiers( - getSubsection(AbbrevSection, E, DW_SECT_ABBREV), - getSubsection(InfoSection, E, DW_SECT_INFO), + Header, getSubsection(AbbrevSection, E, DW_SECT_ABBREV), + CUInfoSection, getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS), CurStrSection); if (!EID) @@ -771,6 +826,11 @@ static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) { C.Length = I->Length; ++I; } + unsigned Index = getContributionIndex(DW_SECT_INFO); + auto &C = NewEntry.Contributions[Index]; + Out.emitBytes(CUInfoSection); + C.Offset = InfoSectionOffset; + InfoSectionOffset += C.Length; } if (!CurTypesSection.empty()) { |