[lld] r313123 - [COFF] Add support for the -wholearchive option

Martin Storsjo via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 13 00:28:04 PDT 2017


Author: mstorsjo
Date: Wed Sep 13 00:28:03 2017
New Revision: 313123

URL: http://llvm.org/viewvc/llvm-project?rev=313123&view=rev
Log:
[COFF] Add support for the -wholearchive option

This fixes PR31824.

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

Added:
    lld/trunk/test/COFF/wholearchive.s
Modified:
    lld/trunk/COFF/Driver.cpp
    lld/trunk/COFF/Driver.h
    lld/trunk/COFF/Options.td

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=313123&r1=313122&r2=313123&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Wed Sep 13 00:28:03 2017
@@ -110,7 +110,8 @@ MemoryBufferRef LinkerDriver::takeBuffer
   return MBRef;
 }
 
-void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> MB) {
+void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> MB,
+                             bool WholeArchive) {
   MemoryBufferRef MBRef = takeBuffer(std::move(MB));
 
   // File type is detected by contents, not by file extension.
@@ -121,10 +122,24 @@ void LinkerDriver::addBuffer(std::unique
   }
 
   FilePaths.push_back(MBRef.getBufferIdentifier());
-  if (Magic == file_magic::archive)
-    return Symtab->addFile(make<ArchiveFile>(MBRef));
-  if (Magic == file_magic::bitcode)
-    return Symtab->addFile(make<BitcodeFile>(MBRef));
+  if (Magic == file_magic::archive) {
+    if (WholeArchive) {
+      std::unique_ptr<Archive> File =
+          check(Archive::create(MBRef),
+                MBRef.getBufferIdentifier() + ": failed to parse archive");
+
+      for (MemoryBufferRef M : getArchiveMembers(File.get()))
+        addArchiveBuffer(M, "<whole-archive>", MBRef.getBufferIdentifier());
+      return;
+    }
+    Symtab->addFile(make<ArchiveFile>(MBRef));
+    return;
+  }
+
+  if (Magic == file_magic::bitcode) {
+    Symtab->addFile(make<BitcodeFile>(MBRef));
+    return;
+  }
 
   if (Magic == file_magic::coff_cl_gl_object)
     error(MBRef.getBufferIdentifier() + ": is not a native COFF file. "
@@ -133,7 +148,7 @@ void LinkerDriver::addBuffer(std::unique
     Symtab->addFile(make<ObjFile>(MBRef));
 }
 
-void LinkerDriver::enqueuePath(StringRef Path) {
+void LinkerDriver::enqueuePath(StringRef Path, bool WholeArchive) {
   auto Future =
       std::make_shared<std::future<MBErrPair>>(createFutureForFile(Path));
   std::string PathStr = Path;
@@ -142,7 +157,7 @@ void LinkerDriver::enqueuePath(StringRef
     if (MBOrErr.second)
       error("could not open " + PathStr + ": " + MBOrErr.second.message());
     else
-      Driver->addBuffer(std::move(MBOrErr.first));
+      Driver->addBuffer(std::move(MBOrErr.first), WholeArchive);
   });
 }
 
@@ -215,7 +230,7 @@ void LinkerDriver::parseDirectives(Strin
       break;
     case OPT_defaultlib:
       if (Optional<StringRef> Path = findLib(Arg->getValue()))
-        enqueuePath(*Path);
+        enqueuePath(*Path, false);
       break;
     case OPT_export: {
       Export E = parseExport(Arg->getValue());
@@ -953,19 +968,29 @@ void LinkerDriver::link(ArrayRef<const c
   if (ErrorCount)
     return;
 
+  bool WholeArchiveFlag = Args.hasArg(OPT_wholearchive_flag);
   // Create a list of input files. Files can be given as arguments
   // for /defaultlib option.
   std::vector<MemoryBufferRef> MBs;
-  for (auto *Arg : Args.filtered(OPT_INPUT))
-    if (Optional<StringRef> Path = findFile(Arg->getValue()))
-      enqueuePath(*Path);
+  for (auto *Arg : Args.filtered(OPT_INPUT, OPT_wholearchive_file)) {
+    switch (Arg->getOption().getID()) {
+    case OPT_INPUT:
+      if (Optional<StringRef> Path = findFile(Arg->getValue()))
+        enqueuePath(*Path, WholeArchiveFlag);
+      break;
+    case OPT_wholearchive_file:
+      if (Optional<StringRef> Path = findFile(Arg->getValue()))
+        enqueuePath(*Path, true);
+      break;
+    }
+  }
   for (auto *Arg : Args.filtered(OPT_defaultlib))
     if (Optional<StringRef> Path = findLib(Arg->getValue()))
-      enqueuePath(*Path);
+      enqueuePath(*Path, false);
 
   // Windows specific -- Create a resource file containing a manifest file.
   if (Config->Manifest == Configuration::Embed)
-    addBuffer(createManifestRes());
+    addBuffer(createManifestRes(), false);
 
   // Read all input files given via the command line.
   run();
@@ -981,7 +1006,7 @@ void LinkerDriver::link(ArrayRef<const c
   // WindowsResource to convert resource files to a regular COFF file,
   // then link the resulting file normally.
   if (!Resources.empty())
-    addBuffer(convertResToCOFF(Resources));
+    addBuffer(convertResToCOFF(Resources), false);
 
   if (Tar)
     Tar->append("response.txt",

Modified: lld/trunk/COFF/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.h?rev=313123&r1=313122&r2=313123&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.h (original)
+++ lld/trunk/COFF/Driver.h Wed Sep 13 00:28:03 2017
@@ -110,11 +110,11 @@ private:
   void invokeMSVC(llvm::opt::InputArgList &Args);
 
   MemoryBufferRef takeBuffer(std::unique_ptr<MemoryBuffer> MB);
-  void addBuffer(std::unique_ptr<MemoryBuffer> MB);
+  void addBuffer(std::unique_ptr<MemoryBuffer> MB, bool WholeArchive);
   void addArchiveBuffer(MemoryBufferRef MBRef, StringRef SymName,
                         StringRef ParentName);
 
-  void enqueuePath(StringRef Path);
+  void enqueuePath(StringRef Path, bool WholeArchive);
 
   void enqueueTask(std::function<void()> Task);
   bool run();

Modified: lld/trunk/COFF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Options.td?rev=313123&r1=313122&r2=313123&view=diff
==============================================================================
--- lld/trunk/COFF/Options.td (original)
+++ lld/trunk/COFF/Options.td Wed Sep 13 00:28:03 2017
@@ -47,6 +47,7 @@ def stack   : P<"stack", "Size of the st
 def stub    : P<"stub", "Specify DOS stub file">;
 def subsystem : P<"subsystem", "Specify subsystem">;
 def version : P<"version", "Specify a version number in the PE header">;
+def wholearchive_file : P<"wholearchive", "Include all object files from this archive">;
 
 def disallowlib : Joined<["/", "-", "-?"], "disallowlib:">, Alias<nodefaultlib>;
 
@@ -78,6 +79,7 @@ def profile : F<"profile">;
 def swaprun_cd : F<"swaprun:cd">;
 def swaprun_net : F<"swaprun:net">;
 def verbose : F<"verbose">;
+def wholearchive_flag : F<"wholearchive">;
 
 def force : F<"force">,
     HelpText<"Allow undefined symbols when creating executables">;

Added: lld/trunk/test/COFF/wholearchive.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/wholearchive.s?rev=313123&view=auto
==============================================================================
--- lld/trunk/test/COFF/wholearchive.s (added)
+++ lld/trunk/test/COFF/wholearchive.s Wed Sep 13 00:28:03 2017
@@ -0,0 +1,19 @@
+# REQEUIRES: x86
+
+# RUN: yaml2obj < %p/Inputs/export.yaml > %t.archive.obj
+# RUN: llvm-ar rcs %t.archive.lib %t.archive.obj
+# RUN: llvm-mc -triple=x86_64-windows-msvc %s -filetype=obj -o %t.main.obj
+
+# RUN: lld-link -dll -out:%t.dll -entry:main %t.main.obj -wholearchive:%t.archive.lib -implib:%t.lib
+# RUN: llvm-readobj %t.lib | FileCheck %s -check-prefix CHECK-IMPLIB
+
+# RUN: lld-link -dll -out:%t.dll -entry:main %t.main.obj -wholearchive %t.archive.lib -implib:%t.lib
+# RUN: llvm-readobj %t.lib | FileCheck %s -check-prefix CHECK-IMPLIB
+
+# CHECK-IMPLIB: Symbol: __imp_exportfn3
+# CHECK-IMPLIB: Symbol: exportfn3
+
+.global main
+.text
+main:
+  ret




More information about the llvm-commits mailing list