Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
35269 views
1
//===- DWARFUnit.cpp ------------------------------------------------------===//
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
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
10
#include "llvm/ADT/SmallString.h"
11
#include "llvm/ADT/StringRef.h"
12
#include "llvm/BinaryFormat/Dwarf.h"
13
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
14
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
15
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
16
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
17
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
18
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
19
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
20
#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
21
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
22
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
23
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
24
#include "llvm/DebugInfo/DWARF/DWARFListTable.h"
25
#include "llvm/DebugInfo/DWARF/DWARFObject.h"
26
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
27
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
28
#include "llvm/Object/ObjectFile.h"
29
#include "llvm/Support/DataExtractor.h"
30
#include "llvm/Support/Errc.h"
31
#include "llvm/Support/Path.h"
32
#include <algorithm>
33
#include <cassert>
34
#include <cstddef>
35
#include <cstdint>
36
#include <utility>
37
#include <vector>
38
39
using namespace llvm;
40
using namespace dwarf;
41
42
void DWARFUnitVector::addUnitsForSection(DWARFContext &C,
43
const DWARFSection &Section,
44
DWARFSectionKind SectionKind) {
45
const DWARFObject &D = C.getDWARFObj();
46
addUnitsImpl(C, D, Section, C.getDebugAbbrev(), &D.getRangesSection(),
47
&D.getLocSection(), D.getStrSection(),
48
D.getStrOffsetsSection(), &D.getAddrSection(),
49
D.getLineSection(), D.isLittleEndian(), false, false,
50
SectionKind);
51
}
52
53
void DWARFUnitVector::addUnitsForDWOSection(DWARFContext &C,
54
const DWARFSection &DWOSection,
55
DWARFSectionKind SectionKind,
56
bool Lazy) {
57
const DWARFObject &D = C.getDWARFObj();
58
addUnitsImpl(C, D, DWOSection, C.getDebugAbbrevDWO(), &D.getRangesDWOSection(),
59
&D.getLocDWOSection(), D.getStrDWOSection(),
60
D.getStrOffsetsDWOSection(), &D.getAddrSection(),
61
D.getLineDWOSection(), C.isLittleEndian(), true, Lazy,
62
SectionKind);
63
}
64
65
void DWARFUnitVector::addUnitsImpl(
66
DWARFContext &Context, const DWARFObject &Obj, const DWARFSection &Section,
67
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
68
const DWARFSection *LocSection, StringRef SS, const DWARFSection &SOS,
69
const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO,
70
bool Lazy, DWARFSectionKind SectionKind) {
71
DWARFDataExtractor Data(Obj, Section, LE, 0);
72
// Lazy initialization of Parser, now that we have all section info.
73
if (!Parser) {
74
Parser = [=, &Context, &Obj, &Section, &SOS,
75
&LS](uint64_t Offset, DWARFSectionKind SectionKind,
76
const DWARFSection *CurSection,
77
const DWARFUnitIndex::Entry *IndexEntry)
78
-> std::unique_ptr<DWARFUnit> {
79
const DWARFSection &InfoSection = CurSection ? *CurSection : Section;
80
DWARFDataExtractor Data(Obj, InfoSection, LE, 0);
81
if (!Data.isValidOffset(Offset))
82
return nullptr;
83
DWARFUnitHeader Header;
84
if (Error ExtractErr =
85
Header.extract(Context, Data, &Offset, SectionKind)) {
86
Context.getWarningHandler()(std::move(ExtractErr));
87
return nullptr;
88
}
89
if (!IndexEntry && IsDWO) {
90
const DWARFUnitIndex &Index = getDWARFUnitIndex(
91
Context, Header.isTypeUnit() ? DW_SECT_EXT_TYPES : DW_SECT_INFO);
92
if (Index) {
93
if (Header.isTypeUnit())
94
IndexEntry = Index.getFromHash(Header.getTypeHash());
95
else if (auto DWOId = Header.getDWOId())
96
IndexEntry = Index.getFromHash(*DWOId);
97
}
98
if (!IndexEntry)
99
IndexEntry = Index.getFromOffset(Header.getOffset());
100
}
101
if (IndexEntry) {
102
if (Error ApplicationErr = Header.applyIndexEntry(IndexEntry)) {
103
Context.getWarningHandler()(std::move(ApplicationErr));
104
return nullptr;
105
}
106
}
107
std::unique_ptr<DWARFUnit> U;
108
if (Header.isTypeUnit())
109
U = std::make_unique<DWARFTypeUnit>(Context, InfoSection, Header, DA,
110
RS, LocSection, SS, SOS, AOS, LS,
111
LE, IsDWO, *this);
112
else
113
U = std::make_unique<DWARFCompileUnit>(Context, InfoSection, Header,
114
DA, RS, LocSection, SS, SOS,
115
AOS, LS, LE, IsDWO, *this);
116
return U;
117
};
118
}
119
if (Lazy)
120
return;
121
// Find a reasonable insertion point within the vector. We skip over
122
// (a) units from a different section, (b) units from the same section
123
// but with lower offset-within-section. This keeps units in order
124
// within a section, although not necessarily within the object file,
125
// even if we do lazy parsing.
126
auto I = this->begin();
127
uint64_t Offset = 0;
128
while (Data.isValidOffset(Offset)) {
129
if (I != this->end() &&
130
(&(*I)->getInfoSection() != &Section || (*I)->getOffset() == Offset)) {
131
++I;
132
continue;
133
}
134
auto U = Parser(Offset, SectionKind, &Section, nullptr);
135
// If parsing failed, we're done with this section.
136
if (!U)
137
break;
138
Offset = U->getNextUnitOffset();
139
I = std::next(this->insert(I, std::move(U)));
140
}
141
}
142
143
DWARFUnit *DWARFUnitVector::addUnit(std::unique_ptr<DWARFUnit> Unit) {
144
auto I = llvm::upper_bound(*this, Unit,
145
[](const std::unique_ptr<DWARFUnit> &LHS,
146
const std::unique_ptr<DWARFUnit> &RHS) {
147
return LHS->getOffset() < RHS->getOffset();
148
});
149
return this->insert(I, std::move(Unit))->get();
150
}
151
152
DWARFUnit *DWARFUnitVector::getUnitForOffset(uint64_t Offset) const {
153
auto end = begin() + getNumInfoUnits();
154
auto *CU =
155
std::upper_bound(begin(), end, Offset,
156
[](uint64_t LHS, const std::unique_ptr<DWARFUnit> &RHS) {
157
return LHS < RHS->getNextUnitOffset();
158
});
159
if (CU != end && (*CU)->getOffset() <= Offset)
160
return CU->get();
161
return nullptr;
162
}
163
164
DWARFUnit *
165
DWARFUnitVector::getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) {
166
const auto *CUOff = E.getContribution(DW_SECT_INFO);
167
if (!CUOff)
168
return nullptr;
169
170
uint64_t Offset = CUOff->getOffset();
171
auto end = begin() + getNumInfoUnits();
172
173
auto *CU =
174
std::upper_bound(begin(), end, CUOff->getOffset(),
175
[](uint64_t LHS, const std::unique_ptr<DWARFUnit> &RHS) {
176
return LHS < RHS->getNextUnitOffset();
177
});
178
if (CU != end && (*CU)->getOffset() <= Offset)
179
return CU->get();
180
181
if (!Parser)
182
return nullptr;
183
184
auto U = Parser(Offset, DW_SECT_INFO, nullptr, &E);
185
if (!U)
186
return nullptr;
187
188
auto *NewCU = U.get();
189
this->insert(CU, std::move(U));
190
++NumInfoUnits;
191
return NewCU;
192
}
193
194
DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
195
const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA,
196
const DWARFSection *RS, const DWARFSection *LocSection,
197
StringRef SS, const DWARFSection &SOS,
198
const DWARFSection *AOS, const DWARFSection &LS, bool LE,
199
bool IsDWO, const DWARFUnitVector &UnitVector)
200
: Context(DC), InfoSection(Section), Header(Header), Abbrev(DA),
201
RangeSection(RS), LineSection(LS), StringSection(SS),
202
StringOffsetSection(SOS), AddrOffsetSection(AOS), IsLittleEndian(LE),
203
IsDWO(IsDWO), UnitVector(UnitVector) {
204
clear();
205
}
206
207
DWARFUnit::~DWARFUnit() = default;
208
209
DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const {
210
return DWARFDataExtractor(Context.getDWARFObj(), InfoSection, IsLittleEndian,
211
getAddressByteSize());
212
}
213
214
std::optional<object::SectionedAddress>
215
DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const {
216
if (!AddrOffsetSectionBase) {
217
auto R = Context.info_section_units();
218
// Surprising if a DWO file has more than one skeleton unit in it - this
219
// probably shouldn't be valid, but if a use case is found, here's where to
220
// support it (probably have to linearly search for the matching skeleton CU
221
// here)
222
if (IsDWO && hasSingleElement(R))
223
return (*R.begin())->getAddrOffsetSectionItem(Index);
224
225
return std::nullopt;
226
}
227
228
uint64_t Offset = *AddrOffsetSectionBase + Index * getAddressByteSize();
229
if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize())
230
return std::nullopt;
231
DWARFDataExtractor DA(Context.getDWARFObj(), *AddrOffsetSection,
232
IsLittleEndian, getAddressByteSize());
233
uint64_t Section;
234
uint64_t Address = DA.getRelocatedAddress(&Offset, &Section);
235
return {{Address, Section}};
236
}
237
238
Expected<uint64_t> DWARFUnit::getStringOffsetSectionItem(uint32_t Index) const {
239
if (!StringOffsetsTableContribution)
240
return make_error<StringError>(
241
"DW_FORM_strx used without a valid string offsets table",
242
inconvertibleErrorCode());
243
unsigned ItemSize = getDwarfStringOffsetsByteSize();
244
uint64_t Offset = getStringOffsetsBase() + Index * ItemSize;
245
if (StringOffsetSection.Data.size() < Offset + ItemSize)
246
return make_error<StringError>("DW_FORM_strx uses index " + Twine(Index) +
247
", which is too large",
248
inconvertibleErrorCode());
249
DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection,
250
IsLittleEndian, 0);
251
return DA.getRelocatedValue(ItemSize, &Offset);
252
}
253
254
Error DWARFUnitHeader::extract(DWARFContext &Context,
255
const DWARFDataExtractor &debug_info,
256
uint64_t *offset_ptr,
257
DWARFSectionKind SectionKind) {
258
Offset = *offset_ptr;
259
Error Err = Error::success();
260
IndexEntry = nullptr;
261
std::tie(Length, FormParams.Format) =
262
debug_info.getInitialLength(offset_ptr, &Err);
263
FormParams.Version = debug_info.getU16(offset_ptr, &Err);
264
if (FormParams.Version >= 5) {
265
UnitType = debug_info.getU8(offset_ptr, &Err);
266
FormParams.AddrSize = debug_info.getU8(offset_ptr, &Err);
267
AbbrOffset = debug_info.getRelocatedValue(
268
FormParams.getDwarfOffsetByteSize(), offset_ptr, nullptr, &Err);
269
} else {
270
AbbrOffset = debug_info.getRelocatedValue(
271
FormParams.getDwarfOffsetByteSize(), offset_ptr, nullptr, &Err);
272
FormParams.AddrSize = debug_info.getU8(offset_ptr, &Err);
273
// Fake a unit type based on the section type. This isn't perfect,
274
// but distinguishing compile and type units is generally enough.
275
if (SectionKind == DW_SECT_EXT_TYPES)
276
UnitType = DW_UT_type;
277
else
278
UnitType = DW_UT_compile;
279
}
280
if (isTypeUnit()) {
281
TypeHash = debug_info.getU64(offset_ptr, &Err);
282
TypeOffset = debug_info.getUnsigned(
283
offset_ptr, FormParams.getDwarfOffsetByteSize(), &Err);
284
} else if (UnitType == DW_UT_split_compile || UnitType == DW_UT_skeleton)
285
DWOId = debug_info.getU64(offset_ptr, &Err);
286
287
if (Err)
288
return joinErrors(
289
createStringError(
290
errc::invalid_argument,
291
"DWARF unit at 0x%8.8" PRIx64 " cannot be parsed:", Offset),
292
std::move(Err));
293
294
// Header fields all parsed, capture the size of this unit header.
295
assert(*offset_ptr - Offset <= 255 && "unexpected header size");
296
Size = uint8_t(*offset_ptr - Offset);
297
uint64_t NextCUOffset = Offset + getUnitLengthFieldByteSize() + getLength();
298
299
if (!debug_info.isValidOffset(getNextUnitOffset() - 1))
300
return createStringError(errc::invalid_argument,
301
"DWARF unit from offset 0x%8.8" PRIx64 " incl. "
302
"to offset 0x%8.8" PRIx64 " excl. "
303
"extends past section size 0x%8.8zx",
304
Offset, NextCUOffset, debug_info.size());
305
306
if (!DWARFContext::isSupportedVersion(getVersion()))
307
return createStringError(
308
errc::invalid_argument,
309
"DWARF unit at offset 0x%8.8" PRIx64 " "
310
"has unsupported version %" PRIu16 ", supported are 2-%u",
311
Offset, getVersion(), DWARFContext::getMaxSupportedVersion());
312
313
// Type offset is unit-relative; should be after the header and before
314
// the end of the current unit.
315
if (isTypeUnit() && TypeOffset < Size)
316
return createStringError(errc::invalid_argument,
317
"DWARF type unit at offset "
318
"0x%8.8" PRIx64 " "
319
"has its relocated type_offset 0x%8.8" PRIx64 " "
320
"pointing inside the header",
321
Offset, Offset + TypeOffset);
322
323
if (isTypeUnit() && TypeOffset >= getUnitLengthFieldByteSize() + getLength())
324
return createStringError(
325
errc::invalid_argument,
326
"DWARF type unit from offset 0x%8.8" PRIx64 " incl. "
327
"to offset 0x%8.8" PRIx64 " excl. has its "
328
"relocated type_offset 0x%8.8" PRIx64 " pointing past the unit end",
329
Offset, NextCUOffset, Offset + TypeOffset);
330
331
if (Error SizeErr = DWARFContext::checkAddressSizeSupported(
332
getAddressByteSize(), errc::invalid_argument,
333
"DWARF unit at offset 0x%8.8" PRIx64, Offset))
334
return SizeErr;
335
336
// Keep track of the highest DWARF version we encounter across all units.
337
Context.setMaxVersionIfGreater(getVersion());
338
return Error::success();
339
}
340
341
Error DWARFUnitHeader::applyIndexEntry(const DWARFUnitIndex::Entry *Entry) {
342
assert(Entry);
343
assert(!IndexEntry);
344
IndexEntry = Entry;
345
if (AbbrOffset)
346
return createStringError(errc::invalid_argument,
347
"DWARF package unit at offset 0x%8.8" PRIx64
348
" has a non-zero abbreviation offset",
349
Offset);
350
351
auto *UnitContrib = IndexEntry->getContribution();
352
if (!UnitContrib)
353
return createStringError(errc::invalid_argument,
354
"DWARF package unit at offset 0x%8.8" PRIx64
355
" has no contribution index",
356
Offset);
357
358
uint64_t IndexLength = getLength() + getUnitLengthFieldByteSize();
359
if (UnitContrib->getLength() != IndexLength)
360
return createStringError(errc::invalid_argument,
361
"DWARF package unit at offset 0x%8.8" PRIx64
362
" has an inconsistent index (expected: %" PRIu64
363
", actual: %" PRIu64 ")",
364
Offset, UnitContrib->getLength(), IndexLength);
365
366
auto *AbbrEntry = IndexEntry->getContribution(DW_SECT_ABBREV);
367
if (!AbbrEntry)
368
return createStringError(errc::invalid_argument,
369
"DWARF package unit at offset 0x%8.8" PRIx64
370
" missing abbreviation column",
371
Offset);
372
373
AbbrOffset = AbbrEntry->getOffset();
374
return Error::success();
375
}
376
377
Error DWARFUnit::extractRangeList(uint64_t RangeListOffset,
378
DWARFDebugRangeList &RangeList) const {
379
// Require that compile unit is extracted.
380
assert(!DieArray.empty());
381
DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection,
382
IsLittleEndian, getAddressByteSize());
383
uint64_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
384
return RangeList.extract(RangesData, &ActualRangeListOffset);
385
}
386
387
void DWARFUnit::clear() {
388
Abbrevs = nullptr;
389
BaseAddr.reset();
390
RangeSectionBase = 0;
391
LocSectionBase = 0;
392
AddrOffsetSectionBase = std::nullopt;
393
SU = nullptr;
394
clearDIEs(false);
395
AddrDieMap.clear();
396
if (DWO)
397
DWO->clear();
398
DWO.reset();
399
}
400
401
const char *DWARFUnit::getCompilationDir() {
402
return dwarf::toString(getUnitDIE().find(DW_AT_comp_dir), nullptr);
403
}
404
405
void DWARFUnit::extractDIEsToVector(
406
bool AppendCUDie, bool AppendNonCUDies,
407
std::vector<DWARFDebugInfoEntry> &Dies) const {
408
if (!AppendCUDie && !AppendNonCUDies)
409
return;
410
411
// Set the offset to that of the first DIE and calculate the start of the
412
// next compilation unit header.
413
uint64_t DIEOffset = getOffset() + getHeaderSize();
414
uint64_t NextCUOffset = getNextUnitOffset();
415
DWARFDebugInfoEntry DIE;
416
DWARFDataExtractor DebugInfoData = getDebugInfoExtractor();
417
// The end offset has been already checked by DWARFUnitHeader::extract.
418
assert(DebugInfoData.isValidOffset(NextCUOffset - 1));
419
std::vector<uint32_t> Parents;
420
std::vector<uint32_t> PrevSiblings;
421
bool IsCUDie = true;
422
423
assert(
424
((AppendCUDie && Dies.empty()) || (!AppendCUDie && Dies.size() == 1)) &&
425
"Dies array is not empty");
426
427
// Fill Parents and Siblings stacks with initial value.
428
Parents.push_back(UINT32_MAX);
429
if (!AppendCUDie)
430
Parents.push_back(0);
431
PrevSiblings.push_back(0);
432
433
// Start to extract dies.
434
do {
435
assert(Parents.size() > 0 && "Empty parents stack");
436
assert((Parents.back() == UINT32_MAX || Parents.back() <= Dies.size()) &&
437
"Wrong parent index");
438
439
// Extract die. Stop if any error occurred.
440
if (!DIE.extractFast(*this, &DIEOffset, DebugInfoData, NextCUOffset,
441
Parents.back()))
442
break;
443
444
// If previous sibling is remembered then update it`s SiblingIdx field.
445
if (PrevSiblings.back() > 0) {
446
assert(PrevSiblings.back() < Dies.size() &&
447
"Previous sibling index is out of Dies boundaries");
448
Dies[PrevSiblings.back()].setSiblingIdx(Dies.size());
449
}
450
451
// Store die into the Dies vector.
452
if (IsCUDie) {
453
if (AppendCUDie)
454
Dies.push_back(DIE);
455
if (!AppendNonCUDies)
456
break;
457
// The average bytes per DIE entry has been seen to be
458
// around 14-20 so let's pre-reserve the needed memory for
459
// our DIE entries accordingly.
460
Dies.reserve(Dies.size() + getDebugInfoSize() / 14);
461
} else {
462
// Remember last previous sibling.
463
PrevSiblings.back() = Dies.size();
464
465
Dies.push_back(DIE);
466
}
467
468
// Check for new children scope.
469
if (const DWARFAbbreviationDeclaration *AbbrDecl =
470
DIE.getAbbreviationDeclarationPtr()) {
471
if (AbbrDecl->hasChildren()) {
472
if (AppendCUDie || !IsCUDie) {
473
assert(Dies.size() > 0 && "Dies does not contain any die");
474
Parents.push_back(Dies.size() - 1);
475
PrevSiblings.push_back(0);
476
}
477
} else if (IsCUDie)
478
// Stop if we have single compile unit die w/o children.
479
break;
480
} else {
481
// NULL DIE: finishes current children scope.
482
Parents.pop_back();
483
PrevSiblings.pop_back();
484
}
485
486
if (IsCUDie)
487
IsCUDie = false;
488
489
// Stop when compile unit die is removed from the parents stack.
490
} while (Parents.size() > 1);
491
}
492
493
void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
494
if (Error e = tryExtractDIEsIfNeeded(CUDieOnly))
495
Context.getRecoverableErrorHandler()(std::move(e));
496
}
497
498
Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) {
499
if ((CUDieOnly && !DieArray.empty()) ||
500
DieArray.size() > 1)
501
return Error::success(); // Already parsed.
502
503
bool HasCUDie = !DieArray.empty();
504
extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
505
506
if (DieArray.empty())
507
return Error::success();
508
509
// If CU DIE was just parsed, copy several attribute values from it.
510
if (HasCUDie)
511
return Error::success();
512
513
DWARFDie UnitDie(this, &DieArray[0]);
514
if (std::optional<uint64_t> DWOId =
515
toUnsigned(UnitDie.find(DW_AT_GNU_dwo_id)))
516
Header.setDWOId(*DWOId);
517
if (!IsDWO) {
518
assert(AddrOffsetSectionBase == std::nullopt);
519
assert(RangeSectionBase == 0);
520
assert(LocSectionBase == 0);
521
AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_addr_base));
522
if (!AddrOffsetSectionBase)
523
AddrOffsetSectionBase =
524
toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base));
525
RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0);
526
LocSectionBase = toSectionOffset(UnitDie.find(DW_AT_loclists_base), 0);
527
}
528
529
// In general, in DWARF v5 and beyond we derive the start of the unit's
530
// contribution to the string offsets table from the unit DIE's
531
// DW_AT_str_offsets_base attribute. Split DWARF units do not use this
532
// attribute, so we assume that there is a contribution to the string
533
// offsets table starting at offset 0 of the debug_str_offsets.dwo section.
534
// In both cases we need to determine the format of the contribution,
535
// which may differ from the unit's format.
536
DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection,
537
IsLittleEndian, 0);
538
if (IsDWO || getVersion() >= 5) {
539
auto StringOffsetOrError =
540
IsDWO ? determineStringOffsetsTableContributionDWO(DA)
541
: determineStringOffsetsTableContribution(DA);
542
if (!StringOffsetOrError)
543
return createStringError(errc::invalid_argument,
544
"invalid reference to or invalid content in "
545
".debug_str_offsets[.dwo]: " +
546
toString(StringOffsetOrError.takeError()));
547
548
StringOffsetsTableContribution = *StringOffsetOrError;
549
}
550
551
// DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to
552
// describe address ranges.
553
if (getVersion() >= 5) {
554
// In case of DWP, the base offset from the index has to be added.
555
if (IsDWO) {
556
uint64_t ContributionBaseOffset = 0;
557
if (auto *IndexEntry = Header.getIndexEntry())
558
if (auto *Contrib = IndexEntry->getContribution(DW_SECT_RNGLISTS))
559
ContributionBaseOffset = Contrib->getOffset();
560
setRangesSection(
561
&Context.getDWARFObj().getRnglistsDWOSection(),
562
ContributionBaseOffset +
563
DWARFListTableHeader::getHeaderSize(Header.getFormat()));
564
} else
565
setRangesSection(&Context.getDWARFObj().getRnglistsSection(),
566
toSectionOffset(UnitDie.find(DW_AT_rnglists_base),
567
DWARFListTableHeader::getHeaderSize(
568
Header.getFormat())));
569
}
570
571
if (IsDWO) {
572
// If we are reading a package file, we need to adjust the location list
573
// data based on the index entries.
574
StringRef Data = Header.getVersion() >= 5
575
? Context.getDWARFObj().getLoclistsDWOSection().Data
576
: Context.getDWARFObj().getLocDWOSection().Data;
577
if (auto *IndexEntry = Header.getIndexEntry())
578
if (const auto *C = IndexEntry->getContribution(
579
Header.getVersion() >= 5 ? DW_SECT_LOCLISTS : DW_SECT_EXT_LOC))
580
Data = Data.substr(C->getOffset(), C->getLength());
581
582
DWARFDataExtractor DWARFData(Data, IsLittleEndian, getAddressByteSize());
583
LocTable =
584
std::make_unique<DWARFDebugLoclists>(DWARFData, Header.getVersion());
585
LocSectionBase = DWARFListTableHeader::getHeaderSize(Header.getFormat());
586
} else if (getVersion() >= 5) {
587
LocTable = std::make_unique<DWARFDebugLoclists>(
588
DWARFDataExtractor(Context.getDWARFObj(),
589
Context.getDWARFObj().getLoclistsSection(),
590
IsLittleEndian, getAddressByteSize()),
591
getVersion());
592
} else {
593
LocTable = std::make_unique<DWARFDebugLoc>(DWARFDataExtractor(
594
Context.getDWARFObj(), Context.getDWARFObj().getLocSection(),
595
IsLittleEndian, getAddressByteSize()));
596
}
597
598
// Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
599
// skeleton CU DIE, so that DWARF users not aware of it are not broken.
600
return Error::success();
601
}
602
603
bool DWARFUnit::parseDWO(StringRef DWOAlternativeLocation) {
604
if (IsDWO)
605
return false;
606
if (DWO)
607
return false;
608
DWARFDie UnitDie = getUnitDIE();
609
if (!UnitDie)
610
return false;
611
auto DWOFileName = getVersion() >= 5
612
? dwarf::toString(UnitDie.find(DW_AT_dwo_name))
613
: dwarf::toString(UnitDie.find(DW_AT_GNU_dwo_name));
614
if (!DWOFileName)
615
return false;
616
auto CompilationDir = dwarf::toString(UnitDie.find(DW_AT_comp_dir));
617
SmallString<16> AbsolutePath;
618
if (sys::path::is_relative(*DWOFileName) && CompilationDir &&
619
*CompilationDir) {
620
sys::path::append(AbsolutePath, *CompilationDir);
621
}
622
sys::path::append(AbsolutePath, *DWOFileName);
623
auto DWOId = getDWOId();
624
if (!DWOId)
625
return false;
626
auto DWOContext = Context.getDWOContext(AbsolutePath);
627
if (!DWOContext) {
628
// Use the alternative location to get the DWARF context for the DWO object.
629
if (DWOAlternativeLocation.empty())
630
return false;
631
// If the alternative context does not correspond to the original DWO object
632
// (different hashes), the below 'getDWOCompileUnitForHash' call will catch
633
// the issue, with a returned null context.
634
DWOContext = Context.getDWOContext(DWOAlternativeLocation);
635
if (!DWOContext)
636
return false;
637
}
638
639
DWARFCompileUnit *DWOCU = DWOContext->getDWOCompileUnitForHash(*DWOId);
640
if (!DWOCU)
641
return false;
642
DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU);
643
DWO->setSkeletonUnit(this);
644
// Share .debug_addr and .debug_ranges section with compile unit in .dwo
645
if (AddrOffsetSectionBase)
646
DWO->setAddrOffsetSection(AddrOffsetSection, *AddrOffsetSectionBase);
647
if (getVersion() == 4) {
648
auto DWORangesBase = UnitDie.getRangesBaseAttribute();
649
DWO->setRangesSection(RangeSection, DWORangesBase.value_or(0));
650
}
651
652
return true;
653
}
654
655
void DWARFUnit::clearDIEs(bool KeepCUDie) {
656
// Do not use resize() + shrink_to_fit() to free memory occupied by dies.
657
// shrink_to_fit() is a *non-binding* request to reduce capacity() to size().
658
// It depends on the implementation whether the request is fulfilled.
659
// Create a new vector with a small capacity and assign it to the DieArray to
660
// have previous contents freed.
661
DieArray = (KeepCUDie && !DieArray.empty())
662
? std::vector<DWARFDebugInfoEntry>({DieArray[0]})
663
: std::vector<DWARFDebugInfoEntry>();
664
}
665
666
Expected<DWARFAddressRangesVector>
667
DWARFUnit::findRnglistFromOffset(uint64_t Offset) {
668
if (getVersion() <= 4) {
669
DWARFDebugRangeList RangeList;
670
if (Error E = extractRangeList(Offset, RangeList))
671
return std::move(E);
672
return RangeList.getAbsoluteRanges(getBaseAddress());
673
}
674
DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection,
675
IsLittleEndian, Header.getAddressByteSize());
676
DWARFDebugRnglistTable RnglistTable;
677
auto RangeListOrError = RnglistTable.findList(RangesData, Offset);
678
if (RangeListOrError)
679
return RangeListOrError.get().getAbsoluteRanges(getBaseAddress(), *this);
680
return RangeListOrError.takeError();
681
}
682
683
Expected<DWARFAddressRangesVector>
684
DWARFUnit::findRnglistFromIndex(uint32_t Index) {
685
if (auto Offset = getRnglistOffset(Index))
686
return findRnglistFromOffset(*Offset);
687
688
return createStringError(errc::invalid_argument,
689
"invalid range list table index %d (possibly "
690
"missing the entire range list table)",
691
Index);
692
}
693
694
Expected<DWARFAddressRangesVector> DWARFUnit::collectAddressRanges() {
695
DWARFDie UnitDie = getUnitDIE();
696
if (!UnitDie)
697
return createStringError(errc::invalid_argument, "No unit DIE");
698
699
// First, check if unit DIE describes address ranges for the whole unit.
700
auto CUDIERangesOrError = UnitDie.getAddressRanges();
701
if (!CUDIERangesOrError)
702
return createStringError(errc::invalid_argument,
703
"decoding address ranges: %s",
704
toString(CUDIERangesOrError.takeError()).c_str());
705
return *CUDIERangesOrError;
706
}
707
708
Expected<DWARFLocationExpressionsVector>
709
DWARFUnit::findLoclistFromOffset(uint64_t Offset) {
710
DWARFLocationExpressionsVector Result;
711
712
Error InterpretationError = Error::success();
713
714
Error ParseError = getLocationTable().visitAbsoluteLocationList(
715
Offset, getBaseAddress(),
716
[this](uint32_t Index) { return getAddrOffsetSectionItem(Index); },
717
[&](Expected<DWARFLocationExpression> L) {
718
if (L)
719
Result.push_back(std::move(*L));
720
else
721
InterpretationError =
722
joinErrors(L.takeError(), std::move(InterpretationError));
723
return !InterpretationError;
724
});
725
726
if (ParseError || InterpretationError)
727
return joinErrors(std::move(ParseError), std::move(InterpretationError));
728
729
return Result;
730
}
731
732
void DWARFUnit::updateAddressDieMap(DWARFDie Die) {
733
if (Die.isSubroutineDIE()) {
734
auto DIERangesOrError = Die.getAddressRanges();
735
if (DIERangesOrError) {
736
for (const auto &R : DIERangesOrError.get()) {
737
// Ignore 0-sized ranges.
738
if (R.LowPC == R.HighPC)
739
continue;
740
auto B = AddrDieMap.upper_bound(R.LowPC);
741
if (B != AddrDieMap.begin() && R.LowPC < (--B)->second.first) {
742
// The range is a sub-range of existing ranges, we need to split the
743
// existing range.
744
if (R.HighPC < B->second.first)
745
AddrDieMap[R.HighPC] = B->second;
746
if (R.LowPC > B->first)
747
AddrDieMap[B->first].first = R.LowPC;
748
}
749
AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die);
750
}
751
} else
752
llvm::consumeError(DIERangesOrError.takeError());
753
}
754
// Parent DIEs are added to the AddrDieMap prior to the Children DIEs to
755
// simplify the logic to update AddrDieMap. The child's range will always
756
// be equal or smaller than the parent's range. With this assumption, when
757
// adding one range into the map, it will at most split a range into 3
758
// sub-ranges.
759
for (DWARFDie Child = Die.getFirstChild(); Child; Child = Child.getSibling())
760
updateAddressDieMap(Child);
761
}
762
763
DWARFDie DWARFUnit::getSubroutineForAddress(uint64_t Address) {
764
extractDIEsIfNeeded(false);
765
if (AddrDieMap.empty())
766
updateAddressDieMap(getUnitDIE());
767
auto R = AddrDieMap.upper_bound(Address);
768
if (R == AddrDieMap.begin())
769
return DWARFDie();
770
// upper_bound's previous item contains Address.
771
--R;
772
if (Address >= R->second.first)
773
return DWARFDie();
774
return R->second.second;
775
}
776
777
void DWARFUnit::updateVariableDieMap(DWARFDie Die) {
778
for (DWARFDie Child : Die) {
779
if (isType(Child.getTag()))
780
continue;
781
updateVariableDieMap(Child);
782
}
783
784
if (Die.getTag() != DW_TAG_variable)
785
return;
786
787
Expected<DWARFLocationExpressionsVector> Locations =
788
Die.getLocations(DW_AT_location);
789
if (!Locations) {
790
// Missing DW_AT_location is fine here.
791
consumeError(Locations.takeError());
792
return;
793
}
794
795
uint64_t Address = UINT64_MAX;
796
797
for (const DWARFLocationExpression &Location : *Locations) {
798
uint8_t AddressSize = getAddressByteSize();
799
DataExtractor Data(Location.Expr, isLittleEndian(), AddressSize);
800
DWARFExpression Expr(Data, AddressSize);
801
auto It = Expr.begin();
802
if (It == Expr.end())
803
continue;
804
805
// Match exactly the main sequence used to describe global variables:
806
// `DW_OP_addr[x] [+ DW_OP_plus_uconst]`. Currently, this is the sequence
807
// that LLVM produces for DILocalVariables and DIGlobalVariables. If, in
808
// future, the DWARF producer (`DwarfCompileUnit::addLocationAttribute()` is
809
// a good starting point) is extended to use further expressions, this code
810
// needs to be updated.
811
uint64_t LocationAddr;
812
if (It->getCode() == dwarf::DW_OP_addr) {
813
LocationAddr = It->getRawOperand(0);
814
} else if (It->getCode() == dwarf::DW_OP_addrx) {
815
uint64_t DebugAddrOffset = It->getRawOperand(0);
816
if (auto Pointer = getAddrOffsetSectionItem(DebugAddrOffset)) {
817
LocationAddr = Pointer->Address;
818
}
819
} else {
820
continue;
821
}
822
823
// Read the optional 2nd operand, a DW_OP_plus_uconst.
824
if (++It != Expr.end()) {
825
if (It->getCode() != dwarf::DW_OP_plus_uconst)
826
continue;
827
828
LocationAddr += It->getRawOperand(0);
829
830
// Probe for a 3rd operand, if it exists, bail.
831
if (++It != Expr.end())
832
continue;
833
}
834
835
Address = LocationAddr;
836
break;
837
}
838
839
// Get the size of the global variable. If all else fails (i.e. the global has
840
// no type), then we use a size of one to still allow symbolization of the
841
// exact address.
842
uint64_t GVSize = 1;
843
if (Die.getAttributeValueAsReferencedDie(DW_AT_type))
844
if (std::optional<uint64_t> Size = Die.getTypeSize(getAddressByteSize()))
845
GVSize = *Size;
846
847
if (Address != UINT64_MAX)
848
VariableDieMap[Address] = {Address + GVSize, Die};
849
}
850
851
DWARFDie DWARFUnit::getVariableForAddress(uint64_t Address) {
852
extractDIEsIfNeeded(false);
853
854
auto RootDie = getUnitDIE();
855
856
auto RootLookup = RootsParsedForVariables.insert(RootDie.getOffset());
857
if (RootLookup.second)
858
updateVariableDieMap(RootDie);
859
860
auto R = VariableDieMap.upper_bound(Address);
861
if (R == VariableDieMap.begin())
862
return DWARFDie();
863
864
// upper_bound's previous item contains Address.
865
--R;
866
if (Address >= R->second.first)
867
return DWARFDie();
868
return R->second.second;
869
}
870
871
void
872
DWARFUnit::getInlinedChainForAddress(uint64_t Address,
873
SmallVectorImpl<DWARFDie> &InlinedChain) {
874
assert(InlinedChain.empty());
875
// Try to look for subprogram DIEs in the DWO file.
876
parseDWO();
877
// First, find the subroutine that contains the given address (the leaf
878
// of inlined chain).
879
DWARFDie SubroutineDIE =
880
(DWO ? *DWO : *this).getSubroutineForAddress(Address);
881
882
while (SubroutineDIE) {
883
if (SubroutineDIE.isSubprogramDIE()) {
884
InlinedChain.push_back(SubroutineDIE);
885
return;
886
}
887
if (SubroutineDIE.getTag() == DW_TAG_inlined_subroutine)
888
InlinedChain.push_back(SubroutineDIE);
889
SubroutineDIE = SubroutineDIE.getParent();
890
}
891
}
892
893
const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context,
894
DWARFSectionKind Kind) {
895
if (Kind == DW_SECT_INFO)
896
return Context.getCUIndex();
897
assert(Kind == DW_SECT_EXT_TYPES);
898
return Context.getTUIndex();
899
}
900
901
DWARFDie DWARFUnit::getParent(const DWARFDebugInfoEntry *Die) {
902
if (const DWARFDebugInfoEntry *Entry = getParentEntry(Die))
903
return DWARFDie(this, Entry);
904
905
return DWARFDie();
906
}
907
908
const DWARFDebugInfoEntry *
909
DWARFUnit::getParentEntry(const DWARFDebugInfoEntry *Die) const {
910
if (!Die)
911
return nullptr;
912
assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size());
913
914
if (std::optional<uint32_t> ParentIdx = Die->getParentIdx()) {
915
assert(*ParentIdx < DieArray.size() &&
916
"ParentIdx is out of DieArray boundaries");
917
return getDebugInfoEntry(*ParentIdx);
918
}
919
920
return nullptr;
921
}
922
923
DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) {
924
if (const DWARFDebugInfoEntry *Sibling = getSiblingEntry(Die))
925
return DWARFDie(this, Sibling);
926
927
return DWARFDie();
928
}
929
930
const DWARFDebugInfoEntry *
931
DWARFUnit::getSiblingEntry(const DWARFDebugInfoEntry *Die) const {
932
if (!Die)
933
return nullptr;
934
assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size());
935
936
if (std::optional<uint32_t> SiblingIdx = Die->getSiblingIdx()) {
937
assert(*SiblingIdx < DieArray.size() &&
938
"SiblingIdx is out of DieArray boundaries");
939
return &DieArray[*SiblingIdx];
940
}
941
942
return nullptr;
943
}
944
945
DWARFDie DWARFUnit::getPreviousSibling(const DWARFDebugInfoEntry *Die) {
946
if (const DWARFDebugInfoEntry *Sibling = getPreviousSiblingEntry(Die))
947
return DWARFDie(this, Sibling);
948
949
return DWARFDie();
950
}
951
952
const DWARFDebugInfoEntry *
953
DWARFUnit::getPreviousSiblingEntry(const DWARFDebugInfoEntry *Die) const {
954
if (!Die)
955
return nullptr;
956
assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size());
957
958
std::optional<uint32_t> ParentIdx = Die->getParentIdx();
959
if (!ParentIdx)
960
// Die is a root die, there is no previous sibling.
961
return nullptr;
962
963
assert(*ParentIdx < DieArray.size() &&
964
"ParentIdx is out of DieArray boundaries");
965
assert(getDIEIndex(Die) > 0 && "Die is a root die");
966
967
uint32_t PrevDieIdx = getDIEIndex(Die) - 1;
968
if (PrevDieIdx == *ParentIdx)
969
// Immediately previous node is parent, there is no previous sibling.
970
return nullptr;
971
972
while (DieArray[PrevDieIdx].getParentIdx() != *ParentIdx) {
973
PrevDieIdx = *DieArray[PrevDieIdx].getParentIdx();
974
975
assert(PrevDieIdx < DieArray.size() &&
976
"PrevDieIdx is out of DieArray boundaries");
977
assert(PrevDieIdx >= *ParentIdx &&
978
"PrevDieIdx is not a child of parent of Die");
979
}
980
981
return &DieArray[PrevDieIdx];
982
}
983
984
DWARFDie DWARFUnit::getFirstChild(const DWARFDebugInfoEntry *Die) {
985
if (const DWARFDebugInfoEntry *Child = getFirstChildEntry(Die))
986
return DWARFDie(this, Child);
987
988
return DWARFDie();
989
}
990
991
const DWARFDebugInfoEntry *
992
DWARFUnit::getFirstChildEntry(const DWARFDebugInfoEntry *Die) const {
993
if (!Die)
994
return nullptr;
995
assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size());
996
997
if (!Die->hasChildren())
998
return nullptr;
999
1000
// TODO: Instead of checking here for invalid die we might reject
1001
// invalid dies at parsing stage(DWARFUnit::extractDIEsToVector).
1002
// We do not want access out of bounds when parsing corrupted debug data.
1003
size_t I = getDIEIndex(Die) + 1;
1004
if (I >= DieArray.size())
1005
return nullptr;
1006
return &DieArray[I];
1007
}
1008
1009
DWARFDie DWARFUnit::getLastChild(const DWARFDebugInfoEntry *Die) {
1010
if (const DWARFDebugInfoEntry *Child = getLastChildEntry(Die))
1011
return DWARFDie(this, Child);
1012
1013
return DWARFDie();
1014
}
1015
1016
const DWARFDebugInfoEntry *
1017
DWARFUnit::getLastChildEntry(const DWARFDebugInfoEntry *Die) const {
1018
if (!Die)
1019
return nullptr;
1020
assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size());
1021
1022
if (!Die->hasChildren())
1023
return nullptr;
1024
1025
if (std::optional<uint32_t> SiblingIdx = Die->getSiblingIdx()) {
1026
assert(*SiblingIdx < DieArray.size() &&
1027
"SiblingIdx is out of DieArray boundaries");
1028
assert(DieArray[*SiblingIdx - 1].getTag() == dwarf::DW_TAG_null &&
1029
"Bad end of children marker");
1030
return &DieArray[*SiblingIdx - 1];
1031
}
1032
1033
// If SiblingIdx is set for non-root dies we could be sure that DWARF is
1034
// correct and "end of children marker" must be found. For root die we do not
1035
// have such a guarantee(parsing root die might be stopped if "end of children
1036
// marker" is missing, SiblingIdx is always zero for root die). That is why we
1037
// do not use assertion for checking for "end of children marker" for root
1038
// die.
1039
1040
// TODO: Instead of checking here for invalid die we might reject
1041
// invalid dies at parsing stage(DWARFUnit::extractDIEsToVector).
1042
if (getDIEIndex(Die) == 0 && DieArray.size() > 1 &&
1043
DieArray.back().getTag() == dwarf::DW_TAG_null) {
1044
// For the unit die we might take last item from DieArray.
1045
assert(getDIEIndex(Die) ==
1046
getDIEIndex(const_cast<DWARFUnit *>(this)->getUnitDIE()) &&
1047
"Bad unit die");
1048
return &DieArray.back();
1049
}
1050
1051
return nullptr;
1052
}
1053
1054
const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const {
1055
if (!Abbrevs) {
1056
Expected<const DWARFAbbreviationDeclarationSet *> AbbrevsOrError =
1057
Abbrev->getAbbreviationDeclarationSet(getAbbreviationsOffset());
1058
if (!AbbrevsOrError) {
1059
// FIXME: We should propagate this error upwards.
1060
consumeError(AbbrevsOrError.takeError());
1061
return nullptr;
1062
}
1063
Abbrevs = *AbbrevsOrError;
1064
}
1065
return Abbrevs;
1066
}
1067
1068
std::optional<object::SectionedAddress> DWARFUnit::getBaseAddress() {
1069
if (BaseAddr)
1070
return BaseAddr;
1071
1072
DWARFDie UnitDie = (SU ? SU : this)->getUnitDIE();
1073
std::optional<DWARFFormValue> PC =
1074
UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc});
1075
BaseAddr = toSectionedAddress(PC);
1076
return BaseAddr;
1077
}
1078
1079
Expected<StrOffsetsContributionDescriptor>
1080
StrOffsetsContributionDescriptor::validateContributionSize(
1081
DWARFDataExtractor &DA) {
1082
uint8_t EntrySize = getDwarfOffsetByteSize();
1083
// In order to ensure that we don't read a partial record at the end of
1084
// the section we validate for a multiple of the entry size.
1085
uint64_t ValidationSize = alignTo(Size, EntrySize);
1086
// Guard against overflow.
1087
if (ValidationSize >= Size)
1088
if (DA.isValidOffsetForDataOfSize((uint32_t)Base, ValidationSize))
1089
return *this;
1090
return createStringError(errc::invalid_argument, "length exceeds section size");
1091
}
1092
1093
// Look for a DWARF64-formatted contribution to the string offsets table
1094
// starting at a given offset and record it in a descriptor.
1095
static Expected<StrOffsetsContributionDescriptor>
1096
parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint64_t Offset) {
1097
if (!DA.isValidOffsetForDataOfSize(Offset, 16))
1098
return createStringError(errc::invalid_argument, "section offset exceeds section size");
1099
1100
if (DA.getU32(&Offset) != dwarf::DW_LENGTH_DWARF64)
1101
return createStringError(errc::invalid_argument, "32 bit contribution referenced from a 64 bit unit");
1102
1103
uint64_t Size = DA.getU64(&Offset);
1104
uint8_t Version = DA.getU16(&Offset);
1105
(void)DA.getU16(&Offset); // padding
1106
// The encoded length includes the 2-byte version field and the 2-byte
1107
// padding, so we need to subtract them out when we populate the descriptor.
1108
return StrOffsetsContributionDescriptor(Offset, Size - 4, Version, DWARF64);
1109
}
1110
1111
// Look for a DWARF32-formatted contribution to the string offsets table
1112
// starting at a given offset and record it in a descriptor.
1113
static Expected<StrOffsetsContributionDescriptor>
1114
parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint64_t Offset) {
1115
if (!DA.isValidOffsetForDataOfSize(Offset, 8))
1116
return createStringError(errc::invalid_argument, "section offset exceeds section size");
1117
1118
uint32_t ContributionSize = DA.getU32(&Offset);
1119
if (ContributionSize >= dwarf::DW_LENGTH_lo_reserved)
1120
return createStringError(errc::invalid_argument, "invalid length");
1121
1122
uint8_t Version = DA.getU16(&Offset);
1123
(void)DA.getU16(&Offset); // padding
1124
// The encoded length includes the 2-byte version field and the 2-byte
1125
// padding, so we need to subtract them out when we populate the descriptor.
1126
return StrOffsetsContributionDescriptor(Offset, ContributionSize - 4, Version,
1127
DWARF32);
1128
}
1129
1130
static Expected<StrOffsetsContributionDescriptor>
1131
parseDWARFStringOffsetsTableHeader(DWARFDataExtractor &DA,
1132
llvm::dwarf::DwarfFormat Format,
1133
uint64_t Offset) {
1134
StrOffsetsContributionDescriptor Desc;
1135
switch (Format) {
1136
case dwarf::DwarfFormat::DWARF64: {
1137
if (Offset < 16)
1138
return createStringError(errc::invalid_argument, "insufficient space for 64 bit header prefix");
1139
auto DescOrError = parseDWARF64StringOffsetsTableHeader(DA, Offset - 16);
1140
if (!DescOrError)
1141
return DescOrError.takeError();
1142
Desc = *DescOrError;
1143
break;
1144
}
1145
case dwarf::DwarfFormat::DWARF32: {
1146
if (Offset < 8)
1147
return createStringError(errc::invalid_argument, "insufficient space for 32 bit header prefix");
1148
auto DescOrError = parseDWARF32StringOffsetsTableHeader(DA, Offset - 8);
1149
if (!DescOrError)
1150
return DescOrError.takeError();
1151
Desc = *DescOrError;
1152
break;
1153
}
1154
}
1155
return Desc.validateContributionSize(DA);
1156
}
1157
1158
Expected<std::optional<StrOffsetsContributionDescriptor>>
1159
DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA) {
1160
assert(!IsDWO);
1161
auto OptOffset = toSectionOffset(getUnitDIE().find(DW_AT_str_offsets_base));
1162
if (!OptOffset)
1163
return std::nullopt;
1164
auto DescOrError =
1165
parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), *OptOffset);
1166
if (!DescOrError)
1167
return DescOrError.takeError();
1168
return *DescOrError;
1169
}
1170
1171
Expected<std::optional<StrOffsetsContributionDescriptor>>
1172
DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA) {
1173
assert(IsDWO);
1174
uint64_t Offset = 0;
1175
auto IndexEntry = Header.getIndexEntry();
1176
const auto *C =
1177
IndexEntry ? IndexEntry->getContribution(DW_SECT_STR_OFFSETS) : nullptr;
1178
if (C)
1179
Offset = C->getOffset();
1180
if (getVersion() >= 5) {
1181
if (DA.getData().data() == nullptr)
1182
return std::nullopt;
1183
Offset += Header.getFormat() == dwarf::DwarfFormat::DWARF32 ? 8 : 16;
1184
// Look for a valid contribution at the given offset.
1185
auto DescOrError = parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), Offset);
1186
if (!DescOrError)
1187
return DescOrError.takeError();
1188
return *DescOrError;
1189
}
1190
// Prior to DWARF v5, we derive the contribution size from the
1191
// index table (in a package file). In a .dwo file it is simply
1192
// the length of the string offsets section.
1193
StrOffsetsContributionDescriptor Desc;
1194
if (C)
1195
Desc = StrOffsetsContributionDescriptor(C->getOffset(), C->getLength(), 4,
1196
Header.getFormat());
1197
else if (!IndexEntry && !StringOffsetSection.Data.empty())
1198
Desc = StrOffsetsContributionDescriptor(0, StringOffsetSection.Data.size(),
1199
4, Header.getFormat());
1200
else
1201
return std::nullopt;
1202
auto DescOrError = Desc.validateContributionSize(DA);
1203
if (!DescOrError)
1204
return DescOrError.takeError();
1205
return *DescOrError;
1206
}
1207
1208
std::optional<uint64_t> DWARFUnit::getRnglistOffset(uint32_t Index) {
1209
DataExtractor RangesData(RangeSection->Data, IsLittleEndian,
1210
getAddressByteSize());
1211
DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection,
1212
IsLittleEndian, 0);
1213
if (std::optional<uint64_t> Off = llvm::DWARFListTableHeader::getOffsetEntry(
1214
RangesData, RangeSectionBase, getFormat(), Index))
1215
return *Off + RangeSectionBase;
1216
return std::nullopt;
1217
}
1218
1219
std::optional<uint64_t> DWARFUnit::getLoclistOffset(uint32_t Index) {
1220
if (std::optional<uint64_t> Off = llvm::DWARFListTableHeader::getOffsetEntry(
1221
LocTable->getData(), LocSectionBase, getFormat(), Index))
1222
return *Off + LocSectionBase;
1223
return std::nullopt;
1224
}
1225
1226