From 4764bb2cb1cf5d6413f633002ca1b63e1caff2eb Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Tue, 9 Oct 2018 17:52:25 +0000 Subject: [PATCH] lld-link: Use /pdbsourcepath: for more places when present. /pdbsourcepath: was added in https://reviews.llvm.org/D48882 to make it possible to have relative paths in the debug info that clang-cl writes. lld-link then makes the paths absolute at link time, which debuggers require. This way, clang-cl's output is independent of the absolute path of the build directory, which is useful for cacheability in distcc-like systems. This patch extends /pdbsourcepath: (if passed) to also be used for: 1. The "cwd" stored in the env block in the pdb is /pdbsourcepath: if present 2. The "exe" stored in the env block in the pdb is made absolute relative to /pdbsourcepath: instead of the cwd 3. The "pdb" stored in the env block in the pdb is made absolute relative to /pdbsourcepath: instead of the cwd 4. For making absolute paths to .obj files referenced from the pdb /pdbsourcepath: is now useful in three scenarios (the first one already working before this change): 1. When building with full debug info, passing the real build dir to /pdbsourcepath: allows having clang-cl's output to be independent of the build directory path. This patch effectively doesn't change behavior for this use case (assuming the cwd is the build dir). 2. When building without compile-time debug info but linking with /debug, a fake fixed /pdbsourcepath: can be passed to get symbolized stacks while making the pdb and exe independent of the current build dir. For this two work, lld-link needs to be invoked with relative paths for the lld-link invocation itself (for "exe"), for the pdb output name, the exe output name (for "pdb"), and the obj input files, and no absolute path must appear on the link command (for "cmd" in the pdb's env block). Since no full debug info is present, it doesn't matter that the absolute path doesn't exist on disk -- we only get symbols in stacks. 3. When building production builds with full debug info that don't have local changes, and that get source indexed and their pdbs get uploaded to a symbol server. /pdbsourcepath: again makes the build output independent of the current directory, and the fixed path passed to /pdbsourcepath: can be given the source indexing transform so that it gets mapped to a repository path. This has the same requirements as 2. This patch also makes it possible to create PDB files containing Windows-style absolute paths when cross-compiling on a POSIX system. Differential Revision: https://reviews.llvm.org/D53021 llvm-svn: 344061 --- lld/COFF/PDB.cpp | 46 +++++++++++++++++++++------- lld/test/COFF/pdb-relative-source-lines.test | 42 +++++++++++++++++++------ 2 files changed, 68 insertions(+), 20 deletions(-) diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp index 80f0219..6790ae6 100644 --- a/lld/COFF/PDB.cpp +++ b/lld/COFF/PDB.cpp @@ -218,6 +218,33 @@ public: }; } +// 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 @@ void DebugSHandler::finish() { 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 @@ void PDBLinker::addObjFile(ObjFile *File) { // 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 @@ static void addCommonLinkerModuleSymbols(StringRef Path, 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 @@ void PDBLinker::addSections(ArrayRef OutputSections, // 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 *")); diff --git a/lld/test/COFF/pdb-relative-source-lines.test b/lld/test/COFF/pdb-relative-source-lines.test index 8c0894c..3e2f349 100644 --- a/lld/test/COFF/pdb-relative-source-lines.test +++ b/lld/test/COFF/pdb-relative-source-lines.test @@ -17,14 +17,26 @@ void bar(void) { $ 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: - !FileChecksums 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' -- 2.7.4