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;
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.
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".
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<DWARFDebugInfoEntryMinimal, 4> DIEs;
- const DWARFUnit *U;
};
}
--- /dev/null
+//===-- 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 {
+ assert(isValid() && "must check validity prior to calling");
+ return Die->getAbbreviationDeclarationPtr();
+ }
+
+ /// Get the absolute offset into the debug info or types section.
+ ///
+ /// \returns the DIE offset or -1U if invalid.
+ uint32_t getOffset() const {
+ assert(isValid() && "must check validity prior to calling");
+ return Die->getOffset();
+ }
+
+ dwarf::Tag getTag() const {
+ auto AbbrevDecl = getAbbreviationDeclarationPtr();
+ if (AbbrevDecl)
+ return AbbrevDecl->getTag();
+ return dwarf::DW_TAG_null;
+ }
+
+ bool hasChildren() const {
+ assert(isValid() && "must check validity prior to calling");
+ return Die->hasChildren();
+ }
+
+ /// Returns true for a valid DIE that terminates a sibling chain.
+ bool isNULL() const {
+ return 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 {
+ assert(isValid() && "must check validity prior to calling");
+ return DWARFDie(U, Die->getSibling());
+ }
+
+ /// 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 {
+ assert(isValid() && "must check validity prior to calling");
+ return DWARFDie(U, Die->getFirstChild());
+ }
+
+ /// 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<DWARFDie> &InlinedChain) const;
+
+};
+
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_DEBUGINFO_DWARFDIE_H
#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"
uint8_t AddrSize;
uint64_t BaseAddr;
// The compile unit debug information entry items.
- std::vector<DWARFDebugInfoEntryMinimal> DieArray;
+ std::vector<DWARFDebugInfoEntry> DieArray;
class DWOHolder {
object::OwningBinary<object::ObjectFile> DWOFile;
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();
/// 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<DWARFDie> &InlinedChain);
/// getUnitSection - Return the DWARFUnitSection containing this unit.
const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; }
/// 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 {
size_t extractDIEsIfNeeded(bool CUDieOnly);
/// extractDIEsToVector - Appends all parsed DIEs to a vector.
void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs,
- std::vector<DWARFDebugInfoEntryMinimal> &DIEs) const;
+ std::vector<DWARFDebugInfoEntry> &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.
/// 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);
};
}
DWARFDebugLoc.cpp
DWARFDebugMacro.cpp
DWARFDebugRangeList.cpp
+ DWARFDie.cpp
DWARFFormValue.cpp
DWARFGdbIndex.cpp
DWARFTypeUnit.cpp
#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"
<< " (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 << "<compile unit can't be parsed!>\n\n";
}
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);
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.
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<DWARFDie> &InlinedChain
+ SmallVector<DWARFDie, 4> 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;
}
return InliningInfo;
const DWARFLineTable *LineTable = nullptr;
- const DWARFDebugInfoEntryInlinedChain &InlinedChain =
- CU->getInlinedChainForAddress(Address);
- if (InlinedChain.DIEs.size() == 0) {
+ SmallVector<DWARFDie, 4> 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) {
}
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) {
}
// 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);
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<uint64_t> 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<uint64_t> 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<uint64_t> 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) {
}
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<const char *> 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<uint64_t> 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<int64_t> 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<uint64_t> 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<uint64_t> 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<uint64_t> 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;
-}
--- /dev/null
+//===-- 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<uint64_t> 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<uint64_t> 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<const char *> 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<uint64_t> 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<int64_t> 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<uint64_t> 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<uint64_t> 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<uint64_t> 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<DWARFDie> &InlinedChain) const {
+ if (isNULL())
+ return;
+ DWARFDie DIE(*this);
+ while (DIE) {
+ // Append current DIE to inlined chain only if it has correct tag
+ // (e.g. it is not a lexical block).
+ if (DIE.isSubroutineDIE())
+ InlinedChain.push_back(DIE);
+
+ // Try to get child which also contains provided address.
+ DWARFDie Child = DIE.getFirstChild();
+ while (Child) {
+ if (Child.addressRangeContainsAddress(Address)) {
+ // Assume there is only one such child.
+ break;
+ }
+ Child = Child.getSibling();
+ }
+ DIE = Child;
+ }
+ // Reverse the obtained chain to make the root of inlined chain last.
+ std::reverse(InlinedChain.begin(), InlinedChain.end());
+}
+
}
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;
<< " 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 << "<type unit can't be parsed!>\n\n";
}
}
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<DWARFDebugInfoEntryMinimal *> ParentChain;
- DWARFDebugInfoEntryMinimal *SiblingChain = nullptr;
+ std::vector<DWARFDebugInfoEntry *> ParentChain;
+ DWARFDebugInfoEntry *SiblingChain = nullptr;
for (auto &DIE : DieArray) {
if (SiblingChain) {
SiblingChain->setSibling(&DIE);
void DWARFUnit::extractDIEsToVector(
bool AppendCUDie, bool AppendNonCUDies,
- std::vector<DWARFDebugInfoEntryMinimal> &Dies) const {
+ std::vector<DWARFDebugInfoEntry> &Dies) const {
if (!AppendCUDie && !AppendNonCUDies)
return;
// 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;
// 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.
}
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);
}
// 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;
}
// 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<DWARFDebugInfoEntryMinimal> TmpArray;
+ std::vector<DWARFDebugInfoEntry> TmpArray;
DieArray.swap(TmpArray);
// Save at least the compile unit DIE
if (KeepCUDie)
}
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;
// 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();
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<DWARFDie> &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,
StringRef Name;
StringRef File;
const DeclContext &Parent;
- const DWARFDebugInfoEntryMinimal *LastSeenDIE;
+ DWARFDie LastSeenDIE;
uint32_t LastSeenCompileUnitID;
uint32_t CanonicalDIEOffset;
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; }
/// emulate some dsymutil-classic functionality.
PointerIntPair<DeclContext *, 1>
getChildDeclContext(DeclContext &Context,
- const DWARFDebugInfoEntryMinimal *DIE, CompileUnit &Unit,
+ const DWARFDie &DIE, CompileUnit &Unit,
NonRelocatableStringpool &StringPool, bool InClangModule);
DeclContext &getRoot() { return Root; }
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 ||
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();
/// \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.
/// \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);
/// 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);
/// \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);
/// 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);
/// 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);
/// \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);
/// 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);
/// 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);
/// 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<std::unique_ptr<CompileUnit>> &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
/// 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);
}
PointerIntPair<DeclContext *, 1> 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
// 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<DeclContext *, 1>(nullptr);
LLVM_FALLTHROUGH;
case dwarf::DW_TAG_member:
// 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<DeclContext *, 1>(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;
// 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
// 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()) {
return PointerIntPair<DeclContext *, 1>(*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;
/// \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 = "<debug map>";
if (CurrentDebugObject)
Context = CurrentDebugObject->getObjectFilename();
return;
errs() << " in DIE:\n";
- DIE->dump(errs(), const_cast<DWARFUnit *>(Unit), 0 /* RecurseDepth */,
- 6 /* Indent */);
+ DIE->dump(errs(), 0 /* RecurseDepth */, 6 /* Indent */);
}
bool DwarfLinker::createStreamer(const Triple &TheTriple,
/// \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,
// 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;
}
}
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();
/// \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) {
return Flags;
if (Options.Verbose)
- DIE.dump(outs(), const_cast<DWARFUnit *>(&OrigUnit), 0, 8 /* Indent */);
+ DIE.dump(outs(), 0, 8 /* Indent */);
return Flags | TF_Keep;
}
/// \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();
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<DWARFUnit *>(&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;
}
/// \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) {
/// 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;
}
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);
Info.Prune = false;
unsigned ODRFlag = UseODR ? TF_ODR : 0;
- lookForDIEsToKeep(RelocMgr, *RefDIE, DMO, *ReferencedCU,
+ lookForDIEsToKeep(RelocMgr, RefDIE, DMO, *ReferencedCU,
TF_Keep | TF_DependencyWalk | ODRFlag);
}
}
/// 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)
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.
}
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();
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)
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;
}
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;
else {
Linker.reportWarning(
"Unsupported scalar attribute form. Dropping attribute.",
- &Unit.getOrigUnit(), &InputDIE);
+ &InputDIE);
return 0;
}
PatchLocation Patch =
/// 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();
Info);
default:
Linker.reportWarning(
- "Unsupported attribute form in cloneAttribute. Dropping.", &U,
- &InputDIE);
+ "Unsupported attribute form in cloneAttribute. Dropping.", &InputDIE);
}
return 0;
}
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?
// 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;
// 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
// 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,
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;
}
// 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();
}
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;
/// 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;
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;
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";
// 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(
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;
// 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<CompileUnit>(*CU, UnitID++,
!Options.NoODR, ""));
}
// 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
#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"
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);
//----------------------------------------------------------------------
ArrayRef<uint8_t> ExtractedBlockData;
Optional<ArrayRef<uint8_t>> 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();
// 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
//----------------------------------------------------------------------
// 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) {
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());
}
}
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) {
#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"