xref: /freebsd-src/contrib/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
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"
30*5ffd83dbSDimitry Andric #include "llvm/MC/MCTargetOptionsCommandFlags.h"
3162cfcf62SDimitry Andric #include "llvm/Object/Decompressor.h"
3262cfcf62SDimitry Andric #include "llvm/Object/ObjectFile.h"
33*5ffd83dbSDimitry 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 
50*5ffd83dbSDimitry Andric static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags;
51*5ffd83dbSDimitry 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];
96*5ffd83dbSDimitry 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);
146*5ffd83dbSDimitry Andric   CompileUnitIdentifiers ID;
147*5ffd83dbSDimitry 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);
155*5ffd83dbSDimitry Andric   if (Version >= 5) {
156*5ffd83dbSDimitry Andric     auto UnitType = InfoData.getU8(&Offset);
157*5ffd83dbSDimitry Andric     if (UnitType != dwarf::DW_UT_split_compile)
158*5ffd83dbSDimitry Andric       return make_error<DWPError>(
159*5ffd83dbSDimitry Andric           std::string("unit type DW_UT_split_compile type not found in "
160*5ffd83dbSDimitry Andric                       "debug_info header. Unexpected unit type 0x" +
161*5ffd83dbSDimitry Andric                       utostr(UnitType) + " found"));
162*5ffd83dbSDimitry Andric   }
16362cfcf62SDimitry Andric   InfoData.getU32(&Offset); // Abbrev offset (should be zero)
16462cfcf62SDimitry Andric   uint8_t AddrSize = InfoData.getU8(&Offset);
165*5ffd83dbSDimitry Andric   if (Version >= 5)
166*5ffd83dbSDimitry 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     }
190*5ffd83dbSDimitry Andric     case dwarf::DW_AT_GNU_dwo_name:
191*5ffd83dbSDimitry 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 
220*5ffd83dbSDimitry Andric static bool isSupportedSectionKind(DWARFSectionKind Kind) {
221*5ffd83dbSDimitry Andric   return Kind != DW_SECT_EXT_unknown;
222*5ffd83dbSDimitry Andric }
223*5ffd83dbSDimitry Andric 
224*5ffd83dbSDimitry Andric // Convert an internal section identifier into the index to use with
225*5ffd83dbSDimitry Andric // UnitIndexEntry::Contributions.
226*5ffd83dbSDimitry Andric static unsigned getContributionIndex(DWARFSectionKind Kind) {
227*5ffd83dbSDimitry Andric   // Assuming the pre-standard DWP format.
228*5ffd83dbSDimitry Andric   assert(serializeSectionKind(Kind, 2) >= DW_SECT_INFO);
229*5ffd83dbSDimitry Andric   return serializeSectionKind(Kind, 2) - DW_SECT_INFO;
230*5ffd83dbSDimitry Andric }
231*5ffd83dbSDimitry Andric 
232*5ffd83dbSDimitry Andric // Convert a UnitIndexEntry::Contributions index to the corresponding on-disk
233*5ffd83dbSDimitry Andric // value of the section identifier.
234*5ffd83dbSDimitry Andric static unsigned getOnDiskSectionId(unsigned Index) {
235*5ffd83dbSDimitry Andric   return Index + DW_SECT_INFO;
236*5ffd83dbSDimitry Andric }
237*5ffd83dbSDimitry Andric 
23862cfcf62SDimitry Andric static StringRef getSubsection(StringRef Section,
23962cfcf62SDimitry Andric                                const DWARFUnitIndex::Entry &Entry,
24062cfcf62SDimitry Andric                                DWARFSectionKind Kind) {
241*5ffd83dbSDimitry 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()) {
253*5ffd83dbSDimitry 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()) {
263*5ffd83dbSDimitry Andric       if (!isSupportedSectionKind(Kind))
264*5ffd83dbSDimitry Andric         continue;
265*5ffd83dbSDimitry Andric       auto &C = Entry.Contributions[getContributionIndex(Kind)];
26662cfcf62SDimitry Andric       C.Offset += I->Offset;
26762cfcf62SDimitry Andric       C.Length = I->Length;
26862cfcf62SDimitry Andric       ++I;
26962cfcf62SDimitry Andric     }
270*5ffd83dbSDimitry Andric     unsigned TypesIndex = getContributionIndex(DW_SECT_EXT_TYPES);
271*5ffd83dbSDimitry Andric     auto &C = Entry.Contributions[TypesIndex];
272*5ffd83dbSDimitry Andric     Out.emitBytes(Types.substr(
273*5ffd83dbSDimitry 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] = {};
292*5ffd83dbSDimitry 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 
308*5ffd83dbSDimitry 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])
321*5ffd83dbSDimitry 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);
353*5ffd83dbSDimitry Andric   Out.emitIntValue(2, 4);                   // Version
354*5ffd83dbSDimitry Andric   Out.emitIntValue(Columns, 4);             // Columns
355*5ffd83dbSDimitry Andric   Out.emitIntValue(IndexEntries.size(), 4); // Num Units
356*5ffd83dbSDimitry Andric   Out.emitIntValue(Buckets.size(), 4);      // Num Buckets
35762cfcf62SDimitry Andric 
35862cfcf62SDimitry Andric   // Write the signatures.
35962cfcf62SDimitry Andric   for (const auto &I : Buckets)
360*5ffd83dbSDimitry 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)
364*5ffd83dbSDimitry 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])
369*5ffd83dbSDimitry 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 
38062cfcf62SDimitry Andric std::string buildDWODescription(StringRef Name, StringRef DWPName, StringRef DWOName) {
38162cfcf62SDimitry Andric   std::string Text = "\'";
38262cfcf62SDimitry Andric   Text += Name;
38362cfcf62SDimitry Andric   Text += '\'';
38462cfcf62SDimitry Andric   if (!DWPName.empty()) {
38562cfcf62SDimitry Andric     Text += " (from ";
38662cfcf62SDimitry Andric     if (!DWOName.empty()) {
38762cfcf62SDimitry Andric       Text += '\'';
38862cfcf62SDimitry Andric       Text += DWOName;
38962cfcf62SDimitry Andric       Text += "' in ";
39062cfcf62SDimitry Andric     }
39162cfcf62SDimitry Andric     Text += '\'';
39262cfcf62SDimitry Andric     Text += DWPName;
39362cfcf62SDimitry Andric     Text += "')";
39462cfcf62SDimitry Andric   }
39562cfcf62SDimitry Andric   return Text;
39662cfcf62SDimitry Andric }
39762cfcf62SDimitry Andric 
39862cfcf62SDimitry Andric static Error createError(StringRef Name, Error E) {
39962cfcf62SDimitry Andric   return make_error<DWPError>(
40062cfcf62SDimitry Andric       ("failure while decompressing compressed section: '" + Name + "', " +
40162cfcf62SDimitry Andric        llvm::toString(std::move(E)))
40262cfcf62SDimitry Andric           .str());
40362cfcf62SDimitry Andric }
40462cfcf62SDimitry Andric 
40562cfcf62SDimitry Andric static Error
40662cfcf62SDimitry Andric handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections,
40762cfcf62SDimitry Andric                         StringRef &Name, StringRef &Contents) {
40862cfcf62SDimitry Andric   if (!Decompressor::isGnuStyle(Name))
40962cfcf62SDimitry Andric     return Error::success();
41062cfcf62SDimitry Andric 
41162cfcf62SDimitry Andric   Expected<Decompressor> Dec =
41262cfcf62SDimitry Andric       Decompressor::create(Name, Contents, false /*IsLE*/, false /*Is64Bit*/);
41362cfcf62SDimitry Andric   if (!Dec)
41462cfcf62SDimitry Andric     return createError(Name, Dec.takeError());
41562cfcf62SDimitry Andric 
41662cfcf62SDimitry Andric   UncompressedSections.emplace_back();
41762cfcf62SDimitry Andric   if (Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
41862cfcf62SDimitry Andric     return createError(Name, std::move(E));
41962cfcf62SDimitry Andric 
42062cfcf62SDimitry Andric   Name = Name.substr(2); // Drop ".z"
42162cfcf62SDimitry Andric   Contents = UncompressedSections.back();
42262cfcf62SDimitry Andric   return Error::success();
42362cfcf62SDimitry Andric }
42462cfcf62SDimitry Andric 
42562cfcf62SDimitry Andric static Error handleSection(
42662cfcf62SDimitry Andric     const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
42762cfcf62SDimitry Andric     const MCSection *StrSection, const MCSection *StrOffsetSection,
42862cfcf62SDimitry Andric     const MCSection *TypesSection, const MCSection *CUIndexSection,
42962cfcf62SDimitry Andric     const MCSection *TUIndexSection, const SectionRef &Section, MCStreamer &Out,
43062cfcf62SDimitry Andric     std::deque<SmallString<32>> &UncompressedSections,
43162cfcf62SDimitry Andric     uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry,
43262cfcf62SDimitry Andric     StringRef &CurStrSection, StringRef &CurStrOffsetSection,
43362cfcf62SDimitry Andric     std::vector<StringRef> &CurTypesSection, StringRef &InfoSection,
43462cfcf62SDimitry Andric     StringRef &AbbrevSection, StringRef &CurCUIndexSection,
43562cfcf62SDimitry Andric     StringRef &CurTUIndexSection) {
43662cfcf62SDimitry Andric   if (Section.isBSS())
43762cfcf62SDimitry Andric     return Error::success();
43862cfcf62SDimitry Andric 
43962cfcf62SDimitry Andric   if (Section.isVirtual())
44062cfcf62SDimitry Andric     return Error::success();
44162cfcf62SDimitry Andric 
44262cfcf62SDimitry Andric   Expected<StringRef> NameOrErr = Section.getName();
44362cfcf62SDimitry Andric   if (!NameOrErr)
44462cfcf62SDimitry Andric     return NameOrErr.takeError();
44562cfcf62SDimitry Andric   StringRef Name = *NameOrErr;
44662cfcf62SDimitry Andric 
44762cfcf62SDimitry Andric   Expected<StringRef> ContentsOrErr = Section.getContents();
44862cfcf62SDimitry Andric   if (!ContentsOrErr)
44962cfcf62SDimitry Andric     return ContentsOrErr.takeError();
45062cfcf62SDimitry Andric   StringRef Contents = *ContentsOrErr;
45162cfcf62SDimitry Andric 
45262cfcf62SDimitry Andric   if (auto Err = handleCompressedSection(UncompressedSections, Name, Contents))
45362cfcf62SDimitry Andric     return Err;
45462cfcf62SDimitry Andric 
45562cfcf62SDimitry Andric   Name = Name.substr(Name.find_first_not_of("._"));
45662cfcf62SDimitry Andric 
45762cfcf62SDimitry Andric   auto SectionPair = KnownSections.find(Name);
45862cfcf62SDimitry Andric   if (SectionPair == KnownSections.end())
45962cfcf62SDimitry Andric     return Error::success();
46062cfcf62SDimitry Andric 
46162cfcf62SDimitry Andric   if (DWARFSectionKind Kind = SectionPair->second.second) {
462*5ffd83dbSDimitry Andric     auto Index = getContributionIndex(Kind);
463*5ffd83dbSDimitry Andric     if (Kind != DW_SECT_EXT_TYPES) {
46462cfcf62SDimitry Andric       CurEntry.Contributions[Index].Offset = ContributionOffsets[Index];
46562cfcf62SDimitry Andric       ContributionOffsets[Index] +=
46662cfcf62SDimitry Andric           (CurEntry.Contributions[Index].Length = Contents.size());
46762cfcf62SDimitry Andric     }
46862cfcf62SDimitry Andric 
46962cfcf62SDimitry Andric     switch (Kind) {
47062cfcf62SDimitry Andric     case DW_SECT_INFO:
47162cfcf62SDimitry Andric       InfoSection = Contents;
47262cfcf62SDimitry Andric       break;
47362cfcf62SDimitry Andric     case DW_SECT_ABBREV:
47462cfcf62SDimitry Andric       AbbrevSection = Contents;
47562cfcf62SDimitry Andric       break;
47662cfcf62SDimitry Andric     default:
47762cfcf62SDimitry Andric       break;
47862cfcf62SDimitry Andric     }
47962cfcf62SDimitry Andric   }
48062cfcf62SDimitry Andric 
48162cfcf62SDimitry Andric   MCSection *OutSection = SectionPair->second.first;
48262cfcf62SDimitry Andric   if (OutSection == StrOffsetSection)
48362cfcf62SDimitry Andric     CurStrOffsetSection = Contents;
48462cfcf62SDimitry Andric   else if (OutSection == StrSection)
48562cfcf62SDimitry Andric     CurStrSection = Contents;
48662cfcf62SDimitry Andric   else if (OutSection == TypesSection)
48762cfcf62SDimitry Andric     CurTypesSection.push_back(Contents);
48862cfcf62SDimitry Andric   else if (OutSection == CUIndexSection)
48962cfcf62SDimitry Andric     CurCUIndexSection = Contents;
49062cfcf62SDimitry Andric   else if (OutSection == TUIndexSection)
49162cfcf62SDimitry Andric     CurTUIndexSection = Contents;
49262cfcf62SDimitry Andric   else {
49362cfcf62SDimitry Andric     Out.SwitchSection(OutSection);
494*5ffd83dbSDimitry Andric     Out.emitBytes(Contents);
49562cfcf62SDimitry Andric   }
49662cfcf62SDimitry Andric   return Error::success();
49762cfcf62SDimitry Andric }
49862cfcf62SDimitry Andric 
49962cfcf62SDimitry Andric static Error
50062cfcf62SDimitry Andric buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
50162cfcf62SDimitry Andric                     const CompileUnitIdentifiers &ID, StringRef DWPName) {
50262cfcf62SDimitry Andric   return make_error<DWPError>(
503*5ffd83dbSDimitry Andric       std::string("duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " +
50462cfcf62SDimitry Andric       buildDWODescription(PrevE.second.Name, PrevE.second.DWPName,
50562cfcf62SDimitry Andric                           PrevE.second.DWOName) +
50662cfcf62SDimitry Andric       " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));
50762cfcf62SDimitry Andric }
50862cfcf62SDimitry Andric 
50962cfcf62SDimitry Andric static Expected<SmallVector<std::string, 16>>
51062cfcf62SDimitry Andric getDWOFilenames(StringRef ExecFilename) {
51162cfcf62SDimitry Andric   auto ErrOrObj = object::ObjectFile::createObjectFile(ExecFilename);
51262cfcf62SDimitry Andric   if (!ErrOrObj)
51362cfcf62SDimitry Andric     return ErrOrObj.takeError();
51462cfcf62SDimitry Andric 
51562cfcf62SDimitry Andric   const ObjectFile &Obj = *ErrOrObj.get().getBinary();
51662cfcf62SDimitry Andric   std::unique_ptr<DWARFContext> DWARFCtx = DWARFContext::create(Obj);
51762cfcf62SDimitry Andric 
51862cfcf62SDimitry Andric   SmallVector<std::string, 16> DWOPaths;
51962cfcf62SDimitry Andric   for (const auto &CU : DWARFCtx->compile_units()) {
52062cfcf62SDimitry Andric     const DWARFDie &Die = CU->getUnitDIE();
52162cfcf62SDimitry Andric     std::string DWOName = dwarf::toString(
52262cfcf62SDimitry Andric         Die.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
52362cfcf62SDimitry Andric     if (DWOName.empty())
52462cfcf62SDimitry Andric       continue;
52562cfcf62SDimitry Andric     std::string DWOCompDir =
52662cfcf62SDimitry Andric         dwarf::toString(Die.find(dwarf::DW_AT_comp_dir), "");
52762cfcf62SDimitry Andric     if (!DWOCompDir.empty()) {
52862cfcf62SDimitry Andric       SmallString<16> DWOPath;
52962cfcf62SDimitry Andric       sys::path::append(DWOPath, DWOCompDir, DWOName);
53062cfcf62SDimitry Andric       DWOPaths.emplace_back(DWOPath.data(), DWOPath.size());
53162cfcf62SDimitry Andric     } else {
53262cfcf62SDimitry Andric       DWOPaths.push_back(std::move(DWOName));
53362cfcf62SDimitry Andric     }
53462cfcf62SDimitry Andric   }
53562cfcf62SDimitry Andric   return std::move(DWOPaths);
53662cfcf62SDimitry Andric }
53762cfcf62SDimitry Andric 
53862cfcf62SDimitry Andric static Error write(MCStreamer &Out, ArrayRef<std::string> Inputs) {
53962cfcf62SDimitry Andric   const auto &MCOFI = *Out.getContext().getObjectFileInfo();
54062cfcf62SDimitry Andric   MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
54162cfcf62SDimitry Andric   MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
54262cfcf62SDimitry Andric   MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection();
54362cfcf62SDimitry Andric   MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection();
54462cfcf62SDimitry Andric   MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection();
54562cfcf62SDimitry Andric   const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = {
54662cfcf62SDimitry Andric       {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}},
547*5ffd83dbSDimitry Andric       {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},
54862cfcf62SDimitry Andric       {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
54962cfcf62SDimitry Andric       {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}},
550*5ffd83dbSDimitry Andric       {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},
55162cfcf62SDimitry Andric       {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
55262cfcf62SDimitry Andric       {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
55362cfcf62SDimitry Andric       {"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}},
55462cfcf62SDimitry Andric       {"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};
55562cfcf62SDimitry Andric 
55662cfcf62SDimitry Andric   MapVector<uint64_t, UnitIndexEntry> IndexEntries;
55762cfcf62SDimitry Andric   MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
55862cfcf62SDimitry Andric 
55962cfcf62SDimitry Andric   uint32_t ContributionOffsets[8] = {};
56062cfcf62SDimitry Andric 
56162cfcf62SDimitry Andric   DWPStringPool Strings(Out, StrSection);
56262cfcf62SDimitry Andric 
56362cfcf62SDimitry Andric   SmallVector<OwningBinary<object::ObjectFile>, 128> Objects;
56462cfcf62SDimitry Andric   Objects.reserve(Inputs.size());
56562cfcf62SDimitry Andric 
56662cfcf62SDimitry Andric   std::deque<SmallString<32>> UncompressedSections;
56762cfcf62SDimitry Andric 
56862cfcf62SDimitry Andric   for (const auto &Input : Inputs) {
56962cfcf62SDimitry Andric     auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
57062cfcf62SDimitry Andric     if (!ErrOrObj)
57162cfcf62SDimitry Andric       return ErrOrObj.takeError();
57262cfcf62SDimitry Andric 
57362cfcf62SDimitry Andric     auto &Obj = *ErrOrObj->getBinary();
57462cfcf62SDimitry Andric     Objects.push_back(std::move(*ErrOrObj));
57562cfcf62SDimitry Andric 
57662cfcf62SDimitry Andric     UnitIndexEntry CurEntry = {};
57762cfcf62SDimitry Andric 
57862cfcf62SDimitry Andric     StringRef CurStrSection;
57962cfcf62SDimitry Andric     StringRef CurStrOffsetSection;
58062cfcf62SDimitry Andric     std::vector<StringRef> CurTypesSection;
58162cfcf62SDimitry Andric     StringRef InfoSection;
58262cfcf62SDimitry Andric     StringRef AbbrevSection;
58362cfcf62SDimitry Andric     StringRef CurCUIndexSection;
58462cfcf62SDimitry Andric     StringRef CurTUIndexSection;
58562cfcf62SDimitry Andric 
58662cfcf62SDimitry Andric     for (const auto &Section : Obj.sections())
58762cfcf62SDimitry Andric       if (auto Err = handleSection(
58862cfcf62SDimitry Andric               KnownSections, StrSection, StrOffsetSection, TypesSection,
58962cfcf62SDimitry Andric               CUIndexSection, TUIndexSection, Section, Out,
59062cfcf62SDimitry Andric               UncompressedSections, ContributionOffsets, CurEntry,
59162cfcf62SDimitry Andric               CurStrSection, CurStrOffsetSection, CurTypesSection, InfoSection,
59262cfcf62SDimitry Andric               AbbrevSection, CurCUIndexSection, CurTUIndexSection))
59362cfcf62SDimitry Andric         return Err;
59462cfcf62SDimitry Andric 
59562cfcf62SDimitry Andric     if (InfoSection.empty())
59662cfcf62SDimitry Andric       continue;
59762cfcf62SDimitry Andric 
59862cfcf62SDimitry Andric     writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection,
59962cfcf62SDimitry Andric                            CurStrOffsetSection);
60062cfcf62SDimitry Andric 
60162cfcf62SDimitry Andric     if (CurCUIndexSection.empty()) {
60262cfcf62SDimitry Andric       Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
60362cfcf62SDimitry Andric           AbbrevSection, InfoSection, CurStrOffsetSection, CurStrSection);
60462cfcf62SDimitry Andric       if (!EID)
60562cfcf62SDimitry Andric         return createFileError(Input, EID.takeError());
60662cfcf62SDimitry Andric       const auto &ID = *EID;
60762cfcf62SDimitry Andric       auto P = IndexEntries.insert(std::make_pair(ID.Signature, CurEntry));
60862cfcf62SDimitry Andric       if (!P.second)
60962cfcf62SDimitry Andric         return buildDuplicateError(*P.first, ID, "");
61062cfcf62SDimitry Andric       P.first->second.Name = ID.Name;
61162cfcf62SDimitry Andric       P.first->second.DWOName = ID.DWOName;
61262cfcf62SDimitry Andric       addAllTypes(Out, TypeIndexEntries, TypesSection, CurTypesSection,
613*5ffd83dbSDimitry Andric                   CurEntry,
614*5ffd83dbSDimitry Andric                   ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]);
61562cfcf62SDimitry Andric       continue;
61662cfcf62SDimitry Andric     }
61762cfcf62SDimitry Andric 
61862cfcf62SDimitry Andric     DWARFUnitIndex CUIndex(DW_SECT_INFO);
61962cfcf62SDimitry Andric     DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
62062cfcf62SDimitry Andric     if (!CUIndex.parse(CUIndexData))
621*5ffd83dbSDimitry Andric       return make_error<DWPError>("failed to parse cu_index");
622*5ffd83dbSDimitry Andric     if (CUIndex.getVersion() != 2)
623*5ffd83dbSDimitry Andric       return make_error<DWPError>(
624*5ffd83dbSDimitry Andric           "unsupported cu_index version: " + utostr(CUIndex.getVersion()) +
625*5ffd83dbSDimitry Andric           " (only version 2 is supported)");
62662cfcf62SDimitry Andric 
62762cfcf62SDimitry Andric     for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
628*5ffd83dbSDimitry Andric       auto *I = E.getContributions();
62962cfcf62SDimitry Andric       if (!I)
63062cfcf62SDimitry Andric         continue;
63162cfcf62SDimitry Andric       auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry));
63262cfcf62SDimitry Andric       Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
63362cfcf62SDimitry Andric           getSubsection(AbbrevSection, E, DW_SECT_ABBREV),
63462cfcf62SDimitry Andric           getSubsection(InfoSection, E, DW_SECT_INFO),
63562cfcf62SDimitry Andric           getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS),
63662cfcf62SDimitry Andric           CurStrSection);
63762cfcf62SDimitry Andric       if (!EID)
63862cfcf62SDimitry Andric         return createFileError(Input, EID.takeError());
63962cfcf62SDimitry Andric       const auto &ID = *EID;
64062cfcf62SDimitry Andric       if (!P.second)
64162cfcf62SDimitry Andric         return buildDuplicateError(*P.first, ID, Input);
64262cfcf62SDimitry Andric       auto &NewEntry = P.first->second;
64362cfcf62SDimitry Andric       NewEntry.Name = ID.Name;
64462cfcf62SDimitry Andric       NewEntry.DWOName = ID.DWOName;
64562cfcf62SDimitry Andric       NewEntry.DWPName = Input;
64662cfcf62SDimitry Andric       for (auto Kind : CUIndex.getColumnKinds()) {
647*5ffd83dbSDimitry Andric         if (!isSupportedSectionKind(Kind))
648*5ffd83dbSDimitry Andric           continue;
649*5ffd83dbSDimitry Andric         auto &C = NewEntry.Contributions[getContributionIndex(Kind)];
65062cfcf62SDimitry Andric         C.Offset += I->Offset;
65162cfcf62SDimitry Andric         C.Length = I->Length;
65262cfcf62SDimitry Andric         ++I;
65362cfcf62SDimitry Andric       }
65462cfcf62SDimitry Andric     }
65562cfcf62SDimitry Andric 
65662cfcf62SDimitry Andric     if (!CurTypesSection.empty()) {
65762cfcf62SDimitry Andric       if (CurTypesSection.size() != 1)
65862cfcf62SDimitry Andric         return make_error<DWPError>("multiple type unit sections in .dwp file");
659*5ffd83dbSDimitry Andric       DWARFUnitIndex TUIndex(DW_SECT_EXT_TYPES);
66062cfcf62SDimitry Andric       DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);
66162cfcf62SDimitry Andric       if (!TUIndex.parse(TUIndexData))
662*5ffd83dbSDimitry Andric         return make_error<DWPError>("failed to parse tu_index");
663*5ffd83dbSDimitry Andric       if (TUIndex.getVersion() != 2)
664*5ffd83dbSDimitry Andric         return make_error<DWPError>(
665*5ffd83dbSDimitry Andric             "unsupported tu_index version: " + utostr(TUIndex.getVersion()) +
666*5ffd83dbSDimitry Andric             " (only version 2 is supported)");
667*5ffd83dbSDimitry Andric 
668*5ffd83dbSDimitry Andric       addAllTypesFromDWP(
669*5ffd83dbSDimitry Andric           Out, TypeIndexEntries, TUIndex, TypesSection, CurTypesSection.front(),
670*5ffd83dbSDimitry Andric           CurEntry,
671*5ffd83dbSDimitry Andric           ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)]);
67262cfcf62SDimitry Andric     }
67362cfcf62SDimitry Andric   }
67462cfcf62SDimitry Andric 
67562cfcf62SDimitry Andric   // Lie about there being no info contributions so the TU index only includes
67662cfcf62SDimitry Andric   // the type unit contribution
67762cfcf62SDimitry Andric   ContributionOffsets[0] = 0;
67862cfcf62SDimitry Andric   writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
67962cfcf62SDimitry Andric              TypeIndexEntries);
68062cfcf62SDimitry Andric 
68162cfcf62SDimitry Andric   // Lie about the type contribution
682*5ffd83dbSDimitry Andric   ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES)] = 0;
68362cfcf62SDimitry Andric   // Unlie about the info contribution
68462cfcf62SDimitry Andric   ContributionOffsets[0] = 1;
68562cfcf62SDimitry Andric 
68662cfcf62SDimitry Andric   writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
68762cfcf62SDimitry Andric              IndexEntries);
68862cfcf62SDimitry Andric 
68962cfcf62SDimitry Andric   return Error::success();
69062cfcf62SDimitry Andric }
69162cfcf62SDimitry Andric 
69262cfcf62SDimitry Andric static int error(const Twine &Error, const Twine &Context) {
69362cfcf62SDimitry Andric   errs() << Twine("while processing ") + Context + ":\n";
69462cfcf62SDimitry Andric   errs() << Twine("error: ") + Error + "\n";
69562cfcf62SDimitry Andric   return 1;
69662cfcf62SDimitry Andric }
69762cfcf62SDimitry Andric 
69862cfcf62SDimitry Andric int main(int argc, char **argv) {
69962cfcf62SDimitry Andric   InitLLVM X(argc, argv);
70062cfcf62SDimitry Andric 
70162cfcf62SDimitry Andric   cl::ParseCommandLineOptions(argc, argv, "merge split dwarf (.dwo) files\n");
70262cfcf62SDimitry Andric 
70362cfcf62SDimitry Andric   llvm::InitializeAllTargetInfos();
70462cfcf62SDimitry Andric   llvm::InitializeAllTargetMCs();
70562cfcf62SDimitry Andric   llvm::InitializeAllTargets();
70662cfcf62SDimitry Andric   llvm::InitializeAllAsmPrinters();
70762cfcf62SDimitry Andric 
70862cfcf62SDimitry Andric   std::string ErrorStr;
70962cfcf62SDimitry Andric   StringRef Context = "dwarf streamer init";
71062cfcf62SDimitry Andric 
71162cfcf62SDimitry Andric   Triple TheTriple("x86_64-linux-gnu");
71262cfcf62SDimitry Andric 
71362cfcf62SDimitry Andric   // Get the target.
71462cfcf62SDimitry Andric   const Target *TheTarget =
71562cfcf62SDimitry Andric       TargetRegistry::lookupTarget("", TheTriple, ErrorStr);
71662cfcf62SDimitry Andric   if (!TheTarget)
71762cfcf62SDimitry Andric     return error(ErrorStr, Context);
71862cfcf62SDimitry Andric   std::string TripleName = TheTriple.getTriple();
71962cfcf62SDimitry Andric 
72062cfcf62SDimitry Andric   // Create all the MC Objects.
72162cfcf62SDimitry Andric   std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
72262cfcf62SDimitry Andric   if (!MRI)
72362cfcf62SDimitry Andric     return error(Twine("no register info for target ") + TripleName, Context);
72462cfcf62SDimitry Andric 
725*5ffd83dbSDimitry Andric   MCTargetOptions MCOptions = llvm::mc::InitMCTargetOptionsFromFlags();
72662cfcf62SDimitry Andric   std::unique_ptr<MCAsmInfo> MAI(
72762cfcf62SDimitry Andric       TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
72862cfcf62SDimitry Andric   if (!MAI)
72962cfcf62SDimitry Andric     return error("no asm info for target " + TripleName, Context);
73062cfcf62SDimitry Andric 
73162cfcf62SDimitry Andric   MCObjectFileInfo MOFI;
73262cfcf62SDimitry Andric   MCContext MC(MAI.get(), MRI.get(), &MOFI);
73362cfcf62SDimitry Andric   MOFI.InitMCObjectFileInfo(TheTriple, /*PIC*/ false, MC);
73462cfcf62SDimitry Andric 
73562cfcf62SDimitry Andric   std::unique_ptr<MCSubtargetInfo> MSTI(
73662cfcf62SDimitry Andric       TheTarget->createMCSubtargetInfo(TripleName, "", ""));
73762cfcf62SDimitry Andric   if (!MSTI)
73862cfcf62SDimitry Andric     return error("no subtarget info for target " + TripleName, Context);
73962cfcf62SDimitry Andric 
74062cfcf62SDimitry Andric   MCTargetOptions Options;
74162cfcf62SDimitry Andric   auto MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, Options);
74262cfcf62SDimitry Andric   if (!MAB)
74362cfcf62SDimitry Andric     return error("no asm backend for target " + TripleName, Context);
74462cfcf62SDimitry Andric 
74562cfcf62SDimitry Andric   std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());
74662cfcf62SDimitry Andric   if (!MII)
74762cfcf62SDimitry Andric     return error("no instr info info for target " + TripleName, Context);
74862cfcf62SDimitry Andric 
74962cfcf62SDimitry Andric   MCCodeEmitter *MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, MC);
75062cfcf62SDimitry Andric   if (!MCE)
75162cfcf62SDimitry Andric     return error("no code emitter for target " + TripleName, Context);
75262cfcf62SDimitry Andric 
75362cfcf62SDimitry Andric   // Create the output file.
75462cfcf62SDimitry Andric   std::error_code EC;
75562cfcf62SDimitry Andric   ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_None);
75662cfcf62SDimitry Andric   Optional<buffer_ostream> BOS;
75762cfcf62SDimitry Andric   raw_pwrite_stream *OS;
75862cfcf62SDimitry Andric   if (EC)
75962cfcf62SDimitry Andric     return error(Twine(OutputFilename) + ": " + EC.message(), Context);
76062cfcf62SDimitry Andric   if (OutFile.os().supportsSeeking()) {
76162cfcf62SDimitry Andric     OS = &OutFile.os();
76262cfcf62SDimitry Andric   } else {
76362cfcf62SDimitry Andric     BOS.emplace(OutFile.os());
76462cfcf62SDimitry Andric     OS = BOS.getPointer();
76562cfcf62SDimitry Andric   }
76662cfcf62SDimitry Andric 
76762cfcf62SDimitry Andric   std::unique_ptr<MCStreamer> MS(TheTarget->createMCObjectStreamer(
76862cfcf62SDimitry Andric       TheTriple, MC, std::unique_ptr<MCAsmBackend>(MAB),
76962cfcf62SDimitry Andric       MAB->createObjectWriter(*OS), std::unique_ptr<MCCodeEmitter>(MCE), *MSTI,
77062cfcf62SDimitry Andric       MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
77162cfcf62SDimitry Andric       /*DWARFMustBeAtTheEnd*/ false));
77262cfcf62SDimitry Andric   if (!MS)
77362cfcf62SDimitry Andric     return error("no object streamer for target " + TripleName, Context);
77462cfcf62SDimitry Andric 
77562cfcf62SDimitry Andric   std::vector<std::string> DWOFilenames = InputFiles;
77662cfcf62SDimitry Andric   for (const auto &ExecFilename : ExecFilenames) {
77762cfcf62SDimitry Andric     auto DWOs = getDWOFilenames(ExecFilename);
77862cfcf62SDimitry Andric     if (!DWOs) {
77962cfcf62SDimitry Andric       logAllUnhandledErrors(DWOs.takeError(), WithColor::error());
78062cfcf62SDimitry Andric       return 1;
78162cfcf62SDimitry Andric     }
78262cfcf62SDimitry Andric     DWOFilenames.insert(DWOFilenames.end(),
78362cfcf62SDimitry Andric                         std::make_move_iterator(DWOs->begin()),
78462cfcf62SDimitry Andric                         std::make_move_iterator(DWOs->end()));
78562cfcf62SDimitry Andric   }
78662cfcf62SDimitry Andric 
78762cfcf62SDimitry Andric   if (auto Err = write(*MS, DWOFilenames)) {
78862cfcf62SDimitry Andric     logAllUnhandledErrors(std::move(Err), WithColor::error());
78962cfcf62SDimitry Andric     return 1;
79062cfcf62SDimitry Andric   }
79162cfcf62SDimitry Andric 
79262cfcf62SDimitry Andric   MS->Finish();
79362cfcf62SDimitry Andric   OutFile.keep();
79462cfcf62SDimitry Andric   return 0;
79562cfcf62SDimitry Andric }
796