jankratochvil updated this revision to Diff 374775.
jankratochvil retitled this revision from "[lldb] DWZ 5/9: Main functionality" 
to "[lldb] DWZ 13/17: Main functionality".
jankratochvil edited the summary of this revision.
jankratochvil added a comment.
Herald added a reviewer: jdoerfert.
Herald added a subscriber: sstefan1.

My question about upstreaming of this patchset. 
<https://reviews.llvm.org/D96236#3020116>


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D96240/new/

https://reviews.llvm.org/D96240

Files:
  lldb/include/lldb/Utility/ConstString.h
  lldb/include/lldb/Utility/FileSpec.h
  lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
  lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
  lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h
  lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFUnitPair.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
  lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
  lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwz.cpp
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwz.h

Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwz.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwz.h
@@ -0,0 +1,36 @@
+//===-- SymbolFileDWARFDwz.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARFDwz_SymbolFileDWARFDwz_h_
+#define SymbolFileDWARFDwz_SymbolFileDWARFDwz_h_
+
+#include "SymbolFileDWARF.h"
+
+typedef std::unique_ptr<SymbolFileDWARFDwz> SymbolFileDWARFDwzUP;
+
+class SymbolFileDWARFDwz : public SymbolFileDWARF {
+public:
+  SymbolFileDWARFDwz(lldb::ObjectFileSP objfile, lldb::ModuleSP m_module);
+
+  bool GetIsDwz() const override { return true; }
+
+  static void InitializeForDWARF(SymbolFileDWARF &dwarf);
+
+  void ClearForDWARF(SymbolFileDWARF &dwarf);
+
+private:
+  void SetForDWARF(SymbolFileDWARF &dwarf);
+
+  size_t m_use_count = 0;
+  lldb::ModuleSP m_module;
+
+  SymbolFileDWARFDwz(const SymbolFileDWARFDwz &) = delete;
+  const SymbolFileDWARFDwz &operator=(const SymbolFileDWARFDwz &) = delete;
+};
+
+#endif // SymbolFileDWARFDwz_SymbolFileDWARFDwz_h_
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwz.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwz.cpp
@@ -0,0 +1,175 @@
+//===-- SymbolFileDWARFDwz.cpp ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolFileDWARFDwz.h"
+#include "DWARFDebugInfo.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/FileSpec.h"
+#include "llvm/ADT/PointerUnion.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SymbolFileDWARFDwz::SymbolFileDWARFDwz(ObjectFileSP objfile, ModuleSP module)
+    : SymbolFileDWARF(std::move(objfile), /*dwo_section_list*/ nullptr),
+      m_module(std::move(module)) {
+  InitializeObject();
+  // Call private DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() as
+  // otherwise DWARFCompileUnit::GetAbbreviations() would have no data.
+  DebugInfo().GetNumUnits();
+}
+
+// C++20: Use heterogeneous lookup for unordered container instead.
+class DwzAsKey {
+public:
+  DwzAsKey(SymbolFileDWARFDwz &dwz) : ptr(&dwz) {}
+  DwzAsKey(FileSpec &fspec) : ptr(&fspec) {}
+  DwzAsKey() {}
+  SymbolFileDWARFDwz &GetDwz() const {
+    return *ptr.get<SymbolFileDWARFDwz *>();
+  }
+  FileSpec &GetFileSpec() const {
+    if (ptr.is<FileSpec *>())
+      return *ptr.get<FileSpec *>();
+    return GetDwz().GetObjectFile()->GetFileSpec();
+  }
+  bool operator==(const DwzAsKey &rhs) const {
+    return GetFileSpec() == rhs.GetFileSpec();
+  }
+  bool operator!=(const DwzAsKey &rhs) const { return !(*this == rhs); }
+  class Hasher {
+  public:
+    size_t operator()(const DwzAsKey &key) const {
+      return FileSpec::Hasher()(key.GetFileSpec());
+    }
+  };
+
+private:
+  llvm::PointerUnion<SymbolFileDWARFDwz *, FileSpec *> ptr;
+};
+
+static std::unordered_map<DwzAsKey, SymbolFileDWARFDwzUP, DwzAsKey::Hasher>
+    dwz_map;
+static llvm::sys::RWMutex dwz_map_mutex;
+
+void SymbolFileDWARFDwz::InitializeForDWARF(SymbolFileDWARF &dwarf) {
+  const DWARFDataExtractor &section_extractor(
+      dwarf.GetDWARFContext().getOrLoadGNUDebugAltLink());
+  if (section_extractor.GetByteSize() == 0)
+    return; // .gnu_debugaltlink does not exist
+  if (dwarf.GetIsDwz()) {
+    dwarf.GetObjectFile()->GetModule()->ReportWarning(
+        "Error reading DWZ common file - it does contain .gnu_debugaltlink");
+    return;
+  }
+  lldb::offset_t offset = 0;
+  const char *link_cstr(section_extractor.GetCStr(&offset));
+  if (!link_cstr) {
+    dwarf.GetObjectFile()->GetModule()->ReportWarning(
+        "Cannot get DWZ common file - missing section .gnu_debugaltlink");
+    return;
+  }
+  lldb::offset_t uuid_bytes_size = section_extractor.BytesLeft(offset);
+  const void *uuid_bytes(section_extractor.GetData(&offset, uuid_bytes_size));
+  if (!uuid_bytes) {
+    dwarf.GetObjectFile()->GetModule()->ReportWarning(
+        "Cannot get DWZ common file - missing build-id"
+        " in section .gnu_debugaltlink with string \"%s\"",
+        link_cstr);
+    return;
+  }
+  UUID link_uuid = UUID::fromOptionalData(uuid_bytes, uuid_bytes_size);
+  if (!link_uuid.IsValid()) {
+    dwarf.GetObjectFile()->GetModule()->ReportWarning(
+        "Cannot get DWZ common file - invalid build-id size %" PRIu64
+        " in section .gnu_debugaltlink with string \"%s\"",
+        uuid_bytes_size, link_cstr);
+    return;
+  }
+  // For objfile "/usr/lib/debug/usr/bin/true.debug"
+  // link_cstr is "../../.dwz/coreutils-8.25-17.fc25.x86_64".
+  ModuleSpec dwz_module_spec;
+  FileSpec &dwz_fspec = dwz_module_spec.GetFileSpec();
+  dwz_fspec = FileSpec(link_cstr);
+  dwz_fspec.PrependPathComponent(
+      dwarf.GetObjectFile()->GetFileSpec().CopyByRemovingLastPathComponent());
+  DwzAsKey dwz_fspec_lookup(dwz_fspec);
+  {
+    llvm::sys::ScopedReader lock(dwz_map_mutex);
+    const auto it = dwz_map.find(dwz_fspec_lookup);
+    if (it != dwz_map.end()) {
+      it->second->SetForDWARF(dwarf);
+      return;
+    }
+  }
+  dwz_module_spec.GetArchitecture() =
+      dwarf.GetObjectFile()->GetModule()->GetArchitecture();
+  ModuleSP dwz_module = std::make_shared<Module>(dwz_module_spec);
+  DataBufferSP dwz_file_data_sp;
+  lldb::offset_t dwz_file_data_offset = 0;
+  lldb::ObjectFileSP dwz_obj_file = ObjectFile::FindPlugin(
+      dwz_module, &dwz_fspec, 0, FileSystem::Instance().GetByteSize(dwz_fspec),
+      dwz_file_data_sp, dwz_file_data_offset);
+  if (!dwz_obj_file) {
+    dwarf.GetObjectFile()->GetModule()->ReportWarning(
+        "Cannot get DWZ common file - file \"%s\" cannot be opened",
+        dwz_fspec.GetCString());
+    return;
+  }
+  lldbassert(dwz_obj_file->GetFileSpec() == dwz_fspec);
+  UUID dwz_uuid = dwz_obj_file->GetUUID();
+  if (!dwz_uuid) {
+    dwarf.GetObjectFile()->GetModule()->ReportWarning(
+        "Cannot get DWZ common file - file \"%s\" does not have build-id",
+        dwz_fspec.GetCString());
+    return;
+  }
+  if (link_uuid != dwz_uuid) {
+    dwarf.GetObjectFile()->GetModule()->ReportWarning(
+        "Cannot get DWZ common file - expected build-id %s but file \"%s\""
+        " has build-id %s",
+        link_uuid.GetAsString().c_str(), dwz_fspec.GetCString(),
+        dwz_uuid.GetAsString().c_str());
+    return;
+  }
+  auto dwz_symbol_file =
+      std::make_unique<SymbolFileDWARFDwz>(dwz_obj_file, std::move(dwz_module));
+  assert(DwzAsKey(*dwz_symbol_file) == dwz_fspec_lookup);
+  {
+    llvm::sys::ScopedWriter lock(dwz_map_mutex);
+    const auto it = dwz_map.find(dwz_fspec_lookup);
+    if (it != dwz_map.end())
+      it->second->SetForDWARF(dwarf);
+    else {
+      dwz_symbol_file->SetForDWARF(dwarf);
+      const auto insertpair = dwz_map.emplace(DwzAsKey(*dwz_symbol_file),
+                                              std::move(dwz_symbol_file));
+      lldbassert(insertpair.second);
+    }
+  }
+}
+
+void SymbolFileDWARFDwz::SetForDWARF(SymbolFileDWARF &dwarf) {
+  lldbassert(&dwarf != this);
+  lldbassert(!dwarf.m_dwz_symfile);
+  dwarf.m_dwz_symfile = this;
+  ++m_use_count;
+}
+
+void SymbolFileDWARFDwz::ClearForDWARF(SymbolFileDWARF &main_dwarf) {
+  lldbassert(main_dwarf.m_dwz_symfile == this);
+  llvm::sys::ScopedWriter lock(dwz_map_mutex);
+  lldbassert(m_use_count);
+  if (--m_use_count)
+    return;
+  size_t erased = dwz_map.erase(DwzAsKey(*this));
+  lldbassert(erased == 1);
+}
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -52,6 +52,7 @@
 class SymbolFileDWARFDebugMap;
 class SymbolFileDWARFDwo;
 class SymbolFileDWARFDwp;
