uint16_t CompileUnit::getLanguage() { if (!Language) { DWARFDie CU = getOrigUnit().getUnitDIE(); Language = dwarf::toUnsigned(CU.find(dwarf::DW_AT_language), 0); } return Language; }
size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { if ((CUDieOnly && !DieArray.empty()) || DieArray.size() > 1) return 0; // Already parsed. bool HasCUDie = !DieArray.empty(); extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); if (DieArray.empty()) return 0; // If CU DIE was just parsed, copy several attribute values from it. if (!HasCUDie) { DWARFDie UnitDie = getUnitDIE(); auto BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_low_pc); if (!BaseAddr) BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_entry_pc); if (BaseAddr) setBaseAddress(*BaseAddr); AddrOffsetSectionBase = UnitDie.getAttributeValueAsSectionOffset( DW_AT_GNU_addr_base, 0); RangeSectionBase = UnitDie.getAttributeValueAsSectionOffset( DW_AT_rnglists_base, 0); // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for // skeleton CU DIE, so that DWARF users not aware of it are not broken. } return DieArray.size(); }
void DWARFUnit::updateAddressDieMap(DWARFDie Die) { if (Die.isSubroutineDIE()) { auto DIERangesOrError = Die.getAddressRanges(); if (DIERangesOrError) { for (const auto &R : DIERangesOrError.get()) { // Ignore 0-sized ranges. if (R.LowPC == R.HighPC) continue; auto B = AddrDieMap.upper_bound(R.LowPC); if (B != AddrDieMap.begin() && R.LowPC < (--B)->second.first) { // The range is a sub-range of existing ranges, we need to split the // existing range. if (R.HighPC < B->second.first) AddrDieMap[R.HighPC] = B->second; if (R.LowPC > B->first) AddrDieMap[B->first].first = R.LowPC; } AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die); } } else llvm::consumeError(DIERangesOrError.takeError()); } // Parent DIEs are added to the AddrDieMap prior to the Children DIEs to // simplify the logic to update AddrDieMap. The child's range will always // be equal or smaller than the parent's range. With this assumption, when // adding one range into the map, it will at most split a range into 3 // sub-ranges. for (DWARFDie Child = Die.getFirstChild(); Child; Child = Child.getSibling()) updateAddressDieMap(Child); }
bool DWARFUnit::parseDWO() { if (isDWO) return false; if (DWO.get()) return false; DWARFDie UnitDie = getUnitDIE(); if (!UnitDie) return false; const char *DWOFileName = UnitDie.getAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr); if (!DWOFileName) return false; const char *CompilationDir = UnitDie.getAttributeValueAsString(DW_AT_comp_dir, nullptr); SmallString<16> AbsolutePath; if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) { sys::path::append(AbsolutePath, CompilationDir); } sys::path::append(AbsolutePath, DWOFileName); DWO = llvm::make_unique<DWOHolder>(AbsolutePath); DWARFUnit *DWOCU = DWO->getUnit(); // Verify that compile unit in .dwo file is valid. if (!DWOCU || DWOCU->getDWOId() != getDWOId()) { DWO.reset(); return false; } // Share .debug_addr and .debug_ranges section with compile unit in .dwo DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); auto DWORangesBase = UnitDie.getRangesBaseAttribute(); DWOCU->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); return true; }
bool DWARFUnit::parseDWO() { if (isDWO) return false; if (DWO.get()) return false; DWARFDie UnitDie = getUnitDIE(); if (!UnitDie) return false; auto DWOFileName = dwarf::toString(UnitDie.find(DW_AT_GNU_dwo_name)); if (!DWOFileName) return false; auto CompilationDir = dwarf::toString(UnitDie.find(DW_AT_comp_dir)); SmallString<16> AbsolutePath; if (sys::path::is_relative(*DWOFileName) && CompilationDir && *CompilationDir) { sys::path::append(AbsolutePath, *CompilationDir); } sys::path::append(AbsolutePath, *DWOFileName); auto DWOId = getDWOId(); if (!DWOId) return false; auto DWOContext = Context.getDWOContext(AbsolutePath); if (!DWOContext) return false; DWARFCompileUnit *DWOCU = DWOContext->getDWOCompileUnitForHash(*DWOId); if (!DWOCU) return false; DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU); // Share .debug_addr and .debug_ranges section with compile unit in .dwo DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); auto DWORangesBase = UnitDie.getRangesBaseAttribute(); DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); return true; }
void DWARFTypeUnit::dump(raw_ostream &OS, bool SummarizeTypes) { DWARFDie TD = getDIEForOffset(TypeOffset + getOffset()); const char *Name = TD.getName(DINameKind::ShortName); if (SummarizeTypes) { OS << "name = '" << Name << "'" << " type_signature = " << format("0x%16" PRIx64, TypeHash) << " length = " << format("0x%08x", getLength()) << '\n'; return; } OS << format("0x%08x", getOffset()) << ": Type Unit:" << " length = " << format("0x%08x", getLength()) << " version = " << format("0x%04x", getVersion()) << " abbr_offset = " << format("0x%04x", getAbbreviations()->getOffset()) << " addr_size = " << format("0x%02x", getAddressByteSize()) << " name = '" << Name << "'" << " type_signature = " << format("0x%16" PRIx64, TypeHash) << " type_offset = " << format("0x%04x", TypeOffset) << " (next unit at " << format("0x%08x", getNextUnitOffset()) << ")\n"; if (DWARFDie TU = getUnitDIE(false)) TU.dump(OS, -1U); else OS << "<type unit can't be parsed!>\n\n"; }
/// Print only DIEs that have a certain name. static void filterByName(const StringSet<> &Names, DWARFContext::cu_iterator_range CUs, raw_ostream &OS) { for (const auto &CU : CUs) for (const auto &Entry : CU->dies()) { DWARFDie Die = {CU.get(), &Entry}; if (const char *NamePtr = Die.getName(DINameKind::ShortName)) { std::string Name = (IgnoreCase && !UseRegex) ? StringRef(NamePtr).lower() : NamePtr; // Match regular expression. if (UseRegex) for (auto Pattern : Names.keys()) { Regex RE(Pattern, IgnoreCase ? Regex::IgnoreCase : Regex::NoFlags); std::string Error; if (!RE.isValid(Error)) { errs() << "error in regular expression: " << Error << "\n"; exit(1); } if (RE.match(Name)) Die.dump(OS, 0, getDumpOpts()); } // Match full text. else if (Names.count(Name)) Die.dump(OS, 0, getDumpOpts()); } } }
static bool isVariableIndexable(const DWARFDie &Die, DWARFContext &DCtx) { Optional<DWARFFormValue> Location = Die.findRecursively(DW_AT_location); if (!Location) return false; auto ContainsInterestingOperators = [&](StringRef D) { DWARFUnit *U = Die.getDwarfUnit(); DataExtractor Data(D, DCtx.isLittleEndian(), U->getAddressByteSize()); DWARFExpression Expression(Data, U->getVersion(), U->getAddressByteSize()); return any_of(Expression, [](DWARFExpression::Operation &Op) { return !Op.isError() && (Op.getCode() == DW_OP_addr || Op.getCode() == DW_OP_form_tls_address || Op.getCode() == DW_OP_GNU_push_tls_address); }); }; if (Optional<ArrayRef<uint8_t>> Expr = Location->getAsBlock()) { // Inlined location. if (ContainsInterestingOperators(toStringRef(*Expr))) return true; } else if (Optional<uint64_t> Offset = Location->getAsSectionOffset()) { // Location list. if (const DWARFDebugLoc *DebugLoc = DCtx.getDebugLoc()) { if (const DWARFDebugLoc::LocationList *LocList = DebugLoc->getLocationListAtOffset(*Offset)) { if (any_of(LocList->Entries, [&](const DWARFDebugLoc::Entry &E) { return ContainsInterestingOperators({E.Loc.data(), E.Loc.size()}); })) return true; } } } return false; }
void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { DWARFDie UnitDie = getUnitDIE(); if (!UnitDie) return; // First, check if unit DIE describes address ranges for the whole unit. const auto &CUDIERanges = UnitDie.getAddressRanges(); if (!CUDIERanges.empty()) { CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end()); return; } // This function is usually called if there in no .debug_aranges section // in order to produce a compile unit level set of address ranges that // is accurate. If the DIEs weren't parsed, then we don't want all dies for // all compile units to stay loaded when they weren't needed. So we can end // up parsing the DWARF and then throwing them all away to keep memory usage // down. const bool ClearDIEs = extractDIEsIfNeeded(false) > 1; getUnitDIE().collectChildrenAddressRanges(CURanges); // Collect address ranges from DIEs in .dwo if necessary. bool DWOCreated = parseDWO(); if (DWO.get()) DWO->getUnit()->collectAddressRanges(CURanges); if (DWOCreated) DWO.reset(); // Keep memory down by clearing DIEs if this generate function // caused them to be parsed. if (ClearDIEs) clearDIEs(true); }
void DWARFDie::getInlinedChainForAddress( const uint64_t Address, SmallVectorImpl<DWARFDie> &InlinedChain) const { if (isNULL()) return; DWARFDie DIE(*this); while (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.push_back(DIE); // Try to get child which also contains provided address. DWARFDie Child = DIE.getFirstChild(); while (Child) { if (Child.addressRangeContainsAddress(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.begin(), InlinedChain.end()); }
Optional<DWARFFormValue> DWARFDie::findRecursively(ArrayRef<dwarf::Attribute> Attrs) const { std::vector<DWARFDie> Worklist; Worklist.push_back(*this); // Keep track if DIEs already seen to prevent infinite recursion. // Empirically we rarely see a depth of more than 3 when dealing with valid // DWARF. This corresponds to following the DW_AT_abstract_origin and // DW_AT_specification just once. SmallSet<DWARFDie, 3> Seen; Seen.insert(*this); while (!Worklist.empty()) { DWARFDie Die = Worklist.back(); Worklist.pop_back(); if (!Die.isValid()) continue; if (auto Value = Die.find(Attrs)) return Value; if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin)) if (Seen.insert(D).second) Worklist.push_back(D); if (auto D = Die.getAttributeValueAsReferencedDie(DW_AT_specification)) if (Seen.insert(D).second) Worklist.push_back(D); } return None; }
/// Helper to dump a DIE with all of its parents, but no siblings. static unsigned dumpParentChain(DWARFDie Die, raw_ostream &OS, unsigned Indent, DIDumpOptions DumpOpts) { if (!Die) return Indent; Indent = dumpParentChain(Die.getParent(), OS, Indent, DumpOpts); Die.dump(OS, Indent, DumpOpts); return Indent + 2; }
void DwarfVariableFinder::getInfo(const DWARFDie &die) { auto tagString = TagString(die.getTag()); if (tagString.empty()) { outs() << format("DW_TAG_Unknown_%x", die.getTag()); } auto formVal = die.find(dwarf::DW_AT_name); formVal->dump(outs()); }
unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die, DieRangeInfo &ParentRI) { unsigned NumErrors = 0; if (!Die.isValid()) return NumErrors; DWARFAddressRangesVector Ranges = Die.getAddressRanges(); // Build RI for this DIE and check that ranges within this DIE do not // overlap. DieRangeInfo RI(Die); for (auto Range : Ranges) { if (!Range.valid()) { ++NumErrors; error() << "Invalid address range " << Range << "\n"; continue; } // Verify that ranges don't intersect. const auto IntersectingRange = RI.insert(Range); if (IntersectingRange != RI.Ranges.end()) { ++NumErrors; error() << "DIE has overlapping address ranges: " << Range << " and " << *IntersectingRange << "\n"; break; } } // Verify that children don't intersect. const auto IntersectingChild = ParentRI.insert(RI); if (IntersectingChild != ParentRI.Children.end()) { ++NumErrors; error() << "DIEs have overlapping address ranges:"; Die.dump(OS, 0); IntersectingChild->Die.dump(OS, 0); OS << "\n"; } // Verify that ranges are contained within their parent. bool ShouldBeContained = !Ranges.empty() && !ParentRI.Ranges.empty() && !(Die.getTag() == DW_TAG_subprogram && ParentRI.Die.getTag() == DW_TAG_subprogram); if (ShouldBeContained && !ParentRI.contains(RI)) { ++NumErrors; error() << "DIE address ranges are not " "contained in its parent's ranges:"; Die.dump(OS, 0); ParentRI.Die.dump(OS, 0); OS << "\n"; } // Recursively check children. for (DWARFDie Child : Die) NumErrors += verifyDieRanges(Child, RI); return NumErrors; }
llvm::Optional<SectionedAddress> DWARFUnit::getBaseAddress() { if (BaseAddr) return BaseAddr; DWARFDie UnitDie = getUnitDIE(); Optional<DWARFFormValue> PC = UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc}); BaseAddr = toSectionedAddress(PC); return BaseAddr; }
unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, DWARFAttribute &AttrValue) { unsigned NumErrors = 0; auto ReportError = [&](const Twine &TitleMsg) { ++NumErrors; error() << TitleMsg << '\n'; Die.dump(OS, 0, DumpOpts); OS << "\n"; }; const DWARFObject &DObj = DCtx.getDWARFObj(); const auto Attr = AttrValue.Attr; switch (Attr) { case DW_AT_ranges: // Make sure the offset in the DW_AT_ranges attribute is valid. if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) { if (*SectionOffset >= DObj.getRangeSection().Data.size()) ReportError("DW_AT_ranges offset is beyond .debug_ranges bounds:"); break; } ReportError("DIE has invalid DW_AT_ranges encoding:"); break; case DW_AT_stmt_list: // Make sure the offset in the DW_AT_stmt_list attribute is valid. if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) { if (*SectionOffset >= DObj.getLineSection().Data.size()) ReportError("DW_AT_stmt_list offset is beyond .debug_line bounds: " + llvm::formatv("{0:x8}", *SectionOffset)); break; } ReportError("DIE has invalid DW_AT_stmt_list encoding:"); break; case DW_AT_location: { Optional<ArrayRef<uint8_t>> Expr = AttrValue.Value.getAsBlock(); if (!Expr) { ReportError("DIE has invalid DW_AT_location encoding:"); break; } DWARFUnit *U = Die.getDwarfUnit(); DataExtractor Data( StringRef(reinterpret_cast<const char *>(Expr->data()), Expr->size()), DCtx.isLittleEndian(), 0); DWARFExpression Expression(Data, U->getVersion(), U->getAddressByteSize()); bool Error = llvm::any_of(Expression, [](DWARFExpression::Operation &Op) { return Op.isError(); }); if (Error) ReportError("DIE contains invalid DWARF expression:"); break; } default: break; } return NumErrors; }
llvm::Optional<BaseAddress> DWARFUnit::getBaseAddress() { if (BaseAddr) return BaseAddr; DWARFDie UnitDie = getUnitDIE(); Optional<DWARFFormValue> PC = UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc}); if (Optional<uint64_t> Addr = toAddress(PC)) BaseAddr = {*Addr, PC->getSectionIndex()}; return BaseAddr; }
void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth, unsigned Indent) const { if (!isValid()) return; DataExtractor debug_info_data = U->getDebugInfoExtractor(); const uint32_t Offset = getOffset(); uint32_t offset = Offset; if (debug_info_data.isValidOffset(offset)) { uint32_t abbrCode = debug_info_data.getULEB128(&offset); WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset); if (abbrCode) { auto AbbrevDecl = getAbbreviationDeclarationPtr(); if (AbbrevDecl) { auto tagString = TagString(getTag()); if (!tagString.empty()) WithColor(OS, syntax::Tag).get().indent(Indent) << tagString; else WithColor(OS, syntax::Tag).get().indent(Indent) << format("DW_TAG_Unknown_%x", getTag()); OS << format(" [%u] %c\n", abbrCode, AbbrevDecl->hasChildren() ? '*' : ' '); // Dump all data in the DIE for the attributes. for (const auto &AttrSpec : AbbrevDecl->attributes()) { if (AttrSpec.Form == DW_FORM_implicit_const) { // We are dumping .debug_info section , // implicit_const attribute values are not really stored here, // but in .debug_abbrev section. So we just skip such attrs. continue; } dumpAttribute(OS, *this, &offset, AttrSpec.Attr, AttrSpec.Form, Indent); } DWARFDie child = getFirstChild(); if (RecurseDepth > 0 && child) { while (child) { child.dump(OS, RecurseDepth-1, Indent+2); child = child.getSibling(); } } } else { OS << "Abbreviation code not found in 'debug_abbrev' class for code: " << abbrCode << '\n'; } } else { OS.indent(Indent) << "NULL\n"; } } }
bool DWARFUnit::parseDWO() { if (isDWO) return false; if (DWO.get()) return false; DWARFDie UnitDie = getUnitDIE(); if (!UnitDie) return false; auto DWOFileName = dwarf::toString(UnitDie.find(DW_AT_GNU_dwo_name)); if (!DWOFileName) return false; auto CompilationDir = dwarf::toString(UnitDie.find(DW_AT_comp_dir)); SmallString<16> AbsolutePath; if (sys::path::is_relative(*DWOFileName) && CompilationDir && *CompilationDir) { sys::path::append(AbsolutePath, *CompilationDir); } sys::path::append(AbsolutePath, *DWOFileName); auto DWOId = getDWOId(); if (!DWOId) return false; auto DWOContext = Context.getDWOContext(AbsolutePath); if (!DWOContext) return false; DWARFCompileUnit *DWOCU = DWOContext->getDWOCompileUnitForHash(*DWOId); if (!DWOCU) return false; DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU); // Share .debug_addr and .debug_ranges section with compile unit in .dwo DWO->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); if (getVersion() >= 5) { DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, isLittleEndian, 0); if (auto TableOrError = parseRngListTableHeader(RangesDA, RangeSectionBase)) DWO->RngListTable = TableOrError.get(); else WithColor::error() << "parsing a range list table: " << toString(TableOrError.takeError()) << '\n'; if (DWO->RngListTable) DWO->RangeSectionBase = DWO->RngListTable->getHeaderSize(); } else { auto DWORangesBase = UnitDie.getRangesBaseAttribute(); DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); } return true; }
/// Recursively dump the DIE type name when applicable. static void dumpTypeName(raw_ostream &OS, const DWARFDie &Die) { DWARFDie D = Die.getAttributeValueAsReferencedDie(DW_AT_type); if (!D.isValid()) return; if (const char *Name = D.getName(DINameKind::LinkageName)) { OS << Name; return; } // FIXME: We should have pretty printers per language. Currently we print // everything as if it was C++ and fall back to the TAG type name. const dwarf::Tag T = D.getTag(); switch (T) { case DW_TAG_array_type: case DW_TAG_pointer_type: case DW_TAG_ptr_to_member_type: case DW_TAG_reference_type: case DW_TAG_rvalue_reference_type: break; default: dumpTypeTagName(OS, T); } // Follow the DW_AT_type if possible. dumpTypeName(OS, D); switch (T) { case DW_TAG_array_type: OS << "[]"; break; case DW_TAG_pointer_type: OS << '*'; break; case DW_TAG_ptr_to_member_type: OS << '*'; break; case DW_TAG_reference_type: OS << '&'; break; case DW_TAG_rvalue_reference_type: OS << "&&"; break; default: break; } }
std::shared_ptr<TypeInfo> DwarfVariableFinder::getType(const DWARFDie &die) { if (!die.isValid()) { assert(0); return std::make_shared<TypeInfo>("", ~0u); } auto die_offset = die.getOffset(); if(typeDict.count(die_offset)) { return typeDict[die_offset]; } auto result = makeType(die); typeDict[die_offset] = result; return result; }
void DwarfVariableFinder::handleVariable(const DWARFDie &die) { //die.dump(outs(), 10); getInfo(die); auto type = getType(die.getAttributeValueAsReferencedDie(dwarf::DW_AT_type)); type->dump(outs()); }
unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die, DWARFAttribute &AttrValue) { const DWARFObject &DObj = DCtx.getDWARFObj(); unsigned NumErrors = 0; const auto Attr = AttrValue.Attr; switch (Attr) { case DW_AT_ranges: // Make sure the offset in the DW_AT_ranges attribute is valid. if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) { if (*SectionOffset >= DObj.getRangeSection().Data.size()) { ++NumErrors; OS << "error: DW_AT_ranges offset is beyond .debug_ranges " "bounds:\n"; Die.dump(OS, 0); OS << "\n"; } } else { ++NumErrors; OS << "error: DIE has invalid DW_AT_ranges encoding:\n"; Die.dump(OS, 0); OS << "\n"; } break; case DW_AT_stmt_list: // Make sure the offset in the DW_AT_stmt_list attribute is valid. if (auto SectionOffset = AttrValue.Value.getAsSectionOffset()) { if (*SectionOffset >= DObj.getLineSection().Data.size()) { ++NumErrors; OS << "error: DW_AT_stmt_list offset is beyond .debug_line " "bounds: " << format("0x%08" PRIx64, *SectionOffset) << "\n"; Die.dump(OS, 0); OS << "\n"; } } else { ++NumErrors; OS << "error: DIE has invalid DW_AT_stmt_list encoding:\n"; Die.dump(OS, 0); OS << "\n"; } break; default: break; } return NumErrors; }
/// Print only DIEs that have a certain name. static void filterByAccelName(ArrayRef<std::string> Names, DWARFContext &DICtx, raw_ostream &OS) { SmallVector<uint64_t, 4> Offsets; for (const auto &Name : Names) { getDIEOffset(DICtx.getAppleNames(), Name, Offsets); getDIEOffset(DICtx.getAppleTypes(), Name, Offsets); getDIEOffset(DICtx.getAppleNamespaces(), Name, Offsets); getDIEOffset(DICtx.getDebugNames(), Name, Offsets); } llvm::sort(Offsets.begin(), Offsets.end()); Offsets.erase(std::unique(Offsets.begin(), Offsets.end()), Offsets.end()); for (uint64_t Off: Offsets) { DWARFDie Die = DICtx.getDIEForOffset(Off); Die.dump(OS, 0, getDumpOpts()); } }
static SmallVector<StringRef, 2> getNames(const DWARFDie &DIE, bool IncludeLinkageName = true) { SmallVector<StringRef, 2> Result; if (const char *Str = DIE.getName(DINameKind::ShortName)) Result.emplace_back(Str); else if (DIE.getTag() == dwarf::DW_TAG_namespace) Result.emplace_back("(anonymous namespace)"); if (IncludeLinkageName) { if (const char *Str = DIE.getName(DINameKind::LinkageName)) { if (Result.empty() || Result[0] != Str) Result.emplace_back(Str); } } return Result; }
void DWARFUnit::getInlinedChainForAddress(uint64_t Address, SmallVectorImpl<DWARFDie> &InlinedChain) { assert(InlinedChain.empty()); // Try to look for subprogram DIEs in the DWO file. parseDWO(); // First, find the subroutine that contains the given address (the leaf // of inlined chain). DWARFDie SubroutineDIE = (DWO ? DWO.get() : this)->getSubroutineForAddress(Address); while (SubroutineDIE) { if (SubroutineDIE.isSubroutineDIE()) InlinedChain.push_back(SubroutineDIE); SubroutineDIE = SubroutineDIE.getParent(); } }
static void dumpArrayType(raw_ostream &OS, const DWARFDie &D) { Optional<uint64_t> Bound; for (const DWARFDie &C : D.children()) if (C.getTag() == DW_TAG_subrange_type) { Optional<uint64_t> LB; Optional<uint64_t> Count; Optional<uint64_t> UB; Optional<unsigned> DefaultLB; if (Optional<DWARFFormValue> L = C.find(DW_AT_lower_bound)) LB = L->getAsUnsignedConstant(); if (Optional<DWARFFormValue> CountV = C.find(DW_AT_count)) Count = CountV->getAsUnsignedConstant(); if (Optional<DWARFFormValue> UpperV = C.find(DW_AT_upper_bound)) UB = UpperV->getAsUnsignedConstant(); if (Optional<DWARFFormValue> LV = D.getDwarfUnit()->getUnitDIE().find(DW_AT_language)) if (Optional<uint64_t> LC = LV->getAsUnsignedConstant()) if ((DefaultLB = LanguageLowerBound(static_cast<dwarf::SourceLanguage>(*LC)))) if (LB && *LB == *DefaultLB) LB = None; if (!LB && !Count && !UB) OS << "[]"; else if (!LB && (Count || UB) && DefaultLB) OS << '[' << (Count ? *Count : *UB - *DefaultLB + 1) << ']'; else { OS << "[["; if (LB) OS << *LB; else OS << '?'; OS << ", "; if (Count) if (LB) OS << *LB + *Count; else OS << "? + " << *Count; else if (UB) OS << *UB + 1; else OS << '?'; OS << ")]"; } } }
void DWARFUnit::getInlinedChainForAddress(uint64_t Address, SmallVectorImpl<DWARFDie> &InlinedChain) { // First, find a subprogram that contains the given address (the root // of inlined chain). DWARFDie SubprogramDIE; // Try to look for subprogram DIEs in the DWO file. parseDWO(); if (DWO) SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address); else SubprogramDIE = getSubprogramForAddress(Address); // Get inlined chain rooted at this subprogram DIE. if (SubprogramDIE) SubprogramDIE.getInlinedChainForAddress(Address, InlinedChain); else InlinedChain.clear(); }
DwarfVariableFinder::DwarfVariableFinder(const DWARFDie &die, raw_ostream &os) : OS(os) { if(!die.hasChildren()) { outs() << "No child \n\n"; return; } for (auto child = die.getFirstChild(); child; child = child.getSibling()) { //Go over all the top level sub_programs if(child.isSubprogramDIE() || child.isSubroutineDIE()) { getInfo(child); //Look for variables among children of sub_program die if(!child.hasChildren()) { continue; } findVariables(child); } } }
size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { if ((CUDieOnly && !DieArray.empty()) || DieArray.size() > 1) return 0; // Already parsed. bool HasCUDie = !DieArray.empty(); extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); if (DieArray.empty()) return 0; // If CU DIE was just parsed, copy several attribute values from it. if (!HasCUDie) { DWARFDie UnitDie = getUnitDIE(); Optional<DWARFFormValue> PC = UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc}); if (Optional<uint64_t> Addr = toAddress(PC)) setBaseAddress({*Addr, PC->getSectionIndex()}); if (!isDWO) { assert(AddrOffsetSectionBase == 0); assert(RangeSectionBase == 0); AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base), 0); RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0); } // In general, we derive the offset of the unit's contibution to the // debug_str_offsets{.dwo} section from the unit DIE's // DW_AT_str_offsets_base attribute. In dwp files we add to it the offset // we get from the index table. StringOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_str_offsets_base), 0); if (IndexEntry) if (const auto *C = IndexEntry->getOffset(DW_SECT_STR_OFFSETS)) StringOffsetSectionBase += C->Offset; // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for // skeleton CU DIE, so that DWARF users not aware of it are not broken. } return DieArray.size(); }