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