Bug 1410148 - Backport llvm r289565 to clang 3.9. r=gps
☠☠ backed out by fda16de8ddff ☠ ☠
authorMike Hommey <mh+mozilla@glandium.org>
Thu, 28 Dec 2017 14:54:51 +0900
changeset 449257 593515920c7e5c82363cacbf99c7a279b2debd82
parent 449256 582e63a45507b5f74a392b106bf4c069d1aaf637
child 449258 f77f58a060adccc5369a1617330520d67067eaae
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps
bugs1410148
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1410148 - Backport llvm r289565 to clang 3.9. r=gps I was able to reproduce the failure to apply llvm-dsymutil on the last mozilla-central revision before debug info was temporarily disabled for rust, and validated that the problem was gone in clang 4. After some bisection, r289565 was identified as having fixed the problem, which, reading the commit message, makes sense. It was however not possible to simply cherry-pick, because of multiple code changes between 3.9 and 4. However, apart from the volume of conflicting changes, it was more or less straightforward to backport. Interestingly, the patch for r313872 was relying on changes from r289565, which is why it required a variant specifically for 3.9, but now we can use the same patch as for other versions. Well, except there's a small difference in the context, and build-clang.py doesn't allow fuzz, so we manually edit the patch to remove that line from the context.
build/build-clang/clang-3.9-linux64.json
build/build-clang/r289565-for-3.9.patch
build/build-clang/r313872-for-3.9.patch
build/build-clang/r313872.patch
--- a/build/build-clang/clang-3.9-linux64.json
+++ b/build/build-clang/clang-3.9-linux64.json
@@ -13,11 +13,12 @@
     "gcc_dir": "/builds/worker/workspace/build/src/gcc",
     "cc": "/builds/worker/workspace/build/src/gcc/bin/gcc",
     "cxx": "/builds/worker/workspace/build/src/gcc/bin/g++",
     "as": "/builds/worker/workspace/build/src/gcc/bin/gcc",
     "patches": [
       "llvm-debug-frame.patch",
       "r277806.patch",
       "r285657.patch",
-      "r313872-for-3.9.patch"
+      "r289565-for-3.9.patch",
+      "r313872.patch"
     ]
 }
