Permit cross-CU references

So far dw_offset_t was global for the whole SymbolFileDWARF but with
.debug_types the same dw_offset_t may mean two different things depending on
its section (=CU). So references now return whole new referenced DWARFDIE
instead of just dw_offset_t.

This means that some functions have to now handle 16 bytes instead of 8 bytes
but I do not see that anywhere performance critical.

Differential Revision: https://reviews.llvm.org/D61502

llvm-svn: 360795
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp
index 7f851d4..9b737e3 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DIERef.cpp
@@ -16,12 +16,13 @@
 DIERef::DIERef(const DWARFFormValue &form_value)
     : cu_offset(DW_INVALID_OFFSET), die_offset(DW_INVALID_OFFSET) {
   if (form_value.IsValid()) {
-    if (const DWARFUnit *unit = form_value.GetUnit()) {
-      if (unit->GetBaseObjOffset() != DW_INVALID_OFFSET)
-        cu_offset = unit->GetBaseObjOffset();
+    DWARFDIE die = form_value.Reference();
+    die_offset = die.GetOffset();
+    if (die) {
+      if (die.GetCU()->GetBaseObjOffset() != DW_INVALID_OFFSET)
+        cu_offset = die.GetCU()->GetBaseObjOffset();
       else
-        cu_offset = unit->GetOffset();
+        cu_offset = die.GetCU()->GetOffset();
     }
-    die_offset = form_value.Reference();
   }
 }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index f415778..51a3744 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -348,7 +348,7 @@
           // will have a hard time tracking down an unnammed structure type in
           // the module DWO file, so we make sure we don't get into this
           // situation by always resolving typedefs from the DWO file.
-          const DWARFDIE encoding_die = dwarf->GetDIE(DIERef(encoding_uid));
+          const DWARFDIE encoding_die = encoding_uid.Reference();
 
           // First make sure that the die that this is typedef'ed to _is_ just
           // a declaration (DW_AT_declaration == 1), not a full definition
@@ -499,7 +499,7 @@
               // Clang sometimes erroneously emits id as objc_object*.  In that
               // case we fix up the type to "id".
 
-              const DWARFDIE encoding_die = dwarf->GetDIE(DIERef(encoding_uid));
+              const DWARFDIE encoding_die = encoding_uid.Reference();
 
               if (encoding_die && encoding_die.Tag() == DW_TAG_structure_type) {
                 if (const char *struct_name = encoding_die.GetName()) {
@@ -1150,7 +1150,7 @@
         bool has_template_params = false;
         DWARFFormValue specification_die_form;
         DWARFFormValue abstract_origin_die_form;
-        dw_offset_t object_pointer_die_offset = DW_INVALID_OFFSET;
+        DWARFDIE object_pointer_die;
 
         unsigned type_quals = 0;
         clang::StorageClass storage =
@@ -1221,7 +1221,7 @@
                 break;
 
               case DW_AT_object_pointer:
-                object_pointer_die_offset = form_value.Reference();
+                object_pointer_die = form_value.Reference();
                 break;
 
               case DW_AT_allocated:
@@ -1254,13 +1254,10 @@
         }
 
         std::string object_pointer_name;
-        if (object_pointer_die_offset != DW_INVALID_OFFSET) {
-          DWARFDIE object_pointer_die = die.GetDIE(object_pointer_die_offset);
-          if (object_pointer_die) {
-            const char *object_pointer_name_cstr = object_pointer_die.GetName();
-            if (object_pointer_name_cstr)
-              object_pointer_name = object_pointer_name_cstr;
-          }
+        if (object_pointer_die) {
+          const char *object_pointer_name_cstr = object_pointer_die.GetName();
+          if (object_pointer_name_cstr)
+            object_pointer_name = object_pointer_name_cstr;
         }
 
         DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
@@ -1422,9 +1419,10 @@
                     LinkDeclContextToDIE(spec_clang_decl_ctx, die);
                   } else {
                     dwarf->GetObjectFile()->GetModule()->ReportWarning(
-                        "0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8" PRIx64
+                        "0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x"
                         ") has no decl\n",
-                        die.GetID(), specification_die_form.Reference());
+                        die.GetID(),
+                        specification_die_form.Reference().GetOffset());
                   }
                   type_handled = true;
                 } else if (abstract_origin_die_form.IsValid()) {
@@ -1442,9 +1440,10 @@
                     LinkDeclContextToDIE(abs_clang_decl_ctx, die);
                   } else {
                     dwarf->GetObjectFile()->GetModule()->ReportWarning(
-                        "0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8" PRIx64
+                        "0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x"
                         ") has no decl\n",
-                        die.GetID(), abstract_origin_die_form.Reference());
+                        die.GetID(),
+                        abstract_origin_die_form.Reference().GetOffset());
                   }
                   type_handled = true;
                 } else {
@@ -1587,8 +1586,7 @@
             clang::FunctionDecl *template_function_decl = nullptr;
 
             if (abstract_origin_die_form.IsValid()) {
-              DWARFDIE abs_die =
-                  dwarf->DebugInfo()->GetDIE(DIERef(abstract_origin_die_form));
+              DWARFDIE abs_die = abstract_origin_die_form.Reference();
 
               SymbolContext sc;
 
@@ -3070,9 +3068,10 @@
                          member_byte_offset > parent_byte_size)) {
                       module_sp->ReportError(
                           "0x%8.8" PRIx64
-                          ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64
+                          ": DW_TAG_member '%s' refers to type 0x%8.8x"
                           " which extends beyond the bounds of 0x%8.8" PRIx64,
-                          die.GetID(), name, encoding_form.Reference(),
+                          die.GetID(), name,
+                          encoding_form.Reference().GetOffset(),
                           parent_die.GetID());
                     }
 
