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