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.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"
48 using namespace llvm::object;
50 static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags;
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));
57 static cl::list<std::string> ExecFilenames(
59 cl::desc("Specify the executable/library files to get the list of *.dwo from"),
60 cl::value_desc("filename"), cl::cat(DwpCategory));
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));
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())
76 DenseMap<uint64_t, uint32_t> OffsetRemapping;
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;
87 Data = DataExtractor(CurStrOffsetSection, true, 0);
89 Out.SwitchSection(StrOffsetSection);
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);
100 static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) {
103 DataExtractor AbbrevData(Abbrev, true, 0);
104 while ((CurCode = AbbrevData.getULEB128(&Offset)) != AbbrCode) {
106 AbbrevData.getULEB128(&Offset);
108 AbbrevData.getU8(&Offset);
110 while (AbbrevData.getULEB128(&Offset) | AbbrevData.getULEB128(&Offset))
116 struct CompileUnitIdentifiers {
117 uint64_t Signature = 0;
118 const char *Name = "";
119 const char *DWOName = "";
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);
138 static Expected<CompileUnitIdentifiers> getCUIdentifiers(StringRef Abbrev,
140 StringRef StrOffsets,
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);
154 uint16_t Version = InfoData.getU16(&Offset);
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"));
163 InfoData.getU32(&Offset); // Abbrev offset (should be zero)
164 uint8_t AddrSize = InfoData.getU8(&Offset);
166 Signature = InfoData.getU64(&Offset);
167 uint32_t AbbrCode = InfoData.getULEB128(&Offset);
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");
175 AbbrevData.getU8(&AbbrevOffset);
178 while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) |
179 (Form = static_cast<dwarf::Form>(AbbrevData.getULEB128(&AbbrevOffset))) &&
180 (Name != 0 || Form != 0)) {
182 case dwarf::DW_AT_name: {
183 Expected<const char *> EName =
184 getIndexedString(Form, InfoData, Offset, StrOffsets, Str);
186 return EName.takeError();
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);
195 return EName.takeError();
199 case dwarf::DW_AT_GNU_dwo_id:
200 Signature = InfoData.getU64(&Offset);
203 DWARFFormValue::skipValue(Form, InfoData, &Offset,
204 dwarf::FormParams({Version, AddrSize, Format}));
208 return make_error<DWPError>("compile unit missing dwo_id");
209 ID.Signature = *Signature;
213 struct UnitIndexEntry {
214 DWARFUnitIndex::Entry::SectionContribution Contributions[8];
220 static bool isSupportedSectionKind(DWARFSectionKind Kind) {
221 return Kind != DW_SECT_EXT_unknown;
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;
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;
238 static StringRef getSubsection(StringRef Section,
239 const DWARFUnitIndex::Entry &Entry,
240 DWARFSectionKind Kind) {
241 const auto *Off = Entry.getContribution(Kind);
244 return Section.substr(Off->Offset, Off->Length);
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();
256 auto P = TypeIndexEntries.insert(std::make_pair(E.getSignature(), TUEntry));
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))
265 auto &C = Entry.Contributions[getContributionIndex(Kind)];
266 C.Offset += I->Offset;
267 C.Length = I->Length;
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;
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);
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;
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;
304 auto P = TypeIndexEntries.insert(std::make_pair(Signature, Entry));
308 Out.emitBytes(Types.substr(PrevOffset, C.Length));
309 TypesOffset += C.Length;
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);
325 writeIndex(MCStreamer &Out, MCSection *Section,
326 ArrayRef<unsigned> ContributionOffsets,
327 const MapVector<uint64_t, UnitIndexEntry> &IndexEntries) {
328 if (IndexEntries.empty())
331 unsigned Columns = 0;
332 for (auto &C : ContributionOffsets)
336 std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
337 uint64_t Mask = Buckets.size() - 1;
339 for (const auto &P : IndexEntries) {
342 auto HP = ((S >> 32) & Mask) | 1;
344 assert(S != IndexEntries.begin()[Buckets[H] - 1].first &&
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
358 // Write the signatures.
359 for (const auto &I : Buckets)
360 Out.emitIntValue(I ? IndexEntries.begin()[I - 1].first : 0, 8);
362 // Write the indexes.
363 for (const auto &I : Buckets)
364 Out.emitIntValue(I, 4);
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);
371 // Write the offsets.
372 writeIndexTable(Out, ContributionOffsets, IndexEntries,
373 &DWARFUnitIndex::Entry::SectionContribution::Offset);
375 // Write the lengths.
376 writeIndexTable(Out, ContributionOffsets, IndexEntries,
377 &DWARFUnitIndex::Entry::SectionContribution::Length);
380 std::string buildDWODescription(StringRef Name, StringRef DWPName, StringRef DWOName) {
381 std::string Text = "\'";
384 if (!DWPName.empty()) {
386 if (!DWOName.empty()) {
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)))
406 handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections,
407 StringRef &Name, StringRef &Contents) {
408 if (!Decompressor::isGnuStyle(Name))
409 return Error::success();
411 Expected<Decompressor> Dec =
412 Decompressor::create(Name, Contents, false /*IsLE*/, false /*Is64Bit*/);
414 return createError(Name, Dec.takeError());
416 UncompressedSections.emplace_back();
417 if (Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
418 return createError(Name, std::move(E));
420 Name = Name.substr(2); // Drop ".z"
421 Contents = UncompressedSections.back();
422 return Error::success();
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) {
437 return Error::success();
439 if (Section.isVirtual())
440 return Error::success();
442 Expected<StringRef> NameOrErr = Section.getName();
444 return NameOrErr.takeError();
445 StringRef Name = *NameOrErr;
447 Expected<StringRef> ContentsOrErr = Section.getContents();
449 return ContentsOrErr.takeError();
450 StringRef Contents = *ContentsOrErr;
452 if (auto Err = handleCompressedSection(UncompressedSections, Name, Contents))
455 Name = Name.substr(Name.find_first_not_of("._"));
457 auto SectionPair = KnownSections.find(Name);
458 if (SectionPair == KnownSections.end())
459 return Error::success();
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());
471 InfoSection = Contents;
474 AbbrevSection = Contents;
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;
493 Out.SwitchSection(OutSection);
494 Out.emitBytes(Contents);
496 return Error::success();
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));
509 static Expected<SmallVector<std::string, 16>>
510 getDWOFilenames(StringRef ExecFilename) {
511 auto ErrOrObj = object::ObjectFile::createObjectFile(ExecFilename);
513 return ErrOrObj.takeError();
515 const ObjectFile &Obj = *ErrOrObj.get().getBinary();
516 std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj);
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}), "");
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());
532 DWOPaths.push_back(std::move(DWOName));
535 return std::move(DWOPaths);
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)}}};
556 MapVector<uint64_t, UnitIndexEntry> IndexEntries;
557 MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
559 uint32_t ContributionOffsets[8] = {};
561 DWPStringPool Strings(Out, StrSection);
563 SmallVector<OwningBinary<object::ObjectFile>, 128> Objects;
564 Objects.reserve(Inputs.size());
566 std::deque<SmallString<32>> UncompressedSections;
568 for (const auto &Input : Inputs) {
569 auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
571 return ErrOrObj.takeError();
573 auto &Obj = *ErrOrObj->getBinary();
574 Objects.push_back(std::move(*ErrOrObj));
576 UnitIndexEntry CurEntry = {};
578 StringRef CurStrSection;
579 StringRef CurStrOffsetSection;
580 std::vector<StringRef> CurTypesSection;
581 StringRef InfoSection;
582 StringRef AbbrevSection;
583 StringRef CurCUIndexSection;
584 StringRef CurTUIndexSection;
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))
595 if (InfoSection.empty())
598 writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection,
599 CurStrOffsetSection);
601 if (CurCUIndexSection.empty()) {
602 Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
603 AbbrevSection, InfoSection, CurStrOffsetSection, CurStrSection);
605 return createFileError(Input, EID.takeError());
606 const auto &ID = *EID;
607 auto P = IndexEntries.insert(std::make_pair(ID.Signature, CurEntry));
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,
614 ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]);
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)");
627 for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
628 auto *I = E.getContributions();
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),
638 return createFileError(Input, EID.takeError());
639 const auto &ID = *EID;
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))
649 auto &C = NewEntry.Contributions[getContributionIndex(Kind)];
650 C.Offset += I->Offset;
651 C.Length = I->Length;
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)");
669 Out, TypeIndexEntries, TUIndex, TypesSection, CurTypesSection.front(),
671 ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]);
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,
681 // Lie about the type contribution
682 ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)] = 0;
683 // Unlie about the info contribution
684 ContributionOffsets[0] = 1;
686 writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
689 return Error::success();
692 static int error(const Twine &Error, const Twine &Context) {
693 errs() << Twine("while processing ") + Context + ":\n";
694 errs() << Twine("error: ") + Error + "\n";
698 int main(int argc, char **argv) {
699 InitLLVM X(argc, argv);
701 cl::ParseCommandLineOptions(argc, argv, "merge split dwarf (.dwo) files\n");
703 llvm::InitializeAllTargetInfos();
704 llvm::InitializeAllTargetMCs();
705 llvm::InitializeAllTargets();
706 llvm::InitializeAllAsmPrinters();
708 std::string ErrorStr;
709 StringRef Context = "dwarf streamer init";
711 Triple TheTriple("x86_64-linux-gnu");
714 const Target *TheTarget =
715 TargetRegistry::lookupTarget("", TheTriple, ErrorStr);
717 return error(ErrorStr, Context);
718 std::string TripleName = TheTriple.getTriple();
720 // Create all the MC Objects.
721 std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
723 return error(Twine("no register info for target ") + TripleName, Context);
725 MCTargetOptions MCOptions = llvm::mc::InitMCTargetOptionsFromFlags();
726 std::unique_ptr<MCAsmInfo> MAI(
727 TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
729 return error("no asm info for target " + TripleName, Context);
731 MCObjectFileInfo MOFI;
732 MCContext MC(MAI.get(), MRI.get(), &MOFI);
733 MOFI.InitMCObjectFileInfo(TheTriple, /*PIC*/ false, MC);
735 std::unique_ptr<MCSubtargetInfo> MSTI(
736 TheTarget->createMCSubtargetInfo(TripleName, "", ""));
738 return error("no subtarget info for target " + TripleName, Context);
740 MCTargetOptions Options;
741 auto MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, Options);
743 return error("no asm backend for target " + TripleName, Context);
745 std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
747 return error("no instr info info for target " + TripleName, Context);
749 MCCodeEmitter *MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, MC);
751 return error("no code emitter for target " + TripleName, Context);
753 // Create the output file.
755 ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_None);
756 Optional<buffer_ostream> BOS;
757 raw_pwrite_stream *OS;
759 return error(Twine(OutputFilename) + ": " + EC.message(), Context);
760 if (OutFile.os().supportsSeeking()) {
763 BOS.emplace(OutFile.os());
764 OS = BOS.getPointer();
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));
773 return error("no object streamer for target " + TripleName, Context);
775 std::vector<std::string> DWOFilenames = InputFiles;
776 for (const auto &ExecFilename : ExecFilenames) {
777 auto DWOs = getDWOFilenames(ExecFilename);
779 logAllUnhandledErrors(DWOs.takeError(), WithColor::error());
782 DWOFilenames.insert(DWOFilenames.end(),
783 std::make_move_iterator(DWOs->begin()),
784 std::make_move_iterator(DWOs->end()));
787 if (auto Err = write(*MS, DWOFilenames)) {
788 logAllUnhandledErrors(std::move(Err), WithColor::error());