@@ -3135,15 +3134,14 @@
               if (name)
                 module_sp->ReportError(
                     "0x%8.8" PRIx64
-                    ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64
+                    ": DW_TAG_member '%s' refers to type 0x%8.8x"
                     " which was unable to be parsed",
-                    die.GetID(), name, encoding_form.Reference());
+                    die.GetID(), name, encoding_form.Reference().GetOffset());
               else
                 module_sp->ReportError(
-                    "0x%8.8" PRIx64
-                    ": DW_TAG_member refers to type 0x%8.8" PRIx64
+                    "0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8x"
                     " which was unable to be parsed",
-                    die.GetID(), encoding_form.Reference());
+                    die.GetID(), encoding_form.Reference().GetOffset());
             }
           }
 
@@ -3253,11 +3251,12 @@
         Type *base_class_type = die.ResolveTypeUID(DIERef(encoding_form));
         if (base_class_type == NULL) {
           module_sp->ReportError("0x%8.8x: DW_TAG_inheritance failed to "
-                                 "resolve the base class at 0x%8.8" PRIx64
+                                 "resolve the base class at 0x%8.8x"
                                  " from enclosing type 0x%8.8x. \nPlease file "
                                  "a bug and attach the file at the start of "
                                  "this error message",
-                                 die.GetOffset(), encoding_form.Reference(),
+                                 die.GetOffset(),
+                                 encoding_form.Reference().GetOffset(),
                                  parent_die.GetOffset());
           break;
         }
@@ -3550,7 +3549,7 @@
 
         if (attr == DW_AT_type &&
             attributes.ExtractFormValueAtIndex(i, form_value))
-          return dwarf->ResolveTypeUID(dwarf->GetDIE(DIERef(form_value)), true);
+          return dwarf->ResolveTypeUID(form_value.Reference(), true);
       }
     }
   }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
index 4fd99f8..b3594a4 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
@@ -41,19 +41,18 @@
   return form_value.ExtractValue(cu->GetData(), &offset);
 }
 
