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 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 206 // Skip all data in the .debug_info for the attributes 207 for (const auto &AttrSpec : AbbrevDecl->attributes()) { 208 auto Form = AttrSpec.Form; 209 210 if (Optional<uint8_t> FixedSize = DWARFFormValue::getFixedByteSize(Form, U)) 211 *OffsetPtr += *FixedSize; 212 else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U)) { 213 // Restore the original offset. 214 *OffsetPtr = Offset; 215 return false; 216 } 217 } 218 return true; 219 } 220 221 bool DWARFDebugInfoEntryMinimal::isSubprogramDIE() const { 222 return getTag() == DW_TAG_subprogram; 223 } 224 225 bool DWARFDebugInfoEntryMinimal::isSubroutineDIE() const { 226 uint32_t Tag = getTag(); 227 return Tag == DW_TAG_subprogram || 228 Tag == DW_TAG_inlined_subroutine; 229 } 230 231 bool DWARFDebugInfoEntryMinimal::getAttributeValue(const DWARFUnit *U, 232 dwarf::Attribute Attr, DWARFFormValue &FormValue) const { 233 if (!AbbrevDecl) 234 return false; 235 236 uint32_t AttrIdx = AbbrevDecl->findAttributeIndex(Attr); 237 if (AttrIdx == -1U) 238 return false; 239 240 DataExtractor DebugInfoData = U->getDebugInfoExtractor(); 241 uint32_t DebugInfoOffset = getOffset(); 242 243 // Skip the abbreviation code so we are at the data for the attributes 244 DebugInfoData.getULEB128(&DebugInfoOffset); 245 246 // Skip preceding attribute values. 247 for (uint32_t i = 0; i < AttrIdx; ++i) { 248 DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(i), 249 DebugInfoData, &DebugInfoOffset, U); 250 } 251 252 FormValue = DWARFFormValue(AbbrevDecl->getFormByIndex(AttrIdx)); 253 return FormValue.extractValue(DebugInfoData, &DebugInfoOffset, U); 254 } 255 256 const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString( 257 const DWARFUnit *U, dwarf::Attribute Attr, 258 const char *FailValue) const { 259 DWARFFormValue FormValue; 260 if (!getAttributeValue(U, Attr, FormValue)) 261 return FailValue; 262 Optional<const char *> Result = FormValue.getAsCString(); 263 return Result.hasValue() ? Result.getValue() : FailValue; 264 } 265 266 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress( 267 const DWARFUnit *U, dwarf::Attribute Attr, 268 uint64_t FailValue) const { 269 DWARFFormValue FormValue; 270 if (!getAttributeValue(U, Attr, FormValue)) 271 return FailValue; 272 Optional<uint64_t> Result = FormValue.getAsAddress(); 273 return Result.hasValue() ? Result.getValue() : FailValue; 274 } 275 276 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsignedConstant( 277 const DWARFUnit *U, dwarf::Attribute Attr, 278 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 286 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsReference( 287 const DWARFUnit *U, dwarf::Attribute Attr, 288 uint64_t FailValue) const { 289 DWARFFormValue FormValue; 290 if (!getAttributeValue(U, Attr, FormValue)) 291 return FailValue; 292 Optional<uint64_t> Result = FormValue.getAsReference(); 293 return Result.hasValue() ? Result.getValue() : FailValue; 294 } 295 296 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSectionOffset( 297 const DWARFUnit *U, dwarf::Attribute Attr, 298 uint64_t FailValue) const { 299 DWARFFormValue FormValue; 300 if (!getAttributeValue(U, Attr, FormValue)) 301 return FailValue; 302 Optional<uint64_t> Result = FormValue.getAsSectionOffset(); 303 return Result.hasValue() ? Result.getValue() : FailValue; 304 } 305 306 uint64_t 307 DWARFDebugInfoEntryMinimal::getRangesBaseAttribute(const DWARFUnit *U, 308 uint64_t FailValue) const { 309 uint64_t Result = 310 getAttributeValueAsSectionOffset(U, DW_AT_rnglists_base, -1ULL); 311 if (Result != -1ULL) 312 return Result; 313 return getAttributeValueAsSectionOffset(U, DW_AT_GNU_ranges_base, FailValue); 314 } 315 316 bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U, 317 uint64_t &LowPC, 318 uint64_t &HighPC) const { 319 LowPC = getAttributeValueAsAddress(U, DW_AT_low_pc, -1ULL); 320 if (LowPC == -1ULL) 321 return false; 322 HighPC = getAttributeValueAsAddress(U, DW_AT_high_pc, -1ULL); 323 if (HighPC == -1ULL) { 324 // Since DWARF4, DW_AT_high_pc may also be of class constant, in which case 325 // it represents function size. 326 HighPC = getAttributeValueAsUnsignedConstant(U, DW_AT_high_pc, -1ULL); 327 if (HighPC != -1ULL) 328 HighPC += LowPC; 329 } 330 return (HighPC != -1ULL); 331 } 332 333 DWARFAddressRangesVector 334 DWARFDebugInfoEntryMinimal::getAddressRanges(const DWARFUnit *U) const { 335 if (isNULL()) 336 return DWARFAddressRangesVector(); 337 // Single range specified by low/high PC. 338 uint64_t LowPC, HighPC; 339 if (getLowAndHighPC(U, LowPC, HighPC)) { 340 return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC)); 341 } 342 // Multiple ranges from .debug_ranges section. 343 uint32_t RangesOffset = 344 getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U); 345 if (RangesOffset != -1U) { 346 DWARFDebugRangeList RangeList; 347 if (U->extractRangeList(RangesOffset, RangeList)) 348 return RangeList.getAbsoluteRanges(U->getBaseAddress()); 349 } 350 return DWARFAddressRangesVector(); 351 } 352 353 void DWARFDebugInfoEntryMinimal::collectChildrenAddressRanges( 354 const DWARFUnit *U, DWARFAddressRangesVector& Ranges) const { 355 if (isNULL()) 356 return; 357 if (isSubprogramDIE()) { 358 const auto &DIERanges = getAddressRanges(U); 359 Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end()); 360 } 361 362 const DWARFDebugInfoEntryMinimal *Child = getFirstChild(); 363 while (Child) { 364 Child->collectChildrenAddressRanges(U, Ranges); 365 Child = Child->getSibling(); 366 } 367 } 368 369 bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress( 370 const DWARFUnit *U, const uint64_t Address) const { 371 for (const auto& R : getAddressRanges(U)) { 372 if (R.first <= Address && Address < R.second) 373 return true; 374 } 375 return false; 376 } 377 378 const char * 379 DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U, 380 DINameKind Kind) const { 381 if (!isSubroutineDIE()) 382 return nullptr; 383 return getName(U, Kind); 384 } 385 386 const char * 387 DWARFDebugInfoEntryMinimal::getName(const DWARFUnit *U, 388 DINameKind Kind) const { 389 if (Kind == DINameKind::None) 390 return nullptr; 391 // Try to get mangled name only if it was asked for. 392 if (Kind == DINameKind::LinkageName) { 393 if (const char *name = 394 getAttributeValueAsString(U, DW_AT_MIPS_linkage_name, nullptr)) 395 return name; 396 if (const char *name = 397 getAttributeValueAsString(U, DW_AT_linkage_name, nullptr)) 398 return name; 399 } 400 if (const char *name = getAttributeValueAsString(U, DW_AT_name, nullptr)) 401 return name; 402 // Try to get name from specification DIE. 403 uint32_t spec_ref = 404 getAttributeValueAsReference(U, DW_AT_specification, -1U); 405 if (spec_ref != -1U) { 406 DWARFDebugInfoEntryMinimal spec_die; 407 if (const DWARFUnit *RefU = findUnitAndExtractFast(spec_die, U, &spec_ref)) { 408 if (const char *name = spec_die.getName(RefU, Kind)) 409 return name; 410 } 411 } 412 // Try to get name from abstract origin DIE. 413 uint32_t abs_origin_ref = 414 getAttributeValueAsReference(U, DW_AT_abstract_origin, -1U); 415 if (abs_origin_ref != -1U) { 416 DWARFDebugInfoEntryMinimal abs_origin_die; 417 if (const DWARFUnit *RefU = findUnitAndExtractFast(abs_origin_die, U, 418 &abs_origin_ref)) { 419 if (const char *name = abs_origin_die.getName(RefU, Kind)) 420 return name; 421 } 422 } 423 return nullptr; 424 } 425 426 void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFUnit *U, 427 uint32_t &CallFile, 428 uint32_t &CallLine, 429 uint32_t &CallColumn) const { 430 CallFile = getAttributeValueAsUnsignedConstant(U, DW_AT_call_file, 0); 431 CallLine = getAttributeValueAsUnsignedConstant(U, DW_AT_call_line, 0); 432 CallColumn = getAttributeValueAsUnsignedConstant(U, DW_AT_call_column, 0); 433 } 434 435 DWARFDebugInfoEntryInlinedChain 436 DWARFDebugInfoEntryMinimal::getInlinedChainForAddress( 437 const DWARFUnit *U, const uint64_t Address) const { 438 DWARFDebugInfoEntryInlinedChain InlinedChain; 439 InlinedChain.U = U; 440 if (isNULL()) 441 return InlinedChain; 442 for (const DWARFDebugInfoEntryMinimal *DIE = this; DIE; ) { 443 // Append current DIE to inlined chain only if it has correct tag 444 // (e.g. it is not a lexical block). 445 if (DIE->isSubroutineDIE()) { 446 InlinedChain.DIEs.push_back(*DIE); 447 } 448 // Try to get child which also contains provided address. 449 const DWARFDebugInfoEntryMinimal *Child = DIE->getFirstChild(); 450 while (Child) { 451 if (Child->addressRangeContainsAddress(U, Address)) { 452 // Assume there is only one such child. 453 break; 454 } 455 Child = Child->getSibling(); 456 } 457 DIE = Child; 458 } 459 // Reverse the obtained chain to make the root of inlined chain last. 460 std::reverse(InlinedChain.DIEs.begin(), InlinedChain.DIEs.end()); 461 return InlinedChain; 462 } 463