new file mode 100644
--- /dev/null
+++ b/build/build-clang/r289565-for-3.9.patch
@@ -0,0 +1,2469 @@
+From adb170fc81e3ab69fc66e34f2c991951dabf764f Mon Sep 17 00:00:00 2001
+From: Greg Clayton <gclayton@apple.com>
+Date: Tue, 13 Dec 2016 18:25:19 +0000
+Subject: [PATCH] Make a DWARFDIE class that can help avoid using the wrong
+ DWARFUnit when extracting attributes
+
+Many places pass around a DWARFDebugInfoEntryMinimal and a DWARFUnit. It is easy to get things wrong by using the wrong DWARFUnit with a DWARFDebugInfoEntryMinimal. This patch creates a DWARFDie class that contains the DWARFUnit and DWARFDebugInfoEntryMinimal objects so that they can't get out of sync. All attribute extraction has been moved out of DWARFDebugInfoEntryMinimal and into DWARFDie. DWARFDebugInfoEntryMinimal was also renamed to DWARFDebugInfoEntry.
+
+DWARFDie objects are temporary objects that are used by clients and contain 2 pointers that you always need to have anyway. Keeping them grouped will avoid errors and simplify many of the attribute extracting APIs by not having to pass in a DWARFUnit.
+
+Differential Revision: https://reviews.llvm.org/D27634
+
+
+git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@289565 91177308-0d34-0410-b5e6-96231b3b80d8
+
+diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h
+index f29d5fe9ecd..f2aec56eefe 100644
+--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h
++++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h
+@@ -25,8 +25,8 @@ class DWARFContext;
+ 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;
+ 
+@@ -35,45 +35,31 @@ class DWARFDebugInfoEntryMinimal {
+ 
+   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,
+-                     uint16_t attr, uint16_t 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);
+ 
+-  uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; }
+-  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".
+@@ -85,74 +71,6 @@ public:
+   const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const {
+     return AbbrevDecl;
+   }
+-
+-  bool getAttributeValue(const DWARFUnit *U, const uint16_t Attr,
+-                         DWARFFormValue &FormValue) const;
+-
+-  const char *getAttributeValueAsString(const DWARFUnit *U, const uint16_t Attr,
+-                                        const char *FailValue) const;
+-
+-  uint64_t getAttributeValueAsAddress(const DWARFUnit *U, const uint16_t Attr,
+-                                      uint64_t FailValue) const;
+-
+-  uint64_t getAttributeValueAsUnsignedConstant(const DWARFUnit *U,
+-                                               const uint16_t Attr,
+-                                               uint64_t FailValue) const;
+-
+-  uint64_t getAttributeValueAsReference(const DWARFUnit *U, const uint16_t Attr,
+-                                        uint64_t FailValue) const;
+-
+-  uint64_t getAttributeValueAsSectionOffset(const DWARFUnit *U,
+-                                            const uint16_t 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;
+ };
+ 
+ }
+diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h
+new file mode 100644
+index 00000000000..e33b9fbc8cb
+--- /dev/null
++++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h
+@@ -0,0 +1,286 @@
++//===-- 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();
++  }
++  
++  uint32_t getTag() const {
++    auto AbbrevDecl = getAbbreviationDeclarationPtr();
++    if (AbbrevDecl)
++      return AbbrevDecl->getTag();
++    return 0;
++  }
++
++  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(const uint16_t 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(const uint16_t 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(const uint16_t Attr,
++                                      uint64_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(const uint16_t 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(const uint16_t 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(const uint16_t 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(const uint16_t 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
+diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+index 9c3fe3be6aa..9a390db5495 100644
+--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
++++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+@@ -14,6 +14,7 @@
+ #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+ #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
+ #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
++#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+ #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+ #include "llvm/DebugInfo/DWARF/DWARFSection.h"
+ #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+@@ -124,7 +125,7 @@ class DWARFUnit {
+   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;
+@@ -201,9 +202,11 @@ public:
+     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();
+@@ -214,7 +217,8 @@ public:
+   /// 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; }
+@@ -232,30 +236,34 @@ public:
+   /// 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) const {
++  DWARFDie getDIEForOffset(uint32_t Offset) {
+     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 {
+@@ -274,7 +282,7 @@ private:
+   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.
+@@ -289,7 +297,7 @@ private:
+   /// 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);
+ };
+ 
+ }
+diff --git a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
+index 7104c5f1039..b1585f1f5f5 100644
+--- a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
++++ b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
+@@ -12,6 +12,7 @@ add_llvm_library(LLVMDebugInfoDWARF
+   DWARFDebugLoc.cpp
+   DWARFDebugMacro.cpp
+   DWARFDebugRangeList.cpp
++  DWARFDie.cpp
+   DWARFFormValue.cpp
+   DWARFTypeUnit.cpp
+   DWARFUnitIndex.cpp
+diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
+index 39a7c772dc7..1aa5c777b10 100644
+--- a/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
++++ b/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
+@@ -22,8 +22,8 @@ void DWARFCompileUnit::dump(raw_ostream &OS) {
+      << " (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";
+ }
+diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+index e8ea71b325a..4188441c6af 100644
+--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
++++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+@@ -153,11 +153,11 @@ void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType, bool DumpEH) {
+     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);
+@@ -393,12 +393,12 @@ DWARFContext::getLineTableForUnit(DWARFUnit *U) {
+   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.
+ 
+@@ -458,14 +458,12 @@ static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address,
+     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;
+   }
+@@ -540,9 +538,9 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
+     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) {
+@@ -557,12 +555,11 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
+   }
+ 
+   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) {
+@@ -584,8 +581,7 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address,
+       }
+       // 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);
+diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp
+index 62d5e666aef..407ffbba710 100644
+--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp
++++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp
+@@ -22,166 +22,7 @@ using namespace llvm;
+ 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) {
+-          const char *tagString = TagString(getTag());
+-          if (tagString)
+-            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;
+-    if (const char *PropName = ApplePropertyString(Bit))
+-      OS << PropName;
+-    else
+-      OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit);
+-    if (!(Val ^= Bit))
+-      break;
+-    OS << ", ";
+-  } while (true);
+-  OS << ")";
+-}
+-
+-static void dumpRanges(raw_ostream &OS, const DWARFAddressRangesVector& Ranges,
+-                       unsigned AddressSize, unsigned Indent) {
+-  if (Ranges.empty())
+-    return;
+-
+-  for (const auto &Range: Ranges) {
+-    OS << '\n';
+-    OS.indent(Indent);
+-    OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")",
+-                 AddressSize*2, Range.first,
+-                 AddressSize*2, Range.second);
+-  }
+-}
+-
+-void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS,
+-                                               DWARFUnit *u,
+-                                               uint32_t *offset_ptr,
+-                                               uint16_t attr, uint16_t form,
+-                                               unsigned indent) const {
+-  const char BaseIndent[] = "            ";
+-  OS << BaseIndent;
+-  OS.indent(indent+2);
+-  const char *attrString = AttributeString(attr);
+-  if (attrString)
+-    WithColor(OS, syntax::Attribute) << attrString;
+-  else
+-    WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", attr);
+-
+-  const char *formString = FormEncodingString(form);
+-  if (formString)
+-    OS << " [" << formString << ']';
+-  else
+-    OS << format(" [DW_FORM_Unknown_%x]", form);
+-
+-  DWARFFormValue formValue(form);
+-
+-  if (!formValue.extractValue(u->getDebugInfoExtractor(), offset_ptr, u))
+-    return;
+-
+-  OS << "\t(";
+-  
+-  const char *Name = nullptr;
+-  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.c_str();
+-      }
+-  } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant())
+-    Name = AttributeValueString(attr, *Val);
+-
+-  if (Name)
+-    WithColor(OS, Color) << Name;
+-  else if (attr == DW_AT_decl_line || attr == DW_AT_call_line)
+-    OS << *formValue.getAsUnsignedConstant();
+-  else
+-    formValue.dump(OS, u);
+-
+-  // We have dumped the attribute raw value. For some attributes
+-  // having both the raw value and the pretty-printed value is
+-  // interesting. These attributes are handled below.
+-  if (attr == DW_AT_specification || attr == DW_AT_abstract_origin) {
+-    Optional<uint64_t> Ref = formValue.getAsReference(u);
+-    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) {
+   Offset = *OffsetPtr;
+   DataExtractor DebugInfoData = U->getDebugInfoExtractor();
+@@ -220,241 +61,3 @@ bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit *U,
+   }
+   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, const uint16_t Attr, DWARFFormValue &FormValue) const {
+-  if (!AbbrevDecl)
+-    return false;
+-
+-  uint32_t AttrIdx = AbbrevDecl->findAttributeIndex(Attr);
+-  if (AttrIdx == -1U)
+-    return false;
+-
+-  DataExtractor DebugInfoData = U->getDebugInfoExtractor();
+-  uint32_t DebugInfoOffset = getOffset();
+-
+-  // Skip the abbreviation code so we are at the data for the attributes
+-  DebugInfoData.getULEB128(&DebugInfoOffset);
+-
+-  // Skip preceding attribute values.
+-  for (uint32_t i = 0; i < AttrIdx; ++i) {
+-    DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(i),
+-                              DebugInfoData, &DebugInfoOffset, U);
+-  }
+-
+-  FormValue = DWARFFormValue(AbbrevDecl->getFormByIndex(AttrIdx));
+-  return FormValue.extractValue(DebugInfoData, &DebugInfoOffset, U);
+-}
+-
+-const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
+-    const DWARFUnit *U, const uint16_t Attr, const char *FailValue) const {
+-  DWARFFormValue FormValue;
+-  if (!getAttributeValue(U, Attr, FormValue))
+-    return FailValue;
+-  Optional<const char *> Result = FormValue.getAsCString(U);
+-  return Result.hasValue() ? Result.getValue() : FailValue;
+-}
+-
+-uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress(
+-    const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
+-  DWARFFormValue FormValue;
+-  if (!getAttributeValue(U, Attr, FormValue))
+-    return FailValue;
+-  Optional<uint64_t> Result = FormValue.getAsAddress(U);
+-  return Result.hasValue() ? Result.getValue() : FailValue;
+-}
+-
+-uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsignedConstant(
+-    const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
+-  DWARFFormValue FormValue;
+-  if (!getAttributeValue(U, Attr, FormValue))
+-    return FailValue;
+-  Optional<uint64_t> Result = FormValue.getAsUnsignedConstant();
+-  return Result.hasValue() ? Result.getValue() : FailValue;
+-}
+-
+-uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
+-    const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
+-  DWARFFormValue FormValue;
+-  if (!getAttributeValue(U, Attr, FormValue))
+-    return FailValue;
+-  Optional<uint64_t> Result = FormValue.getAsReference(U);
+-  return Result.hasValue() ? Result.getValue() : FailValue;
+-}
+-
+-uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSectionOffset(
+-    const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
+-  DWARFFormValue FormValue;
+-  if (!getAttributeValue(U, Attr, FormValue))
+-    return FailValue;
+-  Optional<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_ranges_base, -1ULL);
+-  if (Result != -1ULL)
+-    return Result;
+-  return getAttributeValueAsSectionOffset(U, DW_AT_GNU_ranges_base, FailValue);
+-}
+-
+-bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U,
+-                                                 uint64_t &LowPC,
+-                                                 uint64_t &HighPC) const {
+-  LowPC = getAttributeValueAsAddress(U, DW_AT_low_pc, -1ULL);
+-  if (LowPC == -1ULL)
+-    return false;
+-  HighPC = getAttributeValueAsAddress(U, DW_AT_high_pc, -1ULL);
+-  if (HighPC == -1ULL) {
+-    // Since DWARF4, DW_AT_high_pc may also be of class constant, in which case
+-    // it represents function size.
+-    HighPC = getAttributeValueAsUnsignedConstant(U, DW_AT_high_pc, -1ULL);
+-    if (HighPC != -1ULL)
+-      HighPC += LowPC;
+-  }
+-  return (HighPC != -1ULL);
+-}
+-
+-DWARFAddressRangesVector
+-DWARFDebugInfoEntryMinimal::getAddressRanges(const DWARFUnit *U) const {
+-  if (isNULL())
+-    return DWARFAddressRangesVector();
+-  // Single range specified by low/high PC.
+-  uint64_t LowPC, HighPC;
+-  if (getLowAndHighPC(U, LowPC, HighPC)) {
+-    return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC));
+-  }
+-  // Multiple ranges from .debug_ranges section.
+-  uint32_t RangesOffset =
+-      getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U);
+-  if (RangesOffset != -1U) {
+-    DWARFDebugRangeList RangeList;
+-    if (U->extractRangeList(RangesOffset, RangeList))
+-      return RangeList.getAbsoluteRanges(U->getBaseAddress());
+-  }
+-  return DWARFAddressRangesVector();
+-}
+-
+-void DWARFDebugInfoEntryMinimal::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;
+-}
+diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+new file mode 100644
+index 00000000000..b651619161b
+--- /dev/null
++++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+@@ -0,0 +1,400 @@
++//===-- 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;
++    if (const char *PropName = ApplePropertyString(Bit))
++      OS << PropName;
++    else
++      OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit);
++    if (!(Val ^= Bit))
++      break;
++    OS << ", ";
++  } while (true);
++  OS << ")";
++}
++
++static void dumpRanges(raw_ostream &OS, const DWARFAddressRangesVector& Ranges,
++                       unsigned AddressSize, unsigned Indent) {
++  if (Ranges.empty())
++    return;
++  
++  for (const auto &Range: Ranges) {
++    OS << '\n';
++    OS.indent(Indent);
++    OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")",
++                 AddressSize*2, Range.first,
++                 AddressSize*2, Range.second);
++  }
++}
++
++static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
++                          uint32_t *OffsetPtr, uint16_t Attr,
++                          uint16_t Form, unsigned Indent) {
++  if (!Die.isValid())
++    return;
++  const char BaseIndent[] = "            ";
++  OS << BaseIndent;
++  OS.indent(Indent+2);
++  const char *attrString = AttributeString(Attr);
++  if (attrString)
++    WithColor(OS, syntax::Attribute) << attrString;
++  else
++    WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", Attr);
++
++  const char *formString = FormEncodingString(Form);
++  if (formString)
++    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(";
++  
++  const char *Name = nullptr;
++  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.c_str();
++      }
++  } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant())
++    Name = AttributeValueString(Attr, *Val);
++
++  if (Name)
++    WithColor(OS, Color) << Name;
++  else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line)
++    OS << *formValue.getAsUnsignedConstant();
++  else
++    formValue.dump(OS, U);
++  
++  // We have dumped the attribute raw value. For some attributes
++  // having both the raw value and the pretty-printed value is
++  // interesting. These attributes are handled below.
++  if (Attr == DW_AT_specification || Attr == DW_AT_abstract_origin) {
++    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(const uint16_t Attr,
++                                 DWARFFormValue &FormValue) const {
++  if (!U)
++    return false;
++
++  auto AbbrevDecl = getAbbreviationDeclarationPtr();
++  if (!AbbrevDecl)
++    return false;
++
++  uint32_t AttrIdx = AbbrevDecl->findAttributeIndex(Attr);
++  if (AttrIdx == -1U)
++    return false;
++
++  DataExtractor DebugInfoData = U->getDebugInfoExtractor();
++  uint32_t DebugInfoOffset = getOffset();
++
++  // Skip the abbreviation code so we are at the data for the attributes
++  DebugInfoData.getULEB128(&DebugInfoOffset);
++
++  // Skip preceding attribute values.
++  for (uint32_t i = 0; i < AttrIdx; ++i) {
++    DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(i),
++                              DebugInfoData, &DebugInfoOffset, U);
++  }
++
++  FormValue = DWARFFormValue(AbbrevDecl->getFormByIndex(AttrIdx));
++  return FormValue.extractValue(DebugInfoData, &DebugInfoOffset, U);
++}
++
++const char *DWARFDie::getAttributeValueAsString(const uint16_t Attr,
++                                                const char *FailValue) const {
++  DWARFFormValue FormValue;
++  if (!getAttributeValue(Attr, FormValue))
++    return FailValue;
++  Optional<const char *> Result = FormValue.getAsCString(U);
++  return Result.hasValue() ? Result.getValue() : FailValue;
++}
++
++uint64_t DWARFDie::getAttributeValueAsAddress(const uint16_t Attr,
++                                              uint64_t FailValue) const {
++  DWARFFormValue FormValue;
++  if (!getAttributeValue(Attr, FormValue))
++    return FailValue;
++  Optional<uint64_t> Result = FormValue.getAsAddress(U);
++  return Result.hasValue() ? Result.getValue() : FailValue;
++}
++
++uint64_t
++DWARFDie::getAttributeValueAsUnsignedConstant(const uint16_t 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(const uint16_t Attr,
++                                                uint64_t FailValue) const {
++  DWARFFormValue FormValue;
++  if (!getAttributeValue(Attr, FormValue))
++    return FailValue;
++  Optional<uint64_t> Result = FormValue.getAsReference(U);
++  return Result.hasValue() ? Result.getValue() : FailValue;
++}
++
++uint64_t DWARFDie::getAttributeValueAsSectionOffset(const uint16_t 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(const uint16_t 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_ranges_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) {
++        const char* tagString = TagString(getTag());
++        if (!tagString)
++          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());
++}
++
+diff --git a/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp
+index 766e8ac16f0..e96aee0877a 100644
+--- a/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp
++++ b/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp
+@@ -33,8 +33,8 @@ void DWARFTypeUnit::dump(raw_ostream &OS) {
+      << " (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";
+ }
+diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+index 13c2b508bfa..8ea5fd42c5a 100644
+--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
++++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+@@ -141,27 +141,20 @@ void DWARFUnit::clear() {
+ }
+ 
+ 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);
+@@ -187,7 +180,7 @@ void DWARFUnit::setDIERelations() {
+ 
+ void DWARFUnit::extractDIEsToVector(
+     bool AppendCUDie, bool AppendNonCUDies,
+-    std::vector<DWARFDebugInfoEntryMinimal> &Dies) const {
++    std::vector<DWARFDebugInfoEntry> &Dies) const {
+   if (!AppendCUDie && !AppendNonCUDies)
+     return;
+ 
+@@ -195,7 +188,7 @@ void DWARFUnit::extractDIEsToVector(
+   // next compilation unit header.
+   uint32_t DIEOffset = Offset + getHeaderSize();
+   uint32_t NextCUOffset = getNextUnitOffset();
+-  DWARFDebugInfoEntryMinimal DIE;
++  DWARFDebugInfoEntry DIE;
+   uint32_t Depth = 0;
+   bool IsCUDie = true;
+ 
+@@ -249,15 +242,15 @@ size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
+ 
+   // 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_ranges_base, 0);
++    AddrOffsetSectionBase = UnitDie.getAttributeValueAsSectionOffset(
++        DW_AT_GNU_addr_base, 0);
++    RangeSectionBase = UnitDie.getAttributeValueAsSectionOffset(
++        DW_AT_ranges_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.
+   }
+@@ -286,15 +279,15 @@ bool DWARFUnit::parseDWO() {
+     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);
+@@ -309,7 +302,7 @@ bool DWARFUnit::parseDWO() {
+   }
+   // 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;
+ }
+@@ -323,7 +316,7 @@ void DWARFUnit::clearDIEs(bool KeepCUDie) {
+     // 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)
+@@ -332,11 +325,11 @@ void DWARFUnit::clearDIEs(bool 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;
+@@ -349,7 +342,7 @@ void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) {
+   // 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();
+@@ -364,36 +357,37 @@ void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) {
+     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,
+diff --git a/llvm/tools/dsymutil/DwarfLinker.cpp b/llvm/tools/dsymutil/DwarfLinker.cpp
+index bea30ded591..70bdc50131e 100644
+--- a/llvm/tools/dsymutil/DwarfLinker.cpp
++++ b/llvm/tools/dsymutil/DwarfLinker.cpp
+@@ -101,7 +101,7 @@ class DeclContext {
+   StringRef Name;
+   StringRef File;
+   const DeclContext &Parent;
+-  const DWARFDebugInfoEntryMinimal *LastSeenDIE;
++  DWARFDie LastSeenDIE;
+   uint32_t LastSeenCompileUnitID;
+   uint32_t CanonicalDIEOffset;
+ 
+@@ -113,19 +113,18 @@ public:
+   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; }
+@@ -173,7 +172,7 @@ public:
+   /// 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; }
+@@ -201,9 +200,8 @@ public:
+         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 ||
+@@ -845,10 +843,10 @@ void DwarfStreamer::emitLocationsForUnit(const CompileUnit &Unit,
+   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();
+ 
+@@ -1120,8 +1118,8 @@ public:
+   /// \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.
+@@ -1197,7 +1195,7 @@ private:
+   /// \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);
+ 
+@@ -1207,7 +1205,7 @@ private:
+   /// 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);
+ 
+@@ -1231,23 +1229,23 @@ private:
+   /// \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);
+@@ -1286,7 +1284,7 @@ private:
+     /// applied to the entry point of the function to get the linked address.
+     ///
+     /// \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);
+ 
+     /// Construct the output DIE tree by cloning the DIEs we
+@@ -1318,7 +1316,7 @@ private:
+ 
+     /// 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);
+@@ -1335,7 +1333,7 @@ private:
+     /// \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);
+ 
+@@ -1356,7 +1354,7 @@ private:
+     /// 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);
+@@ -1365,8 +1363,7 @@ private:
+     /// 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);
+@@ -1481,19 +1478,19 @@ static CompileUnit *getUnitForOffset(MutableArrayRef<CompileUnit> Units,
+ /// 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, MutableArrayRef<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(&Unit);
+ 
+   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
+@@ -1527,7 +1524,7 @@ static bool isODRAttribute(uint16_t Attr) {
+ /// 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);
+@@ -1541,9 +1538,9 @@ bool DeclContext::setLastSeenDIE(CompileUnit &U,
+ }
+ 
+ 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
+@@ -1561,8 +1558,7 @@ PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
+     // 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);
+   // Fallthrough
+   case dwarf::DW_TAG_member:
+@@ -1576,14 +1572,13 @@ PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
+     // 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;
+@@ -1617,11 +1612,11 @@ PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
+     // 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
+@@ -1638,8 +1633,8 @@ PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
+                   FileNum, "",
+                   DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
+                   File)) {
+-            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()) {
+@@ -1712,16 +1707,16 @@ PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
+   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;
+@@ -1729,8 +1724,8 @@ bool DwarfLinker::DIECloner::getDIENames(const DWARFDebugInfoEntryMinimal &Die,
+ 
+ /// \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();
+@@ -1740,8 +1735,7 @@ void DwarfLinker::reportWarning(const Twine &Warning, const DWARFUnit *Unit,
+     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,
+@@ -1759,7 +1753,7 @@ 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,
+@@ -1780,9 +1774,9 @@ static bool analyzeContextInfo(const DWARFDebugInfoEntryMinimal *DIE,
+   //   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;
+   }
+ 
+@@ -1800,18 +1794,18 @@ static bool analyzeContextInfo(const DWARFDebugInfoEntryMinimal *DIE,
+   }
+ 
+   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();
+@@ -2076,7 +2070,7 @@ getAttributeOffsets(const DWARFAbbreviationDeclaration *Abbrev, unsigned Idx,
+ /// \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) {
+@@ -2109,7 +2103,7 @@ unsigned DwarfLinker::shouldKeepVariableDIE(RelocationManager &RelocMgr,
+     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;
+ }
+@@ -2118,7 +2112,7 @@ unsigned DwarfLinker::shouldKeepVariableDIE(RelocationManager &RelocMgr,
+ /// \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();
+ 
+@@ -2135,21 +2129,21 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE(
+       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;
+   }
+ 
+@@ -2170,7 +2164,7 @@ unsigned DwarfLinker::shouldKeepSubprogramDIE(
+ /// \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) {
+@@ -2200,18 +2194,18 @@ unsigned DwarfLinker::shouldKeepDIE(RelocationManager &RelocMgr,
+ /// 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;
+   }
+@@ -2233,7 +2227,7 @@ void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr,
+ 
+     Val.extractValue(Data, &Offset, &Unit);
+     CompileUnit *ReferencedCU;
+-    if (const auto *RefDIE =
++    if (auto RefDIE =
+             resolveDIEReference(*this, MutableArrayRef<CompileUnit>(Units), Val,
+                                 Unit, Die, ReferencedCU)) {
+       uint32_t RefIdx = ReferencedCU->getOrigUnit().getDIEIndex(RefDIE);
+@@ -2257,7 +2251,7 @@ void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr,
+         Info.Prune = false;
+ 
+       unsigned ODRFlag = UseODR ? TF_ODR : 0;
+-      lookForDIEsToKeep(RelocMgr, *RefDIE, DMO, *ReferencedCU,
++      lookForDIEsToKeep(RelocMgr, RefDIE, DMO, *ReferencedCU,
+                         TF_Keep | TF_DependencyWalk | ODRFlag);
+     }
+   }
+@@ -2276,10 +2270,10 @@ void DwarfLinker::keepDIEAndDependencies(RelocationManager &RelocMgr,
+ /// 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)
+@@ -2313,9 +2307,9 @@ void DwarfLinker::lookForDIEsToKeep(RelocationManager &RelocMgr,
+   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.
+@@ -2361,7 +2355,7 @@ unsigned DwarfLinker::DIECloner::cloneStringAttribute(DIE &Die,
+ }
+ 
+ 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();
+@@ -2370,8 +2364,8 @@ unsigned DwarfLinker::DIECloner::cloneDieReferenceAttribute(
+   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)
+@@ -2396,7 +2390,7 @@ unsigned DwarfLinker::DIECloner::cloneDieReferenceAttribute(
+     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;
+ 
+@@ -2512,7 +2506,7 @@ unsigned DwarfLinker::DIECloner::cloneAddressAttribute(
+ }
+ 
+ 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;
+@@ -2531,7 +2525,7 @@ unsigned DwarfLinker::DIECloner::cloneScalarAttribute(
+   else {
+     Linker.reportWarning(
+         "Unsupported scalar attribute form. Dropping attribute.",
+-        &Unit.getOrigUnit(), &InputDIE);
++        &InputDIE);
+     return 0;
+   }
+   PatchLocation Patch =
+@@ -2556,7 +2550,7 @@ unsigned DwarfLinker::DIECloner::cloneScalarAttribute(
+ /// 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();
+@@ -2593,8 +2587,7 @@ unsigned DwarfLinker::DIECloner::cloneAttribute(
+                                 Info);
+   default:
+     Linker.reportWarning(
+-        "Unsupported attribute form in cloneAttribute. Dropping.", &U,
+-        &InputDIE);
++        "Unsupported attribute form in cloneAttribute. Dropping.", &InputDIE);
+   }
+ 
+   return 0;
+@@ -2703,10 +2696,10 @@ shouldSkipAttribute(DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
+ }
+ 
+ DIE *DwarfLinker::DIECloner::cloneDIE(
+-    const DWARFDebugInfoEntryMinimal &InputDIE, CompileUnit &Unit,
++    const DWARFDie &InputDIE, CompileUnit &Unit,
+     int64_t PCOffset, uint32_t OutOffset, unsigned Flags) {
+   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?
+@@ -2738,7 +2731,7 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
+   // 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;
+ 
+@@ -2757,12 +2750,12 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
+     // 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
+@@ -2814,7 +2807,7 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
+   // 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,
+@@ -2823,14 +2816,14 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
+       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;
+@@ -2855,9 +2848,9 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
+   }
+ 
+   // 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();
+     }
+@@ -2882,9 +2875,9 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit,
+                                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;
+@@ -2978,9 +2971,9 @@ static void patchStmtList(DIE &Die, DIEInteger Offset) {
+ /// 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;
+ 
+@@ -3210,34 +3203,34 @@ void DwarfLinker::DIECloner::copyAbbrev(
+   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;
+@@ -3338,9 +3331,9 @@ void DwarfLinker::loadClangModule(StringRef Filename, StringRef ModulePath,
+   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";
+@@ -3349,7 +3342,7 @@ void DwarfLinker::loadClangModule(StringRef Filename, StringRef ModulePath,
+       // 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(
+@@ -3385,9 +3378,9 @@ void DwarfLinker::DIECloner::cloneAllCompileUnits(
+     return;
+ 
+   for (auto &CurrentUnit : CompileUnits) {
+-    const auto *InputDIE = CurrentUnit.getOrigUnit().getUnitDIE();
++    auto InputDIE = CurrentUnit.getOrigUnit().getUnitDIE();
+     CurrentUnit.setStartOffset(Linker.OutputDebugInfoSize);
+-    DIE *OutputDIE = cloneDIE(*InputDIE, CurrentUnit, 0 /* PC offset */,
++    DIE *OutputDIE = cloneDIE(InputDIE, CurrentUnit, 0 /* PC offset */,
+                               11 /* Unit Header size */, 0);
+     CurrentUnit.setOutputUnitDIE(OutputDIE);
+     Linker.OutputDebugInfoSize = CurrentUnit.computeNextUnitOffset();
+@@ -3452,13 +3445,13 @@ bool DwarfLinker::link(const DebugMap &Map) {
+ 
+     // 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.emplace_back(*CU, UnitID++, !Options.NoODR, "");
+     }
+ 
+@@ -3473,7 +3466,7 @@ bool DwarfLinker::link(const DebugMap &Map) {
+     // 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
deleted file mode 100644
--- a/build/build-clang/r313872-for-3.9.patch
+++ /dev/null
@@ -1,17 +0,0 @@
---- a/llvm/tools/dsymutil/DwarfLinker.cpp
-+++ b/llvm/tools/dsymutil/DwarfLinker.cpp
-@@ -1489,8 +1489,12 @@
-   uint64_t RefOffset = *RefValue.getAsReference(&Unit);
- 
-   if ((RefCU = getUnitForOffset(Units, RefOffset)))
--    if (const auto *RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset))
--      return RefDie;
-+    if (const auto *RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) {
-+      // In a file with broken references, an attribute might point to a NULL
-+      // DIE.
-+      if(!RefDie->isNULL())
-+        return RefDie;
-+    }
- 
-   Linker.reportWarning("could not find referenced DIE", &Unit, &DIE);
-   return nullptr;
--- a/build/build-clang/r313872.patch
+++ b/build/build-clang/r313872.patch
@@ -1,14 +1,13 @@
 Index: tools/dsymutil/DwarfLinker.cpp
 ===================================================================
 --- a/llvm/tools/dsymutil/DwarfLinker.cpp	(revision 313871)
 +++ b/llvm/tools/dsymutil/DwarfLinker.cpp	(revision 313872)
-@@ -1495,8 +1495,12 @@
-   uint64_t RefOffset = *RefValue.getAsReference();
+@@ -1496,7 +1496,11 @@
  
    if ((RefCU = getUnitForOffset(Units, RefOffset)))
 -    if (const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset))
 -      return RefDie;
 +    if (const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) {
 +      // In a file with broken references, an attribute might point to a NULL
 +      // DIE.
 +      if(!RefDie.isNULL())