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 "DWPError.h"
14 #include "DWPStringPool.h"
15 #include "llvm/ADT/MapVector.h"
16 #include "llvm/ADT/Optional.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
19 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
20 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
21 #include "llvm/MC/MCAsmBackend.h"
22 #include "llvm/MC/MCAsmInfo.h"
23 #include "llvm/MC/MCCodeEmitter.h"
24 #include "llvm/MC/MCContext.h"
25 #include "llvm/MC/MCInstrInfo.h"
26 #include "llvm/MC/MCObjectFileInfo.h"
27 #include "llvm/MC/MCObjectWriter.h"
28 #include "llvm/MC/MCRegisterInfo.h"
29 #include "llvm/MC/MCStreamer.h"
30 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
31 #include "llvm/Object/Decompressor.h"
32 #include "llvm/Object/ObjectFile.h"
33 #include "llvm/Support/CommandLine.h"
34 #include "llvm/Support/DataExtractor.h"
35 #include "llvm/Support/Error.h"
36 #include "llvm/Support/FileSystem.h"
37 #include "llvm/Support/InitLLVM.h"
38 #include "llvm/Support/MathExtras.h"
39 #include "llvm/Support/MemoryBuffer.h"
40 #include "llvm/Support/Path.h"
41 #include "llvm/Support/TargetRegistry.h"
42 #include "llvm/Support/TargetSelect.h"
43 #include "llvm/Support/ToolOutputFile.h"
44 #include "llvm/Support/WithColor.h"
45 #include "llvm/Support/raw_ostream.h"
46 
47 using namespace llvm;
48 using namespace llvm::object;
49 
50 static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags;
51 
52 cl::OptionCategory DwpCategory("Specific Options");
53 static cl::list<std::string> InputFiles(cl::Positional, cl::ZeroOrMore,
54                                         cl::desc("<input files>"),
55                                         cl::cat(DwpCategory));
56 
57 static cl::list<std::string> ExecFilenames(
58     "e", cl::ZeroOrMore,
59     cl::desc("Specify the executable/library files to get the list of *.dwo from"),
60     cl::value_desc("filename"), cl::cat(DwpCategory));
61 
62 static cl::opt<std::string> OutputFilename(cl::Required, "o",
63                                            cl::desc("Specify the output file."),
64                                            cl::value_desc("filename"),
65                                            cl::cat(DwpCategory));
66 
67 static void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,
68                                    MCSection *StrOffsetSection,
69                                    StringRef CurStrSection,
70                                    StringRef CurStrOffsetSection) {
71   // Could possibly produce an error or warning if one of these was non-null but
72   // the other was null.
73   if (CurStrSection.empty() || CurStrOffsetSection.empty())
74     return;
75 
76   DenseMap<uint64_t, uint32_t> OffsetRemapping;
77 
78   DataExtractor Data(CurStrSection, true, 0);
79   uint64_t LocalOffset = 0;
80   uint64_t PrevOffset = 0;
81   while (const char *s = Data.getCStr(&LocalOffset)) {
82     OffsetRemapping[PrevOffset] =
83         Strings.getOffset(s, LocalOffset - PrevOffset);
84     PrevOffset = LocalOffset;
85   }
86 
87   Data = DataExtractor(CurStrOffsetSection, true, 0);
88 
89   Out.SwitchSection(StrOffsetSection);
90 
91   uint64_t Offset = 0;
92   uint64_t Size = CurStrOffsetSection.size();
93   while (Offset < Size) {
94     auto OldOffset = Data.getU32(&Offset);
95     auto NewOffset = OffsetRemapping[OldOffset];
96     Out.emitIntValue(NewOffset, 4);
97   }
98 }
99 
100 static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) {
101   uint64_t CurCode;
102   uint64_t Offset = 0;
103   DataExtractor AbbrevData(Abbrev, true, 0);
104   while ((CurCode = AbbrevData.getULEB128(&Offset)) != AbbrCode) {
105     // Tag
106     AbbrevData.getULEB128(&Offset);
107     // DW_CHILDREN
108     AbbrevData.getU8(&Offset);
109     // Attributes
110     while (AbbrevData.getULEB128(&Offset) | AbbrevData.getULEB128(&Offset))
111       ;
112   }
113   return Offset;
114 }
115 
116 struct CompileUnitIdentifiers {
117   uint64_t Signature = 0;
118   const char *Name = "";
119   const char *DWOName = "";
120 };
121 
122 static Expected<const char *>
123 getIndexedString(dwarf::Form Form, DataExtractor InfoData,
124                  uint64_t &InfoOffset, StringRef StrOffsets, StringRef Str) {
125   if (Form == dwarf::DW_FORM_string)
126     return InfoData.getCStr(&InfoOffset);
127   if (Form != dwarf::DW_FORM_GNU_str_index)
128     return make_error<DWPError>(
129         "string field encoded without DW_FORM_string or DW_FORM_GNU_str_index");
130   auto StrIndex = InfoData.getULEB128(&InfoOffset);
131   DataExtractor StrOffsetsData(StrOffsets, true, 0);
132   uint64_t StrOffsetsOffset = 4 * StrIndex;
133   uint64_t StrOffset = StrOffsetsData.getU32(&StrOffsetsOffset);
134   DataExtractor StrData(Str, true, 0);
135   return StrData.getCStr(&StrOffset);
136 }
137 
138 static Expected<CompileUnitIdentifiers> getCUIdentifiers(StringRef Abbrev,
139                                                          StringRef Info,
140                                                          StringRef StrOffsets,
141                                                          StringRef Str) {
142   uint64_t Offset = 0;
143   DataExtractor InfoData(Info, true, 0);
144   dwarf::DwarfFormat Format = dwarf::DwarfFormat::DWARF32;
145   uint64_t Length = InfoData.getU32(&Offset);
146   CompileUnitIdentifiers ID;
147   Optional<uint64_t> Signature = None;
148   // If the length is 0xffffffff, then this indictes that this is a DWARF 64
149   // stream and the length is actually encoded into a 64 bit value that follows.
150   if (Length == 0xffffffffU) {
151     Format = dwarf::DwarfFormat::DWARF64;
152     Length = InfoData.getU64(&Offset);
153   }
154   uint16_t Version = InfoData.getU16(&Offset);
155   if (Version >= 5) {
156     auto UnitType = InfoData.getU8(&Offset);
157     if (UnitType != dwarf::DW_UT_split_compile)
158       return make_error<DWPError>(
159           std::string("unit type DW_UT_split_compile type not found in "
160                       "debug_info header. Unexpected unit type 0x" +
161                       utostr(UnitType) + " found"));
162   }
163   InfoData.getU32(&Offset); // Abbrev offset (should be zero)
164   uint8_t AddrSize = InfoData.getU8(&Offset);
165   if (Version >= 5)
166     Signature = InfoData.getU64(&Offset);
167   uint32_t AbbrCode = InfoData.getULEB128(&Offset);
168 
169   DataExtractor AbbrevData(Abbrev, true, 0);
170   uint64_t AbbrevOffset = getCUAbbrev(Abbrev, AbbrCode);
171   auto Tag = static_cast<dwarf::Tag>(AbbrevData.getULEB128(&AbbrevOffset));
172   if (Tag != dwarf::DW_TAG_compile_unit)
173     return make_error<DWPError>("top level DIE is not a compile unit");
174   // DW_CHILDREN
175   AbbrevData.getU8(&AbbrevOffset);
176   uint32_t Name;
177   dwarf::Form Form;
178   while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) |
179          (Form = static_cast<dwarf::Form>(AbbrevData.getULEB128(&AbbrevOffset))) &&
180          (Name != 0 || Form != 0)) {
181     switch (Name) {
182     case dwarf::DW_AT_name: {
183       Expected<const char *> EName =
184           getIndexedString(Form, InfoData, Offset, StrOffsets, Str);
185       if (!EName)
186         return EName.takeError();
187       ID.Name = *EName;
188       break;
189     }
190     case dwarf::DW_AT_GNU_dwo_name:
191     case dwarf::DW_AT_dwo_name: {
192       Expected<const char *> EName =
193           getIndexedString(Form, InfoData, Offset, StrOffsets, Str);
194       if (!EName)
195         return EName.takeError();
196       ID.DWOName = *EName;
197       break;
198     }
199     case dwarf::DW_AT_GNU_dwo_id:
200       Signature = InfoData.getU64(&Offset);
201       break;
202     default:
203       DWARFFormValue::skipValue(Form, InfoData, &Offset,
204                                 dwarf::FormParams({Version, AddrSize, Format}));
205     }
206   }
207   if (!Signature)
208     return make_error<DWPError>("compile unit missing dwo_id");
209   ID.Signature = *Signature;
210   return ID;
211 }
212 
213 struct UnitIndexEntry {
214   DWARFUnitIndex::Entry::SectionContribution Contributions[8];
215   std::string Name;
216   std::string DWOName;
217   StringRef DWPName;
218 };
219 
220 static bool isSupportedSectionKind(DWARFSectionKind Kind) {
221   return Kind != DW_SECT_EXT_unknown;
222 }
223 
224 // Convert an internal section identifier into the index to use with
225 // UnitIndexEntry::Contributions.
226 static unsigned getContributionIndex(DWARFSectionKind Kind) {
227   // Assuming the pre-standard DWP format.
228   assert(serializeSectionKind(Kind, 2) >= DW_SECT_INFO);
229   return serializeSectionKind(Kind, 2) - DW_SECT_INFO;
230 }
231 
232 // Convert a UnitIndexEntry::Contributions index to the corresponding on-disk
233 // value of the section identifier.
234 static unsigned getOnDiskSectionId(unsigned Index) {
235   return Index + DW_SECT_INFO;
236 }
237 
238 static StringRef getSubsection(StringRef Section,
239                                const DWARFUnitIndex::Entry &Entry,
240                                DWARFSectionKind Kind) {
241   const auto *Off = Entry.getContribution(Kind);
242   if (!Off)
243     return StringRef();
244   return Section.substr(Off->Offset, Off->Length);
245 }
246 
247 static void addAllTypesFromDWP(
248     MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
249     const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types,
250     const UnitIndexEntry &TUEntry, uint32_t &TypesOffset) {
251   Out.SwitchSection(OutputTypes);
252   for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) {
253     auto *I = E.getContributions();
254     if (!I)
255       continue;
256     auto P = TypeIndexEntries.insert(std::make_pair(E.getSignature(), TUEntry));
257     if (!P.second)
258       continue;
259     auto &Entry = P.first->second;
260     // Zero out the debug_info contribution
261     Entry.Contributions[0] = {};
262     for (auto Kind : TUIndex.getColumnKinds()) {
263       if (!isSupportedSectionKind(Kind))
264         continue;
265       auto &C = Entry.Contributions[getContributionIndex(Kind)];
266       C.Offset += I->Offset;
267       C.Length = I->Length;
268       ++I;
269     }
270     unsigned TypesIndex = getContributionIndex(DW_SECT_EXT_TYPES);
271     auto &C = Entry.Contributions[TypesIndex];
272     Out.emitBytes(Types.substr(
273         C.Offset - TUEntry.Contributions[TypesIndex].Offset, C.Length));
274     C.Offset = TypesOffset;
275     TypesOffset += C.Length;
276   }
277 }
278 
279 static void addAllTypes(MCStreamer &Out,
280                         MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
281                         MCSection *OutputTypes,
282                         const std::vector<StringRef> &TypesSections,
283                         const UnitIndexEntry &CUEntry, uint32_t &TypesOffset) {
284   for (StringRef Types : TypesSections) {
285     Out.SwitchSection(OutputTypes);
286     uint64_t Offset = 0;
287     DataExtractor Data(Types, true, 0);
288     while (Data.isValidOffset(Offset)) {
289       UnitIndexEntry Entry = CUEntry;
290       // Zero out the debug_info contribution
291       Entry.Contributions[0] = {};
292       auto &C = Entry.Contributions[getContributionIndex(DW_SECT_EXT_TYPES)];
293       C.Offset = TypesOffset;
294       auto PrevOffset = Offset;
295       // Length of the unit, including the 4 byte length field.
296       C.Length = Data.getU32(&Offset) + 4;
297 
298       Data.getU16(&Offset); // Version
299       Data.getU32(&Offset); // Abbrev offset
300       Data.getU8(&Offset);  // Address size
301       auto Signature = Data.getU64(&Offset);
302       Offset = PrevOffset + C.Length;
303 
304       auto P = TypeIndexEntries.insert(std::make_pair(Signature, Entry));
305       if (!P.second)
306         continue;
307 
308       Out.emitBytes(Types.substr(PrevOffset, C.Length));
309       TypesOffset += C.Length;
310     }
311   }
312 }
313 
314 static void
315 writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
316                 const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
317                 uint32_t DWARFUnitIndex::Entry::SectionContribution::*Field) {
318   for (const auto &E : IndexEntries)
319     for (size_t i = 0; i != array_lengthof(E.second.Contributions); ++i)
320       if (ContributionOffsets[i])
321         Out.emitIntValue(E.second.Contributions[i].*Field, 4);
322 }
323 
324 static void
325 writeIndex(MCStreamer &Out, MCSection *Section,
326            ArrayRef<unsigned> ContributionOffsets,
327            const MapVector<uint64_t, UnitIndexEntry> &IndexEntries) {
328   if (IndexEntries.empty())
329     return;
330 
331   unsigned Columns = 0;
332   for (auto &C : ContributionOffsets)
333     if (C)
334       ++Columns;
335 
336   std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
337   uint64_t Mask = Buckets.size() - 1;
338   size_t i = 0;
339   for (const auto &P : IndexEntries) {
340     auto S = P.first;
341     auto H = S & Mask;
342     auto HP = ((S >> 32) & Mask) | 1;
343     while (Buckets[H]) {
344       assert(S != IndexEntries.begin()[Buckets[H] - 1].first &&
345              "Duplicate unit");
346       H = (H + HP) & Mask;
347     }
348     Buckets[H] = i + 1;
349     ++i;
350   }
351 
352   Out.SwitchSection(Section);
353   Out.emitIntValue(2, 4);                   // Version
354   Out.emitIntValue(Columns, 4);             // Columns
355   Out.emitIntValue(IndexEntries.size(), 4); // Num Units
356   Out.emitIntValue(Buckets.size(), 4);      // Num Buckets
357 
358   // Write the signatures.
359   for (const auto &I : Buckets)
360     Out.emitIntValue(I ? IndexEntries.begin()[I - 1].first : 0, 8);
361 
362   // Write the indexes.
363   for (const auto &I : Buckets)
364     Out.emitIntValue(I, 4);
365 
366   // Write the column headers (which sections will appear in the table)
367   for (size_t i = 0; i != ContributionOffsets.size(); ++i)
368     if (ContributionOffsets[i])
369       Out.emitIntValue(getOnDiskSectionId(i), 4);
370 
371   // Write the offsets.
372   writeIndexTable(Out, ContributionOffsets, IndexEntries,
373                   &DWARFUnitIndex::Entry::SectionContribution::Offset);
374 
375   // Write the lengths.
376   writeIndexTable(Out, ContributionOffsets, IndexEntries,
377                   &DWARFUnitIndex::Entry::SectionContribution::Length);
378 }
379 
380 std::string buildDWODescription(StringRef Name, StringRef DWPName, StringRef DWOName) {
381   std::string Text = "\'";
382   Text += Name;
383   Text += '\'';
384   if (!DWPName.empty()) {
385     Text += " (from ";
386     if (!DWOName.empty()) {
387       Text += '\'';
388       Text += DWOName;
389       Text += "' in ";
390     }
391     Text += '\'';
392     Text += DWPName;
393     Text += "')";
394   }
395   return Text;
396 }
397 
398 static Error createError(StringRef Name, Error E) {
399   return make_error<DWPError>(
400       ("failure while decompressing compressed section: '" + Name + "', " +
401        llvm::toString(std::move(E)))
402           .str());
403 }
404 
405 static Error
406 handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections,
407                         StringRef &Name, StringRef &Contents) {
408   if (!Decompressor::isGnuStyle(Name))
409     return Error::success();
410 
411   Expected<Decompressor> Dec =
412       Decompressor::create(Name, Contents, false /*IsLE*/, false /*Is64Bit*/);
413   if (!Dec)
414     return createError(Name, Dec.takeError());
415 
416   UncompressedSections.emplace_back();
417   if (Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
418     return createError(Name, std::move(E));
419 
420   Name = Name.substr(2); // Drop ".z"
421   Contents = UncompressedSections.back();
422   return Error::success();
423 }
424 
425 static Error handleSection(
426     const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
427     const MCSection *StrSection, const MCSection *StrOffsetSection,
428     const MCSection *TypesSection, const MCSection *CUIndexSection,
429     const MCSection *TUIndexSection, const SectionRef &Section, MCStreamer &Out,
430     std::deque<SmallString<32>> &UncompressedSections,
431     uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry,
432     StringRef &CurStrSection, StringRef &CurStrOffsetSection,
433     std::vector<StringRef> &CurTypesSection, StringRef &InfoSection,
434     StringRef &AbbrevSection, StringRef &CurCUIndexSection,
435     StringRef &CurTUIndexSection) {
436   if (Section.isBSS())
437     return Error::success();
438 
439   if (Section.isVirtual())
440     return Error::success();
441 
442   Expected<StringRef> NameOrErr = Section.getName();
443   if (!NameOrErr)
444     return NameOrErr.takeError();
445   StringRef Name = *NameOrErr;
446 
447   Expected<StringRef> ContentsOrErr = Section.getContents();
448   if (!ContentsOrErr)
449     return ContentsOrErr.takeError();
450   StringRef Contents = *ContentsOrErr;
451 
452   if (auto Err = handleCompressedSection(UncompressedSections, Name, Contents))
453     return Err;
454 
455   Name = Name.substr(Name.find_first_not_of("._"));
456 
457   auto SectionPair = KnownSections.find(Name);
458   if (SectionPair == KnownSections.end())
459     return Error::success();
460 
461   if (DWARFSectionKind Kind = SectionPair->second.second) {
462     auto Index = getContributionIndex(Kind);
463     if (Kind != DW_SECT_EXT_TYPES) {
464       CurEntry.Contributions[Index].Offset = ContributionOffsets[Index];
465       ContributionOffsets[Index] +=
466           (CurEntry.Contributions[Index].Length = Contents.size());
467     }
468 
469     switch (Kind) {
470     case DW_SECT_INFO:
471       InfoSection = Contents;
472       break;
473     case DW_SECT_ABBREV:
474       AbbrevSection = Contents;
475       break;
476     default:
477       break;
478     }
479   }
480 
481   MCSection *OutSection = SectionPair->second.first;
482   if (OutSection == StrOffsetSection)
483     CurStrOffsetSection = Contents;
484   else if (OutSection == StrSection)
485     CurStrSection = Contents;
486   else if (OutSection == TypesSection)
487     CurTypesSection.push_back(Contents);
488   else if (OutSection == CUIndexSection)
489     CurCUIndexSection = Contents;
490   else if (OutSection == TUIndexSection)
491     CurTUIndexSection = Contents;
492   else {
493     Out.SwitchSection(OutSection);
494     Out.emitBytes(Contents);
495   }
496   return Error::success();
497 }
498 
499 static Error
500 buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
501                     const CompileUnitIdentifiers &ID, StringRef DWPName) {
502   return make_error<DWPError>(
503       std::string("duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " +
504       buildDWODescription(PrevE.second.Name, PrevE.second.DWPName,
505                           PrevE.second.DWOName) +
506       " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));
507 }
508 
509 static Expected<SmallVector<std::string, 16>>
510 getDWOFilenames(StringRef ExecFilename) {
511   auto ErrOrObj = object::ObjectFile::createObjectFile(ExecFilename);
512   if (!ErrOrObj)
513     return ErrOrObj.takeError();
514 
515   const ObjectFile &Obj = *ErrOrObj.get().getBinary();
516   std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj);
517 
518   SmallVector<std::string, 16> DWOPaths;
519   for (const auto &CU : DWARFCtx->compile_units()) {
520     const DWARFDie &Die = CU->getUnitDIE();
521     std::string DWOName = dwarf::toString(
522         Die.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
523     if (DWOName.empty())
524       continue;
525     std::string DWOCompDir =
526         dwarf::toString(Die.find(dwarf::DW_AT_comp_dir), "");
527     if (!DWOCompDir.empty()) {
528       SmallString<16> DWOPath;
529       sys::path::append(DWOPath, DWOCompDir, DWOName);
530       DWOPaths.emplace_back(DWOPath.data(), DWOPath.size());
531     } else {
532       DWOPaths.push_back(std::move(DWOName));
533     }
534   }
535   return std::move(DWOPaths);
536 }
537 
538 static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
539   const auto &MCOFI = *Out.getContext().getObjectFileInfo();
540   MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
541   MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
542   MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection();
543   MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection();
544   MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection();
545   const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = {
546       {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}},
547       {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},
548       {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
549       {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}},
550       {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},
551       {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
552       {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
553       {"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}},
554       {"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};
555 
556   MapVector<uint64_t, UnitIndexEntry> IndexEntries;
557   MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
558 
559   uint32_t ContributionOffsets[8] = {};
560 
561   DWPStringPool Strings(Out, StrSection);
562 
563   SmallVector<OwningBinary<object::ObjectFile>, 128> Objects;
564   Objects.reserve(Inputs.size());
565 
566   std::deque<SmallString<32>> UncompressedSections;
567 
568   for (const auto &Input : Inputs) {
569     auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
570     if (!ErrOrObj)
571       return ErrOrObj.takeError();
572 
573     auto &Obj = *ErrOrObj->getBinary();
574     Objects.push_back(std::move(*ErrOrObj));
575 
576     UnitIndexEntry CurEntry = {};
577 
578     StringRef CurStrSection;
579     StringRef CurStrOffsetSection;
580     std::vector<StringRef> CurTypesSection;
581     StringRef InfoSection;
582     StringRef AbbrevSection;
583     StringRef CurCUIndexSection;
584     StringRef CurTUIndexSection;
585 
586     for (const auto &Section : Obj.sections())
587       if (auto Err = handleSection(
588               KnownSections, StrSection, StrOffsetSection, TypesSection,
589               CUIndexSection, TUIndexSection, Section, Out,
590               UncompressedSections, ContributionOffsets, CurEntry,
591               CurStrSection, CurStrOffsetSection, CurTypesSection, InfoSection,
592               AbbrevSection, CurCUIndexSection, CurTUIndexSection))
593         return Err;
594 
595     if (InfoSection.empty())
596       continue;
597 
598     writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection,
599                            CurStrOffsetSection);
600 
601     if (CurCUIndexSection.empty()) {
602       Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
603           AbbrevSection, InfoSection, CurStrOffsetSection, CurStrSection);
604       if (!EID)
605         return createFileError(Input, EID.takeError());
606       const auto &ID = *EID;
607       auto P = IndexEntries.insert(std::make_pair(ID.Signature, CurEntry));
608       if (!P.second)
609         return buildDuplicateError(*P.first, ID, "");
610       P.first->second.Name = ID.Name;
611       P.first->second.DWOName = ID.DWOName;
612       addAllTypes(Out, TypeIndexEntries, TypesSection, CurTypesSection,
613                   CurEntry,
614                   ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]);
615       continue;
616     }
617 
618     DWARFUnitIndex CUIndex(DW_SECT_INFO);
619     DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
620     if (!CUIndex.parse(CUIndexData))
621       return make_error<DWPError>("failed to parse cu_index");
622     if (CUIndex.getVersion() != 2)
623       return make_error<DWPError>(
624           "unsupported cu_index version: " + utostr(CUIndex.getVersion()) +
625           " (only version 2 is supported)");
626 
627     for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
628       auto *I = E.getContributions();
629       if (!I)
630         continue;
631       auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry));
632       Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
633           getSubsection(AbbrevSection, E, DW_SECT_ABBREV),
634           getSubsection(InfoSection, E, DW_SECT_INFO),
635           getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS),
636           CurStrSection);
637       if (!EID)
638         return createFileError(Input, EID.takeError());
639       const auto &ID = *EID;
640       if (!P.second)
641         return buildDuplicateError(*P.first, ID, Input);
642       auto &NewEntry = P.first->second;
643       NewEntry.Name = ID.Name;
644       NewEntry.DWOName = ID.DWOName;
645       NewEntry.DWPName = Input;
646       for (auto Kind : CUIndex.getColumnKinds()) {
647         if (!isSupportedSectionKind(Kind))
648           continue;
649         auto &C = NewEntry.Contributions[getContributionIndex(Kind)];
650         C.Offset += I->Offset;
651         C.Length = I->Length;
652         ++I;
653       }
654     }
655 
656     if (!CurTypesSection.empty()) {
657       if (CurTypesSection.size() != 1)
658         return make_error<DWPError>("multiple type unit sections in .dwp file");
659       DWARFUnitIndex TUIndex(DW_SECT_EXT_TYPES);
660       DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);
661       if (!TUIndex.parse(TUIndexData))
662         return make_error<DWPError>("failed to parse tu_index");
663       if (TUIndex.getVersion() != 2)
664         return make_error<DWPError>(
665             "unsupported tu_index version: " + utostr(TUIndex.getVersion()) +
666             " (only version 2 is supported)");
667 
668       addAllTypesFromDWP(
669           Out, TypeIndexEntries, TUIndex, TypesSection, CurTypesSection.front(),
670           CurEntry,
671           ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]);
672     }
673   }
674 
675   // Lie about there being no info contributions so the TU index only includes
676   // the type unit contribution
677   ContributionOffsets[0] = 0;
678   writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
679              TypeIndexEntries);
680 
681   // Lie about the type contribution
682   ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)] = 0;
683   // Unlie about the info contribution
684   ContributionOffsets[0] = 1;
685 
686   writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
687              IndexEntries);
688 
689   return Error::success();
690 }
691 
692 static int error(const Twine &Error, const Twine &Context) {
693   errs() << Twine("while processing ") + Context + ":\n";
694   errs() << Twine("error: ") + Error + "\n";
695   return 1;
696 }
697 
698 int main(int argc, char **argv) {
699   InitLLVM X(argc, argv);
700 
701   cl::ParseCommandLineOptions(argc, argv, "merge split dwarf (.dwo) files\n");
702 
703   llvm::InitializeAllTargetInfos();
704   llvm::InitializeAllTargetMCs();
705   llvm::InitializeAllTargets();
706   llvm::InitializeAllAsmPrinters();
707 
708   std::string ErrorStr;
709   StringRef Context = "dwarf streamer init";
710 
711   Triple TheTriple("x86_64-linux-gnu");
712 
713   // Get the target.
714   const Target *TheTarget =
715       TargetRegistry::lookupTarget("", TheTriple, ErrorStr);
716   if (!TheTarget)
717     return error(ErrorStr, Context);
718   std::string TripleName = TheTriple.getTriple();
719 
720   // Create all the MC Objects.
721   std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
722   if (!MRI)
723     return error(Twine("no register info for target ") + TripleName, Context);
724 
725   MCTargetOptions MCOptions = llvm::mc::InitMCTargetOptionsFromFlags();
726   std::unique_ptr<MCAsmInfo> MAI(
727       TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
728   if (!MAI)
729     return error("no asm info for target " + TripleName, Context);
730 
731   MCObjectFileInfo MOFI;
732   MCContext MC(MAI.get(), MRI.get(), &MOFI);
733   MOFI.InitMCObjectFileInfo(TheTriple, /*PIC*/ false, MC);
734 
735   std::unique_ptr<MCSubtargetInfo> MSTI(
736       TheTarget->createMCSubtargetInfo(TripleName, "", ""));
737   if (!MSTI)
738     return error("no subtarget info for target " + TripleName, Context);
739 
740   MCTargetOptions Options;
741   auto MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, Options);
742   if (!MAB)
743     return error("no asm backend for target " + TripleName, Context);
744 
745   std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
746   if (!MII)
747     return error("no instr info info for target " + TripleName, Context);
748 
749   MCCodeEmitter *MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, MC);
750   if (!MCE)
751     return error("no code emitter for target " + TripleName, Context);
752 
753   // Create the output file.
754   std::error_code EC;
755   ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_None);
756   Optional<buffer_ostream> BOS;
757   raw_pwrite_stream *OS;
758   if (EC)
759     return error(Twine(OutputFilename) + ": " + EC.message(), Context);
760   if (OutFile.os().supportsSeeking()) {
761     OS = &OutFile.os();
762   } else {
763     BOS.emplace(OutFile.os());
764     OS = BOS.getPointer();
765   }
766 
767   std::unique_ptr<MCStreamer> MS(TheTarget->createMCObjectStreamer(
768       TheTriple, MC, std::unique_ptr<MCAsmBackend>(MAB),
769       MAB->createObjectWriter(*OS), std::unique_ptr<MCCodeEmitter>(MCE), *MSTI,
770       MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
771       /*DWARFMustBeAtTheEnd*/ false));
772   if (!MS)
773     return error("no object streamer for target " + TripleName, Context);
774 
775   std::vector<std::string> DWOFilenames = InputFiles;
776   for (const auto &ExecFilename : ExecFilenames) {
777     auto DWOs = getDWOFilenames(ExecFilename);
778     if (!DWOs) {
779       logAllUnhandledErrors(DWOs.takeError(), WithColor::error());
780       return 1;
781     }
782     DWOFilenames.insert(DWOFilenames.end(),
783                         std::make_move_iterator(DWOs->begin()),
784                         std::make_move_iterator(DWOs->end()));
785   }
786 
787   if (auto Err = write(*MS, DWOFilenames)) {
788     logAllUnhandledErrors(std::move(Err), WithColor::error());
789     return 1;
790   }
791 
792   MS->Finish();
793   OutFile.keep();
794   return 0;
795 }
796