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