xref: /freebsd/contrib/llvm-project/llvm/lib/DWP/DWP.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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/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"
23 #include <limits>
24 
25 using namespace llvm;
26 using namespace llvm::object;
27 
28 static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags;
29 
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.
35   uint64_t Offset = 0;
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.
40 }
41 
42 static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) {
43   uint64_t Offset = 0;
44   DataExtractor AbbrevData(Abbrev, true, 0);
45   while (AbbrevData.getULEB128(&Offset) != AbbrCode) {
46     // Tag
47     AbbrevData.getULEB128(&Offset);
48     // DW_CHILDREN
49     AbbrevData.getU8(&Offset);
50     // Attributes
51     while (AbbrevData.getULEB128(&Offset) | AbbrevData.getULEB128(&Offset))
52       ;
53   }
54   return Offset;
55 }
56 
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);
62   uint64_t StrIndex;
63   switch (Form) {
64   case dwarf::DW_FORM_strx1:
65     StrIndex = InfoData.getU8(&InfoOffset);
66     break;
67   case dwarf::DW_FORM_strx2:
68     StrIndex = InfoData.getU16(&InfoOffset);
69     break;
70   case dwarf::DW_FORM_strx3:
71     StrIndex = InfoData.getU24(&InfoOffset);
72     break;
73   case dwarf::DW_FORM_strx4:
74     StrIndex = InfoData.getU32(&InfoOffset);
75     break;
76   case dwarf::DW_FORM_strx:
77   case dwarf::DW_FORM_GNU_str_index:
78     StrIndex = InfoData.getULEB128(&InfoOffset);
79     break;
80   default:
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.");
85   }
86   DataExtractor StrOffsetsData(StrOffsets, true, 0);
87   uint64_t StrOffsetsOffset = 4 * StrIndex;
88   StrOffsetsOffset += debugStrOffsetsHeaderSize(StrOffsetsData, Version);
89 
90   uint64_t StrOffset = StrOffsetsData.getU32(&StrOffsetsOffset);
91   DataExtractor StrData(Str, true, 0);
92   return StrData.getCStr(&StrOffset);
93 }
94 
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"));
105 
106   CompileUnitIdentifiers ID;
107 
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");
114   // DW_CHILDREN
115   AbbrevData.getU8(&AbbrevOffset);
116   uint32_t Name;
117   dwarf::Form Form;
118   while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) |
119              (Form = static_cast<dwarf::Form>(
120                   AbbrevData.getULEB128(&AbbrevOffset))) &&
121          (Name != 0 || Form != 0)) {
122     switch (Name) {
123     case dwarf::DW_AT_name: {
124       Expected<const char *> EName = getIndexedString(
125           Form, InfoData, Offset, StrOffsets, Str, Header.Version);
126       if (!EName)
127         return EName.takeError();
128       ID.Name = *EName;
129       break;
130     }
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);
135       if (!EName)
136         return EName.takeError();
137       ID.DWOName = *EName;
138       break;
139     }
140     case dwarf::DW_AT_GNU_dwo_id:
141       Header.Signature = InfoData.getU64(&Offset);
142       break;
143     default:
144       DWARFFormValue::skipValue(
145           Form, InfoData, &Offset,
146           dwarf::FormParams({Header.Version, Header.AddrSize, Header.Format}));
147     }
148   }
149   if (!Header.Signature)
150     return make_error<DWPError>("compile unit missing dwo_id");
151   ID.Signature = *Header.Signature;
152   return ID;
153 }
154 
155 static bool isSupportedSectionKind(DWARFSectionKind Kind) {
156   return Kind != DW_SECT_EXT_unknown;
157 }
158 
159 namespace llvm {
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;
165 }
166 } // namespace llvm
167 
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;
172 }
173 
174 static StringRef getSubsection(StringRef Section,
175                                const DWARFUnitIndex::Entry &Entry,
176                                DWARFSectionKind Kind) {
177   const auto *Off = Entry.getContribution(Kind);
178   if (!Off)
179     return StringRef();
180   return Section.substr(Off->getOffset(), Off->getLength());
181 }
182 
183 static Error sectionOverflowErrorOrWarning(uint32_t PrevOffset,
184                                            uint32_t OverflowedOffset,
185                                            StringRef SectionName,
186                                            bool ContinueOnCuIndexOverflow) {
187   std::string Msg =
188       (SectionName +
189        Twine(" Section Contribution Offset overflow 4G. Previous Offset ") +
190        Twine(PrevOffset) + Twine(", After overflow offset ") +
191        Twine(OverflowedOffset) + Twine("."))
192           .str();
193   if (ContinueOnCuIndexOverflow) {
194     WithColor::defaultWarningHandler(make_error<DWPError>(Msg));
195     return Error::success();
196   }
197   return make_error<DWPError>(Msg);
198 }
199 
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();
208     if (!I)
209       continue;
210     auto P = TypeIndexEntries.insert(std::make_pair(E.getSignature(), TUEntry));
211     if (!P.second)
212       continue;
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))
218         continue;
219       auto &C =
220           Entry.Contributions[getContributionIndex(Kind, TUIndex.getVersion())];
221       C.setOffset(C.getOffset() + I->getOffset());
222       C.setLength(I->getLength());
223       ++I;
224     }
225     auto &C = Entry.Contributions[TypesContributionIndex];
226     Out.emitBytes(Types.substr(
227         C.getOffset() -
228             TUEntry.Contributions[TypesContributionIndex].getOffset(),
229         C.getLength()));
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))
237         return Err;
238     }
239   }
240   return Error::success();
241 }
242 
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);
250     uint64_t Offset = 0;
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);
261 
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();
267 
268       auto P = TypeIndexEntries.insert(std::make_pair(Signature, Entry));
269       if (!P.second)
270         continue;
271 
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))
278           return Err;
279       }
280     }
281   }
282   return Error::success();
283 }
284 
285 static std::string buildDWODescription(StringRef Name, StringRef DWPName,
286                                        StringRef DWOName) {
287   std::string Text = "\'";
288   Text += Name;
289   Text += '\'';
290   bool HasDWO = !DWOName.empty();
291   bool HasDWP = !DWPName.empty();
292   if (HasDWO || HasDWP) {
293     Text += " (from ";
294     if (HasDWO) {
295       Text += '\'';
296       Text += DWOName;
297       Text += '\'';
298     }
299     if (HasDWO && HasDWP)
300       Text += " in ";
301     if (!DWPName.empty()) {
302       Text += '\'';
303       Text += DWPName;
304       Text += '\'';
305     }
306     Text += ")";
307   }
308   return Text;
309 }
310 
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)))
315           .str());
316 }
317 
318 static Error
319 handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections,
320                         SectionRef Sec, StringRef Name, StringRef &Contents) {
321   auto *Obj = dyn_cast<ELFObjectFileBase>(Sec.getObject());
322   if (!Obj ||
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);
330   if (!Dec)
331     return createError(Name, Dec.takeError());
332 
333   UncompressedSections.emplace_back();
334   if (Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
335     return createError(Name, std::move(E));
336 
337   Contents = UncompressedSections.back();
338   return Error::success();
339 }
340 
341 namespace llvm {
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();
346   uint64_t Offset = 0;
347   DWARFDataExtractor InfoData(Info, true, 0);
348   std::tie(Header.Length, Header.Format) =
349       InfoData.getInitialLength(&Offset, &Err);
350   if (Err)
351     return make_error<DWPError>("cannot parse compile unit length: " +
352                                 llvm::toString(std::move(Err)));
353 
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()));
358   }
359 
360   Header.Version = InfoData.getU16(&Offset, &Err);
361   if (Err)
362     return make_error<DWPError>("cannot parse compile unit version: " +
363                                 llvm::toString(std::move(Err)));
364 
365   uint64_t MinHeaderLength;
366   if (Header.Version >= 5) {
367     // Size: Version (2), UnitType (1), AddrSize (1), DebugAbbrevOffset (4),
368     // Signature (8)
369     MinHeaderLength = 16;
370   } else {
371     // Size: Version (2), DebugAbbrevOffset (4), AddrSize (1)
372     MinHeaderLength = 7;
373   }
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) + ".");
378   }
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) {
385       // Type offset.
386       MinHeaderLength += 4;
387       if (Header.Length < MinHeaderLength)
388         return make_error<DWPError>("type unit is missing type offset");
389       InfoData.getU32(&Offset);
390     }
391   } else {
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);
396   }
397 
398   Header.HeaderSize = Offset;
399   return Header;
400 }
401 
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())
409     return;
410 
411   DenseMap<uint64_t, uint32_t> OffsetRemapping;
412 
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;
420   }
421 
422   Data = DataExtractor(CurStrOffsetSection, true, 0);
423 
424   Out.switchSection(StrOffsetSection);
425 
426   uint64_t HeaderSize = debugStrOffsetsHeaderSize(Data, Version);
427   uint64_t Offset = 0;
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);
437   }
438 }
439 
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()),
450                          4);
451 }
452 
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())
458     return;
459 
460   unsigned Columns = 0;
461   for (auto &C : ContributionOffsets)
462     if (C)
463       ++Columns;
464 
465   std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
466   uint64_t Mask = Buckets.size() - 1;
467   size_t I = 0;
468   for (const auto &P : IndexEntries) {
469     auto S = P.first;
470     auto H = S & Mask;
471     auto HP = ((S >> 32) & Mask) | 1;
472     while (Buckets[H]) {
473       assert(S != IndexEntries.begin()[Buckets[H] - 1].first &&
474              "Duplicate unit");
475       H = (H + HP) & Mask;
476     }
477     Buckets[H] = I + 1;
478     ++I;
479   }
480 
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
486 
487   // Write the signatures.
488   for (const auto &I : Buckets)
489     Out.emitIntValue(I ? IndexEntries.begin()[I - 1].first : 0, 8);
490 
491   // Write the indexes.
492   for (const auto &I : Buckets)
493     Out.emitIntValue(I, 4);
494 
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);
499 
500   // Write the offsets.
501   writeIndexTable(Out, ContributionOffsets, IndexEntries, AccessField::Offset);
502 
503   // Write the lengths.
504   writeIndexTable(Out, ContributionOffsets, IndexEntries, AccessField::Length);
505 }
506 
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));
514 }
515 
516 Error handleSection(
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) {
529   if (Section.isBSS())
530     return Error::success();
531 
532   if (Section.isVirtual())
533     return Error::success();
534 
535   Expected<StringRef> NameOrErr = Section.getName();
536   if (!NameOrErr)
537     return NameOrErr.takeError();
538   StringRef Name = *NameOrErr;
539 
540   Expected<StringRef> ContentsOrErr = Section.getContents();
541   if (!ContentsOrErr)
542     return ContentsOrErr.takeError();
543   StringRef Contents = *ContentsOrErr;
544 
545   if (auto Err = handleCompressedSection(UncompressedSections, Section, Name,
546                                          Contents))
547     return Err;
548 
549   Name = Name.substr(Name.find_first_not_of("._"));
550 
551   auto SectionPair = KnownSections.find(Name);
552   if (SectionPair == KnownSections.end())
553     return Error::success();
554 
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()));
558     }
559 
560     if (Kind == DW_SECT_ABBREV) {
561       AbbrevSection = Contents;
562     }
563   }
564 
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);
578   else {
579     Out.switchSection(OutSection);
580     Out.emitBytes(Contents);
581   }
582   return Error::success();
583 }
584 
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)}}};
609 
610   MapVector<uint64_t, UnitIndexEntry> IndexEntries;
611   MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
612 
613   uint32_t ContributionOffsets[8] = {};
614   uint16_t Version = 0;
615   uint32_t IndexVersion = 0;
616 
617   DWPStringPool Strings(Out, StrSection);
618 
619   SmallVector<OwningBinary<object::ObjectFile>, 128> Objects;
620   Objects.reserve(Inputs.size());
621 
622   std::deque<SmallString<32>> UncompressedSections;
623 
624   for (const auto &Input : Inputs) {
625     auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
626     if (!ErrOrObj) {
627       return handleErrors(ErrOrObj.takeError(),
628                           [&](std::unique_ptr<ECError> EC) -> Error {
629                             return createFileError(Input, Error(std::move(EC)));
630                           });
631     }
632 
633     auto &Obj = *ErrOrObj->getBinary();
634     Objects.push_back(std::move(*ErrOrObj));
635 
636     UnitIndexEntry CurEntry = {};
637 
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;
645 
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;
650 
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))
659         return Err;
660 
661     if (CurInfoSection.empty())
662       continue;
663 
664     Expected<InfoSectionUnitHeader> HeaderOrErr =
665         parseInfoSectionUnitHeader(CurInfoSection.front());
666     if (!HeaderOrErr)
667       return HeaderOrErr.takeError();
668     InfoSectionUnitHeader &Header = *HeaderOrErr;
669 
670     if (Version == 0) {
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.");
675     }
676 
677     writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection,
678                            CurStrOffsetSection, Header.Version);
679 
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);
693           }
694           ++SectionIndex;
695         }
696       }
697     }
698 
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()));
709           if (!HeaderOrError)
710             return HeaderOrError.takeError();
711           InfoSectionUnitHeader &Header = *HeaderOrError;
712 
713           UnitIndexEntry Entry = CurEntry;
714           auto &C = Entry.Contributions[getContributionIndex(DW_SECT_INFO,
715                                                              IndexVersion)];
716           C.setOffset(InfoSectionOffset);
717           C.setLength(Header.Length + 4);
718 
719           if (std::numeric_limits<uint32_t>::max() - InfoSectionOffset <
720               C.getLength32()) {
721             if (Error Err = sectionOverflowErrorOrWarning(
722                     InfoSectionOffset, InfoSectionOffset + C.getLength32(),
723                     "debug_info", ContinueOnCuIndexOverflow))
724               return Err;
725           }
726 
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);
734 
735             if (!EID)
736               return createFileError(Input, EID.takeError());
737             const auto &ID = *EID;
738             auto P = IndexEntries.insert(std::make_pair(ID.Signature, Entry));
739             if (!P.second)
740               return buildDuplicateError(*P.first, ID, "");
741             P.first->second.Name = ID.Name;
742             P.first->second.DWOName = ID.DWOName;
743 
744             FoundCUUnit = true;
745           } else if (Header.UnitType == dwarf::DW_UT_split_type) {
746             auto P = TypeIndexEntries.insert(
747                 std::make_pair(*Header.Signature, Entry));
748             if (!P.second)
749               continue;
750           }
751           Out.emitBytes(
752               Info.substr(UnitOffset - C.getLength32(), C.getLength32()));
753           InfoSectionOffset += C.getLength32();
754         }
755       }
756 
757       if (!FoundCUUnit)
758         return make_error<DWPError>("no compile unit found in file: " + Input);
759 
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))
766           return Err;
767       }
768       continue;
769     }
770 
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();
775 
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));
784 
785     Out.switchSection(InfoSection);
786     for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
787       auto *I = E.getContributions();
788       if (!I)
789         continue;
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);
795       if (!HeaderOrError)
796         return HeaderOrError.takeError();
797       InfoSectionUnitHeader &Header = *HeaderOrError;
798 
799       Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
800           Header, getSubsection(AbbrevSection, E, DW_SECT_ABBREV),
801           CUInfoSection,
802           getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS),
803           CurStrSection);
804       if (!EID)
805         return createFileError(Input, EID.takeError());
806       const auto &ID = *EID;
807       if (!P.second)
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))
815           continue;
816         auto &C =
817             NewEntry.Contributions[getContributionIndex(Kind, IndexVersion)];
818         C.setOffset(C.getOffset() + I->getOffset());
819         C.setLength(I->getLength());
820         ++I;
821       }
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();
827     }
828 
829     if (!CurTUIndexSection.empty()) {
830       llvm::DWARFSectionKind TUSectionKind;
831       MCSection *OutSection;
832       StringRef TypeInputSection;
833       // Write type units into debug info section for DWARFv5.
834       if (Version >= 5) {
835         TUSectionKind = DW_SECT_INFO;
836         OutSection = InfoSection;
837         TypeInputSection = DwpSingleInfoSection;
838       } else {
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");
843 
844         TUSectionKind = DW_SECT_EXT_TYPES;
845         OutSection = TypesSection;
846         TypeInputSection = CurTypesSection.front();
847       }
848 
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));
857 
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))
864         return Err;
865     }
866   }
867 
868   if (Version < 5) {
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;
873   }
874   writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
875              TypeIndexEntries, IndexVersion);
876 
877   if (Version < 5) {
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;
883   }
884 
885   writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
886              IndexEntries, IndexVersion);
887 
888   return Error::success();
889 }
890 } // namespace llvm
891