jankratochvil updated this revision to Diff 330325.

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/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/DebugNamesDWARFIndex.cpp
  lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.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();
@@ -323,6 +325,9 @@
 
   static lldb::LanguageType GetLanguage(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:
@@ -492,6 +497,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
@@ -71,6 +71,7 @@
 #include "ManualDWARFIndex.h"
 #include "SymbolFileDWARFDebugMap.h"
 #include "SymbolFileDWARFDwo.h"
+#include "SymbolFileDWARFDwz.h"
 
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/Support/FileSystem.h"
@@ -437,7 +438,10 @@
       m_fetched_external_modules(false),
       m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate) {}
 
-SymbolFileDWARF::~SymbolFileDWARF() {}
+SymbolFileDWARF::~SymbolFileDWARF() {
+  if (m_dwz_symfile)
+    m_dwz_symfile->ClearForDWARF(*this);
+}
 
 static ConstString GetDWARFMachOSegmentName() {
   static ConstString g_dwarf_section_name("__DWARF");
@@ -454,6 +458,8 @@
 
 llvm::Expected<TypeSystem &>
 SymbolFileDWARF::GetTypeSystemForLanguage(LanguageType language) {
+  lldbassert(!GetIsDwz());
+
   if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile())
     return debug_map_symfile->GetTypeSystemForLanguage(language);
 
@@ -468,6 +474,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()) {
     DWARFDataExtractor apple_names, apple_namespaces, apple_types, apple_objc;
     LoadSectionData(eSectionTypeDWARFAppleNames, apple_names);
@@ -676,6 +685,7 @@
 }
 
 lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
+  lldbassert(!GetIsDwz());
   CompUnitSP cu_sp;
   CompileUnit *comp_unit = (CompileUnit *)dwarf_cu.GetUserData();
   if (comp_unit) {
@@ -908,9 +918,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);
@@ -1271,8 +1285,11 @@
                                   const DWARFBaseDIE &die) {
   if (!die.IsValid())
     return LLDB_INVALID_UID;
-  // if (die.GetCU()->GetUnitDIEOnly().Tag() != DW_TAG_partial_unit)
-  main_unit = nullptr;
+  // Try to prevent GetUnitDIEOnly() which may be expensive.
+  if (!GetIsDwz() && die.GetCU()->GetUnitDIEOnly().Tag() != DW_TAG_partial_unit)
+    main_unit = nullptr;
+  else
+    lldbassert(main_unit);
   return GetUID(main_unit, die.GetDIERef(main_unit));
 }
 
@@ -1280,6 +1297,10 @@
   if (GetDebugMapSymfile())
     return GetID() | ref.die_offset();
 
+  if (GetIsDwz()) {
+    lldbassert(main_unit);
+    return main_unit->GetSymbolFileDWARF().GetUID(main_unit, ref);
+  }
   if (main_unit)
     main_unit = &main_unit->GetNonSkeletonUnit();
   if (ref.dwo_num().hasValue())
@@ -1308,6 +1329,9 @@
   DWARFUnit *main_unit_check;
   DWARFDIE dwarfdie_check2 = GetDIE(retval, &main_unit_check);
   lldbassert(dwarfdie_check2 == dwarfdie_check);
+  lldbassert(dwarfdie_check.GetCU()->GetUnitDIEOnly().Tag() !=
+                 DW_TAG_partial_unit ||
+             main_unit_check == main_unit);
 #endif
 
   return retval;
