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