1 //===-- llvm-dwp.cpp - Split DWARF merging tool for llvm ------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // A utility for merging DWARF 5 Split DWARF .dwo files into .dwp (DWARF
12 //===----------------------------------------------------------------------===//
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.inc"
31 #include "llvm/Object/Decompressor.h"
32 #include "llvm/Object/ObjectFile.h"
33 #include "llvm/Support/DataExtractor.h"
34 #include "llvm/Support/Error.h"
35 #include "llvm/Support/FileSystem.h"
36 #include "llvm/Support/InitLLVM.h"
37 #include "llvm/Support/MathExtras.h"
38 #include "llvm/Support/MemoryBuffer.h"
39 #include "llvm/Support/Path.h"
40 #include "llvm/Support/TargetRegistry.h"
41 #include "llvm/Support/TargetSelect.h"
42 #include "llvm/Support/ToolOutputFile.h"
43 #include "llvm/Support/WithColor.h"
44 #include "llvm/Support/raw_ostream.h"
47 using namespace llvm::object;
49 cl::OptionCategory DwpCategory("Specific Options");
50 static cl::list<std::string> InputFiles(cl::Positional, cl::ZeroOrMore,
51 cl::desc("<input files>"),
52 cl::cat(DwpCategory));
54 static cl::list<std::string> ExecFilenames(
56 cl::desc("Specify the executable/library files to get the list of *.dwo from"),
57 cl::value_desc("filename"), cl::cat(DwpCategory));
59 static cl::opt<std::string> OutputFilename(cl::Required, "o",
60 cl::desc("Specify the output file."),
61 cl::value_desc("filename"),
62 cl::cat(DwpCategory));
64 static void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,
65 MCSection *StrOffsetSection,
66 StringRef CurStrSection,
67 StringRef CurStrOffsetSection) {
68 // Could possibly produce an error or warning if one of these was non-null but
69 // the other was null.
70 if (CurStrSection.empty() || CurStrOffsetSection.empty())
73 DenseMap<uint32_t, uint32_t> OffsetRemapping;
75 DataExtractor Data(CurStrSection, true, 0);
76 uint32_t LocalOffset = 0;
77 uint32_t PrevOffset = 0;
78 while (const char *s = Data.getCStr(&LocalOffset)) {
79 OffsetRemapping[PrevOffset] =
80 Strings.getOffset(s, LocalOffset - PrevOffset);
81 PrevOffset = LocalOffset;
84 Data = DataExtractor(CurStrOffsetSection, true, 0);
86 Out.SwitchSection(StrOffsetSection);
89 uint64_t Size = CurStrOffsetSection.size();
90 while (Offset < Size) {
91 auto OldOffset = Data.getU32(&Offset);
92 auto NewOffset = OffsetRemapping[OldOffset];
93 Out.EmitIntValue(NewOffset, 4);
97 static uint32_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) {
100 DataExtractor AbbrevData(Abbrev, true, 0);
101 while ((CurCode = AbbrevData.getULEB128(&Offset)) != AbbrCode) {
103 AbbrevData.getULEB128(&Offset);
105 AbbrevData.getU8(&Offset);
107 while (AbbrevData.getULEB128(&Offset) | AbbrevData.getULEB128(&Offset))
113 struct CompileUnitIdentifiers {
114 uint64_t Signature = 0;
115 const char *Name = "";
116 const char *DWOName = "";
119 static Expected<const char *>
120 getIndexedString(dwarf::Form Form, DataExtractor InfoData,
121 uint32_t &InfoOffset, StringRef StrOffsets, StringRef Str) {
122 if (Form == dwarf::DW_FORM_string)
123 return InfoData.getCStr(&InfoOffset);
124 if (Form != dwarf::DW_FORM_GNU_str_index)
125 return make_error<DWPError>(
126 "string field encoded without DW_FORM_string or DW_FORM_GNU_str_index");
127 auto StrIndex = InfoData.getULEB128(&InfoOffset);
128 DataExtractor StrOffsetsData(StrOffsets, true, 0);
129 uint32_t StrOffsetsOffset = 4 * StrIndex;
130 uint32_t StrOffset = StrOffsetsData.getU32(&StrOffsetsOffset);
131 DataExtractor StrData(Str, true, 0);
132 return StrData.getCStr(&StrOffset);
135 static Expected<CompileUnitIdentifiers> getCUIdentifiers(StringRef Abbrev,
137 StringRef StrOffsets,
140 DataExtractor InfoData(Info, true, 0);
141 dwarf::DwarfFormat Format = dwarf::DwarfFormat::DWARF32;
142 uint64_t Length = InfoData.getU32(&Offset);
143 // If the length is 0xffffffff, then this indictes that this is a DWARF 64
144 // stream and the length is actually encoded into a 64 bit value that follows.
145 if (Length == 0xffffffffU) {
146 Format = dwarf::DwarfFormat::DWARF64;
147 Length = InfoData.getU64(&Offset);
149 uint16_t Version = InfoData.getU16(&Offset);
150 InfoData.getU32(&Offset); // Abbrev offset (should be zero)
151 uint8_t AddrSize = InfoData.getU8(&Offset);
153 uint32_t AbbrCode = InfoData.getULEB128(&Offset);
155 DataExtractor AbbrevData(Abbrev, true, 0);
156 uint32_t AbbrevOffset = getCUAbbrev(Abbrev, AbbrCode);
157 auto Tag = static_cast<dwarf::Tag>(AbbrevData.getULEB128(&AbbrevOffset));
158 if (Tag != dwarf::DW_TAG_compile_unit)
159 return make_error<DWPError>("top level DIE is not a compile unit");
161 AbbrevData.getU8(&AbbrevOffset);
164 CompileUnitIdentifiers ID;
165 Optional<uint64_t> Signature = None;
166 while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) |
167 (Form = static_cast<dwarf::Form>(AbbrevData.getULEB128(&AbbrevOffset))) &&
168 (Name != 0 || Form != 0)) {
170 case dwarf::DW_AT_name: {
171 Expected<const char *> EName =
172 getIndexedString(Form, InfoData, Offset, StrOffsets, Str);
174 return EName.takeError();
178 case dwarf::DW_AT_GNU_dwo_name: {
179 Expected<const char *> EName =
180 getIndexedString(Form, InfoData, Offset, StrOffsets, Str);
182 return EName.takeError();
186 case dwarf::DW_AT_GNU_dwo_id:
187 Signature = InfoData.getU64(&Offset);
190 DWARFFormValue::skipValue(Form, InfoData, &Offset,
191 dwarf::FormParams({Version, AddrSize, Format}));
195 return make_error<DWPError>("compile unit missing dwo_id");
196 ID.Signature = *Signature;
200 struct UnitIndexEntry {
201 DWARFUnitIndex::Entry::SectionContribution Contributions[8];
207 static StringRef getSubsection(StringRef Section,
208 const DWARFUnitIndex::Entry &Entry,
209 DWARFSectionKind Kind) {
210 const auto *Off = Entry.getOffset(Kind);
213 return Section.substr(Off->Offset, Off->Length);
216 static void addAllTypesFromDWP(
217 MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
218 const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types,
219 const UnitIndexEntry &TUEntry, uint32_t &TypesOffset) {
220 Out.SwitchSection(OutputTypes);
221 for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) {
222 auto *I = E.getOffsets();
225 auto P = TypeIndexEntries.insert(std::make_pair(E.getSignature(), TUEntry));
228 auto &Entry = P.first->second;
229 // Zero out the debug_info contribution
230 Entry.Contributions[0] = {};
231 for (auto Kind : TUIndex.getColumnKinds()) {
232 auto &C = Entry.Contributions[Kind - DW_SECT_INFO];
233 C.Offset += I->Offset;
234 C.Length = I->Length;
237 auto &C = Entry.Contributions[DW_SECT_TYPES - DW_SECT_INFO];
238 Out.EmitBytes(Types.substr(
239 C.Offset - TUEntry.Contributions[DW_SECT_TYPES - DW_SECT_INFO].Offset,
241 C.Offset = TypesOffset;
242 TypesOffset += C.Length;
246 static void addAllTypes(MCStreamer &Out,
247 MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
248 MCSection *OutputTypes,
249 const std::vector<StringRef> &TypesSections,
250 const UnitIndexEntry &CUEntry, uint32_t &TypesOffset) {
251 for (StringRef Types : TypesSections) {
252 Out.SwitchSection(OutputTypes);
254 DataExtractor Data(Types, true, 0);
255 while (Data.isValidOffset(Offset)) {
256 UnitIndexEntry Entry = CUEntry;
257 // Zero out the debug_info contribution
258 Entry.Contributions[0] = {};
259 auto &C = Entry.Contributions[DW_SECT_TYPES - DW_SECT_INFO];
260 C.Offset = TypesOffset;
261 auto PrevOffset = Offset;
262 // Length of the unit, including the 4 byte length field.
263 C.Length = Data.getU32(&Offset) + 4;
265 Data.getU16(&Offset); // Version
266 Data.getU32(&Offset); // Abbrev offset
267 Data.getU8(&Offset); // Address size
268 auto Signature = Data.getU64(&Offset);
269 Offset = PrevOffset + C.Length;
271 auto P = TypeIndexEntries.insert(std::make_pair(Signature, Entry));
275 Out.EmitBytes(Types.substr(PrevOffset, C.Length));
276 TypesOffset += C.Length;
282 writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
283 const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
284 uint32_t DWARFUnitIndex::Entry::SectionContribution::*Field) {
285 for (const auto &E : IndexEntries)
286 for (size_t i = 0; i != array_lengthof(E.second.Contributions); ++i)
287 if (ContributionOffsets[i])
288 Out.EmitIntValue(E.second.Contributions[i].*Field, 4);
292 writeIndex(MCStreamer &Out, MCSection *Section,
293 ArrayRef<unsigned> ContributionOffsets,
294 const MapVector<uint64_t, UnitIndexEntry> &IndexEntries) {
295 if (IndexEntries.empty())
298 unsigned Columns = 0;
299 for (auto &C : ContributionOffsets)
303 std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
304 uint64_t Mask = Buckets.size() - 1;
306 for (const auto &P : IndexEntries) {
309 auto HP = ((S >> 32) & Mask) | 1;
311 assert(S != IndexEntries.begin()[Buckets[H] - 1].first &&
319 Out.SwitchSection(Section);
320 Out.EmitIntValue(2, 4); // Version
321 Out.EmitIntValue(Columns, 4); // Columns
322 Out.EmitIntValue(IndexEntries.size(), 4); // Num Units
323 Out.EmitIntValue(Buckets.size(), 4); // Num Buckets
325 // Write the signatures.
326 for (const auto &I : Buckets)
327 Out.EmitIntValue(I ? IndexEntries.begin()[I - 1].first : 0, 8);
329 // Write the indexes.
330 for (const auto &I : Buckets)
331 Out.EmitIntValue(I, 4);
333 // Write the column headers (which sections will appear in the table)
334 for (size_t i = 0; i != ContributionOffsets.size(); ++i)
335 if (ContributionOffsets[i])
336 Out.EmitIntValue(i + DW_SECT_INFO, 4);
338 // Write the offsets.
339 writeIndexTable(Out, ContributionOffsets, IndexEntries,
340 &DWARFUnitIndex::Entry::SectionContribution::Offset);
342 // Write the lengths.
343 writeIndexTable(Out, ContributionOffsets, IndexEntries,
344 &DWARFUnitIndex::Entry::SectionContribution::Length);
347 std::string buildDWODescription(StringRef Name, StringRef DWPName, StringRef DWOName) {
348 std::string Text = "\'";
351 if (!DWPName.empty()) {
353 if (!DWOName.empty()) {
365 static Error createError(StringRef Name, Error E) {
366 return make_error<DWPError>(
367 ("failure while decompressing compressed section: '" + Name + "', " +
368 llvm::toString(std::move(E)))
373 handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections,
374 StringRef &Name, StringRef &Contents) {
375 if (!Decompressor::isGnuStyle(Name))
376 return Error::success();
378 Expected<Decompressor> Dec =
379 Decompressor::create(Name, Contents, false /*IsLE*/, false /*Is64Bit*/);
381 return createError(Name, Dec.takeError());
383 UncompressedSections.emplace_back();
384 if (Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
385 return createError(Name, std::move(E));
387 Name = Name.substr(2); // Drop ".z"
388 Contents = UncompressedSections.back();
389 return Error::success();
392 static Error handleSection(
393 const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
394 const MCSection *StrSection, const MCSection *StrOffsetSection,
395 const MCSection *TypesSection, const MCSection *CUIndexSection,
396 const MCSection *TUIndexSection, const SectionRef &Section, MCStreamer &Out,
397 std::deque<SmallString<32>> &UncompressedSections,
398 uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry,
399 StringRef &CurStrSection, StringRef &CurStrOffsetSection,
400 std::vector<StringRef> &CurTypesSection, StringRef &InfoSection,
401 StringRef &AbbrevSection, StringRef &CurCUIndexSection,
402 StringRef &CurTUIndexSection) {
404 return Error::success();
406 if (Section.isVirtual())
407 return Error::success();
410 if (std::error_code Err = Section.getName(Name))
411 return errorCodeToError(Err);
413 Expected<StringRef> ContentsOrErr = Section.getContents();
415 return ContentsOrErr.takeError();
416 StringRef Contents = *ContentsOrErr;
418 if (auto Err = handleCompressedSection(UncompressedSections, Name, Contents))
421 Name = Name.substr(Name.find_first_not_of("._"));
423 auto SectionPair = KnownSections.find(Name);
424 if (SectionPair == KnownSections.end())
425 return Error::success();
427 if (DWARFSectionKind Kind = SectionPair->second.second) {
428 auto Index = Kind - DW_SECT_INFO;
429 if (Kind != DW_SECT_TYPES) {
430 CurEntry.Contributions[Index].Offset = ContributionOffsets[Index];
431 ContributionOffsets[Index] +=
432 (CurEntry.Contributions[Index].Length = Contents.size());
437 InfoSection = Contents;
440 AbbrevSection = Contents;
447 MCSection *OutSection = SectionPair->second.first;
448 if (OutSection == StrOffsetSection)
449 CurStrOffsetSection = Contents;
450 else if (OutSection == StrSection)
451 CurStrSection = Contents;
452 else if (OutSection == TypesSection)
453 CurTypesSection.push_back(Contents);
454 else if (OutSection == CUIndexSection)
455 CurCUIndexSection = Contents;
456 else if (OutSection == TUIndexSection)
457 CurTUIndexSection = Contents;
459 Out.SwitchSection(OutSection);
460 Out.EmitBytes(Contents);
462 return Error::success();
466 buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
467 const CompileUnitIdentifiers &ID, StringRef DWPName) {
468 return make_error<DWPError>(
469 std::string("Duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " +
470 buildDWODescription(PrevE.second.Name, PrevE.second.DWPName,
471 PrevE.second.DWOName) +
472 " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));
475 static Expected<SmallVector<std::string, 16>>
476 getDWOFilenames(StringRef ExecFilename) {
477 auto ErrOrObj = object::ObjectFile::createObjectFile(ExecFilename);
479 return ErrOrObj.takeError();
481 const ObjectFile &Obj = *ErrOrObj.get().getBinary();
482 std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj);
484 SmallVector<std::string, 16> DWOPaths;
485 for (const auto &CU : DWARFCtx->compile_units()) {
486 const DWARFDie &Die = CU->getUnitDIE();
487 std::string DWOName = dwarf::toString(
488 Die.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
491 std::string DWOCompDir =
492 dwarf::toString(Die.find(dwarf::DW_AT_comp_dir), "");
493 if (!DWOCompDir.empty()) {
494 SmallString<16> DWOPath;
495 sys::path::append(DWOPath, DWOCompDir, DWOName);
496 DWOPaths.emplace_back(DWOPath.data(), DWOPath.size());
498 DWOPaths.push_back(std::move(DWOName));
501 return std::move(DWOPaths);
504 static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
505 const auto &MCOFI = *Out.getContext().getObjectFileInfo();
506 MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
507 MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
508 MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection();
509 MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection();
510 MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection();
511 const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = {
512 {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}},
513 {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_TYPES}},
514 {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
515 {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}},
516 {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_LOC}},
517 {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
518 {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
519 {"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}},
520 {"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};
522 MapVector<uint64_t, UnitIndexEntry> IndexEntries;
523 MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
525 uint32_t ContributionOffsets[8] = {};
527 DWPStringPool Strings(Out, StrSection);
529 SmallVector<OwningBinary<object::ObjectFile>, 128> Objects;
530 Objects.reserve(Inputs.size());
532 std::deque<SmallString<32>> UncompressedSections;
534 for (const auto &Input : Inputs) {
535 auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
537 return ErrOrObj.takeError();
539 auto &Obj = *ErrOrObj->getBinary();
540 Objects.push_back(std::move(*ErrOrObj));
542 UnitIndexEntry CurEntry = {};
544 StringRef CurStrSection;
545 StringRef CurStrOffsetSection;
546 std::vector<StringRef> CurTypesSection;
547 StringRef InfoSection;
548 StringRef AbbrevSection;
549 StringRef CurCUIndexSection;
550 StringRef CurTUIndexSection;
552 for (const auto &Section : Obj.sections())
553 if (auto Err = handleSection(
554 KnownSections, StrSection, StrOffsetSection, TypesSection,
555 CUIndexSection, TUIndexSection, Section, Out,
556 UncompressedSections, ContributionOffsets, CurEntry,
557 CurStrSection, CurStrOffsetSection, CurTypesSection, InfoSection,
558 AbbrevSection, CurCUIndexSection, CurTUIndexSection))
561 if (InfoSection.empty())
564 writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection,
565 CurStrOffsetSection);
567 if (CurCUIndexSection.empty()) {
568 Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
569 AbbrevSection, InfoSection, CurStrOffsetSection, CurStrSection);
571 return createFileError(Input, EID.takeError());
572 const auto &ID = *EID;
573 auto P = IndexEntries.insert(std::make_pair(ID.Signature, CurEntry));
575 return buildDuplicateError(*P.first, ID, "");
576 P.first->second.Name = ID.Name;
577 P.first->second.DWOName = ID.DWOName;
578 addAllTypes(Out, TypeIndexEntries, TypesSection, CurTypesSection,
579 CurEntry, ContributionOffsets[DW_SECT_TYPES - DW_SECT_INFO]);
583 DWARFUnitIndex CUIndex(DW_SECT_INFO);
584 DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
585 if (!CUIndex.parse(CUIndexData))
586 return make_error<DWPError>("Failed to parse cu_index");
588 for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
589 auto *I = E.getOffsets();
592 auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry));
593 Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
594 getSubsection(AbbrevSection, E, DW_SECT_ABBREV),
595 getSubsection(InfoSection, E, DW_SECT_INFO),
596 getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS),
599 return createFileError(Input, EID.takeError());
600 const auto &ID = *EID;
602 return buildDuplicateError(*P.first, ID, Input);
603 auto &NewEntry = P.first->second;
604 NewEntry.Name = ID.Name;
605 NewEntry.DWOName = ID.DWOName;
606 NewEntry.DWPName = Input;
607 for (auto Kind : CUIndex.getColumnKinds()) {
608 auto &C = NewEntry.Contributions[Kind - DW_SECT_INFO];
609 C.Offset += I->Offset;
610 C.Length = I->Length;
615 if (!CurTypesSection.empty()) {
616 if (CurTypesSection.size() != 1)
617 return make_error<DWPError>("multiple type unit sections in .dwp file");
618 DWARFUnitIndex TUIndex(DW_SECT_TYPES);
619 DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);
620 if (!TUIndex.parse(TUIndexData))
621 return make_error<DWPError>("Failed to parse tu_index");
622 addAllTypesFromDWP(Out, TypeIndexEntries, TUIndex, TypesSection,
623 CurTypesSection.front(), CurEntry,
624 ContributionOffsets[DW_SECT_TYPES - DW_SECT_INFO]);
628 // Lie about there being no info contributions so the TU index only includes
629 // the type unit contribution
630 ContributionOffsets[0] = 0;
631 writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
634 // Lie about the type contribution
635 ContributionOffsets[DW_SECT_TYPES - DW_SECT_INFO] = 0;
636 // Unlie about the info contribution
637 ContributionOffsets[0] = 1;
639 writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
642 return Error::success();
645 static int error(const Twine &Error, const Twine &Context) {
646 errs() << Twine("while processing ") + Context + ":\n";
647 errs() << Twine("error: ") + Error + "\n";
651 int main(int argc, char **argv) {
652 InitLLVM X(argc, argv);
654 cl::ParseCommandLineOptions(argc, argv, "merge split dwarf (.dwo) files\n");
656 llvm::InitializeAllTargetInfos();
657 llvm::InitializeAllTargetMCs();
658 llvm::InitializeAllTargets();
659 llvm::InitializeAllAsmPrinters();
661 std::string ErrorStr;
662 StringRef Context = "dwarf streamer init";
664 Triple TheTriple("x86_64-linux-gnu");
667 const Target *TheTarget =
668 TargetRegistry::lookupTarget("", TheTriple, ErrorStr);
670 return error(ErrorStr, Context);
671 std::string TripleName = TheTriple.getTriple();
673 // Create all the MC Objects.
674 std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
676 return error(Twine("no register info for target ") + TripleName, Context);
678 std::unique_ptr<MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TripleName));
680 return error("no asm info for target " + TripleName, Context);
682 MCObjectFileInfo MOFI;
683 MCContext MC(MAI.get(), MRI.get(), &MOFI);
684 MOFI.InitMCObjectFileInfo(TheTriple, /*PIC*/ false, MC);
686 std::unique_ptr<MCSubtargetInfo> MSTI(
687 TheTarget->createMCSubtargetInfo(TripleName, "", ""));
689 return error("no subtarget info for target " + TripleName, Context);
691 MCTargetOptions Options;
692 auto MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, Options);
694 return error("no asm backend for target " + TripleName, Context);
696 std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
698 return error("no instr info info for target " + TripleName, Context);
700 MCCodeEmitter *MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, MC);
702 return error("no code emitter for target " + TripleName, Context);
704 // Create the output file.
706 ToolOutputFile OutFile(OutputFilename, EC, sys::fs::F_None);
707 Optional<buffer_ostream> BOS;
708 raw_pwrite_stream *OS;
710 return error(Twine(OutputFilename) + ": " + EC.message(), Context);
711 if (OutFile.os().supportsSeeking()) {
714 BOS.emplace(OutFile.os());
715 OS = BOS.getPointer();
718 MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags();
719 std::unique_ptr<MCStreamer> MS(TheTarget->createMCObjectStreamer(
720 TheTriple, MC, std::unique_ptr<MCAsmBackend>(MAB),
721 MAB->createObjectWriter(*OS), std::unique_ptr<MCCodeEmitter>(MCE), *MSTI,
722 MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
723 /*DWARFMustBeAtTheEnd*/ false));
725 return error("no object streamer for target " + TripleName, Context);
727 std::vector<std::string> DWOFilenames = InputFiles;
728 for (const auto &ExecFilename : ExecFilenames) {
729 auto DWOs = getDWOFilenames(ExecFilename);
731 logAllUnhandledErrors(DWOs.takeError(), WithColor::error());
734 DWOFilenames.insert(DWOFilenames.end(),
735 std::make_move_iterator(DWOs->begin()),
736 std::make_move_iterator(DWOs->end()));
739 if (auto Err = write(*MS, DWOFilenames)) {
740 logAllUnhandledErrors(std::move(Err), WithColor::error());