xref: /freebsd-src/contrib/llvm-project/llvm/lib/DWP/DWP.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1fe6060f1SDimitry Andric //===-- llvm-dwp.cpp - Split DWARF merging tool for llvm ------------------===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric //
9fe6060f1SDimitry Andric // A utility for merging DWARF 5 Split DWARF .dwo files into .dwp (DWARF
10fe6060f1SDimitry Andric // package files).
11fe6060f1SDimitry Andric //
12fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
13fe6060f1SDimitry Andric #include "llvm/DWP/DWP.h"
14*06c3fb27SDimitry Andric #include "llvm/ADT/Twine.h"
15fe6060f1SDimitry Andric #include "llvm/DWP/DWPError.h"
16fe6060f1SDimitry Andric #include "llvm/MC/MCContext.h"
17fe6060f1SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
18fe6060f1SDimitry Andric #include "llvm/MC/MCTargetOptionsCommandFlags.h"
19fe6060f1SDimitry Andric #include "llvm/Object/Decompressor.h"
20fcaf7f86SDimitry Andric #include "llvm/Object/ELFObjectFile.h"
21*06c3fb27SDimitry Andric #include "llvm/Support/CommandLine.h"
2281ad6265SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
23972a253aSDimitry Andric #include <limits>
24fe6060f1SDimitry Andric 
25fe6060f1SDimitry Andric using namespace llvm;
26fe6060f1SDimitry Andric using namespace llvm::object;
27fe6060f1SDimitry Andric 
28fe6060f1SDimitry Andric static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags;
29fe6060f1SDimitry Andric 
30fe6060f1SDimitry Andric // Returns the size of debug_str_offsets section headers in bytes.
31fe6060f1SDimitry Andric static uint64_t debugStrOffsetsHeaderSize(DataExtractor StrOffsetsData,
32fe6060f1SDimitry Andric                                           uint16_t DwarfVersion) {
33fe6060f1SDimitry Andric   if (DwarfVersion <= 4)
34fe6060f1SDimitry Andric     return 0; // There is no header before dwarf 5.
35fe6060f1SDimitry Andric   uint64_t Offset = 0;
36fe6060f1SDimitry Andric   uint64_t Length = StrOffsetsData.getU32(&Offset);
37fe6060f1SDimitry Andric   if (Length == llvm::dwarf::DW_LENGTH_DWARF64)
38fe6060f1SDimitry Andric     return 16; // unit length: 12 bytes, version: 2 bytes, padding: 2 bytes.
39fe6060f1SDimitry Andric   return 8;    // unit length: 4 bytes, version: 2 bytes, padding: 2 bytes.
40fe6060f1SDimitry Andric }
41fe6060f1SDimitry Andric 
42fe6060f1SDimitry Andric static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) {
43fe6060f1SDimitry Andric   uint64_t Offset = 0;
44fe6060f1SDimitry Andric   DataExtractor AbbrevData(Abbrev, true, 0);
45fe6060f1SDimitry Andric   while (AbbrevData.getULEB128(&Offset) != AbbrCode) {
46fe6060f1SDimitry Andric     // Tag
47fe6060f1SDimitry Andric     AbbrevData.getULEB128(&Offset);
48fe6060f1SDimitry Andric     // DW_CHILDREN
49fe6060f1SDimitry Andric     AbbrevData.getU8(&Offset);
50fe6060f1SDimitry Andric     // Attributes
51fe6060f1SDimitry Andric     while (AbbrevData.getULEB128(&Offset) | AbbrevData.getULEB128(&Offset))
52fe6060f1SDimitry Andric       ;
53fe6060f1SDimitry Andric   }
54fe6060f1SDimitry Andric   return Offset;
55fe6060f1SDimitry Andric }
56fe6060f1SDimitry Andric 
57fe6060f1SDimitry Andric static Expected<const char *>
58fe6060f1SDimitry Andric getIndexedString(dwarf::Form Form, DataExtractor InfoData, uint64_t &InfoOffset,
59fe6060f1SDimitry Andric                  StringRef StrOffsets, StringRef Str, uint16_t Version) {
60fe6060f1SDimitry Andric   if (Form == dwarf::DW_FORM_string)
61fe6060f1SDimitry Andric     return InfoData.getCStr(&InfoOffset);
62fe6060f1SDimitry Andric   uint64_t StrIndex;
63fe6060f1SDimitry Andric   switch (Form) {
64fe6060f1SDimitry Andric   case dwarf::DW_FORM_strx1:
65fe6060f1SDimitry Andric     StrIndex = InfoData.getU8(&InfoOffset);
66fe6060f1SDimitry Andric     break;
67fe6060f1SDimitry Andric   case dwarf::DW_FORM_strx2:
68fe6060f1SDimitry Andric     StrIndex = InfoData.getU16(&InfoOffset);
69fe6060f1SDimitry Andric     break;
70fe6060f1SDimitry Andric   case dwarf::DW_FORM_strx3:
71fe6060f1SDimitry Andric     StrIndex = InfoData.getU24(&InfoOffset);
72fe6060f1SDimitry Andric     break;
73fe6060f1SDimitry Andric   case dwarf::DW_FORM_strx4:
74fe6060f1SDimitry Andric     StrIndex = InfoData.getU32(&InfoOffset);
75fe6060f1SDimitry Andric     break;
76fe6060f1SDimitry Andric   case dwarf::DW_FORM_strx:
77fe6060f1SDimitry Andric   case dwarf::DW_FORM_GNU_str_index:
78fe6060f1SDimitry Andric     StrIndex = InfoData.getULEB128(&InfoOffset);
79fe6060f1SDimitry Andric     break;
80fe6060f1SDimitry Andric   default:
81fe6060f1SDimitry Andric     return make_error<DWPError>(
82fe6060f1SDimitry Andric         "string field must be encoded with one of the following: "
83fe6060f1SDimitry Andric         "DW_FORM_string, DW_FORM_strx, DW_FORM_strx1, DW_FORM_strx2, "
84fe6060f1SDimitry Andric         "DW_FORM_strx3, DW_FORM_strx4, or DW_FORM_GNU_str_index.");
85fe6060f1SDimitry Andric   }
86fe6060f1SDimitry Andric   DataExtractor StrOffsetsData(StrOffsets, true, 0);
87fe6060f1SDimitry Andric   uint64_t StrOffsetsOffset = 4 * StrIndex;
88fe6060f1SDimitry Andric   StrOffsetsOffset += debugStrOffsetsHeaderSize(StrOffsetsData, Version);
89fe6060f1SDimitry Andric 
90fe6060f1SDimitry Andric   uint64_t StrOffset = StrOffsetsData.getU32(&StrOffsetsOffset);
91fe6060f1SDimitry Andric   DataExtractor StrData(Str, true, 0);
92fe6060f1SDimitry Andric   return StrData.getCStr(&StrOffset);
93fe6060f1SDimitry Andric }
94fe6060f1SDimitry Andric 
95fe6060f1SDimitry Andric static Expected<CompileUnitIdentifiers>
96fe6060f1SDimitry Andric getCUIdentifiers(InfoSectionUnitHeader &Header, StringRef Abbrev,
97fe6060f1SDimitry Andric                  StringRef Info, StringRef StrOffsets, StringRef Str) {
98fe6060f1SDimitry Andric   DataExtractor InfoData(Info, true, 0);
99fe6060f1SDimitry Andric   uint64_t Offset = Header.HeaderSize;
100fe6060f1SDimitry Andric   if (Header.Version >= 5 && Header.UnitType != dwarf::DW_UT_split_compile)
101fe6060f1SDimitry Andric     return make_error<DWPError>(
102fe6060f1SDimitry Andric         std::string("unit type DW_UT_split_compile type not found in "
103fe6060f1SDimitry Andric                     "debug_info header. Unexpected unit type 0x" +
104fe6060f1SDimitry Andric                     utostr(Header.UnitType) + " found"));
105fe6060f1SDimitry Andric 
106fe6060f1SDimitry Andric   CompileUnitIdentifiers ID;
107fe6060f1SDimitry Andric 
108fe6060f1SDimitry Andric   uint32_t AbbrCode = InfoData.getULEB128(&Offset);
109fe6060f1SDimitry Andric   DataExtractor AbbrevData(Abbrev, true, 0);
110fe6060f1SDimitry Andric   uint64_t AbbrevOffset = getCUAbbrev(Abbrev, AbbrCode);
111fe6060f1SDimitry Andric   auto Tag = static_cast<dwarf::Tag>(AbbrevData.getULEB128(&AbbrevOffset));
112fe6060f1SDimitry Andric   if (Tag != dwarf::DW_TAG_compile_unit)
113fe6060f1SDimitry Andric     return make_error<DWPError>("top level DIE is not a compile unit");
114fe6060f1SDimitry Andric   // DW_CHILDREN
115fe6060f1SDimitry Andric   AbbrevData.getU8(&AbbrevOffset);
116fe6060f1SDimitry Andric   uint32_t Name;
117fe6060f1SDimitry Andric   dwarf::Form Form;
118fe6060f1SDimitry Andric   while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) |
119fe6060f1SDimitry Andric              (Form = static_cast<dwarf::Form>(
120fe6060f1SDimitry Andric                   AbbrevData.getULEB128(&AbbrevOffset))) &&
121fe6060f1SDimitry Andric          (Name != 0 || Form != 0)) {
122fe6060f1SDimitry Andric     switch (Name) {
123fe6060f1SDimitry Andric     case dwarf::DW_AT_name: {
124fe6060f1SDimitry Andric       Expected<const char *> EName = getIndexedString(
125fe6060f1SDimitry Andric           Form, InfoData, Offset, StrOffsets, Str, Header.Version);
126fe6060f1SDimitry Andric       if (!EName)
127fe6060f1SDimitry Andric         return EName.takeError();
128fe6060f1SDimitry Andric       ID.Name = *EName;
129fe6060f1SDimitry Andric       break;
130fe6060f1SDimitry Andric     }
131fe6060f1SDimitry Andric     case dwarf::DW_AT_GNU_dwo_name:
132fe6060f1SDimitry Andric     case dwarf::DW_AT_dwo_name: {
133fe6060f1SDimitry Andric       Expected<const char *> EName = getIndexedString(
134fe6060f1SDimitry Andric           Form, InfoData, Offset, StrOffsets, Str, Header.Version);
135fe6060f1SDimitry Andric       if (!EName)
136fe6060f1SDimitry Andric         return EName.takeError();
137fe6060f1SDimitry Andric       ID.DWOName = *EName;
138fe6060f1SDimitry Andric       break;
139fe6060f1SDimitry Andric     }
140fe6060f1SDimitry Andric     case dwarf::DW_AT_GNU_dwo_id:
141fe6060f1SDimitry Andric       Header.Signature = InfoData.getU64(&Offset);
142fe6060f1SDimitry Andric       break;
143fe6060f1SDimitry Andric     default:
144fe6060f1SDimitry Andric       DWARFFormValue::skipValue(
145fe6060f1SDimitry Andric           Form, InfoData, &Offset,
146fe6060f1SDimitry Andric           dwarf::FormParams({Header.Version, Header.AddrSize, Header.Format}));
147fe6060f1SDimitry Andric     }
148fe6060f1SDimitry Andric   }
149fe6060f1SDimitry Andric   if (!Header.Signature)
150fe6060f1SDimitry Andric     return make_error<DWPError>("compile unit missing dwo_id");
151fe6060f1SDimitry Andric   ID.Signature = *Header.Signature;
152fe6060f1SDimitry Andric   return ID;
153fe6060f1SDimitry Andric }
154fe6060f1SDimitry Andric 
155fe6060f1SDimitry Andric static bool isSupportedSectionKind(DWARFSectionKind Kind) {
156fe6060f1SDimitry Andric   return Kind != DW_SECT_EXT_unknown;
157fe6060f1SDimitry Andric }
158fe6060f1SDimitry Andric 
159fe6060f1SDimitry Andric namespace llvm {
160fe6060f1SDimitry Andric // Convert an internal section identifier into the index to use with
161fe6060f1SDimitry Andric // UnitIndexEntry::Contributions.
162fe6060f1SDimitry Andric unsigned getContributionIndex(DWARFSectionKind Kind, uint32_t IndexVersion) {
163fe6060f1SDimitry Andric   assert(serializeSectionKind(Kind, IndexVersion) >= DW_SECT_INFO);
164fe6060f1SDimitry Andric   return serializeSectionKind(Kind, IndexVersion) - DW_SECT_INFO;
165fe6060f1SDimitry Andric }
166fe6060f1SDimitry Andric } // namespace llvm
167fe6060f1SDimitry Andric 
168fe6060f1SDimitry Andric // Convert a UnitIndexEntry::Contributions index to the corresponding on-disk
169fe6060f1SDimitry Andric // value of the section identifier.
170fe6060f1SDimitry Andric static unsigned getOnDiskSectionId(unsigned Index) {
171fe6060f1SDimitry Andric   return Index + DW_SECT_INFO;
172fe6060f1SDimitry Andric }
173fe6060f1SDimitry Andric 
174fe6060f1SDimitry Andric static StringRef getSubsection(StringRef Section,
175fe6060f1SDimitry Andric                                const DWARFUnitIndex::Entry &Entry,
176fe6060f1SDimitry Andric                                DWARFSectionKind Kind) {
177fe6060f1SDimitry Andric   const auto *Off = Entry.getContribution(Kind);
178fe6060f1SDimitry Andric   if (!Off)
179fe6060f1SDimitry Andric     return StringRef();
180bdd1243dSDimitry Andric   return Section.substr(Off->getOffset(), Off->getLength());
181fe6060f1SDimitry Andric }
182fe6060f1SDimitry Andric 
183*06c3fb27SDimitry Andric static Error sectionOverflowErrorOrWarning(uint32_t PrevOffset,
184*06c3fb27SDimitry Andric                                            uint32_t OverflowedOffset,
185*06c3fb27SDimitry Andric                                            StringRef SectionName,
186*06c3fb27SDimitry Andric                                            bool ContinueOnCuIndexOverflow) {
187*06c3fb27SDimitry Andric   std::string Msg =
188*06c3fb27SDimitry Andric       (SectionName +
189*06c3fb27SDimitry Andric        Twine(" Section Contribution Offset overflow 4G. Previous Offset ") +
190*06c3fb27SDimitry Andric        Twine(PrevOffset) + Twine(", After overflow offset ") +
191*06c3fb27SDimitry Andric        Twine(OverflowedOffset) + Twine("."))
192*06c3fb27SDimitry Andric           .str();
193*06c3fb27SDimitry Andric   if (ContinueOnCuIndexOverflow) {
194*06c3fb27SDimitry Andric     WithColor::defaultWarningHandler(make_error<DWPError>(Msg));
195*06c3fb27SDimitry Andric     return Error::success();
196*06c3fb27SDimitry Andric   }
197*06c3fb27SDimitry Andric   return make_error<DWPError>(Msg);
198*06c3fb27SDimitry Andric }
199*06c3fb27SDimitry Andric 
200*06c3fb27SDimitry Andric static Error addAllTypesFromDWP(
201*06c3fb27SDimitry Andric     MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
202*06c3fb27SDimitry Andric     const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types,
203*06c3fb27SDimitry Andric     const UnitIndexEntry &TUEntry, uint32_t &TypesOffset,
204*06c3fb27SDimitry Andric     unsigned TypesContributionIndex, bool ContinueOnCuIndexOverflow) {
20581ad6265SDimitry Andric   Out.switchSection(OutputTypes);
206fe6060f1SDimitry Andric   for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) {
207fe6060f1SDimitry Andric     auto *I = E.getContributions();
208fe6060f1SDimitry Andric     if (!I)
209fe6060f1SDimitry Andric       continue;
210fe6060f1SDimitry Andric     auto P = TypeIndexEntries.insert(std::make_pair(E.getSignature(), TUEntry));
211fe6060f1SDimitry Andric     if (!P.second)
212fe6060f1SDimitry Andric       continue;
213fe6060f1SDimitry Andric     auto &Entry = P.first->second;
214fe6060f1SDimitry Andric     // Zero out the debug_info contribution
215fe6060f1SDimitry Andric     Entry.Contributions[0] = {};
216fe6060f1SDimitry Andric     for (auto Kind : TUIndex.getColumnKinds()) {
217fe6060f1SDimitry Andric       if (!isSupportedSectionKind(Kind))
218fe6060f1SDimitry Andric         continue;
219fe6060f1SDimitry Andric       auto &C =
220fe6060f1SDimitry Andric           Entry.Contributions[getContributionIndex(Kind, TUIndex.getVersion())];
221bdd1243dSDimitry Andric       C.setOffset(C.getOffset() + I->getOffset());
222bdd1243dSDimitry Andric       C.setLength(I->getLength());
223fe6060f1SDimitry Andric       ++I;
224fe6060f1SDimitry Andric     }
225fe6060f1SDimitry Andric     auto &C = Entry.Contributions[TypesContributionIndex];
226fe6060f1SDimitry Andric     Out.emitBytes(Types.substr(
227bdd1243dSDimitry Andric         C.getOffset() -
228bdd1243dSDimitry Andric             TUEntry.Contributions[TypesContributionIndex].getOffset(),
229bdd1243dSDimitry Andric         C.getLength()));
230bdd1243dSDimitry Andric     C.setOffset(TypesOffset);
231*06c3fb27SDimitry Andric     uint32_t OldOffset = TypesOffset;
232*06c3fb27SDimitry Andric     static_assert(sizeof(OldOffset) == sizeof(TypesOffset));
233bdd1243dSDimitry Andric     TypesOffset += C.getLength();
234*06c3fb27SDimitry Andric     if (OldOffset > TypesOffset) {
235*06c3fb27SDimitry Andric       if (Error Err = sectionOverflowErrorOrWarning(
236*06c3fb27SDimitry Andric               OldOffset, TypesOffset, "Types", ContinueOnCuIndexOverflow))
237*06c3fb27SDimitry Andric         return Err;
238fe6060f1SDimitry Andric     }
239fe6060f1SDimitry Andric   }
240*06c3fb27SDimitry Andric   return Error::success();
241*06c3fb27SDimitry Andric }
242fe6060f1SDimitry Andric 
243*06c3fb27SDimitry Andric static Error addAllTypesFromTypesSection(
244fe6060f1SDimitry Andric     MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
245fe6060f1SDimitry Andric     MCSection *OutputTypes, const std::vector<StringRef> &TypesSections,
246*06c3fb27SDimitry Andric     const UnitIndexEntry &CUEntry, uint32_t &TypesOffset,
247*06c3fb27SDimitry Andric     bool ContinueOnCuIndexOverflow) {
248fe6060f1SDimitry Andric   for (StringRef Types : TypesSections) {
24981ad6265SDimitry Andric     Out.switchSection(OutputTypes);
250fe6060f1SDimitry Andric     uint64_t Offset = 0;
251fe6060f1SDimitry Andric     DataExtractor Data(Types, true, 0);
252fe6060f1SDimitry Andric     while (Data.isValidOffset(Offset)) {
253fe6060f1SDimitry Andric       UnitIndexEntry Entry = CUEntry;
254fe6060f1SDimitry Andric       // Zero out the debug_info contribution
255fe6060f1SDimitry Andric       Entry.Contributions[0] = {};
256fe6060f1SDimitry Andric       auto &C = Entry.Contributions[getContributionIndex(DW_SECT_EXT_TYPES, 2)];
257bdd1243dSDimitry Andric       C.setOffset(TypesOffset);
258fe6060f1SDimitry Andric       auto PrevOffset = Offset;
259fe6060f1SDimitry Andric       // Length of the unit, including the 4 byte length field.
260bdd1243dSDimitry Andric       C.setLength(Data.getU32(&Offset) + 4);
261fe6060f1SDimitry Andric 
262fe6060f1SDimitry Andric       Data.getU16(&Offset); // Version
263fe6060f1SDimitry Andric       Data.getU32(&Offset); // Abbrev offset
264fe6060f1SDimitry Andric       Data.getU8(&Offset);  // Address size
265fe6060f1SDimitry Andric       auto Signature = Data.getU64(&Offset);
266bdd1243dSDimitry Andric       Offset = PrevOffset + C.getLength32();
267fe6060f1SDimitry Andric 
268fe6060f1SDimitry Andric       auto P = TypeIndexEntries.insert(std::make_pair(Signature, Entry));
269fe6060f1SDimitry Andric       if (!P.second)
270fe6060f1SDimitry Andric         continue;
271fe6060f1SDimitry Andric 
272bdd1243dSDimitry Andric       Out.emitBytes(Types.substr(PrevOffset, C.getLength32()));
273*06c3fb27SDimitry Andric       uint32_t OldOffset = TypesOffset;
274bdd1243dSDimitry Andric       TypesOffset += C.getLength32();
275*06c3fb27SDimitry Andric       if (OldOffset > TypesOffset) {
276*06c3fb27SDimitry Andric         if (Error Err = sectionOverflowErrorOrWarning(
277*06c3fb27SDimitry Andric                 OldOffset, TypesOffset, "types", ContinueOnCuIndexOverflow))
278*06c3fb27SDimitry Andric           return Err;
279fe6060f1SDimitry Andric       }
280fe6060f1SDimitry Andric     }
281fe6060f1SDimitry Andric   }
282*06c3fb27SDimitry Andric   return Error::success();
283*06c3fb27SDimitry Andric }
284fe6060f1SDimitry Andric 
285fe6060f1SDimitry Andric static std::string buildDWODescription(StringRef Name, StringRef DWPName,
286fe6060f1SDimitry Andric                                        StringRef DWOName) {
287fe6060f1SDimitry Andric   std::string Text = "\'";
288fe6060f1SDimitry Andric   Text += Name;
289fe6060f1SDimitry Andric   Text += '\'';
290bdd1243dSDimitry Andric   bool HasDWO = !DWOName.empty();
291bdd1243dSDimitry Andric   bool HasDWP = !DWPName.empty();
292bdd1243dSDimitry Andric   if (HasDWO || HasDWP) {
293fe6060f1SDimitry Andric     Text += " (from ";
294bdd1243dSDimitry Andric     if (HasDWO) {
295fe6060f1SDimitry Andric       Text += '\'';
296fe6060f1SDimitry Andric       Text += DWOName;
297bdd1243dSDimitry Andric       Text += '\'';
298fe6060f1SDimitry Andric     }
299bdd1243dSDimitry Andric     if (HasDWO && HasDWP)
300bdd1243dSDimitry Andric       Text += " in ";
301bdd1243dSDimitry Andric     if (!DWPName.empty()) {
302fe6060f1SDimitry Andric       Text += '\'';
303fe6060f1SDimitry Andric       Text += DWPName;
304bdd1243dSDimitry Andric       Text += '\'';
305bdd1243dSDimitry Andric     }
306bdd1243dSDimitry Andric     Text += ")";
307fe6060f1SDimitry Andric   }
308fe6060f1SDimitry Andric   return Text;
309fe6060f1SDimitry Andric }
310fe6060f1SDimitry Andric 
311fe6060f1SDimitry Andric static Error createError(StringRef Name, Error E) {
312fe6060f1SDimitry Andric   return make_error<DWPError>(
313fe6060f1SDimitry Andric       ("failure while decompressing compressed section: '" + Name + "', " +
314fe6060f1SDimitry Andric        llvm::toString(std::move(E)))
315fe6060f1SDimitry Andric           .str());
316fe6060f1SDimitry Andric }
317fe6060f1SDimitry Andric 
318fe6060f1SDimitry Andric static Error
319fe6060f1SDimitry Andric handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections,
320fcaf7f86SDimitry Andric                         SectionRef Sec, StringRef Name, StringRef &Contents) {
321fcaf7f86SDimitry Andric   auto *Obj = dyn_cast<ELFObjectFileBase>(Sec.getObject());
322fcaf7f86SDimitry Andric   if (!Obj ||
323fcaf7f86SDimitry Andric       !(static_cast<ELFSectionRef>(Sec).getFlags() & ELF::SHF_COMPRESSED))
324fe6060f1SDimitry Andric     return Error::success();
325fcaf7f86SDimitry Andric   bool IsLE = isa<object::ELF32LEObjectFile>(Obj) ||
326fcaf7f86SDimitry Andric               isa<object::ELF64LEObjectFile>(Obj);
327fcaf7f86SDimitry Andric   bool Is64 = isa<object::ELF64LEObjectFile>(Obj) ||
328fcaf7f86SDimitry Andric               isa<object::ELF64BEObjectFile>(Obj);
329fcaf7f86SDimitry Andric   Expected<Decompressor> Dec = Decompressor::create(Name, Contents, IsLE, Is64);
330fe6060f1SDimitry Andric   if (!Dec)
331fe6060f1SDimitry Andric     return createError(Name, Dec.takeError());
332fe6060f1SDimitry Andric 
333fe6060f1SDimitry Andric   UncompressedSections.emplace_back();
334fe6060f1SDimitry Andric   if (Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
335fe6060f1SDimitry Andric     return createError(Name, std::move(E));
336fe6060f1SDimitry Andric 
337fe6060f1SDimitry Andric   Contents = UncompressedSections.back();
338fe6060f1SDimitry Andric   return Error::success();
339fe6060f1SDimitry Andric }
340fe6060f1SDimitry Andric 
341fe6060f1SDimitry Andric namespace llvm {
342fe6060f1SDimitry Andric // Parse and return the header of an info section compile/type unit.
343fe6060f1SDimitry Andric Expected<InfoSectionUnitHeader> parseInfoSectionUnitHeader(StringRef Info) {
344fe6060f1SDimitry Andric   InfoSectionUnitHeader Header;
345fe6060f1SDimitry Andric   Error Err = Error::success();
346fe6060f1SDimitry Andric   uint64_t Offset = 0;
347fe6060f1SDimitry Andric   DWARFDataExtractor InfoData(Info, true, 0);
348fe6060f1SDimitry Andric   std::tie(Header.Length, Header.Format) =
349fe6060f1SDimitry Andric       InfoData.getInitialLength(&Offset, &Err);
350fe6060f1SDimitry Andric   if (Err)
351fe6060f1SDimitry Andric     return make_error<DWPError>("cannot parse compile unit length: " +
352fe6060f1SDimitry Andric                                 llvm::toString(std::move(Err)));
353fe6060f1SDimitry Andric 
354fe6060f1SDimitry Andric   if (!InfoData.isValidOffset(Offset + (Header.Length - 1))) {
355fe6060f1SDimitry Andric     return make_error<DWPError>(
356fe6060f1SDimitry Andric         "compile unit exceeds .debug_info section range: " +
357fe6060f1SDimitry Andric         utostr(Offset + Header.Length) + " >= " + utostr(InfoData.size()));
358fe6060f1SDimitry Andric   }
359fe6060f1SDimitry Andric 
360fe6060f1SDimitry Andric   Header.Version = InfoData.getU16(&Offset, &Err);
361fe6060f1SDimitry Andric   if (Err)
362fe6060f1SDimitry Andric     return make_error<DWPError>("cannot parse compile unit version: " +
363fe6060f1SDimitry Andric                                 llvm::toString(std::move(Err)));
364fe6060f1SDimitry Andric 
365fe6060f1SDimitry Andric   uint64_t MinHeaderLength;
366fe6060f1SDimitry Andric   if (Header.Version >= 5) {
367fe6060f1SDimitry Andric     // Size: Version (2), UnitType (1), AddrSize (1), DebugAbbrevOffset (4),
368fe6060f1SDimitry Andric     // Signature (8)
369fe6060f1SDimitry Andric     MinHeaderLength = 16;
370fe6060f1SDimitry Andric   } else {
371fe6060f1SDimitry Andric     // Size: Version (2), DebugAbbrevOffset (4), AddrSize (1)
372fe6060f1SDimitry Andric     MinHeaderLength = 7;
373fe6060f1SDimitry Andric   }
374fe6060f1SDimitry Andric   if (Header.Length < MinHeaderLength) {
375fe6060f1SDimitry Andric     return make_error<DWPError>("unit length is too small: expected at least " +
376fe6060f1SDimitry Andric                                 utostr(MinHeaderLength) + " got " +
377fe6060f1SDimitry Andric                                 utostr(Header.Length) + ".");
378fe6060f1SDimitry Andric   }
379fe6060f1SDimitry Andric   if (Header.Version >= 5) {
380fe6060f1SDimitry Andric     Header.UnitType = InfoData.getU8(&Offset);
381fe6060f1SDimitry Andric     Header.AddrSize = InfoData.getU8(&Offset);
382fe6060f1SDimitry Andric     Header.DebugAbbrevOffset = InfoData.getU32(&Offset);
383fe6060f1SDimitry Andric     Header.Signature = InfoData.getU64(&Offset);
384fe6060f1SDimitry Andric     if (Header.UnitType == dwarf::DW_UT_split_type) {
385fe6060f1SDimitry Andric       // Type offset.
386fe6060f1SDimitry Andric       MinHeaderLength += 4;
387fe6060f1SDimitry Andric       if (Header.Length < MinHeaderLength)
388fe6060f1SDimitry Andric         return make_error<DWPError>("type unit is missing type offset");
389fe6060f1SDimitry Andric       InfoData.getU32(&Offset);
390fe6060f1SDimitry Andric     }
391fe6060f1SDimitry Andric   } else {
392fe6060f1SDimitry Andric     // Note that, address_size and debug_abbrev_offset fields have switched
393fe6060f1SDimitry Andric     // places between dwarf version 4 and 5.
394fe6060f1SDimitry Andric     Header.DebugAbbrevOffset = InfoData.getU32(&Offset);
395fe6060f1SDimitry Andric     Header.AddrSize = InfoData.getU8(&Offset);
396fe6060f1SDimitry Andric   }
397fe6060f1SDimitry Andric 
398fe6060f1SDimitry Andric   Header.HeaderSize = Offset;
399fe6060f1SDimitry Andric   return Header;
400fe6060f1SDimitry Andric }
401fe6060f1SDimitry Andric 
402fe6060f1SDimitry Andric void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,
403fe6060f1SDimitry Andric                             MCSection *StrOffsetSection,
404fe6060f1SDimitry Andric                             StringRef CurStrSection,
405fe6060f1SDimitry Andric                             StringRef CurStrOffsetSection, uint16_t Version) {
406fe6060f1SDimitry Andric   // Could possibly produce an error or warning if one of these was non-null but
407fe6060f1SDimitry Andric   // the other was null.
408fe6060f1SDimitry Andric   if (CurStrSection.empty() || CurStrOffsetSection.empty())
409fe6060f1SDimitry Andric     return;
410fe6060f1SDimitry Andric 
411fe6060f1SDimitry Andric   DenseMap<uint64_t, uint32_t> OffsetRemapping;
412fe6060f1SDimitry Andric 
413fe6060f1SDimitry Andric   DataExtractor Data(CurStrSection, true, 0);
414fe6060f1SDimitry Andric   uint64_t LocalOffset = 0;
415fe6060f1SDimitry Andric   uint64_t PrevOffset = 0;
416fe6060f1SDimitry Andric   while (const char *S = Data.getCStr(&LocalOffset)) {
417fe6060f1SDimitry Andric     OffsetRemapping[PrevOffset] =
418fe6060f1SDimitry Andric         Strings.getOffset(S, LocalOffset - PrevOffset);
419fe6060f1SDimitry Andric     PrevOffset = LocalOffset;
420fe6060f1SDimitry Andric   }
421fe6060f1SDimitry Andric 
422fe6060f1SDimitry Andric   Data = DataExtractor(CurStrOffsetSection, true, 0);
423fe6060f1SDimitry Andric 
42481ad6265SDimitry Andric   Out.switchSection(StrOffsetSection);
425fe6060f1SDimitry Andric 
426fe6060f1SDimitry Andric   uint64_t HeaderSize = debugStrOffsetsHeaderSize(Data, Version);
427fe6060f1SDimitry Andric   uint64_t Offset = 0;
428fe6060f1SDimitry Andric   uint64_t Size = CurStrOffsetSection.size();
429fe6060f1SDimitry Andric   // FIXME: This can be caused by bad input and should be handled as such.
430fe6060f1SDimitry Andric   assert(HeaderSize <= Size && "StrOffsetSection size is less than its header");
431fe6060f1SDimitry Andric   // Copy the header to the output.
432fe6060f1SDimitry Andric   Out.emitBytes(Data.getBytes(&Offset, HeaderSize));
433fe6060f1SDimitry Andric   while (Offset < Size) {
434fe6060f1SDimitry Andric     auto OldOffset = Data.getU32(&Offset);
435fe6060f1SDimitry Andric     auto NewOffset = OffsetRemapping[OldOffset];
436fe6060f1SDimitry Andric     Out.emitIntValue(NewOffset, 4);
437fe6060f1SDimitry Andric   }
438fe6060f1SDimitry Andric }
439fe6060f1SDimitry Andric 
440bdd1243dSDimitry Andric enum AccessField { Offset, Length };
441bdd1243dSDimitry Andric void writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
442fe6060f1SDimitry Andric                      const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
443bdd1243dSDimitry Andric                      const AccessField &Field) {
444fe6060f1SDimitry Andric   for (const auto &E : IndexEntries)
445bdd1243dSDimitry Andric     for (size_t I = 0; I != std::size(E.second.Contributions); ++I)
446fe6060f1SDimitry Andric       if (ContributionOffsets[I])
447bdd1243dSDimitry Andric         Out.emitIntValue((Field == AccessField::Offset
448bdd1243dSDimitry Andric                               ? E.second.Contributions[I].getOffset32()
449bdd1243dSDimitry Andric                               : E.second.Contributions[I].getLength32()),
450bdd1243dSDimitry Andric                          4);
451fe6060f1SDimitry Andric }
452fe6060f1SDimitry Andric 
453fe6060f1SDimitry Andric void writeIndex(MCStreamer &Out, MCSection *Section,
454fe6060f1SDimitry Andric                 ArrayRef<unsigned> ContributionOffsets,
455fe6060f1SDimitry Andric                 const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
456fe6060f1SDimitry Andric                 uint32_t IndexVersion) {
457fe6060f1SDimitry Andric   if (IndexEntries.empty())
458fe6060f1SDimitry Andric     return;
459fe6060f1SDimitry Andric 
460fe6060f1SDimitry Andric   unsigned Columns = 0;
461fe6060f1SDimitry Andric   for (auto &C : ContributionOffsets)
462fe6060f1SDimitry Andric     if (C)
463fe6060f1SDimitry Andric       ++Columns;
464fe6060f1SDimitry Andric 
465fe6060f1SDimitry Andric   std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
466fe6060f1SDimitry Andric   uint64_t Mask = Buckets.size() - 1;
467fe6060f1SDimitry Andric   size_t I = 0;
468fe6060f1SDimitry Andric   for (const auto &P : IndexEntries) {
469fe6060f1SDimitry Andric     auto S = P.first;
470fe6060f1SDimitry Andric     auto H = S & Mask;
471fe6060f1SDimitry Andric     auto HP = ((S >> 32) & Mask) | 1;
472fe6060f1SDimitry Andric     while (Buckets[H]) {
473fe6060f1SDimitry Andric       assert(S != IndexEntries.begin()[Buckets[H] - 1].first &&
474fe6060f1SDimitry Andric              "Duplicate unit");
475fe6060f1SDimitry Andric       H = (H + HP) & Mask;
476fe6060f1SDimitry Andric     }
477fe6060f1SDimitry Andric     Buckets[H] = I + 1;
478fe6060f1SDimitry Andric     ++I;
479fe6060f1SDimitry Andric   }
480fe6060f1SDimitry Andric 
48181ad6265SDimitry Andric   Out.switchSection(Section);
482fe6060f1SDimitry Andric   Out.emitIntValue(IndexVersion, 4);        // Version
483fe6060f1SDimitry Andric   Out.emitIntValue(Columns, 4);             // Columns
484fe6060f1SDimitry Andric   Out.emitIntValue(IndexEntries.size(), 4); // Num Units
485fe6060f1SDimitry Andric   Out.emitIntValue(Buckets.size(), 4);      // Num Buckets
486fe6060f1SDimitry Andric 
487fe6060f1SDimitry Andric   // Write the signatures.
488fe6060f1SDimitry Andric   for (const auto &I : Buckets)
489fe6060f1SDimitry Andric     Out.emitIntValue(I ? IndexEntries.begin()[I - 1].first : 0, 8);
490fe6060f1SDimitry Andric 
491fe6060f1SDimitry Andric   // Write the indexes.
492fe6060f1SDimitry Andric   for (const auto &I : Buckets)
493fe6060f1SDimitry Andric     Out.emitIntValue(I, 4);
494fe6060f1SDimitry Andric 
495fe6060f1SDimitry Andric   // Write the column headers (which sections will appear in the table)
496fe6060f1SDimitry Andric   for (size_t I = 0; I != ContributionOffsets.size(); ++I)
497fe6060f1SDimitry Andric     if (ContributionOffsets[I])
498fe6060f1SDimitry Andric       Out.emitIntValue(getOnDiskSectionId(I), 4);
499fe6060f1SDimitry Andric 
500fe6060f1SDimitry Andric   // Write the offsets.
501bdd1243dSDimitry Andric   writeIndexTable(Out, ContributionOffsets, IndexEntries, AccessField::Offset);
502fe6060f1SDimitry Andric 
503fe6060f1SDimitry Andric   // Write the lengths.
504bdd1243dSDimitry Andric   writeIndexTable(Out, ContributionOffsets, IndexEntries, AccessField::Length);
505fe6060f1SDimitry Andric }
506fe6060f1SDimitry Andric 
507fe6060f1SDimitry Andric Error buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
508fe6060f1SDimitry Andric                           const CompileUnitIdentifiers &ID, StringRef DWPName) {
509fe6060f1SDimitry Andric   return make_error<DWPError>(
510fe6060f1SDimitry Andric       std::string("duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " +
511fe6060f1SDimitry Andric       buildDWODescription(PrevE.second.Name, PrevE.second.DWPName,
512fe6060f1SDimitry Andric                           PrevE.second.DWOName) +
513fe6060f1SDimitry Andric       " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));
514fe6060f1SDimitry Andric }
515fe6060f1SDimitry Andric 
516fe6060f1SDimitry Andric Error handleSection(
517fe6060f1SDimitry Andric     const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
518fe6060f1SDimitry Andric     const MCSection *StrSection, const MCSection *StrOffsetSection,
519fe6060f1SDimitry Andric     const MCSection *TypesSection, const MCSection *CUIndexSection,
520fe6060f1SDimitry Andric     const MCSection *TUIndexSection, const MCSection *InfoSection,
521fe6060f1SDimitry Andric     const SectionRef &Section, MCStreamer &Out,
522fe6060f1SDimitry Andric     std::deque<SmallString<32>> &UncompressedSections,
523fe6060f1SDimitry Andric     uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry,
524fe6060f1SDimitry Andric     StringRef &CurStrSection, StringRef &CurStrOffsetSection,
525fe6060f1SDimitry Andric     std::vector<StringRef> &CurTypesSection,
526fe6060f1SDimitry Andric     std::vector<StringRef> &CurInfoSection, StringRef &AbbrevSection,
527fe6060f1SDimitry Andric     StringRef &CurCUIndexSection, StringRef &CurTUIndexSection,
528fe6060f1SDimitry Andric     std::vector<std::pair<DWARFSectionKind, uint32_t>> &SectionLength) {
529fe6060f1SDimitry Andric   if (Section.isBSS())
530fe6060f1SDimitry Andric     return Error::success();
531fe6060f1SDimitry Andric 
532fe6060f1SDimitry Andric   if (Section.isVirtual())
533fe6060f1SDimitry Andric     return Error::success();
534fe6060f1SDimitry Andric 
535fe6060f1SDimitry Andric   Expected<StringRef> NameOrErr = Section.getName();
536fe6060f1SDimitry Andric   if (!NameOrErr)
537fe6060f1SDimitry Andric     return NameOrErr.takeError();
538fe6060f1SDimitry Andric   StringRef Name = *NameOrErr;
539fe6060f1SDimitry Andric 
540fe6060f1SDimitry Andric   Expected<StringRef> ContentsOrErr = Section.getContents();
541fe6060f1SDimitry Andric   if (!ContentsOrErr)
542fe6060f1SDimitry Andric     return ContentsOrErr.takeError();
543fe6060f1SDimitry Andric   StringRef Contents = *ContentsOrErr;
544fe6060f1SDimitry Andric 
545fcaf7f86SDimitry Andric   if (auto Err = handleCompressedSection(UncompressedSections, Section, Name,
546fcaf7f86SDimitry Andric                                          Contents))
547fe6060f1SDimitry Andric     return Err;
548fe6060f1SDimitry Andric 
549fe6060f1SDimitry Andric   Name = Name.substr(Name.find_first_not_of("._"));
550fe6060f1SDimitry Andric 
551fe6060f1SDimitry Andric   auto SectionPair = KnownSections.find(Name);
552fe6060f1SDimitry Andric   if (SectionPair == KnownSections.end())
553fe6060f1SDimitry Andric     return Error::success();
554fe6060f1SDimitry Andric 
555fe6060f1SDimitry Andric   if (DWARFSectionKind Kind = SectionPair->second.second) {
556fe6060f1SDimitry Andric     if (Kind != DW_SECT_EXT_TYPES && Kind != DW_SECT_INFO) {
557fe6060f1SDimitry Andric       SectionLength.push_back(std::make_pair(Kind, Contents.size()));
558fe6060f1SDimitry Andric     }
559fe6060f1SDimitry Andric 
560fe6060f1SDimitry Andric     if (Kind == DW_SECT_ABBREV) {
561fe6060f1SDimitry Andric       AbbrevSection = Contents;
562fe6060f1SDimitry Andric     }
563fe6060f1SDimitry Andric   }
564fe6060f1SDimitry Andric 
565fe6060f1SDimitry Andric   MCSection *OutSection = SectionPair->second.first;
566fe6060f1SDimitry Andric   if (OutSection == StrOffsetSection)
567fe6060f1SDimitry Andric     CurStrOffsetSection = Contents;
568fe6060f1SDimitry Andric   else if (OutSection == StrSection)
569fe6060f1SDimitry Andric     CurStrSection = Contents;
570fe6060f1SDimitry Andric   else if (OutSection == TypesSection)
571fe6060f1SDimitry Andric     CurTypesSection.push_back(Contents);
572fe6060f1SDimitry Andric   else if (OutSection == CUIndexSection)
573fe6060f1SDimitry Andric     CurCUIndexSection = Contents;
574fe6060f1SDimitry Andric   else if (OutSection == TUIndexSection)
575fe6060f1SDimitry Andric     CurTUIndexSection = Contents;
576fe6060f1SDimitry Andric   else if (OutSection == InfoSection)
577fe6060f1SDimitry Andric     CurInfoSection.push_back(Contents);
578fe6060f1SDimitry Andric   else {
57981ad6265SDimitry Andric     Out.switchSection(OutSection);
580fe6060f1SDimitry Andric     Out.emitBytes(Contents);
581fe6060f1SDimitry Andric   }
582fe6060f1SDimitry Andric   return Error::success();
583fe6060f1SDimitry Andric }
584fe6060f1SDimitry Andric 
585*06c3fb27SDimitry Andric Error write(MCStreamer &Out, ArrayRef<std::string> Inputs,
586*06c3fb27SDimitry Andric             bool ContinueOnCuIndexOverflow) {
587fe6060f1SDimitry Andric   const auto &MCOFI = *Out.getContext().getObjectFileInfo();
588fe6060f1SDimitry Andric   MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
589fe6060f1SDimitry Andric   MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
590fe6060f1SDimitry Andric   MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection();
591fe6060f1SDimitry Andric   MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection();
592fe6060f1SDimitry Andric   MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection();
593fe6060f1SDimitry Andric   MCSection *const InfoSection = MCOFI.getDwarfInfoDWOSection();
594fe6060f1SDimitry Andric   const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = {
595fe6060f1SDimitry Andric       {"debug_info.dwo", {InfoSection, DW_SECT_INFO}},
596fe6060f1SDimitry Andric       {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},
597fe6060f1SDimitry Andric       {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
598fe6060f1SDimitry Andric       {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}},
599fe6060f1SDimitry Andric       {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},
600fe6060f1SDimitry Andric       {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
601fe6060f1SDimitry Andric       {"debug_macro.dwo", {MCOFI.getDwarfMacroDWOSection(), DW_SECT_MACRO}},
602fe6060f1SDimitry Andric       {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
603fe6060f1SDimitry Andric       {"debug_loclists.dwo",
604fe6060f1SDimitry Andric        {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},
605fe6060f1SDimitry Andric       {"debug_rnglists.dwo",
606fe6060f1SDimitry Andric        {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}},
607fe6060f1SDimitry Andric       {"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}},
608fe6060f1SDimitry Andric       {"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};
609fe6060f1SDimitry Andric 
610fe6060f1SDimitry Andric   MapVector<uint64_t, UnitIndexEntry> IndexEntries;
611fe6060f1SDimitry Andric   MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
612fe6060f1SDimitry Andric 
613fe6060f1SDimitry Andric   uint32_t ContributionOffsets[8] = {};
614fe6060f1SDimitry Andric   uint16_t Version = 0;
615fe6060f1SDimitry Andric   uint32_t IndexVersion = 0;
616fe6060f1SDimitry Andric 
617fe6060f1SDimitry Andric   DWPStringPool Strings(Out, StrSection);
618fe6060f1SDimitry Andric 
619fe6060f1SDimitry Andric   SmallVector<OwningBinary<object::ObjectFile>, 128> Objects;
620fe6060f1SDimitry Andric   Objects.reserve(Inputs.size());
621fe6060f1SDimitry Andric 
622fe6060f1SDimitry Andric   std::deque<SmallString<32>> UncompressedSections;
623fe6060f1SDimitry Andric 
624fe6060f1SDimitry Andric   for (const auto &Input : Inputs) {
625fe6060f1SDimitry Andric     auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
626bdd1243dSDimitry Andric     if (!ErrOrObj) {
627bdd1243dSDimitry Andric       return handleErrors(ErrOrObj.takeError(),
628bdd1243dSDimitry Andric                           [&](std::unique_ptr<ECError> EC) -> Error {
629bdd1243dSDimitry Andric                             return createFileError(Input, Error(std::move(EC)));
630bdd1243dSDimitry Andric                           });
631bdd1243dSDimitry Andric     }
632fe6060f1SDimitry Andric 
633fe6060f1SDimitry Andric     auto &Obj = *ErrOrObj->getBinary();
634fe6060f1SDimitry Andric     Objects.push_back(std::move(*ErrOrObj));
635fe6060f1SDimitry Andric 
636fe6060f1SDimitry Andric     UnitIndexEntry CurEntry = {};
637fe6060f1SDimitry Andric 
638fe6060f1SDimitry Andric     StringRef CurStrSection;
639fe6060f1SDimitry Andric     StringRef CurStrOffsetSection;
640fe6060f1SDimitry Andric     std::vector<StringRef> CurTypesSection;
641fe6060f1SDimitry Andric     std::vector<StringRef> CurInfoSection;
642fe6060f1SDimitry Andric     StringRef AbbrevSection;
643fe6060f1SDimitry Andric     StringRef CurCUIndexSection;
644fe6060f1SDimitry Andric     StringRef CurTUIndexSection;
645fe6060f1SDimitry Andric 
646fe6060f1SDimitry Andric     // This maps each section contained in this file to its length.
647fe6060f1SDimitry Andric     // This information is later on used to calculate the contributions,
648fe6060f1SDimitry Andric     // i.e. offset and length, of each compile/type unit to a section.
649fe6060f1SDimitry Andric     std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength;
650fe6060f1SDimitry Andric 
651fe6060f1SDimitry Andric     for (const auto &Section : Obj.sections())
652fe6060f1SDimitry Andric       if (auto Err = handleSection(
653fe6060f1SDimitry Andric               KnownSections, StrSection, StrOffsetSection, TypesSection,
654fe6060f1SDimitry Andric               CUIndexSection, TUIndexSection, InfoSection, Section, Out,
655fe6060f1SDimitry Andric               UncompressedSections, ContributionOffsets, CurEntry,
656fe6060f1SDimitry Andric               CurStrSection, CurStrOffsetSection, CurTypesSection,
657fe6060f1SDimitry Andric               CurInfoSection, AbbrevSection, CurCUIndexSection,
658fe6060f1SDimitry Andric               CurTUIndexSection, SectionLength))
659fe6060f1SDimitry Andric         return Err;
660fe6060f1SDimitry Andric 
661fe6060f1SDimitry Andric     if (CurInfoSection.empty())
662fe6060f1SDimitry Andric       continue;
663fe6060f1SDimitry Andric 
664fe6060f1SDimitry Andric     Expected<InfoSectionUnitHeader> HeaderOrErr =
665fe6060f1SDimitry Andric         parseInfoSectionUnitHeader(CurInfoSection.front());
666fe6060f1SDimitry Andric     if (!HeaderOrErr)
667fe6060f1SDimitry Andric       return HeaderOrErr.takeError();
668fe6060f1SDimitry Andric     InfoSectionUnitHeader &Header = *HeaderOrErr;
669fe6060f1SDimitry Andric 
670fe6060f1SDimitry Andric     if (Version == 0) {
671fe6060f1SDimitry Andric       Version = Header.Version;
672fe6060f1SDimitry Andric       IndexVersion = Version < 5 ? 2 : 5;
673fe6060f1SDimitry Andric     } else if (Version != Header.Version) {
674fe6060f1SDimitry Andric       return make_error<DWPError>("incompatible DWARF compile unit versions.");
675fe6060f1SDimitry Andric     }
676fe6060f1SDimitry Andric 
677fe6060f1SDimitry Andric     writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection,
678fe6060f1SDimitry Andric                            CurStrOffsetSection, Header.Version);
679fe6060f1SDimitry Andric 
680fe6060f1SDimitry Andric     for (auto Pair : SectionLength) {
681fe6060f1SDimitry Andric       auto Index = getContributionIndex(Pair.first, IndexVersion);
682bdd1243dSDimitry Andric       CurEntry.Contributions[Index].setOffset(ContributionOffsets[Index]);
683bdd1243dSDimitry Andric       CurEntry.Contributions[Index].setLength(Pair.second);
684*06c3fb27SDimitry Andric       uint32_t OldOffset = ContributionOffsets[Index];
685bdd1243dSDimitry Andric       ContributionOffsets[Index] += CurEntry.Contributions[Index].getLength32();
686*06c3fb27SDimitry Andric       if (OldOffset > ContributionOffsets[Index]) {
687*06c3fb27SDimitry Andric         uint32_t SectionIndex = 0;
688*06c3fb27SDimitry Andric         for (auto &Section : Obj.sections()) {
689*06c3fb27SDimitry Andric           if (SectionIndex == Index) {
690*06c3fb27SDimitry Andric             return sectionOverflowErrorOrWarning(
691*06c3fb27SDimitry Andric                 OldOffset, ContributionOffsets[Index], *Section.getName(),
692*06c3fb27SDimitry Andric                 ContinueOnCuIndexOverflow);
693*06c3fb27SDimitry Andric           }
694*06c3fb27SDimitry Andric           ++SectionIndex;
695*06c3fb27SDimitry Andric         }
696*06c3fb27SDimitry Andric       }
697fe6060f1SDimitry Andric     }
698fe6060f1SDimitry Andric 
699fe6060f1SDimitry Andric     uint32_t &InfoSectionOffset =
700fe6060f1SDimitry Andric         ContributionOffsets[getContributionIndex(DW_SECT_INFO, IndexVersion)];
701fe6060f1SDimitry Andric     if (CurCUIndexSection.empty()) {
702fe6060f1SDimitry Andric       bool FoundCUUnit = false;
70381ad6265SDimitry Andric       Out.switchSection(InfoSection);
704fe6060f1SDimitry Andric       for (StringRef Info : CurInfoSection) {
705fe6060f1SDimitry Andric         uint64_t UnitOffset = 0;
706fe6060f1SDimitry Andric         while (Info.size() > UnitOffset) {
707fe6060f1SDimitry Andric           Expected<InfoSectionUnitHeader> HeaderOrError =
708fe6060f1SDimitry Andric               parseInfoSectionUnitHeader(Info.substr(UnitOffset, Info.size()));
709fe6060f1SDimitry Andric           if (!HeaderOrError)
710fe6060f1SDimitry Andric             return HeaderOrError.takeError();
711fe6060f1SDimitry Andric           InfoSectionUnitHeader &Header = *HeaderOrError;
712fe6060f1SDimitry Andric 
713fe6060f1SDimitry Andric           UnitIndexEntry Entry = CurEntry;
714fe6060f1SDimitry Andric           auto &C = Entry.Contributions[getContributionIndex(DW_SECT_INFO,
715fe6060f1SDimitry Andric                                                              IndexVersion)];
716bdd1243dSDimitry Andric           C.setOffset(InfoSectionOffset);
717bdd1243dSDimitry Andric           C.setLength(Header.Length + 4);
718972a253aSDimitry Andric 
719972a253aSDimitry Andric           if (std::numeric_limits<uint32_t>::max() - InfoSectionOffset <
720*06c3fb27SDimitry Andric               C.getLength32()) {
721*06c3fb27SDimitry Andric             if (Error Err = sectionOverflowErrorOrWarning(
722*06c3fb27SDimitry Andric                     InfoSectionOffset, InfoSectionOffset + C.getLength32(),
723*06c3fb27SDimitry Andric                     "debug_info", ContinueOnCuIndexOverflow))
724*06c3fb27SDimitry Andric               return Err;
725*06c3fb27SDimitry Andric           }
726972a253aSDimitry Andric 
727bdd1243dSDimitry Andric           UnitOffset += C.getLength32();
728fe6060f1SDimitry Andric           if (Header.Version < 5 ||
729fe6060f1SDimitry Andric               Header.UnitType == dwarf::DW_UT_split_compile) {
730bdd1243dSDimitry Andric             Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
731bdd1243dSDimitry Andric                 Header, AbbrevSection,
732bdd1243dSDimitry Andric                 Info.substr(UnitOffset - C.getLength32(), C.getLength32()),
733fe6060f1SDimitry Andric                 CurStrOffsetSection, CurStrSection);
734fe6060f1SDimitry Andric 
735fe6060f1SDimitry Andric             if (!EID)
736fe6060f1SDimitry Andric               return createFileError(Input, EID.takeError());
737fe6060f1SDimitry Andric             const auto &ID = *EID;
738fe6060f1SDimitry Andric             auto P = IndexEntries.insert(std::make_pair(ID.Signature, Entry));
739fe6060f1SDimitry Andric             if (!P.second)
740fe6060f1SDimitry Andric               return buildDuplicateError(*P.first, ID, "");
741fe6060f1SDimitry Andric             P.first->second.Name = ID.Name;
742fe6060f1SDimitry Andric             P.first->second.DWOName = ID.DWOName;
743fe6060f1SDimitry Andric 
744fe6060f1SDimitry Andric             FoundCUUnit = true;
745fe6060f1SDimitry Andric           } else if (Header.UnitType == dwarf::DW_UT_split_type) {
746fe6060f1SDimitry Andric             auto P = TypeIndexEntries.insert(
74781ad6265SDimitry Andric                 std::make_pair(*Header.Signature, Entry));
748fe6060f1SDimitry Andric             if (!P.second)
749fe6060f1SDimitry Andric               continue;
750fe6060f1SDimitry Andric           }
751bdd1243dSDimitry Andric           Out.emitBytes(
752bdd1243dSDimitry Andric               Info.substr(UnitOffset - C.getLength32(), C.getLength32()));
753bdd1243dSDimitry Andric           InfoSectionOffset += C.getLength32();
754fe6060f1SDimitry Andric         }
755fe6060f1SDimitry Andric       }
756fe6060f1SDimitry Andric 
757fe6060f1SDimitry Andric       if (!FoundCUUnit)
758fe6060f1SDimitry Andric         return make_error<DWPError>("no compile unit found in file: " + Input);
759fe6060f1SDimitry Andric 
760fe6060f1SDimitry Andric       if (IndexVersion == 2) {
761fe6060f1SDimitry Andric         // Add types from the .debug_types section from DWARF < 5.
762*06c3fb27SDimitry Andric         if (Error Err = addAllTypesFromTypesSection(
763fe6060f1SDimitry Andric                 Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry,
764*06c3fb27SDimitry Andric                 ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)],
765*06c3fb27SDimitry Andric                 ContinueOnCuIndexOverflow))
766*06c3fb27SDimitry Andric           return Err;
767fe6060f1SDimitry Andric       }
768fe6060f1SDimitry Andric       continue;
769fe6060f1SDimitry Andric     }
770fe6060f1SDimitry Andric 
771fe6060f1SDimitry Andric     if (CurInfoSection.size() != 1)
772fe6060f1SDimitry Andric       return make_error<DWPError>("expected exactly one occurrence of a debug "
773fe6060f1SDimitry Andric                                   "info section in a .dwp file");
774fe6060f1SDimitry Andric     StringRef DwpSingleInfoSection = CurInfoSection.front();
775fe6060f1SDimitry Andric 
776fe6060f1SDimitry Andric     DWARFUnitIndex CUIndex(DW_SECT_INFO);
777fe6060f1SDimitry Andric     DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
778fe6060f1SDimitry Andric     if (!CUIndex.parse(CUIndexData))
779fe6060f1SDimitry Andric       return make_error<DWPError>("failed to parse cu_index");
780fe6060f1SDimitry Andric     if (CUIndex.getVersion() != IndexVersion)
781fe6060f1SDimitry Andric       return make_error<DWPError>("incompatible cu_index versions, found " +
782fe6060f1SDimitry Andric                                   utostr(CUIndex.getVersion()) +
783fe6060f1SDimitry Andric                                   " and expecting " + utostr(IndexVersion));
784fe6060f1SDimitry Andric 
78581ad6265SDimitry Andric     Out.switchSection(InfoSection);
786fe6060f1SDimitry Andric     for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
787fe6060f1SDimitry Andric       auto *I = E.getContributions();
788fe6060f1SDimitry Andric       if (!I)
789fe6060f1SDimitry Andric         continue;
790fe6060f1SDimitry Andric       auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry));
791fe6060f1SDimitry Andric       StringRef CUInfoSection =
792fe6060f1SDimitry Andric           getSubsection(DwpSingleInfoSection, E, DW_SECT_INFO);
793fe6060f1SDimitry Andric       Expected<InfoSectionUnitHeader> HeaderOrError =
794fe6060f1SDimitry Andric           parseInfoSectionUnitHeader(CUInfoSection);
795fe6060f1SDimitry Andric       if (!HeaderOrError)
796fe6060f1SDimitry Andric         return HeaderOrError.takeError();
797fe6060f1SDimitry Andric       InfoSectionUnitHeader &Header = *HeaderOrError;
798fe6060f1SDimitry Andric 
799fe6060f1SDimitry Andric       Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
800fe6060f1SDimitry Andric           Header, getSubsection(AbbrevSection, E, DW_SECT_ABBREV),
801fe6060f1SDimitry Andric           CUInfoSection,
802fe6060f1SDimitry Andric           getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS),
803fe6060f1SDimitry Andric           CurStrSection);
804fe6060f1SDimitry Andric       if (!EID)
805fe6060f1SDimitry Andric         return createFileError(Input, EID.takeError());
806fe6060f1SDimitry Andric       const auto &ID = *EID;
807fe6060f1SDimitry Andric       if (!P.second)
808fe6060f1SDimitry Andric         return buildDuplicateError(*P.first, ID, Input);
809fe6060f1SDimitry Andric       auto &NewEntry = P.first->second;
810fe6060f1SDimitry Andric       NewEntry.Name = ID.Name;
811fe6060f1SDimitry Andric       NewEntry.DWOName = ID.DWOName;
812fe6060f1SDimitry Andric       NewEntry.DWPName = Input;
813fe6060f1SDimitry Andric       for (auto Kind : CUIndex.getColumnKinds()) {
814fe6060f1SDimitry Andric         if (!isSupportedSectionKind(Kind))
815fe6060f1SDimitry Andric           continue;
816fe6060f1SDimitry Andric         auto &C =
817fe6060f1SDimitry Andric             NewEntry.Contributions[getContributionIndex(Kind, IndexVersion)];
818bdd1243dSDimitry Andric         C.setOffset(C.getOffset() + I->getOffset());
819bdd1243dSDimitry Andric         C.setLength(I->getLength());
820fe6060f1SDimitry Andric         ++I;
821fe6060f1SDimitry Andric       }
822fe6060f1SDimitry Andric       unsigned Index = getContributionIndex(DW_SECT_INFO, IndexVersion);
823fe6060f1SDimitry Andric       auto &C = NewEntry.Contributions[Index];
824fe6060f1SDimitry Andric       Out.emitBytes(CUInfoSection);
825bdd1243dSDimitry Andric       C.setOffset(InfoSectionOffset);
826bdd1243dSDimitry Andric       InfoSectionOffset += C.getLength32();
827fe6060f1SDimitry Andric     }
828fe6060f1SDimitry Andric 
829fe6060f1SDimitry Andric     if (!CurTUIndexSection.empty()) {
830fe6060f1SDimitry Andric       llvm::DWARFSectionKind TUSectionKind;
831fe6060f1SDimitry Andric       MCSection *OutSection;
832fe6060f1SDimitry Andric       StringRef TypeInputSection;
833fe6060f1SDimitry Andric       // Write type units into debug info section for DWARFv5.
834fe6060f1SDimitry Andric       if (Version >= 5) {
835fe6060f1SDimitry Andric         TUSectionKind = DW_SECT_INFO;
836fe6060f1SDimitry Andric         OutSection = InfoSection;
837fe6060f1SDimitry Andric         TypeInputSection = DwpSingleInfoSection;
838fe6060f1SDimitry Andric       } else {
839fe6060f1SDimitry Andric         // Write type units into debug types section for DWARF < 5.
840fe6060f1SDimitry Andric         if (CurTypesSection.size() != 1)
841fe6060f1SDimitry Andric           return make_error<DWPError>(
842fe6060f1SDimitry Andric               "multiple type unit sections in .dwp file");
843fe6060f1SDimitry Andric 
844fe6060f1SDimitry Andric         TUSectionKind = DW_SECT_EXT_TYPES;
845fe6060f1SDimitry Andric         OutSection = TypesSection;
846fe6060f1SDimitry Andric         TypeInputSection = CurTypesSection.front();
847fe6060f1SDimitry Andric       }
848fe6060f1SDimitry Andric 
849fe6060f1SDimitry Andric       DWARFUnitIndex TUIndex(TUSectionKind);
850fe6060f1SDimitry Andric       DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);
851fe6060f1SDimitry Andric       if (!TUIndex.parse(TUIndexData))
852fe6060f1SDimitry Andric         return make_error<DWPError>("failed to parse tu_index");
853fe6060f1SDimitry Andric       if (TUIndex.getVersion() != IndexVersion)
854fe6060f1SDimitry Andric         return make_error<DWPError>("incompatible tu_index versions, found " +
855fe6060f1SDimitry Andric                                     utostr(TUIndex.getVersion()) +
856fe6060f1SDimitry Andric                                     " and expecting " + utostr(IndexVersion));
857fe6060f1SDimitry Andric 
858fe6060f1SDimitry Andric       unsigned TypesContributionIndex =
859fe6060f1SDimitry Andric           getContributionIndex(TUSectionKind, IndexVersion);
860*06c3fb27SDimitry Andric       if (Error Err = addAllTypesFromDWP(
861*06c3fb27SDimitry Andric               Out, TypeIndexEntries, TUIndex, OutSection, TypeInputSection,
862*06c3fb27SDimitry Andric               CurEntry, ContributionOffsets[TypesContributionIndex],
863*06c3fb27SDimitry Andric               TypesContributionIndex, ContinueOnCuIndexOverflow))
864*06c3fb27SDimitry Andric         return Err;
865fe6060f1SDimitry Andric     }
866fe6060f1SDimitry Andric   }
867fe6060f1SDimitry Andric 
868fe6060f1SDimitry Andric   if (Version < 5) {
869fe6060f1SDimitry Andric     // Lie about there being no info contributions so the TU index only includes
870fe6060f1SDimitry Andric     // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a
871fe6060f1SDimitry Andric     // contribution to the info section, so we do not want to lie about it.
872fe6060f1SDimitry Andric     ContributionOffsets[0] = 0;
873fe6060f1SDimitry Andric   }
874fe6060f1SDimitry Andric   writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
875fe6060f1SDimitry Andric              TypeIndexEntries, IndexVersion);
876fe6060f1SDimitry Andric 
877fe6060f1SDimitry Andric   if (Version < 5) {
878fe6060f1SDimitry Andric     // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
879fe6060f1SDimitry Andric     // section does not exist, so no need to do anything about this.
880fe6060f1SDimitry Andric     ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0;
881fe6060f1SDimitry Andric     // Unlie about the info contribution
882fe6060f1SDimitry Andric     ContributionOffsets[0] = 1;
883fe6060f1SDimitry Andric   }
884fe6060f1SDimitry Andric 
885fe6060f1SDimitry Andric   writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
886fe6060f1SDimitry Andric              IndexEntries, IndexVersion);
887fe6060f1SDimitry Andric 
888fe6060f1SDimitry Andric   return Error::success();
889fe6060f1SDimitry Andric }
890fe6060f1SDimitry Andric } // namespace llvm
891