[Lldb-commits] [lldb] a723694 - [lldb] Add more ways to find split DWARF files

David Spickett via lldb-commits lldb-commits at lists.llvm.org
Thu Sep 7 01:19:17 PDT 2023


Author: David Spickett
Date: 2023-09-07T08:19:11Z
New Revision: a723694321b993f6f53fedf50e70e9cf5a206357

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

LOG: [lldb] Add more ways to find split DWARF files

Fixes #28667

There's a bunch of ways to end up building split DWARF where the
DWO file is not next to the program file. On top of that you may
distribute the program in various ways, move files about, switch
machines, flatten the directories, etc.

This change adds a few more strategies to find DWO files:
* Appending the DW_AT_COMP_DIR and DWO name to all the debug
  search paths.
* Appending the same to the binary's dir.
* Appending the DWO name (e.g. a/b/foo.dwo) to all the debug
  search paths.
* Appending the DWO name to the binary's location.
* Appending the DWO filename (e.g. foo.dwo) to the debug
  search paths.
* Appending the DWO filename to the binary's location.

They are applied in that order and some will be skipped
if the DW_AT_COMP_DIR is relative or absolute, same for
the DWO name (though that seems to always be relative).

This uses the setting target.debug-file-search-paths, which
is used for DWP files already.

The added tests likely do not cover every part of the
strategies listed, it's a best effort.

Reviewed By: clayborg

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

Added: 
    lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-path-symlink-relative-compdir.c
    lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-dwoname-absolute-compdir.c
    lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-filename-only-absolute-compdir.c
    lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-filename-only-relative-compdir.c
    lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-relative-compdir.c
    lldb/test/Shell/SymbolFile/DWARF/dwo-relative-filename-only-binary-dir.c

Modified: 
    lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 0ef4b6e72fa076..04c729e333a985 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1728,34 +1728,120 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
   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()) {
-    comp_dir = cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_comp_dir,
-                                                nullptr);
-    if (!comp_dir) {
-      unit.SetDwoError(Status::createWithFormat(
-          "unable to locate relative .dwo debug file \"{0}\" for "
-          "skeleton DIE {1:x16} without valid DW_AT_comp_dir "
-          "attribute",
-          dwo_name, cu_die.GetOffset()));
-      return nullptr;
+  bool found = false;
+
+  const FileSpecList &debug_file_search_paths =
+      Target::GetDefaultDebugFileSearchPaths();
+  size_t num_search_paths = debug_file_search_paths.GetSize();
+
+  // It's relative, e.g. "foo.dwo", but we just to happen to be right next to
+  // it. Or it's absolute.
+  found = FileSystem::Instance().Exists(dwo_file);
+
+  if (!found) {
+    // It could be a relative path that also uses DW_AT_COMP_DIR.
+    const char *comp_dir =
+        cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_comp_dir, nullptr);
+
+    if (comp_dir) {
+      dwo_file.SetFile(comp_dir, FileSpec::Style::native);
+      if (!dwo_file.IsRelative()) {
+        FileSystem::Instance().Resolve(dwo_file);
+        dwo_file.AppendPathComponent(dwo_name);
+        found = FileSystem::Instance().Exists(dwo_file);
+      } else {
+        FileSpecList dwo_paths;
+
+        // if DW_AT_comp_dir is relative, it should be relative to the location
+        // of the executable, not to the location from which the debugger was
+        // launched.
+        FileSpec relative_to_binary = dwo_file;
+        relative_to_binary.PrependPathComponent(
+            m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef());
+        FileSystem::Instance().Resolve(relative_to_binary);
+        relative_to_binary.AppendPathComponent(dwo_name);
+        dwo_paths.Append(relative_to_binary);
+
+        // Or it's relative to one of the user specified debug directories.
+        for (size_t idx = 0; idx < num_search_paths; ++idx) {
+          FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx);
+          dirspec.AppendPathComponent(comp_dir);
+          FileSystem::Instance().Resolve(dirspec);
+          if (!FileSystem::Instance().IsDirectory(dirspec))
+            continue;
+
+          dirspec.AppendPathComponent(dwo_name);
+          dwo_paths.Append(dirspec);
+        }
+
+        size_t num_possible = dwo_paths.GetSize();
+        for (size_t idx = 0; idx < num_possible && !found; ++idx) {
+          FileSpec dwo_spec = dwo_paths.GetFileSpecAtIndex(idx);
+          if (FileSystem::Instance().Exists(dwo_spec)) {
+            dwo_file = dwo_spec;
+            found = true;
+          }
+        }
+      }
+    } else {
+      Log *log = GetLog(LLDBLog::Symbols);
+      LLDB_LOGF(log,
+                "unable to locate relative .dwo debug file \"%s\" for "
+                "skeleton DIE 0x%016" PRIx64 " without valid DW_AT_comp_dir "
+                "attribute",
+                dwo_name, cu_die.GetOffset());
     }