+class SymbolFileDWARFDwz;
 
 #define DIE_IS_BEING_PARSED ((lldb_private::Type *)1)
 
@@ -75,6 +76,7 @@
   friend class DWARFCompileUnit;
   friend class DWARFDIE;
   friend class DWARFASTParserClang;
+  friend class SymbolFileDWARFDwz;
 
   // Static Functions
   static void Initialize();
@@ -318,6 +320,9 @@
   /// Same as GetLanguage() but reports all C++ versions as C++ (no version).
   static lldb::LanguageType GetLanguageFamily(DWARFUnit &unit);
 
+  SymbolFileDWARFDwz *GetDwzSymbolFile() const { return m_dwz_symfile; }
+  virtual bool GetIsDwz() const { return false; }
+
   llvm::Optional<uint32_t> GetDWARFUnitIndex(uint32_t cu_idx);
 
 protected:
@@ -484,6 +489,8 @@
 
   const lldb_private::FileSpecList &GetSharedUnitSupportFiles(DWARFUnit &tu);
 
+  SymbolFileDWARFDwz *m_dwz_symfile = nullptr;
+
   lldb::ModuleWP m_debug_map_module_wp;
   SymbolFileDWARFDebugMap *m_debug_map_symfile;
 
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -72,6 +72,7 @@
 #include "ManualDWARFIndex.h"
 #include "SymbolFileDWARFDebugMap.h"
 #include "SymbolFileDWARFDwo.h"
