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