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<uint64_t, uint32_t> OffsetRemapping;
75 DataExtractor Data(CurStrSection, true, 0);
76 uint64_t LocalOffset = 0;
77 uint64_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 uint64_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 uint64_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 uint64_t StrOffsetsOffset = 4 * StrIndex;
130 uint64_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 uint64_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();
409 Expected<StringRef> NameOrErr = Section.getName();
411 return NameOrErr.takeError();
412 StringRef Name = *NameOrErr;
414 Expected<StringRef> ContentsOrErr = Section.getContents();
416 return ContentsOrErr.takeError();
417 StringRef Contents = *ContentsOrErr;
419 if (auto Err = handleCompressedSection(UncompressedSections, Name, Contents))
422 Name = Name.substr(Name.find_first_not_of("._"));
424 auto SectionPair = KnownSections.find(Name);
425 if (SectionPair == KnownSections.end())
426 return Error::success();
428 if (DWARFSectionKind Kind = SectionPair->second.second) {
429 auto Index = Kind - DW_SECT_INFO;
430 if (Kind != DW_SECT_TYPES) {
431 CurEntry.Contributions[Index].Offset = ContributionOffsets[Index];
432 ContributionOffsets[Index] +=
433 (CurEntry.Contributions[Index].Length = Contents.size());
438 InfoSection = Contents;
441 AbbrevSection = Contents;
448 MCSection *OutSection = SectionPair->second.first;
449 if (OutSection == StrOffsetSection)
450 CurStrOffsetSection = Contents;
451 else if (OutSection == StrSection)
452 CurStrSection = Contents;
453 else if (OutSection == TypesSection)
454 CurTypesSection.push_back(Contents);
455 else if (OutSection == CUIndexSection)
456 CurCUIndexSection = Contents;
457 else if (OutSection == TUIndexSection)
458 CurTUIndexSection = Contents;
460 Out.SwitchSection(OutSection);
461 Out.EmitBytes(Contents);
463 return Error::success();
467 buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
468 const CompileUnitIdentifiers &ID, StringRef DWPName) {
469 return make_error<DWPError>(
470 std::string("Duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " +
471 buildDWODescription(PrevE.second.Name, PrevE.second.DWPName,
472 PrevE.second.DWOName) +
473 " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));
476 static Expected<SmallVector<std::string, 16>>
477 getDWOFilenames(StringRef ExecFilename) {
478 auto ErrOrObj = object::ObjectFile::createObjectFile(ExecFilename);
480 return ErrOrObj.takeError();
482 const ObjectFile &Obj = *ErrOrObj.get().getBinary();
483 std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj);
485 SmallVector<std::string, 16> DWOPaths;
486 for (const auto &CU : DWARFCtx->compile_units()) {
487 const DWARFDie &Die = CU->getUnitDIE();
488 std::string DWOName = dwarf::toString(
489 Die.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
492 std::string DWOCompDir =
493 dwarf::toString(Die.find(dwarf::DW_AT_comp_dir), "");
494 if (!DWOCompDir.empty()) {
495 SmallString<16> DWOPath;
496 sys::path::append(DWOPath, DWOCompDir, DWOName);
497 DWOPaths.emplace_back(DWOPath.data(), DWOPath.size());
499 DWOPaths.push_back(std::move(DWOName));
502 return std::move(DWOPaths);
505 static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
506 const auto &MCOFI = *Out.getContext().getObjectFileInfo();
507 MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
508 MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
509 MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection();
510 MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection();
511 MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection();
512 const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = {
513 {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}},
514 {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_TYPES}},
515 {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
516 {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}},
517 {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_LOC}},
518 {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
519 {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
520 {"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}},
521 {"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};
523 MapVector<uint64_t, UnitIndexEntry> IndexEntries;
524 MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
526 uint32_t ContributionOffsets[8] = {};
528 DWPStringPool Strings(Out, StrSection);
530 SmallVector<OwningBinary<object::ObjectFile>, 128> Objects;
531 Objects.reserve(Inputs.size());
533 std::deque<SmallString<32>> UncompressedSections;
535 for (const auto &Input : Inputs) {
536 auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
538 return ErrOrObj.takeError();
540 auto &Obj = *ErrOrObj->getBinary();
541 Objects.push_back(std::move(*ErrOrObj));
543 UnitIndexEntry CurEntry = {};
545 StringRef CurStrSection;
546 StringRef CurStrOffsetSection;
547 std::vector<StringRef> CurTypesSection;
548 StringRef InfoSection;
549 StringRef AbbrevSection;
550 StringRef CurCUIndexSection;
551 StringRef CurTUIndexSection;
553 for (const auto &Section : Obj.sections())
554 if (auto Err = handleSection(
555 KnownSections, StrSection, StrOffsetSection, TypesSection,
556 CUIndexSection, TUIndexSection, Section, Out,
557 UncompressedSections, ContributionOffsets, CurEntry,
558 CurStrSection, CurStrOffsetSection, CurTypesSection, InfoSection,
559 AbbrevSection, CurCUIndexSection, CurTUIndexSection))
562 if (InfoSection.empty())
565 writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection,
566 CurStrOffsetSection);
568 if (CurCUIndexSection.empty()) {
569 Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
570 AbbrevSection, InfoSection, CurStrOffsetSection, CurStrSection);
572 return createFileError(Input, EID.takeError());
573 const auto &ID = *EID;
574 auto P = IndexEntries.insert(std::make_pair(ID.Signature, CurEntry));
576 return buildDuplicateError(*P.first, ID, "");
577 P.first->second.Name = ID.Name;
578 P.first->second.DWOName = ID.DWOName;
579 addAllTypes(Out, TypeIndexEntries, TypesSection, CurTypesSection,
580 CurEntry, ContributionOffsets[DW_SECT_TYPES - DW_SECT_INFO]);
584 DWARFUnitIndex CUIndex(DW_SECT_INFO);
585 DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
586 if (!CUIndex.parse(CUIndexData))
587 return make_error<DWPError>("Failed to parse cu_index");
589 for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
590 auto *I = E.getOffsets();
593 auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry));
594 Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
595 getSubsection(AbbrevSection, E, DW_SECT_ABBREV),
596 getSubsection(InfoSection, E, DW_SECT_INFO),
597 getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS),
600 return createFileError(Input, EID.takeError());
601 const auto &ID = *EID;
603 return buildDuplicateError(*P.first, ID, Input);
604 auto &NewEntry = P.first->second;
605 NewEntry.Name = ID.Name;
606 NewEntry.DWOName = ID.DWOName;
607 NewEntry.DWPName = Input;
608 for (auto Kind : CUIndex.getColumnKinds()) {
609 auto &C = NewEntry.Contributions[Kind - DW_SECT_INFO];
610 C.Offset += I->Offset;
611 C.Length = I->Length;
616 if (!CurTypesSection.empty()) {
617 if (CurTypesSection.size() != 1)
618 return make_error<DWPError>("multiple type unit sections in .dwp file");
619 DWARFUnitIndex TUIndex(DW_SECT_TYPES);
620 DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);
621 if (!TUIndex.parse(TUIndexData))
622 return make_error<DWPError>("Failed to parse tu_index");
623 addAllTypesFromDWP(Out, TypeIndexEntries, TUIndex, TypesSection,
624 CurTypesSection.front(), CurEntry,
625 ContributionOffsets[DW_SECT_TYPES - DW_SECT_INFO]);
629 // Lie about there being no info contributions so the TU index only includes
630 // the type unit contribution
631 ContributionOffsets[0] = 0;
632 writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
635 // Lie about the type contribution
636 ContributionOffsets[DW_SECT_TYPES - DW_SECT_INFO] = 0;
637 // Unlie about the info contribution
638 ContributionOffsets[0] = 1;
640 writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
643 return Error::success();
646 static int error(const Twine &Error, const Twine &Context) {
647 errs() << Twine("while processing ") + Context + ":\n";
648 errs() << Twine("error: ") + Error + "\n";
652 int main(int argc, char **argv) {
653 InitLLVM X(argc, argv);
655 cl::ParseCommandLineOptions(argc, argv, "merge split dwarf (.dwo) files\n");
657 llvm::InitializeAllTargetInfos();
658 llvm::InitializeAllTargetMCs();
659 llvm::InitializeAllTargets();
660 llvm::InitializeAllAsmPrinters();
662 std::string ErrorStr;
663 StringRef Context = "dwarf streamer init";
665 Triple TheTriple("x86_64-linux-gnu");
668 const Target *TheTarget =
669 TargetRegistry::lookupTarget("", TheTriple, ErrorStr);
671 return error(ErrorStr, Context);
672 std::string TripleName = TheTriple.getTriple();
674 // Create all the MC Objects.
675 std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
677 return error(Twine("no register info for target ") + TripleName, Context);
679 MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags();
680 std::unique_ptr<MCAsmInfo> MAI(
681 TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
683 return error("no asm info for target " + TripleName, Context);
685 MCObjectFileInfo MOFI;
686 MCContext MC(MAI.get(), MRI.get(), &MOFI);
687 MOFI.InitMCObjectFileInfo(TheTriple, /*PIC*/ false, MC);
689 std::unique_ptr<MCSubtargetInfo> MSTI(
690 TheTarget->createMCSubtargetInfo(TripleName, "", ""));
692 return error("no subtarget info for target " + TripleName, Context);
694 MCTargetOptions Options;
695 auto MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, Options);
697 return error("no asm backend for target " + TripleName, Context);
699 std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
701 return error("no instr info info for target " + TripleName, Context);
703 MCCodeEmitter *MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, MC);
705 return error("no code emitter for target " + TripleName, Context);
707 // Create the output file.
709 ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_None);
710 Optional<buffer_ostream> BOS;
711 raw_pwrite_stream *OS;
713 return error(Twine(OutputFilename) + ": " + EC.message(), Context);
714 if (OutFile.os().supportsSeeking()) {
717 BOS.emplace(OutFile.os());
718 OS = BOS.getPointer();
721 std::unique_ptr<MCStreamer> MS(TheTarget->createMCObjectStreamer(
722 TheTriple, MC, std::unique_ptr<MCAsmBackend>(MAB),
723 MAB->createObjectWriter(*OS), std::unique_ptr<MCCodeEmitter>(MCE), *MSTI,
724 MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
725 /*DWARFMustBeAtTheEnd*/ false));
727 return error("no object streamer for target " + TripleName, Context);
729 std::vector<std::string> DWOFilenames = InputFiles;
730 for (const auto &ExecFilename : ExecFilenames) {
731 auto DWOs = getDWOFilenames(ExecFilename);
733 logAllUnhandledErrors(DWOs.takeError(), WithColor::error());
736 DWOFilenames.insert(DWOFilenames.end(),
737 std::make_move_iterator(DWOs->begin()),
738 std::make_move_iterator(DWOs->end()));
741 if (auto Err = write(*MS, DWOFilenames)) {
742 logAllUnhandledErrors(std::move(Err), WithColor::error());