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