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