aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2019-10-10 20:25:51 +0000
committerZachary Turner <zturner@google.com>2019-10-10 20:25:51 +0000
commit7809ac6b9d6fa488a028346af702a1473b09b937 (patch)
treede16e8709b80cff40a26b29f5bd185204d0d9922
parentacdb89e153e76b3ed3119c01b44a104f7a97f8a6 (diff)
[PDB] Fix bug when using multiple PCH header objects with the same name.
A common pattern in Windows is to have all your precompiled headers use an object named stdafx.obj. If you've got a project with many different static libs, you might use a separate PCH for each one of these. During the final link step, a file from A might reference the PCH object from A, but it will have the same name (stdafx.obj) as any other PCH from another project. The only difference will be the path. For example, A might be A/stdafx.obj while B is B/stdafx.obj. The existing algorithm checks only the filename that was passed on the command line (or stored in archive), but this is insufficient in the case where relative paths are used, because depending on the command line object file / library order, it might find the wrong PCH object first resulting in a signature mismatch. The fix here is to simply check whether the absolute path of the PCH object (which is stored in the input obj file for the file that references the PCH) *ends with* the full relative path of whatever is specified on the command line (or is in the archive). Differential Revision: https://reviews.llvm.org/D66431 git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@374442 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--COFF/PDB.cpp26
-rw-r--r--test/COFF/Inputs/precompa/precomp.objbin0 -> 62698 bytes
-rw-r--r--test/COFF/Inputs/precompa/useprecomp.objbin0 -> 2568 bytes
-rw-r--r--test/COFF/Inputs/precompb/precomp.objbin0 -> 62698 bytes
-rw-r--r--test/COFF/Inputs/precompb/useprecomp.objbin0 -> 1977 bytes
-rw-r--r--test/COFF/precomp-link-samename.test36
-rw-r--r--test/COFF/precomp-link.test4
7 files changed, 47 insertions, 19 deletions
diff --git a/COFF/PDB.cpp b/COFF/PDB.cpp
index 765f820b4..400def8e6 100644
--- a/COFF/PDB.cpp
+++ b/COFF/PDB.cpp
@@ -514,16 +514,15 @@ static bool equals_path(StringRef path1, StringRef path2) {
return path1.equals(path2);
#endif
}
-
// Find by name an OBJ provided on the command line
-static ObjFile *findObjByName(StringRef fileNameOnly) {
- SmallString<128> currentPath;
-
+static ObjFile *findObjWithPrecompSignature(StringRef fileNameOnly,
+ uint32_t precompSignature) {
for (ObjFile *f : ObjFile::instances) {
StringRef currentFileName = sys::path::filename(f->getName());
- // Compare based solely on the file name (link.exe behavior)
- if (equals_path(currentFileName, fileNameOnly))
+ if (f->pchSignature.hasValue() &&
+ f->pchSignature.getValue() == precompSignature &&
+ equals_path(fileNameOnly, currentFileName))
return f;
}
return nullptr;
@@ -560,22 +559,15 @@ Expected<const CVIndexMap &> PDBLinker::aquirePrecompObj(ObjFile *file) {
// link.exe requires that a precompiled headers object must always be provided
// on the command-line, even if that's not necessary.
- auto precompFile = findObjByName(precompFileName);
+ auto precompFile =
+ findObjWithPrecompSignature(precompFileName, precomp.Signature);
if (!precompFile)
return createFileError(
- precompFileName.str(),
- make_error<pdb::PDBError>(pdb::pdb_error_code::external_cmdline_ref));
+ precomp.getPrecompFilePath().str(),
+ make_error<pdb::PDBError>(pdb::pdb_error_code::no_matching_pch));
addObjFile(precompFile, &indexMap);
- if (!precompFile->pchSignature)
- fatal(precompFile->getName() + " is not a precompiled headers object");
-
- if (precomp.getSignature() != precompFile->pchSignature.getValueOr(0))
- return createFileError(
- precomp.getPrecompFilePath().str(),
- make_error<pdb::PDBError>(pdb::pdb_error_code::signature_out_of_date));
-
return indexMap;
}
diff --git a/test/COFF/Inputs/precompa/precomp.obj b/test/COFF/Inputs/precompa/precomp.obj
new file mode 100644
index 000000000..27709f567
--- /dev/null
+++ b/test/COFF/Inputs/precompa/precomp.obj
Binary files differ
diff --git a/test/COFF/Inputs/precompa/useprecomp.obj b/test/COFF/Inputs/precompa/useprecomp.obj
new file mode 100644
index 000000000..c0275ca4b
--- /dev/null
+++ b/test/COFF/Inputs/precompa/useprecomp.obj
Binary files differ
diff --git a/test/COFF/Inputs/precompb/precomp.obj b/test/COFF/Inputs/precompb/precomp.obj
new file mode 100644
index 000000000..416c93430
--- /dev/null
+++ b/test/COFF/Inputs/precompb/precomp.obj
Binary files differ
diff --git a/test/COFF/Inputs/precompb/useprecomp.obj b/test/COFF/Inputs/precompb/useprecomp.obj
new file mode 100644
index 000000000..2bee90540
--- /dev/null
+++ b/test/COFF/Inputs/precompb/useprecomp.obj
Binary files differ
diff --git a/test/COFF/precomp-link-samename.test b/test/COFF/precomp-link-samename.test
new file mode 100644
index 000000000..f44abf289
--- /dev/null
+++ b/test/COFF/precomp-link-samename.test
@@ -0,0 +1,36 @@
+RUN: lld-link %S/Inputs/precompb/useprecomp.obj %S/Inputs/precompa/precomp.obj %S/Inputs/precompb/precomp.obj \
+RUN: %S/Inputs/precompa/useprecomp.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe \
+RUN: /summary | FileCheck %s -check-prefix SUMMARY
+
+RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
+
+
+CHECK: Types (TPI Stream)
+CHECK-NOT: LF_PRECOMP
+CHECK-NOT: LF_ENDPRECOMP
+
+
+SUMMARY: Summary
+SUMMARY-NEXT: --------------------------------------------------------------------------------
+SUMMARY-NEXT: 4 Input OBJ files (expanded from all cmd-line inputs)
+SUMMARY-NEXT: 0 PDB type server dependencies
+SUMMARY-NEXT: 2 Precomp OBJ dependencies
+
+// precompa/precomp.cpp
+#include "precomp.h"
+
+// precompa/useprecomp.cpp
+#include "precomp.h"
+int main(int argc, char **argv) { return 0; }
+
+// precompa/precomp.h
+int precompa_symbol = 42;
+
+// precompb/precomp.cpp
+#include "precomp.h"
+
+// precompb/useprecomp.cpp
+#include "precomp.h"
+
+// precompb/precomp.h
+int precompb_symbol = 142; \ No newline at end of file
diff --git a/test/COFF/precomp-link.test b/test/COFF/precomp-link.test
index e0ab30068..f94f8c204 100644
--- a/test/COFF/precomp-link.test
+++ b/test/COFF/precomp-link.test
@@ -9,10 +9,10 @@ RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-invalid.obj %S/Inputs/pr
RUN: not lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf 2>&1 | FileCheck %s -check-prefix FAILURE-MISSING-PRECOMPOBJ
FAILURE: warning: Cannot use debug info for '{{.*}}precomp-invalid.obj' [LNK4099]
-FAILURE-NEXT: failed to load reference '{{.*}}precomp.obj': The signature does not match; the file(s) might be out of date.
+FAILURE-NEXT: failed to load reference '{{.*}}precomp.obj': No matching precompiled header could be located.
FAILURE-MISSING-PRECOMPOBJ: warning: Cannot use debug info for '{{.*}}precomp-a.obj' [LNK4099]
-FAILURE-MISSING-PRECOMPOBJ-NEXT: failed to load reference '{{.*}}precomp.obj': The path to this file must be provided on the command-line
+FAILURE-MISSING-PRECOMPOBJ-NEXT: failed to load reference '{{.*}}precomp.obj': No matching precompiled header could be located.
CHECK: Types (TPI Stream)
CHECK-NOT: LF_PRECOMP