[lld] fd9962e - [COFF] Add vfsoverlay flag

Alex Brachet via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 11 14:32:11 PDT 2022


Author: Alex Brachet
Date: 2022-07-11T21:31:01Z
New Revision: fd9962e75d8935a042f1ae1e1647e115f4a632fb

URL: https://github.com/llvm/llvm-project/commit/fd9962e75d8935a042f1ae1e1647e115f4a632fb
DIFF: https://github.com/llvm/llvm-project/commit/fd9962e75d8935a042f1ae1e1647e115f4a632fb.diff

LOG: [COFF] Add vfsoverlay flag

This patch adds a new flag vfsoverlay similar to clang’s
ivfsoverlay flag. This is helpful when compiling on case
sensitive file systems when cross compiling to Windows.
Particularly when compiling third party code containing
\#pragma comment(“linker”, “/defaultlib:...”) which
can’t be easily changed.

Differential Revision: https://reviews.llvm.org/D125800

Added: 
    lld/test/COFF/vfsoverlay.test

Modified: 
    lld/COFF/Config.h
    lld/COFF/Driver.cpp
    lld/COFF/Options.td

Removed: 
    


################################################################################
diff  --git a/lld/COFF/Config.h b/lld/COFF/Config.h
index 8edb545cd653e..dd089f5ab6714 100644
--- a/lld/COFF/Config.h
+++ b/lld/COFF/Config.h
@@ -15,6 +15,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Object/COFF.h"
 #include "llvm/Support/CachePruning.h"
+#include "llvm/Support/VirtualFileSystem.h"
 #include <cstdint>
 #include <map>
 #include <set>
@@ -238,6 +239,9 @@ struct Configuration {
   // Used for /print-symbol-order:
   StringRef printSymbolOrder;
 
+  // Used for /vfsoverlay:
+  std::unique_ptr<llvm::vfs::FileSystem> vfs;
+
   uint64_t align = 4096;
   uint64_t imageBase = -1;
   uint64_t fileAlign = 512;

diff  --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index ffa900d42f2de..155e4ca6ee3fe 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -436,17 +436,26 @@ void LinkerDriver::parseDirectives(InputFile *file) {
 // Find file from search paths. You can omit ".obj", this function takes
 // care of that. Note that the returned path is not guaranteed to exist.
 StringRef LinkerDriver::doFindFile(StringRef filename) {
+  auto getFilename = [](StringRef filename) -> StringRef {
+    if (config->vfs)
+      if (auto statOrErr = config->vfs->status(filename))
+        return saver().save(statOrErr->getName());
+    return filename;
+  };
+
   bool hasPathSep = (filename.find_first_of("/\\") != StringRef::npos);
   if (hasPathSep)
-    return filename;
+    return getFilename(filename);
   bool hasExt = filename.contains('.');
   for (StringRef dir : searchPaths) {
     SmallString<128> path = dir;
     sys::path::append(path, filename);
+    path = SmallString<128>{getFilename(path.str())};
     if (sys::fs::exists(path.str()))
       return saver().save(path.str());
     if (!hasExt) {
       path.append(".obj");
+      path = SmallString<128>{getFilename(path.str())};
       if (sys::fs::exists(path.str()))
         return saver().save(path.str());
     }
@@ -1349,6 +1358,28 @@ Optional<std::string> getReproduceFile(const opt::InputArgList &args) {
   return None;
 }
 
+static std::unique_ptr<llvm::vfs::FileSystem>
+getVFS(const opt::InputArgList &args) {
+  using namespace llvm::vfs;
+
+  const opt::Arg *arg = args.getLastArg(OPT_vfsoverlay);
+  if (!arg)
+    return nullptr;
+
+  auto bufOrErr = llvm::MemoryBuffer::getFile(arg->getValue());
+  if (!bufOrErr) {
+    checkError(errorCodeToError(bufOrErr.getError()));
+    return nullptr;
+  }
+
+  if (auto ret = vfs::getVFSFromYAML(std::move(*bufOrErr), /*DiagHandler*/ nullptr,
+                             arg->getValue()))
+    return ret;
+
+  error("Invalid vfs overlay");
+  return nullptr;
+}
+
 void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   ScopedTimer rootTimer(ctx.rootTimer);
 
@@ -1390,6 +1421,8 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
     errorHandler().errorLimit = n;
   }
 
+  config->vfs = getVFS(args);
+
   // Handle /help
   if (args.hasArg(OPT_help)) {
     printHelp(argsArr[0]);

diff  --git a/lld/COFF/Options.td b/lld/COFF/Options.td
index 9f29ea0d523a7..5135f4ea34af6 100644
--- a/lld/COFF/Options.td
+++ b/lld/COFF/Options.td
@@ -278,6 +278,8 @@ def print_symbol_order: P<
     "/call-graph-profile-sort into the specified file">;
 def wrap : P_priv<"wrap">;
 
+def vfsoverlay : P<"vfsoverlay", "Path to a vfsoverlay yaml file to optionally look for /defaultlib's in">;
+
 // Flags for debugging
 def lldmap : F<"lldmap">;
 def lldmap_file : P_priv<"lldmap">;

diff  --git a/lld/test/COFF/vfsoverlay.test b/lld/test/COFF/vfsoverlay.test
new file mode 100644
index 0000000000000..0168ccbce1d29
--- /dev/null
+++ b/lld/test/COFF/vfsoverlay.test
@@ -0,0 +1,33 @@
+# RUN: rm -rf %t
+# RUN: split-file %s %t
+# RUN: cp %p/Inputs/std64.lib %t/std64.lib
+# RUN: sed -e "s|REPLACE|%/t/std64.lib|g" %t/overlay.yaml.in > %t/overlay.yaml
+
+# RUN: lld-link %S/Inputs/hello64.obj /libpath:/noexist /out:%t.exe /entry:main /defaultlib:notstd64 /vfsoverlay:%t/overlay.yaml
+
+# RUN: not lld-link %S/Inputs/hello64.obj /libpath:/noexist /out:%t.exe /entry:main /defaultlib:notstd64 /vfsoverlay:noexist 2>&1 \
+# RUN:   | FileCheck %s
+# CHECK: error: No such file or directory
+
+# RUN: sed -e "s|{|bad|g" %t/overlay.yaml > %t/badoverlay.yaml
+# RUN: not lld-link %S/Inputs/hello64.obj /libpath:/noexist /out:%t.exe /entry:main /defaultlib:notstd64 /vfsoverlay:%t/badoverlay.yaml 2>&1 \
+# RUN:   | FileCheck %s --check-prefix=BAD-OVERLAY
+# BAD-OVERLAY: error: Invalid vfs overlay
+
+#--- overlay.yaml.in
+{
+  'version': 0,
+  'roots' : [
+    {
+      'name': '/noexist',
+      'type': 'directory',
+      'contents': [
+        {
+          'name': 'notstd64.lib',
+          'type': 'file',
+          'external-contents': 'REPLACE'
+        }
+      ]
+    }
+  ]
+}


        


More information about the llvm-commits mailing list