-uint64_t DWARFAttributes::FormValueAsUnsigned(dw_attr_t attr,
-                                              uint64_t fail_value) const {
+DWARFDIE
+DWARFAttributes::FormValueAsReference(dw_attr_t attr) const {
   const uint32_t attr_idx = FindAttributeIndex(attr);
   if (attr_idx != UINT32_MAX)
-    return FormValueAsUnsignedAtIndex(attr_idx, fail_value);
-  return fail_value;
+    return FormValueAsReferenceAtIndex(attr_idx);
+  return {};
 }
 
-uint64_t
-DWARFAttributes::FormValueAsUnsignedAtIndex(uint32_t i,
-                                            uint64_t fail_value) const {
+DWARFDIE
+DWARFAttributes::FormValueAsReferenceAtIndex(uint32_t i) const {
   DWARFFormValue form_value;
   if (ExtractFormValueAtIndex(i, form_value))
     return form_value.Reference();
-  return fail_value;
+  return {};
 }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
index 3abbb9a..58427b1 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
@@ -65,8 +65,8 @@
   }
   dw_attr_t FormAtIndex(uint32_t i) const { return m_infos[i].attr.get_form(); }
   bool ExtractFormValueAtIndex(uint32_t i, DWARFFormValue &form_value) const;
-  uint64_t FormValueAsUnsignedAtIndex(uint32_t i, uint64_t fail_value) const;
-  uint64_t FormValueAsUnsigned(dw_attr_t attr, uint64_t fail_value) const;
+  DWARFDIE FormValueAsReferenceAtIndex(uint32_t i) const;
+  DWARFDIE FormValueAsReference(dw_attr_t attr) const;
   uint32_t FindAttributeIndex(dw_attr_t attr) const;
   void Clear() { m_infos.clear(); }
   size_t Size() const { return m_infos.size(); }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
index 887fc10..dd935a2 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
@@ -56,15 +56,6 @@
     return fail_value;
 }
 
-uint64_t DWARFBaseDIE::GetAttributeValueAsReference(const dw_attr_t attr,
-                                                uint64_t fail_value) const {
-  if (IsValid())
-    return m_die->GetAttributeValueAsReference(GetDWARF(), GetCU(), attr,
-                                               fail_value);
-  else
-    return fail_value;
-}
-
 uint64_t DWARFBaseDIE::GetAttributeValueAsAddress(const dw_attr_t attr,
                                               uint64_t fail_value) const {
   if (IsValid())
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
index 278c2b6..1c81131 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.h
@@ -19,6 +19,7 @@
 class DWARFDebugInfoEntry;
 class DWARFDeclContext;
 class SymbolFileDWARF;
+class DWARFDIE;
 
 class DWARFBaseDIE {
 public:
@@ -113,9 +114,6 @@
   uint64_t GetAttributeValueAsUnsigned(const dw_attr_t attr,
                                        uint64_t fail_value) const;
 
-  uint64_t GetAttributeValueAsReference(const dw_attr_t attr,
-                                        uint64_t fail_value) const;
-
   uint64_t GetAttributeValueAsAddress(const dw_attr_t attr,
                                       uint64_t fail_value) const;
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index 7416a6f..fdb1721 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -112,12 +112,10 @@
 
 DWARFDIE
 DWARFDIE::GetReferencedDIE(const dw_attr_t attr) const {
-  const dw_offset_t die_offset =
-      GetAttributeValueAsReference(attr, DW_INVALID_OFFSET);
-  if (die_offset != DW_INVALID_OFFSET)
-    return GetDIE(die_offset);
+  if (IsValid())
+    return m_die->GetAttributeValueAsReference(GetDWARF(), GetCU(), attr);
   else
-    return DWARFDIE();
+    return {};
 }
 
 DWARFDIE
@@ -137,7 +135,7 @@
     DWARFFormValue form_value;
     if (m_die->GetAttributeValue(dwarf, cu, attr, form_value, nullptr,
                                  check_specification_or_abstract_origin))
-      return dwarf->GetDIE(DIERef(form_value));
+      return form_value.Reference();
   }
   return DWARFDIE();
 }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index 72fd939..a78aba8 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -693,16 +693,16 @@
 
   case DW_AT_abstract_origin:
   case DW_AT_specification: {
-    uint64_t abstract_die_offset = form_value.Reference();
+    DWARFDIE abstract_die = form_value.Reference();
     form_value.Dump(s);
-    //  *ostrm_ptr << HEX32 << abstract_die_offset << " ( ";
-    GetName(dwarf2Data, cu, abstract_die_offset, s);
+    //  *ostrm_ptr << HEX32 << abstract_die.GetOffset() << " ( ";
+    GetName(dwarf2Data, abstract_die.GetCU(), abstract_die.GetOffset(), s);
   } break;
 
   case DW_AT_type: {
-    uint64_t type_die_offset = form_value.Reference();
+    DWARFDIE type_die = form_value.Reference();
     s.PutCString(" ( ");
-    AppendTypeName(dwarf2Data, cu, type_die_offset, s);
+    AppendTypeName(dwarf2Data, type_die.GetCU(), type_die.GetOffset(), s);
     s.PutCString(" )");
   } break;
 