@@ -1345,8 +1369,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
@@ -1619,7 +1650,11 @@
 
 DWARFDIE
 SymbolFileDWARF::GetDIE(const DIERef &die_ref, DWARFUnit **main_unit_return) {
-  if (die_ref.dwo_num()) {
+  if (die_ref.dwo_num() && !GetIsDwz()) {
+    if (GetDwzSymbolFile()) {
+      lldbassert(0 == *die_ref.dwo_num());
+      return GetDwzSymbolFile()->GetDIE(die_ref, main_unit_return);
+    }
     SymbolFileDWARF *dwarf = *die_ref.dwo_num() == 0x1fffffff
                                  ? m_dwp_symfile.get()
                                  : this->DebugInfo()
@@ -4028,5 +4063,7 @@
 }
 
 LanguageType SymbolFileDWARF::GetLanguage(DWARFUnit &unit) {
+  // Caller should have called GetMainDWARFUnit().
+  lldbassert(unit.GetUnitDIEOnly().Tag() != DW_TAG_partial_unit);
   return LanguageTypeFromDWARF(unit.GetDWARFLanguageType());
 }
Index: lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -120,6 +120,15 @@
         unit.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;
+
   const LanguageType cu_language = SymbolFileDWARF::GetLanguage(unit);
 
   IndexUnitImpl(unit, &unit, cu_language, set);
@@ -160,6 +169,7 @@
     case DW_TAG_union_type:
     case DW_TAG_unspecified_type:
     case DW_TAG_variable:
+    case DW_TAG_imported_unit:
       break;
 
     default:
@@ -175,7 +185,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) {
@@ -219,6 +229,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;
         }
       }
     }
@@ -321,6 +336,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;
+        }
+        DWARFDIE 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, main_unit, cu_language, 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,12 +46,14 @@
   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;
 
   cu = &cu->GetNonSkeletonUnit();
   if (llvm::Optional<uint64_t> die_offset = entry.getDIEUnitOffset())
+    // FIXME: .debug_names have no DWZ support yet.
     return DIERef(cu->GetSymbolFileDWARF().GetDwoNum(), llvm::None,
                   DIERef::MainDwz, DIERef::Section::DebugInfo,
                   cu->GetOffset() + *die_offset);
@@ -170,6 +172,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/DWARFUnit.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -651,6 +651,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
@@ -31,7 +31,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
@@ -16,6 +16,7 @@
 #include "DWARFDebugInfo.h"
 #include "DWARFFormValue.h"
 #include "DWARFUnit.h"
+#include "SymbolFileDWARFDwz.h"
 
 class DWARFUnit;
 
@@ -76,6 +77,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:
@@ -124,6 +126,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;
@@ -255,6 +262,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:
@@ -287,6 +299,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;
 
@@ -435,6 +448,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
@@ -477,6 +493,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;
 }
 
@@ -508,6 +538,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(
@@ -517,7 +548,48 @@
     }
     return const_cast<DWARFUnit *>(m_unit)->GetDIE(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(value);
+  }
+
   case DW_FORM_ref_addr: {
+    assert(m_unit);
     DWARFUnit *ref_cu =
         m_unit->GetSymbolFileDWARF().DebugInfo().GetUnitContainingDIEOffset(
             DIERef::Section::DebugInfo, value);
@@ -629,6 +701,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
@@ -115,6 +115,9 @@
           else
             form_size = 4;
           break;
+        case DW_FORM_GNU_ref_alt:
+          form_size = 4;
+          break;
 
         // 0 sized form
         case DW_FORM_flag_present:
@@ -179,6 +182,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
@@ -25,6 +25,7 @@
 #include "DWARFDebugInfoEntry.h"
 #include "DWARFFormValue.h"
 #include "DWARFTypeUnit.h"
+#include "SymbolFileDWARFDwz.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -39,6 +40,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();
@@ -151,12 +154,22 @@
 }
 
 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) {
-  // This function will be extended by a later DWZ patch.
-  DWARFUnit *main_unit = 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()));
   return main_unit;
 }
 
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -37,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;
@@ -117,6 +121,8 @@
 }
 
 DWARFUnit *DWARFCompileUnit::GetMainDWARFUnit(DWARFUnit *main_unit) {
+  if (GetUnitDIEOnly().Tag() != DW_TAG_partial_unit)
+    main_unit = this;
   main_unit = &main_unit->GetNonSkeletonUnit();
   return main_unit;
 }
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFBaseDIE.cpp
@@ -30,7 +30,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
@@ -37,6 +37,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
    • [Lldb-commits] [PATCH... Jan Kratochvil via Phabricator via lldb-commits

Reply via email to