From c11677eedb2c302df0392af4bf21fb2f4978669b Mon Sep 17 00:00:00 2001 From: GkvJwa Date: Mon, 17 Jun 2024 23:20:06 +0800 Subject: [PATCH] [LLD][COFF] Support finding pdb files from outputpath (#94153) In addition to looking for dependent (input) PDB files next to the associated .OBJ file, we now also look into the output folder as well. This mimics MSVC link.exe behavior. Fixes #94152 --- lld/COFF/InputFiles.cpp | 45 +++++++++++++---------- lld/test/COFF/pdb-type-server-simple.test | 7 ++++ 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp index 037fae45242c6f..c3340745e69335 100644 --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -818,19 +818,6 @@ void ObjFile::initializeDependencies() { debugTypesObj = makeTpiSource(ctx, this); } -// Make a PDB path assuming the PDB is in the same folder as the OBJ -static std::string getPdbBaseName(ObjFile *file, StringRef tSPath) { - StringRef localPath = - !file->parentName.empty() ? file->parentName : file->getName(); - SmallString<128> path = sys::path::parent_path(localPath); - - // Currently, type server PDBs are only created by MSVC cl, which only runs - // on Windows, so we can assume type server paths are Windows style. - sys::path::append(path, - sys::path::filename(tSPath, sys::path::Style::windows)); - return std::string(path); -} - // The casing of the PDB path stamped in the OBJ can differ from the actual path // on disk. With this, we ensure to always use lowercase as a key for the // pdbInputFileInstances map, at least on Windows. @@ -843,17 +830,35 @@ static std::string normalizePdbPath(StringRef path) { } // If existing, return the actual PDB path on disk. -static std::optional findPdbPath(StringRef pdbPath, - ObjFile *dependentFile) { +static std::optional +findPdbPath(StringRef pdbPath, ObjFile *dependentFile, StringRef outputPath) { // Ensure the file exists before anything else. In some cases, if the path // points to a removable device, Driver::enqueuePath() would fail with an // error (EAGAIN, "resource unavailable try again") which we want to skip // silently. if (llvm::sys::fs::exists(pdbPath)) return normalizePdbPath(pdbPath); - std::string ret = getPdbBaseName(dependentFile, pdbPath); - if (llvm::sys::fs::exists(ret)) - return normalizePdbPath(ret); + + StringRef objPath = !dependentFile->parentName.empty() + ? dependentFile->parentName + : dependentFile->getName(); + + // Currently, type server PDBs are only created by MSVC cl, which only runs + // on Windows, so we can assume type server paths are Windows style. + StringRef pdbName = sys::path::filename(pdbPath, sys::path::Style::windows); + + // Check if the PDB is in the same folder as the OBJ. + SmallString<128> path; + sys::path::append(path, sys::path::parent_path(objPath), pdbName); + if (llvm::sys::fs::exists(path)) + return normalizePdbPath(path); + + // Check if the PDB is in the output folder. + path.clear(); + sys::path::append(path, sys::path::parent_path(outputPath), pdbName); + if (llvm::sys::fs::exists(path)) + return normalizePdbPath(path); + return std::nullopt; } @@ -865,7 +870,7 @@ PDBInputFile::~PDBInputFile() = default; PDBInputFile *PDBInputFile::findFromRecordPath(const COFFLinkerContext &ctx, StringRef path, ObjFile *fromFile) { - auto p = findPdbPath(path.str(), fromFile); + auto p = findPdbPath(path.str(), fromFile, ctx.config.outputFile); if (!p) return nullptr; auto it = ctx.pdbInputFileInstances.find(*p); @@ -931,7 +936,7 @@ std::optional ObjFile::getDILineInfo(uint32_t offset, } void ObjFile::enqueuePdbFile(StringRef path, ObjFile *fromFile) { - auto p = findPdbPath(path.str(), fromFile); + auto p = findPdbPath(path.str(), fromFile, ctx.config.outputFile); if (!p) return; auto it = ctx.pdbInputFileInstances.emplace(*p, nullptr); diff --git a/lld/test/COFF/pdb-type-server-simple.test b/lld/test/COFF/pdb-type-server-simple.test index e9757d187e2f10..93d66cde4f7129 100644 --- a/lld/test/COFF/pdb-type-server-simple.test +++ b/lld/test/COFF/pdb-type-server-simple.test @@ -27,6 +27,10 @@ Re-run with /DEBUG:GHASH RUN: lld-link a.obj b.obj -entry:main -debug:ghash -out:t.exe -pdb:t.pdb -nodefaultlib -summary -verbose RUN: llvm-pdbutil dump -symbols -types -ids -globals %t/t.pdb | FileCheck %s +Re-run with pdb from outputpath +RUN: mkdir -p libs +RUN: cp a.obj libs/a.obj && cp b.obj libs/b.obj +RUN: lld-link libs/a.obj libs/b.obj -entry:main -debug:ghash -out:t.exe -pdb:t.pdb -nodefaultlib -summary 2>&1 | FileCheck %s -check-prefix FAILURE-MISSING-PDBFILE CHECK-LABEL: Types (TPI Stream) CHECK: ============================================================ @@ -125,3 +129,6 @@ SUMMARY-NEXT: index total bytes count size SUMMARY-NEXT: 0x1006: 256 = 1 * 256 SUMMARY: Run llvm-pdbutil to print details about a particular record: SUMMARY-NEXT: llvm-pdbutil dump -ids -id-index 0x1006 t.pdb + +FAILURE-MISSING-PDBFILE-NOT: Cannot use debug info for '{{.*}}.obj' +FAILURE-MISSING-PDBFILE-NOT: failed to load reference '{{.*}}.pdb': no such file or directory