+#include "SymbolFileDWARFDwz.h"
 
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/Support/FileSystem.h"
@@ -440,7 +441,10 @@
       m_fetched_external_modules(false),
       m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {}
 
-SymbolFileDWARF::~SymbolFileDWARF() = default;
+SymbolFileDWARF::~SymbolFileDWARF() {
+  if (m_dwz_symfile)
+    m_dwz_symfile->ClearForDWARF(*this);
+}
 
 static ConstString GetDWARFMachOSegmentName() {
   static ConstString g_dwarf_section_name("__DWARF");
@@ -457,6 +461,8 @@
 
 llvm::Expected<TypeSystem &>
 SymbolFileDWARF::GetTypeSystemForLanguage(LanguageType language) {
+  lldbassert(!GetIsDwz());
+
   if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile())
     return debug_map_symfile->GetTypeSystemForLanguage(language);
 
@@ -471,6 +477,9 @@
 void SymbolFileDWARF::InitializeObject() {
   Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO);
 
+  // DWZ needs to be already prepared for indexing below.
+  SymbolFileDWARFDwz::InitializeForDWARF(*this);
+
   if (!GetGlobalPluginProperties()->IgnoreFileIndexes()) {
     StreamString module_desc;
     GetObjectFile()->GetModule()->GetDescription(module_desc.AsRawOstream(),
@@ -700,6 +709,7 @@
 }
 
 lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
+  lldbassert(!GetIsDwz());
   CompUnitSP cu_sp;
   CompileUnit *comp_unit = (CompileUnit *)dwarf_cu.GetUserData();
   if (comp_unit) {
@@ -981,9 +991,13 @@
 
 FileSpec SymbolFileDWARF::GetFile(DWARFUnit &unit, size_t file_idx) {
   if (auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(&unit)) {
-    if (CompileUnit *lldb_cu = GetCompUnitForDWARFCompUnit(*dwarf_cu))
-      return lldb_cu->GetSupportFiles().GetFileSpecAtIndex(file_idx);
-    return FileSpec();
+    // Try to prevent GetUnitDIEOnly() which may be expensive.
+    if (!unit.GetSymbolFileDWARF().GetIsDwz() &&
+        unit.GetUnitDIEOnly().Tag() == DW_TAG_compile_unit) {
+      if (CompileUnit *lldb_cu = GetCompUnitForDWARFCompUnit(*dwarf_cu))
+        return lldb_cu->GetSupportFiles().GetFileSpecAtIndex(file_idx);
+      return FileSpec();
+    }
   }
 
   return GetSharedUnitSupportFiles(unit).GetFileSpecAtIndex(file_idx);
@@ -1341,6 +1355,8 @@
   if (GetDebugMapSymfile())
     return GetID() | ref.die_offset();
 
+  lldbassert(!GetIsDwz());
+
 #ifndef NDEBUG
   DWARFDIE dwarfdie_check = GetDIE(ref);
   lldbassert(dwarfdie_check.IsValid());
@@ -1400,8 +1416,15 @@
   if (kind == DIERef::Kind::DwoKind)
     dwo_num = uid >> 32 & 0x1fffffff;
 
-  return DecodedUID{
-      *this, {dwo_num, llvm::None, DIERef::MainDwz, section, die_offset}};
+  llvm::Optional<uint32_t> main_cu = uid >> 32 & 0x1fffffff;
+  if (kind != DIERef::Kind::MainDwzKind && kind != DIERef::Kind::DwzCommonKind)
+    main_cu = llvm::None;
+
+  return DecodedUID{*this,
+                    {dwo_num, main_cu,
+                     kind == DIERef::Kind::DwzCommonKind ? DIERef::CommonDwz
+                                                         : DIERef::MainDwz,
+                     section, die_offset}};
 }
 
 DWARFDIE
@@ -1663,6 +1686,8 @@
 DWARFDIE
 SymbolFileDWARF::GetDIE(const DIERef &die_ref) {
   if (die_ref.dwo_num()) {
+    lldbassert(!GetIsDwz());
+    lldbassert(!GetDwzSymbolFile());
     SymbolFileDWARF *dwarf = *die_ref.dwo_num() == 0x1fffffff
                                  ? m_dwp_symfile.get()
                                  : this->DebugInfo()
@@ -3959,6 +3984,8 @@
 }
 
 LanguageType SymbolFileDWARF::GetLanguage(DWARFUnit &unit) {
+  // Caller should have called GetMainCU().
+  lldbassert(unit.GetUnitDIEOnly().Tag() != DW_TAG_partial_unit);
   return LanguageTypeFromDWARF(unit.GetDWARFLanguageType());
 }
 
Index: lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
@@ -9,6 +9,7 @@
 #include "NameToDIE.h"
 #include "DWARFDebugInfo.h"
 #include "DWARFUnit.h"
+#include "SymbolFileDWARFDwz.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Utility/ConstString.h"
@@ -51,6 +52,7 @@
   lldbassert(!s_unit.GetSymbolFileDWARF().GetDwoNum());
   const DWARFUnit &ns_unit = s_unit.GetNonSkeletonUnit();
   SymbolFileDWARF *ns_symfile = &ns_unit.GetSymbolFileDWARF();
+  lldbassert(!ns_symfile->GetIsDwz());
   const uint32_t size = m_map.GetSize();
   for (uint32_t i = 0; i < size; ++i) {
     const DIERef &die_ref = m_map.GetValueAtIndexUnchecked(i);
Index: lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -11,6 +11,7 @@
 #include "Plugins/SymbolFile/DWARF/DWARFCompileUnit.h"
 #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
 #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
+#include "Plugins/SymbolFile/DWARF/DWARFSimpleDIE.h"
 #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
 #include "lldb/Core/Module.h"
@@ -132,6 +133,8 @@
   // DWZ DW_TAG_partial_unit will get indexed by DW_AT_import
   // from its DW_TAG_compile_unit (possibly transitively).
   // Try to prevent GetUnitDIEOnly() which is expensive.
+  if (unit.GetSymbolFileDWARF().GetIsDwz())
+    return;
   if (unit.GetUnitDIEOnly().Tag() == DW_TAG_partial_unit)
     return;
   IndexUnit(&unit, dwp, set);
@@ -144,6 +147,8 @@
     // DWZ DW_TAG_partial_unit will get indexed by DW_AT_import
     // from its DW_TAG_compile_unit (possibly transitively).
     // GetUnitDIEPtrOnly() is too expensive.
+    if (unit->GetSymbolFileDWARF().GetIsDwz())
+      return;
     if (unit->GetUnitDIEOnly().Tag() == DW_TAG_partial_unit)
       return;
   }
@@ -157,6 +162,15 @@
                         unit->GetOffset(), unit.GetMainCU()->GetOffset());
   }
 
+  // DWZ DW_TAG_partial_unit will get indexed through DW_TAG_imported_unit from
+  // its main DW_TAG_compile_unit (possibly transitively). Indexing it
+  // standalone is not possible as we would not have its main CU. Also try to
+  // prevent calling GetUnitDIEOnly() which may be expensive.
+  if (unit->GetSymbolFileDWARF().GetIsDwz())
+    return;
+  if (unit->GetUnitDIEOnly().Tag() == DW_TAG_partial_unit)
+    return;
+
   IndexUnitImpl(unit, set);
 
   if (SymbolFileDWARFDwo *dwo_symbol_file = unit->GetDwoSymbolFile()) {
@@ -202,6 +216,7 @@
     case DW_TAG_union_type:
     case DW_TAG_unspecified_type:
     case DW_TAG_variable:
+    case DW_TAG_imported_unit:
       break;
 
     default:
@@ -217,7 +232,7 @@
     bool has_location_or_const_value = false;
     bool is_global_or_static_variable = false;
 
-    DWARFFormValue specification_die_form;
+    DWARFFormValue specification_die_form, import_die_form;
     const size_t num_attributes = die.GetAttributes(&unit, attributes);
     if (num_attributes > 0) {
       for (uint32_t i = 0; i < num_attributes; ++i) {
@@ -261,6 +276,11 @@
           if (attributes.ExtractFormValueAtIndex(i, form_value))
             specification_die_form = form_value;
           break;
+
+        case DW_AT_import:
+          if (attributes.ExtractFormValueAtIndex(i, form_value))
+            import_die_form = form_value;
+          break;
         }
       }
     }
@@ -363,6 +383,39 @@
       }
       break;
 
+    case DW_TAG_imported_unit:
+      if (import_die_form.IsValid()) {
+        // DWZ is using DW_TAG_imported_unit only at the top level of CUs.
+        // Therefore GetParent() of any top level DIE in partial unit is always
+        // DW_TAG_compile_unit (possibly after multiple import levels).
+        const DWARFDebugInfoEntry *parent_die = die.GetParent();
+        if (!parent_die || (parent_die->Tag() != DW_TAG_compile_unit &&
+                            parent_die->Tag() != DW_TAG_partial_unit)) {
+          unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
+              "CU 0x%8.8" PRIx32 " DIE 0x%8.8" PRIx32
+              " DW_TAG_imported_unit does not have DW_TAG_compile_unit"
+              " as its parent",
+              unit.GetOffset(), die.GetOffset());
+          break;
+        }
+        DWARFSimpleDIE import_die = import_die_form.Reference();
+        if (!import_die.IsValid())
+          break;
+        DWARFUnit *import_cu = import_die.GetCU();
+        dw_offset_t import_cu_firstdie_offset = import_cu->GetFirstDIEOffset();
+        if (import_die.GetOffset() != import_cu_firstdie_offset) {
+          unit.GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
+              "CU 0x%8.8" PRIx32 " DIE 0x%8.8" PRIx32
+              " DW_TAG_imported_unit of DIE 0x%16.16" PRIx32
+              " is not the target CU first DIE 0x%8.8" PRIx32,
+              unit.GetOffset(), die.GetOffset(), import_die.GetOffset(),
+              import_cu_firstdie_offset);
+          break;
+        }
+        IndexUnitImpl({import_cu, unitpair.GetMainCU()}, set);
+      }
+      break;
+
     default:
       continue;
     }
