diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1728,12 +1728,22 @@ if (std::shared_ptr 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); + bool found = false; + + const FileSpecList &debug_file_search_paths = + Target::GetDefaultDebugFileSearchPaths(); + size_t num_search_paths = debug_file_search_paths.GetSize(); + + if (FileSystem::Instance().Exists(dwo_file)) { + // It's relative, e.g. "foo.dwo", but we just to happen to be right next to + // it. Or it's absolute. + found = true; + } else { + // It must 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) { unit.SetDwoError(Status::createWithFormat( "unable to locate relative .dwo debug file \"{0}\" for " @@ -1744,18 +1754,91 @@ } dwo_file.SetFile(comp_dir, FileSpec::Style::native); - if (dwo_file.IsRelative()) { + 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. - dwo_file.PrependPathComponent( + 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; + } + } + } + } + + 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 spec_to_get_name(dwo_name); + llvm::StringRef filename_only = spec_to_get_name.GetFilename(); + + FileSpec next_to_binary( + m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef()); + FileSystem::Instance().Resolve(next_to_binary); + + FileSpec dwo_name_next_to_binary(next_to_binary); + dwo_name_next_to_binary.AppendPathComponent(dwo_name); + dwo_paths.Append(dwo_name_next_to_binary); + + FileSpec filename_next_to_binary(next_to_binary); + filename_next_to_binary.AppendPathComponent(filename_only); + dwo_paths.Append(filename_next_to_binary); + + 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-paths-dwoname-absolute-compdir.c b/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-dwoname-absolute-compdir.c new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-dwoname-absolute-compdir.c @@ -0,0 +1,34 @@ +/// 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 /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 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-filename-only-absolute-compdir.c @@ -0,0 +1,33 @@ +/// 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 /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 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-filename-only-relative-compdir.c @@ -0,0 +1,28 @@ +/// 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 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/dwo-debug-file-search-paths-relative-compdir.c @@ -0,0 +1,28 @@ +/// 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.c:27" -o "run" -o "frame variable" --batch 2>&1 | FileCheck %s + +// CHECK-NOT: warning: {{.*}}main unable to locate separate debug file (dwo, dwp). Debugging will be degraded. +// CHECK: (int) num = 5 + +int main(void) { + int num = 5; + return 0; +} \ No newline at end of file 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 --- /dev/null +++ b/lldb/test/Shell/SymbolFile/DWARF/dwo-relative-filename-only-binary-dir.c @@ -0,0 +1,23 @@ +/// 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