Skip to content

Commit 479f5bf

Browse files
[LLDB] Improve PDB discovery
When loading a PE/COFF target, the associated PDB file often wasn't found. The executable module contains a path for the associated PDB file, but people often debug from a different directory than the one their build system uses. (This is especially common in post-mortem and cross platform debugging.) Suppose the COFF executable being debugged is `~/proj/foo.exe`, but it was built elsewhere and refers to `D:\remote\build\env\foobar.pdb`, LLDB wouldn't find it. With this change, if no file exists at the PDB path, LLDB will look in the executable directory for a PDB file that matches the name of the one it expected (e.g., `~/proj/foobar.pdb`). If found, the PDB is subject to the same matching criteria (GUIDs and age) as would have been used had it been in the original location. This same-directory-as-the-binary rule is commonly used by debuggers on Windows. Differential Review: https://reviews.llvm.org/D84815
1 parent df79e18 commit 479f5bf

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,16 @@ loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {
134134
return nullptr;
135135
}
136136

137-
// if the file doesn't exist, is not a pdb, or doesn't have a matching guid,
138-
// fail.
137+
// If the file doesn't exist, perhaps the path specified at build time
138+
// doesn't match the PDB's current location, so check the location of the
139+
// executable.
140+
if (!FileSystem::Instance().Exists(pdb_file)) {
141+
const auto exe_dir = FileSpec(exe_path).CopyByRemovingLastPathComponent();
142+
const auto pdb_name = FileSpec(pdb_file).GetFilename().GetCString();
143+
pdb_file = exe_dir.CopyByAppendingPathComponent(pdb_name).GetCString();
144+
}
145+
146+
// If the file is not a PDB or if it doesn't have a matching GUID, fail.
139147
llvm::file_magic magic;
140148
auto ec = llvm::identify_magic(pdb_file, magic);
141149
if (ec || magic != llvm::file_magic::pdb)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
target modules dump symfile
2+
quit
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// clang-format off
2+
// REQUIRES: lld, x86
3+
4+
// Test that lldb can find the PDB file that corresponds to the executable. The linker
5+
// writes a path to the PDB in the executable. If the PDB is not there, lldb should
6+
// check the directory that contains the executable. We'll generate the PDB file in
7+
// a subdirectory and then move it into the directory with the executable. That will
8+
// ensure the PDB path stored in the executable is wrong.
9+
10+
// Build an EXE and PDB in different directories
11+
// RUN: mkdir -p %t/executable
12+
// RUN: rm -f %t/executable/foo.exe %t/executable/bar.pdb
13+
// RUN: mkdir -p %t/symbols
14+
// RUN: rm -f %t/symbols/bar.pdb
15+
// RUN: %clang_cl --target=x86_64-windows-msvc -Od -Z7 -c /Fo%t/executable/foo.obj -- %s
16+
// RUN: lld-link -debug:full -nodefaultlib -entry:main %t/executable/foo.obj \
17+
// RUN: -out:%t/executable/foo.exe -pdb:%t/symbols/bar.pdb
18+
19+
// Find the PDB in its build location
20+
// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t/executable/foo.exe -s \
21+
// RUN: %p/Inputs/locate-pdb.lldbinit | FileCheck %s
22+
23+
// Also find the PDB when it's adjacent to the executable
24+
// RUN: mv -f %t/symbols/bar.pdb %t/executable/bar.pdb
25+
// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t/executable/foo.exe -s \
26+
// RUN: %p/Inputs/locate-pdb.lldbinit | FileCheck %s
27+
28+
int main(int argc, char** argv) {
29+
return 0;
30+
}
31+
32+
// CHECK: (lldb) target modules dump symfile
33+
// CHECK: Dumping debug symbols for 1 modules.
34+
// CHECK: SymbolFile pdb

0 commit comments

Comments
 (0)