@@ -734,13 +734,6 @@
   const DWARFAbbreviationDeclaration *abbrevDecl = nullptr;
   lldb::offset_t offset = 0;
   if (cu) {
-    if (m_tag != DW_TAG_compile_unit && m_tag != DW_TAG_partial_unit) {
-      SymbolFileDWARFDwo *dwo_symbol_file = cu->GetDwoSymbolFile();
-      if (dwo_symbol_file)
-        return GetAttributes(dwo_symbol_file->GetCompileUnit(),
-                             fixed_form_sizes, attributes, curr_depth);
-    }
-
     dwarf2Data = cu->GetSymbolFileDWARF();
     abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset);
   }
@@ -779,9 +772,7 @@
 
       if ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin)) {
         if (form_value.ExtractValue(debug_info_data, &offset)) {
-          dw_offset_t die_offset = form_value.Reference();
-          DWARFDIE spec_die =
-              const_cast<DWARFUnit *>(cu)->GetDIE(die_offset);
+          DWARFDIE spec_die = form_value.Reference();
           if (spec_die)
             spec_die.GetAttributes(attributes, curr_depth + 1);
         }
@@ -845,8 +836,7 @@
 
   if (check_specification_or_abstract_origin) {
     if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value)) {
-      DWARFDIE die =
-          const_cast<DWARFUnit *>(cu)->GetDIE(form_value.Reference());
+      DWARFDIE die = form_value.Reference();
       if (die) {
         dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
             die.GetDWARF(), die.GetCU(), attr, form_value, end_attr_offset_ptr,
@@ -857,8 +847,7 @@
     }
 
     if (GetAttributeValue(dwarf2Data, cu, DW_AT_abstract_origin, form_value)) {
-      DWARFDIE die =
-          const_cast<DWARFUnit *>(cu)->GetDIE(form_value.Reference());
+      DWARFDIE die = form_value.Reference();
       if (die) {
         dw_offset_t die_offset = die.GetDIE()->GetAttributeValue(
             die.GetDWARF(), die.GetCU(), attr, form_value, end_attr_offset_ptr,
@@ -920,15 +909,14 @@
 //
 // Get the value of an attribute as reference and fix up and compile unit
 // relative offsets as needed.
-uint64_t DWARFDebugInfoEntry::GetAttributeValueAsReference(
-    SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
-    const dw_attr_t attr, uint64_t fail_value,
+DWARFDIE DWARFDebugInfoEntry::GetAttributeValueAsReference(
+    SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, const dw_attr_t attr,
     bool check_specification_or_abstract_origin) const {
   DWARFFormValue form_value;
   if (GetAttributeValue(dwarf2Data, cu, attr, form_value, nullptr,
                         check_specification_or_abstract_origin))
     return form_value.Reference();
-  return fail_value;
+  return {};
 }
 
 uint64_t DWARFDebugInfoEntry::GetAttributeValueAsAddress(
@@ -1207,8 +1195,9 @@
         // Follow the DW_AT_type if possible
         DWARFFormValue form_value;
         if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_type, form_value)) {
-          uint64_t next_die_offset = form_value.Reference();
-          result = AppendTypeName(dwarf2Data, cu, next_die_offset, s);
+          DWARFDIE next_die = form_value.Reference();
+          result = AppendTypeName(dwarf2Data, next_die.GetCU(),
+                                  next_die.GetOffset(), s);
         }
 
         switch (abbrevDecl->Tag()) {
@@ -1353,28 +1342,18 @@
       }
     }
 
-    dw_offset_t die_offset;
-
-    die_offset =
-        attributes.FormValueAsUnsigned(DW_AT_specification, DW_INVALID_OFFSET);
-    if (die_offset != DW_INVALID_OFFSET) {
-      DWARFDIE spec_die = cu->GetDIE(die_offset);
-      if (spec_die) {
-        DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE();
-        if (decl_ctx_die)
-          return decl_ctx_die;
-      }
+    DWARFDIE spec_die = attributes.FormValueAsReference(DW_AT_specification);
+    if (spec_die) {
+      DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE();
+      if (decl_ctx_die)
+        return decl_ctx_die;
     }
 
-    die_offset = attributes.FormValueAsUnsigned(DW_AT_abstract_origin,
-                                                DW_INVALID_OFFSET);
-    if (die_offset != DW_INVALID_OFFSET) {
-      DWARFDIE abs_die = cu->GetDIE(die_offset);
-      if (abs_die) {
-        DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE();
-        if (decl_ctx_die)
-          return decl_ctx_die;
-      }
+    DWARFDIE abs_die = attributes.FormValueAsReference(DW_AT_abstract_origin);
+    if (abs_die) {
+      DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE();
+      if (decl_ctx_die)
+        return decl_ctx_die;
     }
 
     die = die.GetParent();
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
index 85efd98..b0815e0 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -103,9 +103,8 @@
       const dw_attr_t attr, uint64_t fail_value,
       bool check_specification_or_abstract_origin = false) const;
 
-  uint64_t GetAttributeValueAsReference(
-      SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
-      const dw_attr_t attr, uint64_t fail_value,
+  DWARFDIE GetAttributeValueAsReference(
+      SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu, const dw_attr_t attr,
       bool check_specification_or_abstract_origin = false) const;
 
   uint64_t GetAttributeValueAsAddress(
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index 6d13a59..db05595 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -11,8 +11,9 @@
 #include "lldb/Core/dwarf.h"
 #include "lldb/Utility/Stream.h"
 
-#include "DWARFUnit.h"
+#include "DWARFDebugInfo.h"
 #include "DWARFFormValue.h"
+#include "DWARFUnit.h"
 
 class DWARFUnit;
 
@@ -544,7 +545,7 @@
   return symbol_file->get_debug_addr_data().GetMaxU64(&offset, index_size);
 }
 
-uint64_t DWARFFormValue::Reference() const {
+DWARFDIE DWARFFormValue::Reference() const {
   uint64_t value = m_value.value.uval;
   switch (m_form) {
   case DW_FORM_ref1:
@@ -554,15 +555,30 @@
   case DW_FORM_ref_udata:
     assert(m_unit); // Unit must be valid for DW_FORM_ref forms that are compile
                     // unit relative or we will get this wrong
-    return value + m_unit->GetOffset();
+    value += m_unit->GetOffset();
+    if (!m_unit->ContainsDIEOffset(value)) {
+      m_unit->GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError(
+          "DW_FORM_ref* DIE reference 0x%" PRIx64 " is outside of its CU",
+          value);
+      return {};
+    }
+    return const_cast<DWARFUnit *>(m_unit)->GetDIE(value);
 
-  case DW_FORM_ref_addr:
-  case DW_FORM_ref_sig8:
-  case DW_FORM_GNU_ref_alt:
-    return value;
+  case DW_FORM_ref_addr: {
+    DWARFUnit *ref_cu =
+        m_unit->GetSymbolFileDWARF()->DebugInfo()->GetUnitContainingDIEOffset(
+            value);
+    if (!ref_cu) {
+      m_unit->GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError(
+          "DW_FORM_ref_addr DIE reference 0x%" PRIx64 " has no matching CU",
+          value);
+      return {};
+    }
+    return ref_cu->GetDIE(value);
+  }
 
   default:
-    return DW_INVALID_OFFSET;
+    return {};
   }
 }
 
@@ -689,8 +705,8 @@
   case DW_FORM_ref4:
   case DW_FORM_ref8:
   case DW_FORM_ref_udata: {
-    uint64_t a = a_value.Reference();
-    uint64_t b = b_value.Reference();
+    uint64_t a = a_value.m_value.value.uval;
+    uint64_t b = b_value.m_value.value.uval;
     if (a < b)
       return -1;
     if (a > b)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
index 1495a1c..668bd5a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -14,6 +14,7 @@
 
 class DWARFUnit;
 class SymbolFileDWARF;
+class DWARFDIE;
 
 class DWARFFormValue {
 public:
@@ -58,7 +59,6 @@
   DWARFFormValue(const DWARFUnit *unit) : m_unit(unit) {}
   DWARFFormValue(const DWARFUnit *unit, dw_form_t form)
       : m_unit(unit), m_form(form) {}
-  const DWARFUnit *GetUnit() const { return m_unit; }
   void SetUnit(const DWARFUnit *unit) { m_unit = unit; }
   dw_form_t Form() const { return m_form; }
   dw_form_t& FormRef() { return m_form; }
@@ -71,7 +71,7 @@
   bool ExtractValue(const lldb_private::DWARFDataExtractor &data,
                     lldb::offset_t *offset_ptr);
   const uint8_t *BlockData() const;
-  uint64_t Reference() const;
+  DWARFDIE Reference() const;
   uint64_t Reference(dw_offset_t offset) const;
   bool Boolean() const { return m_value.value.uval != 0; }
   uint64_t Unsigned() const { return m_value.value.uval; }
@@ -94,6 +94,8 @@
   static bool FormIsSupported(dw_form_t form);
 
 protected:
+  // Compile unit where m_value was located.
+  // It may be different from compile unit where m_value refers to.
   const DWARFUnit *m_unit = nullptr; // Unit for this form
   dw_form_t m_form = 0;              // Form for this value
   ValueType m_value;            // Contains all data for the form
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index c39bfd3..101873c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -541,12 +541,10 @@
         if (die_offset == (*pos).GetOffset())
           return DWARFDIE(this, &(*pos));
       }
-    } else {
-      // Don't specify the compile unit offset as we don't know it because the
-      // DIE belongs to
-      // a different compile unit in the same symbol file.
-      return m_dwarf->DebugInfo()->GetDIEForDIEOffset(die_offset);
-    }
+    } else
+      GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError(
+          "GetDIE for DIE 0x%" PRIx32 " is outside of its CU 0x%" PRIx32,
+          die_offset, GetOffset());
   }
   return DWARFDIE(); // Not found
 }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 622119c..ae7e463 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3309,7 +3309,7 @@
             }
           } break;
           case DW_AT_specification:
-            spec_die = GetDIE(DIERef(form_value));
+            spec_die = form_value.Reference();
             break;
           case DW_AT_start_scope: {
             if (form_value.Form() == DW_FORM_sec_offset) {
@@ -3584,12 +3584,11 @@
     case DW_TAG_subprogram:
     case DW_TAG_inlined_subroutine:
     case DW_TAG_lexical_block: {
-      if (die.GetAttributeValueAsReference(
-              DW_AT_specification, DW_INVALID_OFFSET) == spec_block_die_offset)
+      if (die.GetReferencedDIE(DW_AT_specification).GetOffset() ==
+          spec_block_die_offset)
         return die;
 
-      if (die.GetAttributeValueAsReference(DW_AT_abstract_origin,
-                                           DW_INVALID_OFFSET) ==
+      if (die.GetReferencedDIE(DW_AT_abstract_origin).GetOffset() ==
           spec_block_die_offset)
         return die;
     } break;