Index: include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h +++ include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h @@ -26,8 +26,8 @@ class DWARFFormValue; struct DWARFDebugInfoEntryInlinedChain; -/// DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data. -class DWARFDebugInfoEntryMinimal { +/// DWARFDebugInfoEntry - A DIE with only the minimum required data. +class DWARFDebugInfoEntry { /// Offset within the .debug_info of the start of this entry. uint32_t Offset; @@ -36,15 +36,9 @@ const DWARFAbbreviationDeclaration *AbbrevDecl; public: - DWARFDebugInfoEntryMinimal() + DWARFDebugInfoEntry() : Offset(0), SiblingIdx(0), AbbrevDecl(nullptr) {} - void dump(raw_ostream &OS, DWARFUnit *u, unsigned recurseDepth, - unsigned indent = 0) const; - void dumpAttribute(raw_ostream &OS, DWARFUnit *u, uint32_t *offset_ptr, - dwarf::Attribute attr, dwarf::Form form, - unsigned indent = 0) const; - /// Extracts a debug info entry, which is a child of a given unit, /// starting at a given offset. If DIE can't be extracted, returns false and /// doesn't change OffsetPtr. @@ -53,35 +47,23 @@ bool extractFast(const DWARFUnit &U, uint32_t *OffsetPtr, const DataExtractor &DebugInfoData, uint32_t UEndOffset); - dwarf::Tag getTag() const { - return AbbrevDecl ? AbbrevDecl->getTag() : dwarf::DW_TAG_null; - } - - bool isNULL() const { return AbbrevDecl == nullptr; } - - /// Returns true if DIE represents a subprogram (not inlined). - bool isSubprogramDIE() const; - /// Returns true if DIE represents a subprogram or an inlined - /// subroutine. - bool isSubroutineDIE() const; - uint32_t getOffset() const { return Offset; } - bool hasChildren() const { return !isNULL() && AbbrevDecl->hasChildren(); } + bool hasChildren() const { return AbbrevDecl && AbbrevDecl->hasChildren(); } // We know we are kept in a vector of contiguous entries, so we know // our sibling will be some index after "this". - const DWARFDebugInfoEntryMinimal *getSibling() const { + const DWARFDebugInfoEntry *getSibling() const { return SiblingIdx > 0 ? this + SiblingIdx : nullptr; } // We know we are kept in a vector of contiguous entries, so we know // we don't need to store our child pointer, if we have a child it will // be the next entry in the list... - const DWARFDebugInfoEntryMinimal *getFirstChild() const { + const DWARFDebugInfoEntry *getFirstChild() const { return hasChildren() ? this + 1 : nullptr; } - void setSibling(const DWARFDebugInfoEntryMinimal *Sibling) { + void setSibling(const DWARFDebugInfoEntry *Sibling) { if (Sibling) { // We know we are kept in a vector of contiguous entries, so we know // our sibling will be some index after "this". @@ -93,83 +75,8 @@ const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const { return AbbrevDecl; } - - bool getAttributeValue(const DWARFUnit *U, dwarf::Attribute Attr, - DWARFFormValue &FormValue) const; - - const char *getAttributeValueAsString(const DWARFUnit *U, - dwarf::Attribute Attr, - const char *FailValue) const; - - uint64_t getAttributeValueAsAddress(const DWARFUnit *U, - dwarf::Attribute Attr, - uint64_t FailValue) const; - - int64_t getAttributeValueAsSignedConstant(const DWARFUnit *U, - dwarf::Attribute Attr, - int64_t FailValue) const; - - uint64_t getAttributeValueAsUnsignedConstant(const DWARFUnit *U, - dwarf::Attribute Attr, - uint64_t FailValue) const; - - uint64_t getAttributeValueAsReference(const DWARFUnit *U, - dwarf::Attribute Attr, - uint64_t FailValue) const; - - uint64_t getAttributeValueAsSectionOffset(const DWARFUnit *U, - dwarf::Attribute Attr, - uint64_t FailValue) const; - - uint64_t getRangesBaseAttribute(const DWARFUnit *U, uint64_t FailValue) const; - - /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU. - /// Returns true if both attributes are present. - bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC, - uint64_t &HighPC) const; - - DWARFAddressRangesVector getAddressRanges(const DWARFUnit *U) const; - - void collectChildrenAddressRanges(const DWARFUnit *U, - DWARFAddressRangesVector &Ranges) const; - - bool addressRangeContainsAddress(const DWARFUnit *U, - const uint64_t Address) const; - - /// If a DIE represents a subprogram (or inlined subroutine), - /// returns its mangled name (or short name, if mangled is missing). - /// This name may be fetched from specification or abstract origin - /// for this subprogram. Returns null if no name is found. - const char *getSubroutineName(const DWARFUnit *U, DINameKind Kind) const; - - /// Return the DIE name resolving DW_AT_sepcification or - /// DW_AT_abstract_origin references if necessary. - /// Returns null if no name is found. - const char *getName(const DWARFUnit *U, DINameKind Kind) const; - - /// Retrieves values of DW_AT_call_file, DW_AT_call_line and - /// DW_AT_call_column from DIE (or zeroes if they are missing). - void getCallerFrame(const DWARFUnit *U, uint32_t &CallFile, - uint32_t &CallLine, uint32_t &CallColumn) const; - - /// Get inlined chain for a given address, rooted at the current DIE. - /// Returns empty chain if address is not contained in address range - /// of current DIE. - DWARFDebugInfoEntryInlinedChain - getInlinedChainForAddress(const DWARFUnit *U, const uint64_t Address) const; }; -/// DWARFDebugInfoEntryInlinedChain - represents a chain of inlined_subroutine -/// DIEs, (possibly ending with subprogram DIE), all of which are contained -/// in some concrete inlined instance tree. Address range for each DIE -/// (except the last DIE) in this chain is contained in address -/// range for next DIE in the chain. -struct DWARFDebugInfoEntryInlinedChain { - DWARFDebugInfoEntryInlinedChain() : U(nullptr) {} - SmallVector DIEs; - const DWARFUnit *U; -}; - } #endif Index: include/llvm/DebugInfo/DWARF/DWARFDie.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFDie.h +++ include/llvm/DebugInfo/DWARF/DWARFDie.h @@ -0,0 +1,310 @@ +//===-- DWARFDie.h --------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDIE_H +#define LLVM_LIB_DEBUGINFO_DWARFDIE_H + +#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" + +namespace llvm { + +class DWARFUnit; +class DWARFDebugInfoEntry; +class raw_ostream; + +//===----------------------------------------------------------------------===// +/// Utility class that carries the DWARF compile/type unit and the debug info +/// entry in an object. +/// +/// When accessing information from a debug info entry we always need to DWARF +/// compile/type unit in order to extract the info correctly as some information +/// is relative to the compile/type unit. Prior to this class the DWARFUnit and +/// the DWARFDebugInfoEntry was passed around separately and there was the +/// possibility for error if the wrong DWARFUnit was used to extract a unit +/// relative offset. This class helps to ensure that this doesn't happen and +/// also simplifies the attribute extraction calls by not having to specify the +/// DWARFUnit for each call. +class DWARFDie { + DWARFUnit *U; + const DWARFDebugInfoEntry *Die; +public: + DWARFDie() : U(nullptr), Die(nullptr) {} + DWARFDie(DWARFUnit *Unit, const DWARFDebugInfoEntry * D) : U(Unit), Die(D) {} + + bool isValid() const { return U && Die; } + explicit operator bool() const { return isValid(); } + const DWARFDebugInfoEntry *getDebugInfoEntry() const { return Die; } + DWARFUnit *getDwarfUnit() const { return U; } + + + /// Get the abbreviation declaration for this DIE. + /// + /// \returns the abbreviation declaration or NULL for null tags. + const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const { + if (Die) + return Die->getAbbreviationDeclarationPtr(); + return nullptr; + } + + /// Get the absolute offset into the debug info or types section. + /// + /// \returns the DIE offset or -1U if invalid. + uint32_t getOffset() const { + if (Die) + return Die->getOffset(); + return -1U; + } + + dwarf::Tag getTag() const { + auto AbbrevDecl = getAbbreviationDeclarationPtr(); + if (AbbrevDecl) + return AbbrevDecl->getTag(); + return dwarf::DW_TAG_null; + } + + bool hasChildren() const { + if (Die) + return Die->hasChildren(); + return false; + } + + /// Returns true for a valid DIE that terminates a sibling chain. + /// + /// Returns true if this object is valid and it actually has no abbreviation + /// which indicates that the abbreviation code was zero. If the object isn't + /// valid, like a default constructed DWARFDie, then we don't want to say it + /// is NULL. + bool isNULL() const { + return isValid() && getAbbreviationDeclarationPtr() == nullptr; + } + /// Returns true if DIE represents a subprogram (not inlined). + bool isSubprogramDIE() const; + + /// Returns true if DIE represents a subprogram or an inlined subroutine. + bool isSubroutineDIE() const; + + + /// Get the silbing of this DIE object. + /// + /// \returns a valid DWARFDie instance if this object has a sibling or an + /// invalid DWARFDie instance if it doesn't. + DWARFDie getSibling() const { + if (isValid()) + return DWARFDie(U, Die->getSibling()); + return DWARFDie(); + } + + /// Get the first child of this DIE object. + /// + /// \returns a valid DWARFDie instance if this object has children or an + /// invalid DWARFDie instance if it doesn't. + DWARFDie getFirstChild() const { + if (isValid()) + return DWARFDie(U, Die->getFirstChild()); + return DWARFDie(); + } + + /// Dump the DIE and all of its attributes to the supplied stream. + /// + /// \param OS the stream to use for output. + /// \param recurseDepth the depth to recurse to when dumping this DIE and its + /// children. + /// \param indent the number of characters to indent each line that is output. + void dump(raw_ostream &OS, unsigned recurseDepth, unsigned indent = 0) const; + + /// Extract the specified attribute from this DIE. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \param FormValue contains the attribute value if true is returned. + /// \returns true if the attribute was extracted from this DIE. + bool getAttributeValue(dwarf::Attribute Attr, + DWARFFormValue &FormValue) const; + + /// Extract the specified attribute from this DIE as a C string. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \param FailValue the value to return if this DIE doesn't have this + /// attribute. + /// \returns the NULL terminated C string value owned by the DWARF section + /// that contains the string or FailValue if the attribute doesn't exist or + /// if the attribute's form isn't a form that describes an string. + const char *getAttributeValueAsString(dwarf::Attribute Attr, + const char *FailValue) const; + + /// Extract the specified attribute from this DIE as an address. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \param FailValue the value to return if this DIE doesn't have this + /// attribute. + /// \returns the address value of the attribute or FailValue if the + /// attribute doesn't exist or if the attribute's form isn't a form that + /// describes an address. + uint64_t getAttributeValueAsAddress(dwarf::Attribute Attr, + uint64_t FailValue) const; + + /// Extract the specified attribute from this DIE as a signed integer. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \param FailValue the value to return if this DIE doesn't have this + /// attribute. + /// \returns the signed integer constant value of the attribute or FailValue + /// if the attribute doesn't exist or if the attribute's form isn't a form + /// that describes a signed integer. + int64_t getAttributeValueAsSignedConstant(dwarf::Attribute Attr, + int64_t FailValue) const; + + /// Extract the specified attribute from this DIE as an unsigned integer. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \param FailValue the value to return if this DIE doesn't have this + /// attribute. + /// \returns the unsigned integer constant value of the attribute or FailValue + /// if the attribute doesn't exist or if the attribute's form isn't a form + /// that describes an unsigned integer. + uint64_t getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr, + uint64_t FailValue) const; + + /// Extract the specified attribute from this DIE as absolute DIE Offset. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \param FailValue the value to return if this DIE doesn't have this + /// attribute. + /// \returns the unsigned integer constant value of the attribute or FailValue + /// if the attribute doesn't exist or if the attribute's form isn't a form + /// that describes a reference. + uint64_t getAttributeValueAsReference(dwarf::Attribute Attr, + uint64_t FailValue) const; + + /// Extract the specified attribute from this DIE as absolute section offset. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \param FailValue the value to return if this DIE doesn't have this + /// attribute. + /// \returns the unsigned integer constant value of the attribute or FailValue + /// if the attribute doesn't exist or if the attribute's form isn't a form + /// that describes a section offset. + uint64_t getAttributeValueAsSectionOffset(dwarf::Attribute Attr, + uint64_t FailValue) const; + + /// Extract the specified attribute from this DIE as the referenced DIE. + /// + /// Regardless of the reference type, return the correct DWARFDie instance if + /// the attribute exists. The returned DWARFDie object might be from another + /// DWARFUnit, but that is all encapsulated in the new DWARFDie object. + /// + /// Extract an attribute value from this DIE only. This call doesn't look + /// for the attribute value in any DW_AT_specification or + /// DW_AT_abstract_origin referenced DIEs. + /// + /// \param Attr the attribute to extract. + /// \returns a valid DWARFDie instance if the attribute exists, or an invalid + /// DWARFDie object if it doesn't. + DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const; + + /// Extract the range base attribute from this DIE as absolute section offset. + /// + /// This is a utility function that checks for either the DW_AT_rnglists_base + /// or DW_AT_GNU_ranges_base attribute. + /// + /// \returns the absolute section offset value of the attribute or FailValue + /// if the attribute doesn't exist. + uint64_t getRangesBaseAttribute(uint64_t FailValue) const; + + /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU. + /// Returns true if both attributes are present. + bool getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const; + + /// Get the address ranges for this DIE. + /// + /// Get the hi/low PC range if both attributes are available or exrtracts the + /// non-contiguous address ranges from the DW_AT_ranges attribute. + /// + /// Extracts the range information from this DIE only. This call doesn't look + /// for the range in any DW_AT_specification or DW_AT_abstract_origin DIEs. + /// + /// \returns a address range vector that might be empty if no address range + /// information is available. + DWARFAddressRangesVector getAddressRanges() const; + + /// Get all address ranges for any DW_TAG_subprogram DIEs in this DIE or any + /// of its children. + /// + /// Get the hi/low PC range if both attributes are available or exrtracts the + /// non-contiguous address ranges from the DW_AT_ranges attribute for this DIE + /// and all children. + /// + /// \param Ranges the addres range vector to fill in. + void collectChildrenAddressRanges(DWARFAddressRangesVector &Ranges) const; + + bool addressRangeContainsAddress(const uint64_t Address) const; + + /// If a DIE represents a subprogram (or inlined subroutine), returns its + /// mangled name (or short name, if mangled is missing). This name may be + /// fetched from specification or abstract origin for this subprogram. + /// Returns null if no name is found. + const char *getSubroutineName(DINameKind Kind) const; + + /// Return the DIE name resolving DW_AT_sepcification or DW_AT_abstract_origin + /// references if necessary. Returns null if no name is found. + const char *getName(DINameKind Kind) const; + + /// Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column + /// from DIE (or zeroes if they are missing). This function looks for + /// DW_AT_call attributes in this DIE only, it will not resolve the attribute + /// values in any DW_AT_specification or DW_AT_abstract_origin DIEs. + /// \param CallFile filled in with non-zero if successful, zero if there is no + /// DW_AT_call_file attribute in this DIE. + /// \param CallLine filled in with non-zero if successful, zero if there is no + /// DW_AT_call_line attribute in this DIE. + /// \param CallColumn filled in with non-zero if successful, zero if there is + /// no DW_AT_call_column attribute in this DIE. + void getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, + uint32_t &CallColumn) const; + + /// Get inlined chain for a given address, rooted at the current DIE. + /// Returns empty chain if address is not contained in address range + /// of current DIE. + void + getInlinedChainForAddress(const uint64_t Address, + SmallVectorImpl &InlinedChain) const; + +}; + + +} // end namespace llvm + +#endif // LLVM_LIB_DEBUGINFO_DWARFDIE_H Index: include/llvm/DebugInfo/DWARF/DWARFUnit.h =================================================================== --- include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -14,6 +14,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" @@ -124,7 +125,7 @@ uint8_t AddrSize; uint64_t BaseAddr; // The compile unit debug information entry items. - std::vector DieArray; + std::vector DieArray; class DWOHolder { object::OwningBinary DWOFile; @@ -214,9 +215,11 @@ BaseAddr = base_addr; } - const DWARFDebugInfoEntryMinimal *getUnitDIE(bool ExtractUnitDIEOnly = true) { + DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) { extractDIEsIfNeeded(ExtractUnitDIEOnly); - return DieArray.empty() ? nullptr : &DieArray[0]; + if (DieArray.empty()) + return DWARFDie(); + return DWARFDie(this, &DieArray[0]); } const char *getCompilationDir(); @@ -227,7 +230,8 @@ /// getInlinedChainForAddress - fetches inlined chain for a given address. /// Returns empty chain if there is no subprogram containing address. The /// chain is valid as long as parsed compile unit DIEs are not cleared. - DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(uint64_t Address); + void getInlinedChainForAddress(uint64_t Address, + SmallVectorImpl &InlinedChain); /// getUnitSection - Return the DWARFUnitSection containing this unit. const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; } @@ -245,31 +249,35 @@ /// created by this unit. In other word, it's illegal to call this /// method on a DIE that isn't accessible by following /// children/sibling links starting from this unit's getUnitDIE(). - uint32_t getDIEIndex(const DWARFDebugInfoEntryMinimal *DIE) { + uint32_t getDIEIndex(const DWARFDie &D) { + auto DIE = D.getDebugInfoEntry(); assert(!DieArray.empty() && DIE >= &DieArray[0] && DIE < &DieArray[0] + DieArray.size()); return DIE - &DieArray[0]; } /// \brief Return the DIE object at the given index. - const DWARFDebugInfoEntryMinimal *getDIEAtIndex(unsigned Index) const { - assert(Index < DieArray.size()); - return &DieArray[Index]; + DWARFDie getDIEAtIndex(unsigned Index) { + if (Index < DieArray.size()) + return DWARFDie(this, &DieArray[Index]); + return DWARFDie(); } /// \brief Return the DIE object for a given offset inside the /// unit's DIE vector. /// /// The unit needs to have its DIEs extracted for this method to work. - const DWARFDebugInfoEntryMinimal *getDIEForOffset(uint32_t Offset) { + DWARFDie getDIEForOffset(uint32_t Offset) { extractDIEsIfNeeded(false); assert(!DieArray.empty()); auto it = std::lower_bound( DieArray.begin(), DieArray.end(), Offset, - [](const DWARFDebugInfoEntryMinimal &LHS, uint32_t Offset) { + [](const DWARFDebugInfoEntry &LHS, uint32_t Offset) { return LHS.getOffset() < Offset; }); - return it == DieArray.end() ? nullptr : &*it; + if (it == DieArray.end()) + return DWARFDie(); + return DWARFDie(this, &*it); } uint32_t getLineTableOffset() const { @@ -288,7 +296,7 @@ size_t extractDIEsIfNeeded(bool CUDieOnly); /// extractDIEsToVector - Appends all parsed DIEs to a vector. void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs, - std::vector &DIEs) const; + std::vector &DIEs) const; /// setDIERelations - We read in all of the DIE entries into our flat list /// of DIE entries and now we need to go back through all of them and set the /// parent, sibling and child pointers for quick DIE navigation. @@ -303,7 +311,7 @@ /// getSubprogramForAddress - Returns subprogram DIE with address range /// encompassing the provided address. The pointer is alive as long as parsed /// compile unit DIEs are not cleared. - const DWARFDebugInfoEntryMinimal *getSubprogramForAddress(uint64_t Address); + DWARFDie getSubprogramForAddress(uint64_t Address); }; } Index: lib/DebugInfo/DWARF/CMakeLists.txt =================================================================== --- lib/DebugInfo/DWARF/CMakeLists.txt +++ lib/DebugInfo/DWARF/CMakeLists.txt @@ -12,6 +12,7 @@ DWARFDebugLoc.cpp DWARFDebugMacro.cpp DWARFDebugRangeList.cpp + DWARFDie.cpp DWARFFormValue.cpp DWARFGdbIndex.cpp DWARFTypeUnit.cpp Index: lib/DebugInfo/DWARF/DWARFCompileUnit.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFCompileUnit.cpp +++ lib/DebugInfo/DWARF/DWARFCompileUnit.cpp @@ -9,7 +9,7 @@ #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" +#include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" @@ -24,8 +24,8 @@ << " (next unit at " << format("0x%08x", getNextUnitOffset()) << ")\n"; - if (const DWARFDebugInfoEntryMinimal *CU = getUnitDIE(false)) - CU->dump(OS, this, -1U); + if (DWARFDie CUDie = getUnitDIE(false)) + CUDie.dump(OS, -1U); else OS << "\n\n"; } Index: lib/DebugInfo/DWARF/DWARFContext.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFContext.cpp +++ lib/DebugInfo/DWARF/DWARFContext.cpp @@ -156,11 +156,11 @@ OS << "\n.debug_line contents:\n"; for (const auto &CU : compile_units()) { savedAddressByteSize = CU->getAddressByteSize(); - const auto *CUDIE = CU->getUnitDIE(); - if (CUDIE == nullptr) + auto CUDIE = CU->getUnitDIE(); + if (!CUDIE) continue; - unsigned stmtOffset = CUDIE->getAttributeValueAsSectionOffset( - CU.get(), DW_AT_stmt_list, -1U); + unsigned stmtOffset = CUDIE.getAttributeValueAsSectionOffset( + DW_AT_stmt_list, -1U); if (stmtOffset != -1U) { DataExtractor lineData(getLineSection().Data, isLittleEndian(), savedAddressByteSize); @@ -412,12 +412,12 @@ if (!Line) Line.reset(new DWARFDebugLine(&getLineSection().Relocs)); - const auto *UnitDIE = U->getUnitDIE(); - if (UnitDIE == nullptr) + auto UnitDIE = U->getUnitDIE(); + if (!UnitDIE) return nullptr; unsigned stmtOffset = - UnitDIE->getAttributeValueAsSectionOffset(U, DW_AT_stmt_list, -1U); + UnitDIE.getAttributeValueAsSectionOffset(DW_AT_stmt_list, -1U); if (stmtOffset == -1U) return nullptr; // No line table for this compile unit. @@ -477,14 +477,12 @@ return false; // The address may correspond to instruction in some inlined function, // so we have to build the chain of inlined functions and take the - // name of the topmost function in it. - const DWARFDebugInfoEntryInlinedChain &InlinedChain = - CU->getInlinedChainForAddress(Address); - if (InlinedChain.DIEs.size() == 0) + // name of the topmost function in it.SmallVectorImpl &InlinedChain + SmallVector InlinedChain; + CU->getInlinedChainForAddress(Address, InlinedChain); + if (InlinedChain.size() == 0) return false; - const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0]; - if (const char *Name = - TopFunctionDIE.getSubroutineName(InlinedChain.U, Kind)) { + if (const char *Name = InlinedChain[0].getSubroutineName(Kind)) { FunctionName = Name; return true; } @@ -559,9 +557,9 @@ return InliningInfo; const DWARFLineTable *LineTable = nullptr; - const DWARFDebugInfoEntryInlinedChain &InlinedChain = - CU->getInlinedChainForAddress(Address); - if (InlinedChain.DIEs.size() == 0) { + SmallVector InlinedChain; + CU->getInlinedChainForAddress(Address, InlinedChain); + if (InlinedChain.size() == 0) { // If there is no DIE for address (e.g. it is in unavailable .dwo file), // try to at least get file/line info from symbol table. if (Spec.FLIKind != FileLineInfoKind::None) { @@ -576,12 +574,11 @@ } uint32_t CallFile = 0, CallLine = 0, CallColumn = 0; - for (uint32_t i = 0, n = InlinedChain.DIEs.size(); i != n; i++) { - const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain.DIEs[i]; + for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) { + DWARFDie &FunctionDIE = InlinedChain[i]; DILineInfo Frame; // Get function name if necessary. - if (const char *Name = - FunctionDIE.getSubroutineName(InlinedChain.U, Spec.FNKind)) + if (const char *Name = FunctionDIE.getSubroutineName(Spec.FNKind)) Frame.FunctionName = Name; if (Spec.FLIKind != FileLineInfoKind::None) { if (i == 0) { @@ -603,8 +600,7 @@ } // Get call file/line/column of a current DIE. if (i + 1 < n) { - FunctionDIE.getCallerFrame(InlinedChain.U, CallFile, CallLine, - CallColumn); + FunctionDIE.getCallerFrame(CallFile, CallLine, CallColumn); } } InliningInfo.addFrame(Frame); Index: lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp +++ lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -22,174 +22,13 @@ using namespace dwarf; using namespace syntax; -// 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 = u->getDebugInfoExtractor(); - 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) { - 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()) { - dumpAttribute(OS, u, &offset, AttrSpec.Attr, AttrSpec.Form, indent); - } - - const DWARFDebugInfoEntryMinimal *child = getFirstChild(); - if (recurseDepth > 0 && child) { - while (child) { - child->dump(OS, u, 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"; - } - } -} - -static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) { - OS << " ("; - do { - uint64_t Shift = countTrailingZeros(Val); - assert(Shift < 64 && "undefined behavior"); - uint64_t Bit = 1ULL << Shift; - auto PropName = ApplePropertyString(Bit); - if (!PropName.empty()) - 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, - DWARFUnit *u, - uint32_t *offset_ptr, - dwarf::Attribute attr, - dwarf::Form form, - unsigned indent) const { - const char BaseIndent[] = " "; - OS << BaseIndent; - OS.indent(indent+2); - auto attrString = AttributeString(attr); - if (!attrString.empty()) - WithColor(OS, syntax::Attribute) << attrString; - else - WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", attr); - - auto formString = FormEncodingString(form); - if (!formString.empty()) - OS << " [" << formString << ']'; - else - OS << format(" [DW_FORM_Unknown_%x]", form); - - DWARFFormValue formValue(form); - - if (!formValue.extractValue(u->getDebugInfoExtractor(), offset_ptr, u)) - return; - - OS << "\t("; - - StringRef Name; - std::string File; - auto Color = syntax::Enumerator; - if (attr == DW_AT_decl_file || attr == DW_AT_call_file) { - Color = syntax::String; - if (const auto *LT = u->getContext().getLineTableForUnit(u)) - if (LT->getFileNameByIndex( - formValue.getAsUnsignedConstant().getValue(), - u->getCompilationDir(), - DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) { - File = '"' + File + '"'; - Name = File; - } - } else if (Optional Val = formValue.getAsUnsignedConstant()) - Name = AttributeValueString(attr, *Val); - - if (!Name.empty()) - WithColor(OS, Color) << Name; - else if (attr == DW_AT_decl_line || attr == DW_AT_call_line) - OS << *formValue.getAsUnsignedConstant(); - else - formValue.dump(OS); - - // 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) { - Optional Ref = formValue.getAsReference(); - if (Ref.hasValue()) { - uint32_t RefOffset = Ref.getValue(); - DWARFDebugInfoEntryMinimal DIE; - if (const DWARFUnit *RefU = findUnitAndExtractFast(DIE, u, &RefOffset)) - if (const char *Name = DIE.getName(RefU, DINameKind::LinkageName)) - OS << " \"" << Name << '\"'; - } - } 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 DWARFUnit &U, +bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint32_t *OffsetPtr) { DataExtractor DebugInfoData = U.getDebugInfoExtractor(); const uint32_t UEndOffset = U.getNextUnitOffset(); return extractFast(U, OffsetPtr, DebugInfoData, UEndOffset); } -bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit &U, +bool DWARFDebugInfoEntry::extractFast(const DWARFUnit &U, uint32_t *OffsetPtr, const DataExtractor &DebugInfoData, uint32_t UEndOffset) { @@ -231,237 +70,3 @@ } return true; } - -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::getAttributeValue(const DWARFUnit *U, - dwarf::Attribute Attr, DWARFFormValue &FormValue) const { - if (!AbbrevDecl || !U) - return false; - return AbbrevDecl->getAttributeValue(Offset, Attr, *U, FormValue); -} - -const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString( - const DWARFUnit *U, dwarf::Attribute Attr, - const char *FailValue) const { - DWARFFormValue FormValue; - if (!getAttributeValue(U, Attr, FormValue)) - return FailValue; - Optional Result = FormValue.getAsCString(); - return Result.hasValue() ? Result.getValue() : FailValue; -} - -uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress( - const DWARFUnit *U, dwarf::Attribute Attr, - uint64_t FailValue) const { - DWARFFormValue FormValue; - if (!getAttributeValue(U, Attr, FormValue)) - return FailValue; - Optional Result = FormValue.getAsAddress(); - return Result.hasValue() ? Result.getValue() : FailValue; -} - -int64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSignedConstant( - const DWARFUnit *U, dwarf::Attribute Attr, int64_t FailValue) const { - DWARFFormValue FormValue; - if (!getAttributeValue(U, Attr, FormValue)) - return FailValue; - Optional Result = FormValue.getAsSignedConstant(); - return Result.hasValue() ? Result.getValue() : FailValue; -} - -uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsignedConstant( - const DWARFUnit *U, dwarf::Attribute 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::getAttributeValueAsReference( - const DWARFUnit *U, dwarf::Attribute Attr, - uint64_t FailValue) const { - DWARFFormValue FormValue; - if (!getAttributeValue(U, Attr, FormValue)) - return FailValue; - Optional Result = FormValue.getAsReference(); - return Result.hasValue() ? Result.getValue() : FailValue; -} - -uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSectionOffset( - const DWARFUnit *U, dwarf::Attribute 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::getRangesBaseAttribute(const DWARFUnit *U, - uint64_t FailValue) const { - uint64_t Result = - getAttributeValueAsSectionOffset(U, DW_AT_rnglists_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::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; -} - -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; -} Index: lib/DebugInfo/DWARF/DWARFDie.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFDie.cpp +++ lib/DebugInfo/DWARF/DWARFDie.cpp @@ -0,0 +1,391 @@ +//===-- DWARFDie.cpp ------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/DWARF/DWARFDie.h" +#include "SyntaxHighlighting.h" +#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" +#include "llvm/DebugInfo/DWARF/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; +using namespace syntax; + +namespace { + static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) { + OS << " ("; + do { + uint64_t Shift = countTrailingZeros(Val); + assert(Shift < 64 && "undefined behavior"); + uint64_t Bit = 1ULL << Shift; + auto PropName = ApplePropertyString(Bit); + if (!PropName.empty()) + 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); + } +} + +static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die, + uint32_t *OffsetPtr, dwarf::Attribute Attr, + dwarf::Form Form, unsigned Indent) { + if (!Die.isValid()) + return; + const char BaseIndent[] = " "; + OS << BaseIndent; + OS.indent(Indent+2); + auto attrString = AttributeString(Attr); + if (!attrString.empty()) + WithColor(OS, syntax::Attribute) << attrString; + else + WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", Attr); + + auto formString = FormEncodingString(Form); + if (!formString.empty()) + OS << " [" << formString << ']'; + else + OS << format(" [DW_FORM_Unknown_%x]", Form); + + DWARFUnit *U = Die.getDwarfUnit(); + DWARFFormValue formValue(Form); + + if (!formValue.extractValue(U->getDebugInfoExtractor(), OffsetPtr, U)) + return; + + OS << "\t("; + + StringRef Name; + std::string File; + auto Color = syntax::Enumerator; + if (Attr == DW_AT_decl_file || Attr == DW_AT_call_file) { + Color = syntax::String; + if (const auto *LT = U->getContext().getLineTableForUnit(U)) + if (LT->getFileNameByIndex(formValue.getAsUnsignedConstant().getValue(), U->getCompilationDir(), DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) { + File = '"' + File + '"'; + Name = File; + } + } else if (Optional Val = formValue.getAsUnsignedConstant()) + Name = AttributeValueString(Attr, *Val); + + if (!Name.empty()) + WithColor(OS, Color) << Name; + else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line) + OS << *formValue.getAsUnsignedConstant(); + else + formValue.dump(OS); + + // 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) { + if (const char *Name = Die.getAttributeValueAsReferencedDie(Attr).getName(DINameKind::LinkageName)) + OS << " \"" << Name << '\"'; + } else if (Attr == DW_AT_APPLE_property_attribute) { + if (Optional OptVal = formValue.getAsUnsignedConstant()) + dumpApplePropertyAttribute(OS, *OptVal); + } else if (Attr == DW_AT_ranges) { + dumpRanges(OS, Die.getAddressRanges(), U->getAddressByteSize(), + sizeof(BaseIndent)+Indent+4); + } + + OS << ")\n"; +} + +} // end anonymous namespace + +bool DWARFDie::isSubprogramDIE() const { + return getTag() == DW_TAG_subprogram; +} + +bool DWARFDie::isSubroutineDIE() const { + auto Tag = getTag(); + return Tag == DW_TAG_subprogram || Tag == DW_TAG_inlined_subroutine; +} + +bool DWARFDie::getAttributeValue(dwarf::Attribute Attr, + DWARFFormValue &FormValue) const { + if (!U) + return false; + auto AbbrevDecl = getAbbreviationDeclarationPtr(); + if (AbbrevDecl) + return AbbrevDecl->getAttributeValue(getOffset(), Attr, *U, FormValue); + return false; +} + +const char *DWARFDie::getAttributeValueAsString(dwarf::Attribute Attr, + const char *FailValue) const { + DWARFFormValue FormValue; + if (!getAttributeValue(Attr, FormValue)) + return FailValue; + Optional Result = FormValue.getAsCString(); + return Result.hasValue() ? Result.getValue() : FailValue; +} + +uint64_t DWARFDie::getAttributeValueAsAddress(dwarf::Attribute Attr, + uint64_t FailValue) const { + DWARFFormValue FormValue; + if (!getAttributeValue(Attr, FormValue)) + return FailValue; + Optional Result = FormValue.getAsAddress(); + return Result.hasValue() ? Result.getValue() : FailValue; +} + +int64_t DWARFDie::getAttributeValueAsSignedConstant(dwarf::Attribute Attr, + int64_t FailValue) const { + DWARFFormValue FormValue; + if (!getAttributeValue(Attr, FormValue)) + return FailValue; + Optional Result = FormValue.getAsSignedConstant(); + return Result.hasValue() ? Result.getValue() : FailValue; +} + +uint64_t +DWARFDie::getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr, + uint64_t FailValue) const { + DWARFFormValue FormValue; + if (!getAttributeValue(Attr, FormValue)) + return FailValue; + Optional Result = FormValue.getAsUnsignedConstant(); + return Result.hasValue() ? Result.getValue() : FailValue; +} + +uint64_t DWARFDie::getAttributeValueAsReference(dwarf::Attribute Attr, + uint64_t FailValue) const { + DWARFFormValue FormValue; + if (!getAttributeValue(Attr, FormValue)) + return FailValue; + Optional Result = FormValue.getAsReference(); + return Result.hasValue() ? Result.getValue() : FailValue; +} + +uint64_t DWARFDie::getAttributeValueAsSectionOffset(dwarf::Attribute Attr, + uint64_t FailValue) const { + DWARFFormValue FormValue; + if (!getAttributeValue(Attr, FormValue)) + return FailValue; + Optional Result = FormValue.getAsSectionOffset(); + return Result.hasValue() ? Result.getValue() : FailValue; +} + +DWARFDie +DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const { + uint32_t SpecRef = getAttributeValueAsReference(Attr, -1U); + if (SpecRef != -1U) { + auto SpecUnit = U->getUnitSection().getUnitForOffset(SpecRef); + if (SpecUnit) + return SpecUnit->getDIEForOffset(SpecRef); + } + return DWARFDie(); +} + +uint64_t +DWARFDie::getRangesBaseAttribute(uint64_t FailValue) const { + auto Result = getAttributeValueAsSectionOffset(DW_AT_rnglists_base, -1ULL); + if (Result != -1ULL) + return Result; + return getAttributeValueAsSectionOffset(DW_AT_GNU_ranges_base, FailValue); +} + +bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const { + LowPC = getAttributeValueAsAddress(DW_AT_low_pc, -1ULL); + if (LowPC == -1ULL) + return false; + HighPC = getAttributeValueAsAddress(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(DW_AT_high_pc, -1ULL); + if (HighPC != -1ULL) + HighPC += LowPC; + } + return (HighPC != -1ULL); +} + +DWARFAddressRangesVector +DWARFDie::getAddressRanges() const { + if (isNULL()) + return DWARFAddressRangesVector(); + // Single range specified by low/high PC. + uint64_t LowPC, HighPC; + if (getLowAndHighPC(LowPC, HighPC)) { + return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC)); + } + // Multiple ranges from .debug_ranges section. + uint32_t RangesOffset = getAttributeValueAsSectionOffset(DW_AT_ranges, -1U); + if (RangesOffset != -1U) { + DWARFDebugRangeList RangeList; + if (U->extractRangeList(RangesOffset, RangeList)) + return RangeList.getAbsoluteRanges(U->getBaseAddress()); + } + return DWARFAddressRangesVector(); +} + +void +DWARFDie::collectChildrenAddressRanges(DWARFAddressRangesVector& Ranges) const { + if (isNULL()) + return; + if (isSubprogramDIE()) { + const auto &DIERanges = getAddressRanges(); + Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end()); + } + + DWARFDie Child = getFirstChild(); + while (Child) { + Child.collectChildrenAddressRanges(Ranges); + Child = Child.getSibling(); + } +} + +bool DWARFDie::addressRangeContainsAddress(const uint64_t Address) const { + for (const auto& R : getAddressRanges()) { + if (R.first <= Address && Address < R.second) + return true; + } + return false; +} + +const char * +DWARFDie::getSubroutineName(DINameKind Kind) const { + if (!isSubroutineDIE()) + return nullptr; + return getName(Kind); +} + +const char * +DWARFDie::getName(DINameKind Kind) const { + if (!isValid() || Kind == DINameKind::None) + return nullptr; + const char *name = nullptr; + // Try to get mangled name only if it was asked for. + if (Kind == DINameKind::LinkageName) { + if ((name = getAttributeValueAsString(DW_AT_MIPS_linkage_name, nullptr))) + return name; + if ((name = getAttributeValueAsString(DW_AT_linkage_name, nullptr))) + return name; + } + if ((name = getAttributeValueAsString(DW_AT_name, nullptr))) + return name; + // Try to get name from specification DIE. + DWARFDie SpecDie = getAttributeValueAsReferencedDie(DW_AT_specification); + if (SpecDie && (name = SpecDie.getName(Kind))) + return name; + // Try to get name from abstract origin DIE. + DWARFDie AbsDie = getAttributeValueAsReferencedDie(DW_AT_abstract_origin); + if (AbsDie && (name = AbsDie.getName(Kind))) + return name; + return nullptr; +} + +void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, + uint32_t &CallColumn) const { + CallFile = getAttributeValueAsUnsignedConstant(DW_AT_call_file, 0); + CallLine = getAttributeValueAsUnsignedConstant(DW_AT_call_line, 0); + CallColumn = getAttributeValueAsUnsignedConstant(DW_AT_call_column, 0); +} + +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()) { + 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"; + } + } +} + + +void DWARFDie::getInlinedChainForAddress( + const uint64_t Address, SmallVectorImpl &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()); +} + Index: lib/DebugInfo/DWARF/DWARFTypeUnit.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFTypeUnit.cpp +++ lib/DebugInfo/DWARF/DWARFTypeUnit.cpp @@ -25,11 +25,10 @@ } void DWARFTypeUnit::dump(raw_ostream &OS, bool SummarizeTypes) { - const DWARFDebugInfoEntryMinimal *TD = - getDIEForOffset(TypeOffset + getOffset()); + DWARFDie TD = getDIEForOffset(TypeOffset + getOffset()); DWARFFormValue NameVal; const char *Name = ""; - if (TD->getAttributeValue(this, llvm::dwarf::DW_AT_name, NameVal)) + if (TD.getAttributeValue(llvm::dwarf::DW_AT_name, NameVal)) if (auto ON = NameVal.getAsCString()) Name = *ON; @@ -50,8 +49,8 @@ << " type_offset = " << format("0x%04x", TypeOffset) << " (next unit at " << format("0x%08x", getNextUnitOffset()) << ")\n"; - if (const DWARFDebugInfoEntryMinimal *TU = getUnitDIE(false)) - TU->dump(OS, this, -1U); + if (DWARFDie TU = getUnitDIE(false)) + TU.dump(OS, -1U); else OS << "\n\n"; } Index: lib/DebugInfo/DWARF/DWARFUnit.cpp =================================================================== --- lib/DebugInfo/DWARF/DWARFUnit.cpp +++ lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -151,27 +151,20 @@ } const char *DWARFUnit::getCompilationDir() { - extractDIEsIfNeeded(true); - if (DieArray.empty()) - return nullptr; - return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); + return getUnitDIE().getAttributeValueAsString(DW_AT_comp_dir, nullptr); } uint64_t DWARFUnit::getDWOId() { - extractDIEsIfNeeded(true); - const uint64_t FailValue = -1ULL; - if (DieArray.empty()) - return FailValue; - return DieArray[0] - .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue); + return getUnitDIE().getAttributeValueAsUnsignedConstant(DW_AT_GNU_dwo_id, + -1ULL); } void DWARFUnit::setDIERelations() { if (DieArray.size() <= 1) return; - std::vector ParentChain; - DWARFDebugInfoEntryMinimal *SiblingChain = nullptr; + std::vector ParentChain; + DWARFDebugInfoEntry *SiblingChain = nullptr; for (auto &DIE : DieArray) { if (SiblingChain) { SiblingChain->setSibling(&DIE); @@ -197,7 +190,7 @@ void DWARFUnit::extractDIEsToVector( bool AppendCUDie, bool AppendNonCUDies, - std::vector &Dies) const { + std::vector &Dies) const { if (!AppendCUDie && !AppendNonCUDies) return; @@ -205,7 +198,7 @@ // next compilation unit header. uint32_t DIEOffset = Offset + getHeaderSize(); uint32_t NextCUOffset = getNextUnitOffset(); - DWARFDebugInfoEntryMinimal DIE; + DWARFDebugInfoEntry DIE; DataExtractor DebugInfoData = getDebugInfoExtractor(); uint32_t Depth = 0; bool IsCUDie = true; @@ -260,15 +253,15 @@ // If CU DIE was just parsed, copy several attribute values from it. if (!HasCUDie) { - uint64_t BaseAddr = - DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL); + DWARFDie UnitDie = getUnitDIE(); + uint64_t BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_low_pc, -1ULL); if (BaseAddr == -1ULL) - BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0); + BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_entry_pc, 0); setBaseAddress(BaseAddr); - AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset( - this, DW_AT_GNU_addr_base, 0); - RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset( - this, DW_AT_rnglists_base, 0); + 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. } @@ -297,15 +290,15 @@ return false; if (DWO.get()) return false; - extractDIEsIfNeeded(true); - if (DieArray.empty()) + DWARFDie UnitDie = getUnitDIE(); + if (!UnitDie) return false; const char *DWOFileName = - DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, nullptr); + UnitDie.getAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr); if (!DWOFileName) return false; const char *CompilationDir = - DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); + UnitDie.getAttributeValueAsString(DW_AT_comp_dir, nullptr); SmallString<16> AbsolutePath; if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) { sys::path::append(AbsolutePath, CompilationDir); @@ -320,7 +313,7 @@ } // Share .debug_addr and .debug_ranges section with compile unit in .dwo DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); - uint32_t DWORangesBase = DieArray[0].getRangesBaseAttribute(this, 0); + uint32_t DWORangesBase = UnitDie.getRangesBaseAttribute(0); DWOCU->setRangesSection(RangeSection, DWORangesBase); return true; } @@ -334,7 +327,7 @@ // contents which will cause just the internal pointers to be swapped // so that when temporary vector goes out of scope, it will destroy the // contents. - std::vector TmpArray; + std::vector TmpArray; DieArray.swap(TmpArray); // Save at least the compile unit DIE if (KeepCUDie) @@ -343,11 +336,11 @@ } void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { - const auto *U = getUnitDIE(); - if (U == nullptr) + DWARFDie UnitDie = getUnitDIE(); + if (!UnitDie) return; // First, check if unit DIE describes address ranges for the whole unit. - const auto &CUDIERanges = U->getAddressRanges(this); + const auto &CUDIERanges = UnitDie.getAddressRanges(); if (!CUDIERanges.empty()) { CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end()); return; @@ -360,7 +353,7 @@ // up parsing the DWARF and then throwing them all away to keep memory usage // down. const bool ClearDIEs = extractDIEsIfNeeded(false) > 1; - DieArray[0].collectChildrenAddressRanges(this, CURanges); + getUnitDIE().collectChildrenAddressRanges(CURanges); // Collect address ranges from DIEs in .dwo if necessary. bool DWOCreated = parseDWO(); @@ -375,36 +368,37 @@ clearDIEs(true); } -const DWARFDebugInfoEntryMinimal * +DWARFDie DWARFUnit::getSubprogramForAddress(uint64_t Address) { extractDIEsIfNeeded(false); - for (const DWARFDebugInfoEntryMinimal &DIE : DieArray) { + for (const DWARFDebugInfoEntry &D : DieArray) { + DWARFDie DIE(this, &D); if (DIE.isSubprogramDIE() && - DIE.addressRangeContainsAddress(this, Address)) { - return &DIE; + DIE.addressRangeContainsAddress(Address)) { + return DIE; } } - return nullptr; + return DWARFDie(); } -DWARFDebugInfoEntryInlinedChain -DWARFUnit::getInlinedChainForAddress(uint64_t Address) { +void +DWARFUnit::getInlinedChainForAddress(uint64_t Address, + SmallVectorImpl &InlinedChain) { // First, find a subprogram that contains the given address (the root // of inlined chain). - const DWARFUnit *ChainCU = nullptr; - const DWARFDebugInfoEntryMinimal *SubprogramDIE; + DWARFDie SubprogramDIE; // Try to look for subprogram DIEs in the DWO file. parseDWO(); - if (DWO) { - if ((SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address))) - ChainCU = DWO->getUnit(); - } else if ((SubprogramDIE = getSubprogramForAddress(Address))) - ChainCU = this; + if (DWO) + SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address); + else + SubprogramDIE = getSubprogramForAddress(Address); // Get inlined chain rooted at this subprogram DIE. - if (!SubprogramDIE) - return DWARFDebugInfoEntryInlinedChain(); - return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address); + if (SubprogramDIE) + SubprogramDIE.getInlinedChainForAddress(Address, InlinedChain); + else + InlinedChain.clear(); } const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, Index: tools/dsymutil/DwarfLinker.cpp =================================================================== --- tools/dsymutil/DwarfLinker.cpp +++ tools/dsymutil/DwarfLinker.cpp @@ -102,7 +102,7 @@ StringRef Name; StringRef File; const DeclContext &Parent; - const DWARFDebugInfoEntryMinimal *LastSeenDIE; + DWARFDie LastSeenDIE; uint32_t LastSeenCompileUnitID; uint32_t CanonicalDIEOffset; @@ -114,19 +114,18 @@ DeclContext() : QualifiedNameHash(0), Line(0), ByteSize(0), Tag(dwarf::DW_TAG_compile_unit), Name(), File(), Parent(*this), - LastSeenDIE(nullptr), LastSeenCompileUnitID(0), CanonicalDIEOffset(0) {} + LastSeenDIE(), LastSeenCompileUnitID(0), CanonicalDIEOffset(0) {} DeclContext(unsigned Hash, uint32_t Line, uint32_t ByteSize, uint16_t Tag, StringRef Name, StringRef File, const DeclContext &Parent, - const DWARFDebugInfoEntryMinimal *LastSeenDIE = nullptr, - unsigned CUId = 0) + DWARFDie LastSeenDIE = DWARFDie(), unsigned CUId = 0) : QualifiedNameHash(Hash), Line(Line), ByteSize(ByteSize), Tag(Tag), Name(Name), File(File), Parent(Parent), LastSeenDIE(LastSeenDIE), LastSeenCompileUnitID(CUId), CanonicalDIEOffset(0) {} uint32_t getQualifiedNameHash() const { return QualifiedNameHash; } - bool setLastSeenDIE(CompileUnit &U, const DWARFDebugInfoEntryMinimal *Die); + bool setLastSeenDIE(CompileUnit &U, const DWARFDie &Die); uint32_t getCanonicalDIEOffset() const { return CanonicalDIEOffset; } void setCanonicalDIEOffset(uint32_t Offset) { CanonicalDIEOffset = Offset; } @@ -174,7 +173,7 @@ /// emulate some dsymutil-classic functionality. PointerIntPair getChildDeclContext(DeclContext &Context, - const DWARFDebugInfoEntryMinimal *DIE, CompileUnit &Unit, + const DWARFDie &DIE, CompileUnit &Unit, NonRelocatableStringpool &StringPool, bool InClangModule); DeclContext &getRoot() { return Root; } @@ -200,14 +199,13 @@ StringRef ClangModuleName) : OrigUnit(OrigUnit), ID(ID), NewUnit(OrigUnit.getVersion(), OrigUnit.getAddressByteSize(), - OrigUnit.getUnitDIE()->getTag()), + OrigUnit.getUnitDIE().getTag()), LowPc(UINT64_MAX), HighPc(0), RangeAlloc(), Ranges(RangeAlloc), ClangModuleName(ClangModuleName) { Info.resize(OrigUnit.getNumDIEs()); - const auto *CUDie = OrigUnit.getUnitDIE(false); - unsigned Lang = CUDie->getAttributeValueAsUnsignedConstant( - &OrigUnit, dwarf::DW_AT_language, 0); + auto CUDie = OrigUnit.getUnitDIE(false); + unsigned Lang = CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_language, 0); HasODR = CanUseODR && (Lang == dwarf::DW_LANG_C_plus_plus || Lang == dwarf::DW_LANG_C_plus_plus_03 || Lang == dwarf::DW_LANG_C_plus_plus_11 || @@ -841,10 +839,10 @@ const DWARFSection &InputSec = Dwarf.getLocSection(); DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize); DWARFUnit &OrigUnit = Unit.getOrigUnit(); - const auto *OrigUnitDie = OrigUnit.getUnitDIE(false); + auto OrigUnitDie = OrigUnit.getUnitDIE(false); int64_t UnitPcOffset = 0; - uint64_t OrigLowPc = OrigUnitDie->getAttributeValueAsAddress( - &OrigUnit, dwarf::DW_AT_low_pc, -1ULL); + uint64_t OrigLowPc = OrigUnitDie.getAttributeValueAsAddress( + dwarf::DW_AT_low_pc, -1ULL); if (OrigLowPc != -1ULL) UnitPcOffset = int64_t(OrigLowPc) - Unit.getLowPc(); @@ -1116,8 +1114,8 @@ /// \brief Link the contents of the DebugMap. bool link(const DebugMap &); - void reportWarning(const Twine &Warning, const DWARFUnit *Unit = nullptr, - const DWARFDebugInfoEntryMinimal *DIE = nullptr) const; + void reportWarning(const Twine &Warning, + const DWARFDie *DIE = nullptr) const; private: /// \brief Called at the start of a debug object link. @@ -1193,7 +1191,7 @@ /// \brief Recursively walk the \p DIE tree and look for DIEs to /// keep. Store that information in \p CU's DIEInfo. void lookForDIEsToKeep(RelocationManager &RelocMgr, - const DWARFDebugInfoEntryMinimal &DIE, + const DWARFDie &DIE, const DebugMapObject &DMO, CompileUnit &CU, unsigned Flags); @@ -1203,7 +1201,7 @@ /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name /// pointing to the module, and a DW_AT_gnu_dwo_id with the module /// hash. - bool registerModuleReference(const DWARFDebugInfoEntryMinimal &CUDie, + bool registerModuleReference(const DWARFDie &CUDie, const DWARFUnit &Unit, DebugMap &ModuleMap, unsigned Indent = 0); @@ -1227,23 +1225,23 @@ /// \brief Mark the passed DIE as well as all the ones it depends on /// as kept. void keepDIEAndDependencies(RelocationManager &RelocMgr, - const DWARFDebugInfoEntryMinimal &DIE, + const DWARFDie &DIE, CompileUnit::DIEInfo &MyInfo, const DebugMapObject &DMO, CompileUnit &CU, bool UseODR); unsigned shouldKeepDIE(RelocationManager &RelocMgr, - const DWARFDebugInfoEntryMinimal &DIE, + const DWARFDie &DIE, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags); unsigned shouldKeepVariableDIE(RelocationManager &RelocMgr, - const DWARFDebugInfoEntryMinimal &DIE, + const DWARFDie &DIE, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags); unsigned shouldKeepSubprogramDIE(RelocationManager &RelocMgr, - const DWARFDebugInfoEntryMinimal &DIE, + const DWARFDie &DIE, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags); @@ -1283,7 +1281,7 @@ /// applied to the entry point of the function to get the linked address. /// \param Die the output DIE to use, pass NULL to create one. /// \returns the root of the cloned tree or null if nothing was selected. - DIE *cloneDIE(const DWARFDebugInfoEntryMinimal &InputDIE, CompileUnit &U, + DIE *cloneDIE(const DWARFDie &InputDIE, CompileUnit &U, int64_t PCOffset, uint32_t OutOffset, unsigned Flags, DIE *Die = nullptr); @@ -1316,7 +1314,7 @@ /// Helper for cloneDIE. unsigned cloneAttribute(DIE &Die, - const DWARFDebugInfoEntryMinimal &InputDIE, + const DWARFDie &InputDIE, CompileUnit &U, const DWARFFormValue &Val, const AttributeSpec AttrSpec, unsigned AttrSize, AttributesInfo &AttrInfo); @@ -1333,7 +1331,7 @@ /// \returns the size of the new attribute. unsigned cloneDieReferenceAttribute(DIE &Die, - const DWARFDebugInfoEntryMinimal &InputDIE, + const DWARFDie &InputDIE, AttributeSpec AttrSpec, unsigned AttrSize, const DWARFFormValue &Val, CompileUnit &Unit); @@ -1354,7 +1352,7 @@ /// Clone a scalar attribute and add it to \p Die. /// \returns the size of the new attribute. unsigned cloneScalarAttribute(DIE &Die, - const DWARFDebugInfoEntryMinimal &InputDIE, + const DWARFDie &InputDIE, CompileUnit &U, AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize, AttributesInfo &Info); @@ -1363,8 +1361,7 @@ /// described by \p Die and store them in \Info if they are not /// already there. /// \returns is a name was found. - bool getDIENames(const DWARFDebugInfoEntryMinimal &Die, DWARFUnit &U, - AttributesInfo &Info); + bool getDIENames(const DWARFDie &Die, AttributesInfo &Info); /// Create a copy of abbreviation Abbrev. void copyAbbrev(const DWARFAbbreviationDeclaration &Abbrev, bool hasODR); @@ -1480,19 +1477,19 @@ /// extracted in \p RefValue. The resulting DIE migh be in another /// CompileUnit which is stored into \p ReferencedCU. /// \returns null if resolving fails for any reason. -static const DWARFDebugInfoEntryMinimal *resolveDIEReference( +static DWARFDie resolveDIEReference( const DwarfLinker &Linker, std::vector> &Units, const DWARFFormValue &RefValue, const DWARFUnit &Unit, - const DWARFDebugInfoEntryMinimal &DIE, CompileUnit *&RefCU) { + const DWARFDie &DIE, CompileUnit *&RefCU) { assert(RefValue.isFormClass(DWARFFormValue::FC_Reference)); uint64_t RefOffset = *RefValue.getAsReference(); if ((RefCU = getUnitForOffset(Units, RefOffset))) - if (const auto *RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) + if (const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) return RefDie; - Linker.reportWarning("could not find referenced DIE", &Unit, &DIE); - return nullptr; + Linker.reportWarning("could not find referenced DIE", &DIE); + return DWARFDie(); } /// \returns whether the passed \a Attr type might contain a DIE @@ -1526,7 +1523,7 @@ /// If a context that is not a namespace appears twice in the same CU, /// we know it is ambiguous. Make it invalid. bool DeclContext::setLastSeenDIE(CompileUnit &U, - const DWARFDebugInfoEntryMinimal *Die) { + const DWARFDie &Die) { if (LastSeenCompileUnitID == U.getUniqueID()) { DWARFUnit &OrigUnit = U.getOrigUnit(); uint32_t FirstIdx = OrigUnit.getDIEIndex(LastSeenDIE); @@ -1540,9 +1537,9 @@ } PointerIntPair DeclContextTree::getChildDeclContext( - DeclContext &Context, const DWARFDebugInfoEntryMinimal *DIE, CompileUnit &U, + DeclContext &Context, const DWARFDie &DIE, CompileUnit &U, NonRelocatableStringpool &StringPool, bool InClangModule) { - unsigned Tag = DIE->getTag(); + unsigned Tag = DIE.getTag(); // FIXME: dsymutil-classic compat: We should bail out here if we // have a specification or an abstract_origin. We will get the @@ -1560,8 +1557,7 @@ // Do not unique anything inside CU local functions. if ((Context.getTag() == dwarf::DW_TAG_namespace || Context.getTag() == dwarf::DW_TAG_compile_unit) && - !DIE->getAttributeValueAsUnsignedConstant(&U.getOrigUnit(), - dwarf::DW_AT_external, 0)) + !DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_external, 0)) return PointerIntPair(nullptr); LLVM_FALLTHROUGH; case dwarf::DW_TAG_member: @@ -1575,14 +1571,13 @@ // created on demand. For example implicitely defined constructors // are ambiguous because of the way we identify contexts, and they // won't be generated everytime everywhere. - if (DIE->getAttributeValueAsUnsignedConstant(&U.getOrigUnit(), - dwarf::DW_AT_artificial, 0)) + if (DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_artificial, 0)) return PointerIntPair(nullptr); break; } - const char *Name = DIE->getName(&U.getOrigUnit(), DINameKind::LinkageName); - const char *ShortName = DIE->getName(&U.getOrigUnit(), DINameKind::ShortName); + const char *Name = DIE.getName(DINameKind::LinkageName); + const char *ShortName = DIE.getName(DINameKind::ShortName); StringRef NameRef; StringRef ShortNameRef; StringRef FileRef; @@ -1616,11 +1611,11 @@ // namespaces, use these additional data points to make the process // safer. This is disabled for clang modules, because forward // declarations of module-defined types do not have a file and line. - ByteSize = DIE->getAttributeValueAsUnsignedConstant( - &U.getOrigUnit(), dwarf::DW_AT_byte_size, UINT64_MAX); + ByteSize = DIE.getAttributeValueAsUnsignedConstant( + dwarf::DW_AT_byte_size, UINT64_MAX); if (Tag != dwarf::DW_TAG_namespace || !Name) { - if (unsigned FileNum = DIE->getAttributeValueAsUnsignedConstant( - &U.getOrigUnit(), dwarf::DW_AT_decl_file, 0)) { + if (unsigned FileNum = DIE.getAttributeValueAsUnsignedConstant( + dwarf::DW_AT_decl_file, 0)) { if (const auto *LT = U.getOrigUnit().getContext().getLineTableForUnit( &U.getOrigUnit())) { // FIXME: dsymutil-classic compatibility. I'd rather not @@ -1633,8 +1628,8 @@ // instead of "" would allow more uniquing, but for now, do // it this way to match dsymutil-classic. if (LT->hasFileAtIndex(FileNum)) { - Line = DIE->getAttributeValueAsUnsignedConstant( - &U.getOrigUnit(), dwarf::DW_AT_decl_line, 0); + Line = DIE.getAttributeValueAsUnsignedConstant( + dwarf::DW_AT_decl_line, 0); // Cache the resolved paths, because calling realpath is expansive. StringRef ResolvedPath = U.getResolvedPath(FileNum); if (!ResolvedPath.empty()) { @@ -1714,16 +1709,16 @@ return PointerIntPair(*ContextIter); } -bool DwarfLinker::DIECloner::getDIENames(const DWARFDebugInfoEntryMinimal &Die, - DWARFUnit &U, AttributesInfo &Info) { +bool DwarfLinker::DIECloner::getDIENames(const DWARFDie &Die, + AttributesInfo &Info) { // FIXME: a bit wasteful as the first getName might return the // short name. if (!Info.MangledName && - (Info.MangledName = Die.getName(&U, DINameKind::LinkageName))) + (Info.MangledName = Die.getName(DINameKind::LinkageName))) Info.MangledNameOffset = Linker.StringPool.getStringOffset(Info.MangledName); - if (!Info.Name && (Info.Name = Die.getName(&U, DINameKind::ShortName))) + if (!Info.Name && (Info.Name = Die.getName(DINameKind::ShortName))) Info.NameOffset = Linker.StringPool.getStringOffset(Info.Name); return Info.Name || Info.MangledName; @@ -1731,8 +1726,8 @@ /// \brief Report a warning to the user, optionaly including /// information about a specific \p DIE related to the warning. -void DwarfLinker::reportWarning(const Twine &Warning, const DWARFUnit *Unit, - const DWARFDebugInfoEntryMinimal *DIE) const { +void DwarfLinker::reportWarning(const Twine &Warning, + const DWARFDie *DIE) const { StringRef Context = ""; if (CurrentDebugObject) Context = CurrentDebugObject->getObjectFilename(); @@ -1742,8 +1737,7 @@ return; errs() << " in DIE:\n"; - DIE->dump(errs(), const_cast(Unit), 0 /* RecurseDepth */, - 6 /* Indent */); + DIE->dump(errs(), 0 /* RecurseDepth */, 6 /* Indent */); } bool DwarfLinker::createStreamer(const Triple &TheTriple, @@ -1761,7 +1755,7 @@ /// \return true when this DIE and all of its children are only /// forward declarations to types defined in external clang modules /// (i.e., forward declarations that are children of a DW_TAG_module). -static bool analyzeContextInfo(const DWARFDebugInfoEntryMinimal *DIE, +static bool analyzeContextInfo(const DWARFDie &DIE, unsigned ParentIdx, CompileUnit &CU, DeclContext *CurrentDeclContext, NonRelocatableStringpool &StringPool, @@ -1782,9 +1776,9 @@ // definitions match)." // // We treat non-C++ modules like namespaces for this reason. - if (DIE->getTag() == dwarf::DW_TAG_module && ParentIdx == 0 && - DIE->getAttributeValueAsString(&CU.getOrigUnit(), dwarf::DW_AT_name, - "") != CU.getClangModuleName()) { + if (DIE.getTag() == dwarf::DW_TAG_module && ParentIdx == 0 && + DIE.getAttributeValueAsString(dwarf::DW_AT_name, + "") != CU.getClangModuleName()) { InImportedModule = true; } @@ -1802,18 +1796,18 @@ } Info.Prune = InImportedModule; - if (DIE->hasChildren()) - for (auto *Child = DIE->getFirstChild(); Child && !Child->isNULL(); - Child = Child->getSibling()) + if (DIE.hasChildren()) + for (auto Child = DIE.getFirstChild(); Child && !Child.isNULL(); + Child = Child.getSibling()) Info.Prune &= analyzeContextInfo(Child, MyIdx, CU, CurrentDeclContext, StringPool, Contexts, InImportedModule); // Prune this DIE if it is either a forward declaration inside a // DW_TAG_module or a DW_TAG_module that contains nothing but // forward declarations. - Info.Prune &= (DIE->getTag() == dwarf::DW_TAG_module) || - DIE->getAttributeValueAsUnsignedConstant( - &CU.getOrigUnit(), dwarf::DW_AT_declaration, 0); + Info.Prune &= (DIE.getTag() == dwarf::DW_TAG_module) || + DIE.getAttributeValueAsUnsignedConstant( + dwarf::DW_AT_declaration, 0); // Don't prune it if there is no definition for the DIE. Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset(); @@ -2071,7 +2065,7 @@ /// \brief Check if a variable describing DIE should be kept. /// \returns updated TraversalFlags. unsigned DwarfLinker::shouldKeepVariableDIE(RelocationManager &RelocMgr, - const DWARFDebugInfoEntryMinimal &DIE, + const DWARFDie &DIE, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags) { @@ -2105,7 +2099,7 @@ return Flags; if (Options.Verbose) - DIE.dump(outs(), const_cast(&OrigUnit), 0, 8 /* Indent */); + DIE.dump(outs(), 0, 8 /* Indent */); return Flags | TF_Keep; } @@ -2114,7 +2108,7 @@ /// \returns updated TraversalFlags. unsigned DwarfLinker::shouldKeepSubprogramDIE( RelocationManager &RelocMgr, - const DWARFDebugInfoEntryMinimal &DIE, CompileUnit &Unit, + const DWARFDie &DIE, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags) { const auto *Abbrev = DIE.getAbbreviationDeclarationPtr(); @@ -2131,21 +2125,21 @@ getAttributeOffsets(Abbrev, *LowPcIdx, Offset, OrigUnit); uint64_t LowPc = - DIE.getAttributeValueAsAddress(&OrigUnit, dwarf::DW_AT_low_pc, -1ULL); + DIE.getAttributeValueAsAddress(dwarf::DW_AT_low_pc, -1ULL); assert(LowPc != -1ULL && "low_pc attribute is not an address."); if (LowPc == -1ULL || !RelocMgr.hasValidRelocation(LowPcOffset, LowPcEndOffset, MyInfo)) return Flags; if (Options.Verbose) - DIE.dump(outs(), const_cast(&OrigUnit), 0, 8 /* Indent */); + DIE.dump(outs(), 0, 8 /* Indent */); Flags |= TF_Keep; DWARFFormValue HighPcValue; - if (!DIE.getAttributeValue(&OrigUnit, dwarf::DW_AT_high_pc, HighPcValue)) { + if (!DIE.getAttributeValue(dwarf::DW_AT_high_pc, HighPcValue)) { reportWarning("Function without high_pc. Range will be discarded.\n", - &OrigUnit, &DIE); + &DIE); return Flags; } @@ -2166,7 +2160,7 @@ /// \brief Check if a DIE should be kept. /// \returns updated TraversalFlags. unsigned DwarfLinker::shouldKeepDIE(RelocationManager &RelocMgr, - const DWARFDebugInfoEntryMinimal &DIE, + const DWARFDie &DIE, CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags) { @@ -2198,18 +2192,18 @@ /// TraversalFlags to inform it that it's not doing the primary DIE /// tree walk. void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr, - const DWARFDebugInfoEntryMinimal &Die, + const DWARFDie &Die, CompileUnit::DIEInfo &MyInfo, const DebugMapObject &DMO, CompileUnit &CU, bool UseODR) { - const DWARFUnit &Unit = CU.getOrigUnit(); + DWARFUnit &Unit = CU.getOrigUnit(); MyInfo.Keep = true; // First mark all the parent chain as kept. unsigned AncestorIdx = MyInfo.ParentIdx; while (!CU.getInfo(AncestorIdx).Keep) { unsigned ODRFlag = UseODR ? TF_ODR : 0; - lookForDIEsToKeep(RelocMgr, *Unit.getDIEAtIndex(AncestorIdx), DMO, CU, + lookForDIEsToKeep(RelocMgr, Unit.getDIEAtIndex(AncestorIdx), DMO, CU, TF_ParentWalk | TF_Keep | TF_DependencyWalk | ODRFlag); AncestorIdx = CU.getInfo(AncestorIdx).ParentIdx; } @@ -2231,7 +2225,7 @@ Val.extractValue(Data, &Offset, &Unit); CompileUnit *ReferencedCU; - if (const auto *RefDIE = + if (auto RefDIE = resolveDIEReference(*this, Units, Val, Unit, Die, ReferencedCU)) { uint32_t RefIdx = ReferencedCU->getOrigUnit().getDIEIndex(RefDIE); CompileUnit::DIEInfo &Info = ReferencedCU->getInfo(RefIdx); @@ -2254,7 +2248,7 @@ Info.Prune = false; unsigned ODRFlag = UseODR ? TF_ODR : 0; - lookForDIEsToKeep(RelocMgr, *RefDIE, DMO, *ReferencedCU, + lookForDIEsToKeep(RelocMgr, RefDIE, DMO, *ReferencedCU, TF_Keep | TF_DependencyWalk | ODRFlag); } } @@ -2273,10 +2267,10 @@ /// not respected. The TF_DependencyWalk flag tells us which kind of /// traversal we are currently doing. void DwarfLinker::lookForDIEsToKeep(RelocationManager &RelocMgr, - const DWARFDebugInfoEntryMinimal &Die, + const DWARFDie &Die, const DebugMapObject &DMO, CompileUnit &CU, unsigned Flags) { - unsigned Idx = CU.getOrigUnit().getDIEIndex(&Die); + unsigned Idx = CU.getOrigUnit().getDIEIndex(Die); CompileUnit::DIEInfo &MyInfo = CU.getInfo(Idx); bool AlreadyKept = MyInfo.Keep; if (MyInfo.Prune) @@ -2310,9 +2304,9 @@ if (!Die.hasChildren() || (Flags & TF_ParentWalk)) return; - for (auto *Child = Die.getFirstChild(); Child && !Child->isNULL(); - Child = Child->getSibling()) - lookForDIEsToKeep(RelocMgr, *Child, DMO, CU, Flags); + for (auto Child = Die.getFirstChild(); Child && !Child.isNULL(); + Child = Child.getSibling()) + lookForDIEsToKeep(RelocMgr, Child, DMO, CU, Flags); } /// \brief Assign an abbreviation numer to \p Abbrev. @@ -2358,7 +2352,7 @@ } unsigned DwarfLinker::DIECloner::cloneDieReferenceAttribute( - DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE, + DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec, unsigned AttrSize, const DWARFFormValue &Val, CompileUnit &Unit) { const DWARFUnit &U = Unit.getOrigUnit(); @@ -2367,8 +2361,8 @@ CompileUnit *RefUnit = nullptr; DeclContext *Ctxt = nullptr; - const DWARFDebugInfoEntryMinimal *RefDie = - resolveDIEReference(Linker, CompileUnits, Val, U, InputDIE, RefUnit); + DWARFDie RefDie = resolveDIEReference(Linker, CompileUnits, Val, U, InputDIE, + RefUnit); // If the referenced DIE is not found, drop the attribute. if (!RefDie) @@ -2393,7 +2387,7 @@ assert(Ref > InputDIE.getOffset()); // We haven't cloned this DIE yet. Just create an empty one and // store it. It'll get really cloned when we process it. - RefInfo.Clone = DIE::get(DIEAlloc, dwarf::Tag(RefDie->getTag())); + RefInfo.Clone = DIE::get(DIEAlloc, dwarf::Tag(RefDie.getTag())); } NewRefDie = RefInfo.Clone; @@ -2509,7 +2503,7 @@ } unsigned DwarfLinker::DIECloner::cloneScalarAttribute( - DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE, CompileUnit &Unit, + DIE &Die, const DWARFDie &InputDIE, CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize, AttributesInfo &Info) { uint64_t Value; @@ -2528,7 +2522,7 @@ else { Linker.reportWarning( "Unsupported scalar attribute form. Dropping attribute.", - &Unit.getOrigUnit(), &InputDIE); + &InputDIE); return 0; } PatchLocation Patch = @@ -2553,7 +2547,7 @@ /// value \p Val, and add it to \p Die. /// \returns the size of the cloned attribute. unsigned DwarfLinker::DIECloner::cloneAttribute( - DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE, CompileUnit &Unit, + DIE &Die, const DWARFDie &InputDIE, CompileUnit &Unit, const DWARFFormValue &Val, const AttributeSpec AttrSpec, unsigned AttrSize, AttributesInfo &Info) { const DWARFUnit &U = Unit.getOrigUnit(); @@ -2590,8 +2584,7 @@ Info); default: Linker.reportWarning( - "Unsupported attribute form in cloneAttribute. Dropping.", &U, - &InputDIE); + "Unsupported attribute form in cloneAttribute. Dropping.", &InputDIE); } return 0; @@ -2701,10 +2694,10 @@ } DIE *DwarfLinker::DIECloner::cloneDIE( - const DWARFDebugInfoEntryMinimal &InputDIE, CompileUnit &Unit, + const DWARFDie &InputDIE, CompileUnit &Unit, int64_t PCOffset, uint32_t OutOffset, unsigned Flags, DIE *Die) { DWARFUnit &U = Unit.getOrigUnit(); - unsigned Idx = U.getDIEIndex(&InputDIE); + unsigned Idx = U.getDIEIndex(InputDIE); CompileUnit::DIEInfo &Info = Unit.getInfo(Idx); // Should the DIE appear in the output? @@ -2740,7 +2733,7 @@ // DW_TAG_compile_unit without any children, point to the next unit. uint32_t NextOffset = (Idx + 1 < U.getNumDIEs()) - ? U.getDIEAtIndex(Idx + 1)->getOffset() + ? U.getDIEAtIndex(Idx + 1).getOffset() : U.getNextUnitOffset(); AttributesInfo AttrInfo; @@ -2759,12 +2752,12 @@ // independantly by the linker). The computation of the actual // high_pc value is done in cloneAddressAttribute(). AttrInfo.OrigHighPc = - InputDIE.getAttributeValueAsAddress(&U, dwarf::DW_AT_high_pc, 0); + InputDIE.getAttributeValueAsAddress(dwarf::DW_AT_high_pc, 0); // Also store the low_pc. It might get relocated in an // inline_subprogram that happens at the beginning of its // inlining function. AttrInfo.OrigLowPc = - InputDIE.getAttributeValueAsAddress(&U, dwarf::DW_AT_low_pc, UINT64_MAX); + InputDIE.getAttributeValueAsAddress(dwarf::DW_AT_low_pc, UINT64_MAX); } // Reset the Offset to 0 as we will be working on the local copy of @@ -2816,7 +2809,7 @@ // accelerator tables too. For now stick with dsymutil's behavior. if ((Info.InDebugMap || AttrInfo.HasLowPc) && Tag != dwarf::DW_TAG_compile_unit && - getDIENames(InputDIE, Unit.getOrigUnit(), AttrInfo)) { + getDIENames(InputDIE, AttrInfo)) { if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name) Unit.addNameAccelerator(Die, AttrInfo.MangledName, AttrInfo.MangledNameOffset, @@ -2825,14 +2818,14 @@ Unit.addNameAccelerator(Die, AttrInfo.Name, AttrInfo.NameOffset, Tag == dwarf::DW_TAG_inlined_subroutine); } else if (isTypeTag(Tag) && !AttrInfo.IsDeclaration && - getDIENames(InputDIE, Unit.getOrigUnit(), AttrInfo)) { + getDIENames(InputDIE, AttrInfo)) { Unit.addTypeAccelerator(Die, AttrInfo.Name, AttrInfo.NameOffset); } // Determine whether there are any children that we want to keep. bool HasChildren = false; - for (auto *Child = InputDIE.getFirstChild(); Child && !Child->isNULL(); - Child = Child->getSibling()) { + for (auto Child = InputDIE.getFirstChild(); Child && !Child.isNULL(); + Child = Child.getSibling()) { unsigned Idx = U.getDIEIndex(Child); if (Unit.getInfo(Idx).Keep) { HasChildren = true; @@ -2857,9 +2850,9 @@ } // Recursively clone children. - for (auto *Child = InputDIE.getFirstChild(); Child && !Child->isNULL(); - Child = Child->getSibling()) { - if (DIE *Clone = cloneDIE(*Child, Unit, PCOffset, OutOffset, Flags)) { + for (auto Child = InputDIE.getFirstChild(); Child && !Child.isNULL(); + Child = Child.getSibling()) { + if (DIE *Clone = cloneDIE(Child, Unit, PCOffset, OutOffset, Flags)) { Die->addChild(Clone); OutOffset = Clone->getOffset() + Clone->getSize(); } @@ -2884,9 +2877,9 @@ OrigDwarf.isLittleEndian(), AddressSize); auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange; DWARFUnit &OrigUnit = Unit.getOrigUnit(); - const auto *OrigUnitDie = OrigUnit.getUnitDIE(false); - uint64_t OrigLowPc = OrigUnitDie->getAttributeValueAsAddress( - &OrigUnit, dwarf::DW_AT_low_pc, -1ULL); + auto OrigUnitDie = OrigUnit.getUnitDIE(false); + uint64_t OrigLowPc = OrigUnitDie.getAttributeValueAsAddress( + dwarf::DW_AT_low_pc, -1ULL); // Ranges addresses are based on the unit's low_pc. Compute the // offset we need to apply to adapt to the new unit's low_pc. int64_t UnitPcOffset = 0; @@ -2980,9 +2973,9 @@ /// are present in the binary. void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit, DWARFContext &OrigDwarf) { - const DWARFDebugInfoEntryMinimal *CUDie = Unit.getOrigUnit().getUnitDIE(); - uint64_t StmtList = CUDie->getAttributeValueAsSectionOffset( - &Unit.getOrigUnit(), dwarf::DW_AT_stmt_list, -1ULL); + DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE(); + uint64_t StmtList = CUDie.getAttributeValueAsSectionOffset( + dwarf::DW_AT_stmt_list, -1ULL); if (StmtList == -1ULL) return; @@ -3212,34 +3205,34 @@ Linker.AssignAbbrev(Copy); } -static uint64_t getDwoId(const DWARFDebugInfoEntryMinimal &CUDie, +static uint64_t getDwoId(const DWARFDie &CUDie, const DWARFUnit &Unit) { uint64_t DwoId = - CUDie.getAttributeValueAsUnsignedConstant(&Unit, dwarf::DW_AT_dwo_id, 0); + CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_dwo_id, 0); if (!DwoId) - DwoId = CUDie.getAttributeValueAsUnsignedConstant(&Unit, - dwarf::DW_AT_GNU_dwo_id, 0); + DwoId = CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_GNU_dwo_id, + 0); return DwoId; } bool DwarfLinker::registerModuleReference( - const DWARFDebugInfoEntryMinimal &CUDie, const DWARFUnit &Unit, + const DWARFDie &CUDie, const DWARFUnit &Unit, DebugMap &ModuleMap, unsigned Indent) { std::string PCMfile = - CUDie.getAttributeValueAsString(&Unit, dwarf::DW_AT_dwo_name, ""); + CUDie.getAttributeValueAsString(dwarf::DW_AT_dwo_name, ""); if (PCMfile.empty()) PCMfile = - CUDie.getAttributeValueAsString(&Unit, dwarf::DW_AT_GNU_dwo_name, ""); + CUDie.getAttributeValueAsString(dwarf::DW_AT_GNU_dwo_name, ""); if (PCMfile.empty()) return false; // Clang module DWARF skeleton CUs abuse this for the path to the module. std::string PCMpath = - CUDie.getAttributeValueAsString(&Unit, dwarf::DW_AT_comp_dir, ""); + CUDie.getAttributeValueAsString(dwarf::DW_AT_comp_dir, ""); uint64_t DwoId = getDwoId(CUDie, Unit); std::string Name = - CUDie.getAttributeValueAsString(&Unit, dwarf::DW_AT_name, ""); + CUDie.getAttributeValueAsString(dwarf::DW_AT_name, ""); if (Name.empty()) { reportWarning("Anonymous module skeleton CU for " + PCMfile); return true; @@ -3340,9 +3333,9 @@ DWARFContextInMemory DwarfContext(*ErrOrObj); RelocationManager RelocMgr(*this); for (const auto &CU : DwarfContext.compile_units()) { - auto *CUDie = CU->getUnitDIE(false); + auto CUDie = CU->getUnitDIE(false); // Recursively get all modules imported by this one. - if (!registerModuleReference(*CUDie, *CU, ModuleMap, Indent)) { + if (!registerModuleReference(CUDie, *CU, ModuleMap, Indent)) { if (Unit) { errs() << Filename << ": Clang modules are expected to have exactly" << " 1 compile unit.\n"; @@ -3351,7 +3344,7 @@ // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is // fixed in clang, only warn about DWO_id mismatches in verbose mode. // ASTFileSignatures will change randomly when a module is rebuilt. - uint64_t PCMDwoId = getDwoId(*CUDie, *CU); + uint64_t PCMDwoId = getDwoId(CUDie, *CU); if (PCMDwoId != DwoId) { if (Options.Verbose) reportWarning( @@ -3388,11 +3381,11 @@ return; for (auto &CurrentUnit : CompileUnits) { - const auto *InputDIE = CurrentUnit->getOrigUnit().getUnitDIE(); + auto InputDIE = CurrentUnit->getOrigUnit().getUnitDIE(); CurrentUnit->setStartOffset(Linker.OutputDebugInfoSize); // Clonse the InputDIE into your Unit DIE in our compile unit since it // already has a DIE inside of it. - if (!cloneDIE(*InputDIE, *CurrentUnit, 0 /* PC offset */, + if (!cloneDIE(InputDIE, *CurrentUnit, 0 /* PC offset */, 11 /* Unit Header size */, 0, CurrentUnit->getOutputUnitDIE())) continue; @@ -3456,13 +3449,13 @@ // In a first phase, just read in the debug info and load all clang modules. for (const auto &CU : DwarfContext.compile_units()) { - auto *CUDie = CU->getUnitDIE(false); + auto CUDie = CU->getUnitDIE(false); if (Options.Verbose) { outs() << "Input compilation unit:"; - CUDie->dump(outs(), CU.get(), 0); + CUDie.dump(outs(), 0); } - if (!registerModuleReference(*CUDie, *CU, ModuleMap)) + if (!registerModuleReference(CUDie, *CU, ModuleMap)) Units.push_back(llvm::make_unique(*CU, UnitID++, !Options.NoODR, "")); } @@ -3478,7 +3471,7 @@ // references require the ParentIdx to be setup for every CU in // the object file before calling this. for (auto &CurrentUnit : Units) - lookForDIEsToKeep(RelocMgr, *CurrentUnit->getOrigUnit().getUnitDIE(), *Obj, + lookForDIEsToKeep(RelocMgr, CurrentUnit->getOrigUnit().getUnitDIE(), *Obj, *CurrentUnit, 0); // The calls to applyValidRelocs inside cloneDIE will walk the Index: unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp =================================================================== --- unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -10,7 +10,7 @@ #include "DwarfGenerator.h" #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" +#include "llvm/DebugInfo/DWARF/DWARFDie.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Support/Dwarf.h" @@ -215,13 +215,13 @@ uint32_t NumCUs = DwarfContext.getNumCompileUnits(); EXPECT_EQ(NumCUs, 1u); DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); - auto DiePtr = U->getUnitDIE(false); - EXPECT_TRUE(DiePtr != nullptr); + auto DieDG = U->getUnitDIE(false); + EXPECT_TRUE(DieDG.isValid()); //---------------------------------------------------------------------- // Test address forms //---------------------------------------------------------------------- - EXPECT_EQ(DiePtr->getAttributeValueAsAddress(U, Attr_DW_FORM_addr, 0), + EXPECT_EQ(DieDG.getAttributeValueAsAddress(Attr_DW_FORM_addr, 0), AddrValue); //---------------------------------------------------------------------- @@ -231,28 +231,28 @@ ArrayRef ExtractedBlockData; Optional> BlockDataOpt; - EXPECT_TRUE(DiePtr->getAttributeValue(U, Attr_DW_FORM_block, FormValue)); + EXPECT_TRUE(DieDG.getAttributeValue(Attr_DW_FORM_block, FormValue)); BlockDataOpt = FormValue.getAsBlock(); EXPECT_TRUE(BlockDataOpt.hasValue()); ExtractedBlockData = BlockDataOpt.getValue(); EXPECT_EQ(ExtractedBlockData.size(), BlockSize); EXPECT_TRUE(memcmp(ExtractedBlockData.data(), BlockData, BlockSize) == 0); - EXPECT_TRUE(DiePtr->getAttributeValue(U, Attr_DW_FORM_block1, FormValue)); + EXPECT_TRUE(DieDG.getAttributeValue(Attr_DW_FORM_block1, FormValue)); BlockDataOpt = FormValue.getAsBlock(); EXPECT_TRUE(BlockDataOpt.hasValue()); ExtractedBlockData = BlockDataOpt.getValue(); EXPECT_EQ(ExtractedBlockData.size(), BlockSize); EXPECT_TRUE(memcmp(ExtractedBlockData.data(), BlockData, BlockSize) == 0); - EXPECT_TRUE(DiePtr->getAttributeValue(U, Attr_DW_FORM_block2, FormValue)); + EXPECT_TRUE(DieDG.getAttributeValue(Attr_DW_FORM_block2, FormValue)); BlockDataOpt = FormValue.getAsBlock(); EXPECT_TRUE(BlockDataOpt.hasValue()); ExtractedBlockData = BlockDataOpt.getValue(); EXPECT_EQ(ExtractedBlockData.size(), BlockSize); EXPECT_TRUE(memcmp(ExtractedBlockData.data(), BlockData, BlockSize) == 0); - EXPECT_TRUE(DiePtr->getAttributeValue(U, Attr_DW_FORM_block4, FormValue)); + EXPECT_TRUE(DieDG.getAttributeValue(Attr_DW_FORM_block4, FormValue)); BlockDataOpt = FormValue.getAsBlock(); EXPECT_TRUE(BlockDataOpt.hasValue()); ExtractedBlockData = BlockDataOpt.getValue(); @@ -263,60 +263,60 @@ // Test data forms //---------------------------------------------------------------------- EXPECT_EQ( - DiePtr->getAttributeValueAsUnsignedConstant(U, Attr_DW_FORM_data1, 0), + DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_data1, 0), Data1); EXPECT_EQ( - DiePtr->getAttributeValueAsUnsignedConstant(U, Attr_DW_FORM_data2, 0), + DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_data2, 0), Data2); EXPECT_EQ( - DiePtr->getAttributeValueAsUnsignedConstant(U, Attr_DW_FORM_data4, 0), + DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_data4, 0), Data4); EXPECT_EQ( - DiePtr->getAttributeValueAsUnsignedConstant(U, Attr_DW_FORM_data8, 0), + DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_data8, 0), Data8); //---------------------------------------------------------------------- // Test string forms //---------------------------------------------------------------------- const char *ExtractedStringValue = - DiePtr->getAttributeValueAsString(U, Attr_DW_FORM_string, nullptr); + DieDG.getAttributeValueAsString(Attr_DW_FORM_string, nullptr); EXPECT_TRUE(ExtractedStringValue != nullptr); EXPECT_TRUE(strcmp(StringValue, ExtractedStringValue) == 0); const char *ExtractedStrpValue = - DiePtr->getAttributeValueAsString(U, Attr_DW_FORM_strp, nullptr); + DieDG.getAttributeValueAsString(Attr_DW_FORM_strp, nullptr); EXPECT_TRUE(ExtractedStrpValue != nullptr); EXPECT_TRUE(strcmp(StrpValue, ExtractedStrpValue) == 0); //---------------------------------------------------------------------- // Test reference forms //---------------------------------------------------------------------- - EXPECT_EQ(DiePtr->getAttributeValueAsReference(U, Attr_DW_FORM_ref_addr, 0), + EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref_addr, 0), RefAddr); - EXPECT_EQ(DiePtr->getAttributeValueAsReference(U, Attr_DW_FORM_ref1, 0), + EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref1, 0), Data1); - EXPECT_EQ(DiePtr->getAttributeValueAsReference(U, Attr_DW_FORM_ref2, 0), + EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref2, 0), Data2); - EXPECT_EQ(DiePtr->getAttributeValueAsReference(U, Attr_DW_FORM_ref4, 0), + EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref4, 0), Data4); - EXPECT_EQ(DiePtr->getAttributeValueAsReference(U, Attr_DW_FORM_ref8, 0), + EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref8, 0), Data8); - EXPECT_EQ(DiePtr->getAttributeValueAsReference(U, Attr_DW_FORM_ref_sig8, 0), + EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref_sig8, 0), Data8_2); - EXPECT_EQ(DiePtr->getAttributeValueAsReference(U, Attr_DW_FORM_ref_udata, 0), + EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref_udata, 0), UData[0]); //---------------------------------------------------------------------- // Test flag forms //---------------------------------------------------------------------- - EXPECT_EQ(DiePtr->getAttributeValueAsUnsignedConstant( - U, Attr_DW_FORM_flag_true, 0ULL), + EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant( + Attr_DW_FORM_flag_true, 0ULL), 1ULL); - EXPECT_EQ(DiePtr->getAttributeValueAsUnsignedConstant( - U, Attr_DW_FORM_flag_false, 1ULL), + EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant( + Attr_DW_FORM_flag_false, 1ULL), 0ULL); - EXPECT_EQ(DiePtr->getAttributeValueAsUnsignedConstant( - U, Attr_DW_FORM_flag_present, 0ULL), + EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant( + Attr_DW_FORM_flag_present, 0ULL), 1ULL); // TODO: test Attr_DW_FORM_implicit_const extraction @@ -324,30 +324,30 @@ //---------------------------------------------------------------------- // Test SLEB128 based forms //---------------------------------------------------------------------- - EXPECT_EQ(DiePtr->getAttributeValueAsSignedConstant(U, Attr_DW_FORM_sdata, 0), + EXPECT_EQ(DieDG.getAttributeValueAsSignedConstant(Attr_DW_FORM_sdata, 0), SData); //---------------------------------------------------------------------- // Test ULEB128 based forms //---------------------------------------------------------------------- EXPECT_EQ( - DiePtr->getAttributeValueAsUnsignedConstant(U, Attr_DW_FORM_udata, 0), + DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_udata, 0), UData[0]); //---------------------------------------------------------------------- // Test DWARF32/DWARF64 forms //---------------------------------------------------------------------- EXPECT_EQ( - DiePtr->getAttributeValueAsReference(U, Attr_DW_FORM_GNU_ref_alt, 0), + DieDG.getAttributeValueAsReference(Attr_DW_FORM_GNU_ref_alt, 0), Dwarf32Values[0]); EXPECT_EQ( - DiePtr->getAttributeValueAsSectionOffset(U, Attr_DW_FORM_sec_offset, 0), + DieDG.getAttributeValueAsSectionOffset(Attr_DW_FORM_sec_offset, 0), Dwarf32Values[1]); //---------------------------------------------------------------------- // Add an address at the end to make sure we can decode this value //---------------------------------------------------------------------- - EXPECT_EQ(DiePtr->getAttributeValueAsAddress(U, Attr_Last, 0), AddrValue); + EXPECT_EQ(DieDG.getAttributeValueAsAddress(Attr_Last, 0), AddrValue); } TEST(DWARFDebugInfo, TestDWARF32Version2Addr4AllForms) { @@ -449,41 +449,41 @@ DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); // Get the compile unit DIE is valid. - auto DiePtr = U->getUnitDIE(false); - EXPECT_TRUE(DiePtr != nullptr); - // DiePtr->dump(llvm::outs(), U, UINT32_MAX); + auto DieDG = U->getUnitDIE(false); + EXPECT_TRUE(DieDG.isValid()); + // DieDG.dump(llvm::outs(), U, UINT32_MAX); // Verify the first child of the compile unit DIE is our subprogram. - auto SubprogramDiePtr = DiePtr->getFirstChild(); - EXPECT_TRUE(SubprogramDiePtr != nullptr); - EXPECT_EQ(SubprogramDiePtr->getTag(), DW_TAG_subprogram); + auto SubprogramDieDG = DieDG.getFirstChild(); + EXPECT_TRUE(SubprogramDieDG.isValid()); + EXPECT_EQ(SubprogramDieDG.getTag(), DW_TAG_subprogram); // Verify the first child of the subprogram is our formal parameter. - auto ArgcDiePtr = SubprogramDiePtr->getFirstChild(); - EXPECT_TRUE(ArgcDiePtr != nullptr); - EXPECT_EQ(ArgcDiePtr->getTag(), DW_TAG_formal_parameter); + auto ArgcDieDG = SubprogramDieDG.getFirstChild(); + EXPECT_TRUE(ArgcDieDG.isValid()); + EXPECT_EQ(ArgcDieDG.getTag(), DW_TAG_formal_parameter); // Verify our formal parameter has a NULL tag sibling. - auto NullDiePtr = ArgcDiePtr->getSibling(); - EXPECT_TRUE(NullDiePtr != nullptr); - if (NullDiePtr) { - EXPECT_EQ(NullDiePtr->getTag(), DW_TAG_null); - EXPECT_TRUE(NullDiePtr->getSibling() == nullptr); - EXPECT_TRUE(NullDiePtr->getFirstChild() == nullptr); + auto NullDieDG = ArgcDieDG.getSibling(); + EXPECT_TRUE(NullDieDG.isValid()); + if (NullDieDG) { + EXPECT_EQ(NullDieDG.getTag(), DW_TAG_null); + EXPECT_TRUE(!NullDieDG.getSibling().isValid()); + EXPECT_TRUE(!NullDieDG.getFirstChild().isValid()); } // Verify the sibling of our subprogram is our integer base type. - auto IntDiePtr = SubprogramDiePtr->getSibling(); - EXPECT_TRUE(IntDiePtr != nullptr); - EXPECT_EQ(IntDiePtr->getTag(), DW_TAG_base_type); + auto IntDieDG = SubprogramDieDG.getSibling(); + EXPECT_TRUE(IntDieDG.isValid()); + EXPECT_EQ(IntDieDG.getTag(), DW_TAG_base_type); // Verify the sibling of our subprogram is our integer base is a NULL tag. - NullDiePtr = IntDiePtr->getSibling(); - EXPECT_TRUE(NullDiePtr != nullptr); - if (NullDiePtr) { - EXPECT_EQ(NullDiePtr->getTag(), DW_TAG_null); - EXPECT_TRUE(NullDiePtr->getSibling() == nullptr); - EXPECT_TRUE(NullDiePtr->getFirstChild() == nullptr); + NullDieDG = IntDieDG.getSibling(); + EXPECT_TRUE(NullDieDG.isValid()); + if (NullDieDG) { + EXPECT_EQ(NullDieDG.getTag(), DW_TAG_null); + EXPECT_TRUE(!NullDieDG.getSibling().isValid()); + EXPECT_TRUE(!NullDieDG.getFirstChild().isValid()); } } @@ -623,127 +623,127 @@ DWARFCompileUnit *U2 = DwarfContext.getCompileUnitAtIndex(1); // Get the compile unit DIE is valid. - auto Unit1DiePtr = U1->getUnitDIE(false); - EXPECT_TRUE(Unit1DiePtr != nullptr); - // Unit1DiePtr->dump(llvm::outs(), U1, UINT32_MAX); + auto Unit1DieDG = U1->getUnitDIE(false); + EXPECT_TRUE(Unit1DieDG.isValid()); + // Unit1DieDG.dump(llvm::outs(), UINT32_MAX); - auto Unit2DiePtr = U2->getUnitDIE(false); - EXPECT_TRUE(Unit2DiePtr != nullptr); - // Unit2DiePtr->dump(llvm::outs(), U2, UINT32_MAX); + auto Unit2DieDG = U2->getUnitDIE(false); + EXPECT_TRUE(Unit2DieDG.isValid()); + // Unit2DieDG.dump(llvm::outs(), UINT32_MAX); // Verify the first child of the compile unit 1 DIE is our int base type. - auto CU1TypeDiePtr = Unit1DiePtr->getFirstChild(); - EXPECT_TRUE(CU1TypeDiePtr != nullptr); - EXPECT_EQ(CU1TypeDiePtr->getTag(), DW_TAG_base_type); + auto CU1TypeDieDG = Unit1DieDG.getFirstChild(); + EXPECT_TRUE(CU1TypeDieDG.isValid()); + EXPECT_EQ(CU1TypeDieDG.getTag(), DW_TAG_base_type); EXPECT_EQ( - CU1TypeDiePtr->getAttributeValueAsUnsignedConstant(U1, DW_AT_encoding, 0), + CU1TypeDieDG.getAttributeValueAsUnsignedConstant(DW_AT_encoding, 0), DW_ATE_signed); // Verify the first child of the compile unit 2 DIE is our float base type. - auto CU2TypeDiePtr = Unit2DiePtr->getFirstChild(); - EXPECT_TRUE(CU2TypeDiePtr != nullptr); - EXPECT_EQ(CU2TypeDiePtr->getTag(), DW_TAG_base_type); + auto CU2TypeDieDG = Unit2DieDG.getFirstChild(); + EXPECT_TRUE(CU2TypeDieDG.isValid()); + EXPECT_EQ(CU2TypeDieDG.getTag(), DW_TAG_base_type); EXPECT_EQ( - CU2TypeDiePtr->getAttributeValueAsUnsignedConstant(U2, DW_AT_encoding, 0), + CU2TypeDieDG.getAttributeValueAsUnsignedConstant(DW_AT_encoding, 0), DW_ATE_float); // Verify the sibling of the base type DIE is our Ref1 DIE and that its // DW_AT_type points to our base type DIE. - auto CU1Ref1DiePtr = CU1TypeDiePtr->getSibling(); - EXPECT_TRUE(CU1Ref1DiePtr != nullptr); - EXPECT_EQ(CU1Ref1DiePtr->getTag(), DW_TAG_variable); - EXPECT_EQ(CU1Ref1DiePtr->getAttributeValueAsReference(U1, DW_AT_type, -1ULL), - CU1TypeDiePtr->getOffset()); + auto CU1Ref1DieDG = CU1TypeDieDG.getSibling(); + EXPECT_TRUE(CU1Ref1DieDG.isValid()); + EXPECT_EQ(CU1Ref1DieDG.getTag(), DW_TAG_variable); + EXPECT_EQ(CU1Ref1DieDG.getAttributeValueAsReference(DW_AT_type, -1ULL), + CU1TypeDieDG.getOffset()); // Verify the sibling is our Ref2 DIE and that its DW_AT_type points to our // base type DIE in CU1. - auto CU1Ref2DiePtr = CU1Ref1DiePtr->getSibling(); - EXPECT_TRUE(CU1Ref2DiePtr != nullptr); - EXPECT_EQ(CU1Ref2DiePtr->getTag(), DW_TAG_variable); - EXPECT_EQ(CU1Ref2DiePtr->getAttributeValueAsReference(U1, DW_AT_type, -1ULL), - CU1TypeDiePtr->getOffset()); + auto CU1Ref2DieDG = CU1Ref1DieDG.getSibling(); + EXPECT_TRUE(CU1Ref2DieDG.isValid()); + EXPECT_EQ(CU1Ref2DieDG.getTag(), DW_TAG_variable); + EXPECT_EQ(CU1Ref2DieDG.getAttributeValueAsReference(DW_AT_type, -1ULL), + CU1TypeDieDG.getOffset()); // Verify the sibling is our Ref4 DIE and that its DW_AT_type points to our // base type DIE in CU1. - auto CU1Ref4DiePtr = CU1Ref2DiePtr->getSibling(); - EXPECT_TRUE(CU1Ref4DiePtr != nullptr); - EXPECT_EQ(CU1Ref4DiePtr->getTag(), DW_TAG_variable); - EXPECT_EQ(CU1Ref4DiePtr->getAttributeValueAsReference(U1, DW_AT_type, -1ULL), - CU1TypeDiePtr->getOffset()); + auto CU1Ref4DieDG = CU1Ref2DieDG.getSibling(); + EXPECT_TRUE(CU1Ref4DieDG.isValid()); + EXPECT_EQ(CU1Ref4DieDG.getTag(), DW_TAG_variable); + EXPECT_EQ(CU1Ref4DieDG.getAttributeValueAsReference(DW_AT_type, -1ULL), + CU1TypeDieDG.getOffset()); // Verify the sibling is our Ref8 DIE and that its DW_AT_type points to our // base type DIE in CU1. - auto CU1Ref8DiePtr = CU1Ref4DiePtr->getSibling(); - EXPECT_TRUE(CU1Ref8DiePtr != nullptr); - EXPECT_EQ(CU1Ref8DiePtr->getTag(), DW_TAG_variable); - EXPECT_EQ(CU1Ref8DiePtr->getAttributeValueAsReference(U1, DW_AT_type, -1ULL), - CU1TypeDiePtr->getOffset()); + auto CU1Ref8DieDG = CU1Ref4DieDG.getSibling(); + EXPECT_TRUE(CU1Ref8DieDG.isValid()); + EXPECT_EQ(CU1Ref8DieDG.getTag(), DW_TAG_variable); + EXPECT_EQ(CU1Ref8DieDG.getAttributeValueAsReference(DW_AT_type, -1ULL), + CU1TypeDieDG.getOffset()); // Verify the sibling is our RefAddr DIE and that its DW_AT_type points to our // base type DIE in CU1. - auto CU1RefAddrDiePtr = CU1Ref8DiePtr->getSibling(); - EXPECT_TRUE(CU1RefAddrDiePtr != nullptr); - EXPECT_EQ(CU1RefAddrDiePtr->getTag(), DW_TAG_variable); + auto CU1RefAddrDieDG = CU1Ref8DieDG.getSibling(); + EXPECT_TRUE(CU1RefAddrDieDG.isValid()); + EXPECT_EQ(CU1RefAddrDieDG.getTag(), DW_TAG_variable); EXPECT_EQ( - CU1RefAddrDiePtr->getAttributeValueAsReference(U1, DW_AT_type, -1ULL), - CU1TypeDiePtr->getOffset()); + CU1RefAddrDieDG.getAttributeValueAsReference(DW_AT_type, -1ULL), + CU1TypeDieDG.getOffset()); // Verify the sibling of the Ref4 DIE is our RefAddr DIE and that its // DW_AT_type points to our base type DIE. - auto CU1ToCU2RefAddrDiePtr = CU1RefAddrDiePtr->getSibling(); - EXPECT_TRUE(CU1ToCU2RefAddrDiePtr != nullptr); - EXPECT_EQ(CU1ToCU2RefAddrDiePtr->getTag(), DW_TAG_variable); - EXPECT_EQ(CU1ToCU2RefAddrDiePtr->getAttributeValueAsReference(U1, DW_AT_type, + auto CU1ToCU2RefAddrDieDG = CU1RefAddrDieDG.getSibling(); + EXPECT_TRUE(CU1ToCU2RefAddrDieDG.isValid()); + EXPECT_EQ(CU1ToCU2RefAddrDieDG.getTag(), DW_TAG_variable); + EXPECT_EQ(CU1ToCU2RefAddrDieDG.getAttributeValueAsReference(DW_AT_type, -1ULL), - CU2TypeDiePtr->getOffset()); + CU2TypeDieDG.getOffset()); // Verify the sibling of the base type DIE is our Ref1 DIE and that its // DW_AT_type points to our base type DIE. - auto CU2Ref1DiePtr = CU2TypeDiePtr->getSibling(); - EXPECT_TRUE(CU2Ref1DiePtr != nullptr); - EXPECT_EQ(CU2Ref1DiePtr->getTag(), DW_TAG_variable); - EXPECT_EQ(CU2Ref1DiePtr->getAttributeValueAsReference(U2, DW_AT_type, -1ULL), - CU2TypeDiePtr->getOffset()); + auto CU2Ref1DieDG = CU2TypeDieDG.getSibling(); + EXPECT_TRUE(CU2Ref1DieDG.isValid()); + EXPECT_EQ(CU2Ref1DieDG.getTag(), DW_TAG_variable); + EXPECT_EQ(CU2Ref1DieDG.getAttributeValueAsReference(DW_AT_type, -1ULL), + CU2TypeDieDG.getOffset()); // Verify the sibling is our Ref2 DIE and that its DW_AT_type points to our // base type DIE in CU2. - auto CU2Ref2DiePtr = CU2Ref1DiePtr->getSibling(); - EXPECT_TRUE(CU2Ref2DiePtr != nullptr); - EXPECT_EQ(CU2Ref2DiePtr->getTag(), DW_TAG_variable); - EXPECT_EQ(CU2Ref2DiePtr->getAttributeValueAsReference(U2, DW_AT_type, -1ULL), - CU2TypeDiePtr->getOffset()); + auto CU2Ref2DieDG = CU2Ref1DieDG.getSibling(); + EXPECT_TRUE(CU2Ref2DieDG.isValid()); + EXPECT_EQ(CU2Ref2DieDG.getTag(), DW_TAG_variable); + EXPECT_EQ(CU2Ref2DieDG.getAttributeValueAsReference(DW_AT_type, -1ULL), + CU2TypeDieDG.getOffset()); // Verify the sibling is our Ref4 DIE and that its DW_AT_type points to our // base type DIE in CU2. - auto CU2Ref4DiePtr = CU2Ref2DiePtr->getSibling(); - EXPECT_TRUE(CU2Ref4DiePtr != nullptr); - EXPECT_EQ(CU2Ref4DiePtr->getTag(), DW_TAG_variable); - EXPECT_EQ(CU2Ref4DiePtr->getAttributeValueAsReference(U2, DW_AT_type, -1ULL), - CU2TypeDiePtr->getOffset()); + auto CU2Ref4DieDG = CU2Ref2DieDG.getSibling(); + EXPECT_TRUE(CU2Ref4DieDG.isValid()); + EXPECT_EQ(CU2Ref4DieDG.getTag(), DW_TAG_variable); + EXPECT_EQ(CU2Ref4DieDG.getAttributeValueAsReference(DW_AT_type, -1ULL), + CU2TypeDieDG.getOffset()); // Verify the sibling is our Ref8 DIE and that its DW_AT_type points to our // base type DIE in CU2. - auto CU2Ref8DiePtr = CU2Ref4DiePtr->getSibling(); - EXPECT_TRUE(CU2Ref8DiePtr != nullptr); - EXPECT_EQ(CU2Ref8DiePtr->getTag(), DW_TAG_variable); - EXPECT_EQ(CU2Ref8DiePtr->getAttributeValueAsReference(U2, DW_AT_type, -1ULL), - CU2TypeDiePtr->getOffset()); + auto CU2Ref8DieDG = CU2Ref4DieDG.getSibling(); + EXPECT_TRUE(CU2Ref8DieDG.isValid()); + EXPECT_EQ(CU2Ref8DieDG.getTag(), DW_TAG_variable); + EXPECT_EQ(CU2Ref8DieDG.getAttributeValueAsReference(DW_AT_type, -1ULL), + CU2TypeDieDG.getOffset()); // Verify the sibling is our RefAddr DIE and that its DW_AT_type points to our // base type DIE in CU2. - auto CU2RefAddrDiePtr = CU2Ref8DiePtr->getSibling(); - EXPECT_TRUE(CU2RefAddrDiePtr != nullptr); - EXPECT_EQ(CU2RefAddrDiePtr->getTag(), DW_TAG_variable); + auto CU2RefAddrDieDG = CU2Ref8DieDG.getSibling(); + EXPECT_TRUE(CU2RefAddrDieDG.isValid()); + EXPECT_EQ(CU2RefAddrDieDG.getTag(), DW_TAG_variable); EXPECT_EQ( - CU2RefAddrDiePtr->getAttributeValueAsReference(U2, DW_AT_type, -1ULL), - CU2TypeDiePtr->getOffset()); + CU2RefAddrDieDG.getAttributeValueAsReference(DW_AT_type, -1ULL), + CU2TypeDieDG.getOffset()); // Verify the sibling of the Ref4 DIE is our RefAddr DIE and that its // DW_AT_type points to our base type DIE. - auto CU2ToCU1RefAddrDiePtr = CU2RefAddrDiePtr->getSibling(); - EXPECT_TRUE(CU2ToCU1RefAddrDiePtr != nullptr); - EXPECT_EQ(CU2ToCU1RefAddrDiePtr->getTag(), DW_TAG_variable); - EXPECT_EQ(CU2ToCU1RefAddrDiePtr->getAttributeValueAsReference(U2, DW_AT_type, + auto CU2ToCU1RefAddrDieDG = CU2RefAddrDieDG.getSibling(); + EXPECT_TRUE(CU2ToCU1RefAddrDieDG.isValid()); + EXPECT_EQ(CU2ToCU1RefAddrDieDG.getTag(), DW_TAG_variable); + EXPECT_EQ(CU2ToCU1RefAddrDieDG.getAttributeValueAsReference(DW_AT_type, -1ULL), - CU1TypeDiePtr->getOffset()); + CU1TypeDieDG.getOffset()); } TEST(DWARFDebugInfo, TestDWARF32Version2Addr4References) { Index: unittests/DebugInfo/DWARF/DwarfGenerator.cpp =================================================================== --- unittests/DebugInfo/DWARF/DwarfGenerator.cpp +++ unittests/DebugInfo/DWARF/DwarfGenerator.cpp @@ -13,7 +13,6 @@ #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/DIE.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" -#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/IR/LegacyPassManagers.h"