1 //===- DWARFDie.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 "llvm/DebugInfo/DWARF/DWARFDie.h" 11 #include "SyntaxHighlighting.h" 12 #include "llvm/ADT/None.h" 13 #include "llvm/ADT/Optional.h" 14 #include "llvm/ADT/StringRef.h" 15 #include "llvm/BinaryFormat/Dwarf.h" 16 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" 17 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 18 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" 19 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 20 #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 21 #include "llvm/Support/DataExtractor.h" 22 #include "llvm/Support/Format.h" 23 #include "llvm/Support/MathExtras.h" 24 #include "llvm/Support/raw_ostream.h" 25 #include <algorithm> 26 #include <cassert> 27 #include <cinttypes> 28 #include <cstdint> 29 #include <string> 30 #include <utility> 31 32 using namespace llvm; 33 using namespace dwarf; 34 using namespace syntax; 35 36 static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) { 37 OS << " ("; 38 do { 39 uint64_t Shift = countTrailingZeros(Val); 40 assert(Shift < 64 && "undefined behavior"); 41 uint64_t Bit = 1ULL << Shift; 42 auto PropName = ApplePropertyString(Bit); 43 if (!PropName.empty()) 44 OS << PropName; 45 else 46 OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit); 47 if (!(Val ^= Bit)) 48 break; 49 OS << ", "; 50 } while (true); 51 OS << ")"; 52 } 53 54 static void dumpRanges(raw_ostream &OS, const DWARFAddressRangesVector& Ranges, 55 unsigned AddressSize, unsigned Indent) { 56 if (Ranges.empty()) 57 return; 58 59 for (const auto &Range: Ranges) { 60 OS << '\n'; 61 OS.indent(Indent); 62 OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")", 63 AddressSize*2, Range.LowPC, 64 AddressSize*2, Range.HighPC); 65 } 66 } 67 68 static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, 69 uint32_t *OffsetPtr, dwarf::Attribute Attr, 70 dwarf::Form Form, unsigned Indent, 71 DIDumpOptions DumpOpts) { 72 if (!Die.isValid()) 73 return; 74 const char BaseIndent[] = " "; 75 OS << BaseIndent; 76 OS.indent(Indent+2); 77 auto attrString = AttributeString(Attr); 78 if (!attrString.empty()) 79 WithColor(OS, syntax::Attribute) << attrString; 80 else 81 WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", Attr); 82 83 if (!DumpOpts.Brief) { 84 auto formString = FormEncodingString(Form); 85 if (!formString.empty()) 86 OS << " [" << formString << ']'; 87 else 88 OS << format(" [DW_FORM_Unknown_%x]", Form); 89 } 90 91 DWARFUnit *U = Die.getDwarfUnit(); 92 DWARFFormValue formValue(Form); 93 94 if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, U)) 95 return; 96 97 OS << "\t("; 98 99 StringRef Name; 100 std::string File; 101 auto Color = syntax::Enumerator; 102 if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) { 103 Color = syntax::String; 104 if (const auto *LT = U->getContext().getLineTableForUnit(U)) 105 if (LT->getFileNameByIndex(formValue.getAsUnsignedConstant().getValue(), U->getCompilationDir(), DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) { 106 File = '"' + File + '"'; 107 Name = File; 108 } 109 } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant()) 110 Name = AttributeValueString(Attr, *Val); 111 112 if (!Name.empty()) 113 WithColor(OS, Color) << Name; 114 else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line) 115 OS << *formValue.getAsUnsignedConstant(); 116 else 117 formValue.dump(OS); 118 119 // We have dumped the attribute raw value. For some attributes 120 // having both the raw value and the pretty-printed value is 121 // interesting. These attributes are handled below. 122 if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin) { 123 if (const char *Name = Die.getAttributeValueAsReferencedDie(Attr).getName(DINameKind::LinkageName)) 124 OS << " \"" << Name << '\"'; 125 } else if (Attr == DW_AT_APPLE_property_attribute) { 126 if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant()) 127 dumpApplePropertyAttribute(OS, *OptVal); 128 } else if (Attr == DW_AT_ranges) { 129 dumpRanges(OS, Die.getAddressRanges(), U->getAddressByteSize(), 130 sizeof(BaseIndent)+Indent+4); 131 } 132 133 OS << ")\n"; 134 } 135 136 bool DWARFDie::isSubprogramDIE() const { 137 return getTag() == DW_TAG_subprogram; 138 } 139 140 bool DWARFDie::isSubroutineDIE() const { 141 auto Tag = getTag(); 142 return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine; 143 } 144 145 Optional<DWARFFormValue> 146 DWARFDie::find(dwarf::Attribute Attr) const { 147 if (!isValid()) 148 return None; 149 auto AbbrevDecl = getAbbreviationDeclarationPtr(); 150 if (AbbrevDecl) 151 return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U); 152 return None; 153 } 154 155 Optional<DWARFFormValue> 156 DWARFDie::find(ArrayRef<dwarf::Attribute> Attrs) const { 157 if (!isValid()) 158 return None; 159 auto AbbrevDecl = getAbbreviationDeclarationPtr(); 160 if (AbbrevDecl) { 161 for (auto Attr : Attrs) { 162 if (auto Value = AbbrevDecl->getAttributeValue(getOffset(), Attr, *U)) 163 return Value; 164 } 165 } 166 return None; 167 } 168 169 Optional<DWARFFormValue> 170 DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const { 171 if (!isValid()) 172 return None; 173 auto Die = *this; 174 if (auto Value = Die.find(Attrs)) 175 return Value; 176 if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) 177 Die = D; 178 if (auto Value = Die.find(Attrs)) 179 return Value; 180 if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification)) 181 Die = D; 182 if (auto Value = Die.find(Attrs)) 183 return Value; 184 return None; 185 } 186 187 DWARFDie 188 DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { 189 auto SpecRef = toReference(find(Attr)); 190 if (SpecRef) { 191 auto SpecUnit = U->getUnitSection().getUnitForOffset(*SpecRef); 192 if (SpecUnit) 193 return SpecUnit->getDIEForOffset(*SpecRef); 194 } 195 return DWARFDie(); 196 } 197 198 Optional<uint64_t> 199 DWARFDie::getRangesBaseAttribute() const { 200 return toSectionOffset(find({DW_AT_rnglists_base, DW_AT_GNU_ranges_base})); 201 } 202 203 Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const { 204 if (auto FormValue = find(DW_AT_high_pc)) { 205 if (auto Address = FormValue->getAsAddress()) { 206 // High PC is an address. 207 return Address; 208 } 209 if (auto Offset = FormValue->getAsUnsignedConstant()) { 210 // High PC is an offset from LowPC. 211 return LowPC + *Offset; 212 } 213 } 214 return None; 215 } 216 217 bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, 218 uint64_t &SectionIndex) const { 219 auto F = find(DW_AT_low_pc); 220 auto LowPcAddr = toAddress(F); 221 if (!LowPcAddr) 222 return false; 223 if (auto HighPcAddr = getHighPC(*LowPcAddr)) { 224 LowPC = *LowPcAddr; 225 HighPC = *HighPcAddr; 226 SectionIndex = F->getSectionIndex(); 227 return true; 228 } 229 return false; 230 } 231 232 DWARFAddressRangesVector 233 DWARFDie::getAddressRanges() const { 234 if (isNULL()) 235 return DWARFAddressRangesVector(); 236 // Single range specified by low/high PC. 237 uint64_t LowPC, HighPC, Index; 238 if (getLowAndHighPC(LowPC, HighPC, Index)) 239 return {{LowPC, HighPC, Index}}; 240 241 // Multiple ranges from .debug_ranges section. 242 auto RangesOffset = toSectionOffset(find(DW_AT_ranges)); 243 if (RangesOffset) { 244 DWARFDebugRangeList RangeList; 245 if (U->extractRangeList(*RangesOffset, RangeList)) 246 return RangeList.getAbsoluteRanges(U->getBaseAddress()); 247 } 248 return DWARFAddressRangesVector(); 249 } 250 251 void 252 DWARFDie::collectChildrenAddressRanges(DWARFAddressRangesVector& Ranges) const { 253 if (isNULL()) 254 return; 255 if (isSubprogramDIE()) { 256 const auto &DIERanges = getAddressRanges(); 257 Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end()); 258 } 259 260 for (auto Child: children()) 261 Child.collectChildrenAddressRanges(Ranges); 262 } 263 264 bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const { 265 for (const auto& R : getAddressRanges()) { 266 if (R.LowPC <= Address && Address < R.HighPC) 267 return true; 268 } 269 return false; 270 } 271 272 const char * 273 DWARFDie::getSubroutineName(DINameKind Kind) const { 274 if (!isSubroutineDIE()) 275 return nullptr; 276 return getName(Kind); 277 } 278 279 const char * 280 DWARFDie::getName(DINameKind Kind) const { 281 if (!isValid() || Kind == DINameKind::None) 282 return nullptr; 283 // Try to get mangled name only if it was asked for. 284 if (Kind == DINameKind::LinkageName) { 285 if (auto Name = dwarf::toString(findRecursively({DW_AT_MIPS_linkage_name, 286 DW_AT_linkage_name}), nullptr)) 287 return Name; 288 } 289 if (auto Name = dwarf::toString(findRecursively(DW_AT_name), nullptr)) 290 return Name; 291 return nullptr; 292 } 293 294 uint64_t DWARFDie::getDeclLine() const { 295 return toUnsigned(findRecursively(DW_AT_decl_line), 0); 296 } 297 298 void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, 299 uint32_t &CallColumn, 300 uint32_t &CallDiscriminator) const { 301 CallFile = toUnsigned(find(DW_AT_call_file), 0); 302 CallLine = toUnsigned(find(DW_AT_call_line), 0); 303 CallColumn = toUnsigned(find(DW_AT_call_column), 0); 304 CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0); 305 } 306 307 void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth, unsigned Indent, 308 DIDumpOptions DumpOpts) const { 309 if (!isValid()) 310 return; 311 DataExtractor debug_info_data = U->getDebugInfoExtractor(); 312 const uint32_t Offset = getOffset(); 313 uint32_t offset = Offset; 314 315 if (debug_info_data.isValidOffset(offset)) { 316 uint32_t abbrCode = debug_info_data.getULEB128(&offset); 317 WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset); 318 319 if (abbrCode) { 320 auto AbbrevDecl = getAbbreviationDeclarationPtr(); 321 if (AbbrevDecl) { 322 auto tagString = TagString(getTag()); 323 if (!tagString.empty()) 324 WithColor(OS, syntax::Tag).get().indent(Indent) << tagString; 325 else 326 WithColor(OS, syntax::Tag).get().indent(Indent) 327 << format("DW_TAG_Unknown_%x", getTag()); 328 329 if (!DumpOpts.Brief) 330 OS << format(" [%u] %c", abbrCode, 331 AbbrevDecl->hasChildren() ? '*' : ' '); 332 OS << '\n'; 333 334 // Dump all data in the DIE for the attributes. 335 for (const auto &AttrSpec : AbbrevDecl->attributes()) { 336 if (AttrSpec.Form == DW_FORM_implicit_const) { 337 // We are dumping .debug_info section , 338 // implicit_const attribute values are not really stored here, 339 // but in .debug_abbrev section. So we just skip such attrs. 340 continue; 341 } 342 dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form, 343 Indent, DumpOpts); 344 } 345 346 DWARFDie child = getFirstChild(); 347 if (RecurseDepth > 0 && child) { 348 while (child) { 349 child.dump(OS, RecurseDepth-1, Indent+2, DumpOpts); 350 child = child.getSibling(); 351 } 352 } 353 } else { 354 OS << "Abbreviation code not found in 'debug_abbrev' class for code: " 355 << abbrCode << '\n'; 356 } 357 } else { 358 OS.indent(Indent) << "NULL\n"; 359 } 360 } 361 } 362 363 DWARFDie DWARFDie::getParent() const { 364 if (isValid()) 365 return U->getParent(Die); 366 return DWARFDie(); 367 } 368 369 DWARFDie DWARFDie::getSibling() const { 370 if (isValid()) 371 return U->getSibling(Die); 372 return DWARFDie(); 373 } 374 375 iterator_range<DWARFDie::attribute_iterator> 376 DWARFDie::attributes() const { 377 return make_range(attribute_iterator(*this, false), 378 attribute_iterator(*this, true)); 379 } 380 381 DWARFDie::attribute_iterator::attribute_iterator(DWARFDie D, bool End) : 382 Die(D), AttrValue(0), Index(0) { 383 auto AbbrDecl = Die.getAbbreviationDeclarationPtr(); 384 assert(AbbrDecl && "Must have abbreviation declaration"); 385 if (End) { 386 // This is the end iterator so we set the index to the attribute count. 387 Index = AbbrDecl->getNumAttributes(); 388 } else { 389 // This is the begin iterator so we extract the value for this->Index. 390 AttrValue.Offset = D.getOffset() + AbbrDecl->getCodeByteSize(); 391 updateForIndex(*AbbrDecl, 0); 392 } 393 } 394 395 void DWARFDie::attribute_iterator::updateForIndex( 396 const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I) { 397 Index = I; 398 // AbbrDecl must be valid befor calling this function. 399 auto NumAttrs = AbbrDecl.getNumAttributes(); 400 if (Index < NumAttrs) { 401 AttrValue.Attr = AbbrDecl.getAttrByIndex(Index); 402 // Add the previous byte size of any previous attribute value. 403 AttrValue.Offset += AttrValue.ByteSize; 404 AttrValue.Value.setForm(AbbrDecl.getFormByIndex(Index)); 405 uint32_t ParseOffset = AttrValue.Offset; 406 auto U = Die.getDwarfUnit(); 407 assert(U && "Die must have valid DWARF unit"); 408 bool b = AttrValue.Value.extractValue(U->getDebugInfoExtractor(), 409 &ParseOffset, U); 410 (void)b; 411 assert(b && "extractValue cannot fail on fully parsed DWARF"); 412 AttrValue.ByteSize = ParseOffset - AttrValue.Offset; 413 } else { 414 assert(Index == NumAttrs && "Indexes should be [0, NumAttrs) only"); 415 AttrValue.clear(); 416 } 417 } 418 419 DWARFDie::attribute_iterator &DWARFDie::attribute_iterator::operator++() { 420 if (auto AbbrDecl = Die.getAbbreviationDeclarationPtr()) 421 updateForIndex(*AbbrDecl, Index + 1); 422 return *this; 423 } 424