/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
Line | Count | Source (jump to first uncovered line) |
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/DWARFContext.h" |
15 | | #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" |
16 | | #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" |
17 | | #include "llvm/DebugInfo/DWARF/DWARFDie.h" |
18 | | #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" |
19 | | #include "llvm/Support/DataExtractor.h" |
20 | | #include "llvm/Support/Path.h" |
21 | | #include <algorithm> |
22 | | #include <cassert> |
23 | | #include <cstddef> |
24 | | #include <cstdint> |
25 | | #include <cstdio> |
26 | | #include <utility> |
27 | | #include <vector> |
28 | | |
29 | | using namespace llvm; |
30 | | using namespace dwarf; |
31 | | |
32 | 2.20k | void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) { |
33 | 2.20k | const DWARFObject &D = C.getDWARFObj(); |
34 | 2.20k | parseImpl(C, Section, C.getDebugAbbrev(), &D.getRangeSection(), |
35 | 2.20k | D.getStringSection(), D.getStringOffsetSection(), |
36 | 2.20k | &D.getAddrSection(), D.getLineSection(), D.isLittleEndian(), false, |
37 | 2.20k | false); |
38 | 2.20k | } |
39 | | |
40 | | void DWARFUnitSectionBase::parseDWO(DWARFContext &C, |
41 | 566 | const DWARFSection &DWOSection, bool Lazy) { |
42 | 566 | const DWARFObject &D = C.getDWARFObj(); |
43 | 566 | parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), &D.getRangeDWOSection(), |
44 | 566 | D.getStringDWOSection(), D.getStringOffsetDWOSection(), |
45 | 566 | &D.getAddrSection(), D.getLineDWOSection(), C.isLittleEndian(), |
46 | 566 | true, Lazy); |
47 | 566 | } |
48 | | |
49 | | DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, |
50 | | const DWARFDebugAbbrev *DA, const DWARFSection *RS, |
51 | | StringRef SS, const DWARFSection &SOS, |
52 | | const DWARFSection *AOS, const DWARFSection &LS, bool LE, |
53 | | bool IsDWO, const DWARFUnitSectionBase &UnitSection, |
54 | | const DWARFUnitIndex::Entry *IndexEntry) |
55 | | : Context(DC), InfoSection(Section), Abbrev(DA), RangeSection(RS), |
56 | | LineSection(LS), StringSection(SS), StringOffsetSection(SOS), |
57 | | AddrOffsetSection(AOS), isLittleEndian(LE), isDWO(IsDWO), |
58 | 1.18k | UnitSection(UnitSection), IndexEntry(IndexEntry) { |
59 | 1.18k | clear(); |
60 | 1.18k | } |
61 | | |
62 | 1.21k | DWARFUnit::~DWARFUnit() = default; |
63 | | |
64 | 45.8k | DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const { |
65 | 45.8k | return DWARFDataExtractor(Context.getDWARFObj(), InfoSection, isLittleEndian, |
66 | 45.8k | getAddressByteSize()); |
67 | 45.8k | } |
68 | | |
69 | | bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index, |
70 | 88 | uint64_t &Result) const { |
71 | 88 | uint32_t Offset = AddrOffsetSectionBase + Index * getAddressByteSize(); |
72 | 88 | if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize()) |
73 | 11 | return false; |
74 | 77 | DWARFDataExtractor DA(Context.getDWARFObj(), *AddrOffsetSection, |
75 | 77 | isLittleEndian, getAddressByteSize()); |
76 | 77 | Result = DA.getRelocatedAddress(&Offset); |
77 | 77 | return true; |
78 | 77 | } |
79 | | |
80 | | bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index, |
81 | 500 | uint64_t &Result) const { |
82 | 500 | unsigned ItemSize = getDwarfOffsetByteSize(); |
83 | 500 | uint32_t Offset = StringOffsetSectionBase + Index * ItemSize; |
84 | 500 | if (StringOffsetSection.Data.size() < Offset + ItemSize) |
85 | 1 | return false; |
86 | 499 | DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, |
87 | 499 | isLittleEndian, 0); |
88 | 499 | Result = DA.getRelocatedValue(ItemSize, &Offset); |
89 | 499 | return true; |
90 | 499 | } |
91 | | |
92 | 1.18k | bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) { |
93 | 1.18k | Length = debug_info.getU32(offset_ptr); |
94 | 1.18k | // FIXME: Support DWARF64. |
95 | 1.18k | FormParams.Format = DWARF32; |
96 | 1.18k | FormParams.Version = debug_info.getU16(offset_ptr); |
97 | 1.18k | if (FormParams.Version >= 51.18k ) { |
98 | 42 | UnitType = debug_info.getU8(offset_ptr); |
99 | 42 | FormParams.AddrSize = debug_info.getU8(offset_ptr); |
100 | 42 | AbbrOffset = debug_info.getU32(offset_ptr); |
101 | 1.18k | } else { |
102 | 1.14k | AbbrOffset = debug_info.getU32(offset_ptr); |
103 | 1.14k | FormParams.AddrSize = debug_info.getU8(offset_ptr); |
104 | 1.14k | } |
105 | 1.18k | if (IndexEntry1.18k ) { |
106 | 36 | if (AbbrOffset) |
107 | 0 | return false; |
108 | 36 | auto *UnitContrib = IndexEntry->getOffset(); |
109 | 36 | if (!UnitContrib || 36 UnitContrib->Length != (Length + 4)36 ) |
110 | 0 | return false; |
111 | 36 | auto *AbbrEntry = IndexEntry->getOffset(DW_SECT_ABBREV); |
112 | 36 | if (!AbbrEntry) |
113 | 0 | return false; |
114 | 36 | AbbrOffset = AbbrEntry->Offset; |
115 | 36 | } |
116 | 1.18k | |
117 | 1.18k | bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); |
118 | 1.18k | bool VersionOK = DWARFContext::isSupportedVersion(getVersion()); |
119 | 1.07k | bool AddrSizeOK = getAddressByteSize() == 4 || getAddressByteSize() == 8; |
120 | 1.18k | |
121 | 1.18k | if (!LengthOK || 1.18k !VersionOK1.17k || !AddrSizeOK1.16k ) |
122 | 16 | return false; |
123 | 1.16k | |
124 | 1.16k | // Keep track of the highest DWARF version we encounter across all units. |
125 | 1.16k | Context.setMaxVersionIfGreater(getVersion()); |
126 | 1.16k | return true; |
127 | 1.16k | } |
128 | | |
129 | 1.18k | bool DWARFUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) { |
130 | 1.18k | clear(); |
131 | 1.18k | |
132 | 1.18k | Offset = *offset_ptr; |
133 | 1.18k | |
134 | 1.18k | if (debug_info.isValidOffset(*offset_ptr)1.18k ) { |
135 | 1.18k | if (extractImpl(debug_info, offset_ptr)) |
136 | 1.16k | return true; |
137 | 16 | |
138 | 16 | // reset the offset to where we tried to parse from if anything went wrong |
139 | 16 | *offset_ptr = Offset; |
140 | 16 | } |
141 | 1.18k | |
142 | 15 | return false; |
143 | 1.18k | } |
144 | | |
145 | | bool DWARFUnit::extractRangeList(uint32_t RangeListOffset, |
146 | 123 | DWARFDebugRangeList &RangeList) const { |
147 | 123 | // Require that compile unit is extracted. |
148 | 123 | assert(!DieArray.empty()); |
149 | 123 | DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, |
150 | 123 | isLittleEndian, getAddressByteSize()); |
151 | 123 | uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; |
152 | 123 | return RangeList.extract(RangesData, &ActualRangeListOffset); |
153 | 123 | } |
154 | | |
155 | 2.36k | void DWARFUnit::clear() { |
156 | 2.36k | Offset = 0; |
157 | 2.36k | Length = 0; |
158 | 2.36k | Abbrevs = nullptr; |
159 | 2.36k | FormParams = DWARFFormParams({0, 0, DWARF32}); |
160 | 2.36k | BaseAddr.reset(); |
161 | 2.36k | RangeSectionBase = 0; |
162 | 2.36k | AddrOffsetSectionBase = 0; |
163 | 2.36k | clearDIEs(false); |
164 | 2.36k | DWO.reset(); |
165 | 2.36k | } |
166 | | |
167 | 2.73k | const char *DWARFUnit::getCompilationDir() { |
168 | 2.73k | return dwarf::toString(getUnitDIE().find(DW_AT_comp_dir), nullptr); |
169 | 2.73k | } |
170 | | |
171 | 45 | Optional<uint64_t> DWARFUnit::getDWOId() { |
172 | 45 | return toUnsigned(getUnitDIE().find(DW_AT_GNU_dwo_id)); |
173 | 45 | } |
174 | | |
175 | | void DWARFUnit::extractDIEsToVector( |
176 | | bool AppendCUDie, bool AppendNonCUDies, |
177 | 1.25k | std::vector<DWARFDebugInfoEntry> &Dies) const { |
178 | 1.25k | if (!AppendCUDie && 1.25k !AppendNonCUDies143 ) |
179 | 0 | return; |
180 | 1.25k | |
181 | 1.25k | // Set the offset to that of the first DIE and calculate the start of the |
182 | 1.25k | // next compilation unit header. |
183 | 1.25k | uint32_t DIEOffset = Offset + getHeaderSize(); |
184 | 1.25k | uint32_t NextCUOffset = getNextUnitOffset(); |
185 | 1.25k | DWARFDebugInfoEntry DIE; |
186 | 1.25k | DWARFDataExtractor DebugInfoData = getDebugInfoExtractor(); |
187 | 1.25k | uint32_t Depth = 0; |
188 | 1.25k | bool IsCUDie = true; |
189 | 1.25k | |
190 | 11.4k | while (DIE.extractFast(*this, &DIEOffset, DebugInfoData, NextCUOffset, |
191 | 1.25k | Depth)) { |
192 | 11.2k | if (IsCUDie11.2k ) { |
193 | 1.25k | if (AppendCUDie) |
194 | 1.10k | Dies.push_back(DIE); |
195 | 1.25k | if (!AppendNonCUDies) |
196 | 269 | break; |
197 | 983 | // The average bytes per DIE entry has been seen to be |
198 | 983 | // around 14-20 so let's pre-reserve the needed memory for |
199 | 983 | // our DIE entries accordingly. |
200 | 983 | Dies.reserve(Dies.size() + getDebugInfoSize() / 14); |
201 | 983 | IsCUDie = false; |
202 | 11.2k | } else { |
203 | 10.0k | Dies.push_back(DIE); |
204 | 10.0k | } |
205 | 11.2k | |
206 | 11.0k | if (const DWARFAbbreviationDeclaration *11.0k AbbrDecl11.0k = |
207 | 8.40k | DIE.getAbbreviationDeclarationPtr()) { |
208 | 8.40k | // Normal DIE |
209 | 8.40k | if (AbbrDecl->hasChildren()) |
210 | 2.61k | ++Depth; |
211 | 11.0k | } else { |
212 | 2.62k | // NULL DIE. |
213 | 2.62k | if (Depth > 0) |
214 | 2.61k | --Depth; |
215 | 2.62k | if (Depth == 0) |
216 | 860 | break; // We are done with this compile unit! |
217 | 2.62k | } |
218 | 11.2k | } |
219 | 1.25k | |
220 | 1.25k | // Give a little bit of info if we encounter corrupt DWARF (our offset |
221 | 1.25k | // should always terminate at or before the start of the next compilation |
222 | 1.25k | // unit header). |
223 | 1.25k | if (DIEOffset > NextCUOffset) |
224 | 2 | fprintf(stderr, "warning: DWARF compile unit extends beyond its " |
225 | 2 | "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), DIEOffset); |
226 | 1.25k | } |
227 | | |
228 | 13.0k | size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { |
229 | 13.0k | if ((CUDieOnly && 13.0k !DieArray.empty()8.56k ) || |
230 | 4.72k | DieArray.size() > 1) |
231 | 11.7k | return 0; // Already parsed. |
232 | 1.25k | |
233 | 1.25k | bool HasCUDie = !DieArray.empty(); |
234 | 1.25k | extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); |
235 | 1.25k | |
236 | 1.25k | if (DieArray.empty()) |
237 | 4 | return 0; |
238 | 1.25k | |
239 | 1.25k | // If CU DIE was just parsed, copy several attribute values from it. |
240 | 1.25k | if (1.25k !HasCUDie1.25k ) { |
241 | 1.10k | DWARFDie UnitDie = getUnitDIE(); |
242 | 1.10k | Optional<DWARFFormValue> PC = UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc}); |
243 | 1.10k | if (Optional<uint64_t> Addr = toAddress(PC)) |
244 | 729 | setBaseAddress({*Addr, PC->getSectionIndex()}); |
245 | 1.10k | |
246 | 1.10k | if (!isDWO1.10k ) { |
247 | 1.01k | assert(AddrOffsetSectionBase == 0); |
248 | 1.01k | assert(RangeSectionBase == 0); |
249 | 1.01k | AddrOffsetSectionBase = |
250 | 1.01k | toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base), 0); |
251 | 1.01k | RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0); |
252 | 1.01k | } |
253 | 1.10k | |
254 | 1.10k | // In general, we derive the offset of the unit's contibution to the |
255 | 1.10k | // debug_str_offsets{.dwo} section from the unit DIE's |
256 | 1.10k | // DW_AT_str_offsets_base attribute. In dwp files we add to it the offset |
257 | 1.10k | // we get from the index table. |
258 | 1.10k | StringOffsetSectionBase = |
259 | 1.10k | toSectionOffset(UnitDie.find(DW_AT_str_offsets_base), 0); |
260 | 1.10k | if (IndexEntry) |
261 | 36 | if (const auto *36 C36 = IndexEntry->getOffset(DW_SECT_STR_OFFSETS)) |
262 | 33 | StringOffsetSectionBase += C->Offset; |
263 | 1.10k | |
264 | 1.10k | // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for |
265 | 1.10k | // skeleton CU DIE, so that DWARF users not aware of it are not broken. |
266 | 1.10k | } |
267 | 13.0k | |
268 | 13.0k | return DieArray.size(); |
269 | 13.0k | } |
270 | | |
271 | 328 | bool DWARFUnit::parseDWO() { |
272 | 328 | if (isDWO) |
273 | 4 | return false; |
274 | 324 | if (324 DWO.get()324 ) |
275 | 3 | return false; |
276 | 321 | DWARFDie UnitDie = getUnitDIE(); |
277 | 321 | if (!UnitDie) |
278 | 0 | return false; |
279 | 321 | auto DWOFileName = dwarf::toString(UnitDie.find(DW_AT_GNU_dwo_name)); |
280 | 321 | if (!DWOFileName) |
281 | 292 | return false; |
282 | 29 | auto CompilationDir = dwarf::toString(UnitDie.find(DW_AT_comp_dir)); |
283 | 29 | SmallString<16> AbsolutePath; |
284 | 29 | if (sys::path::is_relative(*DWOFileName) && 29 CompilationDir29 && |
285 | 29 | *CompilationDir29 ) { |
286 | 29 | sys::path::append(AbsolutePath, *CompilationDir); |
287 | 29 | } |
288 | 29 | sys::path::append(AbsolutePath, *DWOFileName); |
289 | 29 | auto DWOId = getDWOId(); |
290 | 29 | if (!DWOId) |
291 | 0 | return false; |
292 | 29 | auto DWOContext = Context.getDWOContext(AbsolutePath); |
293 | 29 | if (!DWOContext) |
294 | 12 | return false; |
295 | 17 | |
296 | 17 | DWARFCompileUnit *DWOCU = DWOContext->getDWOCompileUnitForHash(*DWOId); |
297 | 17 | if (!DWOCU) |
298 | 0 | return false; |
299 | 17 | DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU); |
300 | 17 | // Share .debug_addr and .debug_ranges section with compile unit in .dwo |
301 | 17 | DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); |
302 | 17 | auto DWORangesBase = UnitDie.getRangesBaseAttribute(); |
303 | 17 | DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase0 : 017 ); |
304 | 328 | return true; |
305 | 328 | } |
306 | | |
307 | 2.38k | void DWARFUnit::clearDIEs(bool KeepCUDie) { |
308 | 2.38k | if (DieArray.size() > (unsigned)KeepCUDie2.38k ) { |
309 | 17 | DieArray.resize((unsigned)KeepCUDie); |
310 | 17 | DieArray.shrink_to_fit(); |
311 | 17 | } |
312 | 2.38k | } |
313 | | |
314 | 186 | void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { |
315 | 186 | DWARFDie UnitDie = getUnitDIE(); |
316 | 186 | if (!UnitDie) |
317 | 0 | return; |
318 | 186 | // First, check if unit DIE describes address ranges for the whole unit. |
319 | 186 | const auto &CUDIERanges = UnitDie.getAddressRanges(); |
320 | 186 | if (!CUDIERanges.empty()186 ) { |
321 | 143 | CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end()); |
322 | 143 | return; |
323 | 143 | } |
324 | 43 | |
325 | 43 | // This function is usually called if there in no .debug_aranges section |
326 | 43 | // in order to produce a compile unit level set of address ranges that |
327 | 43 | // is accurate. If the DIEs weren't parsed, then we don't want all dies for |
328 | 43 | // all compile units to stay loaded when they weren't needed. So we can end |
329 | 43 | // up parsing the DWARF and then throwing them all away to keep memory usage |
330 | 43 | // down. |
331 | 43 | const bool ClearDIEs = extractDIEsIfNeeded(false) > 1; |
332 | 43 | getUnitDIE().collectChildrenAddressRanges(CURanges); |
333 | 43 | |
334 | 43 | // Collect address ranges from DIEs in .dwo if necessary. |
335 | 43 | bool DWOCreated = parseDWO(); |
336 | 43 | if (DWO) |
337 | 4 | DWO->collectAddressRanges(CURanges); |
338 | 43 | if (DWOCreated) |
339 | 4 | DWO.reset(); |
340 | 43 | |
341 | 43 | // Keep memory down by clearing DIEs if this generate function |
342 | 43 | // caused them to be parsed. |
343 | 43 | if (ClearDIEs) |
344 | 17 | clearDIEs(true); |
345 | 186 | } |
346 | | |
347 | 1.61k | void DWARFUnit::updateAddressDieMap(DWARFDie Die) { |
348 | 1.61k | if (Die.isSubroutineDIE()1.61k ) { |
349 | 226 | for (const auto &R : Die.getAddressRanges()) { |
350 | 226 | // Ignore 0-sized ranges. |
351 | 226 | if (R.LowPC == R.HighPC) |
352 | 0 | continue; |
353 | 226 | auto B = AddrDieMap.upper_bound(R.LowPC); |
354 | 226 | if (B != AddrDieMap.begin() && 226 R.LowPC < (--B)->second.first146 ) { |
355 | 56 | // The range is a sub-range of existing ranges, we need to split the |
356 | 56 | // existing range. |
357 | 56 | if (R.HighPC < B->second.first) |
358 | 53 | AddrDieMap[R.HighPC] = B->second; |
359 | 56 | if (R.LowPC > B->first) |
360 | 29 | AddrDieMap[B->first].first = R.LowPC; |
361 | 56 | } |
362 | 226 | AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die); |
363 | 226 | } |
364 | 329 | } |
365 | 1.61k | // Parent DIEs are added to the AddrDieMap prior to the Children DIEs to |
366 | 1.61k | // simplify the logic to update AddrDieMap. The child's range will always |
367 | 1.61k | // be equal or smaller than the parent's range. With this assumption, when |
368 | 1.61k | // adding one range into the map, it will at most split a range into 3 |
369 | 1.61k | // sub-ranges. |
370 | 3.13k | for (DWARFDie Child = Die.getFirstChild(); Child3.13k ; Child = Child.getSibling()1.52k ) |
371 | 1.52k | updateAddressDieMap(Child); |
372 | 1.61k | } |
373 | | |
374 | 285 | DWARFDie DWARFUnit::getSubroutineForAddress(uint64_t Address) { |
375 | 285 | extractDIEsIfNeeded(false); |
376 | 285 | if (AddrDieMap.empty()) |
377 | 88 | updateAddressDieMap(getUnitDIE()); |
378 | 285 | auto R = AddrDieMap.upper_bound(Address); |
379 | 285 | if (R == AddrDieMap.begin()) |
380 | 14 | return DWARFDie(); |
381 | 271 | // upper_bound's previous item contains Address. |
382 | 271 | --R; |
383 | 271 | if (Address >= R->second.first) |
384 | 2 | return DWARFDie(); |
385 | 269 | return R->second.second; |
386 | 269 | } |
387 | | |
388 | | void |
389 | | DWARFUnit::getInlinedChainForAddress(uint64_t Address, |
390 | 285 | SmallVectorImpl<DWARFDie> &InlinedChain) { |
391 | 285 | assert(InlinedChain.empty()); |
392 | 285 | // Try to look for subprogram DIEs in the DWO file. |
393 | 285 | parseDWO(); |
394 | 285 | // First, find the subroutine that contains the given address (the leaf |
395 | 285 | // of inlined chain). |
396 | 285 | DWARFDie SubroutineDIE = |
397 | 285 | (DWO ? DWO.get()16 : this269 )->getSubroutineForAddress(Address); |
398 | 285 | |
399 | 881 | while (SubroutineDIE881 ) { |
400 | 596 | if (SubroutineDIE.isSubroutineDIE()) |
401 | 321 | InlinedChain.push_back(SubroutineDIE); |
402 | 596 | SubroutineDIE = SubroutineDIE.getParent(); |
403 | 596 | } |
404 | 285 | } |
405 | | |
406 | | const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context, |
407 | 553 | DWARFSectionKind Kind) { |
408 | 553 | if (Kind == DW_SECT_INFO) |
409 | 541 | return Context.getCUIndex(); |
410 | 553 | assert(Kind == DW_SECT_TYPES); |
411 | 12 | return Context.getTUIndex(); |
412 | 12 | } |
413 | | |
414 | 607 | DWARFDie DWARFUnit::getParent(const DWARFDebugInfoEntry *Die) { |
415 | 607 | if (!Die) |
416 | 0 | return DWARFDie(); |
417 | 607 | const uint32_t Depth = Die->getDepth(); |
418 | 607 | // Unit DIEs always have a depth of zero and never have parents. |
419 | 607 | if (Depth == 0) |
420 | 272 | return DWARFDie(); |
421 | 335 | // Depth of 1 always means parent is the compile/type unit. |
422 | 335 | if (335 Depth == 1335 ) |
423 | 272 | return getUnitDIE(); |
424 | 63 | // Look for previous DIE with a depth that is one less than the Die's depth. |
425 | 63 | const uint32_t ParentDepth = Depth - 1; |
426 | 83 | for (uint32_t I = getDIEIndex(Die) - 1; I > 083 ; --I20 ) { |
427 | 83 | if (DieArray[I].getDepth() == ParentDepth) |
428 | 63 | return DWARFDie(this, &DieArray[I]); |
429 | 83 | } |
430 | 0 | return DWARFDie(); |
431 | 607 | } |
432 | | |
433 | 11.3k | DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) { |
434 | 11.3k | if (!Die) |
435 | 0 | return DWARFDie(); |
436 | 11.3k | uint32_t Depth = Die->getDepth(); |
437 | 11.3k | // Unit DIEs always have a depth of zero and never have siblings. |
438 | 11.3k | if (Depth == 0) |
439 | 1 | return DWARFDie(); |
440 | 11.3k | // NULL DIEs don't have siblings. |
441 | 11.3k | if (11.3k Die->getAbbreviationDeclarationPtr() == nullptr11.3k ) |
442 | 2.03k | return DWARFDie(); |
443 | 9.26k | |
444 | 9.26k | // Find the next DIE whose depth is the same as the Die's depth. |
445 | 16.6k | for (size_t I = getDIEIndex(Die) + 1, EndIdx = DieArray.size(); 9.26k I < EndIdx16.6k ; |
446 | 9.26k | ++I7.39k ) { |
447 | 16.6k | if (DieArray[I].getDepth() == Depth) |
448 | 9.26k | return DWARFDie(this, &DieArray[I]); |
449 | 16.6k | } |
450 | 1 | return DWARFDie(); |
451 | 11.3k | } |
452 | | |
453 | 9.25k | const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const { |
454 | 9.25k | if (!Abbrevs) |
455 | 1.10k | Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset); |
456 | 9.25k | return Abbrevs; |
457 | 9.25k | } |