Index: lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
@@ -46,6 +46,7 @@
   if (!cu_offset)
     return llvm::None;
 
+  // FIXME: .debug_names have no DWZ support yet.
   DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *cu_offset);
   if (!cu)
     return llvm::None;
@@ -170,6 +171,7 @@
     if (!ref)
       continue;
 
+    // FIXME: .debug_names have no DWZ support yet.
     DWARFUnit *cu = m_debug_info.GetUnit(*ref);
     if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) {
       incomplete_types.push_back(*ref);
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFUnitPair.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFUnitPair.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFUnitPair.cpp
@@ -6,7 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "Plugins/SymbolFile/DWARF/DWARFUnitPair.h"
+#include "DWARFUnitPair.h"
+#include "DWARFUnit.h"
 #include <assert.h>
 
 DWARFUnitPair::DWARFUnitPair() : m_cu(nullptr), m_main_cu(nullptr) {}
@@ -14,6 +15,7 @@
     : m_cu(cu), m_main_cu(main_cu) {
   assert(m_cu);
   assert(m_main_cu);
+  assert(!m_main_cu->GetSymbolFileDWARF().GetIsDwz());
 }
 DWARFUnitPair::DWARFUnitPair(DWARFUnit *main_cu)
     : DWARFUnitPair(static_cast<DWARFUnit *>(main_cu), main_cu) {}
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -737,6 +737,8 @@
 }
 
 uint64_t DWARFUnit::GetDWARFLanguageType() {
+  lldbassert(!GetSymbolFileDWARF().GetIsDwz());
+
   if (m_language_type)
     return *m_language_type;
 
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFTypeUnit.h
@@ -29,7 +29,9 @@
                 const DWARFUnitHeader &header,
                 const DWARFAbbreviationDeclarationSet &abbrevs,
                 DIERef::Section section, bool is_dwo)