+  }
 
-    dwo_file.SetFile(comp_dir, FileSpec::Style::native);
-    if (dwo_file.IsRelative()) {
-      // if DW_AT_comp_dir is relative, it should be relative to the location
-      // of the executable, not to the location from which the debugger was
-      // launched.
-      dwo_file.PrependPathComponent(
-          m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef());
+  if (!found) {
+    // Try adding the DW_AT_dwo_name ( e.g. "c/d/main-main.dwo"), and just the
+    // filename ("main-main.dwo") to binary dir and search paths.
+    FileSpecList dwo_paths;
+    FileSpec dwo_name_spec(dwo_name);
+    llvm::StringRef filename_only = dwo_name_spec.GetFilename();
+
+    FileSpec binary_directory(
+        m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef());
+    FileSystem::Instance().Resolve(binary_directory);
+
+    if (dwo_name_spec.IsRelative()) {
+      FileSpec dwo_name_binary_directory(binary_directory);
+      dwo_name_binary_directory.AppendPathComponent(dwo_name);
+      dwo_paths.Append(dwo_name_binary_directory);
+    }
+
+    FileSpec filename_binary_directory(binary_directory);
+    filename_binary_directory.AppendPathComponent(filename_only);
+    dwo_paths.Append(filename_binary_directory);
+
+    for (size_t idx = 0; idx < num_search_paths; ++idx) {
+      FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx);
+      FileSystem::Instance().Resolve(dirspec);
+      if (!FileSystem::Instance().IsDirectory(dirspec))
+        continue;
+
+      FileSpec dwo_name_dirspec(dirspec);
+      dwo_name_dirspec.AppendPathComponent(dwo_name);
+      dwo_paths.Append(dwo_name_dirspec);
+
+      FileSpec filename_dirspec(dirspec);
+      filename_dirspec.AppendPathComponent(filename_only);
+      dwo_paths.Append(filename_dirspec);
+    }
+
+    size_t num_possible = dwo_paths.GetSize();
+    for (size_t idx = 0; idx < num_possible && !found; ++idx) {
+      FileSpec dwo_spec = dwo_paths.GetFileSpecAtIndex(idx);
+      if (FileSystem::Instance().Exists(dwo_spec)) {
+        dwo_file = dwo_spec;
+        found = true;
+      }
     }
-    FileSystem::Instance().Resolve(dwo_file);
-    dwo_file.AppendPathComponent(dwo_name);
   }
 
