blob: f52cc112f7f64dd23ac1064f34c7e552fe9fc3c4 [file] [log] [blame]
Greg Claytonc8c10322016-12-13 18:25:19 +00001//===-- DWARFDie.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/DWARFDie.h"
11#include "SyntaxHighlighting.h"
12#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
13#include "llvm/DebugInfo/DWARF/DWARFContext.h"
14#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
15#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
16#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
17#include "llvm/Support/DataTypes.h"
18#include "llvm/Support/Debug.h"
19#include "llvm/Support/Dwarf.h"
20#include "llvm/Support/Format.h"
21#include "llvm/Support/raw_ostream.h"
22
23using namespace llvm;
24using namespace dwarf;
25using namespace syntax;
26
27namespace {
28 static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) {
29 OS << " (";
30 do {
31 uint64_t Shift = countTrailingZeros(Val);
32 assert(Shift < 64 && "undefined behavior");
33 uint64_t Bit = 1ULL << Shift;
34 auto PropName = ApplePropertyString(Bit);
35 if (!PropName.empty())
36 OS << PropName;
37 else
38 OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit);
39 if (!(Val ^= Bit))
40 break;
41 OS << ", ";
42 } while (true);
43 OS << ")";
44}
45
46static void dumpRanges(raw_ostream &OS, const DWARFAddressRangesVector& Ranges,
47 unsigned AddressSize, unsigned Indent) {
48 if (Ranges.empty())
49 return;
50
51 for (const auto &Range: Ranges) {
52 OS << '\n';
53 OS.indent(Indent);
54 OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")",
55 AddressSize*2, Range.first,
56 AddressSize*2, Range.second);
57 }
58}
59
60static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
61 uint32_t *OffsetPtr, dwarf::Attribute Attr,
62 dwarf::Form Form, unsigned Indent) {
63 if (!Die.isValid())
64 return;
65 const char BaseIndent[] = " ";
66 OS << BaseIndent;
67 OS.indent(Indent+2);
68 auto attrString = AttributeString(Attr);
69 if (!attrString.empty())
70 WithColor(OS, syntax::Attribute) << attrString;
71 else
72 WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", Attr);
73
74 auto formString = FormEncodingString(Form);
75 if (!formString.empty())
76 OS << " [" << formString << ']';
77 else
78 OS << format(" [DW_FORM_Unknown_%x]", Form);
79
80 DWARFUnit *U = Die.getDwarfUnit();
81 DWARFFormValue formValue(Form);
82
83 if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, U))
84 return;
85
86 OS << "\t(";
87
88 StringRef Name;
89 std::string File;
90 auto Color = syntax::Enumerator;
91 if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) {
92 Color = syntax::String;
93 if (const auto *LT = U->getContext().getLineTableForUnit(U))
94 if (LT->getFileNameByIndex(formValue.getAsUnsignedConstant().getValue(), U->getCompilationDir(), DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) {
95 File = '"' + File + '"';
96 Name = File;
97 }
98 } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant())
99 Name = AttributeValueString(Attr, *Val);
100
101 if (!Name.empty())
102 WithColor(OS, Color) << Name;
103 else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line)
104 OS << *formValue.getAsUnsignedConstant();
105 else
106 formValue.dump(OS);
107
108 // We have dumped the attribute raw value. For some attributes
109 // having both the raw value and the pretty-printed value is
110 // interesting. These attributes are handled below.
111 if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin) {
112 if (const char *Name = Die.getAttributeValueAsReferencedDie(Attr).getName(DINameKind::LinkageName))
113 OS << " \"" << Name << '\"';
114 } else if (Attr == DW_AT_APPLE_property_attribute) {
115 if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant())
116 dumpApplePropertyAttribute(OS, *OptVal);
117 } else if (Attr == DW_AT_ranges) {
118 dumpRanges(OS, Die.getAddressRanges(), U->getAddressByteSize(),
119 sizeof(BaseIndent)+Indent+4);
120 }
121
122 OS << ")\n";
123}
124
125} // end anonymous namespace
126
127bool DWARFDie::isSubprogramDIE() const {
128 return getTag() == DW_TAG_subprogram;
129}
130
131bool DWARFDie::isSubroutineDIE() const {
132 auto Tag = getTag();
133 return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine;
134}
135
Greg Clayton1cbf3fa2016-12-13 23:20:56 +0000136Optional<DWARFFormValue>
137DWARFDie::getAttributeValue(dwarf::Attribute Attr) const {
138 if (!isValid())
139 return None;
Greg Claytonc8c10322016-12-13 18:25:19 +0000140 auto AbbrevDecl = getAbbreviationDeclarationPtr();
141 if (AbbrevDecl)
Greg Clayton1cbf3fa2016-12-13 23:20:56 +0000142 return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U);
143 return None;
Greg Claytonc8c10322016-12-13 18:25:19 +0000144}
145
146const char *DWARFDie::getAttributeValueAsString(dwarf::Attribute Attr,
147 const char *FailValue) const {
Greg Clayton1cbf3fa2016-12-13 23:20:56 +0000148 auto FormValue = getAttributeValue(Attr);
149 if (!FormValue)
Greg Claytonc8c10322016-12-13 18:25:19 +0000150 return FailValue;
Greg Clayton1cbf3fa2016-12-13 23:20:56 +0000151 Optional<const char *> Result = FormValue->getAsCString();
Greg Claytonc8c10322016-12-13 18:25:19 +0000152 return Result.hasValue() ? Result.getValue() : FailValue;
153}
154
155uint64_t DWARFDie::getAttributeValueAsAddress(dwarf::Attribute Attr,
156 uint64_t FailValue) const {
Greg Clayton1cbf3fa2016-12-13 23:20:56 +0000157 auto FormValue = getAttributeValue(Attr);
158 if (!FormValue)
Greg Claytonc8c10322016-12-13 18:25:19 +0000159 return FailValue;
Greg Clayton1cbf3fa2016-12-13 23:20:56 +0000160 Optional<uint64_t> Result = FormValue->getAsAddress();
Greg Claytonc8c10322016-12-13 18:25:19 +0000161 return Result.hasValue() ? Result.getValue() : FailValue;
162}
163
164int64_t DWARFDie::getAttributeValueAsSignedConstant(dwarf::Attribute Attr,
165 int64_t FailValue) const {
Greg Clayton1cbf3fa2016-12-13 23:20:56 +0000166 auto FormValue = getAttributeValue(Attr);
167 if (!FormValue)
Greg Claytonc8c10322016-12-13 18:25:19 +0000168 return FailValue;
Greg Clayton1cbf3fa2016-12-13 23:20:56 +0000169 Optional<int64_t> Result = FormValue->getAsSignedConstant();
Greg Claytonc8c10322016-12-13 18:25:19 +0000170 return Result.hasValue() ? Result.getValue() : FailValue;
171}
172
173uint64_t
174DWARFDie::getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr,
175 uint64_t FailValue) const {
Greg Clayton1cbf3fa2016-12-13 23:20:56 +0000176 auto FormValue = getAttributeValue(Attr);
177 if (!FormValue)
Greg Claytonc8c10322016-12-13 18:25:19 +0000178 return FailValue;
Greg Clayton1cbf3fa2016-12-13 23:20:56 +0000179 Optional<uint64_t> Result = FormValue->getAsUnsignedConstant();
Greg Claytonc8c10322016-12-13 18:25:19 +0000180 return Result.hasValue() ? Result.getValue() : FailValue;
181}
182
183uint64_t DWARFDie::getAttributeValueAsReference(dwarf::Attribute Attr,
184 uint64_t FailValue) const {
Greg Clayton1cbf3fa2016-12-13 23:20:56 +0000185 auto FormValue = getAttributeValue(Attr);
186 if (!FormValue)
Greg Claytonc8c10322016-12-13 18:25:19 +0000187 return FailValue;
Greg Clayton1cbf3fa2016-12-13 23:20:56 +0000188 Optional<uint64_t> Result = FormValue->getAsReference();
Greg Claytonc8c10322016-12-13 18:25:19 +0000189 return Result.hasValue() ? Result.getValue() : FailValue;
190}
191
192uint64_t DWARFDie::getAttributeValueAsSectionOffset(dwarf::Attribute Attr,
193 uint64_t FailValue) const {
Greg Clayton1cbf3fa2016-12-13 23:20:56 +0000194 auto FormValue = getAttributeValue(Attr);
195 if (!FormValue)
Greg Claytonc8c10322016-12-13 18:25:19 +0000196 return FailValue;
Greg Clayton1cbf3fa2016-12-13 23:20:56 +0000197 Optional<uint64_t> Result = FormValue->getAsSectionOffset();
Greg Claytonc8c10322016-12-13 18:25:19 +0000198 return Result.hasValue() ? Result.getValue() : FailValue;
199}
200
201DWARFDie
202DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {
203 uint32_t SpecRef = getAttributeValueAsReference(Attr, -1U);
204 if (SpecRef != -1U) {
205 auto SpecUnit = U->getUnitSection().getUnitForOffset(SpecRef);
206 if (SpecUnit)
207 return SpecUnit->getDIEForOffset(SpecRef);
208 }
209 return DWARFDie();
210}
211
212uint64_t
213DWARFDie::getRangesBaseAttribute(uint64_t FailValue) const {
214 auto Result = getAttributeValueAsSectionOffset(DW_AT_rnglists_base, -1ULL);
215 if (Result != -1ULL)
216 return Result;
217 return getAttributeValueAsSectionOffset(DW_AT_GNU_ranges_base, FailValue);
218}
219
220bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const {
221 LowPC = getAttributeValueAsAddress(DW_AT_low_pc, -1ULL);
222 if (LowPC == -1ULL)
223 return false;
224 HighPC = getAttributeValueAsAddress(DW_AT_high_pc, -1ULL);
225 if (HighPC == -1ULL) {
226 // Since DWARF4, DW_AT_high_pc may also be of class constant, in which case
227 // it represents function size.
228 HighPC = getAttributeValueAsUnsignedConstant(DW_AT_high_pc, -1ULL);
229 if (HighPC != -1ULL)
230 HighPC += LowPC;
231 }
232 return (HighPC != -1ULL);
233}
234
235DWARFAddressRangesVector
236DWARFDie::getAddressRanges() const {
237 if (isNULL())
238 return DWARFAddressRangesVector();
239 // Single range specified by low/high PC.
240 uint64_t LowPC, HighPC;
241 if (getLowAndHighPC(LowPC, HighPC)) {
242 return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC));
243 }
244 // Multiple ranges from .debug_ranges section.
245 uint32_t RangesOffset = getAttributeValueAsSectionOffset(DW_AT_ranges, -1U);
246 if (RangesOffset != -1U) {
247 DWARFDebugRangeList RangeList;
248 if (U->extractRangeList(RangesOffset, RangeList))
249 return RangeList.getAbsoluteRanges(U->getBaseAddress());
250 }
251 return DWARFAddressRangesVector();
252}
253
254void
255DWARFDie::collectChildrenAddressRanges(DWARFAddressRangesVector& Ranges) const {
256 if (isNULL())
257 return;
258 if (isSubprogramDIE()) {
259 const auto &DIERanges = getAddressRanges();
260 Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end());
261 }
262
263 DWARFDie Child = getFirstChild();
264 while (Child) {
265 Child.collectChildrenAddressRanges(Ranges);
266 Child = Child.getSibling();
267 }
268}
269
270bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const {
271 for (const auto& R : getAddressRanges()) {
272 if (R.first <= Address && Address < R.second)
273 return true;
274 }
275 return false;
276}
277
278const char *
279DWARFDie::getSubroutineName(DINameKind Kind) const {
280 if (!isSubroutineDIE())
281 return nullptr;
282 return getName(Kind);
283}
284
285const char *
286DWARFDie::getName(DINameKind Kind) const {
287 if (!isValid() || Kind == DINameKind::None)
288 return nullptr;
289 const char *name = nullptr;
290 // Try to get mangled name only if it was asked for.
291 if (Kind == DINameKind::LinkageName) {
292 if ((name = getAttributeValueAsString(DW_AT_MIPS_linkage_name, nullptr)))
293 return name;
294 if ((name = getAttributeValueAsString(DW_AT_linkage_name, nullptr)))
295 return name;
296 }
297 if ((name = getAttributeValueAsString(DW_AT_name, nullptr)))
298 return name;
299 // Try to get name from specification DIE.
300 DWARFDie SpecDie = getAttributeValueAsReferencedDie(DW_AT_specification);
301 if (SpecDie && (name = SpecDie.getName(Kind)))
302 return name;
303 // Try to get name from abstract origin DIE.
304 DWARFDie AbsDie = getAttributeValueAsReferencedDie(DW_AT_abstract_origin);
305 if (AbsDie && (name = AbsDie.getName(Kind)))
306 return name;
307 return nullptr;
308}
309
310void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
311 uint32_t &CallColumn) const {
312 CallFile = getAttributeValueAsUnsignedConstant(DW_AT_call_file, 0);
313 CallLine = getAttributeValueAsUnsignedConstant(DW_AT_call_line, 0);
314 CallColumn = getAttributeValueAsUnsignedConstant(DW_AT_call_column, 0);
315}
316
317void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth,
318 unsigned Indent) const {
319 if (!isValid())
320 return;
321 DataExtractor debug_info_data = U->getDebugInfoExtractor();
322 const uint32_t Offset = getOffset();
323 uint32_t offset = Offset;
324
325 if (debug_info_data.isValidOffset(offset)) {
326 uint32_t abbrCode = debug_info_data.getULEB128(&offset);
327 WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset);
328
329 if (abbrCode) {
330 auto AbbrevDecl = getAbbreviationDeclarationPtr();
331 if (AbbrevDecl) {
332 auto tagString = TagString(getTag());
333 if (!tagString.empty())
334 WithColor(OS, syntax::Tag).get().indent(Indent) << tagString;
335 else
336 WithColor(OS, syntax::Tag).get().indent(Indent)
337 << format("DW_TAG_Unknown_%x", getTag());
338
339 OS << format(" [%u] %c\n", abbrCode,
340 AbbrevDecl->hasChildren() ? '*' : ' ');
341
342 // Dump all data in the DIE for the attributes.
343 for (const auto &AttrSpec : AbbrevDecl->attributes()) {
344 dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form,
345 Indent);
346 }
347
348 DWARFDie child = getFirstChild();
349 if (RecurseDepth > 0 && child) {
350 while (child) {
351 child.dump(OS, RecurseDepth-1, Indent+2);
352 child = child.getSibling();
353 }
354 }
355 } else {
356 OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
357 << abbrCode << '\n';
358 }
359 } else {
360 OS.indent(Indent) << "NULL\n";
361 }
362 }
363}
364
365
366void DWARFDie::getInlinedChainForAddress(
367 const uint64_t Address, SmallVectorImpl<DWARFDie> &InlinedChain) const {
368 if (isNULL())
369 return;
370 DWARFDie DIE(*this);
371 while (DIE) {
372 // Append current DIE to inlined chain only if it has correct tag
373 // (e.g. it is not a lexical block).
374 if (DIE.isSubroutineDIE())
375 InlinedChain.push_back(DIE);
376
377 // Try to get child which also contains provided address.
378 DWARFDie Child = DIE.getFirstChild();
379 while (Child) {
380 if (Child.addressRangeContainsAddress(Address)) {
381 // Assume there is only one such child.
382 break;
383 }
384 Child = Child.getSibling();
385 }
386 DIE = Child;
387 }
388 // Reverse the obtained chain to make the root of inlined chain last.
389 std::reverse(InlinedChain.begin(), InlinedChain.end());
390}
391