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