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, u); 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(u); 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 Offset = *OffsetPtr; 189 DataExtractor DebugInfoData = U->getDebugInfoExtractor(); 190 uint32_t UEndOffset = U->getNextUnitOffset(); 191 if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset)) 192 return false; 193 uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr); 194 if (0 == AbbrCode) { 195 // NULL debug tag entry. 196 AbbrevDecl = nullptr; 197 return true; 198 } 199 AbbrevDecl = U->getAbbreviations()->getAbbreviationDeclaration(AbbrCode); 200 if (nullptr == AbbrevDecl) { 201 // Restore the original offset. 202 *OffsetPtr = Offset; 203 return false; 204 } 205 ArrayRef<uint8_t> FixedFormSizes = DWARFFormValue::getFixedFormSizes( 206 U->getAddressByteSize(), U->getVersion()); 207 assert(FixedFormSizes.size() > 0); 208 209 // Skip all data in the .debug_info for the attributes 210 for (const auto &AttrSpec : AbbrevDecl->attributes()) { 211 auto Form = AttrSpec.Form; 212 213 uint8_t FixedFormSize = 214 (Form < FixedFormSizes.size()) ? FixedFormSizes[Form] : 0; 215 if (FixedFormSize) 216 *OffsetPtr += FixedFormSize; 217 else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U)) { 218 // Restore the original offset. 219 *OffsetPtr = Offset; 220 return false; 221 } 222 } 223 return true; 224 } 225 226 bool DWARFDebugInfoEntryMinimal::isSubprogramDIE() const { 227 return getTag() == DW_TAG_subprogram; 228 } 229 230 bool DWARFDebugInfoEntryMinimal::isSubroutineDIE() const { 231 uint32_t Tag = getTag(); 232 return Tag == DW_TAG_subprogram || 233 Tag == DW_TAG_inlined_subroutine; 234 } 235 236 bool DWARFDebugInfoEntryMinimal::getAttributeValue(const DWARFUnit *U, 237 dwarf::Attribute Attr, DWARFFormValue &FormValue) const { 238 if (!AbbrevDecl) 239 return false; 240 241 uint32_t AttrIdx = AbbrevDecl->findAttributeIndex(Attr); 242 if (AttrIdx == -1U) 243 return false; 244 245 DataExtractor DebugInfoData = U->getDebugInfoExtractor(); 246 uint32_t DebugInfoOffset = getOffset(); 247 248 // Skip the abbreviation code so we are at the data for the attributes 249 DebugInfoData.getULEB128(&DebugInfoOffset); 250 251 // Skip preceding attribute values. 252 for (uint32_t i = 0; i < AttrIdx; ++i) { 253 DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(i), 254 DebugInfoData, &DebugInfoOffset, U); 255 } 256 257 FormValue = DWARFFormValue(AbbrevDecl->getFormByIndex(AttrIdx)); 258 return FormValue.extractValue(DebugInfoData, &DebugInfoOffset, U); 259 } 260 261 const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString( 262 const DWARFUnit *U, dwarf::Attribute Attr, 263 const char *FailValue) const { 264 DWARFFormValue FormValue; 265 if (!getAttributeValue(U, Attr, FormValue)) 266 return FailValue; 267 Optional<const char *> Result = FormValue.getAsCString(U); 268 return Result.hasValue() ? Result.getValue() : FailValue; 269 } 270 271 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress( 272 const DWARFUnit *U, dwarf::Attribute Attr, 273 uint64_t FailValue) const { 274 DWARFFormValue FormValue; 275 if (!getAttributeValue(U, Attr, FormValue)) 276 return FailValue; 277 Optional<uint64_t> Result = FormValue.getAsAddress(U); 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(U); 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