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