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