LLVM  4.0.0
DWARFDie.cpp
Go to the documentation of this file.
1 //===-- 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 
11 #include "SyntaxHighlighting.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"
22 
23 using namespace llvm;
24 using namespace dwarf;
25 using namespace syntax;
26 
27 namespace {
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 
46 static 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 
60 static 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 
89  std::string File;
91  if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) {
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 
128  return getTag() == DW_TAG_subprogram;
129 }
130 
132  auto Tag = getTag();
133  return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine;
134 }
135 
138  if (!isValid())
139  return None;
140  auto AbbrevDecl = getAbbreviationDeclarationPtr();
141  if (AbbrevDecl)
142  return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U);
143  return None;
144 }
145 
147  const char *FailValue) const {
148  auto FormValue = getAttributeValue(Attr);
149  if (!FormValue)
150  return FailValue;
151  Optional<const char *> Result = FormValue->getAsCString();
152  return Result.hasValue() ? Result.getValue() : FailValue;
153 }
154 
157  if (auto FormValue = getAttributeValue(Attr))
158  return FormValue->getAsAddress();
159  return None;
160 }
161 
164  if (auto FormValue = getAttributeValue(Attr))
165  return FormValue->getAsSignedConstant();
166  return None;
167 }
168 
171  if (auto FormValue = getAttributeValue(Attr))
172  return FormValue->getAsUnsignedConstant();
173  return None;
174 }
175 
178  if (auto FormValue = getAttributeValue(Attr))
179  return FormValue->getAsReference();
180  return None;
181 }
182 
185  if (auto FormValue = getAttributeValue(Attr))
186  return FormValue->getAsSectionOffset();
187  return None;
188 }
189 
190 
191 DWARFDie
193  auto SpecRef = getAttributeValueAsReference(Attr);
194  if (SpecRef) {
195  auto SpecUnit = U->getUnitSection().getUnitForOffset(*SpecRef);
196  if (SpecUnit)
197  return SpecUnit->getDIEForOffset(*SpecRef);
198  }
199  return DWARFDie();
200 }
201 
204  auto Result = getAttributeValueAsSectionOffset(DW_AT_rnglists_base);
205  if (Result)
206  return Result;
207  return getAttributeValueAsSectionOffset(DW_AT_GNU_ranges_base);
208 }
209 
211  if (auto FormValue = getAttributeValue(DW_AT_high_pc)) {
212  if (auto Address = FormValue->getAsAddress()) {
213  // High PC is an address.
214  return Address;
215  }
216  if (auto Offset = FormValue->getAsUnsignedConstant()) {
217  // High PC is an offset from LowPC.
218  return LowPC + *Offset;
219  }
220  }
221  return None;
222 }
223 
224 bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const {
225  auto LowPcAddr = getAttributeValueAsAddress(DW_AT_low_pc);
226  if (!LowPcAddr)
227  return false;
228  if (auto HighPcAddr = getHighPC(*LowPcAddr)) {
229  LowPC = *LowPcAddr;
230  HighPC = *HighPcAddr;
231  return true;
232  }
233  return false;
234 }
235 
238  if (isNULL())
239  return DWARFAddressRangesVector();
240  // Single range specified by low/high PC.
241  uint64_t LowPC, HighPC;
242  if (getLowAndHighPC(LowPC, HighPC)) {
243  return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC));
244  }
245  // Multiple ranges from .debug_ranges section.
246  auto RangesOffset = getAttributeValueAsSectionOffset(DW_AT_ranges);
247  if (RangesOffset) {
248  DWARFDebugRangeList RangeList;
249  if (U->extractRangeList(*RangesOffset, RangeList))
250  return RangeList.getAbsoluteRanges(U->getBaseAddress());
251  }
252  return DWARFAddressRangesVector();
253 }
254 
255 void
257  if (isNULL())
258  return;
259  if (isSubprogramDIE()) {
260  const auto &DIERanges = getAddressRanges();
261  Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end());
262  }
263 
264  for (auto Child: children())
265  Child.collectChildrenAddressRanges(Ranges);
266 }
267 
268 bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const {
269  for (const auto& R : getAddressRanges()) {
270  if (R.first <= Address && Address < R.second)
271  return true;
272  }
273  return false;
274 }
275 
276 const char *
278  if (!isSubroutineDIE())
279  return nullptr;
280  return getName(Kind);
281 }
282 
283 const char *
285  if (!isValid() || Kind == DINameKind::None)
286  return nullptr;
287  const char *name = nullptr;
288  // Try to get mangled name only if it was asked for.
289  if (Kind == DINameKind::LinkageName) {
290  if ((name = getAttributeValueAsString(DW_AT_MIPS_linkage_name, nullptr)))
291  return name;
292  if ((name = getAttributeValueAsString(DW_AT_linkage_name, nullptr)))
293  return name;
294  }
295  if ((name = getAttributeValueAsString(DW_AT_name, nullptr)))
296  return name;
297  // Try to get name from specification DIE.
298  DWARFDie SpecDie = getAttributeValueAsReferencedDie(DW_AT_specification);
299  if (SpecDie && (name = SpecDie.getName(Kind)))
300  return name;
301  // Try to get name from abstract origin DIE.
302  DWARFDie AbsDie = getAttributeValueAsReferencedDie(DW_AT_abstract_origin);
303  if (AbsDie && (name = AbsDie.getName(Kind)))
304  return name;
305  return nullptr;
306 }
307 
308 void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
309  uint32_t &CallColumn) const {
310  CallFile = getAttributeValueAsUnsignedConstant(DW_AT_call_file).getValueOr(0);
311  CallLine = getAttributeValueAsUnsignedConstant(DW_AT_call_line).getValueOr(0);
312  CallColumn =
313  getAttributeValueAsUnsignedConstant(DW_AT_call_column).getValueOr(0);
314 }
315 
316 void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth,
317  unsigned Indent) const {
318  if (!isValid())
319  return;
320  DataExtractor debug_info_data = U->getDebugInfoExtractor();
321  const uint32_t Offset = getOffset();
322  uint32_t offset = Offset;
323 
324  if (debug_info_data.isValidOffset(offset)) {
325  uint32_t abbrCode = debug_info_data.getULEB128(&offset);
326  WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset);
327 
328  if (abbrCode) {
329  auto AbbrevDecl = getAbbreviationDeclarationPtr();
330  if (AbbrevDecl) {
331  auto tagString = TagString(getTag());
332  if (!tagString.empty())
333  WithColor(OS, syntax::Tag).get().indent(Indent) << tagString;
334  else
335  WithColor(OS, syntax::Tag).get().indent(Indent)
336  << format("DW_TAG_Unknown_%x", getTag());
337 
338  OS << format(" [%u] %c\n", abbrCode,
339  AbbrevDecl->hasChildren() ? '*' : ' ');
340 
341  // Dump all data in the DIE for the attributes.
342  for (const auto &AttrSpec : AbbrevDecl->attributes()) {
343  dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form,
344  Indent);
345  }
346 
347  DWARFDie child = getFirstChild();
348  if (RecurseDepth > 0 && child) {
349  while (child) {
350  child.dump(OS, RecurseDepth-1, Indent+2);
351  child = child.getSibling();
352  }
353  }
354  } else {
355  OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
356  << abbrCode << '\n';
357  }
358  } else {
359  OS.indent(Indent) << "NULL\n";
360  }
361  }
362 }
363 
364 
366  const uint64_t Address, SmallVectorImpl<DWARFDie> &InlinedChain) const {
367  if (isNULL())
368  return;
369  DWARFDie DIE(*this);
370  while (DIE) {
371  // Append current DIE to inlined chain only if it has correct tag
372  // (e.g. it is not a lexical block).
373  if (DIE.isSubroutineDIE())
374  InlinedChain.push_back(DIE);
375 
376  // Try to get child which also contains provided address.
377  DWARFDie Child = DIE.getFirstChild();
378  while (Child) {
379  if (Child.addressRangeContainsAddress(Address)) {
380  // Assume there is only one such child.
381  break;
382  }
383  Child = Child.getSibling();
384  }
385  DIE = Child;
386  }
387  // Reverse the obtained chain to make the root of inlined chain last.
388  std::reverse(InlinedChain.begin(), InlinedChain.end());
389 }
390 
392  if (isValid())
393  return U->getParent(Die);
394  return DWARFDie();
395 }
396 
398  if (isValid())
399  return U->getSibling(Die);
400  return DWARFDie();
401 }
const NoneType None
Definition: None.h:23
StringRef ApplePropertyString(unsigned)
Definition: Dwarf.cpp:296
Optional< int64_t > getAttributeValueAsSignedConstant(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE as a signed integer.
Definition: DWARFDie.cpp:163
bool hasValue() const
Definition: Optional.h:125
DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE as the referenced DIE.
Definition: DWARFDie.cpp:192
DWARFAddressRangesVector getAddressRanges() const
Get the address ranges for this DIE.
Definition: DWARFDie.cpp:237
Optional< uint64_t > getHighPC(uint64_t LowPC) const
Get the DW_AT_high_pc attribute value as an address.
Definition: DWARFDie.cpp:210
uint64_t getBaseAddress() const
Definition: DWARFUnit.h:222
std::vector< std::pair< uint64_t, uint64_t > > DWARFAddressRangesVector
DWARFAddressRangesVector - represents a set of absolute address ranges.
Optional< DWARFFormValue > getAttributeValue(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Definition: DWARFDie.cpp:137
Attribute
Attributes.
Definition: Dwarf.h:94
void getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, uint32_t &CallColumn) const
Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column from DIE (or zeroes if the...
Definition: DWARFDie.cpp:308
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
void collectChildrenAddressRanges(DWARFAddressRangesVector &Ranges) const
Get all address ranges for any DW_TAG_subprogram DIEs in this DIE or any of its children.
Definition: DWARFDie.cpp:256
bool getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const
Retrieves DW_AT_low_pc and DW_AT_high_pc from CU.
Definition: DWARFDie.cpp:224
DINameKind
A DINameKind is passed to name search methods to specify a preference regarding the type of name reso...
Definition: DIContext.h:97
bool isValid() const
Definition: DWARFDie.h:43
bool addressRangeContainsAddress(const uint64_t Address) const
Definition: DWARFDie.cpp:268
bool isValidOffset(uint32_t offset) const
Test the validity of offset.
const char * getSubroutineName(DINameKind Kind) const
If a DIE represents a subprogram (or inlined subroutine), returns its mangled name (or short name...
Definition: DWARFDie.cpp:277
Optional< uint64_t > getAttributeValueAsAddress(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE as an address.
Definition: DWARFDie.cpp:156
StringRef FormEncodingString(unsigned Encoding)
Definition: Dwarf.cpp:58
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:32
static StringRef getName(Value *V)
DWARFDie getSibling(const DWARFDebugInfoEntry *Die)
Definition: DWARFUnit.cpp:404
const char * getAttributeValueAsString(dwarf::Attribute Attr, const char *FailValue) const
Extract the specified attribute from this DIE as a C string.
Definition: DWARFDie.cpp:146
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
Definition: STLExtras.h:241
DWARFDie getParent(const DWARFDebugInfoEntry *Die)
Definition: DWARFUnit.cpp:385
StringRef AttributeString(unsigned Attribute)
Definition: Dwarf.cpp:47
const T & getValue() const LLVM_LVALUE_FUNCTION
Definition: Optional.h:121
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
StringRef AttributeValueString(uint16_t Attr, unsigned Val)
Returns the symbolic string representing Val when used as a value for attribute Attr.
Definition: Dwarf.cpp:356
DWARFDie getParent() const
Get the parent of this DIE object.
Definition: DWARFDie.cpp:391
format_object< Ts...> format(const char *Fmt, const Ts &...Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
Optional< uint64_t > getAttributeValueAsSectionOffset(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE as absolute section offset.
Definition: DWARFDie.cpp:184
DWARFDie getSibling() const
Get the sibling of this DIE object.
Definition: DWARFDie.cpp:397
DWARFUnit * getDwarfUnit() const
Definition: DWARFDie.h:46
virtual DWARFUnit * getUnitForOffset(uint32_t Offset) const =0
Returns the Unit that contains the given section offset in the same section this Unit originated from...
Utility class that carries the DWARF compile/type unit and the debug info entry in an object...
Definition: DWARFDie.h:36
std::size_t countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the least significant bit to the most stopping at the first 1...
Definition: MathExtras.h:111
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:115
DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const
getAbsoluteRanges - Returns absolute address ranges defined by this range list.
A structured debug information entry.
Definition: DIE.h:655
void getInlinedChainForAddress(const uint64_t Address, SmallVectorImpl< DWARFDie > &InlinedChain) const
Get inlined chain for a given address, rooted at the current DIE.
Definition: DWARFDie.cpp:365
const DWARFUnitSectionBase & getUnitSection() const
getUnitSection - Return the DWARFUnitSection containing this unit.
Definition: DWARFUnit.h:247
uint32_t Offset
Optional< uint64_t > getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE as an unsigned integer.
Definition: DWARFDie.cpp:170
uint64_t getULEB128(uint32_t *offset_ptr) const
Extract a unsigned LEB128 value from *offset_ptr.
const char * getCompilationDir()
Definition: DWARFUnit.cpp:153
unsigned getTag(StringRef TagString)
Definition: Dwarf.cpp:32
void dump(raw_ostream &OS, unsigned recurseDepth, unsigned indent=0) const
Dump the DIE and all of its attributes to the supplied stream.
Definition: DWARFDie.cpp:316
DWARFDie getFirstChild() const
Get the first child of this DIE object.
Definition: DWARFDie.h:103
Color
A "color", which is either even or odd.
bool extractRangeList(uint32_t RangeListOffset, DWARFDebugRangeList &RangeList) const
extractRangeList - extracts the range list referenced by this compile unit from .debug_ranges section...
Definition: DWARFUnit.cpp:131
INITIALIZE_PASS(HexagonGenMux,"hexagon-mux","Hexagon generate mux instructions", false, false) void HexagonGenMux I isValid()
const char * getName(DINameKind Kind) const
Return the DIE name resolving DW_AT_sepcification or DW_AT_abstract_origin references if necessary...
Definition: DWARFDie.cpp:284
Optional< uint64_t > getAttributeValueAsReference(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE as absolute DIE Offset.
Definition: DWARFDie.cpp:177
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:130
Optional< uint64_t > getRangesBaseAttribute() const
Extract the range base attribute from this DIE as absolute section offset.
Definition: DWARFDie.cpp:203
bool isSubroutineDIE() const
Returns true if DIE represents a subprogram or an inlined subroutine.
Definition: DWARFDie.cpp:131
DWARFContext & getContext() const
Definition: DWARFUnit.h:166
bool isSubprogramDIE() const
Returns true if DIE represents a subprogram (not inlined).
Definition: DWARFDie.cpp:127
DataExtractor getDebugInfoExtractor() const
Definition: DWARFUnit.h:184
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:119
StringRef TagString(unsigned Tag)
Definition: Dwarf.cpp:21
uint8_t getAddressByteSize() const
Definition: DWARFUnit.h:211
const unsigned Kind
DWARFDie getDIEForOffset(uint32_t Offset)
Return the DIE object for a given offset inside the unit's DIE vector.
Definition: DWARFUnit.h:279
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const char * name
const DWARFDebugLine::LineTable * getLineTableForUnit(DWARFUnit *cu)
Get a pointer to a parsed line table corresponding to a compile unit.
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:44
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
An RAII object that temporarily switches an output stream to a specific color.