LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DWARFDebugInfoEntry.cpp
Go to the documentation of this file.
1 //===-- DWARFDebugInfoEntry.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 "DWARFDebugInfoEntry.h"
11 #include "DWARFCompileUnit.h"
12 #include "DWARFContext.h"
13 #include "DWARFDebugAbbrev.h"
15 #include "llvm/Support/Debug.h"
16 #include "llvm/Support/Dwarf.h"
17 #include "llvm/Support/Format.h"
19 using namespace llvm;
20 using namespace dwarf;
21 
23  unsigned recurseDepth,
24  unsigned indent) const {
25  DataExtractor debug_info_data = u->getDebugInfoExtractor();
26  uint32_t offset = Offset;
27 
28  if (debug_info_data.isValidOffset(offset)) {
29  uint32_t abbrCode = debug_info_data.getULEB128(&offset);
30 
31  OS << format("\n0x%8.8x: ", Offset);
32  if (abbrCode) {
33  if (AbbrevDecl) {
34  const char *tagString = TagString(getTag());
35  if (tagString)
36  OS.indent(indent) << tagString;
37  else
38  OS.indent(indent) << format("DW_TAG_Unknown_%x", getTag());
39  OS << format(" [%u] %c\n", abbrCode,
40  AbbrevDecl->hasChildren() ? '*' : ' ');
41 
42  // Dump all data in the DIE for the attributes.
43  const uint32_t numAttributes = AbbrevDecl->getNumAttributes();
44  for (uint32_t i = 0; i != numAttributes; ++i) {
45  uint16_t attr = AbbrevDecl->getAttrByIndex(i);
46  uint16_t form = AbbrevDecl->getFormByIndex(i);
47  dumpAttribute(OS, u, &offset, attr, form, indent);
48  }
49 
50  const DWARFDebugInfoEntryMinimal *child = getFirstChild();
51  if (recurseDepth > 0 && child) {
52  while (child) {
53  child->dump(OS, u, recurseDepth-1, indent+2);
54  child = child->getSibling();
55  }
56  }
57  } else {
58  OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
59  << abbrCode << '\n';
60  }
61  } else {
62  OS.indent(indent) << "NULL\n";
63  }
64  }
65 }
66 
68  const DWARFUnit *u,
69  uint32_t *offset_ptr,
70  uint16_t attr, uint16_t form,
71  unsigned indent) const {
72  OS << " ";
73  OS.indent(indent+2);
74  const char *attrString = AttributeString(attr);
75  if (attrString)
76  OS << attrString;
77  else
78  OS << format("DW_AT_Unknown_%x", attr);
79  const char *formString = FormEncodingString(form);
80  if (formString)
81  OS << " [" << formString << ']';
82  else
83  OS << format(" [DW_FORM_Unknown_%x]", form);
84 
85  DWARFFormValue formValue(form);
86 
87  if (!formValue.extractValue(u->getDebugInfoExtractor(), offset_ptr, u))
88  return;
89 
90  OS << "\t(";
91  formValue.dump(OS, u);
92  OS << ")\n";
93 }
94 
96  uint32_t *OffsetPtr) {
97  Offset = *OffsetPtr;
98  DataExtractor DebugInfoData = U->getDebugInfoExtractor();
99  uint32_t UEndOffset = U->getNextUnitOffset();
100  if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset))
101  return false;
102  uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr);
103  if (0 == AbbrCode) {
104  // NULL debug tag entry.
105  AbbrevDecl = NULL;
106  return true;
107  }
108  AbbrevDecl = U->getAbbreviations()->getAbbreviationDeclaration(AbbrCode);
109  if (0 == AbbrevDecl) {
110  // Restore the original offset.
111  *OffsetPtr = Offset;
112  return false;
113  }
115  U->getAddressByteSize(), U->getVersion());
116  assert(FixedFormSizes.size() > 0);
117 
118  // Skip all data in the .debug_info for the attributes
119  for (uint32_t i = 0, n = AbbrevDecl->getNumAttributes(); i < n; ++i) {
120  uint16_t Form = AbbrevDecl->getFormByIndex(i);
121 
122  uint8_t FixedFormSize =
123  (Form < FixedFormSizes.size()) ? FixedFormSizes[Form] : 0;
124  if (FixedFormSize)
125  *OffsetPtr += FixedFormSize;
126  else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U)) {
127  // Restore the original offset.
128  *OffsetPtr = Offset;
129  return false;
130  }
131  }
132  return true;
133 }
134 
136  return getTag() == DW_TAG_subprogram;
137 }
138 
140  uint32_t Tag = getTag();
141  return Tag == DW_TAG_subprogram ||
142  Tag == DW_TAG_inlined_subroutine;
143 }
144 
146  const DWARFUnit *U, const uint16_t Attr, DWARFFormValue &FormValue) const {
147  if (!AbbrevDecl)
148  return false;
149 
150  uint32_t AttrIdx = AbbrevDecl->findAttributeIndex(Attr);
151  if (AttrIdx == -1U)
152  return false;
153 
154  DataExtractor DebugInfoData = U->getDebugInfoExtractor();
155  uint32_t DebugInfoOffset = getOffset();
156 
157  // Skip the abbreviation code so we are at the data for the attributes
158  DebugInfoData.getULEB128(&DebugInfoOffset);
159 
160  // Skip preceding attribute values.
161  for (uint32_t i = 0; i < AttrIdx; ++i) {
162  DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(i),
163  DebugInfoData, &DebugInfoOffset, U);
164  }
165 
166  FormValue = DWARFFormValue(AbbrevDecl->getFormByIndex(AttrIdx));
167  return FormValue.extractValue(DebugInfoData, &DebugInfoOffset, U);
168 }
169 
171  const DWARFUnit *U, const uint16_t Attr, const char *FailValue) const {
172  DWARFFormValue FormValue;
173  if (!getAttributeValue(U, Attr, FormValue))
174  return FailValue;
175  Optional<const char *> Result = FormValue.getAsCString(U);
176  return Result.hasValue() ? Result.getValue() : FailValue;
177 }
178 
180  const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
181  DWARFFormValue FormValue;
182  if (!getAttributeValue(U, Attr, FormValue))
183  return FailValue;
184  Optional<uint64_t> Result = FormValue.getAsAddress(U);
185  return Result.hasValue() ? Result.getValue() : FailValue;
186 }
187 
189  const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
190  DWARFFormValue FormValue;
191  if (!getAttributeValue(U, Attr, FormValue))
192  return FailValue;
193  Optional<uint64_t> Result = FormValue.getAsUnsignedConstant();
194  return Result.hasValue() ? Result.getValue() : FailValue;
195 }
196 
198  const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
199  DWARFFormValue FormValue;
200  if (!getAttributeValue(U, Attr, FormValue))
201  return FailValue;
202  Optional<uint64_t> Result = FormValue.getAsReference(U);
203  return Result.hasValue() ? Result.getValue() : FailValue;
204 }
205 
207  const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
208  DWARFFormValue FormValue;
209  if (!getAttributeValue(U, Attr, FormValue))
210  return FailValue;
211  Optional<uint64_t> Result = FormValue.getAsSectionOffset();
212  return Result.hasValue() ? Result.getValue() : FailValue;
213 }
214 
216  uint64_t &LowPC,
217  uint64_t &HighPC) const {
218  LowPC = getAttributeValueAsAddress(U, DW_AT_low_pc, -1ULL);
219  if (LowPC == -1ULL)
220  return false;
221  HighPC = getAttributeValueAsAddress(U, DW_AT_high_pc, -1ULL);
222  if (HighPC == -1ULL) {
223  // Since DWARF4, DW_AT_high_pc may also be of class constant, in which case
224  // it represents function size.
225  HighPC = getAttributeValueAsUnsignedConstant(U, DW_AT_high_pc, -1ULL);
226  if (HighPC != -1ULL)
227  HighPC += LowPC;
228  }
229  return (HighPC != -1ULL);
230 }
231 
233  const DWARFUnit *U, DWARFDebugAranges *DebugAranges,
234  uint32_t UOffsetInAranges) const {
235  if (AbbrevDecl) {
236  if (isSubprogramDIE()) {
237  uint64_t LowPC, HighPC;
238  if (getLowAndHighPC(U, LowPC, HighPC))
239  DebugAranges->appendRange(UOffsetInAranges, LowPC, HighPC);
240  // FIXME: try to append ranges from .debug_ranges section.
241  }
242 
243  const DWARFDebugInfoEntryMinimal *Child = getFirstChild();
244  while (Child) {
245  Child->buildAddressRangeTable(U, DebugAranges, UOffsetInAranges);
246  Child = Child->getSibling();
247  }
248  }
249 }
250 
252  const DWARFUnit *U, const uint64_t Address) const {
253  if (isNULL())
254  return false;
255  uint64_t LowPC, HighPC;
256  if (getLowAndHighPC(U, LowPC, HighPC))
257  return (LowPC <= Address && Address <= HighPC);
258  // Try to get address ranges from .debug_ranges section.
259  uint32_t RangesOffset =
260  getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U);
261  if (RangesOffset != -1U) {
262  DWARFDebugRangeList RangeList;
263  if (U->extractRangeList(RangesOffset, RangeList))
264  return RangeList.containsAddress(U->getBaseAddress(), Address);
265  }
266  return false;
267 }
268 
269 const char *
271  if (!isSubroutineDIE())
272  return 0;
273  // Try to get mangled name if possible.
274  if (const char *name =
275  getAttributeValueAsString(U, DW_AT_MIPS_linkage_name, 0))
276  return name;
277  if (const char *name = getAttributeValueAsString(U, DW_AT_linkage_name, 0))
278  return name;
279  if (const char *name = getAttributeValueAsString(U, DW_AT_name, 0))
280  return name;
281  // Try to get name from specification DIE.
282  uint32_t spec_ref =
283  getAttributeValueAsReference(U, DW_AT_specification, -1U);
284  if (spec_ref != -1U) {
286  if (spec_die.extractFast(U, &spec_ref)) {
287  if (const char *name = spec_die.getSubroutineName(U))
288  return name;
289  }
290  }
291  // Try to get name from abstract origin DIE.
292  uint32_t abs_origin_ref =
293  getAttributeValueAsReference(U, DW_AT_abstract_origin, -1U);
294  if (abs_origin_ref != -1U) {
295  DWARFDebugInfoEntryMinimal abs_origin_die;
296  if (abs_origin_die.extractFast(U, &abs_origin_ref)) {
297  if (const char *name = abs_origin_die.getSubroutineName(U))
298  return name;
299  }
300  }
301  return 0;
302 }
303 
305  uint32_t &CallFile,
306  uint32_t &CallLine,
307  uint32_t &CallColumn) const {
308  CallFile = getAttributeValueAsUnsignedConstant(U, DW_AT_call_file, 0);
309  CallLine = getAttributeValueAsUnsignedConstant(U, DW_AT_call_line, 0);
310  CallColumn = getAttributeValueAsUnsignedConstant(U, DW_AT_call_column, 0);
311 }
312 
315  const DWARFUnit *U, const uint64_t Address) const {
316  DWARFDebugInfoEntryInlinedChain InlinedChain;
317  InlinedChain.U = U;
318  if (isNULL())
319  return InlinedChain;
320  for (const DWARFDebugInfoEntryMinimal *DIE = this; DIE; ) {
321  // Append current DIE to inlined chain only if it has correct tag
322  // (e.g. it is not a lexical block).
323  if (DIE->isSubroutineDIE()) {
324  InlinedChain.DIEs.push_back(*DIE);
325  }
326  // Try to get child which also contains provided address.
327  const DWARFDebugInfoEntryMinimal *Child = DIE->getFirstChild();
328  while (Child) {
329  if (Child->addressRangeContainsAddress(U, Address)) {
330  // Assume there is only one such child.
331  break;
332  }
333  Child = Child->getSibling();
334  }
335  DIE = Child;
336  }
337  // Reverse the obtained chain to make the root of inlined chain last.
338  std::reverse(InlinedChain.DIEs.begin(), InlinedChain.DIEs.end());
339  return InlinedChain;
340 }
Optional< const char * > getAsCString(const DWARFUnit *U) const
const char * FormEncodingString(unsigned Encoding)
Definition: Dwarf.cpp:266
void dumpAttribute(raw_ostream &OS, const DWARFUnit *u, uint32_t *offset_ptr, uint16_t attr, uint16_t form, unsigned indent=0) const
bool hasValue() const
Definition: Optional.h:119
static ArrayRef< uint8_t > getFixedFormSizes(uint8_t AddrSize, uint16_t Version)
uint64_t getBaseAddress() const
Definition: DWARFUnit.h:118
uint64_t getAttributeValueAsAddress(const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(const DWARFUnit *U, const uint64_t Address) const
bool extractRangeList(uint32_t RangeListOffset, DWARFDebugRangeList &RangeList) const
Definition: DWARFUnit.cpp:88
uint32_t getNextUnitOffset() const
Definition: DWARFUnit.h:109
void dump(raw_ostream &OS, const DWARFUnit *U) const
bool isValidOffset(uint32_t offset) const
bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, const DWARFUnit *u) const
const DWARFAbbreviationDeclarationSet * getAbbreviations() const
Definition: DWARFUnit.h:114
const char * getSubroutineName(const DWARFUnit *U) const
const char * getAttributeValueAsString(const DWARFUnit *U, const uint16_t Attr, const char *FailValue) const
format_object1< T > format(const char *Fmt, const T &Val)
Definition: Format.h:180
bool extractValue(DataExtractor data, uint32_t *offset_ptr, const DWARFUnit *u)
const T & getValue() const LLVM_LVALUE_FUNCTION
Definition: Optional.h:115
bool addressRangeContainsAddress(const DWARFUnit *U, const uint64_t Address) const
const DWARFAbbreviationDeclaration * getAbbreviationDeclaration(uint32_t abbrCode) const
SmallVector< DWARFDebugInfoEntryMinimal, 4 > DIEs
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:109
uint64_t getAttributeValueAsReference(const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const
uint16_t getVersion() const
Definition: DWARFUnit.h:113
DWARFDebugInfoEntryMinimal * getSibling()
DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data.
Definition: DIE.h:109
Optional< uint64_t > getAsReference(const DWARFUnit *U) const
Optional< uint64_t > getAsUnsignedConstant() const
uint64_t getULEB128(uint32_t *offset_ptr) const
const char * TagString(unsigned Tag)
Definition: Dwarf.cpp:22
bool containsAddress(uint64_t BaseAddress, uint64_t Address) const
void buildAddressRangeTable(const DWARFUnit *U, DWARFDebugAranges *DebugAranges, uint32_t CUOffsetInAranges) const
uint64_t getAttributeValueAsUnsignedConstant(const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const
uint64_t getAttributeValueAsSectionOffset(const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const
void getCallerFrame(const DWARFUnit *U, uint32_t &CallFile, uint32_t &CallLine, uint32_t &CallColumn) const
const char * AttributeString(unsigned Attribute)
Definition: Dwarf.cpp:115
DataExtractor getDebugInfoExtractor() const
Definition: DWARFUnit.h:88
void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC)
void dump(raw_ostream &OS, const DWARFUnit *u, unsigned recurseDepth, unsigned indent=0) const
Optional< uint64_t > getAsSectionOffset() const
uint8_t getAddressByteSize() const
Definition: DWARFUnit.h:117
bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC, uint64_t &HighPC) const
bool isSubprogramDIE() const
Returns true if DIE represents a subprogram (not inlined).
bool getAttributeValue(const DWARFUnit *U, const uint16_t Attr, DWARFFormValue &FormValue) const
bool extractFast(const DWARFUnit *U, uint32_t *OffsetPtr)
Optional< uint64_t > getAsAddress(const DWARFUnit *U) const