-      : DWARFUnit(dwarf, uid, header, abbrevs, section, is_dwo) {}
+      : DWARFUnit(dwarf, uid, header, abbrevs, section, is_dwo) {
+    assert(!dwarf.GetIsDwz());
+  }
 
   friend class DWARFUnit;
 };
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -18,6 +18,7 @@
 #include "DWARFFormValue.h"
 #include "DWARFSimpleDIE.h"
 #include "DWARFUnit.h"
+#include "SymbolFileDWARFDwz.h"
 
 class DWARFUnit;
 
@@ -78,6 +79,7 @@
     case DW_FORM_strp:
     case DW_FORM_line_strp:
     case DW_FORM_sec_offset:
+    case DW_FORM_GNU_strp_alt:
       m_value.value.uval = data.GetMaxU64(offset_ptr, 4);
       break;
     case DW_FORM_addrx1:
@@ -126,6 +128,11 @@
         ref_addr_size = 4;
       m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size);
       break;
+    case DW_FORM_GNU_ref_alt:
+      assert(m_unit);
+      ref_addr_size = 4;
+      m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size);
+      break;
     case DW_FORM_indirect:
       m_form = data.GetULEB128(offset_ptr);
       indirect = true;
@@ -257,6 +264,11 @@
     *offset_ptr += ref_addr_size;
     return true;
 
