Skip to content

Commit a723694

Browse files
committed
[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
1 parent f0cd9b2 commit a723694

7 files changed

+274
-21
lines changed

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

Lines changed: 107 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1728,34 +1728,120 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
17281728
if (std::shared_ptr<SymbolFileDWARFDwo> dwp_sp = GetDwpSymbolFile())
17291729
return dwp_sp;
17301730

1731-
const char *comp_dir = nullptr;
17321731
FileSpec dwo_file(dwo_name);
17331732
FileSystem::Instance().Resolve(dwo_file);
1734-
if (dwo_file.IsRelative()) {
1735-
comp_dir = cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_comp_dir,
1736-
nullptr);
1737-
if (!comp_dir) {
1738-
unit.SetDwoError(Status::createWithFormat(
1739-
"unable to locate relative .dwo debug file \"{0}\" for "
1740-
"skeleton DIE {1:x16} without valid DW_AT_comp_dir "
1741-
"attribute",
1742-
dwo_name, cu_die.GetOffset()));
1743-
return nullptr;
1733+
bool found = false;
1734+
1735+
const FileSpecList &debug_file_search_paths =
1736+
Target::GetDefaultDebugFileSearchPaths();
1737+
size_t num_search_paths = debug_file_search_paths.GetSize();
1738+
1739+
// It's relative, e.g. "foo.dwo", but we just to happen to be right next to
1740+
// it. Or it's absolute.
1741+
found = FileSystem::Instance().Exists(dwo_file);
1742+
1743+
if (!found) {
1744+
// It could be a relative path that also uses DW_AT_COMP_DIR.
1745+
const char *comp_dir =
1746+
cu_die.GetAttributeValueAsString(dwarf_cu, DW_AT_comp_dir, nullptr);
1747+
1748+
if (comp_dir) {
1749+
dwo_file.SetFile(comp_dir, FileSpec::Style::native);
1750+
if (!dwo_file.IsRelative()) {
1751+
FileSystem::Instance().Resolve(dwo_file);
1752+
dwo_file.AppendPathComponent(dwo_name);
1753+
found = FileSystem::Instance().Exists(dwo_file);
1754+
} else {
1755+
FileSpecList dwo_paths;
1756+
1757+
// if DW_AT_comp_dir is relative, it should be relative to the location
1758+
// of the executable, not to the location from which the debugger was
1759+
// launched.
1760+
FileSpec relative_to_binary = dwo_file;
1761+
relative_to_binary.PrependPathComponent(
1762+
m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef());
1763+
FileSystem::Instance().Resolve(relative_to_binary);
1764+
relative_to_binary.AppendPathComponent(dwo_name);
1765+
dwo_paths.Append(relative_to_binary);
1766+
1767+
// Or it's relative to one of the user specified debug directories.
1768+
for (size_t idx = 0; idx < num_search_paths; ++idx) {
1769+
FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx);
1770+
dirspec.AppendPathComponent(comp_dir);
1771+
FileSystem::Instance().Resolve(dirspec);
1772+
if (!FileSystem::Instance().IsDirectory(dirspec))
1773+
continue;
1774+
1775+
dirspec.AppendPathComponent(dwo_name);
1776+
dwo_paths.Append(dirspec);
1777+
}
1778+
1779+
size_t num_possible = dwo_paths.GetSize();
1780+
for (size_t idx = 0; idx < num_possible && !found; ++idx) {
1781+
FileSpec dwo_spec = dwo_paths.GetFileSpecAtIndex(idx);
1782+
if (FileSystem::Instance().Exists(dwo_spec)) {
1783+
dwo_file = dwo_spec;
1784+
found = true;
1785+
}
1786+
}
1787+
}
1788+
} else {
1789+
Log *log = GetLog(LLDBLog::Symbols);
1790+
LLDB_LOGF(log,
1791+
"unable to locate relative .dwo debug file \"%s\" for "
1792+
"skeleton DIE 0x%016" PRIx64 " without valid DW_AT_comp_dir "
1793+
"attribute",
1794+
dwo_name, cu_die.GetOffset());
17441795
}
1796+
}
17451797

1746-
dwo_file.SetFile(comp_dir, FileSpec::Style::native);
1747-
if (dwo_file.IsRelative()) {
1748-
// if DW_AT_comp_dir is relative, it should be relative to the location
1749-
// of the executable, not to the location from which the debugger was
1750-
// launched.
1751-
dwo_file.PrependPathComponent(
1752-
m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef());
1798+
if (!found) {
1799+
// Try adding the DW_AT_dwo_name ( e.g. "c/d/main-main.dwo"), and just the
1800+
// filename ("main-main.dwo") to binary dir and search paths.
1801+
FileSpecList dwo_paths;
1802+
FileSpec dwo_name_spec(dwo_name);
1803+
llvm::StringRef filename_only = dwo_name_spec.GetFilename();
1804+
1805+
FileSpec binary_directory(
1806+
m_objfile_sp->GetFileSpec().GetDirectory().GetStringRef());
1807+
FileSystem::Instance().Resolve(binary_directory);
1808+
1809+
if (dwo_name_spec.IsRelative()) {
1810+
FileSpec dwo_name_binary_directory(binary_directory);
1811+
dwo_name_binary_directory.AppendPathComponent(dwo_name);
1812+
dwo_paths.Append(dwo_name_binary_directory);
1813+
}
1814+
1815+
FileSpec filename_binary_directory(binary_directory);
1816+
filename_binary_directory.AppendPathComponent(filename_only);
1817+
dwo_paths.Append(filename_binary_directory);
1818+
1819+
for (size_t idx = 0; idx < num_search_paths; ++idx) {
1820+
FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx);
1821+
FileSystem::Instance().Resolve(dirspec);
1822+
if (!FileSystem::Instance().IsDirectory(dirspec))
1823+
continue;
1824+
1825+
FileSpec dwo_name_dirspec(dirspec);
1826+
dwo_name_dirspec.AppendPathComponent(dwo_name);
1827+
dwo_paths.Append(dwo_name_dirspec);
1828+
1829+
FileSpec filename_dirspec(dirspec);
1830+
filename_dirspec.AppendPathComponent(filename_only);
1831+
dwo_paths.Append(filename_dirspec);
1832+
}
1833+
1834+
size_t num_possible = dwo_paths.GetSize();
1835+
for (size_t idx = 0; idx < num_possible && !found; ++idx) {
1836+
FileSpec dwo_spec = dwo_paths.GetFileSpecAtIndex(idx);
1837+
if (FileSystem::Instance().Exists(dwo_spec)) {
1838+
dwo_file = dwo_spec;
1839+
found = true;
1840+
}
17531841
}
1754-
FileSystem::Instance().Resolve(dwo_file);
1755-
dwo_file.AppendPathComponent(dwo_name);
17561842
}
17571843

1758-
if (!FileSystem::Instance().Exists(dwo_file)) {
1844+
if (!found) {
17591845
unit.SetDwoError(Status::createWithFormat(
17601846
"unable to locate .dwo debug file \"{0}\" for skeleton DIE "
17611847
"{1:x16}",
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/// Check that LLDB uses the paths in target.debug-file-search-paths to find
2+
/// split DWARF files with a relative DW_AT_comp_dir set, when the program file
3+
/// has been moved and/or we're executing it from another directory. Even when
4+
/// the provided search path is actually a symlink to the real location.
5+
// UNSUPPORTED: system-windows
6+
// RUN: rm -rf %t.compdir/ %t.e/
7+
// RUN: mkdir -p %t.compdir/a/b/c/d/
8+
// RUN: cp %s %t.compdir/a/b/c/d/main.c
9+
// RUN: cd %t.compdir/a/b/
10+
/// The produced DWO is named c/d/main-main.dwo, with a DW_AT_comp_dir of a/b.
11+
// RUN: %clang_host -g -gsplit-dwarf -fdebug-prefix-map=%t.compdir=. c/d/main.c -o c/d/main
12+
// RUN: cd ../../..
13+
/// Move only the program, leaving the DWO file in place.
14+
// RUN: mv %t.compdir/a/b/c/d/main %t.compdir/a/
15+
/// Create a symlink to the compliation dir, to use instead of the real path.
16+
// RUN: ln -s %t.compdir %t.symlink_to_compdir
17+
/// Debug it from yet another path.
18+
// RUN: mkdir -p %t.e/
19+
// RUN: cd %t.e
20+
/// DWO should be found by following using symlink + a/b/ + c/d/main-main.dwo.
21+
// RUN: %lldb --no-lldbinit %t.compdir/a/main \
22+
// RUN: -O "settings append target.debug-file-search-paths %t.symlink_to_compdir" \
23+
// RUN: -o "b main" -o "run" -o "p num" --batch 2>&1 | FileCheck %s
24+
25+
// CHECK-NOT: warning: {{.*}}main unable to locate separate debug file (dwo, dwp). Debugging will be degraded.
26+
// CHECK: (int) 5
27+
28+
int num = 5;
29+
30+
int main(void) { return 0; }
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/// Check that LLDB uses the paths in target.debug-file-search-paths to find
2+
/// split DWARF files with DW_AT_comp_dir set to some absolute path, when
3+
/// the program file and DWO have been moved and/or we're executing from
4+
/// another directory. Specifically when the DWO has been moved to another
5+
/// directory but is still at it's name. Here, %t.compdir/c/d/main-main.dwo.
6+
// RUN: rm -rf %t.compdir/ %t.e/
7+
// RUN: mkdir -p %t.compdir/a/b/c/d/
8+
// RUN: cp %s %t.compdir/a/b/c/d/main.c
9+
// RUN: cd %t.compdir/a/b/
10+
/// The produced DWO is named c/d/main-main.dwo, with a non-relative
11+
/// DW_AT_comp_dir of <pathtobuild>/a/b
12+
// RUN: %clang_host -g -gsplit-dwarf c/d/main.c -o c/d/main
13+
// RUN: cd ../../..
14+
/// Move the program.
15+
// RUN: mv %t.compdir/a/b/c/d/main %t.compdir/a/
16+
/// Move the DWO but keep it at the path in in its name.
17+
// RUN: mkdir -p %t.compdir/c/d/
18+
// RUN: mv %t.compdir/a/b/c/d/*.dwo %t.compdir/c/d/
19+
/// Debug it from yet another path.
20+
// RUN: mkdir -p %t.e/
21+
// RUN: cd %t.e
22+
/// LLDB should find in %t.compdir.
23+
// RUN: %lldb --no-lldbinit %t.compdir/a/main \
24+
// RUN: -O "settings append target.debug-file-search-paths %t.compdir" \
25+
// RUN: -o "b main" -o "run" -o "p num" --batch 2>&1 | FileCheck %s
26+
27+
// CHECK-NOT: warning: {{.*}}main unable to locate separate debug file (dwo, dwp). Debugging will be degraded.
28+
// CHECK: (int) 5
29+
30+
int num = 5;
31+
32+
int main(void) { return 0; }
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/// Check that LLDB uses the paths in target.debug-file-search-paths to find
2+
/// split DWARF files with DW_AT_comp_dir set to some non-relative path, when
3+
/// the program file and DWO have been moved and/or we're executing from another
4+
/// directory. Specifically when the DWO is not at it's "name", here we move
5+
/// it to %t.compdir/main-main.dwo and it's name is c/d/main-main.dwo.
6+
// RUN: rm -rf %t.compdir/ %t.e/
7+
// RUN: mkdir -p %t.compdir/a/b/c/d/
8+
// RUN: cp %s %t.compdir/a/b/c/d/main.c
9+
// RUN: cd %t.compdir/a/b/
10+
/// The produced DWO is named c/d/main-main.dwo, with a non-relative
11+
/// DW_AT_comp_dir of <pathtobuild>/a/b
12+
// RUN: %clang_host -g -gsplit-dwarf c/d/main.c -o c/d/main
13+
// RUN: cd ../../..
14+
/// Move the program.
15+
// RUN: mv %t.compdir/a/b/c/d/main %t.compdir/a/
16+
/// Move the DWO.
17+
// RUN: mv %t.compdir/a/b/c/d/*.dwo %t.compdir
18+
/// Debug it from yet another path.
19+
// RUN: mkdir -p %t.e/
20+
// RUN: cd %t.e
21+
/// LLDB should find in %t.compdir.
22+
// RUN: %lldb --no-lldbinit %t.compdir/a/main \
23+
// RUN: -O "settings append target.debug-file-search-paths %t.compdir" \
24+
// RUN: -o "b main" -o "run" -o "p num" --batch 2>&1 | FileCheck %s
25+
26+
// CHECK-NOT: warning: {{.*}}main unable to locate separate debug file (dwo, dwp). Debugging will be degraded.
27+
// CHECK: (int) 5
28+
29+
int num = 5;
30+
31+
int main(void) { return 0; }
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/// Check that when LLDB is looking for a relative DWO it uses the debug search
2+
/// paths setting. If it doesn't find it by adding the whole relative path to
3+
/// of DWO it should try adding just the filename (e.g. main.dwo) to each debug
4+
/// search path.
5+
// RUN: rm -rf %t.compdir/
6+
// RUN: mkdir -p %t.compdir/a/b/
7+
// RUN: cp %s %t.compdir/a/b/main.c
8+
// RUN: cd %t.compdir/a/
9+
/// The produced DWO is named /b/main-main.dwo, with a DW_AT_comp_dir of a/.
10+
// RUN: %clang_host -g -gsplit-dwarf -fdebug-prefix-map=%t.compdir=. b/main.c -o b/main
11+
// RUN: cd ../..
12+
/// Move the DWO file away from the expected location.
13+
// RUN: mv %t.compdir/a/b/*.dwo %t.compdir/
14+
/// LLDB won't find the DWO next to the binary or by adding the relative path
15+
/// to any of the search paths. So it should find the DWO file at
16+
/// %t.compdir/main-main.dwo.
17+
// RUN: %lldb --no-lldbinit %t.compdir/a/b/main \
18+
// RUN: -O "settings append target.debug-file-search-paths %t.compdir" \
19+
// RUN: -o "b main" -o "run" -o "p num" --batch 2>&1 | FileCheck %s
20+
21+
// CHECK-NOT: warning: {{.*}}main unable to locate separate debug file (dwo, dwp). Debugging will be degraded.
22+
// CHECK: (int) 5
23+
24+
int num = 5;
25+
26+
int main(void) { return 0; }
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/// Check that LLDB uses the paths in target.debug-file-search-paths to find
2+
/// split DWARF files with a relative DW_AT_comp_dir set, when the program file
3+
/// has been moved and/or we're executing it from another directory.
4+
// RUN: rm -rf %t.compdir/ %t.e/
5+
// RUN: mkdir -p %t.compdir/a/b/c/d/
6+
// RUN: cp %s %t.compdir/a/b/c/d/main.c
7+
// RUN: cd %t.compdir/a/b/
8+
/// The produced DWO is named c/d/main-main.dwo, with a DW_AT_comp_dir of a/b.
9+
// RUN: %clang_host -g -gsplit-dwarf -fdebug-prefix-map=%t.compdir=. c/d/main.c -o c/d/main
10+
// RUN: cd ../../..
11+
/// Move only the program, leaving the DWO file in place.
12+
// RUN: mv %t.compdir/a/b/c/d/main %t.compdir/a/
13+
/// Debug it from yet another path.
14+
// RUN: mkdir -p %t.e/
15+
// RUN: cd %t.e
16+
/// LLDB won't find the DWO next to the binary or in the current dir, so it
17+
/// should find the DWO file by doing %t.compdir/ + a/b/ + c/d/main-main.dwo.
18+
// RUN: %lldb --no-lldbinit %t.compdir/a/main \
19+
// RUN: -O "settings append target.debug-file-search-paths %t.compdir" \
20+
// RUN: -o "b main" -o "run" -o "p num" --batch 2>&1 | FileCheck %s
21+
22+
// CHECK-NOT: warning: {{.*}}main unable to locate separate debug file (dwo, dwp). Debugging will be degraded.
23+
// CHECK: (int) 5
24+
25+
int num = 5;
26+
27+
int main(void) { return 0; }
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/// Check that LLDB can find a relative DWO file next to a binary just using the
2+
/// filename of that DWO. For example "main.dwo" not "a/b/main.dwo".
3+
// RUN: rm -rf %t.compdir/
4+
// RUN: mkdir -p %t.compdir/a/b/
5+
// RUN: cp %s %t.compdir/a/b/main.c
6+
// RUN: cd %t.compdir/a/
7+
/// The produced DWO is named b/main-main.dwo, with a DW_AT_comp_dir of a/.
8+
// RUN: %clang_host -g -gsplit-dwarf -fdebug-prefix-map=%t.compdir=. b/main.c -o b/main
9+
// RUN: cd ../..
10+
/// Move binary and DWO out of expected locations.
11+
// RUN: mv %t.compdir/a/b/main %t.compdir/
12+
// RUN: mv %t.compdir/a/b/*.dwo %t.compdir/
13+
// RUN: %lldb --no-lldbinit %t.compdir/main \
14+
// RUN: -o "b main" -o "run" -o "p num" --batch 2>&1 | FileCheck %s
15+
16+
// CHECK-NOT: warning: {{.*}}main unable to locate separate debug file (dwo, dwp). Debugging will be degraded.
17+
// CHECK: (int) 5
18+
19+
int num = 5;
20+
21+
int main(void) { return 0; }

0 commit comments

Comments
 (0)