[PATCH] D66431: [PDB] Fix bug when using multiple PCH header objects with the same name.

Zachary Turner via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 19 11:03:34 PDT 2019


zturner created this revision.
zturner added reviewers: rnk, aganea.
Herald added a project: LLVM.

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).


https://reviews.llvm.org/D66431

Files:
  lld/COFF/PDB.cpp
  lld/test/COFF/Inputs/precompa/precomp.obj
  lld/test/COFF/Inputs/precompa/useprecomp.obj
  lld/test/COFF/Inputs/precompb/precomp.obj
  lld/test/COFF/Inputs/precompb/useprecomp.obj
  lld/test/COFF/precomp-link-samename.test


Index: lld/test/COFF/precomp-link-samename.test
===================================================================
--- /dev/null
+++ lld/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
Index: lld/COFF/PDB.cpp
===================================================================
--- lld/COFF/PDB.cpp
+++ lld/COFF/PDB.cpp
@@ -507,22 +507,19 @@
 }
 
 static bool equals_path(StringRef path1, StringRef path2) {
+    SmallString<128> path1_norm = sys::path::convert_to_slash(path1);
+    SmallString<128> path2_norm = sys::path::convert_to_slash(path2);
 #if defined(_WIN32)
-  return path1.equals_lower(path2);
+    return StringRef(path1_norm).endswith_lower(path2_norm);
 #else
-  return path1.equals(path2);
+    return StringRef(path1_norm).endswith(path2_norm);
 #endif
 }
 
 // Find by name an OBJ provided on the command line
-static ObjFile *findObjByName(StringRef fileNameOnly) {
-  SmallString<128> currentPath;
-
+static ObjFile *findObjByName(StringRef filePath) {
   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 (equals_path(filePath, f->getName()))
       return f;
   }
   return nullptr;
@@ -559,7 +556,7 @@
 
   // 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 = findObjByName(precomp.getPrecompFilePath());
   if (!precompFile)
     return createFileError(
         precompFileName.str(),


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D66431.215950.patch
Type: text/x-patch
Size: 2807 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190819/c2fc3f27/attachment.bin>


More information about the llvm-commits mailing list