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 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsignedConstant( 273 const DWARFUnit *U, dwarf::Attribute Attr, 274 uint64_t FailValue) const { 275 DWARFFormValue FormValue; 276 if (!getAttributeValue(U, Attr, FormValue)) 277 return FailValue; 278 Optional<uint64_t> Result = FormValue.getAsUnsignedConstant(); 279 return Result.hasValue() ? Result.getValue() : FailValue; 280 } 281 282 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsReference( 283 const DWARFUnit *U, dwarf::Attribute Attr, 284 uint64_t FailValue) const { 285 DWARFFormValue FormValue; 286 if (!getAttributeValue(U, Attr, FormValue)) 287 return FailValue; 288 Optional<uint64_t> Result = FormValue.getAsReference(); 289 return Result.hasValue() ? Result.getValue() : FailValue; 290 } 291 292 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSectionOffset( 293 const DWARFUnit *U, dwarf::Attribute Attr, 294 uint64_t FailValue) const { 295 DWARFFormValue FormValue; 296 if (!getAttributeValue(U, Attr, FormValue)) 297 return FailValue; 298 Optional<uint64_t> Result = FormValue.getAsSectionOffset(); 299 return Result.hasValue() ? Result.getValue() : FailValue; 300 } 301 302 uint64_t 303 DWARFDebugInfoEntryMinimal::getRangesBaseAttribute(const DWARFUnit *U, 304 uint64_t FailValue) const { 305 uint64_t Result = 306 getAttributeValueAsSectionOffset(U, DW_AT_rnglists_base, -1ULL); 307 if (Result != -1ULL) 308 return Result; 309 return getAttributeValueAsSectionOffset(U, DW_AT_GNU_ranges_base, FailValue); 310 } 311 312 bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U, 313 uint64_t &LowPC, 314 uint64_t &HighPC) const { 315 LowPC = getAttributeValueAsAddress(U, DW_AT_low_pc, -1ULL); 316 if (LowPC == -1ULL) 317 return false; 318 HighPC = getAttributeValueAsAddress(U, DW_AT_high_pc, -1ULL); 319 if (HighPC == -1ULL) { 320 // Since DWARF4, DW_AT_high_pc may also be of class constant, in which case 321 // it represents function size. 322 HighPC = getAttributeValueAsUnsignedConstant(U, DW_AT_high_pc, -1ULL); 323 if (HighPC != -1ULL) 324 HighPC += LowPC; 325 } 326 return (HighPC != -1ULL); 327 } 328 329 DWARFAddressRangesVector 330 DWARFDebugInfoEntryMinimal::getAddressRanges(const DWARFUnit *U) const { 331 if (isNULL()) 332 return DWARFAddressRangesVector(); 333 // Single range specified by low/high PC. 334 uint64_t LowPC, HighPC; 335 if (getLowAndHighPC(U, LowPC, HighPC)) { 336 return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC)); 337 } 338 // Multiple ranges from .debug_ranges section. 339 uint32_t RangesOffset = 340 getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U); 341 if (RangesOffset != -1U) { 342 DWARFDebugRangeList RangeList; 343 if (U->extractRangeList(RangesOffset, RangeList)) 344 return RangeList.getAbsoluteRanges(U->getBaseAddress()); 345 } 346 return DWARFAddressRangesVector(); 347 } 348 349 void DWARFDebugInfoEntryMinimal::collectChildrenAddressRanges( 350 const DWARFUnit *U, DWARFAddressRangesVector& Ranges) const { 351 if (isNULL()) 352 return; 353 if (isSubprogramDIE()) { 354 const auto &DIERanges = getAddressRanges(U); 355 Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end()); 356 } 357 358 const DWARFDebugInfoEntryMinimal *Child = getFirstChild(); 359 while (Child) { 360 Child->collectChildrenAddressRanges(U, Ranges); 361 Child = Child->getSibling(); 362 } 363 } 364 365 bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress( 366 const DWARFUnit *U, const uint64_t Address) const { 367 for (const auto& R : getAddressRanges(U)) { 368 if (R.first <= Address && Address < R.second) 369 return true; 370 } 371 return false; 372 } 373 374 const char * 375 DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U, 376 DINameKind Kind) const { 377 if (!isSubroutineDIE()) 378 return nullptr; 379 return getName(U, Kind); 380 } 381 382 const char * 383 DWARFDebugInfoEntryMinimal::getName(const DWARFUnit *U, 384 DINameKind Kind) const { 385 if (Kind == DINameKind::None) 386 return nullptr; 387 // Try to get mangled name only if it was asked for. 388 if (Kind == DINameKind::LinkageName) { 389 if (const char *name = 390 getAttributeValueAsString(U, DW_AT_MIPS_linkage_name, nullptr)) 391 return name; 392 if (const char *name = 393 getAttributeValueAsString(U, DW_AT_linkage_name, nullptr)) 394 return name; 395 } 396 if (const char *name = getAttributeValueAsString(U, DW_AT_name, nullptr)) 397 return name; 398 // Try to get name from specification DIE. 399 uint32_t spec_ref = 400 getAttributeValueAsReference(U, DW_AT_specification, -1U); 401 if (spec_ref != -1U) { 402 DWARFDebugInfoEntryMinimal spec_die; 403 if (const DWARFUnit *RefU = findUnitAndExtractFast(spec_die, U, &spec_ref)) { 404 if (const char *name = spec_die.getName(RefU, Kind)) 405 return name; 406 } 407 } 408 // Try to get name from abstract origin DIE. 409 uint32_t abs_origin_ref = 410 getAttributeValueAsReference(U, DW_AT_abstract_origin, -1U); 411 if (abs_origin_ref != -1U) { 412 DWARFDebugInfoEntryMinimal abs_origin_die; 413 if (const DWARFUnit *RefU = findUnitAndExtractFast(abs_origin_die, U, 414 &abs_origin_ref)) { 415 if (const char *name = abs_origin_die.getName(RefU, Kind)) 416 return name; 417 } 418 } 419 return nullptr; 420 } 421 422 void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFUnit *U, 423 uint32_t &CallFile, 424 uint32_t &CallLine, 425 uint32_t &CallColumn) const { 426 CallFile = getAttributeValueAsUnsignedConstant(U, DW_AT_call_file, 0); 427 CallLine = getAttributeValueAsUnsignedConstant(U, DW_AT_call_line, 0); 428 CallColumn = getAttributeValueAsUnsignedConstant(U, DW_AT_call_column, 0); 429 } 430 431 DWARFDebugInfoEntryInlinedChain 432 DWARFDebugInfoEntryMinimal::getInlinedChainForAddress( 433 const DWARFUnit *U, const uint64_t Address) const { 434 DWARFDebugInfoEntryInlinedChain InlinedChain; 435 InlinedChain.U = U; 436 if (isNULL()) 437 return InlinedChain; 438 for (const DWARFDebugInfoEntryMinimal *DIE = this; DIE; ) { 439 // Append current DIE to inlined chain only if it has correct tag 440 // (e.g. it is not a lexical block). 441 if (DIE->isSubroutineDIE()) { 442 InlinedChain.DIEs.push_back(*DIE); 443 } 444 // Try to get child which also contains provided address. 445 const DWARFDebugInfoEntryMinimal *Child = DIE->getFirstChild(); 446 while (Child) { 447 if (Child->addressRangeContainsAddress(U, Address)) { 448 // Assume there is only one such child. 449 break; 450 } 451 Child = Child->getSibling(); 452 } 453 DIE = Child; 454 } 455 // Reverse the obtained chain to make the root of inlined chain last. 456 std::reverse(InlinedChain.DIEs.begin(), InlinedChain.DIEs.end()); 457 return InlinedChain; 458 } 459