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 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 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 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 127 bool DWARFDie::isSubprogramDIE() const { 128 return getTag() == DW_TAG_subprogram; 129 } 130 131 bool DWARFDie::isSubroutineDIE() const { 132 auto Tag = getTag(); 133 return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine; 134 } 135 136 Optional<DWARFFormValue> 137 DWARFDie::getAttributeValue(dwarf::Attribute Attr) const { 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 146 const char *DWARFDie::getAttributeValueAsString(dwarf::Attribute Attr, 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 155 Optional<uint64_t> 156 DWARFDie::getAttributeValueAsAddress(dwarf::Attribute Attr) const { 157 if (auto FormValue = getAttributeValue(Attr)) 158 return FormValue->getAsAddress(); 159 return None; 160 } 161 162 Optional<int64_t> 163 DWARFDie::getAttributeValueAsSignedConstant(dwarf::Attribute Attr) const { 164 if (auto FormValue = getAttributeValue(Attr)) 165 return FormValue->getAsSignedConstant(); 166 return None; 167 } 168 169 Optional<uint64_t> 170 DWARFDie::getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const { 171 if (auto FormValue = getAttributeValue(Attr)) 172 return FormValue->getAsUnsignedConstant(); 173 return None; 174 } 175 176 Optional<uint64_t> 177 DWARFDie::getAttributeValueAsReference(dwarf::Attribute Attr) const { 178 if (auto FormValue = getAttributeValue(Attr)) 179 return FormValue->getAsReference(); 180 return None; 181 } 182 183 Optional<uint64_t> 184 DWARFDie::getAttributeValueAsSectionOffset(dwarf::Attribute Attr) const { 185 if (auto FormValue = getAttributeValue(Attr)) 186 return FormValue->getAsSectionOffset(); 187 return None; 188 } 189 190 191 DWARFDie 192 DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { 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 202 Optional<uint64_t> 203 DWARFDie::getRangesBaseAttribute() const { 204 auto Result = getAttributeValueAsSectionOffset(DW_AT_rnglists_base); 205 if (Result) 206 return Result; 207 return getAttributeValueAsSectionOffset(DW_AT_GNU_ranges_base); 208 } 209 210 Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const { 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 236 DWARFAddressRangesVector 237 DWARFDie::getAddressRanges() const { 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 256 DWARFDie::collectChildrenAddressRanges(DWARFAddressRangesVector& Ranges) const { 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 * 277 DWARFDie::getSubroutineName(DINameKind Kind) const { 278 if (!isSubroutineDIE()) 279 return nullptr; 280 return getName(Kind); 281 } 282 283 const char * 284 DWARFDie::getName(DINameKind Kind) const { 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 365 void DWARFDie::getInlinedChainForAddress( 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 391 DWARFDie DWARFDie::getParent() const { 392 if (isValid()) 393 return U->getParent(Die); 394 return DWARFDie(); 395 } 396 397 DWARFDie DWARFDie::getSibling() const { 398 if (isValid()) 399 return U->getSibling(Die); 400 return DWARFDie(); 401 } 402