1 //===-- llvm-dwp.cpp - Split DWARF merging tool for llvm ------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // A utility for merging DWARF 5 Split DWARF .dwo files into .dwp (DWARF
10 // package files).
11 //
12 //===----------------------------------------------------------------------===//
13 #include "llvm/DWP/DWP.h"
14 #include "llvm/DWP/DWPError.h"
15 #include "llvm/MC/MCContext.h"
16 #include "llvm/MC/MCObjectFileInfo.h"
17 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
18 #include "llvm/Object/Decompressor.h"
19 #include "llvm/Object/ELFObjectFile.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include <limits>
22 
23 using namespace llvm;
24 using namespace llvm::object;
25 
26 static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags;
27 
28 // Returns the size of debug_str_offsets section headers in bytes.
29 static uint64_t debugStrOffsetsHeaderSize(DataExtractor StrOffsetsData,
30                                           uint16_t DwarfVersion) {
31   if (DwarfVersion <= 4)
32     return 0; // There is no header before dwarf 5.
33   uint64_t Offset = 0;
34   uint64_t Length = StrOffsetsData.getU32(&Offset);
35   if (Length == llvm::dwarf::DW_LENGTH_DWARF64)
36     return 16; // unit length: 12 bytes, version: 2 bytes, padding: 2 bytes.
37   return 8;    // unit length: 4 bytes, version: 2 bytes, padding: 2 bytes.
38 }
39 
40 static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) {
41   uint64_t Offset = 0;
42   DataExtractor AbbrevData(Abbrev, true, 0);
43   while (AbbrevData.getULEB128(&Offset) != AbbrCode) {
44     // Tag
45     AbbrevData.getULEB128(&Offset);
46     // DW_CHILDREN
47     AbbrevData.getU8(&Offset);
48     // Attributes
49     while (AbbrevData.getULEB128(&Offset) | AbbrevData.getULEB128(&Offset))
50       ;
51   }
52   return Offset;
53 }
54 
55 static Expected<const char *>
56 getIndexedString(dwarf::Form Form, DataExtractor InfoData, uint64_t &InfoOffset,
57                  StringRef StrOffsets, StringRef Str, uint16_t Version) {
58   if (Form == dwarf::DW_FORM_string)
59     return InfoData.getCStr(&InfoOffset);
60   uint64_t StrIndex;
61   switch (Form) {
62   case dwarf::DW_FORM_strx1:
63     StrIndex = InfoData.getU8(&InfoOffset);
64     break;
65   case dwarf::DW_FORM_strx2:
66     StrIndex = InfoData.getU16(&InfoOffset);
67     break;
68   case dwarf::DW_FORM_strx3:
69     StrIndex = InfoData.getU24(&InfoOffset);
70     break;
71   case dwarf::DW_FORM_strx4:
72     StrIndex = InfoData.getU32(&InfoOffset);
73     break;
74   case dwarf::DW_FORM_strx:
75   case dwarf::DW_FORM_GNU_str_index:
76     StrIndex = InfoData.getULEB128(&InfoOffset);
77     break;
78   default:
79     return make_error<DWPError>(
80         "string field must be encoded with one of the following: "
81         "DW_FORM_string, DW_FORM_strx, DW_FORM_strx1, DW_FORM_strx2, "
82         "DW_FORM_strx3, DW_FORM_strx4, or DW_FORM_GNU_str_index.");
83   }
84   DataExtractor StrOffsetsData(StrOffsets, true, 0);
85   uint64_t StrOffsetsOffset = 4 * StrIndex;
86   StrOffsetsOffset += debugStrOffsetsHeaderSize(StrOffsetsData, Version);
87 
88   uint64_t StrOffset = StrOffsetsData.getU32(&StrOffsetsOffset);
89   DataExtractor StrData(Str, true, 0);
90   return StrData.getCStr(&StrOffset);
91 }
92 
93 static Expected<CompileUnitIdentifiers>
94 getCUIdentifiers(InfoSectionUnitHeader &Header, StringRef Abbrev,
95                  StringRef Info, StringRef StrOffsets, StringRef Str) {
96   DataExtractor InfoData(Info, true, 0);
97   uint64_t Offset = Header.HeaderSize;
98   if (Header.Version >= 5 && Header.UnitType != dwarf::DW_UT_split_compile)
99     return make_error<DWPError>(
100         std::string("unit type DW_UT_split_compile type not found in "
101                     "debug_info header. Unexpected unit type 0x" +
102                     utostr(Header.UnitType) + " found"));
103 
104   CompileUnitIdentifiers ID;
105 
106   uint32_t AbbrCode = InfoData.getULEB128(&Offset);
107   DataExtractor AbbrevData(Abbrev, true, 0);
108   uint64_t AbbrevOffset = getCUAbbrev(Abbrev, AbbrCode);
109   auto Tag = static_cast<dwarf::Tag>(AbbrevData.getULEB128(&AbbrevOffset));
110   if (Tag != dwarf::DW_TAG_compile_unit)
111     return make_error<DWPError>("top level DIE is not a compile unit");
112   // DW_CHILDREN
113   AbbrevData.getU8(&AbbrevOffset);
114   uint32_t Name;
115   dwarf::Form Form;
116   while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) |
117              (Form = static_cast<dwarf::Form>(
118                   AbbrevData.getULEB128(&AbbrevOffset))) &&
119          (Name != 0 || Form != 0)) {
120     switch (Name) {
121     case dwarf::DW_AT_name: {
122       Expected<const char *> EName = getIndexedString(
123           Form, InfoData, Offset, StrOffsets, Str, Header.Version);
124       if (!EName)
125         return EName.takeError();
126       ID.Name = *EName;
127       break;
128     }
129     case dwarf::DW_AT_GNU_dwo_name:
130     case dwarf::DW_AT_dwo_name: {
131       Expected<const char *> EName = getIndexedString(
132           Form, InfoData, Offset, StrOffsets, Str, Header.Version);
133       if (!EName)
134         return EName.takeError();
135       ID.DWOName = *EName;
136       break;
137     }
138     case dwarf::DW_AT_GNU_dwo_id:
139       Header.Signature = InfoData.getU64(&Offset);
140       break;
141     default:
142       DWARFFormValue::skipValue(
143           Form, InfoData, &Offset,
144           dwarf::FormParams({Header.Version, Header.AddrSize, Header.Format}));
145     }
146   }
147   if (!Header.Signature)
148     return make_error<DWPError>("compile unit missing dwo_id");
149   ID.Signature = *Header.Signature;
150   return ID;
151 }
152 
153 static bool isSupportedSectionKind(DWARFSectionKind Kind) {
154   return Kind != DW_SECT_EXT_unknown;
155 }
156 
157 namespace llvm {
158 // Convert an internal section identifier into the index to use with
159 // UnitIndexEntry::Contributions.
160 unsigned getContributionIndex(DWARFSectionKind Kind, uint32_t IndexVersion) {
161   assert(serializeSectionKind(Kind, IndexVersion) >= DW_SECT_INFO);
162   return serializeSectionKind(Kind, IndexVersion) - DW_SECT_INFO;
163 }
164 } // namespace llvm
165 
166 // Convert a UnitIndexEntry::Contributions index to the corresponding on-disk
167 // value of the section identifier.
168 static unsigned getOnDiskSectionId(unsigned Index) {
169   return Index + DW_SECT_INFO;
170 }
171 
172 static StringRef getSubsection(StringRef Section,
173                                const DWARFUnitIndex::Entry &Entry,
174                                DWARFSectionKind Kind) {
175   const auto *Off = Entry.getContribution(Kind);
176   if (!Off)
177     return StringRef();
178   return Section.substr(Off->Offset, Off->Length);
179 }
180 
181 static void
182 addAllTypesFromDWP(MCStreamer &Out,
183                    MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
184                    const DWARFUnitIndex &TUIndex, MCSection *OutputTypes,
185                    StringRef Types, const UnitIndexEntry &TUEntry,
186                    uint32_t &TypesOffset, unsigned TypesContributionIndex) {
187   Out.switchSection(OutputTypes);
188   for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) {
189     auto *I = E.getContributions();
190     if (!I)
191       continue;
192     auto P = TypeIndexEntries.insert(std::make_pair(E.getSignature(), TUEntry));
193     if (!P.second)
194       continue;
195     auto &Entry = P.first->second;
196     // Zero out the debug_info contribution
197     Entry.Contributions[0] = {};
198     for (auto Kind : TUIndex.getColumnKinds()) {
199       if (!isSupportedSectionKind(Kind))
200         continue;
201       auto &C =
202           Entry.Contributions[getContributionIndex(Kind, TUIndex.getVersion())];
203       C.Offset += I->Offset;
204       C.Length = I->Length;
205       ++I;
206     }
207     auto &C = Entry.Contributions[TypesContributionIndex];
208     Out.emitBytes(Types.substr(
209         C.Offset - TUEntry.Contributions[TypesContributionIndex].Offset,
210         C.Length));
211     C.Offset = TypesOffset;
212     TypesOffset += C.Length;
213   }
214 }
215 
216 static void addAllTypesFromTypesSection(
217     MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
218     MCSection *OutputTypes, const std::vector<StringRef> &TypesSections,
219     const UnitIndexEntry &CUEntry, uint32_t &TypesOffset) {
220   for (StringRef Types : TypesSections) {
221     Out.switchSection(OutputTypes);
222     uint64_t Offset = 0;
223     DataExtractor Data(Types, true, 0);
224     while (Data.isValidOffset(Offset)) {
225       UnitIndexEntry Entry = CUEntry;
226       // Zero out the debug_info contribution
227       Entry.Contributions[0] = {};
228       auto &C = Entry.Contributions[getContributionIndex(DW_SECT_EXT_TYPES, 2)];
229       C.Offset = TypesOffset;
230       auto PrevOffset = Offset;
231       // Length of the unit, including the 4 byte length field.
232       C.Length = Data.getU32(&Offset) + 4;
233 
234       Data.getU16(&Offset); // Version
235       Data.getU32(&Offset); // Abbrev offset
236       Data.getU8(&Offset);  // Address size
237       auto Signature = Data.getU64(&Offset);
238       Offset = PrevOffset + C.Length;
239 
240       auto P = TypeIndexEntries.insert(std::make_pair(Signature, Entry));
241       if (!P.second)
242         continue;
243 
244       Out.emitBytes(Types.substr(PrevOffset, C.Length));
245       TypesOffset += C.Length;
246     }
247   }
248 }
249 
250 static std::string buildDWODescription(StringRef Name, StringRef DWPName,
251                                        StringRef DWOName) {
252   std::string Text = "\'";
253   Text += Name;
254   Text += '\'';
255   if (!DWPName.empty()) {
256     Text += " (from ";
257     if (!DWOName.empty()) {
258       Text += '\'';
259       Text += DWOName;
260       Text += "' in ";
261     }
262     Text += '\'';
263     Text += DWPName;
264     Text += "')";
265   }
266   return Text;
267 }
268 
269 static Error createError(StringRef Name, Error E) {
270   return make_error<DWPError>(
271       ("failure while decompressing compressed section: '" + Name + "', " +
272        llvm::toString(std::move(E)))
273           .str());
274 }
275 
276 static Error
277 handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections,
278                         SectionRef Sec, StringRef Name, StringRef &Contents) {
279   auto *Obj = dyn_cast<ELFObjectFileBase>(Sec.getObject());
280   if (!Obj ||
281       !(static_cast<ELFSectionRef>(Sec).getFlags() & ELF::SHF_COMPRESSED))
282     return Error::success();
283   bool IsLE = isa<object::ELF32LEObjectFile>(Obj) ||
284               isa<object::ELF64LEObjectFile>(Obj);
285   bool Is64 = isa<object::ELF64LEObjectFile>(Obj) ||
286               isa<object::ELF64BEObjectFile>(Obj);
287   Expected<Decompressor> Dec = Decompressor::create(Name, Contents, IsLE, Is64);
288   if (!Dec)
289     return createError(Name, Dec.takeError());
290 
291   UncompressedSections.emplace_back();
292   if (Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
293     return createError(Name, std::move(E));
294 
295   Contents = UncompressedSections.back();
296   return Error::success();
297 }
298 
299 namespace llvm {
300 // Parse and return the header of an info section compile/type unit.
301 Expected<InfoSectionUnitHeader> parseInfoSectionUnitHeader(StringRef Info) {
302   InfoSectionUnitHeader Header;
303   Error Err = Error::success();
304   uint64_t Offset = 0;
305   DWARFDataExtractor InfoData(Info, true, 0);
306   std::tie(Header.Length, Header.Format) =
307       InfoData.getInitialLength(&Offset, &Err);
308   if (Err)
309     return make_error<DWPError>("cannot parse compile unit length: " +
310                                 llvm::toString(std::move(Err)));
311 
312   if (!InfoData.isValidOffset(Offset + (Header.Length - 1))) {
313     return make_error<DWPError>(
314         "compile unit exceeds .debug_info section range: " +
315         utostr(Offset + Header.Length) + " >= " + utostr(InfoData.size()));
316   }
317 
318   Header.Version = InfoData.getU16(&Offset, &Err);
319   if (Err)
320     return make_error<DWPError>("cannot parse compile unit version: " +
321                                 llvm::toString(std::move(Err)));
322 
323   uint64_t MinHeaderLength;
324   if (Header.Version >= 5) {
325     // Size: Version (2), UnitType (1), AddrSize (1), DebugAbbrevOffset (4),
326     // Signature (8)
327     MinHeaderLength = 16;
328   } else {
329     // Size: Version (2), DebugAbbrevOffset (4), AddrSize (1)
330     MinHeaderLength = 7;
331   }
332   if (Header.Length < MinHeaderLength) {
333     return make_error<DWPError>("unit length is too small: expected at least " +
334                                 utostr(MinHeaderLength) + " got " +
335                                 utostr(Header.Length) + ".");
336   }
337   if (Header.Version >= 5) {
338     Header.UnitType = InfoData.getU8(&Offset);
339     Header.AddrSize = InfoData.getU8(&Offset);
340     Header.DebugAbbrevOffset = InfoData.getU32(&Offset);
341     Header.Signature = InfoData.getU64(&Offset);
342     if (Header.UnitType == dwarf::DW_UT_split_type) {
343       // Type offset.
344       MinHeaderLength += 4;
345       if (Header.Length < MinHeaderLength)
346         return make_error<DWPError>("type unit is missing type offset");
347       InfoData.getU32(&Offset);
348     }
349   } else {
350     // Note that, address_size and debug_abbrev_offset fields have switched
351     // places between dwarf version 4 and 5.
352     Header.DebugAbbrevOffset = InfoData.getU32(&Offset);
353     Header.AddrSize = InfoData.getU8(&Offset);
354   }
355 
356   Header.HeaderSize = Offset;
357   return Header;
358 }
359 
360 void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,
361                             MCSection *StrOffsetSection,
362                             StringRef CurStrSection,
363                             StringRef CurStrOffsetSection, uint16_t Version) {
364   // Could possibly produce an error or warning if one of these was non-null but
365   // the other was null.
366   if (CurStrSection.empty() || CurStrOffsetSection.empty())
367     return;
368 
369   DenseMap<uint64_t, uint32_t> OffsetRemapping;
370 
371   DataExtractor Data(CurStrSection, true, 0);
372   uint64_t LocalOffset = 0;
373   uint64_t PrevOffset = 0;
374   while (const char *S = Data.getCStr(&LocalOffset)) {
375     OffsetRemapping[PrevOffset] =
376         Strings.getOffset(S, LocalOffset - PrevOffset);
377     PrevOffset = LocalOffset;
378   }
379 
380   Data = DataExtractor(CurStrOffsetSection, true, 0);
381 
382   Out.switchSection(StrOffsetSection);
383 
384   uint64_t HeaderSize = debugStrOffsetsHeaderSize(Data, Version);
385   uint64_t Offset = 0;
386   uint64_t Size = CurStrOffsetSection.size();
387   // FIXME: This can be caused by bad input and should be handled as such.
388   assert(HeaderSize <= Size && "StrOffsetSection size is less than its header");
389   // Copy the header to the output.
390   Out.emitBytes(Data.getBytes(&Offset, HeaderSize));
391   while (Offset < Size) {
392     auto OldOffset = Data.getU32(&Offset);
393     auto NewOffset = OffsetRemapping[OldOffset];
394     Out.emitIntValue(NewOffset, 4);
395   }
396 }
397 
398 void writeIndexTable(
399     MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
400     const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
401     uint32_t DWARFUnitIndex::Entry::SectionContribution::*Field) {
402   for (const auto &E : IndexEntries)
403     for (size_t I = 0; I != array_lengthof(E.second.Contributions); ++I)
404       if (ContributionOffsets[I])
405         Out.emitIntValue(E.second.Contributions[I].*Field, 4);
406 }
407 
408 void writeIndex(MCStreamer &Out, MCSection *Section,
409                 ArrayRef<unsigned> ContributionOffsets,
410                 const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
411                 uint32_t IndexVersion) {
412   if (IndexEntries.empty())
413     return;
414 
415   unsigned Columns = 0;
416   for (auto &C : ContributionOffsets)
417     if (C)
418       ++Columns;
419 
420   std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
421   uint64_t Mask = Buckets.size() - 1;
422   size_t I = 0;
423   for (const auto &P : IndexEntries) {
424     auto S = P.first;
425     auto H = S & Mask;
426     auto HP = ((S >> 32) & Mask) | 1;
427     while (Buckets[H]) {
428       assert(S != IndexEntries.begin()[Buckets[H] - 1].first &&
429              "Duplicate unit");
430       H = (H + HP) & Mask;
431     }
432     Buckets[H] = I + 1;
433     ++I;
434   }
435 
436   Out.switchSection(Section);
437   Out.emitIntValue(IndexVersion, 4);        // Version
438   Out.emitIntValue(Columns, 4);             // Columns
439   Out.emitIntValue(IndexEntries.size(), 4); // Num Units
440   Out.emitIntValue(Buckets.size(), 4);      // Num Buckets
441 
442   // Write the signatures.
443   for (const auto &I : Buckets)
444     Out.emitIntValue(I ? IndexEntries.begin()[I - 1].first : 0, 8);
445 
446   // Write the indexes.
447   for (const auto &I : Buckets)
448     Out.emitIntValue(I, 4);
449 
450   // Write the column headers (which sections will appear in the table)
451   for (size_t I = 0; I != ContributionOffsets.size(); ++I)
452     if (ContributionOffsets[I])
453       Out.emitIntValue(getOnDiskSectionId(I), 4);
454 
455   // Write the offsets.
456   writeIndexTable(Out, ContributionOffsets, IndexEntries,
457                   &DWARFUnitIndex::Entry::SectionContribution::Offset);
458 
459   // Write the lengths.
460   writeIndexTable(Out, ContributionOffsets, IndexEntries,
461                   &DWARFUnitIndex::Entry::SectionContribution::Length);
462 }
463 
464 Error buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
465                           const CompileUnitIdentifiers &ID, StringRef DWPName) {
466   return make_error<DWPError>(
467       std::string("duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " +
468       buildDWODescription(PrevE.second.Name, PrevE.second.DWPName,
469                           PrevE.second.DWOName) +
470       " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));
471 }
472 
473 Error handleSection(
474     const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
475     const MCSection *StrSection, const MCSection *StrOffsetSection,
476     const MCSection *TypesSection, const MCSection *CUIndexSection,
477     const MCSection *TUIndexSection, const MCSection *InfoSection,
478     const SectionRef &Section, MCStreamer &Out,
479     std::deque<SmallString<32>> &UncompressedSections,
480     uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry,
481     StringRef &CurStrSection, StringRef &CurStrOffsetSection,
482     std::vector<StringRef> &CurTypesSection,
483     std::vector<StringRef> &CurInfoSection, StringRef &AbbrevSection,
484     StringRef &CurCUIndexSection, StringRef &CurTUIndexSection,
485     std::vector<std::pair<DWARFSectionKind, uint32_t>> &SectionLength) {
486   if (Section.isBSS())
487     return Error::success();
488 
489   if (Section.isVirtual())
490     return Error::success();
491 
492   Expected<StringRef> NameOrErr = Section.getName();
493   if (!NameOrErr)
494     return NameOrErr.takeError();
495   StringRef Name = *NameOrErr;
496 
497   Expected<StringRef> ContentsOrErr = Section.getContents();
498   if (!ContentsOrErr)
499     return ContentsOrErr.takeError();
500   StringRef Contents = *ContentsOrErr;
501 
502   if (auto Err = handleCompressedSection(UncompressedSections, Section, Name,
503                                          Contents))
504     return Err;
505 
506   Name = Name.substr(Name.find_first_not_of("._"));
507 
508   auto SectionPair = KnownSections.find(Name);
509   if (SectionPair == KnownSections.end())
510     return Error::success();
511 
512   if (DWARFSectionKind Kind = SectionPair->second.second) {
513     if (Kind != DW_SECT_EXT_TYPES && Kind != DW_SECT_INFO) {
514       SectionLength.push_back(std::make_pair(Kind, Contents.size()));
515     }
516 
517     if (Kind == DW_SECT_ABBREV) {
518       AbbrevSection = Contents;
519     }
520   }
521 
522   MCSection *OutSection = SectionPair->second.first;
523   if (OutSection == StrOffsetSection)
524     CurStrOffsetSection = Contents;
525   else if (OutSection == StrSection)
526     CurStrSection = Contents;
527   else if (OutSection == TypesSection)
528     CurTypesSection.push_back(Contents);
529   else if (OutSection == CUIndexSection)
530     CurCUIndexSection = Contents;
531   else if (OutSection == TUIndexSection)
532     CurTUIndexSection = Contents;
533   else if (OutSection == InfoSection)
534     CurInfoSection.push_back(Contents);
535   else {
536     Out.switchSection(OutSection);
537     Out.emitBytes(Contents);
538   }
539   return Error::success();
540 }
541 
542 Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
543   const auto &MCOFI = *Out.getContext().getObjectFileInfo();
544   MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
545   MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
546   MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection();
547   MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection();
548   MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection();
549   MCSection *const InfoSection = MCOFI.getDwarfInfoDWOSection();
550   const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = {
551       {"debug_info.dwo", {InfoSection, DW_SECT_INFO}},
552       {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},
553       {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
554       {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}},
555       {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},
556       {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
557       {"debug_macro.dwo", {MCOFI.getDwarfMacroDWOSection(), DW_SECT_MACRO}},
558       {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
559       {"debug_loclists.dwo",
560        {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},
561       {"debug_rnglists.dwo",
562        {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}},
563       {"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}},
564       {"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};
565 
566   MapVector<uint64_t, UnitIndexEntry> IndexEntries;
567   MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
568 
569   uint32_t ContributionOffsets[8] = {};
570   uint16_t Version = 0;
571   uint32_t IndexVersion = 0;
572 
573   DWPStringPool Strings(Out, StrSection);
574 
575   SmallVector<OwningBinary<object::ObjectFile>, 128> Objects;
576   Objects.reserve(Inputs.size());
577 
578   std::deque<SmallString<32>> UncompressedSections;
579 
580   for (const auto &Input : Inputs) {
581     auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
582     if (!ErrOrObj)
583       return ErrOrObj.takeError();
584 
585     auto &Obj = *ErrOrObj->getBinary();
586     Objects.push_back(std::move(*ErrOrObj));
587 
588     UnitIndexEntry CurEntry = {};
589 
590     StringRef CurStrSection;
591     StringRef CurStrOffsetSection;
592     std::vector<StringRef> CurTypesSection;
593     std::vector<StringRef> CurInfoSection;
594     StringRef AbbrevSection;
595     StringRef CurCUIndexSection;
596     StringRef CurTUIndexSection;
597 
598     // This maps each section contained in this file to its length.
599     // This information is later on used to calculate the contributions,
600     // i.e. offset and length, of each compile/type unit to a section.
601     std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength;
602 
603     for (const auto &Section : Obj.sections())
604       if (auto Err = handleSection(
605               KnownSections, StrSection, StrOffsetSection, TypesSection,
606               CUIndexSection, TUIndexSection, InfoSection, Section, Out,
607               UncompressedSections, ContributionOffsets, CurEntry,
608               CurStrSection, CurStrOffsetSection, CurTypesSection,
609               CurInfoSection, AbbrevSection, CurCUIndexSection,
610               CurTUIndexSection, SectionLength))
611         return Err;
612 
613     if (CurInfoSection.empty())
614       continue;
615 
616     Expected<InfoSectionUnitHeader> HeaderOrErr =
617         parseInfoSectionUnitHeader(CurInfoSection.front());
618     if (!HeaderOrErr)
619       return HeaderOrErr.takeError();
620     InfoSectionUnitHeader &Header = *HeaderOrErr;
621 
622     if (Version == 0) {
623       Version = Header.Version;
624       IndexVersion = Version < 5 ? 2 : 5;
625     } else if (Version != Header.Version) {
626       return make_error<DWPError>("incompatible DWARF compile unit versions.");
627     }
628 
629     writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection,
630                            CurStrOffsetSection, Header.Version);
631 
632     for (auto Pair : SectionLength) {
633       auto Index = getContributionIndex(Pair.first, IndexVersion);
634       CurEntry.Contributions[Index].Offset = ContributionOffsets[Index];
635       ContributionOffsets[Index] +=
636           (CurEntry.Contributions[Index].Length = Pair.second);
637     }
638 
639     uint32_t &InfoSectionOffset =
640         ContributionOffsets[getContributionIndex(DW_SECT_INFO, IndexVersion)];
641     if (CurCUIndexSection.empty()) {
642       bool FoundCUUnit = false;
643       Out.switchSection(InfoSection);
644       for (StringRef Info : CurInfoSection) {
645         uint64_t UnitOffset = 0;
646         while (Info.size() > UnitOffset) {
647           Expected<InfoSectionUnitHeader> HeaderOrError =
648               parseInfoSectionUnitHeader(Info.substr(UnitOffset, Info.size()));
649           if (!HeaderOrError)
650             return HeaderOrError.takeError();
651           InfoSectionUnitHeader &Header = *HeaderOrError;
652 
653           UnitIndexEntry Entry = CurEntry;
654           auto &C = Entry.Contributions[getContributionIndex(DW_SECT_INFO,
655                                                              IndexVersion)];
656           C.Offset = InfoSectionOffset;
657           C.Length = Header.Length + 4;
658 
659           if (std::numeric_limits<uint32_t>::max() - InfoSectionOffset <
660               C.Length)
661             return make_error<DWPError>(
662                 "debug information section offset is greater than 4GB");
663 
664           UnitOffset += C.Length;
665           if (Header.Version < 5 ||
666               Header.UnitType == dwarf::DW_UT_split_compile) {
667             Expected<CompileUnitIdentifiers> EID =
668                 getCUIdentifiers(Header, AbbrevSection,
669                                  Info.substr(UnitOffset - C.Length, C.Length),
670                                  CurStrOffsetSection, CurStrSection);
671 
672             if (!EID)
673               return createFileError(Input, EID.takeError());
674             const auto &ID = *EID;
675             auto P = IndexEntries.insert(std::make_pair(ID.Signature, Entry));
676             if (!P.second)
677               return buildDuplicateError(*P.first, ID, "");
678             P.first->second.Name = ID.Name;
679             P.first->second.DWOName = ID.DWOName;
680 
681             FoundCUUnit = true;
682           } else if (Header.UnitType == dwarf::DW_UT_split_type) {
683             auto P = TypeIndexEntries.insert(
684                 std::make_pair(*Header.Signature, Entry));
685             if (!P.second)
686               continue;
687           }
688           Out.emitBytes(Info.substr(UnitOffset - C.Length, C.Length));
689           InfoSectionOffset += C.Length;
690         }
691       }
692 
693       if (!FoundCUUnit)
694         return make_error<DWPError>("no compile unit found in file: " + Input);
695 
696       if (IndexVersion == 2) {
697         // Add types from the .debug_types section from DWARF < 5.
698         addAllTypesFromTypesSection(
699             Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry,
700             ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)]);
701       }
702       continue;
703     }
704 
705     if (CurInfoSection.size() != 1)
706       return make_error<DWPError>("expected exactly one occurrence of a debug "
707                                   "info section in a .dwp file");
708     StringRef DwpSingleInfoSection = CurInfoSection.front();
709 
710     DWARFUnitIndex CUIndex(DW_SECT_INFO);
711     DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
712     if (!CUIndex.parse(CUIndexData))
713       return make_error<DWPError>("failed to parse cu_index");
714     if (CUIndex.getVersion() != IndexVersion)
715       return make_error<DWPError>("incompatible cu_index versions, found " +
716                                   utostr(CUIndex.getVersion()) +
717                                   " and expecting " + utostr(IndexVersion));
718 
719     Out.switchSection(InfoSection);
720     for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
721       auto *I = E.getContributions();
722       if (!I)
723         continue;
724       auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry));
725       StringRef CUInfoSection =
726           getSubsection(DwpSingleInfoSection, E, DW_SECT_INFO);
727       Expected<InfoSectionUnitHeader> HeaderOrError =
728           parseInfoSectionUnitHeader(CUInfoSection);
729       if (!HeaderOrError)
730         return HeaderOrError.takeError();
731       InfoSectionUnitHeader &Header = *HeaderOrError;
732 
733       Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
734           Header, getSubsection(AbbrevSection, E, DW_SECT_ABBREV),
735           CUInfoSection,
736           getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS),
737           CurStrSection);
738       if (!EID)
739         return createFileError(Input, EID.takeError());
740       const auto &ID = *EID;
741       if (!P.second)
742         return buildDuplicateError(*P.first, ID, Input);
743       auto &NewEntry = P.first->second;
744       NewEntry.Name = ID.Name;
745       NewEntry.DWOName = ID.DWOName;
746       NewEntry.DWPName = Input;
747       for (auto Kind : CUIndex.getColumnKinds()) {
748         if (!isSupportedSectionKind(Kind))
749           continue;
750         auto &C =
751             NewEntry.Contributions[getContributionIndex(Kind, IndexVersion)];
752         C.Offset += I->Offset;
753         C.Length = I->Length;
754         ++I;
755       }
756       unsigned Index = getContributionIndex(DW_SECT_INFO, IndexVersion);
757       auto &C = NewEntry.Contributions[Index];
758       Out.emitBytes(CUInfoSection);
759       C.Offset = InfoSectionOffset;
760       InfoSectionOffset += C.Length;
761     }
762 
763     if (!CurTUIndexSection.empty()) {
764       llvm::DWARFSectionKind TUSectionKind;
765       MCSection *OutSection;
766       StringRef TypeInputSection;
767       // Write type units into debug info section for DWARFv5.
768       if (Version >= 5) {
769         TUSectionKind = DW_SECT_INFO;
770         OutSection = InfoSection;
771         TypeInputSection = DwpSingleInfoSection;
772       } else {
773         // Write type units into debug types section for DWARF < 5.
774         if (CurTypesSection.size() != 1)
775           return make_error<DWPError>(
776               "multiple type unit sections in .dwp file");
777 
778         TUSectionKind = DW_SECT_EXT_TYPES;
779         OutSection = TypesSection;
780         TypeInputSection = CurTypesSection.front();
781       }
782 
783       DWARFUnitIndex TUIndex(TUSectionKind);
784       DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);
785       if (!TUIndex.parse(TUIndexData))
786         return make_error<DWPError>("failed to parse tu_index");
787       if (TUIndex.getVersion() != IndexVersion)
788         return make_error<DWPError>("incompatible tu_index versions, found " +
789                                     utostr(TUIndex.getVersion()) +
790                                     " and expecting " + utostr(IndexVersion));
791 
792       unsigned TypesContributionIndex =
793           getContributionIndex(TUSectionKind, IndexVersion);
794       addAllTypesFromDWP(Out, TypeIndexEntries, TUIndex, OutSection,
795                          TypeInputSection, CurEntry,
796                          ContributionOffsets[TypesContributionIndex],
797                          TypesContributionIndex);
798     }
799   }
800 
801   if (Version < 5) {
802     // Lie about there being no info contributions so the TU index only includes
803     // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a
804     // contribution to the info section, so we do not want to lie about it.
805     ContributionOffsets[0] = 0;
806   }
807   writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
808              TypeIndexEntries, IndexVersion);
809 
810   if (Version < 5) {
811     // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
812     // section does not exist, so no need to do anything about this.
813     ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0;
814     // Unlie about the info contribution
815     ContributionOffsets[0] = 1;
816   }
817 
818   writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
819              IndexEntries, IndexVersion);
820 
821   return Error::success();
822 }
823 } // namespace llvm
824