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