-  if (!FileSystem::Instance().Exists(dwo_file)) {
+  if (!found) {
     unit.SetDwoError(Status::createWithFormat(
         "unable to locate .dwo debug file \"{0}\" for skeleton DIE "
         "{1:x16}",

diff  --git a/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-path-symlink-relative-compdir.c b/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-path-symlink-relative-compdir.c
new file mode 100644
index 00000000000000..e5d7c1f65fc4d4
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-path-symlink-relative-compdir.c
@@ -0,0 +1,30 @@
+/// Check that LLDB uses the paths in target.debug-file-search-paths to find
+/// split DWARF files with a relative DW_AT_comp_dir set, when the program file
+/// has been moved and/or we're executing it from another directory. Even when
+/// the provided search path is actually a symlink to the real location.
+// UNSUPPORTED: system-windows
+// RUN: rm -rf %t.compdir/ %t.e/
+// RUN: mkdir -p %t.compdir/a/b/c/d/
+// RUN: cp %s %t.compdir/a/b/c/d/main.c
+// RUN: cd %t.compdir/a/b/
+/// The produced DWO is named c/d/main-main.dwo, with a DW_AT_comp_dir of a/b.
+// RUN: %clang_host -g -gsplit-dwarf -fdebug-prefix-map=%t.compdir=. c/d/main.c -o c/d/main
+// RUN: cd ../../..
+/// Move only the program, leaving the DWO file in place.
+// RUN: mv %t.compdir/a/b/c/d/main %t.compdir/a/
+/// Create a symlink to the compliation dir, to use instead of the real path.
+// RUN: ln -s %t.compdir %t.symlink_to_compdir
+/// Debug it from yet another path.
+// RUN: mkdir -p %t.e/
+// RUN: cd %t.e
+/// DWO should be found by following using symlink + a/b/ + c/d/main-main.dwo.
+// RUN: %lldb --no-lldbinit %t.compdir/a/main \
+// RUN:   -O "settings append target.debug-file-search-paths %t.symlink_to_compdir" \
+// RUN:   -o "b main" -o "run" -o "p num" --batch 2>&1 | FileCheck %s
+
+// CHECK-NOT: warning: {{.*}}main unable to locate separate debug file (dwo, dwp). Debugging will be degraded.
+// CHECK: (int) 5
+
+int num = 5;
+
+int main(void) { return 0; }

diff  --git a/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-dwoname-absolute-compdir.c b/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-dwoname-absolute-compdir.c
new file mode 100644
index 00000000000000..01a8cdf461909e
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-dwoname-absolute-compdir.c
@@ -0,0 +1,32 @@
+/// Check that LLDB uses the paths in target.debug-file-search-paths to find
+/// split DWARF files with DW_AT_comp_dir set to some absolute path, when
+/// the program file and DWO have been moved and/or we're executing from
+/// another directory. Specifically when the DWO has been moved to another
+/// directory but is still at it's name. Here, %t.compdir/c/d/main-main.dwo.
+// RUN: rm -rf %t.compdir/ %t.e/
+// RUN: mkdir -p %t.compdir/a/b/c/d/
+// RUN: cp %s %t.compdir/a/b/c/d/main.c
+// RUN: cd %t.compdir/a/b/
+/// The produced DWO is named c/d/main-main.dwo, with a non-relative
+/// DW_AT_comp_dir of <pathtobuild>/a/b
+// RUN: %clang_host -g -gsplit-dwarf c/d/main.c -o c/d/main
+// RUN: cd ../../..
+/// Move the program.
+// RUN: mv %t.compdir/a/b/c/d/main %t.compdir/a/
+/// Move the DWO but keep it at the path in in its name.
+// RUN: mkdir -p %t.compdir/c/d/
+// RUN: mv %t.compdir/a/b/c/d/*.dwo %t.compdir/c/d/
+/// Debug it from yet another path.
+// RUN: mkdir -p %t.e/
+// RUN: cd %t.e
+/// LLDB should find in %t.compdir.
+// RUN: %lldb --no-lldbinit %t.compdir/a/main \
+// RUN:   -O "settings append target.debug-file-search-paths %t.compdir" \
+// RUN:   -o "b main" -o "run" -o "p num" --batch 2>&1 | FileCheck %s
+
+// CHECK-NOT: warning: {{.*}}main unable to locate separate debug file (dwo, dwp). Debugging will be degraded.
+// CHECK: (int) 5
+
+int num = 5;
+
+int main(void) { return 0; }
\ No newline at end of file

diff  --git a/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-filename-only-absolute-compdir.c b/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-filename-only-absolute-compdir.c
new file mode 100644
index 00000000000000..f47889cd443d7b
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-filename-only-absolute-compdir.c
@@ -0,0 +1,31 @@
+/// Check that LLDB uses the paths in target.debug-file-search-paths to find
+/// split DWARF files with DW_AT_comp_dir set to some non-relative path, when
+/// the program file and DWO have been moved and/or we're executing from another
+/// directory. Specifically when the DWO is not at it's "name", here we move
+/// it to %t.compdir/main-main.dwo and it's name is c/d/main-main.dwo.
+// RUN: rm -rf %t.compdir/ %t.e/
+// RUN: mkdir -p %t.compdir/a/b/c/d/
+// RUN: cp %s %t.compdir/a/b/c/d/main.c
+// RUN: cd %t.compdir/a/b/
+/// The produced DWO is named c/d/main-main.dwo, with a non-relative
+/// DW_AT_comp_dir of <pathtobuild>/a/b
+// RUN: %clang_host -g -gsplit-dwarf c/d/main.c -o c/d/main
+// RUN: cd ../../..
+/// Move the program.
+// RUN: mv %t.compdir/a/b/c/d/main %t.compdir/a/
+/// Move the DWO.
+// RUN: mv %t.compdir/a/b/c/d/*.dwo %t.compdir
+/// Debug it from yet another path.
+// RUN: mkdir -p %t.e/
+// RUN: cd %t.e
+/// LLDB should find in %t.compdir.
+// RUN: %lldb --no-lldbinit %t.compdir/a/main \
+// RUN:   -O "settings append target.debug-file-search-paths %t.compdir" \
+// RUN:   -o "b main" -o "run" -o "p num" --batch 2>&1 | FileCheck %s
+
+// CHECK-NOT: warning: {{.*}}main unable to locate separate debug file (dwo, dwp). Debugging will be degraded.
+// CHECK: (int) 5
+
+int num = 5;
+
+int main(void) { return 0; }
\ No newline at end of file

diff  --git a/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-filename-only-relative-compdir.c b/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-filename-only-relative-compdir.c
new file mode 100644
index 00000000000000..07befc450dc765
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-filename-only-relative-compdir.c
@@ -0,0 +1,26 @@
+/// Check that when LLDB is looking for a relative DWO it uses the debug search
+/// paths setting. If it doesn't find it by adding the whole relative path to
+/// of DWO it should try adding just the filename (e.g. main.dwo) to each debug
+/// search path.
+// RUN: rm -rf %t.compdir/
+// RUN: mkdir -p %t.compdir/a/b/
+// RUN: cp %s %t.compdir/a/b/main.c
+// RUN: cd %t.compdir/a/
+/// The produced DWO is named /b/main-main.dwo, with a DW_AT_comp_dir of a/.
+// RUN: %clang_host -g -gsplit-dwarf -fdebug-prefix-map=%t.compdir=. b/main.c -o b/main
+// RUN: cd ../..
+/// Move the DWO file away from the expected location.
+// RUN: mv %t.compdir/a/b/*.dwo %t.compdir/
+/// LLDB won't find the DWO next to the binary or by adding the relative path
+/// to any of the search paths. So it should find the DWO file at
+/// %t.compdir/main-main.dwo.
+// RUN: %lldb --no-lldbinit %t.compdir/a/b/main \
+// RUN:   -O "settings append target.debug-file-search-paths %t.compdir" \
+// RUN:   -o "b main" -o "run" -o "p num" --batch 2>&1 | FileCheck %s
+
+// CHECK-NOT: warning: {{.*}}main unable to locate separate debug file (dwo, dwp). Debugging will be degraded.
+// CHECK: (int) 5
+
+int num = 5;
+
+int main(void) { return 0; }
\ No newline at end of file

diff  --git a/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-relative-compdir.c b/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-relative-compdir.c
new file mode 100644
index 00000000000000..af75877cfb318f
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-relative-compdir.c
@@ -0,0 +1,27 @@
+/// Check that LLDB uses the paths in target.debug-file-search-paths to find
+/// split DWARF files with a relative DW_AT_comp_dir set, when the program file
+/// has been moved and/or we're executing it from another directory.
+// RUN: rm -rf %t.compdir/ %t.e/
+// RUN: mkdir -p %t.compdir/a/b/c/d/
+// RUN: cp %s %t.compdir/a/b/c/d/main.c
+// RUN: cd %t.compdir/a/b/
+/// The produced DWO is named c/d/main-main.dwo, with a DW_AT_comp_dir of a/b.
+// RUN: %clang_host -g -gsplit-dwarf -fdebug-prefix-map=%t.compdir=. c/d/main.c -o c/d/main
+// RUN: cd ../../..
+/// Move only the program, leaving the DWO file in place.
+// RUN: mv %t.compdir/a/b/c/d/main %t.compdir/a/
+/// Debug it from yet another path.
+// RUN: mkdir -p %t.e/
+// RUN: cd %t.e
+/// LLDB won't find the DWO next to the binary or in the current dir, so it
+/// should find the DWO file by doing %t.compdir/ + a/b/ + c/d/main-main.dwo.
+// RUN: %lldb --no-lldbinit %t.compdir/a/main \
+// RUN:   -O "settings append target.debug-file-search-paths %t.compdir" \
+// RUN:   -o "b main" -o "run" -o "p num" --batch 2>&1 | FileCheck %s
+
+// CHECK-NOT: warning: {{.*}}main unable to locate separate debug file (dwo, dwp). Debugging will be degraded.
+// CHECK: (int) 5
+
+int num = 5;
+
+int main(void) { return 0; }

diff  --git a/lldb/test/Shell/SymbolFile/DWARF/dwo-relative-filename-only-binary-dir.c b/lldb/test/Shell/SymbolFile/DWARF/dwo-relative-filename-only-binary-dir.c
new file mode 100644
index 00000000000000..a08b5a6733c9d0
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/DWARF/dwo-relative-filename-only-binary-dir.c
@@ -0,0 +1,21 @@
+/// Check that LLDB can find a relative DWO file next to a binary just using the
+/// filename of that DWO. For example "main.dwo" not "a/b/main.dwo".
+// RUN: rm -rf %t.compdir/
+// RUN: mkdir -p %t.compdir/a/b/
+// RUN: cp %s %t.compdir/a/b/main.c
+// RUN: cd %t.compdir/a/
+/// The produced DWO is named b/main-main.dwo, with a DW_AT_comp_dir of a/.
+// RUN: %clang_host -g -gsplit-dwarf -fdebug-prefix-map=%t.compdir=. b/main.c -o b/main
+// RUN: cd ../..
+/// Move binary and DWO out of expected locations.
+// RUN: mv %t.compdir/a/b/main %t.compdir/
+// RUN: mv %t.compdir/a/b/*.dwo %t.compdir/
+// RUN: %lldb --no-lldbinit %t.compdir/main \
+// RUN:   -o "b main" -o "run" -o "p num" --batch 2>&1 | FileCheck %s
+
+// CHECK-NOT: warning: {{.*}}main unable to locate separate debug file (dwo, dwp). Debugging will be degraded.
+// CHECK: (int) 5
+
+int num = 5;
+
+int main(void) { return 0; }
\ No newline at end of file


        


More information about the lldb-commits mailing list