Line data Source code
1 : //===- DWARFUnit.cpp ------------------------------------------------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 :
10 : #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
11 : #include "llvm/ADT/SmallString.h"
12 : #include "llvm/ADT/StringRef.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/DWARFDebugRnglists.h"
19 : #include "llvm/DebugInfo/DWARF/DWARFDie.h"
20 : #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
21 : #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
22 : #include "llvm/Support/DataExtractor.h"
23 : #include "llvm/Support/Errc.h"
24 : #include "llvm/Support/Path.h"
25 : #include "llvm/Support/WithColor.h"
26 : #include <algorithm>
27 : #include <cassert>
28 : #include <cstddef>
29 : #include <cstdint>
30 : #include <cstdio>
31 : #include <utility>
32 : #include <vector>
33 :
34 : using namespace llvm;
35 : using namespace dwarf;
36 :
37 1605 : void DWARFUnitVector::addUnitsForSection(DWARFContext &C,
38 : const DWARFSection &Section,
39 : DWARFSectionKind SectionKind) {
40 : const DWARFObject &D = C.getDWARFObj();
41 1605 : addUnitsImpl(C, D, Section, C.getDebugAbbrev(), &D.getRangeSection(),
42 1605 : D.getStringSection(), D.getStringOffsetSection(),
43 1605 : &D.getAddrSection(), D.getLineSection(), D.isLittleEndian(),
44 : false, false, SectionKind);
45 1605 : }
46 :
47 305 : void DWARFUnitVector::addUnitsForDWOSection(DWARFContext &C,
48 : const DWARFSection &DWOSection,
49 : DWARFSectionKind SectionKind,
50 : bool Lazy) {
51 : const DWARFObject &D = C.getDWARFObj();
52 610 : addUnitsImpl(C, D, DWOSection, C.getDebugAbbrevDWO(), &D.getRangeDWOSection(),
53 305 : D.getStringDWOSection(), D.getStringOffsetDWOSection(),
54 305 : &D.getAddrSection(), D.getLineDWOSection(), C.isLittleEndian(),
55 : true, Lazy, SectionKind);
56 305 : }
57 :
58 1910 : void DWARFUnitVector::addUnitsImpl(
59 : DWARFContext &Context, const DWARFObject &Obj, const DWARFSection &Section,
60 : const DWARFDebugAbbrev *DA, const DWARFSection *RS, StringRef SS,
61 : const DWARFSection &SOS, const DWARFSection *AOS, const DWARFSection &LS,
62 : bool LE, bool IsDWO, bool Lazy, DWARFSectionKind SectionKind) {
63 : DWARFDataExtractor Data(Obj, Section, LE, 0);
64 : // Lazy initialization of Parser, now that we have all section info.
65 1910 : if (!Parser) {
66 : Parser = [=, &Context, &Obj, &Section, &SOS, &LS](
67 : uint32_t Offset, DWARFSectionKind SectionKind,
68 : const DWARFSection *CurSection) -> std::unique_ptr<DWARFUnit> {
69 : const DWARFSection &InfoSection = CurSection ? *CurSection : Section;
70 : DWARFDataExtractor Data(Obj, InfoSection, LE, 0);
71 : if (!Data.isValidOffset(Offset))
72 : return nullptr;
73 : const DWARFUnitIndex *Index = nullptr;
74 : if (IsDWO)
75 : Index = &getDWARFUnitIndex(Context, SectionKind);
76 : DWARFUnitHeader Header;
77 : if (!Header.extract(Context, Data, &Offset, SectionKind, Index))
78 : return nullptr;
79 : std::unique_ptr<DWARFUnit> U;
80 : if (Header.isTypeUnit())
81 : U = llvm::make_unique<DWARFTypeUnit>(Context, InfoSection, Header, DA,
82 : RS, SS, SOS, AOS, LS, LE, IsDWO,
83 : *this);
84 : else
85 : U = llvm::make_unique<DWARFCompileUnit>(Context, InfoSection, Header,
86 : DA, RS, SS, SOS, AOS, LS, LE,
87 : IsDWO, *this);
88 : return U;
89 1669 : };
90 : }
91 1910 : if (Lazy)
92 : return;
93 : // Find a reasonable insertion point within the vector. We skip over
94 : // (a) units from a different section, (b) units from the same section
95 : // but with lower offset-within-section. This keeps units in order
96 : // within a section, although not necessarily within the object file,
97 : // even if we do lazy parsing.
98 : auto I = this->begin();
99 : uint32_t Offset = 0;
100 6842 : while (Data.isValidOffset(Offset)) {
101 4986 : if (I != this->end() &&
102 112 : (&(*I)->getInfoSection() != &Section || (*I)->getOffset() == Offset)) {
103 112 : ++I;
104 112 : continue;
105 : }
106 4874 : auto U = Parser(Offset, SectionKind, &Section);
107 : // If parsing failed, we're done with this section.
108 4874 : if (!U)
109 : break;
110 : Offset = U->getNextUnitOffset();
111 4840 : I = std::next(this->insert(I, std::move(U)));
112 : }
113 : }
114 :
115 93 : DWARFUnit *DWARFUnitVector::addUnit(std::unique_ptr<DWARFUnit> Unit) {
116 : auto I = std::upper_bound(begin(), end(), Unit,
117 : [](const std::unique_ptr<DWARFUnit> &LHS,
118 : const std::unique_ptr<DWARFUnit> &RHS) {
119 0 : return LHS->getOffset() < RHS->getOffset();
120 : });
121 93 : return this->insert(I, std::move(Unit))->get();
122 : }
123 :
124 6829 : DWARFUnit *DWARFUnitVector::getUnitForOffset(uint32_t Offset) const {
125 6829 : auto end = begin() + getNumInfoUnits();
126 : auto *CU =
127 : std::upper_bound(begin(), end, Offset,
128 : [](uint32_t LHS, const std::unique_ptr<DWARFUnit> &RHS) {
129 0 : return LHS < RHS->getNextUnitOffset();
130 : });
131 6829 : if (CU != end && (*CU)->getOffset() <= Offset)
132 : return CU->get();
133 : return nullptr;
134 : }
135 :
136 : DWARFUnit *
137 4 : DWARFUnitVector::getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) {
138 4 : const auto *CUOff = E.getOffset(DW_SECT_INFO);
139 4 : if (!CUOff)
140 : return nullptr;
141 :
142 4 : auto Offset = CUOff->Offset;
143 4 : auto end = begin() + getNumInfoUnits();
144 :
145 : auto *CU =
146 4 : std::upper_bound(begin(), end, CUOff->Offset,
147 : [](uint32_t LHS, const std::unique_ptr<DWARFUnit> &RHS) {
148 0 : return LHS < RHS->getNextUnitOffset();
149 : });
150 4 : if (CU != end && (*CU)->getOffset() <= Offset)
151 : return CU->get();
152 :
153 4 : if (!Parser)
154 : return nullptr;
155 :
156 4 : auto U = Parser(Offset, DW_SECT_INFO, nullptr);
157 4 : if (!U)
158 : U = nullptr;
159 :
160 : auto *NewCU = U.get();
161 4 : this->insert(CU, std::move(U));
162 4 : ++NumInfoUnits;
163 : return NewCU;
164 : }
165 :
166 4937 : DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
167 : const DWARFUnitHeader &Header,
168 : const DWARFDebugAbbrev *DA, const DWARFSection *RS,
169 : StringRef SS, const DWARFSection &SOS,
170 : const DWARFSection *AOS, const DWARFSection &LS, bool LE,
171 4937 : bool IsDWO, const DWARFUnitVector &UnitVector)
172 : : Context(DC), InfoSection(Section), Header(Header), Abbrev(DA),
173 : RangeSection(RS), LineSection(LS), StringSection(SS),
174 : StringOffsetSection(SOS), AddrOffsetSection(AOS), isLittleEndian(LE),
175 4953 : isDWO(IsDWO), UnitVector(UnitVector) {
176 4937 : clear();
177 4937 : }
178 :
179 : DWARFUnit::~DWARFUnit() = default;
180 :
181 76631 : DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const {
182 153262 : return DWARFDataExtractor(Context.getDWARFObj(), InfoSection, isLittleEndian,
183 153262 : getAddressByteSize());
184 : }
185 :
186 113 : bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index,
187 : uint64_t &Result) const {
188 113 : uint32_t Offset = AddrOffsetSectionBase + Index * getAddressByteSize();
189 226 : if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize())
190 : return false;
191 97 : DWARFDataExtractor DA(Context.getDWARFObj(), *AddrOffsetSection,
192 97 : isLittleEndian, getAddressByteSize());
193 97 : Result = DA.getRelocatedAddress(&Offset);
194 97 : return true;
195 : }
196 :
197 1295 : bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index,
198 : uint64_t &Result) const {
199 1295 : if (!StringOffsetsTableContribution)
200 : return false;
201 1294 : unsigned ItemSize = getDwarfStringOffsetsByteSize();
202 1294 : uint32_t Offset = getStringOffsetsBase() + Index * ItemSize;
203 2588 : if (StringOffsetSection.Data.size() < Offset + ItemSize)
204 : return false;
205 1294 : DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection,
206 1294 : isLittleEndian, 0);
207 1294 : Result = DA.getRelocatedValue(ItemSize, &Offset);
208 1294 : return true;
209 : }
210 :
211 4971 : bool DWARFUnitHeader::extract(DWARFContext &Context,
212 : const DWARFDataExtractor &debug_info,
213 : uint32_t *offset_ptr,
214 : DWARFSectionKind SectionKind,
215 : const DWARFUnitIndex *Index) {
216 4971 : Offset = *offset_ptr;
217 4971 : IndexEntry = Index ? Index->getFromOffset(*offset_ptr) : nullptr;
218 4971 : Length = debug_info.getU32(offset_ptr);
219 : // FIXME: Support DWARF64.
220 : unsigned SizeOfLength = 4;
221 4971 : FormParams.Format = DWARF32;
222 4971 : FormParams.Version = debug_info.getU16(offset_ptr);
223 4971 : if (FormParams.Version >= 5) {
224 110 : UnitType = debug_info.getU8(offset_ptr);
225 110 : FormParams.AddrSize = debug_info.getU8(offset_ptr);
226 110 : AbbrOffset = debug_info.getU32(offset_ptr);
227 : } else {
228 4861 : AbbrOffset = debug_info.getRelocatedValue(4, offset_ptr);
229 4861 : FormParams.AddrSize = debug_info.getU8(offset_ptr);
230 : // Fake a unit type based on the section type. This isn't perfect,
231 : // but distinguishing compile and type units is generally enough.
232 4861 : if (SectionKind == DW_SECT_TYPES)
233 50 : UnitType = DW_UT_type;
234 : else
235 4811 : UnitType = DW_UT_compile;
236 : }
237 4971 : if (IndexEntry) {
238 41 : if (AbbrOffset)
239 : return false;
240 41 : auto *UnitContrib = IndexEntry->getOffset();
241 41 : if (!UnitContrib || UnitContrib->Length != (Length + 4))
242 : return false;
243 41 : auto *AbbrEntry = IndexEntry->getOffset(DW_SECT_ABBREV);
244 41 : if (!AbbrEntry)
245 : return false;
246 41 : AbbrOffset = AbbrEntry->Offset;
247 : }
248 9942 : if (isTypeUnit()) {
249 64 : TypeHash = debug_info.getU64(offset_ptr);
250 64 : TypeOffset = debug_info.getU32(offset_ptr);
251 4907 : } else if (UnitType == DW_UT_split_compile || UnitType == DW_UT_skeleton)
252 16 : DWOId = debug_info.getU64(offset_ptr);
253 :
254 : // Header fields all parsed, capture the size of this unit header.
255 : assert(*offset_ptr - Offset <= 255 && "unexpected header size");
256 4971 : Size = uint8_t(*offset_ptr - Offset);
257 :
258 : // Type offset is unit-relative; should be after the header and before
259 : // the end of the current unit.
260 : bool TypeOffsetOK =
261 4971 : !isTypeUnit()
262 4971 : ? true
263 64 : : TypeOffset >= Size && TypeOffset < getLength() + SizeOfLength;
264 9942 : bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
265 4971 : bool VersionOK = DWARFContext::isSupportedVersion(getVersion());
266 4971 : bool AddrSizeOK = getAddressByteSize() == 4 || getAddressByteSize() == 8;
267 :
268 4971 : if (!LengthOK || !VersionOK || !AddrSizeOK || !TypeOffsetOK)
269 : return false;
270 :
271 : // Keep track of the highest DWARF version we encounter across all units.
272 : Context.setMaxVersionIfGreater(getVersion());
273 : return true;
274 : }
275 :
276 : // Parse the rangelist table header, including the optional array of offsets
277 : // following it (DWARF v5 and later).
278 : static Expected<DWARFDebugRnglistTable>
279 12 : parseRngListTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {
280 : // TODO: Support DWARF64
281 : // We are expected to be called with Offset 0 or pointing just past the table
282 : // header, which is 12 bytes long for DWARF32.
283 12 : if (Offset > 0) {
284 11 : if (Offset < 12U)
285 2 : return createStringError(errc::invalid_argument, "Did not detect a valid"
286 : " range list table with base = 0x%" PRIu32,
287 : Offset);
288 9 : Offset -= 12U;
289 : }
290 : llvm::DWARFDebugRnglistTable Table;
291 10 : if (Error E = Table.extractHeaderAndOffsets(DA, &Offset))
292 : return std::move(E);
293 : return Table;
294 : }
295 :
296 1164 : Error DWARFUnit::extractRangeList(uint32_t RangeListOffset,
297 : DWARFDebugRangeList &RangeList) const {
298 : // Require that compile unit is extracted.
299 : assert(!DieArray.empty());
300 1164 : DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection,
301 1164 : isLittleEndian, getAddressByteSize());
302 1164 : uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
303 1164 : return RangeList.extract(RangesData, &ActualRangeListOffset);
304 : }
305 :
306 4937 : void DWARFUnit::clear() {
307 4937 : Abbrevs = nullptr;
308 : BaseAddr.reset();
309 4937 : RangeSectionBase = 0;
310 4937 : AddrOffsetSectionBase = 0;
311 4937 : clearDIEs(false);
312 : DWO.reset();
313 4937 : }
314 :
315 3585 : const char *DWARFUnit::getCompilationDir() {
316 3585 : return dwarf::toString(getUnitDIE().find(DW_AT_comp_dir), nullptr);
317 : }
318 :
319 4756 : void DWARFUnit::extractDIEsToVector(
320 : bool AppendCUDie, bool AppendNonCUDies,
321 : std::vector<DWARFDebugInfoEntry> &Dies) const {
322 4756 : if (!AppendCUDie && !AppendNonCUDies)
323 0 : return;
324 :
325 : // Set the offset to that of the first DIE and calculate the start of the
326 : // next compilation unit header.
327 4756 : uint32_t DIEOffset = getOffset() + getHeaderSize();
328 : uint32_t NextCUOffset = getNextUnitOffset();
329 4756 : DWARFDebugInfoEntry DIE;
330 4756 : DWARFDataExtractor DebugInfoData = getDebugInfoExtractor();
331 : uint32_t Depth = 0;
332 : bool IsCUDie = true;
333 :
334 39707 : while (DIE.extractFast(*this, &DIEOffset, DebugInfoData, NextCUOffset,
335 : Depth)) {
336 39003 : if (IsCUDie) {
337 4745 : if (AppendCUDie)
338 3956 : Dies.push_back(DIE);
339 4745 : if (!AppendNonCUDies)
340 : break;
341 : // The average bytes per DIE entry has been seen to be
342 : // around 14-20 so let's pre-reserve the needed memory for
343 : // our DIE entries accordingly.
344 4514 : Dies.reserve(Dies.size() + getDebugInfoSize() / 14);
345 : IsCUDie = false;
346 : } else {
347 34258 : Dies.push_back(DIE);
348 : }
349 :
350 36515 : if (const DWARFAbbreviationDeclaration *AbbrDecl =
351 36515 : DIE.getAbbreviationDeclarationPtr()) {
352 : // Normal DIE
353 29276 : if (AbbrDecl->hasChildren())
354 7216 : ++Depth;
355 : } else {
356 : // NULL DIE.
357 7239 : if (Depth > 0)
358 7211 : --Depth;
359 7239 : if (Depth == 0)
360 : break; // We are done with this compile unit!
361 : }
362 : }
363 :
364 : // Give a little bit of info if we encounter corrupt DWARF (our offset
365 : // should always terminate at or before the start of the next compilation
366 : // unit header).
367 4756 : if (DIEOffset > NextCUOffset)
368 6 : WithColor::warning() << format("DWARF compile unit extends beyond its "
369 : "bounds cu 0x%8.8x at 0x%8.8x\n",
370 6 : getOffset(), DIEOffset);
371 : }
372 :
373 31568 : size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
374 31568 : if ((CUDieOnly && !DieArray.empty()) ||
375 15400 : DieArray.size() > 1)
376 : return 0; // Already parsed.
377 :
378 : bool HasCUDie = !DieArray.empty();
379 4756 : extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
380 :
381 4756 : if (DieArray.empty())
382 : return 0;
383 :
384 : // If CU DIE was just parsed, copy several attribute values from it.
385 4745 : if (!HasCUDie) {
386 3956 : DWARFDie UnitDie = getUnitDIE();
387 7912 : if (Optional<uint64_t> DWOId = toUnsigned(UnitDie.find(DW_AT_GNU_dwo_id)))
388 183 : Header.setDWOId(*DWOId);
389 3956 : if (!isDWO) {
390 : assert(AddrOffsetSectionBase == 0);
391 : assert(RangeSectionBase == 0);
392 3843 : AddrOffsetSectionBase =
393 3843 : toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base), 0);
394 7686 : RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0);
395 : }
396 :
397 : // In general, in DWARF v5 and beyond we derive the start of the unit's
398 : // contribution to the string offsets table from the unit DIE's
399 : // DW_AT_str_offsets_base attribute. Split DWARF units do not use this
400 : // attribute, so we assume that there is a contribution to the string
401 : // offsets table starting at offset 0 of the debug_str_offsets.dwo section.
402 : // In both cases we need to determine the format of the contribution,
403 : // which may differ from the unit's format.
404 : uint64_t StringOffsetsContributionBase =
405 3956 : isDWO ? 0 : toSectionOffset(UnitDie.find(DW_AT_str_offsets_base), 0);
406 3956 : auto IndexEntry = Header.getIndexEntry();
407 3956 : if (IndexEntry)
408 41 : if (const auto *C = IndexEntry->getOffset(DW_SECT_STR_OFFSETS))
409 38 : StringOffsetsContributionBase += C->Offset;
410 :
411 3956 : DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection,
412 3956 : isLittleEndian, 0);
413 3956 : if (isDWO)
414 : StringOffsetsTableContribution =
415 226 : determineStringOffsetsTableContributionDWO(
416 : DA, StringOffsetsContributionBase);
417 3843 : else if (getVersion() >= 5)
418 162 : StringOffsetsTableContribution = determineStringOffsetsTableContribution(
419 : DA, StringOffsetsContributionBase);
420 :
421 : // DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to
422 : // describe address ranges.
423 3956 : if (getVersion() >= 5) {
424 102 : if (isDWO)
425 42 : setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0);
426 : else
427 162 : setRangesSection(&Context.getDWARFObj().getRnglistsSection(),
428 162 : toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0));
429 204 : if (RangeSection->Data.size()) {
430 : // Parse the range list table header. Individual range lists are
431 : // extracted lazily.
432 12 : DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection,
433 12 : isLittleEndian, 0);
434 12 : if (auto TableOrError =
435 24 : parseRngListTableHeader(RangesDA, RangeSectionBase))
436 : RngListTable = TableOrError.get();
437 : else
438 2 : WithColor::error() << "parsing a range list table: "
439 4 : << toString(TableOrError.takeError())
440 : << '\n';
441 :
442 : // In a split dwarf unit, there is no DW_AT_rnglists_base attribute.
443 : // Adjust RangeSectionBase to point past the table header.
444 12 : if (isDWO && RngListTable)
445 1 : RangeSectionBase = RngListTable->getHeaderSize();
446 : }
447 : }
448 :
449 : // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
450 : // skeleton CU DIE, so that DWARF users not aware of it are not broken.
451 : }
452 :
453 9490 : return DieArray.size();
454 : }
455 :
456 1274 : bool DWARFUnit::parseDWO() {
457 1274 : if (isDWO)
458 : return false;
459 1269 : if (DWO.get())
460 : return false;
461 1266 : DWARFDie UnitDie = getUnitDIE();
462 : if (!UnitDie)
463 : return false;
464 1266 : auto DWOFileName = dwarf::toString(UnitDie.find(DW_AT_GNU_dwo_name));
465 1266 : if (!DWOFileName)
466 : return false;
467 64 : auto CompilationDir = dwarf::toString(UnitDie.find(DW_AT_comp_dir));
468 : SmallString<16> AbsolutePath;
469 96 : if (sys::path::is_relative(*DWOFileName) && CompilationDir &&
470 32 : *CompilationDir) {
471 32 : sys::path::append(AbsolutePath, *CompilationDir);
472 : }
473 64 : sys::path::append(AbsolutePath, *DWOFileName);
474 : auto DWOId = getDWOId();
475 32 : if (!DWOId)
476 : return false;
477 64 : auto DWOContext = Context.getDWOContext(AbsolutePath);
478 32 : if (!DWOContext)
479 : return false;
480 :
481 19 : DWARFCompileUnit *DWOCU = DWOContext->getDWOCompileUnitForHash(*DWOId);
482 19 : if (!DWOCU)
483 : return false;
484 : DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU);
485 : // Share .debug_addr and .debug_ranges section with compile unit in .dwo
486 19 : DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);
487 19 : if (getVersion() >= 5) {
488 0 : DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0);
489 0 : DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection,
490 0 : isLittleEndian, 0);
491 0 : if (auto TableOrError = parseRngListTableHeader(RangesDA, RangeSectionBase))
492 : DWO->RngListTable = TableOrError.get();
493 : else
494 0 : WithColor::error() << "parsing a range list table: "
495 0 : << toString(TableOrError.takeError())
496 : << '\n';
497 0 : if (DWO->RngListTable)
498 0 : DWO->RangeSectionBase = DWO->RngListTable->getHeaderSize();
499 : } else {
500 19 : auto DWORangesBase = UnitDie.getRangesBaseAttribute();
501 19 : DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0);
502 : }
503 :
504 : return true;
505 : }
506 :
507 4958 : void DWARFUnit::clearDIEs(bool KeepCUDie) {
508 9916 : if (DieArray.size() > (unsigned)KeepCUDie) {
509 21 : DieArray.resize((unsigned)KeepCUDie);
510 : DieArray.shrink_to_fit();
511 : }
512 4958 : }
513 :
514 : Expected<DWARFAddressRangesVector>
515 1176 : DWARFUnit::findRnglistFromOffset(uint32_t Offset) {
516 1176 : if (getVersion() <= 4) {
517 : DWARFDebugRangeList RangeList;
518 2328 : if (Error E = extractRangeList(Offset, RangeList))
519 : return std::move(E);
520 1160 : return RangeList.getAbsoluteRanges(getBaseAddress());
521 : }
522 12 : if (RngListTable) {
523 11 : DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection,
524 11 : isLittleEndian, RngListTable->getAddrSize());
525 22 : auto RangeListOrError = RngListTable->findList(RangesData, Offset);
526 11 : if (RangeListOrError)
527 9 : return RangeListOrError.get().getAbsoluteRanges(getBaseAddress());
528 : return RangeListOrError.takeError();
529 : }
530 :
531 1 : return createStringError(errc::invalid_argument,
532 : "missing or invalid range list table");
533 : }
534 :
535 : Expected<DWARFAddressRangesVector>
536 5 : DWARFUnit::findRnglistFromIndex(uint32_t Index) {
537 8 : if (auto Offset = getRnglistOffset(Index))
538 3 : return findRnglistFromOffset(*Offset + RangeSectionBase);
539 :
540 2 : if (RngListTable)
541 0 : return createStringError(errc::invalid_argument,
542 : "invalid range list table index %d", Index);
543 : else
544 2 : return createStringError(errc::invalid_argument,
545 : "missing or invalid range list table");
546 : }
547 :
548 2333 : void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) {
549 2333 : DWARFDie UnitDie = getUnitDIE();
550 : if (!UnitDie)
551 1791 : return;
552 : // First, check if unit DIE describes address ranges for the whole unit.
553 2875 : auto CUDIERangesOrError = UnitDie.getAddressRanges();
554 2333 : if (CUDIERangesOrError) {
555 2331 : if (!CUDIERangesOrError.get().empty()) {
556 : CURanges.insert(CURanges.end(), CUDIERangesOrError.get().begin(),
557 1791 : CUDIERangesOrError.get().end());
558 1791 : return;
559 : }
560 : } else
561 2 : WithColor::error() << "decoding address ranges: "
562 4 : << toString(CUDIERangesOrError.takeError()) << '\n';
563 :
564 : // This function is usually called if there in no .debug_aranges section
565 : // in order to produce a compile unit level set of address ranges that
566 : // is accurate. If the DIEs weren't parsed, then we don't want all dies for
567 : // all compile units to stay loaded when they weren't needed. So we can end
568 : // up parsing the DWARF and then throwing them all away to keep memory usage
569 : // down.
570 542 : const bool ClearDIEs = extractDIEsIfNeeded(false) > 1;
571 542 : getUnitDIE().collectChildrenAddressRanges(CURanges);
572 :
573 : // Collect address ranges from DIEs in .dwo if necessary.
574 542 : bool DWOCreated = parseDWO();
575 542 : if (DWO)
576 5 : DWO->collectAddressRanges(CURanges);
577 542 : if (DWOCreated)
578 : DWO.reset();
579 :
580 : // Keep memory down by clearing DIEs if this generate function
581 : // caused them to be parsed.
582 542 : if (ClearDIEs)
583 21 : clearDIEs(true);
584 : }
585 :
586 22006 : void DWARFUnit::updateAddressDieMap(DWARFDie Die) {
587 22006 : if (Die.isSubroutineDIE()) {
588 7226 : auto DIERangesOrError = Die.getAddressRanges();
589 3613 : if (DIERangesOrError) {
590 3938 : for (const auto &R : DIERangesOrError.get()) {
591 : // Ignore 0-sized ranges.
592 325 : if (R.LowPC == R.HighPC)
593 : continue;
594 : auto B = AddrDieMap.upper_bound(R.LowPC);
595 325 : if (B != AddrDieMap.begin() && R.LowPC < (--B)->second.first) {
596 : // The range is a sub-range of existing ranges, we need to split the
597 : // existing range.
598 59 : if (R.HighPC < B->second.first)
599 56 : AddrDieMap[R.HighPC] = B->second;
600 59 : if (R.LowPC > B->first)
601 30 : AddrDieMap[B->first].first = R.LowPC;
602 : }
603 325 : AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die);
604 : }
605 : } else
606 0 : llvm::consumeError(DIERangesOrError.takeError());
607 : }
608 : // Parent DIEs are added to the AddrDieMap prior to the Children DIEs to
609 : // simplify the logic to update AddrDieMap. The child's range will always
610 : // be equal or smaller than the parent's range. With this assumption, when
611 : // adding one range into the map, it will at most split a range into 3
612 : // sub-ranges.
613 22006 : for (DWARFDie Child = Die.getFirstChild(); Child; Child = Child.getSibling())
614 21837 : updateAddressDieMap(Child);
615 22006 : }
616 :
617 735 : DWARFDie DWARFUnit::getSubroutineForAddress(uint64_t Address) {
618 735 : extractDIEsIfNeeded(false);
619 735 : if (AddrDieMap.empty())
620 169 : updateAddressDieMap(getUnitDIE());
621 : auto R = AddrDieMap.upper_bound(Address);
622 735 : if (R == AddrDieMap.begin())
623 35 : return DWARFDie();
624 : // upper_bound's previous item contains Address.
625 : --R;
626 700 : if (Address >= R->second.first)
627 5 : return DWARFDie();
628 695 : return R->second.second;
629 : }
630 :
631 : void
632 732 : DWARFUnit::getInlinedChainForAddress(uint64_t Address,
633 : SmallVectorImpl<DWARFDie> &InlinedChain) {
634 : assert(InlinedChain.empty());
635 : // Try to look for subprogram DIEs in the DWO file.
636 732 : parseDWO();
637 : // First, find the subroutine that contains the given address (the leaf
638 : // of inlined chain).
639 : DWARFDie SubroutineDIE =
640 749 : (DWO ? DWO.get() : this)->getSubroutineForAddress(Address);
641 :
642 : if (!SubroutineDIE)
643 40 : return;
644 :
645 753 : while (!SubroutineDIE.isSubprogramDIE()) {
646 61 : if (SubroutineDIE.getTag() == DW_TAG_inlined_subroutine)
647 55 : InlinedChain.push_back(SubroutineDIE);
648 61 : SubroutineDIE = SubroutineDIE.getParent();
649 : }
650 692 : InlinedChain.push_back(SubroutineDIE);
651 : }
652 :
653 116 : const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context,
654 : DWARFSectionKind Kind) {
655 116 : if (Kind == DW_SECT_INFO)
656 89 : return Context.getCUIndex();
657 : assert(Kind == DW_SECT_TYPES);
658 27 : return Context.getTUIndex();
659 : }
660 :
661 88 : DWARFDie DWARFUnit::getParent(const DWARFDebugInfoEntry *Die) {
662 88 : if (!Die)
663 0 : return DWARFDie();
664 88 : const uint32_t Depth = Die->getDepth();
665 : // Unit DIEs always have a depth of zero and never have parents.
666 88 : if (Depth == 0)
667 6 : return DWARFDie();
668 : // Depth of 1 always means parent is the compile/type unit.
669 82 : if (Depth == 1)
670 : return getUnitDIE();
671 : // Look for previous DIE with a depth that is one less than the Die's depth.
672 76 : const uint32_t ParentDepth = Depth - 1;
673 104 : for (uint32_t I = getDIEIndex(Die) - 1; I > 0; --I) {
674 208 : if (DieArray[I].getDepth() == ParentDepth)
675 76 : return DWARFDie(this, &DieArray[I]);
676 : }
677 0 : return DWARFDie();
678 : }
679 :
680 33486 : DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) {
681 33486 : if (!Die)
682 0 : return DWARFDie();
683 33486 : uint32_t Depth = Die->getDepth();
684 : // Unit DIEs always have a depth of zero and never have siblings.
685 33486 : if (Depth == 0)
686 1 : return DWARFDie();
687 : // NULL DIEs don't have siblings.
688 33485 : if (Die->getAbbreviationDeclarationPtr() == nullptr)
689 5852 : return DWARFDie();
690 :
691 : // Find the next DIE whose depth is the same as the Die's depth.
692 50939 : for (size_t I = getDIEIndex(Die) + 1, EndIdx = DieArray.size(); I < EndIdx;
693 : ++I) {
694 50938 : if (DieArray[I].getDepth() == Depth)
695 27632 : return DWARFDie(this, &DieArray[I]);
696 : }
697 1 : return DWARFDie();
698 : }
699 :
700 3131 : DWARFDie DWARFUnit::getPreviousSibling(const DWARFDebugInfoEntry *Die) {
701 3131 : if (!Die)
702 0 : return DWARFDie();
703 3131 : uint32_t Depth = Die->getDepth();
704 : // Unit DIEs always have a depth of zero and never have siblings.
705 3131 : if (Depth == 0)
706 0 : return DWARFDie();
707 :
708 : // Find the previous DIE whose depth is the same as the Die's depth.
709 4071 : for (size_t I = getDIEIndex(Die); I > 0;) {
710 4071 : --I;
711 4071 : if (DieArray[I].getDepth() == Depth - 1)
712 987 : return DWARFDie();
713 3084 : if (DieArray[I].getDepth() == Depth)
714 2144 : return DWARFDie(this, &DieArray[I]);
715 : }
716 0 : return DWARFDie();
717 : }
718 :
719 32938 : DWARFDie DWARFUnit::getFirstChild(const DWARFDebugInfoEntry *Die) {
720 32938 : if (!Die->hasChildren())
721 24731 : return DWARFDie();
722 :
723 : // We do not want access out of bounds when parsing corrupted debug data.
724 8207 : size_t I = getDIEIndex(Die) + 1;
725 16414 : if (I >= DieArray.size())
726 1 : return DWARFDie();
727 8206 : return DWARFDie(this, &DieArray[I]);
728 : }
729 :
730 4657 : DWARFDie DWARFUnit::getLastChild(const DWARFDebugInfoEntry *Die) {
731 4657 : if (!Die->hasChildren())
732 2419 : return DWARFDie();
733 :
734 2238 : uint32_t Depth = Die->getDepth();
735 13968 : for (size_t I = getDIEIndex(Die) + 1, EndIdx = DieArray.size(); I < EndIdx;
736 : ++I) {
737 21453 : if (DieArray[I].getDepth() == Depth + 1 &&
738 9723 : DieArray[I].getTag() == dwarf::DW_TAG_null)
739 2233 : return DWARFDie(this, &DieArray[I]);
740 : assert(DieArray[I].getDepth() > Depth && "Not processing children?");
741 : }
742 5 : return DWARFDie();
743 : }
744 :
745 32494 : const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const {
746 32494 : if (!Abbrevs)
747 3955 : Abbrevs = Abbrev->getAbbreviationDeclarationSet(Header.getAbbrOffset());
748 32494 : return Abbrevs;
749 : }
750 :
751 1335 : llvm::Optional<BaseAddress> DWARFUnit::getBaseAddress() {
752 1335 : if (BaseAddr)
753 : return BaseAddr;
754 :
755 1238 : DWARFDie UnitDie = getUnitDIE();
756 1238 : Optional<DWARFFormValue> PC = UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc});
757 1238 : if (Optional<uint64_t> Addr = toAddress(PC))
758 1226 : BaseAddr = {*Addr, PC->getSectionIndex()};
759 :
760 : return BaseAddr;
761 : }
762 :
763 : Optional<StrOffsetsContributionDescriptor>
764 71 : StrOffsetsContributionDescriptor::validateContributionSize(
765 : DWARFDataExtractor &DA) {
766 : uint8_t EntrySize = getDwarfOffsetByteSize();
767 : // In order to ensure that we don't read a partial record at the end of
768 : // the section we validate for a multiple of the entry size.
769 71 : uint64_t ValidationSize = alignTo(Size, EntrySize);
770 : // Guard against overflow.
771 71 : if (ValidationSize >= Size)
772 71 : if (DA.isValidOffsetForDataOfSize((uint32_t)Base, ValidationSize))
773 : return *this;
774 : return Optional<StrOffsetsContributionDescriptor>();
775 : }
776 :
777 : // Look for a DWARF64-formatted contribution to the string offsets table
778 : // starting at a given offset and record it in a descriptor.
779 : static Optional<StrOffsetsContributionDescriptor>
780 27 : parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {
781 27 : if (!DA.isValidOffsetForDataOfSize(Offset, 16))
782 : return Optional<StrOffsetsContributionDescriptor>();
783 :
784 23 : if (DA.getU32(&Offset) != 0xffffffff)
785 : return Optional<StrOffsetsContributionDescriptor>();
786 :
787 2 : uint64_t Size = DA.getU64(&Offset);
788 2 : uint8_t Version = DA.getU16(&Offset);
789 2 : (void)DA.getU16(&Offset); // padding
790 : // The encoded length includes the 2-byte version field and the 2-byte
791 : // padding, so we need to subtract them out when we populate the descriptor.
792 2 : return StrOffsetsContributionDescriptor(Offset, Size - 4, Version, DWARF64);
793 : //return Optional<StrOffsetsContributionDescriptor>(Descriptor);
794 : }
795 :
796 : // Look for a DWARF32-formatted contribution to the string offsets table
797 : // starting at a given offset and record it in a descriptor.
798 : static Optional<StrOffsetsContributionDescriptor>
799 74 : parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {
800 74 : if (!DA.isValidOffsetForDataOfSize(Offset, 8))
801 : return Optional<StrOffsetsContributionDescriptor>();
802 70 : uint32_t ContributionSize = DA.getU32(&Offset);
803 70 : if (ContributionSize >= 0xfffffff0)
804 : return Optional<StrOffsetsContributionDescriptor>();
805 69 : uint8_t Version = DA.getU16(&Offset);
806 69 : (void)DA.getU16(&Offset); // padding
807 : // The encoded length includes the 2-byte version field and the 2-byte
808 : // padding, so we need to subtract them out when we populate the descriptor.
809 69 : return StrOffsetsContributionDescriptor(Offset, ContributionSize - 4, Version,
810 : DWARF32);
811 : //return Optional<StrOffsetsContributionDescriptor>(Descriptor);
812 : }
813 :
814 : Optional<StrOffsetsContributionDescriptor>
815 81 : DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA,
816 : uint64_t Offset) {
817 : Optional<StrOffsetsContributionDescriptor> Descriptor;
818 : // Attempt to find a DWARF64 contribution 16 bytes before the base.
819 81 : if (Offset >= 16)
820 : Descriptor =
821 12 : parseDWARF64StringOffsetsTableHeader(DA, (uint32_t)Offset - 16);
822 : // Try to find a DWARF32 contribution 8 bytes before the base.
823 81 : if (!Descriptor && Offset >= 8)
824 106 : Descriptor = parseDWARF32StringOffsetsTableHeader(DA, (uint32_t)Offset - 8);
825 81 : return Descriptor ? Descriptor->validateContributionSize(DA) : Descriptor;
826 : }
827 :
828 : Optional<StrOffsetsContributionDescriptor>
829 113 : DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA,
830 : uint64_t Offset) {
831 113 : if (getVersion() >= 5) {
832 : // Look for a valid contribution at the given offset.
833 : auto Descriptor =
834 21 : parseDWARF64StringOffsetsTableHeader(DA, (uint32_t)Offset);
835 21 : if (!Descriptor)
836 42 : Descriptor = parseDWARF32StringOffsetsTableHeader(DA, (uint32_t)Offset);
837 21 : return Descriptor ? Descriptor->validateContributionSize(DA) : Descriptor;
838 : }
839 : // Prior to DWARF v5, we derive the contribution size from the
840 : // index table (in a package file). In a .dwo file it is simply
841 : // the length of the string offsets section.
842 : uint64_t Size = 0;
843 92 : auto IndexEntry = Header.getIndexEntry();
844 92 : if (!IndexEntry)
845 55 : Size = StringOffsetSection.Data.size();
846 37 : else if (const auto *C = IndexEntry->getOffset(DW_SECT_STR_OFFSETS))
847 34 : Size = C->Length;
848 : // Return a descriptor with the given offset as base, version 4 and
849 : // DWARF32 format.
850 : //return Optional<StrOffsetsContributionDescriptor>(
851 : //StrOffsetsContributionDescriptor(Offset, Size, 4, DWARF32));
852 : return StrOffsetsContributionDescriptor(Offset, Size, 4, DWARF32);
853 : }
|