xref: /freebsd-src/contrib/llvm-project/llvm/lib/DWP/DWP.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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"
1406c3fb27SDimitry Andric #include "llvm/ADT/Twine.h"
15fe6060f1SDimitry Andric #include "llvm/DWP/DWPError.h"
16fe6060f1SDimitry Andric #include "llvm/MC/MCContext.h"
17fe6060f1SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
18fe6060f1SDimitry Andric #include "llvm/MC/MCTargetOptionsCommandFlags.h"
19fe6060f1SDimitry Andric #include "llvm/Object/Decompressor.h"
20fcaf7f86SDimitry Andric #include "llvm/Object/ELFObjectFile.h"
2106c3fb27SDimitry Andric #include "llvm/Support/CommandLine.h"
2281ad6265SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
23972a253aSDimitry Andric #include <limits>
24fe6060f1SDimitry Andric 
25fe6060f1SDimitry Andric using namespace llvm;
26fe6060f1SDimitry Andric using namespace llvm::object;
27fe6060f1SDimitry Andric 
28fe6060f1SDimitry Andric static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags;
29fe6060f1SDimitry Andric 
30fe6060f1SDimitry Andric // Returns the size of debug_str_offsets section headers in bytes.
31fe6060f1SDimitry Andric static uint64_t debugStrOffsetsHeaderSize(DataExtractor StrOffsetsData,
32fe6060f1SDimitry Andric                                           uint16_t DwarfVersion) {
33fe6060f1SDimitry Andric   if (DwarfVersion <= 4)
34fe6060f1SDimitry Andric     return 0; // There is no header before dwarf 5.
35fe6060f1SDimitry Andric   uint64_t Offset = 0;
36fe6060f1SDimitry Andric   uint64_t Length = StrOffsetsData.getU32(&Offset);
37fe6060f1SDimitry Andric   if (Length == llvm::dwarf::DW_LENGTH_DWARF64)
38fe6060f1SDimitry Andric     return 16; // unit length: 12 bytes, version: 2 bytes, padding: 2 bytes.
39fe6060f1SDimitry Andric   return 8;    // unit length: 4 bytes, version: 2 bytes, padding: 2 bytes.
40fe6060f1SDimitry Andric }
41fe6060f1SDimitry Andric 
42fe6060f1SDimitry Andric static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) {
43fe6060f1SDimitry Andric   uint64_t Offset = 0;
44fe6060f1SDimitry Andric   DataExtractor AbbrevData(Abbrev, true, 0);
45fe6060f1SDimitry Andric   while (AbbrevData.getULEB128(&Offset) != AbbrCode) {
46fe6060f1SDimitry Andric     // Tag
47fe6060f1SDimitry Andric     AbbrevData.getULEB128(&Offset);
48fe6060f1SDimitry Andric     // DW_CHILDREN
49fe6060f1SDimitry Andric     AbbrevData.getU8(&Offset);
50fe6060f1SDimitry Andric     // Attributes
51fe6060f1SDimitry Andric     while (AbbrevData.getULEB128(&Offset) | AbbrevData.getULEB128(&Offset))
52fe6060f1SDimitry Andric       ;
53fe6060f1SDimitry Andric   }
54fe6060f1SDimitry Andric   return Offset;
55fe6060f1SDimitry Andric }
56fe6060f1SDimitry Andric 
57fe6060f1SDimitry Andric static Expected<const char *>
58fe6060f1SDimitry Andric getIndexedString(dwarf::Form Form, DataExtractor InfoData, uint64_t &InfoOffset,
59fe6060f1SDimitry Andric                  StringRef StrOffsets, StringRef Str, uint16_t Version) {
60fe6060f1SDimitry Andric   if (Form == dwarf::DW_FORM_string)
61fe6060f1SDimitry Andric     return InfoData.getCStr(&InfoOffset);
62fe6060f1SDimitry Andric   uint64_t StrIndex;
63fe6060f1SDimitry Andric   switch (Form) {
64fe6060f1SDimitry Andric   case dwarf::DW_FORM_strx1:
65fe6060f1SDimitry Andric     StrIndex = InfoData.getU8(&InfoOffset);
66fe6060f1SDimitry Andric     break;
67fe6060f1SDimitry Andric   case dwarf::DW_FORM_strx2:
68fe6060f1SDimitry Andric     StrIndex = InfoData.getU16(&InfoOffset);
69fe6060f1SDimitry Andric     break;
70fe6060f1SDimitry Andric   case dwarf::DW_FORM_strx3:
71fe6060f1SDimitry Andric     StrIndex = InfoData.getU24(&InfoOffset);
72fe6060f1SDimitry Andric     break;
73fe6060f1SDimitry Andric   case dwarf::DW_FORM_strx4:
74fe6060f1SDimitry Andric     StrIndex = InfoData.getU32(&InfoOffset);
75fe6060f1SDimitry Andric     break;
76fe6060f1SDimitry Andric   case dwarf::DW_FORM_strx:
77fe6060f1SDimitry Andric   case dwarf::DW_FORM_GNU_str_index:
78fe6060f1SDimitry Andric     StrIndex = InfoData.getULEB128(&InfoOffset);
79fe6060f1SDimitry Andric     break;
80fe6060f1SDimitry Andric   default:
81fe6060f1SDimitry Andric     return make_error<DWPError>(
82fe6060f1SDimitry Andric         "string field must be encoded with one of the following: "
83fe6060f1SDimitry Andric         "DW_FORM_string, DW_FORM_strx, DW_FORM_strx1, DW_FORM_strx2, "
84fe6060f1SDimitry Andric         "DW_FORM_strx3, DW_FORM_strx4, or DW_FORM_GNU_str_index.");
85fe6060f1SDimitry Andric   }
86fe6060f1SDimitry Andric   DataExtractor StrOffsetsData(StrOffsets, true, 0);
87fe6060f1SDimitry Andric   uint64_t StrOffsetsOffset = 4 * StrIndex;
88fe6060f1SDimitry Andric   StrOffsetsOffset += debugStrOffsetsHeaderSize(StrOffsetsData, Version);
89fe6060f1SDimitry Andric 
90fe6060f1SDimitry Andric   uint64_t StrOffset = StrOffsetsData.getU32(&StrOffsetsOffset);
91fe6060f1SDimitry Andric   DataExtractor StrData(Str, true, 0);
92fe6060f1SDimitry Andric   return StrData.getCStr(&StrOffset);
93fe6060f1SDimitry Andric }
94fe6060f1SDimitry Andric 
95fe6060f1SDimitry Andric static Expected<CompileUnitIdentifiers>
96fe6060f1SDimitry Andric getCUIdentifiers(InfoSectionUnitHeader &Header, StringRef Abbrev,
97fe6060f1SDimitry Andric                  StringRef Info, StringRef StrOffsets, StringRef Str) {
98fe6060f1SDimitry Andric   DataExtractor InfoData(Info, true, 0);
99fe6060f1SDimitry Andric   uint64_t Offset = Header.HeaderSize;
100fe6060f1SDimitry Andric   if (Header.Version >= 5 && Header.UnitType != dwarf::DW_UT_split_compile)
101fe6060f1SDimitry Andric     return make_error<DWPError>(
102fe6060f1SDimitry Andric         std::string("unit type DW_UT_split_compile type not found in "
103fe6060f1SDimitry Andric                     "debug_info header. Unexpected unit type 0x" +
104fe6060f1SDimitry Andric                     utostr(Header.UnitType) + " found"));
105fe6060f1SDimitry Andric 
106fe6060f1SDimitry Andric   CompileUnitIdentifiers ID;
107fe6060f1SDimitry Andric 
108fe6060f1SDimitry Andric   uint32_t AbbrCode = InfoData.getULEB128(&Offset);
109fe6060f1SDimitry Andric   DataExtractor AbbrevData(Abbrev, true, 0);
110fe6060f1SDimitry Andric   uint64_t AbbrevOffset = getCUAbbrev(Abbrev, AbbrCode);
111fe6060f1SDimitry Andric   auto Tag = static_cast<dwarf::Tag>(AbbrevData.getULEB128(&AbbrevOffset));
112fe6060f1SDimitry Andric   if (Tag != dwarf::DW_TAG_compile_unit)
113fe6060f1SDimitry Andric     return make_error<DWPError>("top level DIE is not a compile unit");
114fe6060f1SDimitry Andric   // DW_CHILDREN
115fe6060f1SDimitry Andric   AbbrevData.getU8(&AbbrevOffset);
116fe6060f1SDimitry Andric   uint32_t Name;
117fe6060f1SDimitry Andric   dwarf::Form Form;
118fe6060f1SDimitry Andric   while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) |
119fe6060f1SDimitry Andric              (Form = static_cast<dwarf::Form>(
120fe6060f1SDimitry Andric                   AbbrevData.getULEB128(&AbbrevOffset))) &&
121fe6060f1SDimitry Andric          (Name != 0 || Form != 0)) {
122fe6060f1SDimitry Andric     switch (Name) {
123fe6060f1SDimitry Andric     case dwarf::DW_AT_name: {
124fe6060f1SDimitry Andric       Expected<const char *> EName = getIndexedString(
125fe6060f1SDimitry Andric           Form, InfoData, Offset, StrOffsets, Str, Header.Version);
126fe6060f1SDimitry Andric       if (!EName)
127fe6060f1SDimitry Andric         return EName.takeError();
128fe6060f1SDimitry Andric       ID.Name = *EName;
129fe6060f1SDimitry Andric       break;
130fe6060f1SDimitry Andric     }
131fe6060f1SDimitry Andric     case dwarf::DW_AT_GNU_dwo_name:
132fe6060f1SDimitry Andric     case dwarf::DW_AT_dwo_name: {
133fe6060f1SDimitry Andric       Expected<const char *> EName = getIndexedString(
134fe6060f1SDimitry Andric           Form, InfoData, Offset, StrOffsets, Str, Header.Version);
135fe6060f1SDimitry Andric       if (!EName)
136fe6060f1SDimitry Andric         return EName.takeError();
137fe6060f1SDimitry Andric       ID.DWOName = *EName;
138fe6060f1SDimitry Andric       break;
139fe6060f1SDimitry Andric     }
140fe6060f1SDimitry Andric     case dwarf::DW_AT_GNU_dwo_id:
141fe6060f1SDimitry Andric       Header.Signature = InfoData.getU64(&Offset);
142fe6060f1SDimitry Andric       break;
143fe6060f1SDimitry Andric     default:
144fe6060f1SDimitry Andric       DWARFFormValue::skipValue(
145fe6060f1SDimitry Andric           Form, InfoData, &Offset,
146fe6060f1SDimitry Andric           dwarf::FormParams({Header.Version, Header.AddrSize, Header.Format}));
147fe6060f1SDimitry Andric     }
148fe6060f1SDimitry Andric   }
149fe6060f1SDimitry Andric   if (!Header.Signature)
150fe6060f1SDimitry Andric     return make_error<DWPError>("compile unit missing dwo_id");
151fe6060f1SDimitry Andric   ID.Signature = *Header.Signature;
152fe6060f1SDimitry Andric   return ID;
153fe6060f1SDimitry Andric }
154fe6060f1SDimitry Andric 
155fe6060f1SDimitry Andric static bool isSupportedSectionKind(DWARFSectionKind Kind) {
156fe6060f1SDimitry Andric   return Kind != DW_SECT_EXT_unknown;
157fe6060f1SDimitry Andric }
158fe6060f1SDimitry Andric 
159fe6060f1SDimitry Andric namespace llvm {
160fe6060f1SDimitry Andric // Convert an internal section identifier into the index to use with
161fe6060f1SDimitry Andric // UnitIndexEntry::Contributions.
162fe6060f1SDimitry Andric unsigned getContributionIndex(DWARFSectionKind Kind, uint32_t IndexVersion) {
163fe6060f1SDimitry Andric   assert(serializeSectionKind(Kind, IndexVersion) >= DW_SECT_INFO);
164fe6060f1SDimitry Andric   return serializeSectionKind(Kind, IndexVersion) - DW_SECT_INFO;
165fe6060f1SDimitry Andric }
166fe6060f1SDimitry Andric } // namespace llvm
167fe6060f1SDimitry Andric 
168fe6060f1SDimitry Andric // Convert a UnitIndexEntry::Contributions index to the corresponding on-disk
169fe6060f1SDimitry Andric // value of the section identifier.
170fe6060f1SDimitry Andric static unsigned getOnDiskSectionId(unsigned Index) {
171fe6060f1SDimitry Andric   return Index + DW_SECT_INFO;
172fe6060f1SDimitry Andric }
173fe6060f1SDimitry Andric 
174fe6060f1SDimitry Andric static StringRef getSubsection(StringRef Section,
175fe6060f1SDimitry Andric                                const DWARFUnitIndex::Entry &Entry,
176fe6060f1SDimitry Andric                                DWARFSectionKind Kind) {
177fe6060f1SDimitry Andric   const auto *Off = Entry.getContribution(Kind);
178fe6060f1SDimitry Andric   if (!Off)
179fe6060f1SDimitry Andric     return StringRef();
180bdd1243dSDimitry Andric   return Section.substr(Off->getOffset(), Off->getLength());
181fe6060f1SDimitry Andric }
182fe6060f1SDimitry Andric 
18306c3fb27SDimitry Andric static Error sectionOverflowErrorOrWarning(uint32_t PrevOffset,
18406c3fb27SDimitry Andric                                            uint32_t OverflowedOffset,
18506c3fb27SDimitry Andric                                            StringRef SectionName,
1865f757f3fSDimitry Andric                                            OnCuIndexOverflow OverflowOptValue,
1875f757f3fSDimitry Andric                                            bool &AnySectionOverflow) {
18806c3fb27SDimitry Andric   std::string Msg =
18906c3fb27SDimitry Andric       (SectionName +
19006c3fb27SDimitry Andric        Twine(" Section Contribution Offset overflow 4G. Previous Offset ") +
19106c3fb27SDimitry Andric        Twine(PrevOffset) + Twine(", After overflow offset ") +
19206c3fb27SDimitry Andric        Twine(OverflowedOffset) + Twine("."))
19306c3fb27SDimitry Andric           .str();
1945f757f3fSDimitry Andric   if (OverflowOptValue == OnCuIndexOverflow::Continue) {
1955f757f3fSDimitry Andric     WithColor::defaultWarningHandler(make_error<DWPError>(Msg));
1965f757f3fSDimitry Andric     return Error::success();
1975f757f3fSDimitry Andric   } else if (OverflowOptValue == OnCuIndexOverflow::SoftStop) {
1985f757f3fSDimitry Andric     AnySectionOverflow = true;
19906c3fb27SDimitry Andric     WithColor::defaultWarningHandler(make_error<DWPError>(Msg));
20006c3fb27SDimitry Andric     return Error::success();
20106c3fb27SDimitry Andric   }
20206c3fb27SDimitry Andric   return make_error<DWPError>(Msg);
20306c3fb27SDimitry Andric }
20406c3fb27SDimitry Andric 
20506c3fb27SDimitry Andric static Error addAllTypesFromDWP(
20606c3fb27SDimitry Andric     MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
20706c3fb27SDimitry Andric     const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types,
20806c3fb27SDimitry Andric     const UnitIndexEntry &TUEntry, uint32_t &TypesOffset,
2095f757f3fSDimitry Andric     unsigned TypesContributionIndex, OnCuIndexOverflow OverflowOptValue,
2105f757f3fSDimitry Andric     bool &AnySectionOverflow) {
21181ad6265SDimitry Andric   Out.switchSection(OutputTypes);
212fe6060f1SDimitry Andric   for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) {
213fe6060f1SDimitry Andric     auto *I = E.getContributions();
214fe6060f1SDimitry Andric     if (!I)
215fe6060f1SDimitry Andric       continue;
216fe6060f1SDimitry Andric     auto P = TypeIndexEntries.insert(std::make_pair(E.getSignature(), TUEntry));
217fe6060f1SDimitry Andric     if (!P.second)
218fe6060f1SDimitry Andric       continue;
219fe6060f1SDimitry Andric     auto &Entry = P.first->second;
220fe6060f1SDimitry Andric     // Zero out the debug_info contribution
221fe6060f1SDimitry Andric     Entry.Contributions[0] = {};
222fe6060f1SDimitry Andric     for (auto Kind : TUIndex.getColumnKinds()) {
223fe6060f1SDimitry Andric       if (!isSupportedSectionKind(Kind))
224fe6060f1SDimitry Andric         continue;
225fe6060f1SDimitry Andric       auto &C =
226fe6060f1SDimitry Andric           Entry.Contributions[getContributionIndex(Kind, TUIndex.getVersion())];
227bdd1243dSDimitry Andric       C.setOffset(C.getOffset() + I->getOffset());
228bdd1243dSDimitry Andric       C.setLength(I->getLength());
229fe6060f1SDimitry Andric       ++I;
230fe6060f1SDimitry Andric     }
231fe6060f1SDimitry Andric     auto &C = Entry.Contributions[TypesContributionIndex];
232fe6060f1SDimitry Andric     Out.emitBytes(Types.substr(
233bdd1243dSDimitry Andric         C.getOffset() -
234bdd1243dSDimitry Andric             TUEntry.Contributions[TypesContributionIndex].getOffset(),
235bdd1243dSDimitry Andric         C.getLength()));
236bdd1243dSDimitry Andric     C.setOffset(TypesOffset);
23706c3fb27SDimitry Andric     uint32_t OldOffset = TypesOffset;
23806c3fb27SDimitry Andric     static_assert(sizeof(OldOffset) == sizeof(TypesOffset));
239bdd1243dSDimitry Andric     TypesOffset += C.getLength();
24006c3fb27SDimitry Andric     if (OldOffset > TypesOffset) {
2415f757f3fSDimitry Andric       if (Error Err = sectionOverflowErrorOrWarning(OldOffset, TypesOffset,
2425f757f3fSDimitry Andric                                                     "Types", OverflowOptValue,
2435f757f3fSDimitry Andric                                                     AnySectionOverflow))
24406c3fb27SDimitry Andric         return Err;
2455f757f3fSDimitry Andric       if (AnySectionOverflow) {
2465f757f3fSDimitry Andric         TypesOffset = OldOffset;
2475f757f3fSDimitry Andric         return Error::success();
2485f757f3fSDimitry Andric       }
249fe6060f1SDimitry Andric     }
250fe6060f1SDimitry Andric   }
25106c3fb27SDimitry Andric   return Error::success();
25206c3fb27SDimitry Andric }
253fe6060f1SDimitry Andric 
25406c3fb27SDimitry Andric static Error addAllTypesFromTypesSection(
255fe6060f1SDimitry Andric     MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
256fe6060f1SDimitry Andric     MCSection *OutputTypes, const std::vector<StringRef> &TypesSections,
25706c3fb27SDimitry Andric     const UnitIndexEntry &CUEntry, uint32_t &TypesOffset,
2585f757f3fSDimitry Andric     OnCuIndexOverflow OverflowOptValue, bool &AnySectionOverflow) {
259fe6060f1SDimitry Andric   for (StringRef Types : TypesSections) {
26081ad6265SDimitry Andric     Out.switchSection(OutputTypes);
261fe6060f1SDimitry Andric     uint64_t Offset = 0;
262fe6060f1SDimitry Andric     DataExtractor Data(Types, true, 0);
263fe6060f1SDimitry Andric     while (Data.isValidOffset(Offset)) {
264fe6060f1SDimitry Andric       UnitIndexEntry Entry = CUEntry;
265fe6060f1SDimitry Andric       // Zero out the debug_info contribution
266fe6060f1SDimitry Andric       Entry.Contributions[0] = {};
267fe6060f1SDimitry Andric       auto &C = Entry.Contributions[getContributionIndex(DW_SECT_EXT_TYPES, 2)];
268bdd1243dSDimitry Andric       C.setOffset(TypesOffset);
269fe6060f1SDimitry Andric       auto PrevOffset = Offset;
270fe6060f1SDimitry Andric       // Length of the unit, including the 4 byte length field.
271bdd1243dSDimitry Andric       C.setLength(Data.getU32(&Offset) + 4);
272fe6060f1SDimitry Andric 
273fe6060f1SDimitry Andric       Data.getU16(&Offset); // Version
274fe6060f1SDimitry Andric       Data.getU32(&Offset); // Abbrev offset
275fe6060f1SDimitry Andric       Data.getU8(&Offset);  // Address size
276fe6060f1SDimitry Andric       auto Signature = Data.getU64(&Offset);
277bdd1243dSDimitry Andric       Offset = PrevOffset + C.getLength32();
278fe6060f1SDimitry Andric 
279fe6060f1SDimitry Andric       auto P = TypeIndexEntries.insert(std::make_pair(Signature, Entry));
280fe6060f1SDimitry Andric       if (!P.second)
281fe6060f1SDimitry Andric         continue;
282fe6060f1SDimitry Andric 
283bdd1243dSDimitry Andric       Out.emitBytes(Types.substr(PrevOffset, C.getLength32()));
28406c3fb27SDimitry Andric       uint32_t OldOffset = TypesOffset;
285bdd1243dSDimitry Andric       TypesOffset += C.getLength32();
28606c3fb27SDimitry Andric       if (OldOffset > TypesOffset) {
2875f757f3fSDimitry Andric         if (Error Err = sectionOverflowErrorOrWarning(OldOffset, TypesOffset,
2885f757f3fSDimitry Andric                                                       "Types", OverflowOptValue,
2895f757f3fSDimitry Andric                                                       AnySectionOverflow))
29006c3fb27SDimitry Andric           return Err;
2915f757f3fSDimitry Andric         if (AnySectionOverflow) {
2925f757f3fSDimitry Andric           TypesOffset = OldOffset;
2935f757f3fSDimitry Andric           return Error::success();
2945f757f3fSDimitry Andric         }
295fe6060f1SDimitry Andric       }
296fe6060f1SDimitry Andric     }
297fe6060f1SDimitry Andric   }
29806c3fb27SDimitry Andric   return Error::success();
29906c3fb27SDimitry Andric }
300fe6060f1SDimitry Andric 
301fe6060f1SDimitry Andric static std::string buildDWODescription(StringRef Name, StringRef DWPName,
302fe6060f1SDimitry Andric                                        StringRef DWOName) {
303fe6060f1SDimitry Andric   std::string Text = "\'";
304fe6060f1SDimitry Andric   Text += Name;
305fe6060f1SDimitry Andric   Text += '\'';
306bdd1243dSDimitry Andric   bool HasDWO = !DWOName.empty();
307bdd1243dSDimitry Andric   bool HasDWP = !DWPName.empty();
308bdd1243dSDimitry Andric   if (HasDWO || HasDWP) {
309fe6060f1SDimitry Andric     Text += " (from ";
310bdd1243dSDimitry Andric     if (HasDWO) {
311fe6060f1SDimitry Andric       Text += '\'';
312fe6060f1SDimitry Andric       Text += DWOName;
313bdd1243dSDimitry Andric       Text += '\'';
314fe6060f1SDimitry Andric     }
315bdd1243dSDimitry Andric     if (HasDWO && HasDWP)
316bdd1243dSDimitry Andric       Text += " in ";
317bdd1243dSDimitry Andric     if (!DWPName.empty()) {
318fe6060f1SDimitry Andric       Text += '\'';
319fe6060f1SDimitry Andric       Text += DWPName;
320bdd1243dSDimitry Andric       Text += '\'';
321bdd1243dSDimitry Andric     }
322bdd1243dSDimitry Andric     Text += ")";
323fe6060f1SDimitry Andric   }
324fe6060f1SDimitry Andric   return Text;
325fe6060f1SDimitry Andric }
326fe6060f1SDimitry Andric 
327fe6060f1SDimitry Andric static Error createError(StringRef Name, Error E) {
328fe6060f1SDimitry Andric   return make_error<DWPError>(
329fe6060f1SDimitry Andric       ("failure while decompressing compressed section: '" + Name + "', " +
330fe6060f1SDimitry Andric        llvm::toString(std::move(E)))
331fe6060f1SDimitry Andric           .str());
332fe6060f1SDimitry Andric }
333fe6060f1SDimitry Andric 
334fe6060f1SDimitry Andric static Error
335fe6060f1SDimitry Andric handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections,
336fcaf7f86SDimitry Andric                         SectionRef Sec, StringRef Name, StringRef &Contents) {
337fcaf7f86SDimitry Andric   auto *Obj = dyn_cast<ELFObjectFileBase>(Sec.getObject());
338fcaf7f86SDimitry Andric   if (!Obj ||
339fcaf7f86SDimitry Andric       !(static_cast<ELFSectionRef>(Sec).getFlags() & ELF::SHF_COMPRESSED))
340fe6060f1SDimitry Andric     return Error::success();
341fcaf7f86SDimitry Andric   bool IsLE = isa<object::ELF32LEObjectFile>(Obj) ||
342fcaf7f86SDimitry Andric               isa<object::ELF64LEObjectFile>(Obj);
343fcaf7f86SDimitry Andric   bool Is64 = isa<object::ELF64LEObjectFile>(Obj) ||
344fcaf7f86SDimitry Andric               isa<object::ELF64BEObjectFile>(Obj);
345fcaf7f86SDimitry Andric   Expected<Decompressor> Dec = Decompressor::create(Name, Contents, IsLE, Is64);
346fe6060f1SDimitry Andric   if (!Dec)
347fe6060f1SDimitry Andric     return createError(Name, Dec.takeError());
348fe6060f1SDimitry Andric 
349fe6060f1SDimitry Andric   UncompressedSections.emplace_back();
350fe6060f1SDimitry Andric   if (Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
351fe6060f1SDimitry Andric     return createError(Name, std::move(E));
352fe6060f1SDimitry Andric 
353fe6060f1SDimitry Andric   Contents = UncompressedSections.back();
354fe6060f1SDimitry Andric   return Error::success();
355fe6060f1SDimitry Andric }
356fe6060f1SDimitry Andric 
357fe6060f1SDimitry Andric namespace llvm {
358fe6060f1SDimitry Andric // Parse and return the header of an info section compile/type unit.
359fe6060f1SDimitry Andric Expected<InfoSectionUnitHeader> parseInfoSectionUnitHeader(StringRef Info) {
360fe6060f1SDimitry Andric   InfoSectionUnitHeader Header;
361fe6060f1SDimitry Andric   Error Err = Error::success();
362fe6060f1SDimitry Andric   uint64_t Offset = 0;
363fe6060f1SDimitry Andric   DWARFDataExtractor InfoData(Info, true, 0);
364fe6060f1SDimitry Andric   std::tie(Header.Length, Header.Format) =
365fe6060f1SDimitry Andric       InfoData.getInitialLength(&Offset, &Err);
366fe6060f1SDimitry Andric   if (Err)
367fe6060f1SDimitry Andric     return make_error<DWPError>("cannot parse compile unit length: " +
368fe6060f1SDimitry Andric                                 llvm::toString(std::move(Err)));
369fe6060f1SDimitry Andric 
370fe6060f1SDimitry Andric   if (!InfoData.isValidOffset(Offset + (Header.Length - 1))) {
371fe6060f1SDimitry Andric     return make_error<DWPError>(
372fe6060f1SDimitry Andric         "compile unit exceeds .debug_info section range: " +
373fe6060f1SDimitry Andric         utostr(Offset + Header.Length) + " >= " + utostr(InfoData.size()));
374fe6060f1SDimitry Andric   }
375fe6060f1SDimitry Andric 
376fe6060f1SDimitry Andric   Header.Version = InfoData.getU16(&Offset, &Err);
377fe6060f1SDimitry Andric   if (Err)
378fe6060f1SDimitry Andric     return make_error<DWPError>("cannot parse compile unit version: " +
379fe6060f1SDimitry Andric                                 llvm::toString(std::move(Err)));
380fe6060f1SDimitry Andric 
381fe6060f1SDimitry Andric   uint64_t MinHeaderLength;
382fe6060f1SDimitry Andric   if (Header.Version >= 5) {
383fe6060f1SDimitry Andric     // Size: Version (2), UnitType (1), AddrSize (1), DebugAbbrevOffset (4),
384fe6060f1SDimitry Andric     // Signature (8)
385fe6060f1SDimitry Andric     MinHeaderLength = 16;
386fe6060f1SDimitry Andric   } else {
387fe6060f1SDimitry Andric     // Size: Version (2), DebugAbbrevOffset (4), AddrSize (1)
388fe6060f1SDimitry Andric     MinHeaderLength = 7;
389fe6060f1SDimitry Andric   }
390fe6060f1SDimitry Andric   if (Header.Length < MinHeaderLength) {
391fe6060f1SDimitry Andric     return make_error<DWPError>("unit length is too small: expected at least " +
392fe6060f1SDimitry Andric                                 utostr(MinHeaderLength) + " got " +
393fe6060f1SDimitry Andric                                 utostr(Header.Length) + ".");
394fe6060f1SDimitry Andric   }
395fe6060f1SDimitry Andric   if (Header.Version >= 5) {
396fe6060f1SDimitry Andric     Header.UnitType = InfoData.getU8(&Offset);
397fe6060f1SDimitry Andric     Header.AddrSize = InfoData.getU8(&Offset);
398fe6060f1SDimitry Andric     Header.DebugAbbrevOffset = InfoData.getU32(&Offset);
399fe6060f1SDimitry Andric     Header.Signature = InfoData.getU64(&Offset);
400fe6060f1SDimitry Andric     if (Header.UnitType == dwarf::DW_UT_split_type) {
401fe6060f1SDimitry Andric       // Type offset.
402fe6060f1SDimitry Andric       MinHeaderLength += 4;
403fe6060f1SDimitry Andric       if (Header.Length < MinHeaderLength)
404fe6060f1SDimitry Andric         return make_error<DWPError>("type unit is missing type offset");
405fe6060f1SDimitry Andric       InfoData.getU32(&Offset);
406fe6060f1SDimitry Andric     }
407fe6060f1SDimitry Andric   } else {
408fe6060f1SDimitry Andric     // Note that, address_size and debug_abbrev_offset fields have switched
409fe6060f1SDimitry Andric     // places between dwarf version 4 and 5.
410fe6060f1SDimitry Andric     Header.DebugAbbrevOffset = InfoData.getU32(&Offset);
411fe6060f1SDimitry Andric     Header.AddrSize = InfoData.getU8(&Offset);
412fe6060f1SDimitry Andric   }
413fe6060f1SDimitry Andric 
414fe6060f1SDimitry Andric   Header.HeaderSize = Offset;
415fe6060f1SDimitry Andric   return Header;
416fe6060f1SDimitry Andric }
417fe6060f1SDimitry Andric 
418*0fca6ea1SDimitry Andric static void writeNewOffsetsTo(MCStreamer &Out, DataExtractor &Data,
419*0fca6ea1SDimitry Andric                               DenseMap<uint64_t, uint32_t> &OffsetRemapping,
420*0fca6ea1SDimitry Andric                               uint64_t &Offset, uint64_t &Size) {
421*0fca6ea1SDimitry Andric 
422*0fca6ea1SDimitry Andric   while (Offset < Size) {
423*0fca6ea1SDimitry Andric     auto OldOffset = Data.getU32(&Offset);
424*0fca6ea1SDimitry Andric     auto NewOffset = OffsetRemapping[OldOffset];
425*0fca6ea1SDimitry Andric     Out.emitIntValue(NewOffset, 4);
426*0fca6ea1SDimitry Andric   }
427*0fca6ea1SDimitry Andric }
428*0fca6ea1SDimitry Andric 
429fe6060f1SDimitry Andric void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,
430fe6060f1SDimitry Andric                             MCSection *StrOffsetSection,
431fe6060f1SDimitry Andric                             StringRef CurStrSection,
432fe6060f1SDimitry Andric                             StringRef CurStrOffsetSection, uint16_t Version) {
433fe6060f1SDimitry Andric   // Could possibly produce an error or warning if one of these was non-null but
434fe6060f1SDimitry Andric   // the other was null.
435fe6060f1SDimitry Andric   if (CurStrSection.empty() || CurStrOffsetSection.empty())
436fe6060f1SDimitry Andric     return;
437fe6060f1SDimitry Andric 
438fe6060f1SDimitry Andric   DenseMap<uint64_t, uint32_t> OffsetRemapping;
439fe6060f1SDimitry Andric 
440fe6060f1SDimitry Andric   DataExtractor Data(CurStrSection, true, 0);
441fe6060f1SDimitry Andric   uint64_t LocalOffset = 0;
442fe6060f1SDimitry Andric   uint64_t PrevOffset = 0;
443fe6060f1SDimitry Andric   while (const char *S = Data.getCStr(&LocalOffset)) {
444fe6060f1SDimitry Andric     OffsetRemapping[PrevOffset] =
445fe6060f1SDimitry Andric         Strings.getOffset(S, LocalOffset - PrevOffset);
446fe6060f1SDimitry Andric     PrevOffset = LocalOffset;
447fe6060f1SDimitry Andric   }
448fe6060f1SDimitry Andric 
449fe6060f1SDimitry Andric   Data = DataExtractor(CurStrOffsetSection, true, 0);
450fe6060f1SDimitry Andric 
45181ad6265SDimitry Andric   Out.switchSection(StrOffsetSection);
452fe6060f1SDimitry Andric 
453fe6060f1SDimitry Andric   uint64_t Offset = 0;
454fe6060f1SDimitry Andric   uint64_t Size = CurStrOffsetSection.size();
455*0fca6ea1SDimitry Andric   if (Version > 4) {
456fe6060f1SDimitry Andric     while (Offset < Size) {
457*0fca6ea1SDimitry Andric       uint64_t HeaderSize = debugStrOffsetsHeaderSize(Data, Version);
458*0fca6ea1SDimitry Andric       assert(HeaderSize <= Size - Offset &&
459*0fca6ea1SDimitry Andric              "StrOffsetSection size is less than its header");
460*0fca6ea1SDimitry Andric 
461*0fca6ea1SDimitry Andric       uint64_t ContributionEnd = 0;
462*0fca6ea1SDimitry Andric       uint64_t ContributionSize = 0;
463*0fca6ea1SDimitry Andric       uint64_t HeaderLengthOffset = Offset;
464*0fca6ea1SDimitry Andric       if (HeaderSize == 8) {
465*0fca6ea1SDimitry Andric         ContributionSize = Data.getU32(&HeaderLengthOffset);
466*0fca6ea1SDimitry Andric       } else if (HeaderSize == 16) {
467*0fca6ea1SDimitry Andric         HeaderLengthOffset += 4; // skip the dwarf64 marker
468*0fca6ea1SDimitry Andric         ContributionSize = Data.getU64(&HeaderLengthOffset);
469*0fca6ea1SDimitry Andric       }
470*0fca6ea1SDimitry Andric       ContributionEnd = ContributionSize + HeaderLengthOffset;
471*0fca6ea1SDimitry Andric       Out.emitBytes(Data.getBytes(&Offset, HeaderSize));
472*0fca6ea1SDimitry Andric       writeNewOffsetsTo(Out, Data, OffsetRemapping, Offset, ContributionEnd);
473*0fca6ea1SDimitry Andric     }
474*0fca6ea1SDimitry Andric 
475*0fca6ea1SDimitry Andric   } else {
476*0fca6ea1SDimitry Andric     writeNewOffsetsTo(Out, Data, OffsetRemapping, Offset, Size);
477fe6060f1SDimitry Andric   }
478fe6060f1SDimitry Andric }
479fe6060f1SDimitry Andric 
480bdd1243dSDimitry Andric enum AccessField { Offset, Length };
481bdd1243dSDimitry Andric void writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
482fe6060f1SDimitry Andric                      const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
483bdd1243dSDimitry Andric                      const AccessField &Field) {
484fe6060f1SDimitry Andric   for (const auto &E : IndexEntries)
485bdd1243dSDimitry Andric     for (size_t I = 0; I != std::size(E.second.Contributions); ++I)
486fe6060f1SDimitry Andric       if (ContributionOffsets[I])
487bdd1243dSDimitry Andric         Out.emitIntValue((Field == AccessField::Offset
488bdd1243dSDimitry Andric                               ? E.second.Contributions[I].getOffset32()
489bdd1243dSDimitry Andric                               : E.second.Contributions[I].getLength32()),
490bdd1243dSDimitry Andric                          4);
491fe6060f1SDimitry Andric }
492fe6060f1SDimitry Andric 
493fe6060f1SDimitry Andric void writeIndex(MCStreamer &Out, MCSection *Section,
494fe6060f1SDimitry Andric                 ArrayRef<unsigned> ContributionOffsets,
495fe6060f1SDimitry Andric                 const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
496fe6060f1SDimitry Andric                 uint32_t IndexVersion) {
497fe6060f1SDimitry Andric   if (IndexEntries.empty())
498fe6060f1SDimitry Andric     return;
499fe6060f1SDimitry Andric 
500fe6060f1SDimitry Andric   unsigned Columns = 0;
501fe6060f1SDimitry Andric   for (auto &C : ContributionOffsets)
502fe6060f1SDimitry Andric     if (C)
503fe6060f1SDimitry Andric       ++Columns;
504fe6060f1SDimitry Andric 
505fe6060f1SDimitry Andric   std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
506fe6060f1SDimitry Andric   uint64_t Mask = Buckets.size() - 1;
507fe6060f1SDimitry Andric   size_t I = 0;
508fe6060f1SDimitry Andric   for (const auto &P : IndexEntries) {
509fe6060f1SDimitry Andric     auto S = P.first;
510fe6060f1SDimitry Andric     auto H = S & Mask;
511fe6060f1SDimitry Andric     auto HP = ((S >> 32) & Mask) | 1;
512fe6060f1SDimitry Andric     while (Buckets[H]) {
513fe6060f1SDimitry Andric       assert(S != IndexEntries.begin()[Buckets[H] - 1].first &&
514fe6060f1SDimitry Andric              "Duplicate unit");
515fe6060f1SDimitry Andric       H = (H + HP) & Mask;
516fe6060f1SDimitry Andric     }
517fe6060f1SDimitry Andric     Buckets[H] = I + 1;
518fe6060f1SDimitry Andric     ++I;
519fe6060f1SDimitry Andric   }
520fe6060f1SDimitry Andric 
52181ad6265SDimitry Andric   Out.switchSection(Section);
522fe6060f1SDimitry Andric   Out.emitIntValue(IndexVersion, 4);        // Version
523fe6060f1SDimitry Andric   Out.emitIntValue(Columns, 4);             // Columns
524fe6060f1SDimitry Andric   Out.emitIntValue(IndexEntries.size(), 4); // Num Units
525fe6060f1SDimitry Andric   Out.emitIntValue(Buckets.size(), 4);      // Num Buckets
526fe6060f1SDimitry Andric 
527fe6060f1SDimitry Andric   // Write the signatures.
528fe6060f1SDimitry Andric   for (const auto &I : Buckets)
529fe6060f1SDimitry Andric     Out.emitIntValue(I ? IndexEntries.begin()[I - 1].first : 0, 8);
530fe6060f1SDimitry Andric 
531fe6060f1SDimitry Andric   // Write the indexes.
532fe6060f1SDimitry Andric   for (const auto &I : Buckets)
533fe6060f1SDimitry Andric     Out.emitIntValue(I, 4);
534fe6060f1SDimitry Andric 
535fe6060f1SDimitry Andric   // Write the column headers (which sections will appear in the table)
536fe6060f1SDimitry Andric   for (size_t I = 0; I != ContributionOffsets.size(); ++I)
537fe6060f1SDimitry Andric     if (ContributionOffsets[I])
538fe6060f1SDimitry Andric       Out.emitIntValue(getOnDiskSectionId(I), 4);
539fe6060f1SDimitry Andric 
540fe6060f1SDimitry Andric   // Write the offsets.
541bdd1243dSDimitry Andric   writeIndexTable(Out, ContributionOffsets, IndexEntries, AccessField::Offset);
542fe6060f1SDimitry Andric 
543fe6060f1SDimitry Andric   // Write the lengths.
544bdd1243dSDimitry Andric   writeIndexTable(Out, ContributionOffsets, IndexEntries, AccessField::Length);
545fe6060f1SDimitry Andric }
546fe6060f1SDimitry Andric 
547fe6060f1SDimitry Andric Error buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
548fe6060f1SDimitry Andric                           const CompileUnitIdentifiers &ID, StringRef DWPName) {
549fe6060f1SDimitry Andric   return make_error<DWPError>(
550fe6060f1SDimitry Andric       std::string("duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " +
551fe6060f1SDimitry Andric       buildDWODescription(PrevE.second.Name, PrevE.second.DWPName,
552fe6060f1SDimitry Andric                           PrevE.second.DWOName) +
553fe6060f1SDimitry Andric       " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));
554fe6060f1SDimitry Andric }
555fe6060f1SDimitry Andric 
556fe6060f1SDimitry Andric Error handleSection(
557fe6060f1SDimitry Andric     const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
558fe6060f1SDimitry Andric     const MCSection *StrSection, const MCSection *StrOffsetSection,
559fe6060f1SDimitry Andric     const MCSection *TypesSection, const MCSection *CUIndexSection,
560fe6060f1SDimitry Andric     const MCSection *TUIndexSection, const MCSection *InfoSection,
561fe6060f1SDimitry Andric     const SectionRef &Section, MCStreamer &Out,
562fe6060f1SDimitry Andric     std::deque<SmallString<32>> &UncompressedSections,
563fe6060f1SDimitry Andric     uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry,
564fe6060f1SDimitry Andric     StringRef &CurStrSection, StringRef &CurStrOffsetSection,
565fe6060f1SDimitry Andric     std::vector<StringRef> &CurTypesSection,
566fe6060f1SDimitry Andric     std::vector<StringRef> &CurInfoSection, StringRef &AbbrevSection,
567fe6060f1SDimitry Andric     StringRef &CurCUIndexSection, StringRef &CurTUIndexSection,
568fe6060f1SDimitry Andric     std::vector<std::pair<DWARFSectionKind, uint32_t>> &SectionLength) {
569fe6060f1SDimitry Andric   if (Section.isBSS())
570fe6060f1SDimitry Andric     return Error::success();
571fe6060f1SDimitry Andric 
572fe6060f1SDimitry Andric   if (Section.isVirtual())
573fe6060f1SDimitry Andric     return Error::success();
574fe6060f1SDimitry Andric 
575fe6060f1SDimitry Andric   Expected<StringRef> NameOrErr = Section.getName();
576fe6060f1SDimitry Andric   if (!NameOrErr)
577fe6060f1SDimitry Andric     return NameOrErr.takeError();
578fe6060f1SDimitry Andric   StringRef Name = *NameOrErr;
579fe6060f1SDimitry Andric 
580fe6060f1SDimitry Andric   Expected<StringRef> ContentsOrErr = Section.getContents();
581fe6060f1SDimitry Andric   if (!ContentsOrErr)
582fe6060f1SDimitry Andric     return ContentsOrErr.takeError();
583fe6060f1SDimitry Andric   StringRef Contents = *ContentsOrErr;
584fe6060f1SDimitry Andric 
585fcaf7f86SDimitry Andric   if (auto Err = handleCompressedSection(UncompressedSections, Section, Name,
586fcaf7f86SDimitry Andric                                          Contents))
587fe6060f1SDimitry Andric     return Err;
588fe6060f1SDimitry Andric 
589fe6060f1SDimitry Andric   Name = Name.substr(Name.find_first_not_of("._"));
590fe6060f1SDimitry Andric 
591fe6060f1SDimitry Andric   auto SectionPair = KnownSections.find(Name);
592fe6060f1SDimitry Andric   if (SectionPair == KnownSections.end())
593fe6060f1SDimitry Andric     return Error::success();
594fe6060f1SDimitry Andric 
595fe6060f1SDimitry Andric   if (DWARFSectionKind Kind = SectionPair->second.second) {
596fe6060f1SDimitry Andric     if (Kind != DW_SECT_EXT_TYPES && Kind != DW_SECT_INFO) {
597fe6060f1SDimitry Andric       SectionLength.push_back(std::make_pair(Kind, Contents.size()));
598fe6060f1SDimitry Andric     }
599fe6060f1SDimitry Andric 
600fe6060f1SDimitry Andric     if (Kind == DW_SECT_ABBREV) {
601fe6060f1SDimitry Andric       AbbrevSection = Contents;
602fe6060f1SDimitry Andric     }
603fe6060f1SDimitry Andric   }
604fe6060f1SDimitry Andric 
605fe6060f1SDimitry Andric   MCSection *OutSection = SectionPair->second.first;
606fe6060f1SDimitry Andric   if (OutSection == StrOffsetSection)
607fe6060f1SDimitry Andric     CurStrOffsetSection = Contents;
608fe6060f1SDimitry Andric   else if (OutSection == StrSection)
609fe6060f1SDimitry Andric     CurStrSection = Contents;
610fe6060f1SDimitry Andric   else if (OutSection == TypesSection)
611fe6060f1SDimitry Andric     CurTypesSection.push_back(Contents);
612fe6060f1SDimitry Andric   else if (OutSection == CUIndexSection)
613fe6060f1SDimitry Andric     CurCUIndexSection = Contents;
614fe6060f1SDimitry Andric   else if (OutSection == TUIndexSection)
615fe6060f1SDimitry Andric     CurTUIndexSection = Contents;
616fe6060f1SDimitry Andric   else if (OutSection == InfoSection)
617fe6060f1SDimitry Andric     CurInfoSection.push_back(Contents);
618fe6060f1SDimitry Andric   else {
61981ad6265SDimitry Andric     Out.switchSection(OutSection);
620fe6060f1SDimitry Andric     Out.emitBytes(Contents);
621fe6060f1SDimitry Andric   }
622fe6060f1SDimitry Andric   return Error::success();
623fe6060f1SDimitry Andric }
624fe6060f1SDimitry Andric 
62506c3fb27SDimitry Andric Error write(MCStreamer &Out, ArrayRef<std::string> Inputs,
6265f757f3fSDimitry Andric             OnCuIndexOverflow OverflowOptValue) {
627fe6060f1SDimitry Andric   const auto &MCOFI = *Out.getContext().getObjectFileInfo();
628fe6060f1SDimitry Andric   MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
629fe6060f1SDimitry Andric   MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
630fe6060f1SDimitry Andric   MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection();
631fe6060f1SDimitry Andric   MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection();
632fe6060f1SDimitry Andric   MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection();
633fe6060f1SDimitry Andric   MCSection *const InfoSection = MCOFI.getDwarfInfoDWOSection();
634fe6060f1SDimitry Andric   const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = {
635fe6060f1SDimitry Andric       {"debug_info.dwo", {InfoSection, DW_SECT_INFO}},
636fe6060f1SDimitry Andric       {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},
637fe6060f1SDimitry Andric       {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
638fe6060f1SDimitry Andric       {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}},
639fe6060f1SDimitry Andric       {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},
640fe6060f1SDimitry Andric       {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
641fe6060f1SDimitry Andric       {"debug_macro.dwo", {MCOFI.getDwarfMacroDWOSection(), DW_SECT_MACRO}},
642fe6060f1SDimitry Andric       {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
643fe6060f1SDimitry Andric       {"debug_loclists.dwo",
644fe6060f1SDimitry Andric        {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},
645fe6060f1SDimitry Andric       {"debug_rnglists.dwo",
646fe6060f1SDimitry Andric        {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}},
647fe6060f1SDimitry Andric       {"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}},
648fe6060f1SDimitry Andric       {"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};
649fe6060f1SDimitry Andric 
650fe6060f1SDimitry Andric   MapVector<uint64_t, UnitIndexEntry> IndexEntries;
651fe6060f1SDimitry Andric   MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
652fe6060f1SDimitry Andric 
653fe6060f1SDimitry Andric   uint32_t ContributionOffsets[8] = {};
654fe6060f1SDimitry Andric   uint16_t Version = 0;
655fe6060f1SDimitry Andric   uint32_t IndexVersion = 0;
6565f757f3fSDimitry Andric   bool AnySectionOverflow = false;
657fe6060f1SDimitry Andric 
658fe6060f1SDimitry Andric   DWPStringPool Strings(Out, StrSection);
659fe6060f1SDimitry Andric 
660fe6060f1SDimitry Andric   SmallVector<OwningBinary<object::ObjectFile>, 128> Objects;
661fe6060f1SDimitry Andric   Objects.reserve(Inputs.size());
662fe6060f1SDimitry Andric 
663fe6060f1SDimitry Andric   std::deque<SmallString<32>> UncompressedSections;
664fe6060f1SDimitry Andric 
665fe6060f1SDimitry Andric   for (const auto &Input : Inputs) {
666fe6060f1SDimitry Andric     auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
667bdd1243dSDimitry Andric     if (!ErrOrObj) {
668bdd1243dSDimitry Andric       return handleErrors(ErrOrObj.takeError(),
669bdd1243dSDimitry Andric                           [&](std::unique_ptr<ECError> EC) -> Error {
670bdd1243dSDimitry Andric                             return createFileError(Input, Error(std::move(EC)));
671bdd1243dSDimitry Andric                           });
672bdd1243dSDimitry Andric     }
673fe6060f1SDimitry Andric 
674fe6060f1SDimitry Andric     auto &Obj = *ErrOrObj->getBinary();
675fe6060f1SDimitry Andric     Objects.push_back(std::move(*ErrOrObj));
676fe6060f1SDimitry Andric 
677fe6060f1SDimitry Andric     UnitIndexEntry CurEntry = {};
678fe6060f1SDimitry Andric 
679fe6060f1SDimitry Andric     StringRef CurStrSection;
680fe6060f1SDimitry Andric     StringRef CurStrOffsetSection;
681fe6060f1SDimitry Andric     std::vector<StringRef> CurTypesSection;
682fe6060f1SDimitry Andric     std::vector<StringRef> CurInfoSection;
683fe6060f1SDimitry Andric     StringRef AbbrevSection;
684fe6060f1SDimitry Andric     StringRef CurCUIndexSection;
685fe6060f1SDimitry Andric     StringRef CurTUIndexSection;
686fe6060f1SDimitry Andric 
687fe6060f1SDimitry Andric     // This maps each section contained in this file to its length.
688fe6060f1SDimitry Andric     // This information is later on used to calculate the contributions,
689fe6060f1SDimitry Andric     // i.e. offset and length, of each compile/type unit to a section.
690fe6060f1SDimitry Andric     std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength;
691fe6060f1SDimitry Andric 
692fe6060f1SDimitry Andric     for (const auto &Section : Obj.sections())
693fe6060f1SDimitry Andric       if (auto Err = handleSection(
694fe6060f1SDimitry Andric               KnownSections, StrSection, StrOffsetSection, TypesSection,
695fe6060f1SDimitry Andric               CUIndexSection, TUIndexSection, InfoSection, Section, Out,
696fe6060f1SDimitry Andric               UncompressedSections, ContributionOffsets, CurEntry,
697fe6060f1SDimitry Andric               CurStrSection, CurStrOffsetSection, CurTypesSection,
698fe6060f1SDimitry Andric               CurInfoSection, AbbrevSection, CurCUIndexSection,
699fe6060f1SDimitry Andric               CurTUIndexSection, SectionLength))
700fe6060f1SDimitry Andric         return Err;
701fe6060f1SDimitry Andric 
702fe6060f1SDimitry Andric     if (CurInfoSection.empty())
703fe6060f1SDimitry Andric       continue;
704fe6060f1SDimitry Andric 
705fe6060f1SDimitry Andric     Expected<InfoSectionUnitHeader> HeaderOrErr =
706fe6060f1SDimitry Andric         parseInfoSectionUnitHeader(CurInfoSection.front());
707fe6060f1SDimitry Andric     if (!HeaderOrErr)
708fe6060f1SDimitry Andric       return HeaderOrErr.takeError();
709fe6060f1SDimitry Andric     InfoSectionUnitHeader &Header = *HeaderOrErr;
710fe6060f1SDimitry Andric 
711fe6060f1SDimitry Andric     if (Version == 0) {
712fe6060f1SDimitry Andric       Version = Header.Version;
713fe6060f1SDimitry Andric       IndexVersion = Version < 5 ? 2 : 5;
714fe6060f1SDimitry Andric     } else if (Version != Header.Version) {
715fe6060f1SDimitry Andric       return make_error<DWPError>("incompatible DWARF compile unit versions.");
716fe6060f1SDimitry Andric     }
717fe6060f1SDimitry Andric 
718fe6060f1SDimitry Andric     writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection,
719fe6060f1SDimitry Andric                            CurStrOffsetSection, Header.Version);
720fe6060f1SDimitry Andric 
721fe6060f1SDimitry Andric     for (auto Pair : SectionLength) {
722fe6060f1SDimitry Andric       auto Index = getContributionIndex(Pair.first, IndexVersion);
723bdd1243dSDimitry Andric       CurEntry.Contributions[Index].setOffset(ContributionOffsets[Index]);
724bdd1243dSDimitry Andric       CurEntry.Contributions[Index].setLength(Pair.second);
72506c3fb27SDimitry Andric       uint32_t OldOffset = ContributionOffsets[Index];
726bdd1243dSDimitry Andric       ContributionOffsets[Index] += CurEntry.Contributions[Index].getLength32();
72706c3fb27SDimitry Andric       if (OldOffset > ContributionOffsets[Index]) {
72806c3fb27SDimitry Andric         uint32_t SectionIndex = 0;
72906c3fb27SDimitry Andric         for (auto &Section : Obj.sections()) {
73006c3fb27SDimitry Andric           if (SectionIndex == Index) {
7315f757f3fSDimitry Andric             if (Error Err = sectionOverflowErrorOrWarning(
73206c3fb27SDimitry Andric                     OldOffset, ContributionOffsets[Index], *Section.getName(),
7335f757f3fSDimitry Andric                     OverflowOptValue, AnySectionOverflow))
7345f757f3fSDimitry Andric               return Err;
73506c3fb27SDimitry Andric           }
73606c3fb27SDimitry Andric           ++SectionIndex;
73706c3fb27SDimitry Andric         }
7385f757f3fSDimitry Andric         if (AnySectionOverflow)
7395f757f3fSDimitry Andric           break;
74006c3fb27SDimitry Andric       }
741fe6060f1SDimitry Andric     }
742fe6060f1SDimitry Andric 
743fe6060f1SDimitry Andric     uint32_t &InfoSectionOffset =
744fe6060f1SDimitry Andric         ContributionOffsets[getContributionIndex(DW_SECT_INFO, IndexVersion)];
745fe6060f1SDimitry Andric     if (CurCUIndexSection.empty()) {
746fe6060f1SDimitry Andric       bool FoundCUUnit = false;
74781ad6265SDimitry Andric       Out.switchSection(InfoSection);
748fe6060f1SDimitry Andric       for (StringRef Info : CurInfoSection) {
749fe6060f1SDimitry Andric         uint64_t UnitOffset = 0;
750fe6060f1SDimitry Andric         while (Info.size() > UnitOffset) {
751fe6060f1SDimitry Andric           Expected<InfoSectionUnitHeader> HeaderOrError =
752fe6060f1SDimitry Andric               parseInfoSectionUnitHeader(Info.substr(UnitOffset, Info.size()));
753fe6060f1SDimitry Andric           if (!HeaderOrError)
754fe6060f1SDimitry Andric             return HeaderOrError.takeError();
755fe6060f1SDimitry Andric           InfoSectionUnitHeader &Header = *HeaderOrError;
756fe6060f1SDimitry Andric 
757fe6060f1SDimitry Andric           UnitIndexEntry Entry = CurEntry;
758fe6060f1SDimitry Andric           auto &C = Entry.Contributions[getContributionIndex(DW_SECT_INFO,
759fe6060f1SDimitry Andric                                                              IndexVersion)];
760bdd1243dSDimitry Andric           C.setOffset(InfoSectionOffset);
761bdd1243dSDimitry Andric           C.setLength(Header.Length + 4);
762972a253aSDimitry Andric 
763972a253aSDimitry Andric           if (std::numeric_limits<uint32_t>::max() - InfoSectionOffset <
76406c3fb27SDimitry Andric               C.getLength32()) {
76506c3fb27SDimitry Andric             if (Error Err = sectionOverflowErrorOrWarning(
76606c3fb27SDimitry Andric                     InfoSectionOffset, InfoSectionOffset + C.getLength32(),
7675f757f3fSDimitry Andric                     "debug_info", OverflowOptValue, AnySectionOverflow))
76806c3fb27SDimitry Andric               return Err;
7695f757f3fSDimitry Andric             if (AnySectionOverflow) {
7705f757f3fSDimitry Andric               if (Header.Version < 5 ||
7715f757f3fSDimitry Andric                   Header.UnitType == dwarf::DW_UT_split_compile)
7725f757f3fSDimitry Andric                 FoundCUUnit = true;
7735f757f3fSDimitry Andric               break;
7745f757f3fSDimitry Andric             }
77506c3fb27SDimitry Andric           }
776972a253aSDimitry Andric 
777bdd1243dSDimitry Andric           UnitOffset += C.getLength32();
778fe6060f1SDimitry Andric           if (Header.Version < 5 ||
779fe6060f1SDimitry Andric               Header.UnitType == dwarf::DW_UT_split_compile) {
780bdd1243dSDimitry Andric             Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
781bdd1243dSDimitry Andric                 Header, AbbrevSection,
782bdd1243dSDimitry Andric                 Info.substr(UnitOffset - C.getLength32(), C.getLength32()),
783fe6060f1SDimitry Andric                 CurStrOffsetSection, CurStrSection);
784fe6060f1SDimitry Andric 
785fe6060f1SDimitry Andric             if (!EID)
786fe6060f1SDimitry Andric               return createFileError(Input, EID.takeError());
787fe6060f1SDimitry Andric             const auto &ID = *EID;
788fe6060f1SDimitry Andric             auto P = IndexEntries.insert(std::make_pair(ID.Signature, Entry));
789fe6060f1SDimitry Andric             if (!P.second)
790fe6060f1SDimitry Andric               return buildDuplicateError(*P.first, ID, "");
791fe6060f1SDimitry Andric             P.first->second.Name = ID.Name;
792fe6060f1SDimitry Andric             P.first->second.DWOName = ID.DWOName;
793fe6060f1SDimitry Andric 
794fe6060f1SDimitry Andric             FoundCUUnit = true;
795fe6060f1SDimitry Andric           } else if (Header.UnitType == dwarf::DW_UT_split_type) {
796fe6060f1SDimitry Andric             auto P = TypeIndexEntries.insert(
79781ad6265SDimitry Andric                 std::make_pair(*Header.Signature, Entry));
798fe6060f1SDimitry Andric             if (!P.second)
799fe6060f1SDimitry Andric               continue;
800fe6060f1SDimitry Andric           }
801bdd1243dSDimitry Andric           Out.emitBytes(
802bdd1243dSDimitry Andric               Info.substr(UnitOffset - C.getLength32(), C.getLength32()));
803bdd1243dSDimitry Andric           InfoSectionOffset += C.getLength32();
804fe6060f1SDimitry Andric         }
8055f757f3fSDimitry Andric         if (AnySectionOverflow)
8065f757f3fSDimitry Andric           break;
807fe6060f1SDimitry Andric       }
808fe6060f1SDimitry Andric 
809fe6060f1SDimitry Andric       if (!FoundCUUnit)
810fe6060f1SDimitry Andric         return make_error<DWPError>("no compile unit found in file: " + Input);
811fe6060f1SDimitry Andric 
812fe6060f1SDimitry Andric       if (IndexVersion == 2) {
813fe6060f1SDimitry Andric         // Add types from the .debug_types section from DWARF < 5.
81406c3fb27SDimitry Andric         if (Error Err = addAllTypesFromTypesSection(
815fe6060f1SDimitry Andric                 Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry,
81606c3fb27SDimitry Andric                 ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)],
8175f757f3fSDimitry Andric                 OverflowOptValue, AnySectionOverflow))
81806c3fb27SDimitry Andric           return Err;
819fe6060f1SDimitry Andric       }
8205f757f3fSDimitry Andric       if (AnySectionOverflow)
8215f757f3fSDimitry Andric         break;
822fe6060f1SDimitry Andric       continue;
823fe6060f1SDimitry Andric     }
824fe6060f1SDimitry Andric 
825fe6060f1SDimitry Andric     if (CurInfoSection.size() != 1)
826fe6060f1SDimitry Andric       return make_error<DWPError>("expected exactly one occurrence of a debug "
827fe6060f1SDimitry Andric                                   "info section in a .dwp file");
828fe6060f1SDimitry Andric     StringRef DwpSingleInfoSection = CurInfoSection.front();
829fe6060f1SDimitry Andric 
830fe6060f1SDimitry Andric     DWARFUnitIndex CUIndex(DW_SECT_INFO);
831fe6060f1SDimitry Andric     DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
832fe6060f1SDimitry Andric     if (!CUIndex.parse(CUIndexData))
833fe6060f1SDimitry Andric       return make_error<DWPError>("failed to parse cu_index");
834fe6060f1SDimitry Andric     if (CUIndex.getVersion() != IndexVersion)
835fe6060f1SDimitry Andric       return make_error<DWPError>("incompatible cu_index versions, found " +
836fe6060f1SDimitry Andric                                   utostr(CUIndex.getVersion()) +
837fe6060f1SDimitry Andric                                   " and expecting " + utostr(IndexVersion));
838fe6060f1SDimitry Andric 
83981ad6265SDimitry Andric     Out.switchSection(InfoSection);
840fe6060f1SDimitry Andric     for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
841fe6060f1SDimitry Andric       auto *I = E.getContributions();
842fe6060f1SDimitry Andric       if (!I)
843fe6060f1SDimitry Andric         continue;
844fe6060f1SDimitry Andric       auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry));
845fe6060f1SDimitry Andric       StringRef CUInfoSection =
846fe6060f1SDimitry Andric           getSubsection(DwpSingleInfoSection, E, DW_SECT_INFO);
847fe6060f1SDimitry Andric       Expected<InfoSectionUnitHeader> HeaderOrError =
848fe6060f1SDimitry Andric           parseInfoSectionUnitHeader(CUInfoSection);
849fe6060f1SDimitry Andric       if (!HeaderOrError)
850fe6060f1SDimitry Andric         return HeaderOrError.takeError();
851fe6060f1SDimitry Andric       InfoSectionUnitHeader &Header = *HeaderOrError;
852fe6060f1SDimitry Andric 
853fe6060f1SDimitry Andric       Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
854fe6060f1SDimitry Andric           Header, getSubsection(AbbrevSection, E, DW_SECT_ABBREV),
855fe6060f1SDimitry Andric           CUInfoSection,
856fe6060f1SDimitry Andric           getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS),
857fe6060f1SDimitry Andric           CurStrSection);
858fe6060f1SDimitry Andric       if (!EID)
859fe6060f1SDimitry Andric         return createFileError(Input, EID.takeError());
860fe6060f1SDimitry Andric       const auto &ID = *EID;
861fe6060f1SDimitry Andric       if (!P.second)
862fe6060f1SDimitry Andric         return buildDuplicateError(*P.first, ID, Input);
863fe6060f1SDimitry Andric       auto &NewEntry = P.first->second;
864fe6060f1SDimitry Andric       NewEntry.Name = ID.Name;
865fe6060f1SDimitry Andric       NewEntry.DWOName = ID.DWOName;
866fe6060f1SDimitry Andric       NewEntry.DWPName = Input;
867fe6060f1SDimitry Andric       for (auto Kind : CUIndex.getColumnKinds()) {
868fe6060f1SDimitry Andric         if (!isSupportedSectionKind(Kind))
869fe6060f1SDimitry Andric           continue;
870fe6060f1SDimitry Andric         auto &C =
871fe6060f1SDimitry Andric             NewEntry.Contributions[getContributionIndex(Kind, IndexVersion)];
872bdd1243dSDimitry Andric         C.setOffset(C.getOffset() + I->getOffset());
873bdd1243dSDimitry Andric         C.setLength(I->getLength());
874fe6060f1SDimitry Andric         ++I;
875fe6060f1SDimitry Andric       }
876fe6060f1SDimitry Andric       unsigned Index = getContributionIndex(DW_SECT_INFO, IndexVersion);
877fe6060f1SDimitry Andric       auto &C = NewEntry.Contributions[Index];
878fe6060f1SDimitry Andric       Out.emitBytes(CUInfoSection);
879bdd1243dSDimitry Andric       C.setOffset(InfoSectionOffset);
880bdd1243dSDimitry Andric       InfoSectionOffset += C.getLength32();
881fe6060f1SDimitry Andric     }
882fe6060f1SDimitry Andric 
883fe6060f1SDimitry Andric     if (!CurTUIndexSection.empty()) {
884fe6060f1SDimitry Andric       llvm::DWARFSectionKind TUSectionKind;
885fe6060f1SDimitry Andric       MCSection *OutSection;
886fe6060f1SDimitry Andric       StringRef TypeInputSection;
887fe6060f1SDimitry Andric       // Write type units into debug info section for DWARFv5.
888fe6060f1SDimitry Andric       if (Version >= 5) {
889fe6060f1SDimitry Andric         TUSectionKind = DW_SECT_INFO;
890fe6060f1SDimitry Andric         OutSection = InfoSection;
891fe6060f1SDimitry Andric         TypeInputSection = DwpSingleInfoSection;
892fe6060f1SDimitry Andric       } else {
893fe6060f1SDimitry Andric         // Write type units into debug types section for DWARF < 5.
894fe6060f1SDimitry Andric         if (CurTypesSection.size() != 1)
895fe6060f1SDimitry Andric           return make_error<DWPError>(
896fe6060f1SDimitry Andric               "multiple type unit sections in .dwp file");
897fe6060f1SDimitry Andric 
898fe6060f1SDimitry Andric         TUSectionKind = DW_SECT_EXT_TYPES;
899fe6060f1SDimitry Andric         OutSection = TypesSection;
900fe6060f1SDimitry Andric         TypeInputSection = CurTypesSection.front();
901fe6060f1SDimitry Andric       }
902fe6060f1SDimitry Andric 
903fe6060f1SDimitry Andric       DWARFUnitIndex TUIndex(TUSectionKind);
904fe6060f1SDimitry Andric       DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);
905fe6060f1SDimitry Andric       if (!TUIndex.parse(TUIndexData))
906fe6060f1SDimitry Andric         return make_error<DWPError>("failed to parse tu_index");
907fe6060f1SDimitry Andric       if (TUIndex.getVersion() != IndexVersion)
908fe6060f1SDimitry Andric         return make_error<DWPError>("incompatible tu_index versions, found " +
909fe6060f1SDimitry Andric                                     utostr(TUIndex.getVersion()) +
910fe6060f1SDimitry Andric                                     " and expecting " + utostr(IndexVersion));
911fe6060f1SDimitry Andric 
912fe6060f1SDimitry Andric       unsigned TypesContributionIndex =
913fe6060f1SDimitry Andric           getContributionIndex(TUSectionKind, IndexVersion);
91406c3fb27SDimitry Andric       if (Error Err = addAllTypesFromDWP(
91506c3fb27SDimitry Andric               Out, TypeIndexEntries, TUIndex, OutSection, TypeInputSection,
91606c3fb27SDimitry Andric               CurEntry, ContributionOffsets[TypesContributionIndex],
9175f757f3fSDimitry Andric               TypesContributionIndex, OverflowOptValue, AnySectionOverflow))
91806c3fb27SDimitry Andric         return Err;
919fe6060f1SDimitry Andric     }
9205f757f3fSDimitry Andric     if (AnySectionOverflow)
9215f757f3fSDimitry Andric       break;
922fe6060f1SDimitry Andric   }
923fe6060f1SDimitry Andric 
924fe6060f1SDimitry Andric   if (Version < 5) {
925fe6060f1SDimitry Andric     // Lie about there being no info contributions so the TU index only includes
926fe6060f1SDimitry Andric     // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a
927fe6060f1SDimitry Andric     // contribution to the info section, so we do not want to lie about it.
928fe6060f1SDimitry Andric     ContributionOffsets[0] = 0;
929fe6060f1SDimitry Andric   }
930fe6060f1SDimitry Andric   writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
931fe6060f1SDimitry Andric              TypeIndexEntries, IndexVersion);
932fe6060f1SDimitry Andric 
933fe6060f1SDimitry Andric   if (Version < 5) {
934fe6060f1SDimitry Andric     // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
935fe6060f1SDimitry Andric     // section does not exist, so no need to do anything about this.
936fe6060f1SDimitry Andric     ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0;
937fe6060f1SDimitry Andric     // Unlie about the info contribution
938fe6060f1SDimitry Andric     ContributionOffsets[0] = 1;
939fe6060f1SDimitry Andric   }
940fe6060f1SDimitry Andric 
941fe6060f1SDimitry Andric   writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
942fe6060f1SDimitry Andric              IndexEntries, IndexVersion);
943fe6060f1SDimitry Andric 
944fe6060f1SDimitry Andric   return Error::success();
945fe6060f1SDimitry Andric }
946fe6060f1SDimitry Andric } // namespace llvm
947