[Lldb-commits] [lldb] 5a45d32 - [lldb] Add more ways to find the .dwp file. (#81067)

via lldb-commits lldb-commits at lists.llvm.org
Tue Feb 20 18:17:05 PST 2024


Author: Greg Clayton
Date: 2024-02-20T18:17:01-08:00
New Revision: 5a45d32b5b42dc4ed4852b0045391a1c2be41b48

URL: https://github.com/llvm/llvm-project/commit/5a45d32b5b42dc4ed4852b0045391a1c2be41b48
DIFF: https://github.com/llvm/llvm-project/commit/5a45d32b5b42dc4ed4852b0045391a1c2be41b48.diff

LOG: [lldb] Add more ways to find the .dwp file. (#81067)

When using split DWARF we can run into many different ways to store
debug info:
- lldb loads `<exe>` which contains skeleton DWARF and needs to find
`<exe>.dwp`
- lldb loads `<exe>` which is stripped but has .gnu_debuglink pointing
to `<exe>.debug` with skeleton DWARF and needs to find `<exe>.dwp`
- lldb loads `<exe>` which is stripped but has .gnu_debuglink pointing
to `<exe>.debug` with skeleton DWARF and needs to find `<exe>.debug.dwp`
- lldb loads `<exe>.debug` and needs to find `<exe>.dwp`

Previously we only handled the first two cases. This patch adds support
for the latter two.

Added: 
    

Modified: 
    lldb/include/lldb/Utility/FileSpecList.h
    lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
    lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
    lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
    lldb/test/Shell/SymbolFile/DWARF/x86/dwp-separate-debug-file.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Utility/FileSpecList.h b/lldb/include/lldb/Utility/FileSpecList.h
index 49edc667ddd5b6..6eb3bb9971f13a 100644
--- a/lldb/include/lldb/Utility/FileSpecList.h
+++ b/lldb/include/lldb/Utility/FileSpecList.h
@@ -238,6 +238,10 @@ class FileSpecList {
   const_iterator begin() const { return m_files.begin(); }
   const_iterator end() const { return m_files.end(); }
 
+  llvm::iterator_range<const_iterator> files() const {
+    return llvm::make_range(begin(), end());
+  }
+
 protected:
   collection m_files; ///< A collection of FileSpec objects.
 };

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
index 6b063f3bd88d85..795355b57a06db 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
@@ -22,6 +22,7 @@ static constexpr Log::Category g_categories[] = {
     {{"map"},
      {"log insertions of object files into DWARF debug maps"},
      DWARFLog::DebugMap},
+    {{"split"}, {"log split DWARF related activities"}, DWARFLog::SplitDwarf},
 };
 
 static Log::Channel g_channel(g_categories, DWARFLog::DebugInfo);

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
index 662aa6757e2ffc..7f254a1162bd10 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
@@ -20,6 +20,7 @@ enum class DWARFLog : Log::MaskType {
   DebugMap = Log::ChannelFlag<2>,
   Lookups = Log::ChannelFlag<3>,
   TypeCompletion = Log::ChannelFlag<4>,
+  SplitDwarf = Log::ChannelFlag<5>,
   LLVM_MARK_AS_BITMASK_ENUM(TypeCompletion)
 };
 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 42211b9a21b0e3..84ff4c2565a050 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -4349,26 +4349,60 @@ SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
 
 const std::shared_ptr<SymbolFileDWARFDwo> &SymbolFileDWARF::GetDwpSymbolFile() {
   llvm::call_once(m_dwp_symfile_once_flag, [this]() {
+    // Create a list of files to try and append .dwp to.
+    FileSpecList symfiles;
+    // Append the module's object file path.
+    const FileSpec module_fspec = m_objfile_sp->GetModule()->GetFileSpec();
+    symfiles.Append(module_fspec);
+    // Append the object file for this SymbolFile only if it is 
diff erent from
+    // the module's file path. Our main module could be "a.out", our symbol file
+    // could be "a.debug" and our ".dwp" file might be "a.debug.dwp" instead of
+    // "a.out.dwp".
+    const FileSpec symfile_fspec(m_objfile_sp->GetFileSpec());
+    if (symfile_fspec != module_fspec) {
+      symfiles.Append(symfile_fspec);
+    } else {
+      // If we don't have a separate debug info file, then try stripping the
+      // extension. The main module could be "a.debug" and the .dwp file could
+      // be "a.dwp" instead of "a.debug.dwp".
+      ConstString filename_no_ext =
+          module_fspec.GetFileNameStrippingExtension();
+      if (filename_no_ext != module_fspec.GetFilename()) {
+        FileSpec module_spec_no_ext(module_fspec);
+        module_spec_no_ext.SetFilename(filename_no_ext);
+        symfiles.Append(module_spec_no_ext);
+      }
+    }
+    Log *log = GetLog(DWARFLog::SplitDwarf);
+    FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
     ModuleSpec module_spec;
     module_spec.GetFileSpec() = m_objfile_sp->GetFileSpec();
-    module_spec.GetSymbolFileSpec() =
-        FileSpec(m_objfile_sp->GetModule()->GetFileSpec().GetPath() + ".dwp");
-
     module_spec.GetUUID() = m_objfile_sp->GetUUID();
-    FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
-    FileSpec dwp_filespec =
-        PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
-    if (FileSystem::Instance().Exists(dwp_filespec)) {
-      DataBufferSP dwp_file_data_sp;
-      lldb::offset_t dwp_file_data_offset = 0;
-      ObjectFileSP dwp_obj_file = ObjectFile::FindPlugin(
-          GetObjectFile()->GetModule(), &dwp_filespec, 0,
-          FileSystem::Instance().GetByteSize(dwp_filespec), dwp_file_data_sp,
-          dwp_file_data_offset);
-      if (!dwp_obj_file)
-        return;
-      m_dwp_symfile = std::make_shared<SymbolFileDWARFDwo>(
-          *this, dwp_obj_file, DIERef::k_file_index_mask);
+    for (const auto &symfile : symfiles.files()) {
+      module_spec.GetSymbolFileSpec() =
+          FileSpec(symfile.GetPath() + ".dwp", symfile.GetPathStyle());
+      LLDB_LOG(log, "Searching for DWP using: \"{0}\"",
+               module_spec.GetSymbolFileSpec());
+      FileSpec dwp_filespec =
+          PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
+      if (FileSystem::Instance().Exists(dwp_filespec)) {
+        LLDB_LOG(log, "Found DWP file: \"{0}\"", dwp_filespec);
+        DataBufferSP dwp_file_data_sp;
+        lldb::offset_t dwp_file_data_offset = 0;
+        ObjectFileSP dwp_obj_file = ObjectFile::FindPlugin(
+            GetObjectFile()->GetModule(), &dwp_filespec, 0,
+            FileSystem::Instance().GetByteSize(dwp_filespec), dwp_file_data_sp,
+            dwp_file_data_offset);
+        if (dwp_obj_file) {
+          m_dwp_symfile = std::make_shared<SymbolFileDWARFDwo>(
+              *this, dwp_obj_file, DIERef::k_file_index_mask);
+          break;
+        }
+      }
+    }
+    if (!m_dwp_symfile) {
+      LLDB_LOG(log, "Unable to locate for DWP file for: \"{0}\"",
+               m_objfile_sp->GetModule()->GetFileSpec());
     }
   });
   return m_dwp_symfile;

diff  --git a/lldb/test/Shell/SymbolFile/DWARF/x86/dwp-separate-debug-file.cpp b/lldb/test/Shell/SymbolFile/DWARF/x86/dwp-separate-debug-file.cpp
index a47209931c3840..9a8149065b6e58 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/x86/dwp-separate-debug-file.cpp
+++ b/lldb/test/Shell/SymbolFile/DWARF/x86/dwp-separate-debug-file.cpp
@@ -1,12 +1,16 @@
 // REQUIRES: lld
 
+// Now test with DWARF5
 // RUN: %clang -target x86_64-pc-linux -gsplit-dwarf -gdwarf-5 -c %s -o %t.dwarf5.o
 // RUN: ld.lld %t.dwarf5.o -o %t.dwarf5
 // RUN: llvm-dwp %t.dwarf5.dwo -o %t.dwarf5.dwp
 // RUN: rm %t.dwarf5.dwo
 // RUN: llvm-objcopy --only-keep-debug %t.dwarf5 %t.dwarf5.debug
 // RUN: llvm-objcopy --strip-all --add-gnu-debuglink=%t.dwarf5.debug %t.dwarf5
-// RUN: %lldb %t.dwarf5 -o "target variable a" -b | FileCheck %s
+// RUN: %lldb \
+// RUN:   -O "log enable dwarf split" \
+// RUN:   -o "target variable a" \
+// RUN:   -b %t.dwarf5 | FileCheck %s
 
 // Run one time with the index cache enabled to populate the index cache. When
 // we populate the index cache we have to parse all of the DWARF debug info
@@ -34,6 +38,31 @@
 // RUN:   -o "statistics dump" \
 // RUN:   %t.dwarf5 -b | FileCheck %s -check-prefix=CACHED
 
+// Make sure that if we load the "%t.dwarf5.debug" file, that we can find and
+// load the .dwo file from the .dwp when it is "%t.dwarf5.dwp"
+// RUN: %lldb %t.dwarf5.debug -o "b main" -b | FileCheck %s -check-prefix=DEBUG
+
+// Make sure that if we load the "%t.dwarf5" file, that we can find and
+// load the .dwo file from the .dwp when it is "%t.dwarf5.debug.dwp"
+// RUN: mv %t.dwarf5.dwp %t.dwarf5.debug.dwp
+// RUN: %lldb %t.dwarf5 -o "b main" -b | FileCheck %s -check-prefix=DEBUG
+
+// Make sure that if we load the "%t.dwarf5.debug" file, that we can find and
+// load the .dwo file from the .dwp when it is "%t.dwarf5.debug.dwp"
+// RUN: %lldb %t.dwarf5.debug -o "b main" -b | FileCheck %s -check-prefix=DEBUG
+
+// Make sure that if we remove the .dwp file we see an appropriate error.
+// RUN: rm %t.dwarf5.debug.dwp
+// RUN: %lldb \
+// RUN:   -O "log enable dwarf split" \
+// RUN:   -o "b main" \
+// RUN:   -b %t.dwarf5 2>&1 | FileCheck %s -check-prefix=NODWP
+
+// RUN: %lldb \
+// RUN:   -O "log enable dwarf split" \
+// RUN:   -o "b main" \
+// RUN:   -b %t.dwarf5.debug 2>&1 | FileCheck %s -check-prefix=NODWP
+
 // Now test with DWARF4
 // RUN: %clang -target x86_64-pc-linux -gsplit-dwarf -gdwarf-4 -c %s -o %t.dwarf4.o
 // RUN: ld.lld %t.dwarf4.o -o %t.dwarf4
@@ -41,7 +70,10 @@
 // RUN: rm %t.dwarf4.dwo
 // RUN: llvm-objcopy --only-keep-debug %t.dwarf4 %t.dwarf4.debug
 // RUN: llvm-objcopy --strip-all --add-gnu-debuglink=%t.dwarf4.debug %t.dwarf4
-// RUN: %lldb %t.dwarf4 -o "target variable a" -b | FileCheck %s
+// RUN: %lldb \
+// RUN:   -O "log enable dwarf split" \
+// RUN:   -o "target variable a" \
+// RUN:   -b %t.dwarf4 | FileCheck %s
 
 // Run one time with the index cache enabled to populate the index cache. When
 // we populate the index cache we have to parse all of the DWARF debug info
@@ -69,6 +101,46 @@
 // RUN:   -o "statistics dump" \
 // RUN:   %t.dwarf4 -b | FileCheck %s -check-prefix=CACHED
 
+// Make sure that if we load the "%t.dwarf4.debug" file, that we can find and
+// load the .dwo file from the .dwp when it is "%t.dwarf4.dwp"
+// RUN: %lldb %t.dwarf4.debug -o "b main" -b | FileCheck %s -check-prefix=DEBUG
+
+// Make sure that if we load the "%t.dwarf4" file, that we can find and
+// load the .dwo file from the .dwp when it is "%t.dwarf4.debug.dwp"
+// RUN: mv %t.dwarf4.dwp %t.dwarf4.debug.dwp
+// RUN: %lldb %t.dwarf4 -o "b main" -b | FileCheck %s -check-prefix=DEBUG
+
+// Make sure that if we load the "%t.dwarf4.debug" file, that we can find and
+// load the .dwo file from the .dwp when it is "%t.dwarf4.debug.dwp"
+// RUN: %lldb %t.dwarf4.debug -o "b main" -b | FileCheck %s -check-prefix=DEBUG
+
+// Make sure that if we remove the .dwp file we see an appropriate error.
+// RUN: rm %t.dwarf4.debug.dwp
+// RUN: %lldb \
+// RUN:   -O "log enable dwarf split" \
+// RUN:   -o "b main" \
+// RUN:   -b %t.dwarf4 2>&1 | FileCheck %s -check-prefix=NODWP
+
+// RUN: %lldb \
+// RUN:   -O "log enable dwarf split" \
+// RUN:   -o "b main" \
+// RUN:   -b %t.dwarf4.debug 2>&1 | FileCheck %s -check-prefix=NODWP
+
+// Test if we have a GNU build ID in our main executable and in our debug file,
+// and we have a .dwp file that doesn't, that we can still load our .dwp file.
+// RUN: %clang -target x86_64-pc-linux -gsplit-dwarf -gdwarf-5 -c %s -o %t.o
+// RUN: ld.lld %t.o --build-id=md5 -o %t
+// RUN: llvm-dwp %t.dwo -o %t.dwp
+// RUN: rm %t.dwo
+// RUN: llvm-objcopy --only-keep-debug %t %t.debug
+// RUN: llvm-objcopy --strip-all --add-gnu-debuglink=%t.debug %t
+// RUN: %lldb \
+// RUN:   -O "log enable dwarf split" \
+// RUN:   -o "target variable a" \
+// RUN:   -b %t | FileCheck %s
+
+// CHECK: Searching for DWP using:
+// CHECK: Found DWP file:
 // CHECK: (A) a = (x = 47)
 
 // CACHE: script lldb.target.modules[0].FindTypes('::A').GetTypeAtIndex(0)
@@ -83,6 +155,16 @@
 // CACHED-NEXT: }
 // CACHED: "totalDebugInfoIndexLoadedFromCache": 1
 
+// Make sure debug information was loaded by verifying that the
+// DEBUG: Breakpoint 1: where = dwp-separate-debug-file.cpp.tmp.dwarf{{[45]}}{{(\.debug)?}}`main + {{[0-9]+}} at dwp-separate-debug-file.cpp:{{[0-9]+}}:{{[0-9]+}}, address = {{0x[0-9a-fA-F]+}}
+
+// Make sure if we load the stripped binary or the debug info file with no .dwp
+// nor any .dwo files that we are not able to fine the .dwp or .dwo files.
+// NODWP: Searching for DWP using:
+// NODWP: Searching for DWP using:
+// NODWP: Unable to locate for DWP file for:
+// NODWP: unable to locate separate debug file (dwo, dwp). Debugging will be degraded.
+
 struct A {
   int x = 47;
 };


        


More information about the lldb-commits mailing list