This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGccb47b41e493: Track .dwo/.dwp loading errors and notify user 
when viewing variables. (authored by clayborg).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134252

Files:
  lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  lldb/test/API/commands/frame/var/TestFrameVar.py

Index: lldb/test/API/commands/frame/var/TestFrameVar.py
===================================================================
--- lldb/test/API/commands/frame/var/TestFrameVar.py
+++ lldb/test/API/commands/frame/var/TestFrameVar.py
@@ -9,6 +9,7 @@
 from lldbsuite.test.decorators import *
 from lldbsuite.test.lldbtest import *
 import os
+import shutil
 import time
 
 class TestFrameVar(TestBase):
@@ -182,3 +183,59 @@
             'no variable information is available in debug info for this compile unit'
         ]
         self.check_frame_variable_errors(thread, error_strings)
+
+    @skipUnlessPlatform(["linux", "freebsd"])
+    @add_test_categories(["dwo"])
+    def test_fission_missing_dwo(self):
+        '''
+            Test that if we build a binary with "-gsplit-dwarf" that we can
+            set a file and line breakpoint successfully, and get an error
+            letting us know we were unable to load the .dwo file.
+        '''
+        self.build(dictionary={'CFLAGS_EXTRAS': '-gsplit-dwarf'})
+        exe = self.getBuildArtifact("a.out")
+        main_dwo = self.getBuildArtifact("main.dwo")
+
+        self.assertTrue(os.path.exists(main_dwo), 'Make sure "%s" file exists' % (main_dwo))
+        # Delete the main.dwo file that contains the debug info so we force an
+        # error when we run to main and try to get variables.
+        os.unlink(main_dwo)
+
+        # We have to set a named breakpoint because we don't have any debug info
+        # because we deleted the main.o file since the mod times don't match
+        # and debug info won't be loaded
+        (target, process, thread, bkpt) = lldbutil.run_to_name_breakpoint(self, 'main')
+        error_strings = [
+            'unable to locate .dwo debug file "',
+            'main.dwo" for skeleton DIE 0x'
+        ]
+        self.check_frame_variable_errors(thread, error_strings)
+
+    @skipUnlessPlatform(["linux", "freebsd"])
+    @add_test_categories(["dwo"])
+    def test_fission_invalid_dwo_objectfile(self):
+        '''
+            Test that if we build a binary with "-gsplit-dwarf" that we can
+            set a file and line breakpoint successfully, and get an error
+            letting us know we were unable to load the .dwo file because it
+            existed, but it wasn't a valid object file.
+        '''
+        self.build(dictionary={'CFLAGS_EXTRAS': '-gsplit-dwarf'})
+        exe = self.getBuildArtifact("a.out")
+        main_dwo = self.getBuildArtifact("main.dwo")
+
+        self.assertTrue(os.path.exists(main_dwo), 'Make sure "%s" file exists' % (main_dwo))
+        # Overwrite the main.dwo with the main.c source file so that the .dwo
+        # file exists, but it isn't a valid object file as there is an error
+        # for this case.
+        shutil.copyfile(self.getSourcePath('main.c'), main_dwo)
+
+        # We have to set a named breakpoint because we don't have any debug info
+        # because we deleted the main.o file since the mod times don't match
+        # and debug info won't be loaded
+        (target, process, thread, bkpt) = lldbutil.run_to_name_breakpoint(self, 'main')
+        error_strings = [
+            'unable to load object file for .dwo debug file "'
+            'main.dwo" for unit DIE 0x',
+        ]
+        self.check_frame_variable_errors(thread, error_strings)
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1732,24 +1732,34 @@
     return nullptr;
 
   DWARFCompileUnit *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(&unit);
-  // Only compile units can be split into two parts.
-  if (!dwarf_cu)
+  // Only compile units can be split into two parts and we should only
+  // look for a DWO file if there is a valid DWO ID.
+  if (!dwarf_cu || !dwarf_cu->GetDWOId().has_value())
     return nullptr;
 
   const char *dwo_name = GetDWOName(*dwarf_cu, cu_die);
-  if (!dwo_name)
+  if (!dwo_name) {
+    unit.SetDwoError(Status("missing DWO name in skeleton DIE 0x%8.8" PRIx32,
+                            cu_die.GetOffset()));
     return nullptr;
+  }
 
   if (std::shared_ptr<SymbolFileDWARFDwo> dwp_sp = GetDwpSymbolFile())
     return dwp_sp;
 
