xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp (revision d409305fa3838fb39b38c26fc085fb729b8766d5)
162cfcf62SDimitry Andric //===-- llvm-dwp.cpp - Split DWARF merging tool for llvm ------------------===//
262cfcf62SDimitry Andric //
362cfcf62SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
462cfcf62SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
562cfcf62SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
662cfcf62SDimitry Andric //
762cfcf62SDimitry Andric //===----------------------------------------------------------------------===//
862cfcf62SDimitry Andric //
962cfcf62SDimitry Andric // A utility for merging DWARF 5 Split DWARF .dwo files into .dwp (DWARF
1062cfcf62SDimitry Andric // package files).
1162cfcf62SDimitry Andric //
1262cfcf62SDimitry Andric //===----------------------------------------------------------------------===//
1362cfcf62SDimitry Andric #include "DWPError.h"
1462cfcf62SDimitry Andric #include "DWPStringPool.h"
1562cfcf62SDimitry Andric #include "llvm/ADT/MapVector.h"
1662cfcf62SDimitry Andric #include "llvm/ADT/Optional.h"
1762cfcf62SDimitry Andric #include "llvm/ADT/STLExtras.h"
1862cfcf62SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h"
1962cfcf62SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
2062cfcf62SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
2162cfcf62SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
2262cfcf62SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
2362cfcf62SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
2462cfcf62SDimitry Andric #include "llvm/MC/MCContext.h"
2562cfcf62SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
2662cfcf62SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
2762cfcf62SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
2862cfcf62SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
2962cfcf62SDimitry Andric #include "llvm/MC/MCStreamer.h"
305ffd83dbSDimitry Andric #include "llvm/MC/MCTargetOptionsCommandFlags.h"
3162cfcf62SDimitry Andric #include "llvm/Object/Decompressor.h"
3262cfcf62SDimitry Andric #include "llvm/Object/ObjectFile.h"
335ffd83dbSDimitry Andric #include "llvm/Support/CommandLine.h"
3462cfcf62SDimitry Andric #include "llvm/Support/DataExtractor.h"
3562cfcf62SDimitry Andric #include "llvm/Support/Error.h"
3662cfcf62SDimitry Andric #include "llvm/Support/FileSystem.h"
3762cfcf62SDimitry Andric #include "llvm/Support/InitLLVM.h"
3862cfcf62SDimitry Andric #include "llvm/Support/MathExtras.h"
3962cfcf62SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
4062cfcf62SDimitry Andric #include "llvm/Support/Path.h"
4162cfcf62SDimitry Andric #include "llvm/Support/TargetRegistry.h"
4262cfcf62SDimitry Andric #include "llvm/Support/TargetSelect.h"
4362cfcf62SDimitry Andric #include "llvm/Support/ToolOutputFile.h"
4462cfcf62SDimitry Andric #include "llvm/Support/WithColor.h"
4562cfcf62SDimitry Andric #include "llvm/Support/raw_ostream.h"
4662cfcf62SDimitry Andric 
4762cfcf62SDimitry Andric using namespace llvm;
4862cfcf62SDimitry Andric using namespace llvm::object;
4962cfcf62SDimitry Andric 
505ffd83dbSDimitry Andric static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags;
515ffd83dbSDimitry Andric 
5262cfcf62SDimitry Andric cl::OptionCategory DwpCategory("Specific Options");
5362cfcf62SDimitry Andric static cl::list<std::string> InputFiles(cl::Positional, cl::ZeroOrMore,
5462cfcf62SDimitry Andric                                         cl::desc("<input files>"),
5562cfcf62SDimitry Andric                                         cl::cat(DwpCategory));
5662cfcf62SDimitry Andric 
5762cfcf62SDimitry Andric static cl::list<std::string> ExecFilenames(
5862cfcf62SDimitry Andric     "e", cl::ZeroOrMore,
5962cfcf62SDimitry Andric     cl::desc("Specify the executable/library files to get the list of *.dwo from"),
6062cfcf62SDimitry Andric     cl::value_desc("filename"), cl::cat(DwpCategory));
6162cfcf62SDimitry Andric 
6262cfcf62SDimitry Andric static cl::opt<std::string> OutputFilename(cl::Required, "o",
6362cfcf62SDimitry Andric                                            cl::desc("Specify the output file."),
6462cfcf62SDimitry Andric                                            cl::value_desc("filename"),
6562cfcf62SDimitry Andric                                            cl::cat(DwpCategory));
6662cfcf62SDimitry Andric 
6762cfcf62SDimitry Andric static void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,
6862cfcf62SDimitry Andric                                    MCSection *StrOffsetSection,
6962cfcf62SDimitry Andric                                    StringRef CurStrSection,
7062cfcf62SDimitry Andric                                    StringRef CurStrOffsetSection) {
7162cfcf62SDimitry Andric   // Could possibly produce an error or warning if one of these was non-null but
7262cfcf62SDimitry Andric   // the other was null.
7362cfcf62SDimitry Andric   if (CurStrSection.empty() || CurStrOffsetSection.empty())
7462cfcf62SDimitry Andric     return;
7562cfcf62SDimitry Andric 
7662cfcf62SDimitry Andric   DenseMap<uint64_t, uint32_t> OffsetRemapping;
7762cfcf62SDimitry Andric 
7862cfcf62SDimitry Andric   DataExtractor Data(CurStrSection, true, 0);
7962cfcf62SDimitry Andric   uint64_t LocalOffset = 0;
8062cfcf62SDimitry Andric   uint64_t PrevOffset = 0;
8162cfcf62SDimitry Andric   while (const char *s = Data.getCStr(&LocalOffset)) {
8262cfcf62SDimitry Andric     OffsetRemapping[PrevOffset] =
8362cfcf62SDimitry Andric         Strings.getOffset(s, LocalOffset - PrevOffset);
8462cfcf62SDimitry Andric     PrevOffset = LocalOffset;
8562cfcf62SDimitry Andric   }
8662cfcf62SDimitry Andric 
8762cfcf62SDimitry Andric   Data = DataExtractor(CurStrOffsetSection, true, 0);
8862cfcf62SDimitry Andric 
8962cfcf62SDimitry Andric   Out.SwitchSection(StrOffsetSection);
9062cfcf62SDimitry Andric 
9162cfcf62SDimitry Andric   uint64_t Offset = 0;
9262cfcf62SDimitry Andric   uint64_t Size = CurStrOffsetSection.size();
9362cfcf62SDimitry Andric   while (Offset < Size) {
9462cfcf62SDimitry Andric     auto OldOffset = Data.getU32(&Offset);
9562cfcf62SDimitry Andric     auto NewOffset = OffsetRemapping[OldOffset];
965ffd83dbSDimitry Andric     Out.emitIntValue(NewOffset, 4);
9762cfcf62SDimitry Andric   }
9862cfcf62SDimitry Andric }
9962cfcf62SDimitry Andric 
10062cfcf62SDimitry Andric static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) {
10162cfcf62SDimitry Andric   uint64_t CurCode;
10262cfcf62SDimitry Andric   uint64_t Offset = 0;
10362cfcf62SDimitry Andric   DataExtractor AbbrevData(Abbrev, true, 0);
10462cfcf62SDimitry Andric   while ((CurCode = AbbrevData.getULEB128(&Offset)) != AbbrCode) {
10562cfcf62SDimitry Andric     // Tag
10662cfcf62SDimitry Andric     AbbrevData.getULEB128(&Offset);
10762cfcf62SDimitry Andric     // DW_CHILDREN
10862cfcf62SDimitry Andric     AbbrevData.getU8(&Offset);
10962cfcf62SDimitry Andric     // Attributes
11062cfcf62SDimitry Andric     while (AbbrevData.getULEB128(&Offset) | AbbrevData.getULEB128(&Offset))
11162cfcf62SDimitry Andric       ;
11262cfcf62SDimitry Andric   }
11362cfcf62SDimitry Andric   return Offset;
11462cfcf62SDimitry Andric }
11562cfcf62SDimitry Andric 
11662cfcf62SDimitry Andric struct CompileUnitIdentifiers {
11762cfcf62SDimitry Andric   uint64_t Signature = 0;
11862cfcf62SDimitry Andric   const char *Name = "";
11962cfcf62SDimitry Andric   const char *DWOName = "";
12062cfcf62SDimitry Andric };
12162cfcf62SDimitry Andric 
12262cfcf62SDimitry Andric static Expected<const char *>
12362cfcf62SDimitry Andric getIndexedString(dwarf::Form Form, DataExtractor InfoData,
12462cfcf62SDimitry Andric                  uint64_t &InfoOffset, StringRef StrOffsets, StringRef Str) {
12562cfcf62SDimitry Andric   if (Form == dwarf::DW_FORM_string)
12662cfcf62SDimitry Andric     return InfoData.getCStr(&InfoOffset);
12762cfcf62SDimitry Andric   if (Form != dwarf::DW_FORM_GNU_str_index)
12862cfcf62SDimitry Andric     return make_error<DWPError>(
12962cfcf62SDimitry Andric         "string field encoded without DW_FORM_string or DW_FORM_GNU_str_index");
13062cfcf62SDimitry Andric   auto StrIndex = InfoData.getULEB128(&InfoOffset);
13162cfcf62SDimitry Andric   DataExtractor StrOffsetsData(StrOffsets, true, 0);
13262cfcf62SDimitry Andric   uint64_t StrOffsetsOffset = 4 * StrIndex;
13362cfcf62SDimitry Andric   uint64_t StrOffset = StrOffsetsData.getU32(&StrOffsetsOffset);
13462cfcf62SDimitry Andric   DataExtractor StrData(Str, true, 0);
13562cfcf62SDimitry Andric   return StrData.getCStr(&StrOffset);
13662cfcf62SDimitry Andric }
13762cfcf62SDimitry Andric 
13862cfcf62SDimitry Andric static Expected<CompileUnitIdentifiers> getCUIdentifiers(StringRef Abbrev,
13962cfcf62SDimitry Andric                                                          StringRef Info,
14062cfcf62SDimitry Andric                                                          StringRef StrOffsets,
14162cfcf62SDimitry Andric                                                          StringRef Str) {
14262cfcf62SDimitry Andric   uint64_t Offset = 0;
14362cfcf62SDimitry Andric   DataExtractor InfoData(Info, true, 0);
14462cfcf62SDimitry Andric   dwarf::DwarfFormat Format = dwarf::DwarfFormat::DWARF32;
14562cfcf62SDimitry Andric   uint64_t Length = InfoData.getU32(&Offset);
1465ffd83dbSDimitry Andric   CompileUnitIdentifiers ID;
1475ffd83dbSDimitry Andric   Optional<uint64_t> Signature = None;
14862cfcf62SDimitry Andric   // If the length is 0xffffffff, then this indictes that this is a DWARF 64
14962cfcf62SDimitry Andric   // stream and the length is actually encoded into a 64 bit value that follows.
15062cfcf62SDimitry Andric   if (Length == 0xffffffffU) {
15162cfcf62SDimitry Andric     Format = dwarf::DwarfFormat::DWARF64;
15262cfcf62SDimitry Andric     Length = InfoData.getU64(&Offset);
15362cfcf62SDimitry Andric   }
15462cfcf62SDimitry Andric   uint16_t Version = InfoData.getU16(&Offset);
1555ffd83dbSDimitry Andric   if (Version >= 5) {
1565ffd83dbSDimitry Andric     auto UnitType = InfoData.getU8(&Offset);
1575ffd83dbSDimitry Andric     if (UnitType != dwarf::DW_UT_split_compile)
1585ffd83dbSDimitry Andric       return make_error<DWPError>(
1595ffd83dbSDimitry Andric           std::string("unit type DW_UT_split_compile type not found in "
1605ffd83dbSDimitry Andric                       "debug_info header. Unexpected unit type 0x" +
1615ffd83dbSDimitry Andric                       utostr(UnitType) + " found"));
1625ffd83dbSDimitry Andric   }
16362cfcf62SDimitry Andric   InfoData.getU32(&Offset); // Abbrev offset (should be zero)
16462cfcf62SDimitry Andric   uint8_t AddrSize = InfoData.getU8(&Offset);
1655ffd83dbSDimitry Andric   if (Version >= 5)
1665ffd83dbSDimitry Andric     Signature = InfoData.getU64(&Offset);
16762cfcf62SDimitry Andric   uint32_t AbbrCode = InfoData.getULEB128(&Offset);
16862cfcf62SDimitry Andric 
16962cfcf62SDimitry Andric   DataExtractor AbbrevData(Abbrev, true, 0);
17062cfcf62SDimitry Andric   uint64_t AbbrevOffset = getCUAbbrev(Abbrev, AbbrCode);
17162cfcf62SDimitry Andric   auto Tag = static_cast<dwarf::Tag>(AbbrevData.getULEB128(&AbbrevOffset));
17262cfcf62SDimitry Andric   if (Tag != dwarf::DW_TAG_compile_unit)
17362cfcf62SDimitry Andric     return make_error<DWPError>("top level DIE is not a compile unit");
17462cfcf62SDimitry Andric   // DW_CHILDREN
17562cfcf62SDimitry Andric   AbbrevData.getU8(&AbbrevOffset);
17662cfcf62SDimitry Andric   uint32_t Name;
17762cfcf62SDimitry Andric   dwarf::Form Form;
17862cfcf62SDimitry Andric   while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) |
17962cfcf62SDimitry Andric          (Form = static_cast<dwarf::Form>(AbbrevData.getULEB128(&AbbrevOffset))) &&
18062cfcf62SDimitry Andric          (Name != 0 || Form != 0)) {
18162cfcf62SDimitry Andric     switch (Name) {
18262cfcf62SDimitry Andric     case dwarf::DW_AT_name: {
18362cfcf62SDimitry Andric       Expected<const char *> EName =
18462cfcf62SDimitry Andric           getIndexedString(Form, InfoData, Offset, StrOffsets, Str);
18562cfcf62SDimitry Andric       if (!EName)
18662cfcf62SDimitry Andric         return EName.takeError();
18762cfcf62SDimitry Andric       ID.Name = *EName;
18862cfcf62SDimitry Andric       break;
18962cfcf62SDimitry Andric     }
1905ffd83dbSDimitry Andric     case dwarf::DW_AT_GNU_dwo_name:
1915ffd83dbSDimitry Andric     case dwarf::DW_AT_dwo_name: {
19262cfcf62SDimitry Andric       Expected<const char *> EName =
19362cfcf62SDimitry Andric           getIndexedString(Form, InfoData, Offset, StrOffsets, Str);
19462cfcf62SDimitry Andric       if (!EName)
19562cfcf62SDimitry Andric         return EName.takeError();
19662cfcf62SDimitry Andric       ID.DWOName = *EName;
19762cfcf62SDimitry Andric       break;
19862cfcf62SDimitry Andric     }
19962cfcf62SDimitry Andric     case dwarf::DW_AT_GNU_dwo_id:
20062cfcf62SDimitry Andric       Signature = InfoData.getU64(&Offset);
20162cfcf62SDimitry Andric       break;
20262cfcf62SDimitry Andric     default:
20362cfcf62SDimitry Andric       DWARFFormValue::skipValue(Form, InfoData, &Offset,
20462cfcf62SDimitry Andric                                 dwarf::FormParams({Version, AddrSize, Format}));
20562cfcf62SDimitry Andric     }
20662cfcf62SDimitry Andric   }
20762cfcf62SDimitry Andric   if (!Signature)
20862cfcf62SDimitry Andric     return make_error<DWPError>("compile unit missing dwo_id");
20962cfcf62SDimitry Andric   ID.Signature = *Signature;
21062cfcf62SDimitry Andric   return ID;
21162cfcf62SDimitry Andric }
21262cfcf62SDimitry Andric 
21362cfcf62SDimitry Andric struct UnitIndexEntry {
21462cfcf62SDimitry Andric   DWARFUnitIndex::Entry::SectionContribution Contributions[8];
21562cfcf62SDimitry Andric   std::string Name;
21662cfcf62SDimitry Andric   std::string DWOName;
21762cfcf62SDimitry Andric   StringRef DWPName;
21862cfcf62SDimitry Andric };
21962cfcf62SDimitry Andric 
2205ffd83dbSDimitry Andric static bool isSupportedSectionKind(DWARFSectionKind Kind) {
2215ffd83dbSDimitry Andric   return Kind != DW_SECT_EXT_unknown;
2225ffd83dbSDimitry Andric }
2235ffd83dbSDimitry Andric 
2245ffd83dbSDimitry Andric // Convert an internal section identifier into the index to use with
2255ffd83dbSDimitry Andric // UnitIndexEntry::Contributions.
2265ffd83dbSDimitry Andric static unsigned getContributionIndex(DWARFSectionKind Kind) {
2275ffd83dbSDimitry Andric   // Assuming the pre-standard DWP format.
2285ffd83dbSDimitry Andric   assert(serializeSectionKind(Kind, 2) >= DW_SECT_INFO);
2295ffd83dbSDimitry Andric   return serializeSectionKind(Kind, 2) - DW_SECT_INFO;
2305ffd83dbSDimitry Andric }
2315ffd83dbSDimitry Andric 
2325ffd83dbSDimitry Andric // Convert a UnitIndexEntry::Contributions index to the corresponding on-disk
2335ffd83dbSDimitry Andric // value of the section identifier.
2345ffd83dbSDimitry Andric static unsigned getOnDiskSectionId(unsigned Index) {
2355ffd83dbSDimitry Andric   return Index + DW_SECT_INFO;
2365ffd83dbSDimitry Andric }
2375ffd83dbSDimitry Andric 
23862cfcf62SDimitry Andric static StringRef getSubsection(StringRef Section,
23962cfcf62SDimitry Andric                                const DWARFUnitIndex::Entry &Entry,
24062cfcf62SDimitry Andric                                DWARFSectionKind Kind) {
2415ffd83dbSDimitry Andric   const auto *Off = Entry.getContribution(Kind);
24262cfcf62SDimitry Andric   if (!Off)
24362cfcf62SDimitry Andric     return StringRef();
24462cfcf62SDimitry Andric   return Section.substr(Off->Offset, Off->Length);
24562cfcf62SDimitry Andric }
24662cfcf62SDimitry Andric 
24762cfcf62SDimitry Andric static void addAllTypesFromDWP(
24862cfcf62SDimitry Andric     MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
24962cfcf62SDimitry Andric     const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types,
25062cfcf62SDimitry Andric     const UnitIndexEntry &TUEntry, uint32_t &TypesOffset) {
25162cfcf62SDimitry Andric   Out.SwitchSection(OutputTypes);
25262cfcf62SDimitry Andric   for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) {
2535ffd83dbSDimitry Andric     auto *I = E.getContributions();
25462cfcf62SDimitry Andric     if (!I)
25562cfcf62SDimitry Andric       continue;
25662cfcf62SDimitry Andric     auto P = TypeIndexEntries.insert(std::make_pair(E.getSignature(), TUEntry));
25762cfcf62SDimitry Andric     if (!P.second)
25862cfcf62SDimitry Andric       continue;
25962cfcf62SDimitry Andric     auto &Entry = P.first->second;
26062cfcf62SDimitry Andric     // Zero out the debug_info contribution
26162cfcf62SDimitry Andric     Entry.Contributions[0] = {};
26262cfcf62SDimitry Andric     for (auto Kind : TUIndex.getColumnKinds()) {
2635ffd83dbSDimitry Andric       if (!isSupportedSectionKind(Kind))
2645ffd83dbSDimitry Andric         continue;
2655ffd83dbSDimitry Andric       auto &C = Entry.Contributions[getContributionIndex(Kind)];
26662cfcf62SDimitry Andric       C.Offset += I->Offset;
26762cfcf62SDimitry Andric       C.Length = I->Length;
26862cfcf62SDimitry Andric       ++I;
26962cfcf62SDimitry Andric     }
2705ffd83dbSDimitry Andric     unsigned TypesIndex = getContributionIndex(DW_SECT_EXT_TYPES);
2715ffd83dbSDimitry Andric     auto &C = Entry.Contributions[TypesIndex];
2725ffd83dbSDimitry Andric     Out.emitBytes(Types.substr(
2735ffd83dbSDimitry Andric         C.Offset - TUEntry.Contributions[TypesIndex].Offset, C.Length));
27462cfcf62SDimitry Andric     C.Offset = TypesOffset;
27562cfcf62SDimitry Andric     TypesOffset += C.Length;
27662cfcf62SDimitry Andric   }
27762cfcf62SDimitry Andric }
27862cfcf62SDimitry Andric 
27962cfcf62SDimitry Andric static void addAllTypes(MCStreamer &Out,
28062cfcf62SDimitry Andric                         MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
28162cfcf62SDimitry Andric                         MCSection *OutputTypes,
28262cfcf62SDimitry Andric                         const std::vector<StringRef> &TypesSections,
28362cfcf62SDimitry Andric                         const UnitIndexEntry &CUEntry, uint32_t &TypesOffset) {
28462cfcf62SDimitry Andric   for (StringRef Types : TypesSections) {
28562cfcf62SDimitry Andric     Out.SwitchSection(OutputTypes);
28662cfcf62SDimitry Andric     uint64_t Offset = 0;
28762cfcf62SDimitry Andric     DataExtractor Data(Types, true, 0);
28862cfcf62SDimitry Andric     while (Data.isValidOffset(Offset)) {
28962cfcf62SDimitry Andric       UnitIndexEntry Entry = CUEntry;
29062cfcf62SDimitry Andric       // Zero out the debug_info contribution
29162cfcf62SDimitry Andric       Entry.Contributions[0] = {};
2925ffd83dbSDimitry Andric       auto &C = Entry.Contributions[getContributionIndex(DW_SECT_EXT_TYPES)];
29362cfcf62SDimitry Andric       C.Offset = TypesOffset;
29462cfcf62SDimitry Andric       auto PrevOffset = Offset;
29562cfcf62SDimitry Andric       // Length of the unit, including the 4 byte length field.
29662cfcf62SDimitry Andric       C.Length = Data.getU32(&Offset) + 4;
29762cfcf62SDimitry Andric 
29862cfcf62SDimitry Andric       Data.getU16(&Offset); // Version
29962cfcf62SDimitry Andric       Data.getU32(&Offset); // Abbrev offset
30062cfcf62SDimitry Andric       Data.getU8(&Offset);  // Address size
30162cfcf62SDimitry Andric       auto Signature = Data.getU64(&Offset);
30262cfcf62SDimitry Andric       Offset = PrevOffset + C.Length;
30362cfcf62SDimitry Andric 
30462cfcf62SDimitry Andric       auto P = TypeIndexEntries.insert(std::make_pair(Signature, Entry));
30562cfcf62SDimitry Andric       if (!P.second)
30662cfcf62SDimitry Andric         continue;
30762cfcf62SDimitry Andric 
3085ffd83dbSDimitry Andric       Out.emitBytes(Types.substr(PrevOffset, C.Length));
30962cfcf62SDimitry Andric       TypesOffset += C.Length;
31062cfcf62SDimitry Andric     }
31162cfcf62SDimitry Andric   }
31262cfcf62SDimitry Andric }
31362cfcf62SDimitry Andric 
31462cfcf62SDimitry Andric static void
31562cfcf62SDimitry Andric writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
31662cfcf62SDimitry Andric                 const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
31762cfcf62SDimitry Andric                 uint32_t DWARFUnitIndex::Entry::SectionContribution::*Field) {
31862cfcf62SDimitry Andric   for (const auto &E : IndexEntries)
31962cfcf62SDimitry Andric     for (size_t i = 0; i != array_lengthof(E.second.Contributions); ++i)
32062cfcf62SDimitry Andric       if (ContributionOffsets[i])
3215ffd83dbSDimitry Andric         Out.emitIntValue(E.second.Contributions[i].*Field, 4);
32262cfcf62SDimitry Andric }
32362cfcf62SDimitry Andric 
32462cfcf62SDimitry Andric static void
32562cfcf62SDimitry Andric writeIndex(MCStreamer &Out, MCSection *Section,
32662cfcf62SDimitry Andric            ArrayRef<unsigned> ContributionOffsets,
32762cfcf62SDimitry Andric            const MapVector<uint64_t, UnitIndexEntry> &IndexEntries) {
32862cfcf62SDimitry Andric   if (IndexEntries.empty())
32962cfcf62SDimitry Andric     return;
33062cfcf62SDimitry Andric 
33162cfcf62SDimitry Andric   unsigned Columns = 0;
33262cfcf62SDimitry Andric   for (auto &C : ContributionOffsets)
33362cfcf62SDimitry Andric     if (C)
33462cfcf62SDimitry Andric       ++Columns;
33562cfcf62SDimitry Andric 
33662cfcf62SDimitry Andric   std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
33762cfcf62SDimitry Andric   uint64_t Mask = Buckets.size() - 1;
33862cfcf62SDimitry Andric   size_t i = 0;
33962cfcf62SDimitry Andric   for (const auto &P : IndexEntries) {
34062cfcf62SDimitry Andric     auto S = P.first;
34162cfcf62SDimitry Andric     auto H = S & Mask;
34262cfcf62SDimitry Andric     auto HP = ((S >> 32) & Mask) | 1;
34362cfcf62SDimitry Andric     while (Buckets[H]) {
34462cfcf62SDimitry Andric       assert(S != IndexEntries.begin()[Buckets[H] - 1].first &&
34562cfcf62SDimitry Andric              "Duplicate unit");
34662cfcf62SDimitry Andric       H = (H + HP) & Mask;
34762cfcf62SDimitry Andric     }
34862cfcf62SDimitry Andric     Buckets[H] = i + 1;
34962cfcf62SDimitry Andric     ++i;
35062cfcf62SDimitry Andric   }
35162cfcf62SDimitry Andric 
35262cfcf62SDimitry Andric   Out.SwitchSection(Section);
3535ffd83dbSDimitry Andric   Out.emitIntValue(2, 4);                   // Version
3545ffd83dbSDimitry Andric   Out.emitIntValue(Columns, 4);             // Columns
3555ffd83dbSDimitry Andric   Out.emitIntValue(IndexEntries.size(), 4); // Num Units
3565ffd83dbSDimitry Andric   Out.emitIntValue(Buckets.size(), 4);      // Num Buckets
35762cfcf62SDimitry Andric 
35862cfcf62SDimitry Andric   // Write the signatures.
35962cfcf62SDimitry Andric   for (const auto &I : Buckets)
3605ffd83dbSDimitry Andric     Out.emitIntValue(I ? IndexEntries.begin()[I - 1].first : 0, 8);
36162cfcf62SDimitry Andric 
36262cfcf62SDimitry Andric   // Write the indexes.
36362cfcf62SDimitry Andric   for (const auto &I : Buckets)
3645ffd83dbSDimitry Andric     Out.emitIntValue(I, 4);
36562cfcf62SDimitry Andric 
36662cfcf62SDimitry Andric   // Write the column headers (which sections will appear in the table)
36762cfcf62SDimitry Andric   for (size_t i = 0; i != ContributionOffsets.size(); ++i)
36862cfcf62SDimitry Andric     if (ContributionOffsets[i])
3695ffd83dbSDimitry Andric       Out.emitIntValue(getOnDiskSectionId(i), 4);
37062cfcf62SDimitry Andric 
37162cfcf62SDimitry Andric   // Write the offsets.
37262cfcf62SDimitry Andric   writeIndexTable(Out, ContributionOffsets, IndexEntries,
37362cfcf62SDimitry Andric                   &DWARFUnitIndex::Entry::SectionContribution::Offset);
37462cfcf62SDimitry Andric 
37562cfcf62SDimitry Andric   // Write the lengths.
37662cfcf62SDimitry Andric   writeIndexTable(Out, ContributionOffsets, IndexEntries,
37762cfcf62SDimitry Andric                   &DWARFUnitIndex::Entry::SectionContribution::Length);
37862cfcf62SDimitry Andric }
37962cfcf62SDimitry Andric 
380e8d8bef9SDimitry Andric static std::string buildDWODescription(StringRef Name, StringRef DWPName,
381e8d8bef9SDimitry Andric                                        StringRef DWOName) {
38262cfcf62SDimitry Andric   std::string Text = "\'";
38362cfcf62SDimitry Andric   Text += Name;
38462cfcf62SDimitry Andric   Text += '\'';
38562cfcf62SDimitry Andric   if (!DWPName.empty()) {
38662cfcf62SDimitry Andric     Text += " (from ";
38762cfcf62SDimitry Andric     if (!DWOName.empty()) {
38862cfcf62SDimitry Andric       Text += '\'';
38962cfcf62SDimitry Andric       Text += DWOName;
39062cfcf62SDimitry Andric       Text += "' in ";
39162cfcf62SDimitry Andric     }
39262cfcf62SDimitry Andric     Text += '\'';
39362cfcf62SDimitry Andric     Text += DWPName;
39462cfcf62SDimitry Andric     Text += "')";
39562cfcf62SDimitry Andric   }
39662cfcf62SDimitry Andric   return Text;
39762cfcf62SDimitry Andric }
39862cfcf62SDimitry Andric 
39962cfcf62SDimitry Andric static Error createError(StringRef Name, Error E) {
40062cfcf62SDimitry Andric   return make_error<DWPError>(
40162cfcf62SDimitry Andric       ("failure while decompressing compressed section: '" + Name + "', " +
40262cfcf62SDimitry Andric        llvm::toString(std::move(E)))
40362cfcf62SDimitry Andric           .str());
40462cfcf62SDimitry Andric }
40562cfcf62SDimitry Andric 
40662cfcf62SDimitry Andric static Error
40762cfcf62SDimitry Andric handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections,
40862cfcf62SDimitry Andric                         StringRef &Name, StringRef &Contents) {
40962cfcf62SDimitry Andric   if (!Decompressor::isGnuStyle(Name))
41062cfcf62SDimitry Andric     return Error::success();
41162cfcf62SDimitry Andric 
41262cfcf62SDimitry Andric   Expected<Decompressor> Dec =
41362cfcf62SDimitry Andric       Decompressor::create(Name, Contents, false /*IsLE*/, false /*Is64Bit*/);
41462cfcf62SDimitry Andric   if (!Dec)
41562cfcf62SDimitry Andric     return createError(Name, Dec.takeError());
41662cfcf62SDimitry Andric 
41762cfcf62SDimitry Andric   UncompressedSections.emplace_back();
41862cfcf62SDimitry Andric   if (Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
41962cfcf62SDimitry Andric     return createError(Name, std::move(E));
42062cfcf62SDimitry Andric 
42162cfcf62SDimitry Andric   Name = Name.substr(2); // Drop ".z"
42262cfcf62SDimitry Andric   Contents = UncompressedSections.back();
42362cfcf62SDimitry Andric   return Error::success();
42462cfcf62SDimitry Andric }
42562cfcf62SDimitry Andric 
42662cfcf62SDimitry Andric static Error handleSection(
42762cfcf62SDimitry Andric     const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
42862cfcf62SDimitry Andric     const MCSection *StrSection, const MCSection *StrOffsetSection,
42962cfcf62SDimitry Andric     const MCSection *TypesSection, const MCSection *CUIndexSection,
43062cfcf62SDimitry Andric     const MCSection *TUIndexSection, const SectionRef &Section, MCStreamer &Out,
43162cfcf62SDimitry Andric     std::deque<SmallString<32>> &UncompressedSections,
43262cfcf62SDimitry Andric     uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry,
43362cfcf62SDimitry Andric     StringRef &CurStrSection, StringRef &CurStrOffsetSection,
43462cfcf62SDimitry Andric     std::vector<StringRef> &CurTypesSection, StringRef &InfoSection,
43562cfcf62SDimitry Andric     StringRef &AbbrevSection, StringRef &CurCUIndexSection,
43662cfcf62SDimitry Andric     StringRef &CurTUIndexSection) {
43762cfcf62SDimitry Andric   if (Section.isBSS())
43862cfcf62SDimitry Andric     return Error::success();
43962cfcf62SDimitry Andric 
44062cfcf62SDimitry Andric   if (Section.isVirtual())
44162cfcf62SDimitry Andric     return Error::success();
44262cfcf62SDimitry Andric 
44362cfcf62SDimitry Andric   Expected<StringRef> NameOrErr = Section.getName();
44462cfcf62SDimitry Andric   if (!NameOrErr)
44562cfcf62SDimitry Andric     return NameOrErr.takeError();
44662cfcf62SDimitry Andric   StringRef Name = *NameOrErr;
44762cfcf62SDimitry Andric 
44862cfcf62SDimitry Andric   Expected<StringRef> ContentsOrErr = Section.getContents();
44962cfcf62SDimitry Andric   if (!ContentsOrErr)
45062cfcf62SDimitry Andric     return ContentsOrErr.takeError();
45162cfcf62SDimitry Andric   StringRef Contents = *ContentsOrErr;
45262cfcf62SDimitry Andric 
45362cfcf62SDimitry Andric   if (auto Err = handleCompressedSection(UncompressedSections, Name, Contents))
45462cfcf62SDimitry Andric     return Err;
45562cfcf62SDimitry Andric 
45662cfcf62SDimitry Andric   Name = Name.substr(Name.find_first_not_of("._"));
45762cfcf62SDimitry Andric 
45862cfcf62SDimitry Andric   auto SectionPair = KnownSections.find(Name);
45962cfcf62SDimitry Andric   if (SectionPair == KnownSections.end())
46062cfcf62SDimitry Andric     return Error::success();
46162cfcf62SDimitry Andric 
46262cfcf62SDimitry Andric   if (DWARFSectionKind Kind = SectionPair->second.second) {
4635ffd83dbSDimitry Andric     auto Index = getContributionIndex(Kind);
4645ffd83dbSDimitry Andric     if (Kind != DW_SECT_EXT_TYPES) {
46562cfcf62SDimitry Andric       CurEntry.Contributions[Index].Offset = ContributionOffsets[Index];
46662cfcf62SDimitry Andric       ContributionOffsets[Index] +=
46762cfcf62SDimitry Andric           (CurEntry.Contributions[Index].Length = Contents.size());
46862cfcf62SDimitry Andric     }
46962cfcf62SDimitry Andric 
47062cfcf62SDimitry Andric     switch (Kind) {
47162cfcf62SDimitry Andric     case DW_SECT_INFO:
47262cfcf62SDimitry Andric       InfoSection = Contents;
47362cfcf62SDimitry Andric       break;
47462cfcf62SDimitry Andric     case DW_SECT_ABBREV:
47562cfcf62SDimitry Andric       AbbrevSection = Contents;
47662cfcf62SDimitry Andric       break;
47762cfcf62SDimitry Andric     default:
47862cfcf62SDimitry Andric       break;
47962cfcf62SDimitry Andric     }
48062cfcf62SDimitry Andric   }
48162cfcf62SDimitry Andric 
48262cfcf62SDimitry Andric   MCSection *OutSection = SectionPair->second.first;
48362cfcf62SDimitry Andric   if (OutSection == StrOffsetSection)
48462cfcf62SDimitry Andric     CurStrOffsetSection = Contents;
48562cfcf62SDimitry Andric   else if (OutSection == StrSection)
48662cfcf62SDimitry Andric     CurStrSection = Contents;
48762cfcf62SDimitry Andric   else if (OutSection == TypesSection)
48862cfcf62SDimitry Andric     CurTypesSection.push_back(Contents);
48962cfcf62SDimitry Andric   else if (OutSection == CUIndexSection)
49062cfcf62SDimitry Andric     CurCUIndexSection = Contents;
49162cfcf62SDimitry Andric   else if (OutSection == TUIndexSection)
49262cfcf62SDimitry Andric     CurTUIndexSection = Contents;
49362cfcf62SDimitry Andric   else {
49462cfcf62SDimitry Andric     Out.SwitchSection(OutSection);
4955ffd83dbSDimitry Andric     Out.emitBytes(Contents);
49662cfcf62SDimitry Andric   }
49762cfcf62SDimitry Andric   return Error::success();
49862cfcf62SDimitry Andric }
49962cfcf62SDimitry Andric 
50062cfcf62SDimitry Andric static Error
50162cfcf62SDimitry Andric buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
50262cfcf62SDimitry Andric                     const CompileUnitIdentifiers &ID, StringRef DWPName) {
50362cfcf62SDimitry Andric   return make_error<DWPError>(
5045ffd83dbSDimitry Andric       std::string("duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " +
50562cfcf62SDimitry Andric       buildDWODescription(PrevE.second.Name, PrevE.second.DWPName,
50662cfcf62SDimitry Andric                           PrevE.second.DWOName) +
50762cfcf62SDimitry Andric       " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));
50862cfcf62SDimitry Andric }
50962cfcf62SDimitry Andric 
51062cfcf62SDimitry Andric static Expected<SmallVector<std::string, 16>>
51162cfcf62SDimitry Andric getDWOFilenames(StringRef ExecFilename) {
51262cfcf62SDimitry Andric   auto ErrOrObj = object::ObjectFile::createObjectFile(ExecFilename);
51362cfcf62SDimitry Andric   if (!ErrOrObj)
51462cfcf62SDimitry Andric     return ErrOrObj.takeError();
51562cfcf62SDimitry Andric 
51662cfcf62SDimitry Andric   const ObjectFile &Obj = *ErrOrObj.get().getBinary();
51762cfcf62SDimitry Andric   std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj);
51862cfcf62SDimitry Andric 
51962cfcf62SDimitry Andric   SmallVector<std::string, 16> DWOPaths;
52062cfcf62SDimitry Andric   for (const auto &CU : DWARFCtx->compile_units()) {
52162cfcf62SDimitry Andric     const DWARFDie &Die = CU->getUnitDIE();
52262cfcf62SDimitry Andric     std::string DWOName = dwarf::toString(
52362cfcf62SDimitry Andric         Die.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
52462cfcf62SDimitry Andric     if (DWOName.empty())
52562cfcf62SDimitry Andric       continue;
52662cfcf62SDimitry Andric     std::string DWOCompDir =
52762cfcf62SDimitry Andric         dwarf::toString(Die.find(dwarf::DW_AT_comp_dir), "");
52862cfcf62SDimitry Andric     if (!DWOCompDir.empty()) {
529*d409305fSDimitry Andric       SmallString<16> DWOPath(std::move(DWOName));
530*d409305fSDimitry Andric       sys::fs::make_absolute(DWOCompDir, DWOPath);
53162cfcf62SDimitry Andric       DWOPaths.emplace_back(DWOPath.data(), DWOPath.size());
53262cfcf62SDimitry Andric     } else {
53362cfcf62SDimitry Andric       DWOPaths.push_back(std::move(DWOName));
53462cfcf62SDimitry Andric     }
53562cfcf62SDimitry Andric   }
53662cfcf62SDimitry Andric   return std::move(DWOPaths);
53762cfcf62SDimitry Andric }
53862cfcf62SDimitry Andric 
53962cfcf62SDimitry Andric static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
54062cfcf62SDimitry Andric   const auto &MCOFI = *Out.getContext().getObjectFileInfo();
54162cfcf62SDimitry Andric   MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
54262cfcf62SDimitry Andric   MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
54362cfcf62SDimitry Andric   MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection();
54462cfcf62SDimitry Andric   MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection();
54562cfcf62SDimitry Andric   MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection();
54662cfcf62SDimitry Andric   const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = {
54762cfcf62SDimitry Andric       {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}},
5485ffd83dbSDimitry Andric       {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},
54962cfcf62SDimitry Andric       {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
55062cfcf62SDimitry Andric       {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}},
5515ffd83dbSDimitry Andric       {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},
55262cfcf62SDimitry Andric       {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
55362cfcf62SDimitry Andric       {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
55462cfcf62SDimitry Andric       {"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}},
55562cfcf62SDimitry Andric       {"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};
55662cfcf62SDimitry Andric 
55762cfcf62SDimitry Andric   MapVector<uint64_t, UnitIndexEntry> IndexEntries;
55862cfcf62SDimitry Andric   MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
55962cfcf62SDimitry Andric 
56062cfcf62SDimitry Andric   uint32_t ContributionOffsets[8] = {};
56162cfcf62SDimitry Andric 
56262cfcf62SDimitry Andric   DWPStringPool Strings(Out, StrSection);
56362cfcf62SDimitry Andric 
56462cfcf62SDimitry Andric   SmallVector<OwningBinary<object::ObjectFile>, 128> Objects;
56562cfcf62SDimitry Andric   Objects.reserve(Inputs.size());
56662cfcf62SDimitry Andric 
56762cfcf62SDimitry Andric   std::deque<SmallString<32>> UncompressedSections;
56862cfcf62SDimitry Andric 
56962cfcf62SDimitry Andric   for (const auto &Input : Inputs) {
57062cfcf62SDimitry Andric     auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
57162cfcf62SDimitry Andric     if (!ErrOrObj)
57262cfcf62SDimitry Andric       return ErrOrObj.takeError();
57362cfcf62SDimitry Andric 
57462cfcf62SDimitry Andric     auto &Obj = *ErrOrObj->getBinary();
57562cfcf62SDimitry Andric     Objects.push_back(std::move(*ErrOrObj));
57662cfcf62SDimitry Andric 
57762cfcf62SDimitry Andric     UnitIndexEntry CurEntry = {};
57862cfcf62SDimitry Andric 
57962cfcf62SDimitry Andric     StringRef CurStrSection;
58062cfcf62SDimitry Andric     StringRef CurStrOffsetSection;
58162cfcf62SDimitry Andric     std::vector<StringRef> CurTypesSection;
58262cfcf62SDimitry Andric     StringRef InfoSection;
58362cfcf62SDimitry Andric     StringRef AbbrevSection;
58462cfcf62SDimitry Andric     StringRef CurCUIndexSection;
58562cfcf62SDimitry Andric     StringRef CurTUIndexSection;
58662cfcf62SDimitry Andric 
58762cfcf62SDimitry Andric     for (const auto &Section : Obj.sections())
58862cfcf62SDimitry Andric       if (auto Err = handleSection(
58962cfcf62SDimitry Andric               KnownSections, StrSection, StrOffsetSection, TypesSection,
59062cfcf62SDimitry Andric               CUIndexSection, TUIndexSection, Section, Out,
59162cfcf62SDimitry Andric               UncompressedSections, ContributionOffsets, CurEntry,
59262cfcf62SDimitry Andric               CurStrSection, CurStrOffsetSection, CurTypesSection, InfoSection,
59362cfcf62SDimitry Andric               AbbrevSection, CurCUIndexSection, CurTUIndexSection))
59462cfcf62SDimitry Andric         return Err;
59562cfcf62SDimitry Andric 
59662cfcf62SDimitry Andric     if (InfoSection.empty())
59762cfcf62SDimitry Andric       continue;
59862cfcf62SDimitry Andric 
59962cfcf62SDimitry Andric     writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection,
60062cfcf62SDimitry Andric                            CurStrOffsetSection);
60162cfcf62SDimitry Andric 
60262cfcf62SDimitry Andric     if (CurCUIndexSection.empty()) {
60362cfcf62SDimitry Andric       Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
60462cfcf62SDimitry Andric           AbbrevSection, InfoSection, CurStrOffsetSection, CurStrSection);
60562cfcf62SDimitry Andric       if (!EID)
60662cfcf62SDimitry Andric         return createFileError(Input, EID.takeError());
60762cfcf62SDimitry Andric       const auto &ID = *EID;
60862cfcf62SDimitry Andric       auto P = IndexEntries.insert(std::make_pair(ID.Signature, CurEntry));
60962cfcf62SDimitry Andric       if (!P.second)
61062cfcf62SDimitry Andric         return buildDuplicateError(*P.first, ID, "");
61162cfcf62SDimitry Andric       P.first->second.Name = ID.Name;
61262cfcf62SDimitry Andric       P.first->second.DWOName = ID.DWOName;
61362cfcf62SDimitry Andric       addAllTypes(Out, TypeIndexEntries, TypesSection, CurTypesSection,
6145ffd83dbSDimitry Andric                   CurEntry,
6155ffd83dbSDimitry Andric                   ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]);
61662cfcf62SDimitry Andric       continue;
61762cfcf62SDimitry Andric     }
61862cfcf62SDimitry Andric 
61962cfcf62SDimitry Andric     DWARFUnitIndex CUIndex(DW_SECT_INFO);
62062cfcf62SDimitry Andric     DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
62162cfcf62SDimitry Andric     if (!CUIndex.parse(CUIndexData))
6225ffd83dbSDimitry Andric       return make_error<DWPError>("failed to parse cu_index");
6235ffd83dbSDimitry Andric     if (CUIndex.getVersion() != 2)
6245ffd83dbSDimitry Andric       return make_error<DWPError>(
6255ffd83dbSDimitry Andric           "unsupported cu_index version: " + utostr(CUIndex.getVersion()) +
6265ffd83dbSDimitry Andric           " (only version 2 is supported)");
62762cfcf62SDimitry Andric 
62862cfcf62SDimitry Andric     for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
6295ffd83dbSDimitry Andric       auto *I = E.getContributions();
63062cfcf62SDimitry Andric       if (!I)
63162cfcf62SDimitry Andric         continue;
63262cfcf62SDimitry Andric       auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry));
63362cfcf62SDimitry Andric       Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
63462cfcf62SDimitry Andric           getSubsection(AbbrevSection, E, DW_SECT_ABBREV),
63562cfcf62SDimitry Andric           getSubsection(InfoSection, E, DW_SECT_INFO),
63662cfcf62SDimitry Andric           getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS),
63762cfcf62SDimitry Andric           CurStrSection);
63862cfcf62SDimitry Andric       if (!EID)
63962cfcf62SDimitry Andric         return createFileError(Input, EID.takeError());
64062cfcf62SDimitry Andric       const auto &ID = *EID;
64162cfcf62SDimitry Andric       if (!P.second)
64262cfcf62SDimitry Andric         return buildDuplicateError(*P.first, ID, Input);
64362cfcf62SDimitry Andric       auto &NewEntry = P.first->second;
64462cfcf62SDimitry Andric       NewEntry.Name = ID.Name;
64562cfcf62SDimitry Andric       NewEntry.DWOName = ID.DWOName;
64662cfcf62SDimitry Andric       NewEntry.DWPName = Input;
64762cfcf62SDimitry Andric       for (auto Kind : CUIndex.getColumnKinds()) {
6485ffd83dbSDimitry Andric         if (!isSupportedSectionKind(Kind))
6495ffd83dbSDimitry Andric           continue;
6505ffd83dbSDimitry Andric         auto &C = NewEntry.Contributions[getContributionIndex(Kind)];
65162cfcf62SDimitry Andric         C.Offset += I->Offset;
65262cfcf62SDimitry Andric         C.Length = I->Length;
65362cfcf62SDimitry Andric         ++I;
65462cfcf62SDimitry Andric       }
65562cfcf62SDimitry Andric     }
65662cfcf62SDimitry Andric 
65762cfcf62SDimitry Andric     if (!CurTypesSection.empty()) {
65862cfcf62SDimitry Andric       if (CurTypesSection.size() != 1)
65962cfcf62SDimitry Andric         return make_error<DWPError>("multiple type unit sections in .dwp file");
6605ffd83dbSDimitry Andric       DWARFUnitIndex TUIndex(DW_SECT_EXT_TYPES);
66162cfcf62SDimitry Andric       DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);
66262cfcf62SDimitry Andric       if (!TUIndex.parse(TUIndexData))
6635ffd83dbSDimitry Andric         return make_error<DWPError>("failed to parse tu_index");
6645ffd83dbSDimitry Andric       if (TUIndex.getVersion() != 2)
6655ffd83dbSDimitry Andric         return make_error<DWPError>(
6665ffd83dbSDimitry Andric             "unsupported tu_index version: " + utostr(TUIndex.getVersion()) +
6675ffd83dbSDimitry Andric             " (only version 2 is supported)");
6685ffd83dbSDimitry Andric 
6695ffd83dbSDimitry Andric       addAllTypesFromDWP(
6705ffd83dbSDimitry Andric           Out, TypeIndexEntries, TUIndex, TypesSection, CurTypesSection.front(),
6715ffd83dbSDimitry Andric           CurEntry,
6725ffd83dbSDimitry Andric           ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]);
67362cfcf62SDimitry Andric     }
67462cfcf62SDimitry Andric   }
67562cfcf62SDimitry Andric 
67662cfcf62SDimitry Andric   // Lie about there being no info contributions so the TU index only includes
67762cfcf62SDimitry Andric   // the type unit contribution
67862cfcf62SDimitry Andric   ContributionOffsets[0] = 0;
67962cfcf62SDimitry Andric   writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
68062cfcf62SDimitry Andric              TypeIndexEntries);
68162cfcf62SDimitry Andric 
68262cfcf62SDimitry Andric   // Lie about the type contribution
6835ffd83dbSDimitry Andric   ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)] = 0;
68462cfcf62SDimitry Andric   // Unlie about the info contribution
68562cfcf62SDimitry Andric   ContributionOffsets[0] = 1;
68662cfcf62SDimitry Andric 
68762cfcf62SDimitry Andric   writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
68862cfcf62SDimitry Andric              IndexEntries);
68962cfcf62SDimitry Andric 
69062cfcf62SDimitry Andric   return Error::success();
69162cfcf62SDimitry Andric }
69262cfcf62SDimitry Andric 
69362cfcf62SDimitry Andric static int error(const Twine &Error, const Twine &Context) {
69462cfcf62SDimitry Andric   errs() << Twine("while processing ") + Context + ":\n";
69562cfcf62SDimitry Andric   errs() << Twine("error: ") + Error + "\n";
69662cfcf62SDimitry Andric   return 1;
69762cfcf62SDimitry Andric }
69862cfcf62SDimitry Andric 
699e8d8bef9SDimitry Andric static Expected<Triple> readTargetTriple(StringRef FileName) {
700e8d8bef9SDimitry Andric   auto ErrOrObj = object::ObjectFile::createObjectFile(FileName);
701e8d8bef9SDimitry Andric   if (!ErrOrObj)
702e8d8bef9SDimitry Andric     return ErrOrObj.takeError();
703e8d8bef9SDimitry Andric 
704e8d8bef9SDimitry Andric   return ErrOrObj->getBinary()->makeTriple();
705e8d8bef9SDimitry Andric }
706e8d8bef9SDimitry Andric 
70762cfcf62SDimitry Andric int main(int argc, char **argv) {
70862cfcf62SDimitry Andric   InitLLVM X(argc, argv);
70962cfcf62SDimitry Andric 
71062cfcf62SDimitry Andric   cl::ParseCommandLineOptions(argc, argv, "merge split dwarf (.dwo) files\n");
71162cfcf62SDimitry Andric 
71262cfcf62SDimitry Andric   llvm::InitializeAllTargetInfos();
71362cfcf62SDimitry Andric   llvm::InitializeAllTargetMCs();
71462cfcf62SDimitry Andric   llvm::InitializeAllTargets();
71562cfcf62SDimitry Andric   llvm::InitializeAllAsmPrinters();
71662cfcf62SDimitry Andric 
717e8d8bef9SDimitry Andric   std::vector<std::string> DWOFilenames = InputFiles;
718e8d8bef9SDimitry Andric   for (const auto &ExecFilename : ExecFilenames) {
719e8d8bef9SDimitry Andric     auto DWOs = getDWOFilenames(ExecFilename);
720e8d8bef9SDimitry Andric     if (!DWOs) {
721e8d8bef9SDimitry Andric       logAllUnhandledErrors(DWOs.takeError(), WithColor::error());
722e8d8bef9SDimitry Andric       return 1;
723e8d8bef9SDimitry Andric     }
724e8d8bef9SDimitry Andric     DWOFilenames.insert(DWOFilenames.end(),
725e8d8bef9SDimitry Andric                         std::make_move_iterator(DWOs->begin()),
726e8d8bef9SDimitry Andric                         std::make_move_iterator(DWOs->end()));
727e8d8bef9SDimitry Andric   }
728e8d8bef9SDimitry Andric 
729e8d8bef9SDimitry Andric   if (DWOFilenames.empty())
730e8d8bef9SDimitry Andric     return 0;
731e8d8bef9SDimitry Andric 
73262cfcf62SDimitry Andric   std::string ErrorStr;
73362cfcf62SDimitry Andric   StringRef Context = "dwarf streamer init";
73462cfcf62SDimitry Andric 
735e8d8bef9SDimitry Andric   auto ErrOrTriple = readTargetTriple(DWOFilenames.front());
736e8d8bef9SDimitry Andric   if (!ErrOrTriple) {
737e8d8bef9SDimitry Andric     logAllUnhandledErrors(ErrOrTriple.takeError(), WithColor::error());
738e8d8bef9SDimitry Andric     return 1;
739e8d8bef9SDimitry Andric   }
74062cfcf62SDimitry Andric 
74162cfcf62SDimitry Andric   // Get the target.
74262cfcf62SDimitry Andric   const Target *TheTarget =
743e8d8bef9SDimitry Andric       TargetRegistry::lookupTarget("", *ErrOrTriple, ErrorStr);
74462cfcf62SDimitry Andric   if (!TheTarget)
74562cfcf62SDimitry Andric     return error(ErrorStr, Context);
746e8d8bef9SDimitry Andric   std::string TripleName = ErrOrTriple->getTriple();
74762cfcf62SDimitry Andric 
74862cfcf62SDimitry Andric   // Create all the MC Objects.
74962cfcf62SDimitry Andric   std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
75062cfcf62SDimitry Andric   if (!MRI)
75162cfcf62SDimitry Andric     return error(Twine("no register info for target ") + TripleName, Context);
75262cfcf62SDimitry Andric 
7535ffd83dbSDimitry Andric   MCTargetOptions MCOptions = llvm::mc::InitMCTargetOptionsFromFlags();
75462cfcf62SDimitry Andric   std::unique_ptr<MCAsmInfo> MAI(
75562cfcf62SDimitry Andric       TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
75662cfcf62SDimitry Andric   if (!MAI)
75762cfcf62SDimitry Andric     return error("no asm info for target " + TripleName, Context);
75862cfcf62SDimitry Andric 
75962cfcf62SDimitry Andric   MCObjectFileInfo MOFI;
76062cfcf62SDimitry Andric   MCContext MC(MAI.get(), MRI.get(), &MOFI);
761e8d8bef9SDimitry Andric   MOFI.InitMCObjectFileInfo(*ErrOrTriple, /*PIC*/ false, MC);
76262cfcf62SDimitry Andric 
76362cfcf62SDimitry Andric   std::unique_ptr<MCSubtargetInfo> MSTI(
76462cfcf62SDimitry Andric       TheTarget->createMCSubtargetInfo(TripleName, "", ""));
76562cfcf62SDimitry Andric   if (!MSTI)
76662cfcf62SDimitry Andric     return error("no subtarget info for target " + TripleName, Context);
76762cfcf62SDimitry Andric 
76862cfcf62SDimitry Andric   MCTargetOptions Options;
76962cfcf62SDimitry Andric   auto MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, Options);
77062cfcf62SDimitry Andric   if (!MAB)
77162cfcf62SDimitry Andric     return error("no asm backend for target " + TripleName, Context);
77262cfcf62SDimitry Andric 
77362cfcf62SDimitry Andric   std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
77462cfcf62SDimitry Andric   if (!MII)
77562cfcf62SDimitry Andric     return error("no instr info info for target " + TripleName, Context);
77662cfcf62SDimitry Andric 
77762cfcf62SDimitry Andric   MCCodeEmitter *MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, MC);
77862cfcf62SDimitry Andric   if (!MCE)
77962cfcf62SDimitry Andric     return error("no code emitter for target " + TripleName, Context);
78062cfcf62SDimitry Andric 
78162cfcf62SDimitry Andric   // Create the output file.
78262cfcf62SDimitry Andric   std::error_code EC;
78362cfcf62SDimitry Andric   ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_None);
78462cfcf62SDimitry Andric   Optional<buffer_ostream> BOS;
78562cfcf62SDimitry Andric   raw_pwrite_stream *OS;
78662cfcf62SDimitry Andric   if (EC)
78762cfcf62SDimitry Andric     return error(Twine(OutputFilename) + ": " + EC.message(), Context);
78862cfcf62SDimitry Andric   if (OutFile.os().supportsSeeking()) {
78962cfcf62SDimitry Andric     OS = &OutFile.os();
79062cfcf62SDimitry Andric   } else {
79162cfcf62SDimitry Andric     BOS.emplace(OutFile.os());
79262cfcf62SDimitry Andric     OS = BOS.getPointer();
79362cfcf62SDimitry Andric   }
79462cfcf62SDimitry Andric 
79562cfcf62SDimitry Andric   std::unique_ptr<MCStreamer> MS(TheTarget->createMCObjectStreamer(
796e8d8bef9SDimitry Andric       *ErrOrTriple, MC, std::unique_ptr<MCAsmBackend>(MAB),
79762cfcf62SDimitry Andric       MAB->createObjectWriter(*OS), std::unique_ptr<MCCodeEmitter>(MCE), *MSTI,
79862cfcf62SDimitry Andric       MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
79962cfcf62SDimitry Andric       /*DWARFMustBeAtTheEnd*/ false));
80062cfcf62SDimitry Andric   if (!MS)
80162cfcf62SDimitry Andric     return error("no object streamer for target " + TripleName, Context);
80262cfcf62SDimitry Andric 
80362cfcf62SDimitry Andric   if (auto Err = write(*MS, DWOFilenames)) {
80462cfcf62SDimitry Andric     logAllUnhandledErrors(std::move(Err), WithColor::error());
80562cfcf62SDimitry Andric     return 1;
80662cfcf62SDimitry Andric   }
80762cfcf62SDimitry Andric 
80862cfcf62SDimitry Andric   MS->Finish();
80962cfcf62SDimitry Andric   OutFile.keep();
81062cfcf62SDimitry Andric   return 0;
81162cfcf62SDimitry Andric }
812