+  case DW_FORM_GNU_ref_alt:
+    ref_addr_size = 4;
+    *offset_ptr += ref_addr_size;
+    return true;
+
   // 0 bytes values (implied from DW_FORM)
   case DW_FORM_flag_present:
   case DW_FORM_implicit_const:
@@ -289,6 +301,7 @@
     case DW_FORM_sec_offset:
     case DW_FORM_strp:
     case DW_FORM_line_strp:
+    case DW_FORM_GNU_strp_alt:
       *offset_ptr += 4;
       return true;
 
@@ -437,6 +450,9 @@
   case DW_FORM_ref_udata:
     unit_relative_offset = true;
     break;
+  case DW_FORM_GNU_ref_alt:
+    DumpAddress(s.AsRawOstream(), uvalue, 4 * 2);
+    break;
 
   // All DW_FORM_indirect attributes should be resolved prior to calling this
   // function
@@ -479,6 +495,20 @@
   if (m_form == DW_FORM_line_strp)
     return context.getOrLoadLineStrData().PeekCStr(m_value.value.uval);
 
+  if (m_form == DW_FORM_GNU_strp_alt) {
+    SymbolFileDWARFDwz *dwz_symbol_file =
+        m_unit->GetSymbolFileDWARF().GetDwzSymbolFile();
+    if (!dwz_symbol_file) {
+      m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
+          "String reference to DWZ offset 0x%8.8" PRIx64
+          " is in a file without associated DWZ common file",
+          m_value.value.uval);
+      return nullptr;
+    }
+    return dwz_symbol_file->GetDWARFContext().getOrLoadStrData().PeekCStr(
+        m_value.value.uval);
+  }
+
   return nullptr;
 }
 
@@ -510,6 +540,7 @@
   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
+    // The offset adjustment is already appropriate inside this CU.
     value += m_unit->GetOffset();
     if (!m_unit->ContainsDIEOffset(value)) {
       m_unit->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
@@ -521,7 +552,48 @@
     return {cu, cu->GetDIEPtr(value)};
   }
 
