/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- DWARFDie.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/DWARFDie.h" |
10 | | #include "llvm/ADT/None.h" |
11 | | #include "llvm/ADT/Optional.h" |
12 | | #include "llvm/ADT/SmallSet.h" |
13 | | #include "llvm/ADT/StringRef.h" |
14 | | #include "llvm/BinaryFormat/Dwarf.h" |
15 | | #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" |
16 | | #include "llvm/DebugInfo/DWARF/DWARFContext.h" |
17 | | #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" |
18 | | #include "llvm/DebugInfo/DWARF/DWARFExpression.h" |
19 | | #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" |
20 | | #include "llvm/DebugInfo/DWARF/DWARFUnit.h" |
21 | | #include "llvm/Object/ObjectFile.h" |
22 | | #include "llvm/Support/DataExtractor.h" |
23 | | #include "llvm/Support/Format.h" |
24 | | #include "llvm/Support/FormatVariadic.h" |
25 | | #include "llvm/Support/MathExtras.h" |
26 | | #include "llvm/Support/WithColor.h" |
27 | | #include "llvm/Support/raw_ostream.h" |
28 | | #include <algorithm> |
29 | | #include <cassert> |
30 | | #include <cinttypes> |
31 | | #include <cstdint> |
32 | | #include <string> |
33 | | #include <utility> |
34 | | |
35 | | using namespace llvm; |
36 | | using namespace dwarf; |
37 | | using namespace object; |
38 | | |
39 | 25 | static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) { |
40 | 25 | OS << " ("; |
41 | 98 | do { |
42 | 98 | uint64_t Shift = countTrailingZeros(Val); |
43 | 98 | assert(Shift < 64 && "undefined behavior"); |
44 | 98 | uint64_t Bit = 1ULL << Shift; |
45 | 98 | auto PropName = ApplePropertyString(Bit); |
46 | 98 | if (!PropName.empty()) |
47 | 98 | OS << PropName; |
48 | 0 | else |
49 | 0 | OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit); |
50 | 98 | if (!(Val ^= Bit)) |
51 | 25 | break; |
52 | 73 | OS << ", "; |
53 | 73 | } while (true); |
54 | 25 | OS << ")"; |
55 | 25 | } |
56 | | |
57 | | static void dumpRanges(const DWARFObject &Obj, raw_ostream &OS, |
58 | | const DWARFAddressRangesVector &Ranges, |
59 | | unsigned AddressSize, unsigned Indent, |
60 | 57 | const DIDumpOptions &DumpOpts) { |
61 | 57 | if (!DumpOpts.ShowAddresses) |
62 | 1 | return; |
63 | 56 | |
64 | 56 | ArrayRef<SectionName> SectionNames; |
65 | 56 | if (DumpOpts.Verbose) |
66 | 35 | SectionNames = Obj.getSectionNames(); |
67 | 56 | |
68 | 141 | for (const DWARFAddressRange &R : Ranges) { |
69 | 141 | OS << '\n'; |
70 | 141 | OS.indent(Indent); |
71 | 141 | R.dump(OS, AddressSize); |
72 | 141 | |
73 | 141 | DWARFFormValue::dumpAddressSection(Obj, OS, DumpOpts, R.SectionIndex); |
74 | 141 | } |
75 | 56 | } |
76 | | |
77 | | static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue, |
78 | | DWARFUnit *U, unsigned Indent, |
79 | 3.53k | DIDumpOptions DumpOpts) { |
80 | 3.53k | DWARFContext &Ctx = U->getContext(); |
81 | 3.53k | const DWARFObject &Obj = Ctx.getDWARFObj(); |
82 | 3.53k | const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); |
83 | 3.53k | if (FormValue.isFormClass(DWARFFormValue::FC_Block) || |
84 | 3.53k | FormValue.isFormClass(DWARFFormValue::FC_Exprloc)2.78k ) { |
85 | 1.95k | ArrayRef<uint8_t> Expr = *FormValue.getAsBlock(); |
86 | 1.95k | DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), |
87 | 1.95k | Ctx.isLittleEndian(), 0); |
88 | 1.95k | DWARFExpression(Data, U->getVersion(), U->getAddressByteSize()) |
89 | 1.95k | .print(OS, MRI, U); |
90 | 1.95k | return; |
91 | 1.95k | } |
92 | 1.58k | |
93 | 1.58k | FormValue.dump(OS, DumpOpts); |
94 | 1.58k | if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) { |
95 | 203 | uint32_t Offset = *FormValue.getAsSectionOffset(); |
96 | 203 | if (!U->isDWOUnit() && !U->getLocSection()->Data.empty()196 ) { |
97 | 190 | DWARFDebugLoc DebugLoc; |
98 | 190 | DWARFDataExtractor Data(Obj, *U->getLocSection(), Ctx.isLittleEndian(), |
99 | 190 | Obj.getAddressSize()); |
100 | 190 | auto LL = DebugLoc.parseOneLocationList(Data, &Offset); |
101 | 190 | if (LL) { |
102 | 190 | uint64_t BaseAddr = 0; |
103 | 190 | if (Optional<object::SectionedAddress> BA = U->getBaseAddress()) |
104 | 187 | BaseAddr = BA->Address; |
105 | 190 | LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, U, |
106 | 190 | BaseAddr, Indent); |
107 | 190 | } else |
108 | 0 | OS << "error extracting location list."; |
109 | 190 | return; |
110 | 190 | } |
111 | 13 | |
112 | 13 | bool UseLocLists = !U->isDWOUnit(); |
113 | 13 | StringRef LoclistsSectionData = |
114 | 13 | UseLocLists ? Obj.getLoclistsSection().Data6 : U->getLocSectionData()7 ; |
115 | 13 | |
116 | 13 | if (!LoclistsSectionData.empty()) { |
117 | 13 | DataExtractor Data(LoclistsSectionData, Ctx.isLittleEndian(), |
118 | 13 | Obj.getAddressSize()); |
119 | 13 | |
120 | 13 | // Old-style location list were used in DWARF v4 (.debug_loc.dwo section). |
121 | 13 | // Modern locations list (.debug_loclists) are used starting from v5. |
122 | 13 | // Ideally we should take the version from the .debug_loclists section |
123 | 13 | // header, but using CU's version for simplicity. |
124 | 13 | auto LL = DWARFDebugLoclists::parseOneLocationList( |
125 | 13 | Data, &Offset, UseLocLists ? U->getVersion()6 : 47 ); |
126 | 13 | |
127 | 13 | uint64_t BaseAddr = 0; |
128 | 13 | if (Optional<object::SectionedAddress> BA = U->getBaseAddress()) |
129 | 6 | BaseAddr = BA->Address; |
130 | 13 | |
131 | 13 | if (LL) |
132 | 13 | LL->dump(OS, BaseAddr, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, |
133 | 13 | U, Indent); |
134 | 0 | else |
135 | 0 | OS << "error extracting location list."; |
136 | 13 | } |
137 | 13 | } |
138 | 1.58k | } |
139 | | |
140 | | /// Dump the name encoded in the type tag. |
141 | 286 | static void dumpTypeTagName(raw_ostream &OS, dwarf::Tag T) { |
142 | 286 | StringRef TagStr = TagString(T); |
143 | 286 | if (!TagStr.startswith("DW_TAG_") || !TagStr.endswith("_type")) |
144 | 1 | return; |
145 | 285 | OS << TagStr.substr(7, TagStr.size() - 12) << " "; |
146 | 285 | } |
147 | | |
148 | 43 | static void dumpArrayType(raw_ostream &OS, const DWARFDie &D) { |
149 | 43 | Optional<uint64_t> Bound; |
150 | 43 | for (const DWARFDie &C : D.children()) |
151 | 59 | if (C.getTag() == DW_TAG_subrange_type) { |
152 | 58 | Optional<uint64_t> LB; |
153 | 58 | Optional<uint64_t> Count; |
154 | 58 | Optional<uint64_t> UB; |
155 | 58 | Optional<unsigned> DefaultLB; |
156 | 58 | if (Optional<DWARFFormValue> L = C.find(DW_AT_lower_bound)) |
157 | 11 | LB = L->getAsUnsignedConstant(); |
158 | 58 | if (Optional<DWARFFormValue> CountV = C.find(DW_AT_count)) |
159 | 45 | Count = CountV->getAsUnsignedConstant(); |
160 | 58 | if (Optional<DWARFFormValue> UpperV = C.find(DW_AT_upper_bound)) |
161 | 3 | UB = UpperV->getAsUnsignedConstant(); |
162 | 58 | if (Optional<DWARFFormValue> LV = |
163 | 58 | D.getDwarfUnit()->getUnitDIE().find(DW_AT_language)) |
164 | 58 | if (Optional<uint64_t> LC = LV->getAsUnsignedConstant()) |
165 | 58 | if ((DefaultLB = |
166 | 58 | LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LC)))) |
167 | 58 | if (LB && *LB == *DefaultLB11 ) |
168 | 7 | LB = None; |
169 | 58 | if (!LB && !Count54 && !UB23 ) |
170 | 21 | OS << "[]"; |
171 | 37 | else if (!LB && (33 Count33 || UB2 ) && DefaultLB33 ) |
172 | 33 | OS << '[' << (Count ? *Count31 : *UB - *DefaultLB + 12 ) << ']'; |
173 | 4 | else { |
174 | 4 | OS << "[["; |
175 | 4 | if (LB) |
176 | 4 | OS << *LB; |
177 | 0 | else |
178 | 0 | OS << '?'; |
179 | 4 | OS << ", "; |
180 | 4 | if (Count) |
181 | 2 | if (LB) |
182 | 2 | OS << *LB + *Count; |
183 | 0 | else |
184 | 0 | OS << "? + " << *Count; |
185 | 2 | else if (UB) |
186 | 1 | OS << *UB + 1; |
187 | 1 | else |
188 | 1 | OS << '?'; |
189 | 4 | OS << ")]"; |
190 | 4 | } |
191 | 58 | } |
192 | 43 | } |
193 | | |
194 | | /// Recursively dump the DIE type name when applicable. |
195 | 4.09k | static void dumpTypeName(raw_ostream &OS, const DWARFDie &D) { |
196 | 4.09k | if (!D.isValid()) |
197 | 150 | return; |
198 | 3.94k | |
199 | 3.94k | if (const char *Name = D.getName(DINameKind::LinkageName)) { |
200 | 2.94k | OS << Name; |
201 | 2.94k | return; |
202 | 2.94k | } |
203 | 1.00k | |
204 | 1.00k | // FIXME: We should have pretty printers per language. Currently we print |
205 | 1.00k | // everything as if it was C++ and fall back to the TAG type name. |
206 | 1.00k | const dwarf::Tag T = D.getTag(); |
207 | 1.00k | switch (T) { |
208 | 1.00k | case DW_TAG_array_type: |
209 | 714 | case DW_TAG_pointer_type: |
210 | 714 | case DW_TAG_ptr_to_member_type: |
211 | 714 | case DW_TAG_reference_type: |
212 | 714 | case DW_TAG_rvalue_reference_type: |
213 | 714 | case DW_TAG_subroutine_type: |
214 | 714 | break; |
215 | 714 | default: |
216 | 286 | dumpTypeTagName(OS, T); |
217 | 1.00k | } |
218 | 1.00k | |
219 | 1.00k | // Follow the DW_AT_type if possible. |
220 | 1.00k | DWARFDie TypeDie = D.getAttributeValueAsReferencedDie(DW_AT_type); |
221 | 1.00k | dumpTypeName(OS, TypeDie); |
222 | 1.00k | |
223 | 1.00k | switch (T) { |
224 | 1.00k | case DW_TAG_subroutine_type: { |
225 | 36 | if (!TypeDie) |
226 | 20 | OS << "void"; |
227 | 36 | OS << '('; |
228 | 36 | bool First = true; |
229 | 36 | for (const DWARFDie &C : D.children()) { |
230 | 29 | if (C.getTag() == DW_TAG_formal_parameter) { |
231 | 25 | if (!First) |
232 | 5 | OS << ", "; |
233 | 25 | First = false; |
234 | 25 | dumpTypeName(OS, C.getAttributeValueAsReferencedDie(DW_AT_type)); |
235 | 25 | } |
236 | 29 | } |
237 | 36 | OS << ')'; |
238 | 36 | break; |
239 | 1.00k | } |
240 | 1.00k | case DW_TAG_array_type: { |
241 | 43 | dumpArrayType(OS, D); |
242 | 43 | break; |
243 | 1.00k | } |
244 | 1.00k | case DW_TAG_pointer_type: |
245 | 593 | OS << '*'; |
246 | 593 | break; |
247 | 1.00k | case DW_TAG_ptr_to_member_type: |
248 | 9 | if (DWARFDie Cont = |
249 | 9 | D.getAttributeValueAsReferencedDie(DW_AT_containing_type)) { |
250 | 9 | dumpTypeName(OS << ' ', Cont); |
251 | 9 | OS << "::"; |
252 | 9 | } |
253 | 9 | OS << '*'; |
254 | 9 | break; |
255 | 1.00k | case DW_TAG_reference_type: |
256 | 30 | OS << '&'; |
257 | 30 | break; |
258 | 1.00k | case DW_TAG_rvalue_reference_type: |
259 | 3 | OS << "&&"; |
260 | 3 | break; |
261 | 1.00k | default: |
262 | 286 | break; |
263 | 1.00k | } |
264 | 1.00k | } |
265 | | |
266 | | static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, |
267 | | uint32_t *OffsetPtr, dwarf::Attribute Attr, |
268 | | dwarf::Form Form, unsigned Indent, |
269 | 29.6k | DIDumpOptions DumpOpts) { |
270 | 29.6k | if (!Die.isValid()) |
271 | 0 | return; |
272 | 29.6k | const char BaseIndent[] = " "; |
273 | 29.6k | OS << BaseIndent; |
274 | 29.6k | OS.indent(Indent + 2); |
275 | 29.6k | WithColor(OS, HighlightColor::Attribute) << formatv("{0}", Attr); |
276 | 29.6k | |
277 | 29.6k | if (DumpOpts.Verbose || DumpOpts.ShowForm10.6k ) |
278 | 19.0k | OS << formatv(" [{0}]", Form); |
279 | 29.6k | |
280 | 29.6k | DWARFUnit *U = Die.getDwarfUnit(); |
281 | 29.6k | DWARFFormValue FormValue = DWARFFormValue::createFromUnit(Form, U, OffsetPtr); |
282 | 29.6k | |
283 | 29.6k | OS << "\t("; |
284 | 29.6k | |
285 | 29.6k | StringRef Name; |
286 | 29.6k | std::string File; |
287 | 29.6k | auto Color = HighlightColor::Enumerator; |
288 | 29.6k | if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file26.7k ) { |
289 | 2.98k | Color = HighlightColor::String; |
290 | 2.98k | if (const auto *LT = U->getContext().getLineTableForUnit(U)) |
291 | 2.76k | if (LT->getFileNameByIndex( |
292 | 2.76k | FormValue.getAsUnsignedConstant().getValue(), |
293 | 2.76k | U->getCompilationDir(), |
294 | 2.76k | DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) { |
295 | 2.76k | File = '"' + File + '"'; |
296 | 2.76k | Name = File; |
297 | 2.76k | } |
298 | 26.6k | } else if (Optional<uint64_t> Val = FormValue.getAsUnsignedConstant()) |
299 | 10.8k | Name = AttributeValueString(Attr, *Val); |
300 | 29.6k | |
301 | 29.6k | if (!Name.empty()) |
302 | 4.56k | WithColor(OS, Color) << Name; |
303 | 25.0k | else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line22.1k ) |
304 | 3.03k | OS << *FormValue.getAsUnsignedConstant(); |
305 | 22.0k | else if (Attr == DW_AT_high_pc && !DumpOpts.ShowForm1.42k && !DumpOpts.Verbose1.41k && |
306 | 22.0k | FormValue.getAsUnsignedConstant()551 ) { |
307 | 336 | if (DumpOpts.ShowAddresses) { |
308 | 329 | // Print the actual address rather than the offset. |
309 | 329 | uint64_t LowPC, HighPC, Index; |
310 | 329 | if (Die.getLowAndHighPC(LowPC, HighPC, Index)) |
311 | 327 | OS << format("0x%016" PRIx64, HighPC); |
312 | 2 | else |
313 | 2 | FormValue.dump(OS, DumpOpts); |
314 | 329 | } |
315 | 21.7k | } else if (DWARFAttribute::mayHaveLocationDescription(Attr)) |
316 | 3.53k | dumpLocation(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts); |
317 | 18.1k | else |
318 | 18.1k | FormValue.dump(OS, DumpOpts); |
319 | 29.6k | |
320 | 29.6k | std::string Space = DumpOpts.ShowAddresses ? " "29.5k : ""102 ; |
321 | 29.6k | |
322 | 29.6k | // We have dumped the attribute raw value. For some attributes |
323 | 29.6k | // having both the raw value and the pretty-printed value is |
324 | 29.6k | // interesting. These attributes are handled below. |
325 | 29.6k | if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin29.5k ) { |
326 | 344 | if (const char *Name = |
327 | 342 | Die.getAttributeValueAsReferencedDie(FormValue).getName( |
328 | 342 | DINameKind::LinkageName)) |
329 | 342 | OS << Space << "\"" << Name << '\"'; |
330 | 29.2k | } else if (Attr == DW_AT_type) { |
331 | 3.05k | OS << Space << "\""; |
332 | 3.05k | dumpTypeName(OS, Die.getAttributeValueAsReferencedDie(FormValue)); |
333 | 3.05k | OS << '"'; |
334 | 26.2k | } else if (Attr == DW_AT_APPLE_property_attribute) { |
335 | 25 | if (Optional<uint64_t> OptVal = FormValue.getAsUnsignedConstant()) |
336 | 25 | dumpApplePropertyAttribute(OS, *OptVal); |
337 | 26.2k | } else if (Attr == DW_AT_ranges) { |
338 | 63 | const DWARFObject &Obj = Die.getDwarfUnit()->getContext().getDWARFObj(); |
339 | 63 | // For DW_FORM_rnglistx we need to dump the offset separately, since |
340 | 63 | // we have only dumped the index so far. |
341 | 63 | if (FormValue.getForm() == DW_FORM_rnglistx) |
342 | 10 | if (auto RangeListOffset = |
343 | 9 | U->getRnglistOffset(*FormValue.getAsSectionOffset())) { |
344 | 9 | DWARFFormValue FV = DWARFFormValue::createFromUValue( |
345 | 9 | dwarf::DW_FORM_sec_offset, *RangeListOffset); |
346 | 9 | FV.dump(OS, DumpOpts); |
347 | 9 | } |
348 | 63 | if (auto RangesOrError = Die.getAddressRanges()) |
349 | 57 | dumpRanges(Obj, OS, RangesOrError.get(), U->getAddressByteSize(), |
350 | 57 | sizeof(BaseIndent) + Indent + 4, DumpOpts); |
351 | 6 | else |
352 | 6 | WithColor::error() << "decoding address ranges: " |
353 | 6 | << toString(RangesOrError.takeError()) << '\n'; |
354 | 63 | } |
355 | 29.6k | |
356 | 29.6k | OS << ")\n"; |
357 | 29.6k | } |
358 | | |
359 | 830 | bool DWARFDie::isSubprogramDIE() const { return getTag() == DW_TAG_subprogram; } |
360 | | |
361 | 2.65k | bool DWARFDie::isSubroutineDIE() const { |
362 | 2.65k | auto Tag = getTag(); |
363 | 2.65k | return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine2.11k ; |
364 | 2.65k | } |
365 | | |
366 | 49.2k | Optional<DWARFFormValue> DWARFDie::find(dwarf::Attribute Attr) const { |
367 | 49.2k | if (!isValid()) |
368 | 0 | return None; |
369 | 49.2k | auto AbbrevDecl = getAbbreviationDeclarationPtr(); |
370 | 49.2k | if (AbbrevDecl) |
371 | 47.8k | return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U); |
372 | 1.34k | return None; |
373 | 1.34k | } |
374 | | |
375 | | Optional<DWARFFormValue> |
376 | 17.8k | DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const { |
377 | 17.8k | if (!isValid()) |
378 | 0 | return None; |
379 | 17.8k | auto AbbrevDecl = getAbbreviationDeclarationPtr(); |
380 | 17.8k | if (AbbrevDecl) { |
381 | 24.2k | for (auto Attr : Attrs) { |
382 | 24.2k | if (auto Value = AbbrevDecl->getAttributeValue(getOffset(), Attr, *U)) |
383 | 8.63k | return Value; |
384 | 24.2k | } |
385 | 17.3k | } |
386 | 17.8k | return None9.22k ; |
387 | 17.8k | } |
388 | | |
389 | | Optional<DWARFFormValue> |
390 | 16.4k | DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const { |
391 | 16.4k | std::vector<DWARFDie> Worklist; |
392 | 16.4k | Worklist.push_back(*this); |
393 | 16.4k | |
394 | 16.4k | // Keep track if DIEs already seen to prevent infinite recursion. |
395 | 16.4k | // Empirically we rarely see a depth of more than 3 when dealing with valid |
396 | 16.4k | // DWARF. This corresponds to following the DW_AT_abstract_origin and |
397 | 16.4k | // DW_AT_specification just once. |
398 | 16.4k | SmallSet<DWARFDie, 3> Seen; |
399 | 16.4k | Seen.insert(*this); |
400 | 16.4k | |
401 | 25.1k | while (!Worklist.empty()) { |
402 | 17.1k | DWARFDie Die = Worklist.back(); |
403 | 17.1k | Worklist.pop_back(); |
404 | 17.1k | |
405 | 17.1k | if (!Die.isValid()) |
406 | 0 | continue; |
407 | 17.1k | |
408 | 17.1k | if (auto Value = Die.find(Attrs)) |
409 | 8.32k | return Value; |
410 | 8.77k | |
411 | 8.77k | if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) |
412 | 660 | if (Seen.insert(D).second) |
413 | 658 | Worklist.push_back(D); |
414 | 8.77k | |
415 | 8.77k | if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification)) |
416 | 26 | if (Seen.insert(D).second) |
417 | 26 | Worklist.push_back(D); |
418 | 8.77k | } |
419 | 16.4k | |
420 | 16.4k | return None8.09k ; |
421 | 16.4k | } |
422 | | |
423 | | DWARFDie |
424 | 19.0k | DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { |
425 | 19.0k | if (Optional<DWARFFormValue> F = find(Attr)) |
426 | 2.02k | return getAttributeValueAsReferencedDie(*F); |
427 | 17.0k | return DWARFDie(); |
428 | 17.0k | } |
429 | | |
430 | | DWARFDie |
431 | 5.42k | DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const { |
432 | 5.42k | if (auto SpecRef = V.getAsRelativeReference()) { |
433 | 5.42k | if (SpecRef->Unit) |
434 | 5.11k | return SpecRef->Unit->getDIEForOffset(SpecRef->Unit->getOffset() + SpecRef->Offset); |
435 | 316 | if (auto SpecUnit = U->getUnitVector().getUnitForOffset(SpecRef->Offset)) |
436 | 304 | return SpecUnit->getDIEForOffset(SpecRef->Offset); |
437 | 12 | } |
438 | 12 | return DWARFDie(); |
439 | 12 | } |
440 | | |
441 | 6 | Optional<uint64_t> DWARFDie::getRangesBaseAttribute() const { |
442 | 6 | return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base})); |
443 | 6 | } |
444 | | |
445 | 1.53k | Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const { |
446 | 1.53k | if (auto FormValue = find(DW_AT_high_pc)) { |
447 | 1.36k | if (auto Address = FormValue->getAsAddress()) { |
448 | 318 | // High PC is an address. |
449 | 318 | return Address; |
450 | 318 | } |
451 | 1.04k | if (auto Offset = FormValue->getAsUnsignedConstant()) { |
452 | 1.04k | // High PC is an offset from LowPC. |
453 | 1.04k | return LowPC + *Offset; |
454 | 1.04k | } |
455 | 173 | } |
456 | 173 | return None; |
457 | 173 | } |
458 | | |
459 | | bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, |
460 | 1.94k | uint64_t &SectionIndex) const { |
461 | 1.94k | auto F = find(DW_AT_low_pc); |
462 | 1.94k | auto LowPcAddr = toSectionedAddress(F); |
463 | 1.94k | if (!LowPcAddr) |
464 | 694 | return false; |
465 | 1.25k | if (auto HighPcAddr = getHighPC(LowPcAddr->Address)) { |
466 | 1.09k | LowPC = LowPcAddr->Address; |
467 | 1.09k | HighPC = *HighPcAddr; |
468 | 1.09k | SectionIndex = LowPcAddr->SectionIndex; |
469 | 1.09k | return true; |
470 | 1.09k | } |
471 | 160 | return false; |
472 | 160 | } |
473 | | |
474 | 1.59k | Expected<DWARFAddressRangesVector> DWARFDie::getAddressRanges() const { |
475 | 1.59k | if (isNULL()) |
476 | 2 | return DWARFAddressRangesVector(); |
477 | 1.59k | // Single range specified by low/high PC. |
478 | 1.59k | uint64_t LowPC, HighPC, Index; |
479 | 1.59k | if (getLowAndHighPC(LowPC, HighPC, Index)) |
480 | 758 | return DWARFAddressRangesVector{{LowPC, HighPC, Index}}; |
481 | 833 | |
482 | 833 | Optional<DWARFFormValue> Value = find(DW_AT_ranges); |
483 | 833 | if (Value) { |
484 | 170 | if (Value->getForm() == DW_FORM_rnglistx) |
485 | 14 | return U->findRnglistFromIndex(*Value->getAsSectionOffset()); |
486 | 156 | return U->findRnglistFromOffset(*Value->getAsSectionOffset()); |
487 | 156 | } |
488 | 663 | return DWARFAddressRangesVector(); |
489 | 663 | } |
490 | | |
491 | | void DWARFDie::collectChildrenAddressRanges( |
492 | 0 | DWARFAddressRangesVector &Ranges) const { |
493 | 0 | if (isNULL()) |
494 | 0 | return; |
495 | 0 | if (isSubprogramDIE()) { |
496 | 0 | if (auto DIERangesOrError = getAddressRanges()) |
497 | 0 | Ranges.insert(Ranges.end(), DIERangesOrError.get().begin(), |
498 | 0 | DIERangesOrError.get().end()); |
499 | 0 | else |
500 | 0 | llvm::consumeError(DIERangesOrError.takeError()); |
501 | 0 | } |
502 | 0 |
|
503 | 0 | for (auto Child : children()) |
504 | 0 | Child.collectChildrenAddressRanges(Ranges); |
505 | 0 | } |
506 | | |
507 | 3 | bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const { |
508 | 3 | auto RangesOrError = getAddressRanges(); |
509 | 3 | if (!RangesOrError) { |
510 | 0 | llvm::consumeError(RangesOrError.takeError()); |
511 | 0 | return false; |
512 | 0 | } |
513 | 3 | |
514 | 3 | for (const auto &R : RangesOrError.get()) |
515 | 3 | if (R.LowPC <= Address && Address < R.HighPC) |
516 | 2 | return true; |
517 | 3 | return false1 ; |
518 | 3 | } |
519 | | |
520 | 229 | const char *DWARFDie::getSubroutineName(DINameKind Kind) const { |
521 | 229 | if (!isSubroutineDIE()) |
522 | 0 | return nullptr; |
523 | 229 | return getName(Kind); |
524 | 229 | } |
525 | | |
526 | 8.93k | const char *DWARFDie::getName(DINameKind Kind) const { |
527 | 8.93k | if (!isValid() || Kind == DINameKind::None) |
528 | 33 | return nullptr; |
529 | 8.89k | // Try to get mangled name only if it was asked for. |
530 | 8.89k | if (Kind == DINameKind::LinkageName) { |
531 | 6.33k | if (auto Name = dwarf::toString( |
532 | 290 | findRecursively({DW_AT_MIPS_linkage_name, DW_AT_linkage_name}), |
533 | 290 | nullptr)) |
534 | 290 | return Name; |
535 | 8.60k | } |
536 | 8.60k | if (auto Name = dwarf::toString(findRecursively(DW_AT_name), nullptr)) |
537 | 6.57k | return Name; |
538 | 2.03k | return nullptr; |
539 | 2.03k | } |
540 | | |
541 | 814 | uint64_t DWARFDie::getDeclLine() const { |
542 | 814 | return toUnsigned(findRecursively(DW_AT_decl_line), 0); |
543 | 814 | } |
544 | | |
545 | | void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, |
546 | | uint32_t &CallColumn, |
547 | 100 | uint32_t &CallDiscriminator) const { |
548 | 100 | CallFile = toUnsigned(find(DW_AT_call_file), 0); |
549 | 100 | CallLine = toUnsigned(find(DW_AT_call_line), 0); |
550 | 100 | CallColumn = toUnsigned(find(DW_AT_call_column), 0); |
551 | 100 | CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0); |
552 | 100 | } |
553 | | |
554 | | /// Helper to dump a DIE with all of its parents, but no siblings. |
555 | | static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent, |
556 | 16 | DIDumpOptions DumpOpts, unsigned Depth = 0) { |
557 | 16 | if (!Die) |
558 | 5 | return Indent; |
559 | 11 | if (DumpOpts.ParentRecurseDepth > 0 && Depth >= DumpOpts.ParentRecurseDepth) |
560 | 1 | return Indent; |
561 | 10 | Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts, Depth + 1); |
562 | 10 | Die.dump(OS, Indent, DumpOpts); |
563 | 10 | return Indent + 2; |
564 | 10 | } |
565 | | |
566 | | void DWARFDie::dump(raw_ostream &OS, unsigned Indent, |
567 | 8.55k | DIDumpOptions DumpOpts) const { |
568 | 8.55k | if (!isValid()) |
569 | 1 | return; |
570 | 8.55k | DWARFDataExtractor debug_info_data = U->getDebugInfoExtractor(); |
571 | 8.55k | const uint32_t Offset = getOffset(); |
572 | 8.55k | uint32_t offset = Offset; |
573 | 8.55k | if (DumpOpts.ShowParents) { |
574 | 6 | DIDumpOptions ParentDumpOpts = DumpOpts; |
575 | 6 | ParentDumpOpts.ShowParents = false; |
576 | 6 | ParentDumpOpts.ShowChildren = false; |
577 | 6 | Indent = dumpParentChain(getParent(), OS, Indent, ParentDumpOpts); |
578 | 6 | } |
579 | 8.55k | |
580 | 8.55k | if (debug_info_data.isValidOffset(offset)) { |
581 | 8.55k | uint32_t abbrCode = debug_info_data.getULEB128(&offset); |
582 | 8.55k | if (DumpOpts.ShowAddresses) |
583 | 8.52k | WithColor(OS, HighlightColor::Address).get() |
584 | 8.52k | << format("\n0x%8.8x: ", Offset); |
585 | 8.55k | |
586 | 8.55k | if (abbrCode) { |
587 | 6.52k | auto AbbrevDecl = getAbbreviationDeclarationPtr(); |
588 | 6.52k | if (AbbrevDecl) { |
589 | 6.52k | WithColor(OS, HighlightColor::Tag).get().indent(Indent) |
590 | 6.52k | << formatv("{0}", getTag()); |
591 | 6.52k | if (DumpOpts.Verbose) |
592 | 4.28k | OS << format(" [%u] %c", abbrCode, |
593 | 4.28k | AbbrevDecl->hasChildren() ? '*'1.40k : ' '2.88k ); |
594 | 6.52k | OS << '\n'; |
595 | 6.52k | |
596 | 6.52k | // Dump all data in the DIE for the attributes. |
597 | 29.6k | for (const auto &AttrSpec : AbbrevDecl->attributes()) { |
598 | 29.6k | if (AttrSpec.Form == DW_FORM_implicit_const) { |
599 | 0 | // We are dumping .debug_info section , |
600 | 0 | // implicit_const attribute values are not really stored here, |
601 | 0 | // but in .debug_abbrev section. So we just skip such attrs. |
602 | 0 | continue; |
603 | 0 | } |
604 | 29.6k | dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form, |
605 | 29.6k | Indent, DumpOpts); |
606 | 29.6k | } |
607 | 6.52k | |
608 | 6.52k | DWARFDie child = getFirstChild(); |
609 | 6.52k | if (DumpOpts.ShowChildren && DumpOpts.ChildRecurseDepth > 06.31k && child6.29k ) { |
610 | 2.03k | DumpOpts.ChildRecurseDepth--; |
611 | 2.03k | DIDumpOptions ChildDumpOpts = DumpOpts; |
612 | 2.03k | ChildDumpOpts.ShowParents = false; |
613 | 9.56k | while (child) { |
614 | 7.52k | child.dump(OS, Indent + 2, ChildDumpOpts); |
615 | 7.52k | child = child.getSibling(); |
616 | 7.52k | } |
617 | 2.03k | } |
618 | 6.52k | } else { |
619 | 0 | OS << "Abbreviation code not found in 'debug_abbrev' class for code: " |
620 | 0 | << abbrCode << '\n'; |
621 | 0 | } |
622 | 6.52k | } else { |
623 | 2.03k | OS.indent(Indent) << "NULL\n"; |
624 | 2.03k | } |
625 | 8.55k | } |
626 | 8.55k | } |
627 | | |
628 | 0 | LLVM_DUMP_METHOD void DWARFDie::dump() const { dump(llvm::errs(), 0); } |
629 | | |
630 | 140 | DWARFDie DWARFDie::getParent() const { |
631 | 140 | if (isValid()) |
632 | 139 | return U->getParent(Die); |
633 | 1 | return DWARFDie(); |
634 | 1 | } |
635 | | |
636 | 14.2k | DWARFDie DWARFDie::getSibling() const { |
637 | 14.2k | if (isValid()) |
638 | 14.2k | return U->getSibling(Die); |
639 | 1 | return DWARFDie(); |
640 | 1 | } |
641 | | |
642 | 3.24k | DWARFDie DWARFDie::getPreviousSibling() const { |
643 | 3.24k | if (isValid()) |
644 | 3.24k | return U->getPreviousSibling(Die); |
645 | 0 | return DWARFDie(); |
646 | 0 | } |
647 | | |
648 | 13.2k | DWARFDie DWARFDie::getFirstChild() const { |
649 | 13.2k | if (isValid()) |
650 | 13.2k | return U->getFirstChild(Die); |
651 | 2 | return DWARFDie(); |
652 | 2 | } |
653 | | |
654 | 4.05k | DWARFDie DWARFDie::getLastChild() const { |
655 | 4.05k | if (isValid()) |
656 | 4.05k | return U->getLastChild(Die); |
657 | 1 | return DWARFDie(); |
658 | 1 | } |
659 | | |
660 | 579 | iterator_range<DWARFDie::attribute_iterator> DWARFDie::attributes() const { |
661 | 579 | return make_range(attribute_iterator(*this, false), |
662 | 579 | attribute_iterator(*this, true)); |
663 | 579 | } |
664 | | |
665 | | DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End) |
666 | 1.15k | : Die(D), Index(0) { |
667 | 1.15k | auto AbbrDecl = Die.getAbbreviationDeclarationPtr(); |
668 | 1.15k | assert(AbbrDecl && "Must have abbreviation declaration"); |
669 | 1.15k | if (End) { |
670 | 579 | // This is the end iterator so we set the index to the attribute count. |
671 | 579 | Index = AbbrDecl->getNumAttributes(); |
672 | 579 | } else { |
673 | 579 | // This is the begin iterator so we extract the value for this->Index. |
674 | 579 | AttrValue.Offset = D.getOffset() + AbbrDecl->getCodeByteSize(); |
675 | 579 | updateForIndex(*AbbrDecl, 0); |
676 | 579 | } |
677 | 1.15k | } |
678 | | |
679 | | void DWARFDie::attribute_iterator::updateForIndex( |
680 | 3.20k | const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I) { |
681 | 3.20k | Index = I; |
682 | 3.20k | // AbbrDecl must be valid before calling this function. |
683 | 3.20k | auto NumAttrs = AbbrDecl.getNumAttributes(); |
684 | 3.20k | if (Index < NumAttrs) { |
685 | 2.62k | AttrValue.Attr = AbbrDecl.getAttrByIndex(Index); |
686 | 2.62k | // Add the previous byte size of any previous attribute value. |
687 | 2.62k | AttrValue.Offset += AttrValue.ByteSize; |
688 | 2.62k | uint32_t ParseOffset = AttrValue.Offset; |
689 | 2.62k | auto U = Die.getDwarfUnit(); |
690 | 2.62k | assert(U && "Die must have valid DWARF unit"); |
691 | 2.62k | AttrValue.Value = DWARFFormValue::createFromUnit( |
692 | 2.62k | AbbrDecl.getFormByIndex(Index), U, &ParseOffset); |
693 | 2.62k | AttrValue.ByteSize = ParseOffset - AttrValue.Offset; |
694 | 2.62k | } else { |
695 | 579 | assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only"); |
696 | 579 | AttrValue = {}; |
697 | 579 | } |
698 | 3.20k | } |
699 | | |
700 | 2.62k | DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() { |
701 | 2.62k | if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr()) |
702 | 2.62k | updateForIndex(*AbbrDecl, Index + 1); |
703 | 2.62k | return *this; |
704 | 2.62k | } |
705 | | |
706 | 22.4k | bool DWARFAttribute::mayHaveLocationDescription(dwarf::Attribute Attr) { |
707 | 22.4k | switch (Attr) { |
708 | 22.4k | // From the DWARF v5 specification. |
709 | 22.4k | case DW_AT_location: |
710 | 4.25k | case DW_AT_byte_size: |
711 | 4.25k | case DW_AT_bit_size: |
712 | 4.25k | case DW_AT_string_length: |
713 | 4.25k | case DW_AT_lower_bound: |
714 | 4.25k | case DW_AT_return_addr: |
715 | 4.25k | case DW_AT_bit_stride: |
716 | 4.25k | case DW_AT_upper_bound: |
717 | 4.25k | case DW_AT_count: |
718 | 4.25k | case DW_AT_data_member_location: |
719 | 4.25k | case DW_AT_frame_base: |
720 | 4.25k | case DW_AT_segment: |
721 | 4.25k | case DW_AT_static_link: |
722 | 4.25k | case DW_AT_use_location: |
723 | 4.25k | case DW_AT_vtable_elem_location: |
724 | 4.25k | case DW_AT_allocated: |
725 | 4.25k | case DW_AT_associated: |
726 | 4.25k | case DW_AT_byte_stride: |
727 | 4.25k | case DW_AT_rank: |
728 | 4.25k | case DW_AT_call_value: |
729 | 4.25k | case DW_AT_call_origin: |
730 | 4.25k | case DW_AT_call_target: |
731 | 4.25k | case DW_AT_call_target_clobbered: |
732 | 4.25k | case DW_AT_call_data_location: |
733 | 4.25k | case DW_AT_call_data_value: |
734 | 4.25k | // Extensions. |
735 | 4.25k | case DW_AT_GNU_call_site_value: |
736 | 4.25k | return true; |
737 | 18.1k | default: |
738 | 18.1k | return false; |
739 | 22.4k | } |
740 | 22.4k | } |