1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | #include "DWARFDebugInfoEntry.h" |
11 | #include "DWARFCompileUnit.h" |
12 | #include "DWARFContext.h" |
13 | #include "DWARFDebugAbbrev.h" |
14 | #include "llvm/DebugInfo/DWARFFormValue.h" |
15 | #include "llvm/Support/DataTypes.h" |
16 | #include "llvm/Support/Debug.h" |
17 | #include "llvm/Support/Dwarf.h" |
18 | #include "llvm/Support/Format.h" |
19 | #include "llvm/Support/raw_ostream.h" |
20 | using namespace llvm; |
21 | using namespace dwarf; |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | static const DWARFUnit *findUnitAndExtractFast(DWARFDebugInfoEntryMinimal &DIE, |
28 | const DWARFUnit *Unit, |
29 | uint32_t *Offset) { |
30 | Unit = Unit->getUnitSection().getUnitForOffset(*Offset); |
31 | return (Unit && DIE.extractFast(Unit, Offset)) ? Unit : nullptr; |
32 | } |
33 | |
34 | void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, DWARFUnit *u, |
35 | unsigned recurseDepth, |
36 | unsigned indent) const { |
37 | DataExtractor debug_info_data = u->getDebugInfoExtractor(); |
38 | uint32_t offset = Offset; |
39 | |
40 | if (debug_info_data.isValidOffset(offset)) { |
41 | uint32_t abbrCode = debug_info_data.getULEB128(&offset); |
42 | |
43 | OS << format("\n0x%8.8x: ", Offset); |
44 | if (abbrCode) { |
45 | if (AbbrevDecl) { |
46 | const char *tagString = TagString(getTag()); |
47 | if (tagString) |
48 | OS.indent(indent) << tagString; |
49 | else |
50 | OS.indent(indent) << format("DW_TAG_Unknown_%x", getTag()); |
51 | OS << format(" [%u] %c\n", abbrCode, |
52 | AbbrevDecl->hasChildren() ? '*' : ' '); |
53 | |
54 | |
55 | for (const auto &AttrSpec : AbbrevDecl->attributes()) { |
56 | dumpAttribute(OS, u, &offset, AttrSpec.Attr, AttrSpec.Form, indent); |
57 | } |
58 | |
59 | const DWARFDebugInfoEntryMinimal *child = getFirstChild(); |
60 | if (recurseDepth > 0 && child) { |
61 | while (child) { |
62 | child->dump(OS, u, recurseDepth-1, indent+2); |
63 | child = child->getSibling(); |
64 | } |
65 | } |
66 | } else { |
67 | OS << "Abbreviation code not found in 'debug_abbrev' class for code: " |
68 | << abbrCode << '\n'; |
69 | } |
70 | } else { |
71 | OS.indent(indent) << "NULL\n"; |
72 | } |
73 | } |
74 | } |
75 | |
76 | static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) { |
77 | OS << " ("; |
78 | do { |
79 | uint64_t Bit = 1ULL << countTrailingZeros(Val); |
| 20 | | The result of the '<<' expression is undefined |
|
80 | if (const char *PropName = ApplePropertyString(Bit)) |
81 | OS << PropName; |
82 | else |
83 | OS << format("DW_APPLE_PROPERTY_0x%" PRIx64"l" "x", Bit); |
84 | if (!(Val ^= Bit)) |
85 | break; |
86 | OS << ", "; |
87 | } while (true); |
88 | OS << ")"; |
89 | } |
90 | |
91 | static void dumpRanges(raw_ostream &OS, const DWARFAddressRangesVector& Ranges, |
92 | unsigned AddressSize, unsigned Indent) { |
93 | if (Ranges.empty()) |
94 | return; |
95 | |
96 | for (const auto &Range: Ranges) { |
97 | OS << '\n'; |
98 | OS.indent(Indent); |
99 | OS << format("[0x%0*" PRIx64"l" "x" " - 0x%0*" PRIx64"l" "x" ")", |
100 | AddressSize*2, Range.first, |
101 | AddressSize*2, Range.second); |
102 | } |
103 | } |
104 | |
105 | void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS, |
106 | DWARFUnit *u, |
107 | uint32_t *offset_ptr, |
108 | uint16_t attr, uint16_t form, |
109 | unsigned indent) const { |
110 | const char BaseIndent[] = " "; |
111 | OS << BaseIndent; |
112 | OS.indent(indent+2); |
113 | const char *attrString = AttributeString(attr); |
114 | if (attrString) |
| 1 | Assuming 'attrString' is null | |
|
| |
115 | OS << attrString; |
116 | else |
117 | OS << format("DW_AT_Unknown_%x", attr); |
118 | const char *formString = FormEncodingString(form); |
119 | if (formString) |
| 3 | | Assuming 'formString' is null | |
|
| |
120 | OS << " [" << formString << ']'; |
121 | else |
122 | OS << format(" [DW_FORM_Unknown_%x]", form); |
123 | |
124 | DWARFFormValue formValue(form); |
125 | |
126 | if (!formValue.extractValue(u->getDebugInfoExtractor(), offset_ptr, u)) |
| |
127 | return; |
128 | |
129 | OS << "\t("; |
130 | |
131 | const char *Name = nullptr; |
132 | std::string File; |
133 | if (attr == DW_AT_decl_file || attr == DW_AT_call_file) { |
| 6 | | Assuming 'attr' is not equal to DW_AT_decl_file | |
|
| 7 | | Assuming 'attr' is not equal to DW_AT_call_file | |
|
| |
134 | if (const auto *LT = u->getContext().getLineTableForUnit(u)) |
135 | if (LT->getFileNameByIndex( |
136 | formValue.getAsUnsignedConstant().getValue(), |
137 | u->getCompilationDir(), |
138 | DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) { |
139 | File = '"' + File + '"'; |
140 | Name = File.c_str(); |
141 | } |
142 | } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant()) |
| |
143 | Name = AttributeValueString(attr, *Val); |
144 | |
145 | if (Name) { |
| |
146 | OS << Name; |
147 | } else if (attr == DW_AT_decl_line || attr == DW_AT_call_line) { |
| 11 | | Assuming 'attr' is not equal to DW_AT_decl_line | |
|
| 12 | | Assuming 'attr' is not equal to DW_AT_call_line | |
|
| |
148 | OS << *formValue.getAsUnsignedConstant(); |
149 | } else { |
150 | formValue.dump(OS, u); |
151 | } |
152 | |
153 | |
154 | |
155 | |
156 | if ((attr == DW_AT_specification || attr == DW_AT_abstract_origin) && |
| 14 | | Assuming 'attr' is not equal to DW_AT_specification | |
|
| 15 | | Assuming 'attr' is not equal to DW_AT_abstract_origin | |
|
157 | |
158 | formValue.getForm() != DW_FORM_ref_sig8) { |
159 | uint32_t Ref = formValue.getAsReference(u).getValue(); |
160 | DWARFDebugInfoEntryMinimal DIE; |
161 | if (const DWARFUnit *RefU = findUnitAndExtractFast(DIE, u, &Ref)) |
162 | if (const char *Ref = DIE.getName(RefU, DINameKind::LinkageName)) |
163 | OS << " \"" << Ref << '\"'; |
164 | } else if (attr == DW_AT_APPLE_property_attribute) { |
| 16 | | Assuming 'attr' is equal to DW_AT_APPLE_property_attribute | |
|
| |
165 | if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant()) |
| |
166 | dumpApplePropertyAttribute(OS, *OptVal); |
| 19 | | Calling 'dumpApplePropertyAttribute' | |
|
167 | } else if (attr == DW_AT_ranges) { |
168 | dumpRanges(OS, getAddressRanges(u), u->getAddressByteSize(), |
169 | sizeof(BaseIndent)+indent+4); |
170 | } |
171 | |
172 | OS << ")\n"; |
173 | } |
174 | |
175 | bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit *U, |
176 | uint32_t *OffsetPtr) { |
177 | Offset = *OffsetPtr; |
178 | DataExtractor DebugInfoData = U->getDebugInfoExtractor(); |
179 | uint32_t UEndOffset = U->getNextUnitOffset(); |
180 | if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset)) |
181 | return false; |
182 | uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr); |
183 | if (0 == AbbrCode) { |
184 | |
185 | AbbrevDecl = nullptr; |
186 | return true; |
187 | } |
188 | AbbrevDecl = U->getAbbreviations()->getAbbreviationDeclaration(AbbrCode); |
189 | if (nullptr == AbbrevDecl) { |
190 | |
191 | *OffsetPtr = Offset; |
192 | return false; |
193 | } |
194 | ArrayRef<uint8_t> FixedFormSizes = DWARFFormValue::getFixedFormSizes( |
195 | U->getAddressByteSize(), U->getVersion()); |
196 | assert(FixedFormSizes.size() > 0)((FixedFormSizes.size() > 0) ? static_cast<void> (0) : __assert_fail ("FixedFormSizes.size() > 0", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn224240/lib/DebugInfo/DWARFDebugInfoEntry.cpp" , 196, __PRETTY_FUNCTION__)); |
197 | |
198 | |
199 | for (const auto &AttrSpec : AbbrevDecl->attributes()) { |
200 | uint16_t Form = AttrSpec.Form; |
201 | |
202 | uint8_t FixedFormSize = |
203 | (Form < FixedFormSizes.size()) ? FixedFormSizes[Form] : 0; |
204 | if (FixedFormSize) |
205 | *OffsetPtr += FixedFormSize; |
206 | else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U)) { |
207 | |
208 | *OffsetPtr = Offset; |
209 | return false; |
210 | } |
211 | } |
212 | return true; |
213 | } |
214 | |
215 | bool DWARFDebugInfoEntryMinimal::isSubprogramDIE() const { |
216 | return getTag() == DW_TAG_subprogram; |
217 | } |
218 | |
219 | bool DWARFDebugInfoEntryMinimal::isSubroutineDIE() const { |
220 | uint32_t Tag = getTag(); |
221 | return Tag == DW_TAG_subprogram || |
222 | Tag == DW_TAG_inlined_subroutine; |
223 | } |
224 | |
225 | bool DWARFDebugInfoEntryMinimal::getAttributeValue( |
226 | const DWARFUnit *U, const uint16_t Attr, DWARFFormValue &FormValue) const { |
227 | if (!AbbrevDecl) |
228 | return false; |
229 | |
230 | uint32_t AttrIdx = AbbrevDecl->findAttributeIndex(Attr); |
231 | if (AttrIdx == -1U) |
232 | return false; |
233 | |
234 | DataExtractor DebugInfoData = U->getDebugInfoExtractor(); |
235 | uint32_t DebugInfoOffset = getOffset(); |
236 | |
237 | |
238 | DebugInfoData.getULEB128(&DebugInfoOffset); |
239 | |
240 | |
241 | for (uint32_t i = 0; i < AttrIdx; ++i) { |
242 | DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(i), |
243 | DebugInfoData, &DebugInfoOffset, U); |
244 | } |
245 | |
246 | FormValue = DWARFFormValue(AbbrevDecl->getFormByIndex(AttrIdx)); |
247 | return FormValue.extractValue(DebugInfoData, &DebugInfoOffset, U); |
248 | } |
249 | |
250 | const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString( |
251 | const DWARFUnit *U, const uint16_t Attr, const char *FailValue) const { |
252 | DWARFFormValue FormValue; |
253 | if (!getAttributeValue(U, Attr, FormValue)) |
254 | return FailValue; |
255 | Optional<const char *> Result = FormValue.getAsCString(U); |
256 | return Result.hasValue() ? Result.getValue() : FailValue; |
257 | } |
258 | |
259 | uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress( |
260 | const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { |
261 | DWARFFormValue FormValue; |
262 | if (!getAttributeValue(U, Attr, FormValue)) |
263 | return FailValue; |
264 | Optional<uint64_t> Result = FormValue.getAsAddress(U); |
265 | return Result.hasValue() ? Result.getValue() : FailValue; |
266 | } |
267 | |
268 | uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsignedConstant( |
269 | const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { |
270 | DWARFFormValue FormValue; |
271 | if (!getAttributeValue(U, Attr, FormValue)) |
272 | return FailValue; |
273 | Optional<uint64_t> Result = FormValue.getAsUnsignedConstant(); |
274 | return Result.hasValue() ? Result.getValue() : FailValue; |
275 | } |
276 | |
277 | uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsReference( |
278 | const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { |
279 | DWARFFormValue FormValue; |
280 | if (!getAttributeValue(U, Attr, FormValue)) |
281 | return FailValue; |
282 | Optional<uint64_t> Result = FormValue.getAsReference(U); |
283 | return Result.hasValue() ? Result.getValue() : FailValue; |
284 | } |
285 | |
286 | uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSectionOffset( |
287 | const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { |
288 | DWARFFormValue FormValue; |
289 | if (!getAttributeValue(U, Attr, FormValue)) |
290 | return FailValue; |
291 | Optional<uint64_t> Result = FormValue.getAsSectionOffset(); |
292 | return Result.hasValue() ? Result.getValue() : FailValue; |
293 | } |
294 | |
295 | uint64_t |
296 | DWARFDebugInfoEntryMinimal::getRangesBaseAttribute(const DWARFUnit *U, |
297 | uint64_t FailValue) const { |
298 | uint64_t Result = |
299 | getAttributeValueAsSectionOffset(U, DW_AT_ranges_base, -1ULL); |
300 | if (Result != -1ULL) |
301 | return Result; |
302 | return getAttributeValueAsSectionOffset(U, DW_AT_GNU_ranges_base, FailValue); |
303 | } |
304 | |
305 | bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U, |
306 | uint64_t &LowPC, |
307 | uint64_t &HighPC) const { |
308 | LowPC = getAttributeValueAsAddress(U, DW_AT_low_pc, -1ULL); |
309 | if (LowPC == -1ULL) |
310 | return false; |
311 | HighPC = getAttributeValueAsAddress(U, DW_AT_high_pc, -1ULL); |
312 | if (HighPC == -1ULL) { |
313 | |
314 | |
315 | HighPC = getAttributeValueAsUnsignedConstant(U, DW_AT_high_pc, -1ULL); |
316 | if (HighPC != -1ULL) |
317 | HighPC += LowPC; |
318 | } |
319 | return (HighPC != -1ULL); |
320 | } |
321 | |
322 | DWARFAddressRangesVector |
323 | DWARFDebugInfoEntryMinimal::getAddressRanges(const DWARFUnit *U) const { |
324 | if (isNULL()) |
325 | return DWARFAddressRangesVector(); |
326 | |
327 | uint64_t LowPC, HighPC; |
328 | if (getLowAndHighPC(U, LowPC, HighPC)) { |
329 | return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC)); |
330 | } |
331 | |
332 | uint32_t RangesOffset = |
333 | getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U); |
334 | if (RangesOffset != -1U) { |
335 | DWARFDebugRangeList RangeList; |
336 | if (U->extractRangeList(RangesOffset, RangeList)) |
337 | return RangeList.getAbsoluteRanges(U->getBaseAddress()); |
338 | } |
339 | return DWARFAddressRangesVector(); |
340 | } |
341 | |
342 | void DWARFDebugInfoEntryMinimal::collectChildrenAddressRanges( |
343 | const DWARFUnit *U, DWARFAddressRangesVector& Ranges) const { |
344 | if (isNULL()) |
345 | return; |
346 | if (isSubprogramDIE()) { |
347 | const auto &DIERanges = getAddressRanges(U); |
348 | Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end()); |
349 | } |
350 | |
351 | const DWARFDebugInfoEntryMinimal *Child = getFirstChild(); |
352 | while (Child) { |
353 | Child->collectChildrenAddressRanges(U, Ranges); |
354 | Child = Child->getSibling(); |
355 | } |
356 | } |
357 | |
358 | bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress( |
359 | const DWARFUnit *U, const uint64_t Address) const { |
360 | for (const auto& R : getAddressRanges(U)) { |
361 | if (R.first <= Address && Address < R.second) |
362 | return true; |
363 | } |
364 | return false; |
365 | } |
366 | |
367 | const char * |
368 | DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U, |
369 | DINameKind Kind) const { |
370 | if (!isSubroutineDIE()) |
371 | return nullptr; |
372 | return getName(U, Kind); |
373 | } |
374 | |
375 | const char * |
376 | DWARFDebugInfoEntryMinimal::getName(const DWARFUnit *U, |
377 | DINameKind Kind) const { |
378 | if (Kind == DINameKind::None) |
379 | return nullptr; |
380 | |
381 | if (Kind == DINameKind::LinkageName) { |
382 | if (const char *name = |
383 | getAttributeValueAsString(U, DW_AT_MIPS_linkage_name, nullptr)) |
384 | return name; |
385 | if (const char *name = |
386 | getAttributeValueAsString(U, DW_AT_linkage_name, nullptr)) |
387 | return name; |
388 | } |
389 | if (const char *name = getAttributeValueAsString(U, DW_AT_name, nullptr)) |
390 | return name; |
391 | |
392 | uint32_t spec_ref = |
393 | getAttributeValueAsReference(U, DW_AT_specification, -1U); |
394 | if (spec_ref != -1U) { |
395 | DWARFDebugInfoEntryMinimal spec_die; |
396 | if (const DWARFUnit *RefU = findUnitAndExtractFast(spec_die, U, &spec_ref)) { |
397 | if (const char *name = spec_die.getName(RefU, Kind)) |
398 | return name; |
399 | } |
400 | } |
401 | |
402 | uint32_t abs_origin_ref = |
403 | getAttributeValueAsReference(U, DW_AT_abstract_origin, -1U); |
404 | if (abs_origin_ref != -1U) { |
405 | DWARFDebugInfoEntryMinimal abs_origin_die; |
406 | if (const DWARFUnit *RefU = findUnitAndExtractFast(abs_origin_die, U, |
407 | &abs_origin_ref)) { |
408 | if (const char *name = abs_origin_die.getName(RefU, Kind)) |
409 | return name; |
410 | } |
411 | } |
412 | return nullptr; |
413 | } |
414 | |
415 | void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFUnit *U, |
416 | uint32_t &CallFile, |
417 | uint32_t &CallLine, |
418 | uint32_t &CallColumn) const { |
419 | CallFile = getAttributeValueAsUnsignedConstant(U, DW_AT_call_file, 0); |
420 | CallLine = getAttributeValueAsUnsignedConstant(U, DW_AT_call_line, 0); |
421 | CallColumn = getAttributeValueAsUnsignedConstant(U, DW_AT_call_column, 0); |
422 | } |
423 | |
424 | DWARFDebugInfoEntryInlinedChain |
425 | DWARFDebugInfoEntryMinimal::getInlinedChainForAddress( |
426 | const DWARFUnit *U, const uint64_t Address) const { |
427 | DWARFDebugInfoEntryInlinedChain InlinedChain; |
428 | InlinedChain.U = U; |
429 | if (isNULL()) |
430 | return InlinedChain; |
431 | for (const DWARFDebugInfoEntryMinimal *DIE = this; DIE; ) { |
432 | |
433 | |
434 | if (DIE->isSubroutineDIE()) { |
435 | InlinedChain.DIEs.push_back(*DIE); |
436 | } |
437 | |
438 | const DWARFDebugInfoEntryMinimal *Child = DIE->getFirstChild(); |
439 | while (Child) { |
440 | if (Child->addressRangeContainsAddress(U, Address)) { |
441 | |
442 | break; |
443 | } |
444 | Child = Child->getSibling(); |
445 | } |
446 | DIE = Child; |
447 | } |
448 | |
449 | std::reverse(InlinedChain.DIEs.begin(), InlinedChain.DIEs.end()); |
450 | return InlinedChain; |
451 | } |