+  case DW_FORM_GNU_ref_alt: {
+    assert(m_unit);
+    SymbolFileDWARF &symbol_file = m_unit->GetSymbolFileDWARF();
+    if (symbol_file.GetIsDwz())
+      symbol_file.GetObjectFile()->GetModule()->ReportError(
+          "DW_FORM_GNU_ref_alt to DWZ offset 0x%8.8" PRIx64
+          " is in a DWZ common file itself",
+          value);
+    else if (!symbol_file.GetDwzSymbolFile()) {
+      symbol_file.GetObjectFile()->GetModule()->ReportError(
+          "DW_FORM_GNU_ref_alt to DWZ offset 0x%8.8" PRIx64
+          " has no DWZ common file",
+          value);
+      return {};
+    }
+    SymbolFileDWARF *target_symbol_file = &symbol_file;
+    if (!target_symbol_file->GetIsDwz()) {
+      target_symbol_file = symbol_file.GetDwzSymbolFile();
+      if (!target_symbol_file) {
+        symbol_file.GetObjectFile()->GetModule()->ReportError(
+            "There is Reference to DWZ offset 0x%8.8" PRIx64
+            " but the DWZ common file is missing",
+            value);
+        return {};
+      }
+    }
+    lldbassert(target_symbol_file->GetIsDwz());
+    DWARFDebugInfo &target_debuginfo = target_symbol_file->DebugInfo();
+    DWARFUnit *target_cu = target_debuginfo.GetUnitContainingDIEOffset(
+        DIERef::Section::DebugInfo, value);
+    if (!target_cu) {
+      symbol_file.GetObjectFile()->GetModule()->ReportError(
+          "There is Reference to DWZ offset 0x%8.8" PRIx64
+          " but the DWZ common file does not contain a unit for that offset",
+          value);
+      return {};
+    }
+    return target_cu->GetDIE(const_cast<DWARFUnit *>(m_unit), value);
+  }
+
   case DW_FORM_ref_addr: {
+    assert(m_unit);
     DWARFUnit *ref_cu =
         m_unit->GetSymbolFileDWARF().DebugInfo().GetUnitContainingDIEOffset(
             DIERef::Section::DebugInfo, value);
@@ -647,6 +719,8 @@
     case DW_FORM_GNU_str_index:
     case DW_FORM_GNU_addr_index:
     case DW_FORM_implicit_const:
+    case DW_FORM_GNU_ref_alt:
+    case DW_FORM_GNU_strp_alt:
       return true;
     default:
       break;
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -116,6 +116,9 @@
           else
             form_size = 4;
           break;
+        case DW_FORM_GNU_ref_alt:
+          form_size = 4;
+          break;
 
         // 0 sized form
         case DW_FORM_flag_present:
@@ -180,6 +183,7 @@
 
         case DW_FORM_strp:
         case DW_FORM_line_strp:
+        case DW_FORM_GNU_strp_alt:
         case DW_FORM_sec_offset:
           data.GetU32(&offset);
           break;
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -24,6 +24,7 @@
 #include "DWARFDebugInfoEntry.h"
 #include "DWARFFormValue.h"
 #include "DWARFTypeUnit.h"
+#include "SymbolFileDWARFDwz.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -38,6 +39,8 @@
   if (m_cu_aranges_up)
     return *m_cu_aranges_up;
 
+  lldbassert(!m_dwarf.GetIsDwz());
+
   m_cu_aranges_up = std::make_unique<DWARFDebugAranges>();
   const DWARFDataExtractor &debug_aranges_data =
       m_context.getOrLoadArangesData();
@@ -150,11 +153,24 @@
 }
 
 DWARFUnit *DWARFDebugInfo::GetUnit(const DIERef &die_ref) {
+  bool dwz_common =
+      die_ref.main_cu() && die_ref.dwz_common() == DIERef::CommonDwz;
+  if (dwz_common && !m_dwarf.GetIsDwz()) {
+    lldbassert(m_dwarf.GetDwzSymbolFile());
+    return m_dwarf.GetDwzSymbolFile()->DebugInfo().GetUnit(die_ref);
+  }
+  lldbassert(dwz_common == m_dwarf.GetIsDwz());
   return GetUnitContainingDIEOffset(die_ref.section(), die_ref.die_offset());
 }
 
 DWARFUnit *DWARFDebugInfo::GetMainUnit(const DIERef &die_ref) {
-  return GetUnit(die_ref);
+  DWARFUnit *main_unit;
+  if (!die_ref.main_cu())
+    main_unit = GetUnit(die_ref);
+  else
+    main_unit = GetUnitAtIndex(*m_dwarf.GetDWARFUnitIndex(*die_ref.main_cu()));
+  lldbassert(!main_unit->GetSymbolFileDWARF().GetIsDwz());
+  return main_unit;
 }
 
 DWARFUnit *
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -32,6 +32,11 @@
 
   DWARFDIE DIE() { return {DWARFUnitPair(this), DIEPtr()}; }
 
+  static DWARFCompileUnit *GetMainUnit(const lldb_private::SymbolContext &sc,
+                                       SymbolFileDWARF **dwarf_return);
+  static DWARFCompileUnit *GetMainUnit(lldb_private::CompileUnit &comp_unit,
+                                       SymbolFileDWARF **dwarf_return);
+
 private:
   DWARFCompileUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
                    const DWARFUnitHeader &header,
@@ -42,6 +47,10 @@
   DWARFCompileUnit(const DWARFCompileUnit &) = delete;
   const DWARFCompileUnit &operator=(const DWARFCompileUnit &) = delete;
 
+  static DWARFCompileUnit *GetMainUnit(lldb_private::Module &module,
+                                       lldb_private::CompileUnit *comp_unit,
+                                       SymbolFileDWARF **dwarf_return);
+
   friend class DWARFUnit;
 };
 
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -10,6 +10,7 @@
 #include "DWARFDebugAranges.h"
 #include "SymbolFileDWARFDebugMap.h"
 
