Bug Summary

File:build/source/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
Warning:line 816, column 20
The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage

Annotated Source Code

Press '?' to see keyboard shortcuts

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