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 "DWARFDebugInfoEntry.h" 11 #include "DWARFCompileUnit.h" 12 #include "DWARFContext.h" 13 #include "DWARFDebugAbbrev.h" 14 #include "llvm/DebugInfo/DWARFFormValue.h" 15 #include "llvm/Support/Debug.h" 16 #include "llvm/Support/Dwarf.h" 17 #include "llvm/Support/Format.h" 18 #include "llvm/Support/raw_ostream.h" 19 using namespace llvm; 20 using namespace dwarf; 21 typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind; 22 23 void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, const DWARFUnit *u, 24 unsigned recurseDepth, 25 unsigned indent) const { 26 DataExtractor debug_info_data = u->getDebugInfoExtractor(); 27 uint32_t offset = Offset; 28 29 if (debug_info_data.isValidOffset(offset)) { 30 uint32_t abbrCode = debug_info_data.getULEB128(&offset); 31 32 OS << format("\n0x%8.8x: ", Offset); 33 if (abbrCode) { 34 if (AbbrevDecl) { 35 const char *tagString = TagString(getTag()); 36 if (tagString) 37 OS.indent(indent) << tagString; 38 else 39 OS.indent(indent) << format("DW_TAG_Unknown_%x", getTag()); 40 OS << format(" [%u] %c\n", abbrCode, 41 AbbrevDecl->hasChildren() ? '*' : ' '); 42 43 // Dump all data in the DIE for the attributes. 44 for (const auto &AttrSpec : AbbrevDecl->attributes()) { 45 dumpAttribute(OS, u, &offset, AttrSpec.Attr, AttrSpec.Form, indent); 46 } 47 48 const DWARFDebugInfoEntryMinimal *child = getFirstChild(); 49 if (recurseDepth > 0 && child) { 50 while (child) { 51 child->dump(OS, u, recurseDepth-1, indent+2); 52 child = child->getSibling(); 53 } 54 } 55 } else { 56 OS << "Abbreviation code not found in 'debug_abbrev' class for code: " 57 << abbrCode << '\n'; 58 } 59 } else { 60 OS.indent(indent) << "NULL\n"; 61 } 62 } 63 } 64 65 void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS, 66 const DWARFUnit *u, 67 uint32_t *offset_ptr, 68 uint16_t attr, uint16_t form, 69 unsigned indent) const { 70 OS << " "; 71 OS.indent(indent+2); 72 const char *attrString = AttributeString(attr); 73 if (attrString) 74 OS << attrString; 75 else 76 OS << format("DW_AT_Unknown_%x", attr); 77 const char *formString = FormEncodingString(form); 78 if (formString) 79 OS << " [" << formString << ']'; 80 else 81 OS << format(" [DW_FORM_Unknown_%x]", form); 82 83 DWARFFormValue formValue(form); 84 85 if (!formValue.extractValue(u->getDebugInfoExtractor(), offset_ptr, u)) 86 return; 87 88 OS << "\t("; 89 formValue.dump(OS, u); 90 OS << ")\n"; 91 } 92 93 bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit *U, 94 uint32_t *OffsetPtr) { 95 Offset = *OffsetPtr; 96 DataExtractor DebugInfoData = U->getDebugInfoExtractor(); 97 uint32_t UEndOffset = U->getNextUnitOffset(); 98 if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset)) 99 return false; 100 uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr); 101 if (0 == AbbrCode) { 102 // NULL debug tag entry. 103 AbbrevDecl = nullptr; 104 return true; 105 } 106 AbbrevDecl = U->getAbbreviations()->getAbbreviationDeclaration(AbbrCode); 107 if (nullptr == AbbrevDecl) { 108 // Restore the original offset. 109 *OffsetPtr = Offset; 110 return false; 111 } 112 ArrayRef<uint8_t> FixedFormSizes = DWARFFormValue::getFixedFormSizes( 113 U->getAddressByteSize(), U->getVersion()); 114 assert(FixedFormSizes.size() > 0); 115 116 // Skip all data in the .debug_info for the attributes 117 for (const auto &AttrSpec : AbbrevDecl->attributes()) { 118 uint16_t Form = AttrSpec.Form; 119 120 uint8_t FixedFormSize = 121 (Form < FixedFormSizes.size()) ? FixedFormSizes[Form] : 0; 122 if (FixedFormSize) 123 *OffsetPtr += FixedFormSize; 124 else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U)) { 125 // Restore the original offset. 126 *OffsetPtr = Offset; 127 return false; 128 } 129 } 130 return true; 131 } 132 133 bool DWARFDebugInfoEntryMinimal::isSubprogramDIE() const { 134 return getTag() == DW_TAG_subprogram; 135 } 136 137 bool DWARFDebugInfoEntryMinimal::isSubroutineDIE() const { 138 uint32_t Tag = getTag(); 139 return Tag == DW_TAG_subprogram || 140 Tag == DW_TAG_inlined_subroutine; 141 } 142 143 bool DWARFDebugInfoEntryMinimal::getAttributeValue( 144 const DWARFUnit *U, const uint16_t Attr, DWARFFormValue &FormValue) const { 145 if (!AbbrevDecl) 146 return false; 147 148 uint32_t AttrIdx = AbbrevDecl->findAttributeIndex(Attr); 149 if (AttrIdx == -1U) 150 return false; 151 152 DataExtractor DebugInfoData = U->getDebugInfoExtractor(); 153 uint32_t DebugInfoOffset = getOffset(); 154 155 // Skip the abbreviation code so we are at the data for the attributes 156 DebugInfoData.getULEB128(&DebugInfoOffset); 157 158 // Skip preceding attribute values. 159 for (uint32_t i = 0; i < AttrIdx; ++i) { 160 DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(i), 161 DebugInfoData, &DebugInfoOffset, U); 162 } 163 164 FormValue = DWARFFormValue(AbbrevDecl->getFormByIndex(AttrIdx)); 165 return FormValue.extractValue(DebugInfoData, &DebugInfoOffset, U); 166 } 167 168 const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString( 169 const DWARFUnit *U, const uint16_t Attr, const char *FailValue) const { 170 DWARFFormValue FormValue; 171 if (!getAttributeValue(U, Attr, FormValue)) 172 return FailValue; 173 Optional<const char *> Result = FormValue.getAsCString(U); 174 return Result.hasValue() ? Result.getValue() : FailValue; 175 } 176 177 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress( 178 const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { 179 DWARFFormValue FormValue; 180 if (!getAttributeValue(U, Attr, FormValue)) 181 return FailValue; 182 Optional<uint64_t> Result = FormValue.getAsAddress(U); 183 return Result.hasValue() ? Result.getValue() : FailValue; 184 } 185 186 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsignedConstant( 187 const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { 188 DWARFFormValue FormValue; 189 if (!getAttributeValue(U, Attr, FormValue)) 190 return FailValue; 191 Optional<uint64_t> Result = FormValue.getAsUnsignedConstant(); 192 return Result.hasValue() ? Result.getValue() : FailValue; 193 } 194 195 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsReference( 196 const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { 197 DWARFFormValue FormValue; 198 if (!getAttributeValue(U, Attr, FormValue)) 199 return FailValue; 200 Optional<uint64_t> Result = FormValue.getAsReference(U); 201 return Result.hasValue() ? Result.getValue() : FailValue; 202 } 203 204 uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSectionOffset( 205 const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { 206 DWARFFormValue FormValue; 207 if (!getAttributeValue(U, Attr, FormValue)) 208 return FailValue; 209 Optional<uint64_t> Result = FormValue.getAsSectionOffset(); 210 return Result.hasValue() ? Result.getValue() : FailValue; 211 } 212 213 uint64_t 214 DWARFDebugInfoEntryMinimal::getRangesBaseAttribute(const DWARFUnit *U, 215 uint64_t FailValue) const { 216 uint64_t Result = 217 getAttributeValueAsSectionOffset(U, DW_AT_ranges_base, -1ULL); 218 if (Result != -1ULL) 219 return Result; 220 return getAttributeValueAsSectionOffset(U, DW_AT_GNU_ranges_base, FailValue); 221 } 222 223 bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U, 224 uint64_t &LowPC, 225 uint64_t &HighPC) const { 226 LowPC = getAttributeValueAsAddress(U, DW_AT_low_pc, -1ULL); 227 if (LowPC == -1ULL) 228 return false; 229 HighPC = getAttributeValueAsAddress(U, DW_AT_high_pc, -1ULL); 230 if (HighPC == -1ULL) { 231 // Since DWARF4, DW_AT_high_pc may also be of class constant, in which case 232 // it represents function size. 233 HighPC = getAttributeValueAsUnsignedConstant(U, DW_AT_high_pc, -1ULL); 234 if (HighPC != -1ULL) 235 HighPC += LowPC; 236 } 237 return (HighPC != -1ULL); 238 } 239 240 DWARFAddressRangesVector 241 DWARFDebugInfoEntryMinimal::getAddressRanges(const DWARFUnit *U) const { 242 if (isNULL()) 243 return DWARFAddressRangesVector(); 244 // Single range specified by low/high PC. 245 uint64_t LowPC, HighPC; 246 if (getLowAndHighPC(U, LowPC, HighPC)) { 247 return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC)); 248 } 249 // Multiple ranges from .debug_ranges section. 250 uint32_t RangesOffset = 251 getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U); 252 if (RangesOffset != -1U) { 253 DWARFDebugRangeList RangeList; 254 if (U->extractRangeList(RangesOffset, RangeList)) 255 return RangeList.getAbsoluteRanges(U->getBaseAddress()); 256 } 257 return DWARFAddressRangesVector(); 258 } 259 260 void DWARFDebugInfoEntryMinimal::collectChildrenAddressRanges( 261 const DWARFUnit *U, DWARFAddressRangesVector& Ranges) const { 262 if (isNULL()) 263 return; 264 if (isSubprogramDIE()) { 265 const auto &DIERanges = getAddressRanges(U); 266 Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end()); 267 } 268 269 const DWARFDebugInfoEntryMinimal *Child = getFirstChild(); 270 while (Child) { 271 Child->collectChildrenAddressRanges(U, Ranges); 272 Child = Child->getSibling(); 273 } 274 } 275 276 bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress( 277 const DWARFUnit *U, const uint64_t Address) const { 278 for (const auto& R : getAddressRanges(U)) { 279 if (R.first <= Address && Address < R.second) 280 return true; 281 } 282 return false; 283 } 284 285 const char * 286 DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U, 287 FunctionNameKind Kind) const { 288 if (!isSubroutineDIE() || Kind == FunctionNameKind::None) 289 return nullptr; 290 // Try to get mangled name only if it was asked for. 291 if (Kind == FunctionNameKind::LinkageName) { 292 if (const char *name = 293 getAttributeValueAsString(U, DW_AT_MIPS_linkage_name, nullptr)) 294 return name; 295 if (const char *name = 296 getAttributeValueAsString(U, DW_AT_linkage_name, nullptr)) 297 return name; 298 } 299 if (const char *name = getAttributeValueAsString(U, DW_AT_name, nullptr)) 300 return name; 301 // Try to get name from specification DIE. 302 uint32_t spec_ref = 303 getAttributeValueAsReference(U, DW_AT_specification, -1U); 304 if (spec_ref != -1U) { 305 DWARFDebugInfoEntryMinimal spec_die; 306 if (spec_die.extractFast(U, &spec_ref)) { 307 if (const char *name = spec_die.getSubroutineName(U, Kind)) 308 return name; 309 } 310 } 311 // Try to get name from abstract origin DIE. 312 uint32_t abs_origin_ref = 313 getAttributeValueAsReference(U, DW_AT_abstract_origin, -1U); 314 if (abs_origin_ref != -1U) { 315 DWARFDebugInfoEntryMinimal abs_origin_die; 316 if (abs_origin_die.extractFast(U, &abs_origin_ref)) { 317 if (const char *name = abs_origin_die.getSubroutineName(U, Kind)) 318 return name; 319 } 320 } 321 return nullptr; 322 } 323 324 void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFUnit *U, 325 uint32_t &CallFile, 326 uint32_t &CallLine, 327 uint32_t &CallColumn) const { 328 CallFile = getAttributeValueAsUnsignedConstant(U, DW_AT_call_file, 0); 329 CallLine = getAttributeValueAsUnsignedConstant(U, DW_AT_call_line, 0); 330 CallColumn = getAttributeValueAsUnsignedConstant(U, DW_AT_call_column, 0); 331 } 332 333 DWARFDebugInfoEntryInlinedChain 334 DWARFDebugInfoEntryMinimal::getInlinedChainForAddress( 335 const DWARFUnit *U, const uint64_t Address) const { 336 DWARFDebugInfoEntryInlinedChain InlinedChain; 337 InlinedChain.U = U; 338 if (isNULL()) 339 return InlinedChain; 340 for (const DWARFDebugInfoEntryMinimal *DIE = this; DIE; ) { 341 // Append current DIE to inlined chain only if it has correct tag 342 // (e.g. it is not a lexical block). 343 if (DIE->isSubroutineDIE()) { 344 InlinedChain.DIEs.push_back(*DIE); 345 } 346 // Try to get child which also contains provided address. 347 const DWARFDebugInfoEntryMinimal *Child = DIE->getFirstChild(); 348 while (Child) { 349 if (Child->addressRangeContainsAddress(U, Address)) { 350 // Assume there is only one such child. 351 break; 352 } 353 Child = Child->getSibling(); 354 } 355 DIE = Child; 356 } 357 // Reverse the obtained chain to make the root of inlined chain last. 358 std::reverse(InlinedChain.DIEs.begin(), InlinedChain.DIEs.end()); 359 return InlinedChain; 360 } 361