Index: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -57,8 +57,7 @@ /// This data structure is the top level entity that deals with dwarf debug /// information parsing. The actual data is supplied through DWARFObj. class DWARFContext : public DIContext { - DWARFUnitVector CUs; - DWARFUnitVector TUs; + DWARFUnitVector NormalUnits; std::unique_ptr CUIndex; std::unique_ptr GdbIndex; std::unique_ptr TUIndex; @@ -75,8 +74,7 @@ std::unique_ptr AppleNamespaces; std::unique_ptr AppleObjC; - DWARFUnitVector DWOCUs; - DWARFUnitVector DWOTUs; + DWARFUnitVector DWOUnits; std::unique_ptr AbbrevDWO; std::unique_ptr LocDWO; @@ -95,22 +93,17 @@ std::unique_ptr RegInfo; /// Read compile units from the debug_info section (if necessary) - /// and store them in CUs. - void parseCompileUnits(); - - /// Read type units from the debug_types sections (if necessary) - /// and store them in TUs. - void parseTypeUnits(); + /// and type units from the debug_types sections (if necessary) + /// and store them in NormalUnits. + void parseNormalUnits(); /// Read compile units from the debug_info.dwo section (if necessary) - /// and store them in DWOCUs. - void parseDWOCompileUnits(); - - /// Read type units from the debug_types.dwo section (if necessary) - /// and store them in DWOTUs. - void parseDWOTypeUnits(); + /// and type units from the debug_types.dwo section (if necessary) + /// and store them in DWOUnits. + /// If \p Lazy is true, set up to parse but don't actually parse them. + enum { EagerParse = false, LazyParse = true }; + void parseDWOUnits(bool Lazy = false); -protected: std::unique_ptr DObj; public: @@ -142,64 +135,81 @@ using cu_iterator_range = DWARFUnitVector::iterator_range; using tu_iterator_range = DWARFUnitVector::iterator_range; - /// Get compile units in this context. - cu_iterator_range compile_units() { - parseCompileUnits(); - return cu_iterator_range(CUs.begin(), CUs.end()); + /// Get units from .debug_info in this context. + cu_iterator_range info_section_units() { + parseNormalUnits(); + return cu_iterator_range(NormalUnits.begin(), + NormalUnits.begin() + + NormalUnits.getNumInfoUnits()); } + /// Get units from .debug_types in this context. + tu_iterator_range types_section_units() { + parseNormalUnits(); + return tu_iterator_range( + NormalUnits.begin() + NormalUnits.getNumInfoUnits(), NormalUnits.end()); + } + + /// Get compile units in this context. + cu_iterator_range compile_units() { return info_section_units(); } + /// Get type units in this context. - tu_iterator_range type_units() { - parseTypeUnits(); - return tu_iterator_range(TUs.begin(), TUs.end()); + tu_iterator_range type_units() { return types_section_units(); } + + /// Get units from .debug_info..dwo in the DWO context. + cu_iterator_range dwo_info_section_units() { + parseDWOUnits(); + return cu_iterator_range(DWOUnits.begin(), + DWOUnits.begin() + DWOUnits.getNumInfoUnits()); } - /// Get compile units in the DWO context. - cu_iterator_range dwo_compile_units() { - parseDWOCompileUnits(); - return cu_iterator_range(DWOCUs.begin(), DWOCUs.end()); + /// Get units from .debug_types.dwo in the DWO context. + tu_iterator_range dwo_types_section_units() { + parseDWOUnits(); + return tu_iterator_range(DWOUnits.begin() + DWOUnits.getNumInfoUnits(), + DWOUnits.end()); } + /// Get compile units in the DWO context. + cu_iterator_range dwo_compile_units() { return dwo_info_section_units(); } + /// Get type units in the DWO context. - tu_iterator_range dwo_type_units() { - parseDWOTypeUnits(); - return tu_iterator_range(DWOTUs.begin(), DWOTUs.end()); - } + tu_iterator_range dwo_type_units() { return dwo_types_section_units(); } /// Get the number of compile units in this context. unsigned getNumCompileUnits() { - parseCompileUnits(); - return CUs.size(); + parseNormalUnits(); + return NormalUnits.getNumInfoUnits(); } - /// Get the number of compile units in this context. + /// Get the number of type units in this context. unsigned getNumTypeUnits() { - parseTypeUnits(); - return TUs.size(); + parseNormalUnits(); + return NormalUnits.getNumTypesUnits(); } /// Get the number of compile units in the DWO context. unsigned getNumDWOCompileUnits() { - parseDWOCompileUnits(); - return DWOCUs.size(); + parseDWOUnits(); + return DWOUnits.getNumInfoUnits(); } - /// Get the number of compile units in the DWO context. + /// Get the number of type units in the DWO context. unsigned getNumDWOTypeUnits() { - parseDWOTypeUnits(); - return DWOTUs.size(); + parseDWOUnits(); + return DWOUnits.getNumTypesUnits(); } /// Get the unit at the specified index. DWARFUnit *getUnitAtIndex(unsigned index) { - parseCompileUnits(); - return CUs[index].get(); + parseNormalUnits(); + return NormalUnits[index].get(); } /// Get the unit at the specified index for the DWO units. DWARFUnit *getDWOUnitAtIndex(unsigned index) { - parseDWOCompileUnits(); - return DWOCUs[index].get(); + parseDWOUnits(); + return DWOUnits[index].get(); } DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash); Index: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -104,10 +104,13 @@ const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, DWARFSectionKind Kind); -/// Describes one section's Units. +/// Describe a collection of units. Intended to hold all units either from +/// .debug_info and .debug_types, or from .debug_info.dwo and .debug_types.dwo. class DWARFUnitVector final : public SmallVector, 1> { - std::function(uint32_t, const DWARFSection *)> + std::function(uint32_t, DWARFSectionKind, + const DWARFSection *)> Parser; + unsigned NumInfoUnits = 0; public: using UnitVector = SmallVectorImpl>; @@ -116,11 +119,31 @@ DWARFUnit *getUnitForOffset(uint32_t Offset) const; DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E); + + /// Read units from a .debug_info or .debug_types section. Calls made + /// before finishedInfoUnits() are assumed to be for .debug_info sections, + /// calls after finishedInfoUnits() are for .debug_types sections. Caller + /// must not mix calls to addUnitsForSection and addUnitsForDWOSection. void addUnitsForSection(DWARFContext &C, const DWARFSection &Section, DWARFSectionKind SectionKind); + /// Read units from a .debug_info.dwo or .debug_types.dwo section. Calls + /// made before finishedInfoUnits() are assumed to be for .debug_info.dwo + /// sections, calls after finishedInfoUnits() are for .debug_types.dwo + /// sections. Caller must not mix calls to addUnitsForSection and + /// addUnitsForDWOSection. void addUnitsForDWOSection(DWARFContext &C, const DWARFSection &DWOSection, DWARFSectionKind SectionKind, bool Lazy = false); + /// Returns number of all units held by this instance. + unsigned getNumUnits() { return size(); } + /// Returns number of units from all .debug_info[.dwo] sections. + unsigned getNumInfoUnits() { return NumInfoUnits; } + /// Returns number of units from all .debug_types[.dwo] sections. + unsigned getNumTypesUnits() { return size() - NumInfoUnits; } + /// Indicate that parsing .debug_info[.dwo] is done, and remaining units + /// will be from .debug_types[.dwo]. + void finishedInfoUnits() { NumInfoUnits = size(); } + private: void addUnitsImpl(DWARFContext &Context, const DWARFObject &Obj, const DWARFSection &Section, const DWARFDebugAbbrev *DA, @@ -238,6 +261,7 @@ virtual ~DWARFUnit(); DWARFContext& getContext() const { return Context; } + const DWARFSection &getInfoSection() const { return InfoSection; } uint32_t getOffset() const { return Header.getOffset(); } const dwarf::FormParams &getFormParams() const { return Header.getFormParams(); Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -351,9 +351,9 @@ } }; dumpDebugInfo(Explicit, ".debug_info", DObj->getInfoSection(), - compile_units()); + info_section_units()); dumpDebugInfo(ExplicitDWO, ".debug_info.dwo", DObj->getInfoDWOSection(), - dwo_compile_units()); + dwo_info_section_units()); auto dumpDebugType = [&](const char *Name, tu_iterator_range TUs) { OS << '\n' << Name << " contents:\n"; @@ -367,9 +367,9 @@ }; if ((DumpType & DIDT_DebugTypes)) { if (Explicit || getNumTypeUnits()) - dumpDebugType(".debug_types", type_units()); + dumpDebugType(".debug_types", types_section_units()); if (ExplicitDWO || getNumDWOTypeUnits()) - dumpDebugType(".debug_types.dwo", dwo_type_units()); + dumpDebugType(".debug_types.dwo", dwo_types_section_units()); } if (shouldDump(Explicit, ".debug_loc", DIDT_ID_DebugLoc, @@ -581,13 +581,12 @@ } DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) { - if (DWOCUs.empty()) - DWOCUs.addUnitsForDWOSection(*this, DObj->getInfoDWOSection(), DW_SECT_INFO, - true); + parseDWOUnits(LazyParse); if (const auto &CUI = getCUIndex()) { if (const auto *R = CUI.getFromHash(Hash)) - return dyn_cast_or_null(DWOCUs.getUnitForIndexEntry(*R)); + return dyn_cast_or_null( + DWOUnits.getUnitForIndexEntry(*R)); return nullptr; } @@ -612,8 +611,8 @@ } DWARFDie DWARFContext::getDIEForOffset(uint32_t Offset) { - parseCompileUnits(); - if (auto *CU = CUs.getUnitForOffset(Offset)) + parseNormalUnits(); + if (auto *CU = NormalUnits.getUnitForOffset(Offset)) return CU->getDIEForOffset(Offset); return DWARFDie(); } @@ -842,37 +841,31 @@ RecoverableErrorCallback); } -void DWARFContext::parseCompileUnits() { - if (!CUs.empty()) - return; - CUs.addUnitsForSection(*this, DObj->getInfoSection(), DW_SECT_INFO); -} - -void DWARFContext::parseTypeUnits() { - if (!TUs.empty()) +void DWARFContext::parseNormalUnits() { + if (!NormalUnits.empty()) return; + NormalUnits.addUnitsForSection(*this, DObj->getInfoSection(), DW_SECT_INFO); + NormalUnits.finishedInfoUnits(); DObj->forEachTypesSections([&](const DWARFSection &S) { - TUs.addUnitsForSection(*this, S, DW_SECT_TYPES); + NormalUnits.addUnitsForSection(*this, S, DW_SECT_TYPES); }); } -void DWARFContext::parseDWOCompileUnits() { - if (!DWOCUs.empty()) - return; - DWOCUs.addUnitsForDWOSection(*this, DObj->getInfoDWOSection(), DW_SECT_INFO); -} - -void DWARFContext::parseDWOTypeUnits() { - if (!DWOTUs.empty()) +void DWARFContext::parseDWOUnits(bool Lazy) { + if (!DWOUnits.empty()) return; + DWOUnits.addUnitsForDWOSection(*this, DObj->getInfoDWOSection(), DW_SECT_INFO, + Lazy); + DWOUnits.finishedInfoUnits(); DObj->forEachTypesDWOSections([&](const DWARFSection &S) { - DWOTUs.addUnitsForDWOSection(*this, S, DW_SECT_TYPES); + DWOUnits.addUnitsForDWOSection(*this, S, DW_SECT_TYPES, Lazy); }); } DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) { - parseCompileUnits(); - return dyn_cast_or_null(CUs.getUnitForOffset(Offset)); + parseNormalUnits(); + return dyn_cast_or_null( + NormalUnits.getUnitForOffset(Offset)); } DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) { Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -62,16 +62,16 @@ DWARFDataExtractor Data(Obj, Section, LE, 0); // Lazy initialization of Parser, now that we have all section info. if (!Parser) { - const DWARFUnitIndex *Index = nullptr; - if (IsDWO) - Index = &getDWARFUnitIndex(Context, SectionKind); Parser = [=, &Context, &Obj, &Section, &SOS, &LS]( - uint32_t Offset, + uint32_t Offset, DWARFSectionKind SectionKind, const DWARFSection *CurSection) -> std::unique_ptr { const DWARFSection &InfoSection = CurSection ? *CurSection : Section; DWARFDataExtractor Data(Obj, InfoSection, LE, 0); if (!Data.isValidOffset(Offset)) return nullptr; + const DWARFUnitIndex *Index = nullptr; + if (IsDWO) + Index = &getDWARFUnitIndex(Context, SectionKind); DWARFUnitHeader Header; if (!Header.extract(Context, Data, &Offset, SectionKind, Index)) return nullptr; @@ -89,14 +89,21 @@ } if (Lazy) return; + // Find a reasonable insertion point within the vector. We skip over + // (a) units from a different section, (b) units from the same section + // but with lower offset-within-section. This keeps units in order + // within a section, although not necessarily within the object file, + // even if we do lazy parsing. auto I = this->begin(); uint32_t Offset = 0; while (Data.isValidOffset(Offset)) { - if (I != this->end() && (*I)->getOffset() == Offset) { + if (I != this->end() && + (&(*I)->getInfoSection() != &Section || (*I)->getOffset() == Offset)) { ++I; continue; } - auto U = Parser(Offset, &Section); + auto U = Parser(Offset, SectionKind, &Section); + // If parsing failed, we're done with this section. if (!U) break; Offset = U->getNextUnitOffset(); @@ -134,7 +141,7 @@ if (!Parser) return nullptr; - auto U = Parser(Offset, nullptr); + auto U = Parser(Offset, DW_SECT_INFO, nullptr); if (!U) U = nullptr;