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