Skip to content

Commit 5a45d32

Browse files
authored
[lldb] Add more ways to find the .dwp file. (llvm#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.
1 parent 2836d8e commit 5a45d32

File tree

5 files changed

+141
-19
lines changed

5 files changed

+141
-19
lines changed

lldb/include/lldb/Utility/FileSpecList.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,10 @@ class FileSpecList {
238238
const_iterator begin() const { return m_files.begin(); }
239239
const_iterator end() const { return m_files.end(); }
240240

241+
llvm::iterator_range<const_iterator> files() const {
242+
return llvm::make_range(begin(), end());
243+
}
244+
241245
protected:
242246
collection m_files; ///< A collection of FileSpec objects.
243247
};

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ static constexpr Log::Category g_categories[] = {
2222
{{"map"},
2323
{"log insertions of object files into DWARF debug maps"},
2424
DWARFLog::DebugMap},
25+
{{"split"}, {"log split DWARF related activities"}, DWARFLog::SplitDwarf},
2526
};
2627

2728
static Log::Channel g_channel(g_categories, DWARFLog::DebugInfo);

lldb/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ enum class DWARFLog : Log::MaskType {
2020
DebugMap = Log::ChannelFlag<2>,
2121
Lookups = Log::ChannelFlag<3>,
2222
TypeCompletion = Log::ChannelFlag<4>,
23+
SplitDwarf = Log::ChannelFlag<5>,
2324
LLVM_MARK_AS_BITMASK_ENUM(TypeCompletion)
2425
};
2526
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();

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

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4349,26 +4349,60 @@ SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
43494349

43504350
const std::shared_ptr<SymbolFileDWARFDwo> &SymbolFileDWARF::GetDwpSymbolFile() {
43514351
llvm::call_once(m_dwp_symfile_once_flag, [this]() {
4352+
// Create a list of files to try and append .dwp to.
4353+
FileSpecList symfiles;
4354+
// Append the module's object file path.
4355+
const FileSpec module_fspec = m_objfile_sp->GetModule()->GetFileSpec();
4356+
symfiles.Append(module_fspec);
4357+
// Append the object file for this SymbolFile only if it is different from
4358+
// the module's file path. Our main module could be "a.out", our symbol file
4359+
// could be "a.debug" and our ".dwp" file might be "a.debug.dwp" instead of
4360+
// "a.out.dwp".
4361+
const FileSpec symfile_fspec(m_objfile_sp->GetFileSpec());
4362+
if (symfile_fspec != module_fspec) {
4363+
symfiles.Append(symfile_fspec);
4364+
} else {
4365+
// If we don't have a separate debug info file, then try stripping the
4366+
// extension. The main module could be "a.debug" and the .dwp file could
4367+
// be "a.dwp" instead of "a.debug.dwp".
4368+
ConstString filename_no_ext =
4369+
module_fspec.GetFileNameStrippingExtension();
4370+
if (filename_no_ext != module_fspec.GetFilename()) {
4371+
FileSpec module_spec_no_ext(module_fspec);
4372+
module_spec_no_ext.SetFilename(filename_no_ext);
4373+
symfiles.Append(module_spec_no_ext);
4374+
}
4375+
}
4376+
Log *log = GetLog(DWARFLog::SplitDwarf);
4377+
FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
43524378
ModuleSpec module_spec;
43534379
module_spec.GetFileSpec() = m_objfile_sp->GetFileSpec();
4354-
module_spec.GetSymbolFileSpec() =
4355-
FileSpec(m_objfile_sp->GetModule()->GetFileSpec().GetPath() + ".dwp");
4356-
43574380
module_spec.GetUUID() = m_objfile_sp->GetUUID();
4358-
FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
4359-
FileSpec dwp_filespec =
4360-
PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
4361-
if (FileSystem::Instance().Exists(dwp_filespec)) {
4362-
DataBufferSP dwp_file_data_sp;
4363-
lldb::offset_t dwp_file_data_offset = 0;
4364-
ObjectFileSP dwp_obj_file = ObjectFile::FindPlugin(
4365-
GetObjectFile()->GetModule(), &dwp_filespec, 0,
4366-
FileSystem::Instance().GetByteSize(dwp_filespec), dwp_file_data_sp,
4367-
dwp_file_data_offset);
4368-
if (!dwp_obj_file)
4369-
return;
4370-
m_dwp_symfile = std::make_shared<SymbolFileDWARFDwo>(
4371-
*this, dwp_obj_file, DIERef::k_file_index_mask);
4381+
for (const auto &symfile : symfiles.files()) {
4382+
module_spec.GetSymbolFileSpec() =
4383+
FileSpec(symfile.GetPath() + ".dwp", symfile.GetPathStyle());
4384+
LLDB_LOG(log, "Searching for DWP using: \"{0}\"",
4385+
module_spec.GetSymbolFileSpec());
4386+
FileSpec dwp_filespec =
4387+
PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
4388+
if (FileSystem::Instance().Exists(dwp_filespec)) {
4389+
LLDB_LOG(log, "Found DWP file: \"{0}\"", dwp_filespec);
4390+
DataBufferSP dwp_file_data_sp;
4391+
lldb::offset_t dwp_file_data_offset = 0;
4392+
ObjectFileSP dwp_obj_file = ObjectFile::FindPlugin(
4393+
GetObjectFile()->GetModule(), &dwp_filespec, 0,
4394+
FileSystem::Instance().GetByteSize(dwp_filespec), dwp_file_data_sp,
4395+
dwp_file_data_offset);
4396+
if (dwp_obj_file) {
4397+
m_dwp_symfile = std::make_shared<SymbolFileDWARFDwo>(
4398+
*this, dwp_obj_file, DIERef::k_file_index_mask);
4399+
break;
4400+
}
4401+
}
4402+
}
4403+
if (!m_dwp_symfile) {
4404+
LLDB_LOG(log, "Unable to locate for DWP file for: \"{0}\"",
4405+
m_objfile_sp->GetModule()->GetFileSpec());
43724406
}
43734407
});
43744408
return m_dwp_symfile;

lldb/test/Shell/SymbolFile/DWARF/x86/dwp-separate-debug-file.cpp

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
// REQUIRES: lld
22

3+
// Now test with DWARF5
34
// RUN: %clang -target x86_64-pc-linux -gsplit-dwarf -gdwarf-5 -c %s -o %t.dwarf5.o
45
// RUN: ld.lld %t.dwarf5.o -o %t.dwarf5
56
// RUN: llvm-dwp %t.dwarf5.dwo -o %t.dwarf5.dwp
67
// RUN: rm %t.dwarf5.dwo
78
// RUN: llvm-objcopy --only-keep-debug %t.dwarf5 %t.dwarf5.debug
89
// RUN: llvm-objcopy --strip-all --add-gnu-debuglink=%t.dwarf5.debug %t.dwarf5
9-
// RUN: %lldb %t.dwarf5 -o "target variable a" -b | FileCheck %s
10+
// RUN: %lldb \
11+
// RUN: -O "log enable dwarf split" \
12+
// RUN: -o "target variable a" \
13+
// RUN: -b %t.dwarf5 | FileCheck %s
1014

1115
// Run one time with the index cache enabled to populate the index cache. When
1216
// we populate the index cache we have to parse all of the DWARF debug info
@@ -34,14 +38,42 @@
3438
// RUN: -o "statistics dump" \
3539
// RUN: %t.dwarf5 -b | FileCheck %s -check-prefix=CACHED
3640

41+
// Make sure that if we load the "%t.dwarf5.debug" file, that we can find and
42+
// load the .dwo file from the .dwp when it is "%t.dwarf5.dwp"
43+
// RUN: %lldb %t.dwarf5.debug -o "b main" -b | FileCheck %s -check-prefix=DEBUG
44+
45+
// Make sure that if we load the "%t.dwarf5" file, that we can find and
46+
// load the .dwo file from the .dwp when it is "%t.dwarf5.debug.dwp"
47+
// RUN: mv %t.dwarf5.dwp %t.dwarf5.debug.dwp
48+
// RUN: %lldb %t.dwarf5 -o "b main" -b | FileCheck %s -check-prefix=DEBUG
49+
50+
// Make sure that if we load the "%t.dwarf5.debug" file, that we can find and
51+
// load the .dwo file from the .dwp when it is "%t.dwarf5.debug.dwp"
52+
// RUN: %lldb %t.dwarf5.debug -o "b main" -b | FileCheck %s -check-prefix=DEBUG
53+
54+
// Make sure that if we remove the .dwp file we see an appropriate error.
55+
// RUN: rm %t.dwarf5.debug.dwp
56+
// RUN: %lldb \
57+
// RUN: -O "log enable dwarf split" \
58+
// RUN: -o "b main" \
59+
// RUN: -b %t.dwarf5 2>&1 | FileCheck %s -check-prefix=NODWP
60+
61+
// RUN: %lldb \
62+
// RUN: -O "log enable dwarf split" \
63+
// RUN: -o "b main" \
64+
// RUN: -b %t.dwarf5.debug 2>&1 | FileCheck %s -check-prefix=NODWP
65+
3766
// Now test with DWARF4
3867
// RUN: %clang -target x86_64-pc-linux -gsplit-dwarf -gdwarf-4 -c %s -o %t.dwarf4.o
3968
// RUN: ld.lld %t.dwarf4.o -o %t.dwarf4
4069
// RUN: llvm-dwp %t.dwarf4.dwo -o %t.dwarf4.dwp
4170
// RUN: rm %t.dwarf4.dwo
4271
// RUN: llvm-objcopy --only-keep-debug %t.dwarf4 %t.dwarf4.debug
4372
// RUN: llvm-objcopy --strip-all --add-gnu-debuglink=%t.dwarf4.debug %t.dwarf4
44-
// RUN: %lldb %t.dwarf4 -o "target variable a" -b | FileCheck %s
73+
// RUN: %lldb \
74+
// RUN: -O "log enable dwarf split" \
75+
// RUN: -o "target variable a" \
76+
// RUN: -b %t.dwarf4 | FileCheck %s
4577

4678
// Run one time with the index cache enabled to populate the index cache. When
4779
// we populate the index cache we have to parse all of the DWARF debug info
@@ -69,6 +101,46 @@
69101
// RUN: -o "statistics dump" \
70102
// RUN: %t.dwarf4 -b | FileCheck %s -check-prefix=CACHED
71103

104+
// Make sure that if we load the "%t.dwarf4.debug" file, that we can find and
105+
// load the .dwo file from the .dwp when it is "%t.dwarf4.dwp"
106+
// RUN: %lldb %t.dwarf4.debug -o "b main" -b | FileCheck %s -check-prefix=DEBUG
107+
108+
// Make sure that if we load the "%t.dwarf4" file, that we can find and
109+
// load the .dwo file from the .dwp when it is "%t.dwarf4.debug.dwp"
110+
// RUN: mv %t.dwarf4.dwp %t.dwarf4.debug.dwp
111+
// RUN: %lldb %t.dwarf4 -o "b main" -b | FileCheck %s -check-prefix=DEBUG
112+
113+
// Make sure that if we load the "%t.dwarf4.debug" file, that we can find and
114+
// load the .dwo file from the .dwp when it is "%t.dwarf4.debug.dwp"
115+
// RUN: %lldb %t.dwarf4.debug -o "b main" -b | FileCheck %s -check-prefix=DEBUG
116+
117+
// Make sure that if we remove the .dwp file we see an appropriate error.
118+
// RUN: rm %t.dwarf4.debug.dwp
119+
// RUN: %lldb \
120+
// RUN: -O "log enable dwarf split" \
121+
// RUN: -o "b main" \
122+
// RUN: -b %t.dwarf4 2>&1 | FileCheck %s -check-prefix=NODWP
123+
124+
// RUN: %lldb \
125+
// RUN: -O "log enable dwarf split" \
126+
// RUN: -o "b main" \
127+
// RUN: -b %t.dwarf4.debug 2>&1 | FileCheck %s -check-prefix=NODWP
128+
129+
// Test if we have a GNU build ID in our main executable and in our debug file,
130+
// and we have a .dwp file that doesn't, that we can still load our .dwp file.
131+
// RUN: %clang -target x86_64-pc-linux -gsplit-dwarf -gdwarf-5 -c %s -o %t.o
132+
// RUN: ld.lld %t.o --build-id=md5 -o %t
133+
// RUN: llvm-dwp %t.dwo -o %t.dwp
134+
// RUN: rm %t.dwo
135+
// RUN: llvm-objcopy --only-keep-debug %t %t.debug
136+
// RUN: llvm-objcopy --strip-all --add-gnu-debuglink=%t.debug %t
137+
// RUN: %lldb \
138+
// RUN: -O "log enable dwarf split" \
139+
// RUN: -o "target variable a" \
140+
// RUN: -b %t | FileCheck %s
141+
142+
// CHECK: Searching for DWP using:
143+
// CHECK: Found DWP file:
72144
// CHECK: (A) a = (x = 47)
73145

74146
// CACHE: script lldb.target.modules[0].FindTypes('::A').GetTypeAtIndex(0)
@@ -83,6 +155,16 @@
83155
// CACHED-NEXT: }
84156
// CACHED: "totalDebugInfoIndexLoadedFromCache": 1
85157

158+
// Make sure debug information was loaded by verifying that the
159+
// 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]+}}
160+
161+
// Make sure if we load the stripped binary or the debug info file with no .dwp
162+
// nor any .dwo files that we are not able to fine the .dwp or .dwo files.
163+
// NODWP: Searching for DWP using:
164+
// NODWP: Searching for DWP using:
165+
// NODWP: Unable to locate for DWP file for:
166+
// NODWP: unable to locate separate debug file (dwo, dwp). Debugging will be degraded.
167+
86168
struct A {
87169
int x = 47;
88170
};

0 commit comments

Comments
 (0)