+#include "lldb/Core/Module.h"
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Symbol/LineTable.h"
 #include "lldb/Utility/Stream.h"
@@ -36,6 +37,10 @@
   // First get the compile unit DIE only and check contains ranges information.
   const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
 
+  // DWZ partial units never contain any PC.
+  if (die && die->Tag() == DW_TAG_partial_unit)
+    return;
+
   const dw_offset_t cu_offset = GetOffset();
   if (die) {
     DWARFRangeList ranges;
@@ -116,3 +121,40 @@
   }
   return DWARFDIE();
 }
+
+DWARFCompileUnit *
+DWARFCompileUnit::GetMainUnit(Module &module, CompileUnit *comp_unit,
+                              SymbolFileDWARF **dwarf_return) {
+  SymbolFile *symfile = module.GetSymbolFile();
+  SymbolFileDWARF *dwarf;
+  if (auto *debug_map_symfile =
+          llvm::dyn_cast<SymbolFileDWARFDebugMap>(symfile)) {
+    lldbassert(comp_unit);
+    dwarf = debug_map_symfile->GetSymbolFile(*comp_unit);
+  } else {
+    dwarf = llvm::dyn_cast<SymbolFileDWARF>(symfile);
+    lldbassert(dwarf);
+  }
+  if (dwarf_return)
+    *dwarf_return = dwarf;
+  if (!comp_unit) {
+    lldbassert(dwarf_return);
+    return nullptr;
+  }
+  return dwarf->GetDWARFCompileUnit(comp_unit);
+}
+
+DWARFCompileUnit *
+DWARFCompileUnit::GetMainUnit(CompileUnit &comp_unit,
+                              SymbolFileDWARF **dwarf_return) {
+  ModuleSP module_sp = comp_unit.CalculateSymbolContextModule();
+  lldbassert(module_sp);
+  return GetMainUnit(*module_sp, &comp_unit, dwarf_return);
+}
+
+DWARFCompileUnit *
+DWARFCompileUnit::GetMainUnit(const SymbolContext &sc,
+                              SymbolFileDWARF **dwarf_return) {
+  lldbassert(sc.module_sp);
+  return GetMainUnit(*sc.module_sp, sc.comp_unit, dwarf_return);
+}
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
@@ -34,7 +34,9 @@
   return DIERef(
       m_cu->GetSymbolFileDWARF().GetDwoNum(),
       (!main_unit ? llvm::None : llvm::Optional<uint32_t>(main_unit->GetID())),
-      DIERef::MainDwz, m_cu->GetDebugSection(), m_die->GetOffset());
+      GetCU()->GetSymbolFileDWARF().GetIsDwz() ? DIERef::CommonDwz
+                                               : DIERef::MainDwz,
+      m_cu->GetDebugSection(), m_die->GetOffset());
 }
 
 dw_tag_t DWARFBaseDIE::Tag() const {
Index: lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
+++ lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
@@ -39,6 +39,7 @@
   NameToDIE.cpp
   SymbolFileDWARF.cpp
   SymbolFileDWARFDwo.cpp
+  SymbolFileDWARFDwz.cpp
   SymbolFileDWARFDebugMap.cpp
   UniqueDWARFASTType.cpp
 
Index: lldb/include/lldb/Utility/FileSpec.h
===================================================================
--- lldb/include/lldb/Utility/FileSpec.h
+++ lldb/include/lldb/Utility/FileSpec.h
@@ -397,6 +397,14 @@
 
   ConstString GetLastPathComponent() const;
 
+  class Hasher {
+  public:
+    size_t operator()(const FileSpec &key) const {
+      return (ConstString::Hasher()(key.m_directory) << 16) ^
+             ConstString::Hasher()(key.m_filename) ^ key.m_is_resolved;
+    }
+  };
+
 protected:
   friend struct llvm::yaml::MappingTraits<FileSpec>;
 
Index: lldb/include/lldb/Utility/ConstString.h
===================================================================
--- lldb/include/lldb/Utility/ConstString.h
+++ lldb/include/lldb/Utility/ConstString.h
@@ -408,6 +408,17 @@
   ///     in memory.
   static size_t StaticMemorySize();
 
+  class Hasher {
+  public:
+    size_t operator()(const ConstString &key) const {
+      // https://stackoverflow.com/questions/7666509/hash-function-for-string
+      size_t hash = 5381;
+      for (const char *p = key.m_string; *p; ++p)
+        hash = hash * 33 + static_cast<uint8_t>(*p);
+      return hash;
+    }
+  };
+
 protected:
   template <typename T> friend struct ::llvm::DenseMapInfo;
   /// Only used by DenseMapInfo.
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
  • [Lldb-commits] [PATCH] D96... Jan Kratochvil via Phabricator via lldb-commits

Reply via email to