+  const char *comp_dir = nullptr;
   FileSpec dwo_file(dwo_name);
   FileSystem::Instance().Resolve(dwo_file);
   if (dwo_file.IsRelative()) {
-    const char *comp_dir =
-        cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_comp_dir, nullptr);
-    if (!comp_dir)
+    comp_dir = cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_comp_dir,
+                                                nullptr);
+    if (!comp_dir) {
+      unit.SetDwoError(
+          Status("unable to locate relative .dwo debug file \"%s\" for "
+                 "skeleton DIE 0x%8.8" PRIx32 " without valid DW_AT_comp_dir "
+                 "attribute", dwo_name, cu_die.GetOffset()));
       return nullptr;
+    }
 
     dwo_file.SetFile(comp_dir, FileSpec::Style::native);
     if (dwo_file.IsRelative()) {
@@ -1764,6 +1774,11 @@
   }
 
   if (!FileSystem::Instance().Exists(dwo_file)) {
+    unit.SetDwoError(
+        Status("unable to locate .dwo debug file \"%s\" for skeleton DIE "
+               "0x%8.8" PRIx32, dwo_file.GetPath().c_str(),
+               cu_die.GetOffset()));
+
     if (m_dwo_warning_issued.test_and_set(std::memory_order_relaxed) == false) {
       GetObjectFile()->GetModule()->ReportWarning(
           "unable to locate separate debug file (dwo, dwp). Debugging will be "
@@ -1779,8 +1794,12 @@
       GetObjectFile()->GetModule(), &dwo_file, file_offset,
       FileSystem::Instance().GetByteSize(dwo_file), dwo_file_data_sp,
       dwo_file_data_offset);
-  if (dwo_obj_file == nullptr)
+  if (dwo_obj_file == nullptr) {
+    unit.SetDwoError(
+          Status("unable to load object file for .dwo debug file \"%s\" for "
+                 "unit DIE 0x%8.8" PRIx32, dwo_name, cu_die.GetOffset()));
     return nullptr;
+  }
 
   return std::make_shared<SymbolFileDWARFDwo>(*this, dwo_obj_file,
                                               dwarf_cu->GetID());
@@ -4132,6 +4151,14 @@
   if (!dwarf_cu)
     return Status();
 
+  // Check if we have a skeleton compile unit that had issues trying to load
+  // its .dwo/.dwp file. First pares the Unit DIE to make sure we see any .dwo
+  // related errors.
+  dwarf_cu->ExtractUnitDIEIfNeeded();
+  const Status &dwo_error = dwarf_cu->GetDwoError();
+  if (dwo_error.Fail())
+    return dwo_error;
+
   // Don't return an error for assembly files as they typically don't have
   // varaible information.
   if (dwarf_cu->GetDWARFLanguageType() == DW_LANG_Mips_Assembler)
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -266,6 +266,25 @@
   ///   True if any DIEs match any tag in \a tags, false otherwise.
   bool HasAny(llvm::ArrayRef<dw_tag_t> tags);
 
+
+  /// Get the fission .dwo file specific error for this compile unit.
+  ///
+  /// The skeleton compile unit only can have a DWO error. Any other type
+  /// of DWARFUnit will not have a valid DWO error.
+  ///
+  /// \returns
+  ///   A valid DWO error if there is a problem with anything in the
+  ///   locating or parsing inforamtion in the .dwo file
+  const lldb_private::Status &GetDwoError() const { return m_dwo_error; }
+
+  /// Set the fission .dwo file specific error for this compile unit.
+  ///
+  /// This helps tracks issues that arise when trying to locate or parse a
+  /// .dwo file. Things like a missing .dwo file, DWO ID mismatch, and other
+  /// .dwo errors can be stored in each compile unit so the issues can be
+  /// communicated to the user.
+  void SetDwoError(const lldb_private::Status &error) { m_dwo_error = error; }
+
 protected:
   DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid,
             const DWARFUnitHeader &header,
@@ -346,6 +365,10 @@
   bool m_has_parsed_non_skeleton_unit;
   /// Value of DW_AT_GNU_dwo_id (v4) or dwo_id from CU header (v5).
   llvm::Optional<uint64_t> m_dwo_id;
+  /// If we get an error when trying to load a .dwo file, save that error here.
+  /// Errors include .dwo/.dwp file not found, or the .dwp/.dwp file was found
+  /// but DWO ID doesn't match, etc.
+  lldb_private::Status m_dwo_error;
 
 private:
   void ParseProducerInfo();
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -76,6 +76,7 @@
     return;
 
   m_has_parsed_non_skeleton_unit = true;
+  m_dwo_error.Clear();
 
   if (!m_dwo_id)
     return; // No DWO file.
@@ -87,13 +88,24 @@
 
   DWARFUnit *dwo_cu = dwo_symbol_file->GetDWOCompileUnitForHash(*m_dwo_id);
 
-  if (!dwo_cu)
+  if (!dwo_cu) {
+    SetDwoError(
+        Status("unable to load .dwo file from \"%s\" due to ID (0x%16.16" PRIx64
+               ") mismatch for skeleton DIE at 0x%8.8" PRIx32,
+               dwo_symbol_file->GetObjectFile()->GetFileSpec().GetPath().c_str(),
+               *m_dwo_id, m_first_die.GetOffset()));
     return; // Can't fetch the compile unit from the dwo file.
+  }
   dwo_cu->SetUserData(this);
 
   DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly();
-  if (!dwo_cu_die.IsValid())
-    return; // Can't fetch the compile unit DIE from the dwo file.
+  if (!dwo_cu_die.IsValid()) {
+    // Can't fetch the compile unit DIE from the dwo file.
+    SetDwoError(
+        Status("unable to extract compile unit DIE from .dwo file for skeleton "
+               "DIE at 0x%8.8" PRIx32, m_first_die.GetOffset()));
+    return;
+  }
 
   // Here for DWO CU we want to use the address base set in the skeleton unit
   // (DW_AT_addr_base) if it is available and use the DW_AT_GNU_addr_base
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to