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