X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FDebugInfo%2FDWARFDebugInfoEntry.cpp;h=583e70055c0104e7b9970f6f42f03d8a43ba6fc3;hb=7435fa333d1b646690021bfaa9350355017d0bdf;hp=1b089adbe13b5f52f61ba1420ae4391e75184b13;hpb=34f864fd382156331c61fbb6b7ae4828108b9d69;p=oota-llvm.git diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARFDebugInfoEntry.cpp index 1b089adbe13..583e70055c0 100644 --- a/lib/DebugInfo/DWARFDebugInfoEntry.cpp +++ b/lib/DebugInfo/DWARFDebugInfoEntry.cpp @@ -1,4 +1,4 @@ -//===-- DWARFDebugInfoEntry.cpp --------------------------------------------===// +//===-- DWARFDebugInfoEntry.cpp -------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -11,22 +11,34 @@ #include "DWARFCompileUnit.h" #include "DWARFContext.h" #include "DWARFDebugAbbrev.h" -#include "DWARFFormValue.h" +#include "llvm/DebugInfo/DWARFFormValue.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace dwarf; -void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, - const DWARFCompileUnit *cu, +// Small helper to extract a DIE pointed by a reference +// attribute. It looks up the Unit containing the DIE and calls +// DIE.extractFast with the right unit. Returns new unit on success, +// nullptr otherwise. +static const DWARFUnit *findUnitAndExtractFast(DWARFDebugInfoEntryMinimal &DIE, + const DWARFUnit *Unit, + uint32_t *Offset) { + Unit = Unit->getUnitSection().getUnitForOffset(*Offset); + return (Unit && DIE.extractFast(Unit, Offset)) ? Unit : nullptr; +} + +void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, DWARFUnit *u, unsigned recurseDepth, unsigned indent) const { - DataExtractor debug_info_data = cu->getDebugInfoExtractor(); + DataExtractor debug_info_data = u->getDebugInfoExtractor(); uint32_t offset = Offset; if (debug_info_data.isValidOffset(offset)) { - uint64_t abbrCode = debug_info_data.getULEB128(&offset); + uint32_t abbrCode = debug_info_data.getULEB128(&offset); OS << format("\n0x%8.8x: ", Offset); if (abbrCode) { @@ -39,18 +51,15 @@ void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, OS << format(" [%u] %c\n", abbrCode, AbbrevDecl->hasChildren() ? '*' : ' '); - // Dump all data in the .debug_info for the attributes - const uint32_t numAttributes = AbbrevDecl->getNumAttributes(); - for (uint32_t i = 0; i != numAttributes; ++i) { - uint16_t attr = AbbrevDecl->getAttrByIndex(i); - uint16_t form = AbbrevDecl->getFormByIndex(i); - dumpAttribute(OS, cu, &offset, attr, form, indent); + // Dump all data in the DIE for the attributes. + for (const auto &AttrSpec : AbbrevDecl->attributes()) { + dumpAttribute(OS, u, &offset, AttrSpec.Attr, AttrSpec.Form, indent); } const DWARFDebugInfoEntryMinimal *child = getFirstChild(); if (recurseDepth > 0 && child) { while (child) { - child->dump(OS, cu, recurseDepth-1, indent+2); + child->dump(OS, u, recurseDepth-1, indent+2); child = child->getSibling(); } } @@ -64,13 +73,42 @@ void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, } } +static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) { + OS << " ("; + do { + uint64_t Bit = 1ULL << countTrailingZeros(Val); + if (const char *PropName = ApplePropertyString(Bit)) + OS << PropName; + else + OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit); + if (!(Val ^= Bit)) + break; + OS << ", "; + } while (true); + OS << ")"; +} + +static void dumpRanges(raw_ostream &OS, const DWARFAddressRangesVector& Ranges, + unsigned AddressSize, unsigned Indent) { + if (Ranges.empty()) + return; + + for (const auto &Range: Ranges) { + OS << '\n'; + OS.indent(Indent); + OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")", + AddressSize*2, Range.first, + AddressSize*2, Range.second); + } +} + void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS, - const DWARFCompileUnit *cu, - uint32_t* offset_ptr, - uint16_t attr, - uint16_t form, + DWARFUnit *u, + uint32_t *offset_ptr, + uint16_t attr, uint16_t form, unsigned indent) const { - OS << format("0x%8.8x: ", *offset_ptr); + const char BaseIndent[] = " "; + OS << BaseIndent; OS.indent(indent+2); const char *attrString = AttributeString(attr); if (attrString) @@ -85,360 +123,329 @@ void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS, DWARFFormValue formValue(form); - if (!formValue.extractValue(cu->getDebugInfoExtractor(), offset_ptr, cu)) + if (!formValue.extractValue(u->getDebugInfoExtractor(), offset_ptr, u)) return; OS << "\t("; - formValue.dump(OS, cu); + + const char *Name = nullptr; + std::string File; + if (attr == DW_AT_decl_file || attr == DW_AT_call_file) { + if (const auto *LT = u->getContext().getLineTableForUnit(u)) + if (LT->getFileNameByIndex( + formValue.getAsUnsignedConstant().getValue(), + u->getCompilationDir(), + DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) { + File = '"' + File + '"'; + Name = File.c_str(); + } + } else if (Optional Val = formValue.getAsUnsignedConstant()) + Name = AttributeValueString(attr, *Val); + + if (Name) { + OS << Name; + } else if (attr == DW_AT_decl_line || attr == DW_AT_call_line) { + OS << *formValue.getAsUnsignedConstant(); + } else { + formValue.dump(OS, u); + } + + // We have dumped the attribute raw value. For some attributes + // having both the raw value and the pretty-printed value is + // interesting. These attributes are handled below. + if ((attr == DW_AT_specification || attr == DW_AT_abstract_origin) && + // The signature references aren't handled. + formValue.getForm() != DW_FORM_ref_sig8) { + uint32_t Ref = formValue.getAsReference(u).getValue(); + DWARFDebugInfoEntryMinimal DIE; + if (const DWARFUnit *RefU = findUnitAndExtractFast(DIE, u, &Ref)) + if (const char *Ref = DIE.getName(RefU, DINameKind::LinkageName)) + OS << " \"" << Ref << '\"'; + } else if (attr == DW_AT_APPLE_property_attribute) { + if (Optional OptVal = formValue.getAsUnsignedConstant()) + dumpApplePropertyAttribute(OS, *OptVal); + } else if (attr == DW_AT_ranges) { + dumpRanges(OS, getAddressRanges(u), u->getAddressByteSize(), + sizeof(BaseIndent)+indent+4); + } + OS << ")\n"; } -bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFCompileUnit *cu, - const uint8_t *fixed_form_sizes, - uint32_t *offset_ptr) { - Offset = *offset_ptr; - - DataExtractor debug_info_data = cu->getDebugInfoExtractor(); - uint64_t abbrCode = debug_info_data.getULEB128(offset_ptr); - - assert (fixed_form_sizes); // For best performance this should be specified! - - if (abbrCode) { - uint32_t offset = *offset_ptr; - - AbbrevDecl = cu->getAbbreviations()->getAbbreviationDeclaration(abbrCode); - - // Skip all data in the .debug_info for the attributes - const uint32_t numAttributes = AbbrevDecl->getNumAttributes(); - uint32_t i; - uint16_t form; - for (i=0; igetFormByIndex(i); - - const uint8_t fixed_skip_size = fixed_form_sizes[form]; - if (fixed_skip_size) - offset += fixed_skip_size; - else { - bool form_is_indirect = false; - do { - form_is_indirect = false; - uint32_t form_size = 0; - switch (form) { - // Blocks if inlined data that have a length field and the data bytes - // inlined in the .debug_info. - case DW_FORM_block: - form_size = debug_info_data.getULEB128(&offset); - break; - case DW_FORM_block1: - form_size = debug_info_data.getU8(&offset); - break; - case DW_FORM_block2: - form_size = debug_info_data.getU16(&offset); - break; - case DW_FORM_block4: - form_size = debug_info_data.getU32(&offset); - break; - - // Inlined NULL terminated C-strings - case DW_FORM_string: - debug_info_data.getCStr(&offset); - break; - - // Compile unit address sized values - case DW_FORM_addr: - case DW_FORM_ref_addr: - form_size = cu->getAddressByteSize(); - break; - - // 1 byte values - case DW_FORM_data1: - case DW_FORM_flag: - case DW_FORM_ref1: - form_size = 1; - break; - - // 2 byte values - case DW_FORM_data2: - case DW_FORM_ref2: - form_size = 2; - break; - - // 4 byte values - case DW_FORM_strp: - case DW_FORM_data4: - case DW_FORM_ref4: - form_size = 4; - break; - - // 8 byte values - case DW_FORM_data8: - case DW_FORM_ref8: - form_size = 8; - break; - - // signed or unsigned LEB 128 values - case DW_FORM_sdata: - case DW_FORM_udata: - case DW_FORM_ref_udata: - debug_info_data.getULEB128(&offset); - break; - - case DW_FORM_indirect: - form_is_indirect = true; - form = debug_info_data.getULEB128(&offset); - break; - - default: - *offset_ptr = Offset; - return false; - } - offset += form_size; - - } while (form_is_indirect); - } - } - *offset_ptr = offset; +bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit *U, + uint32_t *OffsetPtr) { + Offset = *OffsetPtr; + DataExtractor DebugInfoData = U->getDebugInfoExtractor(); + uint32_t UEndOffset = U->getNextUnitOffset(); + if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset)) + return false; + uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr); + if (0 == AbbrCode) { + // NULL debug tag entry. + AbbrevDecl = nullptr; return true; - } else { - AbbrevDecl = NULL; - return true; // NULL debug tag entry } + AbbrevDecl = U->getAbbreviations()->getAbbreviationDeclaration(AbbrCode); + if (nullptr == AbbrevDecl) { + // Restore the original offset. + *OffsetPtr = Offset; + return false; + } + ArrayRef FixedFormSizes = DWARFFormValue::getFixedFormSizes( + U->getAddressByteSize(), U->getVersion()); + assert(FixedFormSizes.size() > 0); + + // Skip all data in the .debug_info for the attributes + for (const auto &AttrSpec : AbbrevDecl->attributes()) { + uint16_t Form = AttrSpec.Form; + + uint8_t FixedFormSize = + (Form < FixedFormSizes.size()) ? FixedFormSizes[Form] : 0; + if (FixedFormSize) + *OffsetPtr += FixedFormSize; + else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U)) { + // Restore the original offset. + *OffsetPtr = Offset; + return false; + } + } + return true; +} - return false; +bool DWARFDebugInfoEntryMinimal::isSubprogramDIE() const { + return getTag() == DW_TAG_subprogram; +} + +bool DWARFDebugInfoEntryMinimal::isSubroutineDIE() const { + uint32_t Tag = getTag(); + return Tag == DW_TAG_subprogram || + Tag == DW_TAG_inlined_subroutine; } -bool -DWARFDebugInfoEntryMinimal::extract(const DWARFCompileUnit *cu, - uint32_t *offset_ptr) { - DataExtractor debug_info_data = cu->getDebugInfoExtractor(); - const uint32_t cu_end_offset = cu->getNextCompileUnitOffset(); - const uint8_t cu_addr_size = cu->getAddressByteSize(); - uint32_t offset = *offset_ptr; - if ((offset < cu_end_offset) && debug_info_data.isValidOffset(offset)) { - Offset = offset; +bool DWARFDebugInfoEntryMinimal::getAttributeValue( + const DWARFUnit *U, const uint16_t Attr, DWARFFormValue &FormValue) const { + if (!AbbrevDecl) + return false; - uint64_t abbrCode = debug_info_data.getULEB128(&offset); + uint32_t AttrIdx = AbbrevDecl->findAttributeIndex(Attr); + if (AttrIdx == -1U) + return false; - if (abbrCode) { - AbbrevDecl = cu->getAbbreviations()->getAbbreviationDeclaration(abbrCode); + DataExtractor DebugInfoData = U->getDebugInfoExtractor(); + uint32_t DebugInfoOffset = getOffset(); - if (AbbrevDecl) { - uint16_t tag = AbbrevDecl->getTag(); - - bool isCompileUnitTag = tag == DW_TAG_compile_unit; - if(cu && isCompileUnitTag) - const_cast(cu)->setBaseAddress(0); - - // Skip all data in the .debug_info for the attributes - const uint32_t numAttributes = AbbrevDecl->getNumAttributes(); - for (uint32_t i = 0; i != numAttributes; ++i) { - uint16_t attr = AbbrevDecl->getAttrByIndex(i); - uint16_t form = AbbrevDecl->getFormByIndex(i); - - if (isCompileUnitTag && - ((attr == DW_AT_entry_pc) || (attr == DW_AT_low_pc))) { - DWARFFormValue form_value(form); - if (form_value.extractValue(debug_info_data, &offset, cu)) { - if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc) - const_cast(cu) - ->setBaseAddress(form_value.getUnsigned()); - } - } else { - bool form_is_indirect = false; - do { - form_is_indirect = false; - register uint32_t form_size = 0; - switch (form) { - // Blocks if inlined data that have a length field and the data - // bytes // inlined in the .debug_info - case DW_FORM_block: - form_size = debug_info_data.getULEB128(&offset); - break; - case DW_FORM_block1: - form_size = debug_info_data.getU8(&offset); - break; - case DW_FORM_block2: - form_size = debug_info_data.getU16(&offset); - break; - case DW_FORM_block4: - form_size = debug_info_data.getU32(&offset); - break; - - // Inlined NULL terminated C-strings - case DW_FORM_string: - debug_info_data.getCStr(&offset); - break; - - // Compile unit address sized values - case DW_FORM_addr: - case DW_FORM_ref_addr: - form_size = cu_addr_size; - break; - - // 1 byte values - case DW_FORM_data1: - case DW_FORM_flag: - case DW_FORM_ref1: - form_size = 1; - break; - - // 2 byte values - case DW_FORM_data2: - case DW_FORM_ref2: - form_size = 2; - break; - - // 4 byte values - case DW_FORM_strp: - form_size = 4; - break; - - case DW_FORM_data4: - case DW_FORM_ref4: - form_size = 4; - break; - - // 8 byte values - case DW_FORM_data8: - case DW_FORM_ref8: - form_size = 8; - break; - - // signed or unsigned LEB 128 values - case DW_FORM_sdata: - case DW_FORM_udata: - case DW_FORM_ref_udata: - debug_info_data.getULEB128(&offset); - break; - - case DW_FORM_indirect: - form = debug_info_data.getULEB128(&offset); - form_is_indirect = true; - break; - - default: - *offset_ptr = offset; - return false; - } - - offset += form_size; - } while (form_is_indirect); - } - } - *offset_ptr = offset; - return true; - } - } else { - AbbrevDecl = NULL; - *offset_ptr = offset; - return true; // NULL debug tag entry - } + // Skip the abbreviation code so we are at the data for the attributes + DebugInfoData.getULEB128(&DebugInfoOffset); + + // Skip preceding attribute values. + for (uint32_t i = 0; i < AttrIdx; ++i) { + DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(i), + DebugInfoData, &DebugInfoOffset, U); } - return false; + FormValue = DWARFFormValue(AbbrevDecl->getFormByIndex(AttrIdx)); + return FormValue.extractValue(DebugInfoData, &DebugInfoOffset, U); } -uint32_t -DWARFDebugInfoEntryMinimal::getAttributeValue(const DWARFCompileUnit *cu, - const uint16_t attr, - DWARFFormValue &form_value, - uint32_t *end_attr_offset_ptr) - const { - if (AbbrevDecl) { - uint32_t attr_idx = AbbrevDecl->findAttributeIndex(attr); - - if (attr_idx != -1U) { - uint32_t offset = getOffset(); - - DataExtractor debug_info_data = cu->getDebugInfoExtractor(); - - // Skip the abbreviation code so we are at the data for the attributes - debug_info_data.getULEB128(&offset); - - uint32_t idx = 0; - while (idx < attr_idx) - DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(idx++), - debug_info_data, &offset, cu); - - const uint32_t attr_offset = offset; - form_value = DWARFFormValue(AbbrevDecl->getFormByIndex(idx)); - if (form_value.extractValue(debug_info_data, &offset, cu)) { - if (end_attr_offset_ptr) - *end_attr_offset_ptr = offset; - return attr_offset; - } - } - } +const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString( + const DWARFUnit *U, const uint16_t Attr, const char *FailValue) const { + DWARFFormValue FormValue; + if (!getAttributeValue(U, Attr, FormValue)) + return FailValue; + Optional Result = FormValue.getAsCString(U); + return Result.hasValue() ? Result.getValue() : FailValue; +} - return 0; +uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress( + const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { + DWARFFormValue FormValue; + if (!getAttributeValue(U, Attr, FormValue)) + return FailValue; + Optional Result = FormValue.getAsAddress(U); + return Result.hasValue() ? Result.getValue() : FailValue; } -const char* -DWARFDebugInfoEntryMinimal::getAttributeValueAsString( - const DWARFCompileUnit* cu, - const uint16_t attr, - const char* fail_value) const { - DWARFFormValue form_value; - if (getAttributeValue(cu, attr, form_value)) { - DataExtractor stringExtractor(cu->getContext().getStringSection(), - false, 0); - return form_value.getAsCString(&stringExtractor); - } - return fail_value; +uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsignedConstant( + const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { + DWARFFormValue FormValue; + if (!getAttributeValue(U, Attr, FormValue)) + return FailValue; + Optional Result = FormValue.getAsUnsignedConstant(); + return Result.hasValue() ? Result.getValue() : FailValue; } -uint64_t -DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsigned( - const DWARFCompileUnit* cu, - const uint16_t attr, - uint64_t fail_value) const { - DWARFFormValue form_value; - if (getAttributeValue(cu, attr, form_value)) - return form_value.getUnsigned(); - return fail_value; +uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsReference( + const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { + DWARFFormValue FormValue; + if (!getAttributeValue(U, Attr, FormValue)) + return FailValue; + Optional Result = FormValue.getAsReference(U); + return Result.hasValue() ? Result.getValue() : FailValue; } -int64_t -DWARFDebugInfoEntryMinimal::getAttributeValueAsSigned( - const DWARFCompileUnit* cu, - const uint16_t attr, - int64_t fail_value) const { - DWARFFormValue form_value; - if (getAttributeValue(cu, attr, form_value)) - return form_value.getSigned(); - return fail_value; +uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSectionOffset( + const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const { + DWARFFormValue FormValue; + if (!getAttributeValue(U, Attr, FormValue)) + return FailValue; + Optional Result = FormValue.getAsSectionOffset(); + return Result.hasValue() ? Result.getValue() : FailValue; } uint64_t -DWARFDebugInfoEntryMinimal::getAttributeValueAsReference( - const DWARFCompileUnit* cu, - const uint16_t attr, - uint64_t fail_value) const { - DWARFFormValue form_value; - if (getAttributeValue(cu, attr, form_value)) - return form_value.getReference(cu); - return fail_value; +DWARFDebugInfoEntryMinimal::getRangesBaseAttribute(const DWARFUnit *U, + uint64_t FailValue) const { + uint64_t Result = + getAttributeValueAsSectionOffset(U, DW_AT_ranges_base, -1ULL); + if (Result != -1ULL) + return Result; + return getAttributeValueAsSectionOffset(U, DW_AT_GNU_ranges_base, FailValue); +} + +bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U, + uint64_t &LowPC, + uint64_t &HighPC) const { + LowPC = getAttributeValueAsAddress(U, DW_AT_low_pc, -1ULL); + if (LowPC == -1ULL) + return false; + HighPC = getAttributeValueAsAddress(U, DW_AT_high_pc, -1ULL); + if (HighPC == -1ULL) { + // Since DWARF4, DW_AT_high_pc may also be of class constant, in which case + // it represents function size. + HighPC = getAttributeValueAsUnsignedConstant(U, DW_AT_high_pc, -1ULL); + if (HighPC != -1ULL) + HighPC += LowPC; + } + return (HighPC != -1ULL); +} + +DWARFAddressRangesVector +DWARFDebugInfoEntryMinimal::getAddressRanges(const DWARFUnit *U) const { + if (isNULL()) + return DWARFAddressRangesVector(); + // Single range specified by low/high PC. + uint64_t LowPC, HighPC; + if (getLowAndHighPC(U, LowPC, HighPC)) { + return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC)); + } + // Multiple ranges from .debug_ranges section. + uint32_t RangesOffset = + getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U); + if (RangesOffset != -1U) { + DWARFDebugRangeList RangeList; + if (U->extractRangeList(RangesOffset, RangeList)) + return RangeList.getAbsoluteRanges(U->getBaseAddress()); + } + return DWARFAddressRangesVector(); } -void -DWARFDebugInfoEntryMinimal::buildAddressRangeTable(const DWARFCompileUnit *cu, - DWARFDebugAranges *debug_aranges) - const { - if (AbbrevDecl) { - uint16_t tag = AbbrevDecl->getTag(); - if (tag == DW_TAG_subprogram) { - uint64_t hi_pc = -1ULL; - uint64_t lo_pc = getAttributeValueAsUnsigned(cu, DW_AT_low_pc, -1ULL); - if (lo_pc != -1ULL) - hi_pc = getAttributeValueAsUnsigned(cu, DW_AT_high_pc, -1ULL); - if (hi_pc != -1ULL) - debug_aranges->appendRange(cu->getOffset(), lo_pc, hi_pc); +void DWARFDebugInfoEntryMinimal::collectChildrenAddressRanges( + const DWARFUnit *U, DWARFAddressRangesVector& Ranges) const { + if (isNULL()) + return; + if (isSubprogramDIE()) { + const auto &DIERanges = getAddressRanges(U); + Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end()); + } + + const DWARFDebugInfoEntryMinimal *Child = getFirstChild(); + while (Child) { + Child->collectChildrenAddressRanges(U, Ranges); + Child = Child->getSibling(); + } +} + +bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress( + const DWARFUnit *U, const uint64_t Address) const { + for (const auto& R : getAddressRanges(U)) { + if (R.first <= Address && Address < R.second) + return true; + } + return false; +} + +const char * +DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U, + DINameKind Kind) const { + if (!isSubroutineDIE()) + return nullptr; + return getName(U, Kind); +} + +const char * +DWARFDebugInfoEntryMinimal::getName(const DWARFUnit *U, + DINameKind Kind) const { + if (Kind == DINameKind::None) + return nullptr; + // Try to get mangled name only if it was asked for. + if (Kind == DINameKind::LinkageName) { + if (const char *name = + getAttributeValueAsString(U, DW_AT_MIPS_linkage_name, nullptr)) + return name; + if (const char *name = + getAttributeValueAsString(U, DW_AT_linkage_name, nullptr)) + return name; + } + if (const char *name = getAttributeValueAsString(U, DW_AT_name, nullptr)) + return name; + // Try to get name from specification DIE. + uint32_t spec_ref = + getAttributeValueAsReference(U, DW_AT_specification, -1U); + if (spec_ref != -1U) { + DWARFDebugInfoEntryMinimal spec_die; + if (const DWARFUnit *RefU = findUnitAndExtractFast(spec_die, U, &spec_ref)) { + if (const char *name = spec_die.getName(RefU, Kind)) + return name; } + } + // Try to get name from abstract origin DIE. + uint32_t abs_origin_ref = + getAttributeValueAsReference(U, DW_AT_abstract_origin, -1U); + if (abs_origin_ref != -1U) { + DWARFDebugInfoEntryMinimal abs_origin_die; + if (const DWARFUnit *RefU = findUnitAndExtractFast(abs_origin_die, U, + &abs_origin_ref)) { + if (const char *name = abs_origin_die.getName(RefU, Kind)) + return name; + } + } + return nullptr; +} - const DWARFDebugInfoEntryMinimal *child = getFirstChild(); - while (child) { - child->buildAddressRangeTable(cu, debug_aranges); - child = child->getSibling(); +void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFUnit *U, + uint32_t &CallFile, + uint32_t &CallLine, + uint32_t &CallColumn) const { + CallFile = getAttributeValueAsUnsignedConstant(U, DW_AT_call_file, 0); + CallLine = getAttributeValueAsUnsignedConstant(U, DW_AT_call_line, 0); + CallColumn = getAttributeValueAsUnsignedConstant(U, DW_AT_call_column, 0); +} + +DWARFDebugInfoEntryInlinedChain +DWARFDebugInfoEntryMinimal::getInlinedChainForAddress( + const DWARFUnit *U, const uint64_t Address) const { + DWARFDebugInfoEntryInlinedChain InlinedChain; + InlinedChain.U = U; + if (isNULL()) + return InlinedChain; + for (const DWARFDebugInfoEntryMinimal *DIE = this; DIE; ) { + // Append current DIE to inlined chain only if it has correct tag + // (e.g. it is not a lexical block). + if (DIE->isSubroutineDIE()) { + InlinedChain.DIEs.push_back(*DIE); + } + // Try to get child which also contains provided address. + const DWARFDebugInfoEntryMinimal *Child = DIE->getFirstChild(); + while (Child) { + if (Child->addressRangeContainsAddress(U, Address)) { + // Assume there is only one such child. + break; + } + Child = Child->getSibling(); } + DIE = Child; } + // Reverse the obtained chain to make the root of inlined chain last. + std::reverse(InlinedChain.DIEs.begin(), InlinedChain.DIEs.end()); + return InlinedChain; }