1 //===-- llvm-dwp.cpp - Split DWARF merging tool for llvm ------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // A utility for merging DWARF 5 Split DWARF .dwo files into .dwp (DWARF
12 //===----------------------------------------------------------------------===//
13 #include "llvm/DWP/DWP.h"
14 #include "llvm/ADT/Twine.h"
15 #include "llvm/DWP/DWPError.h"
16 #include "llvm/MC/MCContext.h"
17 #include "llvm/MC/MCObjectFileInfo.h"
18 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
19 #include "llvm/Object/Decompressor.h"
20 #include "llvm/Object/ELFObjectFile.h"
21 #include "llvm/Support/CommandLine.h"
22 #include "llvm/Support/MemoryBuffer.h"
26 using namespace llvm::object;
28 static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags;
30 // Returns the size of debug_str_offsets section headers in bytes.
31 static uint64_t debugStrOffsetsHeaderSize(DataExtractor StrOffsetsData,
32 uint16_t DwarfVersion) {
33 if (DwarfVersion <= 4)
34 return 0; // There is no header before dwarf 5.
36 uint64_t Length = StrOffsetsData.getU32(&Offset);
37 if (Length == llvm::dwarf::DW_LENGTH_DWARF64)
38 return 16; // unit length: 12 bytes, version: 2 bytes, padding: 2 bytes.
39 return 8; // unit length: 4 bytes, version: 2 bytes, padding: 2 bytes.
42 static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) {
44 DataExtractor AbbrevData(Abbrev, true, 0);
45 while (AbbrevData.getULEB128(&Offset) != AbbrCode) {
47 AbbrevData.getULEB128(&Offset);
49 AbbrevData.getU8(&Offset);
51 while (AbbrevData.getULEB128(&Offset) | AbbrevData.getULEB128(&Offset))
57 static Expected<const char *>
58 getIndexedString(dwarf::Form Form, DataExtractor InfoData, uint64_t &InfoOffset,
59 StringRef StrOffsets, StringRef Str, uint16_t Version) {
60 if (Form == dwarf::DW_FORM_string)
61 return InfoData.getCStr(&InfoOffset);
64 case dwarf::DW_FORM_strx1:
65 StrIndex = InfoData.getU8(&InfoOffset);
67 case dwarf::DW_FORM_strx2:
68 StrIndex = InfoData.getU16(&InfoOffset);
70 case dwarf::DW_FORM_strx3:
71 StrIndex = InfoData.getU24(&InfoOffset);
73 case dwarf::DW_FORM_strx4:
74 StrIndex = InfoData.getU32(&InfoOffset);
76 case dwarf::DW_FORM_strx:
77 case dwarf::DW_FORM_GNU_str_index:
78 StrIndex = InfoData.getULEB128(&InfoOffset);
81 return make_error<DWPError>(
82 "string field must be encoded with one of the following: "
83 "DW_FORM_string, DW_FORM_strx, DW_FORM_strx1, DW_FORM_strx2, "
84 "DW_FORM_strx3, DW_FORM_strx4, or DW_FORM_GNU_str_index.");
86 DataExtractor StrOffsetsData(StrOffsets, true, 0);
87 uint64_t StrOffsetsOffset = 4 * StrIndex;
88 StrOffsetsOffset += debugStrOffsetsHeaderSize(StrOffsetsData, Version);
90 uint64_t StrOffset = StrOffsetsData.getU32(&StrOffsetsOffset);
91 DataExtractor StrData(Str, true, 0);
92 return StrData.getCStr(&StrOffset);
95 static Expected<CompileUnitIdentifiers>
96 getCUIdentifiers(InfoSectionUnitHeader &Header, StringRef Abbrev,
97 StringRef Info, StringRef StrOffsets, StringRef Str) {
98 DataExtractor InfoData(Info, true, 0);
99 uint64_t Offset = Header.HeaderSize;
100 if (Header.Version >= 5 && Header.UnitType != dwarf::DW_UT_split_compile)
101 return make_error<DWPError>(
102 std::string("unit type DW_UT_split_compile type not found in "
103 "debug_info header. Unexpected unit type 0x" +
104 utostr(Header.UnitType) + " found"));
106 CompileUnitIdentifiers ID;
108 uint32_t AbbrCode = InfoData.getULEB128(&Offset);
109 DataExtractor AbbrevData(Abbrev, true, 0);
110 uint64_t AbbrevOffset = getCUAbbrev(Abbrev, AbbrCode);
111 auto Tag = static_cast<dwarf::Tag>(AbbrevData.getULEB128(&AbbrevOffset));
112 if (Tag != dwarf::DW_TAG_compile_unit)
113 return make_error<DWPError>("top level DIE is not a compile unit");
115 AbbrevData.getU8(&AbbrevOffset);
118 while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) |
119 (Form = static_cast<dwarf::Form>(
120 AbbrevData.getULEB128(&AbbrevOffset))) &&
121 (Name != 0 || Form != 0)) {
123 case dwarf::DW_AT_name: {
124 Expected<const char *> EName = getIndexedString(
125 Form, InfoData, Offset, StrOffsets, Str, Header.Version);
127 return EName.takeError();
131 case dwarf::DW_AT_GNU_dwo_name:
132 case dwarf::DW_AT_dwo_name: {
133 Expected<const char *> EName = getIndexedString(
134 Form, InfoData, Offset, StrOffsets, Str, Header.Version);
136 return EName.takeError();
140 case dwarf::DW_AT_GNU_dwo_id:
141 Header.Signature = InfoData.getU64(&Offset);
144 DWARFFormValue::skipValue(
145 Form, InfoData, &Offset,
146 dwarf::FormParams({Header.Version, Header.AddrSize, Header.Format}));
149 if (!Header.Signature)
150 return make_error<DWPError>("compile unit missing dwo_id");
151 ID.Signature = *Header.Signature;
155 static bool isSupportedSectionKind(DWARFSectionKind Kind) {
156 return Kind != DW_SECT_EXT_unknown;
160 // Convert an internal section identifier into the index to use with
161 // UnitIndexEntry::Contributions.
162 unsigned getContributionIndex(DWARFSectionKind Kind, uint32_t IndexVersion) {
163 assert(serializeSectionKind(Kind, IndexVersion) >= DW_SECT_INFO);
164 return serializeSectionKind(Kind, IndexVersion) - DW_SECT_INFO;
168 // Convert a UnitIndexEntry::Contributions index to the corresponding on-disk
169 // value of the section identifier.
170 static unsigned getOnDiskSectionId(unsigned Index) {
171 return Index + DW_SECT_INFO;
174 static StringRef getSubsection(StringRef Section,
175 const DWARFUnitIndex::Entry &Entry,
176 DWARFSectionKind Kind) {
177 const auto *Off = Entry.getContribution(Kind);
180 return Section.substr(Off->getOffset(), Off->getLength());
183 static Error sectionOverflowErrorOrWarning(uint32_t PrevOffset,
184 uint32_t OverflowedOffset,
185 StringRef SectionName,
186 bool ContinueOnCuIndexOverflow) {
189 Twine(" Section Contribution Offset overflow 4G. Previous Offset ") +
190 Twine(PrevOffset) + Twine(", After overflow offset ") +
191 Twine(OverflowedOffset) + Twine("."))
193 if (ContinueOnCuIndexOverflow) {
194 WithColor::defaultWarningHandler(make_error<DWPError>(Msg));
195 return Error::success();
197 return make_error<DWPError>(Msg);
200 static Error addAllTypesFromDWP(
201 MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
202 const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types,
203 const UnitIndexEntry &TUEntry, uint32_t &TypesOffset,
204 unsigned TypesContributionIndex, bool ContinueOnCuIndexOverflow) {
205 Out.switchSection(OutputTypes);
206 for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) {
207 auto *I = E.getContributions();
210 auto P = TypeIndexEntries.insert(std::make_pair(E.getSignature(), TUEntry));
213 auto &Entry = P.first->second;
214 // Zero out the debug_info contribution
215 Entry.Contributions[0] = {};
216 for (auto Kind : TUIndex.getColumnKinds()) {
217 if (!isSupportedSectionKind(Kind))
220 Entry.Contributions[getContributionIndex(Kind, TUIndex.getVersion())];
221 C.setOffset(C.getOffset() + I->getOffset());
222 C.setLength(I->getLength());
225 auto &C = Entry.Contributions[TypesContributionIndex];
226 Out.emitBytes(Types.substr(
228 TUEntry.Contributions[TypesContributionIndex].getOffset(),
230 C.setOffset(TypesOffset);
231 uint32_t OldOffset = TypesOffset;
232 static_assert(sizeof(OldOffset) == sizeof(TypesOffset));
233 TypesOffset += C.getLength();
234 if (OldOffset > TypesOffset) {
235 if (Error Err = sectionOverflowErrorOrWarning(
236 OldOffset, TypesOffset, "Types", ContinueOnCuIndexOverflow))
240 return Error::success();
243 static Error addAllTypesFromTypesSection(
244 MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
245 MCSection *OutputTypes, const std::vector<StringRef> &TypesSections,
246 const UnitIndexEntry &CUEntry, uint32_t &TypesOffset,
247 bool ContinueOnCuIndexOverflow) {
248 for (StringRef Types : TypesSections) {
249 Out.switchSection(OutputTypes);
251 DataExtractor Data(Types, true, 0);
252 while (Data.isValidOffset(Offset)) {
253 UnitIndexEntry Entry = CUEntry;
254 // Zero out the debug_info contribution
255 Entry.Contributions[0] = {};
256 auto &C = Entry.Contributions[getContributionIndex(DW_SECT_EXT_TYPES, 2)];
257 C.setOffset(TypesOffset);
258 auto PrevOffset = Offset;
259 // Length of the unit, including the 4 byte length field.
260 C.setLength(Data.getU32(&Offset) + 4);
262 Data.getU16(&Offset); // Version
263 Data.getU32(&Offset); // Abbrev offset
264 Data.getU8(&Offset); // Address size
265 auto Signature = Data.getU64(&Offset);
266 Offset = PrevOffset + C.getLength32();
268 auto P = TypeIndexEntries.insert(std::make_pair(Signature, Entry));
272 Out.emitBytes(Types.substr(PrevOffset, C.getLength32()));
273 uint32_t OldOffset = TypesOffset;
274 TypesOffset += C.getLength32();
275 if (OldOffset > TypesOffset) {
276 if (Error Err = sectionOverflowErrorOrWarning(
277 OldOffset, TypesOffset, "types", ContinueOnCuIndexOverflow))
282 return Error::success();
285 static std::string buildDWODescription(StringRef Name, StringRef DWPName,
287 std::string Text = "\'";
290 bool HasDWO = !DWOName.empty();
291 bool HasDWP = !DWPName.empty();
292 if (HasDWO || HasDWP) {
299 if (HasDWO && HasDWP)
301 if (!DWPName.empty()) {
311 static Error createError(StringRef Name, Error E) {
312 return make_error<DWPError>(
313 ("failure while decompressing compressed section: '" + Name + "', " +
314 llvm::toString(std::move(E)))
319 handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections,
320 SectionRef Sec, StringRef Name, StringRef &Contents) {
321 auto *Obj = dyn_cast<ELFObjectFileBase>(Sec.getObject());
323 !(static_cast<ELFSectionRef>(Sec).getFlags() & ELF::SHF_COMPRESSED))
324 return Error::success();
325 bool IsLE = isa<object::ELF32LEObjectFile>(Obj) ||
326 isa<object::ELF64LEObjectFile>(Obj);
327 bool Is64 = isa<object::ELF64LEObjectFile>(Obj) ||
328 isa<object::ELF64BEObjectFile>(Obj);
329 Expected<Decompressor> Dec = Decompressor::create(Name, Contents, IsLE, Is64);
331 return createError(Name, Dec.takeError());
333 UncompressedSections.emplace_back();
334 if (Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
335 return createError(Name, std::move(E));
337 Contents = UncompressedSections.back();
338 return Error::success();
342 // Parse and return the header of an info section compile/type unit.
343 Expected<InfoSectionUnitHeader> parseInfoSectionUnitHeader(StringRef Info) {
344 InfoSectionUnitHeader Header;
345 Error Err = Error::success();
347 DWARFDataExtractor InfoData(Info, true, 0);
348 std::tie(Header.Length, Header.Format) =
349 InfoData.getInitialLength(&Offset, &Err);
351 return make_error<DWPError>("cannot parse compile unit length: " +
352 llvm::toString(std::move(Err)));
354 if (!InfoData.isValidOffset(Offset + (Header.Length - 1))) {
355 return make_error<DWPError>(
356 "compile unit exceeds .debug_info section range: " +
357 utostr(Offset + Header.Length) + " >= " + utostr(InfoData.size()));
360 Header.Version = InfoData.getU16(&Offset, &Err);
362 return make_error<DWPError>("cannot parse compile unit version: " +
363 llvm::toString(std::move(Err)));
365 uint64_t MinHeaderLength;
366 if (Header.Version >= 5) {
367 // Size: Version (2), UnitType (1), AddrSize (1), DebugAbbrevOffset (4),
369 MinHeaderLength = 16;
371 // Size: Version (2), DebugAbbrevOffset (4), AddrSize (1)
374 if (Header.Length < MinHeaderLength) {
375 return make_error<DWPError>("unit length is too small: expected at least " +
376 utostr(MinHeaderLength) + " got " +
377 utostr(Header.Length) + ".");
379 if (Header.Version >= 5) {
380 Header.UnitType = InfoData.getU8(&Offset);
381 Header.AddrSize = InfoData.getU8(&Offset);
382 Header.DebugAbbrevOffset = InfoData.getU32(&Offset);
383 Header.Signature = InfoData.getU64(&Offset);
384 if (Header.UnitType == dwarf::DW_UT_split_type) {
386 MinHeaderLength += 4;
387 if (Header.Length < MinHeaderLength)
388 return make_error<DWPError>("type unit is missing type offset");
389 InfoData.getU32(&Offset);
392 // Note that, address_size and debug_abbrev_offset fields have switched
393 // places between dwarf version 4 and 5.
394 Header.DebugAbbrevOffset = InfoData.getU32(&Offset);
395 Header.AddrSize = InfoData.getU8(&Offset);
398 Header.HeaderSize = Offset;
402 void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,
403 MCSection *StrOffsetSection,
404 StringRef CurStrSection,
405 StringRef CurStrOffsetSection, uint16_t Version) {
406 // Could possibly produce an error or warning if one of these was non-null but
407 // the other was null.
408 if (CurStrSection.empty() || CurStrOffsetSection.empty())
411 DenseMap<uint64_t, uint32_t> OffsetRemapping;
413 DataExtractor Data(CurStrSection, true, 0);
414 uint64_t LocalOffset = 0;
415 uint64_t PrevOffset = 0;
416 while (const char *S = Data.getCStr(&LocalOffset)) {
417 OffsetRemapping[PrevOffset] =
418 Strings.getOffset(S, LocalOffset - PrevOffset);
419 PrevOffset = LocalOffset;
422 Data = DataExtractor(CurStrOffsetSection, true, 0);
424 Out.switchSection(StrOffsetSection);
426 uint64_t HeaderSize = debugStrOffsetsHeaderSize(Data, Version);
428 uint64_t Size = CurStrOffsetSection.size();
429 // FIXME: This can be caused by bad input and should be handled as such.
430 assert(HeaderSize <= Size && "StrOffsetSection size is less than its header");
431 // Copy the header to the output.
432 Out.emitBytes(Data.getBytes(&Offset, HeaderSize));
433 while (Offset < Size) {
434 auto OldOffset = Data.getU32(&Offset);
435 auto NewOffset = OffsetRemapping[OldOffset];
436 Out.emitIntValue(NewOffset, 4);
440 enum AccessField { Offset, Length };
441 void writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
442 const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
443 const AccessField &Field) {
444 for (const auto &E : IndexEntries)
445 for (size_t I = 0; I != std::size(E.second.Contributions); ++I)
446 if (ContributionOffsets[I])
447 Out.emitIntValue((Field == AccessField::Offset
448 ? E.second.Contributions[I].getOffset32()
449 : E.second.Contributions[I].getLength32()),
453 void writeIndex(MCStreamer &Out, MCSection *Section,
454 ArrayRef<unsigned> ContributionOffsets,
455 const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
456 uint32_t IndexVersion) {
457 if (IndexEntries.empty())
460 unsigned Columns = 0;
461 for (auto &C : ContributionOffsets)
465 std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
466 uint64_t Mask = Buckets.size() - 1;
468 for (const auto &P : IndexEntries) {
471 auto HP = ((S >> 32) & Mask) | 1;
473 assert(S != IndexEntries.begin()[Buckets[H] - 1].first &&
481 Out.switchSection(Section);
482 Out.emitIntValue(IndexVersion, 4); // Version
483 Out.emitIntValue(Columns, 4); // Columns
484 Out.emitIntValue(IndexEntries.size(), 4); // Num Units
485 Out.emitIntValue(Buckets.size(), 4); // Num Buckets
487 // Write the signatures.
488 for (const auto &I : Buckets)
489 Out.emitIntValue(I ? IndexEntries.begin()[I - 1].first : 0, 8);
491 // Write the indexes.
492 for (const auto &I : Buckets)
493 Out.emitIntValue(I, 4);
495 // Write the column headers (which sections will appear in the table)
496 for (size_t I = 0; I != ContributionOffsets.size(); ++I)
497 if (ContributionOffsets[I])
498 Out.emitIntValue(getOnDiskSectionId(I), 4);
500 // Write the offsets.
501 writeIndexTable(Out, ContributionOffsets, IndexEntries, AccessField::Offset);
503 // Write the lengths.
504 writeIndexTable(Out, ContributionOffsets, IndexEntries, AccessField::Length);
507 Error buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
508 const CompileUnitIdentifiers &ID, StringRef DWPName) {
509 return make_error<DWPError>(
510 std::string("duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " +
511 buildDWODescription(PrevE.second.Name, PrevE.second.DWPName,
512 PrevE.second.DWOName) +
513 " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));
517 const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
518 const MCSection *StrSection, const MCSection *StrOffsetSection,
519 const MCSection *TypesSection, const MCSection *CUIndexSection,
520 const MCSection *TUIndexSection, const MCSection *InfoSection,
521 const SectionRef &Section, MCStreamer &Out,
522 std::deque<SmallString<32>> &UncompressedSections,
523 uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry,
524 StringRef &CurStrSection, StringRef &CurStrOffsetSection,
525 std::vector<StringRef> &CurTypesSection,
526 std::vector<StringRef> &CurInfoSection, StringRef &AbbrevSection,
527 StringRef &CurCUIndexSection, StringRef &CurTUIndexSection,
528 std::vector<std::pair<DWARFSectionKind, uint32_t>> &SectionLength) {
530 return Error::success();
532 if (Section.isVirtual())
533 return Error::success();
535 Expected<StringRef> NameOrErr = Section.getName();
537 return NameOrErr.takeError();
538 StringRef Name = *NameOrErr;
540 Expected<StringRef> ContentsOrErr = Section.getContents();
542 return ContentsOrErr.takeError();
543 StringRef Contents = *ContentsOrErr;
545 if (auto Err = handleCompressedSection(UncompressedSections, Section, Name,
549 Name = Name.substr(Name.find_first_not_of("._"));
551 auto SectionPair = KnownSections.find(Name);
552 if (SectionPair == KnownSections.end())
553 return Error::success();
555 if (DWARFSectionKind Kind = SectionPair->second.second) {
556 if (Kind != DW_SECT_EXT_TYPES && Kind != DW_SECT_INFO) {
557 SectionLength.push_back(std::make_pair(Kind, Contents.size()));
560 if (Kind == DW_SECT_ABBREV) {
561 AbbrevSection = Contents;
565 MCSection *OutSection = SectionPair->second.first;
566 if (OutSection == StrOffsetSection)
567 CurStrOffsetSection = Contents;
568 else if (OutSection == StrSection)
569 CurStrSection = Contents;
570 else if (OutSection == TypesSection)
571 CurTypesSection.push_back(Contents);
572 else if (OutSection == CUIndexSection)
573 CurCUIndexSection = Contents;
574 else if (OutSection == TUIndexSection)
575 CurTUIndexSection = Contents;
576 else if (OutSection == InfoSection)
577 CurInfoSection.push_back(Contents);
579 Out.switchSection(OutSection);
580 Out.emitBytes(Contents);
582 return Error::success();
585 Error write(MCStreamer &Out, ArrayRef<std::string> Inputs,
586 bool ContinueOnCuIndexOverflow) {
587 const auto &MCOFI = *Out.getContext().getObjectFileInfo();
588 MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
589 MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
590 MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection();
591 MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection();
592 MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection();
593 MCSection *const InfoSection = MCOFI.getDwarfInfoDWOSection();
594 const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = {
595 {"debug_info.dwo", {InfoSection, DW_SECT_INFO}},
596 {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},
597 {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
598 {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}},
599 {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},
600 {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
601 {"debug_macro.dwo", {MCOFI.getDwarfMacroDWOSection(), DW_SECT_MACRO}},
602 {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
603 {"debug_loclists.dwo",
604 {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},
605 {"debug_rnglists.dwo",
606 {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}},
607 {"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}},
608 {"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};
610 MapVector<uint64_t, UnitIndexEntry> IndexEntries;
611 MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
613 uint32_t ContributionOffsets[8] = {};
614 uint16_t Version = 0;
615 uint32_t IndexVersion = 0;
617 DWPStringPool Strings(Out, StrSection);
619 SmallVector<OwningBinary<object::ObjectFile>, 128> Objects;
620 Objects.reserve(Inputs.size());
622 std::deque<SmallString<32>> UncompressedSections;
624 for (const auto &Input : Inputs) {
625 auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
627 return handleErrors(ErrOrObj.takeError(),
628 [&](std::unique_ptr<ECError> EC) -> Error {
629 return createFileError(Input, Error(std::move(EC)));
633 auto &Obj = *ErrOrObj->getBinary();
634 Objects.push_back(std::move(*ErrOrObj));
636 UnitIndexEntry CurEntry = {};
638 StringRef CurStrSection;
639 StringRef CurStrOffsetSection;
640 std::vector<StringRef> CurTypesSection;
641 std::vector<StringRef> CurInfoSection;
642 StringRef AbbrevSection;
643 StringRef CurCUIndexSection;
644 StringRef CurTUIndexSection;
646 // This maps each section contained in this file to its length.
647 // This information is later on used to calculate the contributions,
648 // i.e. offset and length, of each compile/type unit to a section.
649 std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength;
651 for (const auto &Section : Obj.sections())
652 if (auto Err = handleSection(
653 KnownSections, StrSection, StrOffsetSection, TypesSection,
654 CUIndexSection, TUIndexSection, InfoSection, Section, Out,
655 UncompressedSections, ContributionOffsets, CurEntry,
656 CurStrSection, CurStrOffsetSection, CurTypesSection,
657 CurInfoSection, AbbrevSection, CurCUIndexSection,
658 CurTUIndexSection, SectionLength))
661 if (CurInfoSection.empty())
664 Expected<InfoSectionUnitHeader> HeaderOrErr =
665 parseInfoSectionUnitHeader(CurInfoSection.front());
667 return HeaderOrErr.takeError();
668 InfoSectionUnitHeader &Header = *HeaderOrErr;
671 Version = Header.Version;
672 IndexVersion = Version < 5 ? 2 : 5;
673 } else if (Version != Header.Version) {
674 return make_error<DWPError>("incompatible DWARF compile unit versions.");
677 writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection,
678 CurStrOffsetSection, Header.Version);
680 for (auto Pair : SectionLength) {
681 auto Index = getContributionIndex(Pair.first, IndexVersion);
682 CurEntry.Contributions[Index].setOffset(ContributionOffsets[Index]);
683 CurEntry.Contributions[Index].setLength(Pair.second);
684 uint32_t OldOffset = ContributionOffsets[Index];
685 ContributionOffsets[Index] += CurEntry.Contributions[Index].getLength32();
686 if (OldOffset > ContributionOffsets[Index]) {
687 uint32_t SectionIndex = 0;
688 for (auto &Section : Obj.sections()) {
689 if (SectionIndex == Index) {
690 return sectionOverflowErrorOrWarning(
691 OldOffset, ContributionOffsets[Index], *Section.getName(),
692 ContinueOnCuIndexOverflow);
699 uint32_t &InfoSectionOffset =
700 ContributionOffsets[getContributionIndex(DW_SECT_INFO, IndexVersion)];
701 if (CurCUIndexSection.empty()) {
702 bool FoundCUUnit = false;
703 Out.switchSection(InfoSection);
704 for (StringRef Info : CurInfoSection) {
705 uint64_t UnitOffset = 0;
706 while (Info.size() > UnitOffset) {
707 Expected<InfoSectionUnitHeader> HeaderOrError =
708 parseInfoSectionUnitHeader(Info.substr(UnitOffset, Info.size()));
710 return HeaderOrError.takeError();
711 InfoSectionUnitHeader &Header = *HeaderOrError;
713 UnitIndexEntry Entry = CurEntry;
714 auto &C = Entry.Contributions[getContributionIndex(DW_SECT_INFO,
716 C.setOffset(InfoSectionOffset);
717 C.setLength(Header.Length + 4);
719 if (std::numeric_limits<uint32_t>::max() - InfoSectionOffset <
721 if (Error Err = sectionOverflowErrorOrWarning(
722 InfoSectionOffset, InfoSectionOffset + C.getLength32(),
723 "debug_info", ContinueOnCuIndexOverflow))
727 UnitOffset += C.getLength32();
728 if (Header.Version < 5 ||
729 Header.UnitType == dwarf::DW_UT_split_compile) {
730 Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
731 Header, AbbrevSection,
732 Info.substr(UnitOffset - C.getLength32(), C.getLength32()),
733 CurStrOffsetSection, CurStrSection);
736 return createFileError(Input, EID.takeError());
737 const auto &ID = *EID;
738 auto P = IndexEntries.insert(std::make_pair(ID.Signature, Entry));
740 return buildDuplicateError(*P.first, ID, "");
741 P.first->second.Name = ID.Name;
742 P.first->second.DWOName = ID.DWOName;
745 } else if (Header.UnitType == dwarf::DW_UT_split_type) {
746 auto P = TypeIndexEntries.insert(
747 std::make_pair(*Header.Signature, Entry));
752 Info.substr(UnitOffset - C.getLength32(), C.getLength32()));
753 InfoSectionOffset += C.getLength32();
758 return make_error<DWPError>("no compile unit found in file: " + Input);
760 if (IndexVersion == 2) {
761 // Add types from the .debug_types section from DWARF < 5.
762 if (Error Err = addAllTypesFromTypesSection(
763 Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry,
764 ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)],
765 ContinueOnCuIndexOverflow))
771 if (CurInfoSection.size() != 1)
772 return make_error<DWPError>("expected exactly one occurrence of a debug "
773 "info section in a .dwp file");
774 StringRef DwpSingleInfoSection = CurInfoSection.front();
776 DWARFUnitIndex CUIndex(DW_SECT_INFO);
777 DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
778 if (!CUIndex.parse(CUIndexData))
779 return make_error<DWPError>("failed to parse cu_index");
780 if (CUIndex.getVersion() != IndexVersion)
781 return make_error<DWPError>("incompatible cu_index versions, found " +
782 utostr(CUIndex.getVersion()) +
783 " and expecting " + utostr(IndexVersion));
785 Out.switchSection(InfoSection);
786 for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
787 auto *I = E.getContributions();
790 auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry));
791 StringRef CUInfoSection =
792 getSubsection(DwpSingleInfoSection, E, DW_SECT_INFO);
793 Expected<InfoSectionUnitHeader> HeaderOrError =
794 parseInfoSectionUnitHeader(CUInfoSection);
796 return HeaderOrError.takeError();
797 InfoSectionUnitHeader &Header = *HeaderOrError;
799 Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
800 Header, getSubsection(AbbrevSection, E, DW_SECT_ABBREV),
802 getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS),
805 return createFileError(Input, EID.takeError());
806 const auto &ID = *EID;
808 return buildDuplicateError(*P.first, ID, Input);
809 auto &NewEntry = P.first->second;
810 NewEntry.Name = ID.Name;
811 NewEntry.DWOName = ID.DWOName;
812 NewEntry.DWPName = Input;
813 for (auto Kind : CUIndex.getColumnKinds()) {
814 if (!isSupportedSectionKind(Kind))
817 NewEntry.Contributions[getContributionIndex(Kind, IndexVersion)];
818 C.setOffset(C.getOffset() + I->getOffset());
819 C.setLength(I->getLength());
822 unsigned Index = getContributionIndex(DW_SECT_INFO, IndexVersion);
823 auto &C = NewEntry.Contributions[Index];
824 Out.emitBytes(CUInfoSection);
825 C.setOffset(InfoSectionOffset);
826 InfoSectionOffset += C.getLength32();
829 if (!CurTUIndexSection.empty()) {
830 llvm::DWARFSectionKind TUSectionKind;
831 MCSection *OutSection;
832 StringRef TypeInputSection;
833 // Write type units into debug info section for DWARFv5.
835 TUSectionKind = DW_SECT_INFO;
836 OutSection = InfoSection;
837 TypeInputSection = DwpSingleInfoSection;
839 // Write type units into debug types section for DWARF < 5.
840 if (CurTypesSection.size() != 1)
841 return make_error<DWPError>(
842 "multiple type unit sections in .dwp file");
844 TUSectionKind = DW_SECT_EXT_TYPES;
845 OutSection = TypesSection;
846 TypeInputSection = CurTypesSection.front();
849 DWARFUnitIndex TUIndex(TUSectionKind);
850 DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);
851 if (!TUIndex.parse(TUIndexData))
852 return make_error<DWPError>("failed to parse tu_index");
853 if (TUIndex.getVersion() != IndexVersion)
854 return make_error<DWPError>("incompatible tu_index versions, found " +
855 utostr(TUIndex.getVersion()) +
856 " and expecting " + utostr(IndexVersion));
858 unsigned TypesContributionIndex =
859 getContributionIndex(TUSectionKind, IndexVersion);
860 if (Error Err = addAllTypesFromDWP(
861 Out, TypeIndexEntries, TUIndex, OutSection, TypeInputSection,
862 CurEntry, ContributionOffsets[TypesContributionIndex],
863 TypesContributionIndex, ContinueOnCuIndexOverflow))
869 // Lie about there being no info contributions so the TU index only includes
870 // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a
871 // contribution to the info section, so we do not want to lie about it.
872 ContributionOffsets[0] = 0;
874 writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
875 TypeIndexEntries, IndexVersion);
878 // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
879 // section does not exist, so no need to do anything about this.
880 ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0;
881 // Unlie about the info contribution
882 ContributionOffsets[0] = 1;
885 writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
886 IndexEntries, IndexVersion);
888 return Error::success();