Index: lld/trunk/COFF/PDB.cpp =================================================================== --- lld/trunk/COFF/PDB.cpp +++ lld/trunk/COFF/PDB.cpp @@ -218,6 +218,33 @@ }; } +// Visual Studio's debugger requires absolute paths in various places in the +// PDB to work without additional configuration: +// https://docs.microsoft.com/en-us/visualstudio/debugger/debug-source-files-common-properties-solution-property-pages-dialog-box +static void pdbMakeAbsolute(SmallVectorImpl &FileName) { + if (sys::path::is_absolute(FileName, sys::path::Style::windows)) + return; + if (Config->PDBSourcePath.empty()) { + // Debuggers generally want that PDB files contain absolute, Windows-style + // paths. On POSIX hosts, this here will produce an absolute POSIX-style + // path, which is weird -- but it's not clear what else to do. + // People doing cross builds should probably just always pass + // /pbdsourcepath: and make sure paths to input obj files and to lld-link + // itself are relative. + sys::fs::make_absolute(FileName); + return; + } + // Using /pdbsourcepath: with absolute POSIX paths will prepend + // PDBSourcePath to the absolute POSIX path. Since absolute POSIX paths + // don't make sense in PDB files anyways, this is gargabe-in-garbage-out. + SmallString<128> AbsoluteFileName = Config->PDBSourcePath; + sys::path::append(AbsoluteFileName, sys::path::Style::windows, FileName); + sys::path::native(AbsoluteFileName, sys::path::Style::windows); + sys::path::remove_dots(AbsoluteFileName, /*remove_dot_dots=*/true, + sys::path::Style::windows); + FileName = std::move(AbsoluteFileName); +} + static SectionChunk *findByName(ArrayRef Sections, StringRef Name) { for (SectionChunk *C : Sections) @@ -984,13 +1011,7 @@ for (FileChecksumEntry &FC : Checksums) { SmallString<128> FileName = ExitOnErr(CVStrTab.getString(FC.FileNameOffset)); - if (!sys::path::is_absolute(FileName) && !Config->PDBSourcePath.empty()) { - SmallString<128> AbsoluteFileName = Config->PDBSourcePath; - sys::path::append(AbsoluteFileName, FileName); - sys::path::native(AbsoluteFileName); - sys::path::remove_dots(AbsoluteFileName, /*remove_dot_dots=*/true); - FileName = std::move(AbsoluteFileName); - } + pdbMakeAbsolute(FileName); ExitOnErr(Linker.Builder.getDbiBuilder().addModuleSourceFile( *File.ModuleDBI, FileName)); NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum); @@ -1005,7 +1026,7 @@ // absolute. bool InArchive = !File->ParentName.empty(); SmallString<128> Path = InArchive ? File->ParentName : File->getName(); - sys::fs::make_absolute(Path); + pdbMakeAbsolute(Path); sys::path::native(Path, sys::path::Style::windows); StringRef Name = InArchive ? File->getName() : StringRef(Path); @@ -1201,11 +1222,14 @@ std::string ArgStr = llvm::join(Args, " "); EBS.Fields.push_back("cwd"); SmallString<64> cwd; - sys::fs::current_path(cwd); + if (Config->PDBSourcePath.empty()) + sys::fs::current_path(cwd); + else + cwd = Config->PDBSourcePath; EBS.Fields.push_back(cwd); EBS.Fields.push_back("exe"); SmallString<64> exe = Config->Argv[0]; - llvm::sys::fs::make_absolute(exe); + pdbMakeAbsolute(exe); EBS.Fields.push_back(exe); EBS.Fields.push_back("pdb"); EBS.Fields.push_back(Path); @@ -1287,7 +1311,7 @@ // It's not entirely clear what this is, but the * Linker * module uses it. pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); NativePath = Config->PDBPath; - sys::fs::make_absolute(NativePath); + pdbMakeAbsolute(NativePath); sys::path::native(NativePath, sys::path::Style::windows); uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath); auto &LinkerModule = ExitOnErr(DbiBuilder.addModuleInfo("* Linker *")); Index: lld/trunk/test/COFF/pdb-relative-source-lines.test =================================================================== --- lld/trunk/test/COFF/pdb-relative-source-lines.test +++ lld/trunk/test/COFF/pdb-relative-source-lines.test @@ -17,14 +17,26 @@ $ clang-cl -Xclang -fdebug-compilation-dir -Xclang . -c -Z7 pdb_lines*.c -RUN: yaml2obj %S/Inputs/pdb_lines_1_relative.yaml -o %t.pdb_lines_1_relative.obj -RUN: yaml2obj %S/Inputs/pdb_lines_2_relative.yaml -o %t.pdb_lines_2_relative.obj -RUN: rm -f %t.exe %t.pdb -RUN: lld-link -debug -pdbsourcepath:c:\\src -entry:main -nodefaultlib -out:%t.exe -pdb:%t.pdb %t.pdb_lines_1_relative.obj %t.pdb_lines_2_relative.obj -RUN: llvm-pdbutil pdb2yaml -modules -module-files -subsections=lines,fc %t.pdb | FileCheck %s +/pdbsourcepath: only sets the directory that relative paths are considered +relative to, so this test needs to pass relative paths to lld-link for: +1. The input obj files +2. The /pdb: switch +3. The lld-link invocation itself +To achieve this, put all inputs of the lld-link invocation (including lld-link +itself) in a temp directory that's cwd and then make sure to only use relative +arguments when calling ./lld-link below. +RUN: rm -rf %t +RUN: mkdir %t +RUN: cp lld-link %t/lld-link +RUN: cd %t -CHECK-LABEL: - Module: {{.*}}pdb_lines_1_relative.obj -CHECK-NEXT: ObjFile: {{.*}}pdb_lines_1_relative.obj +RUN: yaml2obj %S/Inputs/pdb_lines_1_relative.yaml -o %t/pdb_lines_1_relative.obj +RUN: yaml2obj %S/Inputs/pdb_lines_2_relative.yaml -o %t/pdb_lines_2_relative.obj +RUN: ./lld-link -debug -pdbsourcepath:c:\\src -entry:main -nodefaultlib -out:out.exe -pdb:out.pdb pdb_lines_1_relative.obj pdb_lines_2_relative.obj +RUN: llvm-pdbutil pdb2yaml -modules -module-files -module-syms -subsections=lines,fc %t/out.pdb | FileCheck %s + +CHECK-LABEL: - Module: 'c:\src\pdb_lines_1_relative.obj' +CHECK-NEXT: ObjFile: 'c:\src\pdb_lines_1_relative.obj' CHECK: SourceFiles: CHECK-NEXT: - 'c:{{[\\/]}}src{{[\\/]}}pdb_lines_1.c' CHECK-NEXT: - 'c:{{[\\/]}}src{{[\\/]}}foo.h' @@ -35,11 +47,23 @@ CHECK: - FileName: 'c:{{[\\/]}}src{{[\\/]}}pdb_lines_1.c' CHECK: - FileName: 'c:{{[\\/]}}src{{[\\/]}}foo.h' -CHECK-LABEL: - Module: {{.*}}pdb_lines_2_relative.obj -CHECK-NEXT: ObjFile: {{.*}}pdb_lines_2_relative.obj +CHECK-LABEL: - Module: 'c:\src\pdb_lines_2_relative.obj' +CHECK-NEXT: ObjFile: 'c:\src\pdb_lines_2_relative.obj' CHECK: SourceFiles: CHECK-NEXT: - 'c:{{[\\/]}}src{{[\\/]}}pdb_lines_2.c' CHECK: Subsections: CHECK: - FileName: 'c:{{[\\/]}}src{{[\\/]}}pdb_lines_2.c' CHECK: - !FileChecksums CHECK: - FileName: 'c:{{[\\/]}}src{{[\\/]}}pdb_lines_2.c' + +CHECK-LABEL: - Kind: S_ENVBLOCK +CHECK-NEXT: EnvBlockSym: +CHECK-NEXT: Entries: +CHECK-NEXT: - cwd +CHECK-NEXT: - 'c:\src' +CHECK-NEXT: - exe +CHECK-NEXT: - 'c:\src\lld-link' +CHECK-NEXT: - pdb +CHECK-NEXT: - 'c:\src\out.pdb' +CHECK-NEXT: - cmd +CHECK-NEXT: - '-debug -pdbsourcepath:c:\src -entry:main -nodefaultlib -out:out.exe -pdb:out.pdb pdb_lines_1_relative.obj pdb_lines_2_relative.obj'