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