[COFF] Allow exporting all symbols from system libraries specfied with -wholearchive:
authorMartin Storsjo <martin@martin.st>
Tue, 4 Sep 2018 20:56:56 +0000 (20:56 +0000)
committerMartin Storsjo <martin@martin.st>
Tue, 4 Sep 2018 20:56:56 +0000 (20:56 +0000)
When building a shared libc++.dll, it pulls in libc++abi.a statically
with the --wholearchive flag. If such a build is done with
--export-all-symbols, it's reasonable to assume that everything
from that library also should be exported with the same rules as normal
local object files, even though we normally avoid autoexporting things
from libc++abi.a in other cases when linking a DLL (user code).

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

llvm-svn: 341403

lld/COFF/Driver.cpp
lld/COFF/MinGW.cpp
lld/COFF/MinGW.h
lld/test/COFF/export-all.s

index 5a0ce05..0584c74 100644 (file)
@@ -1198,10 +1198,14 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
     return;
 
   std::set<sys::fs::UniqueID> WholeArchives;
-  for (auto *Arg : Args.filtered(OPT_wholearchive_file))
-    if (Optional<StringRef> Path = doFindFile(Arg->getValue()))
+  AutoExporter Exporter;
+  for (auto *Arg : Args.filtered(OPT_wholearchive_file)) {
+    if (Optional<StringRef> Path = doFindFile(Arg->getValue())) {
       if (Optional<sys::fs::UniqueID> ID = getUniqueID(*Path))
         WholeArchives.insert(*ID);
+      Exporter.addWholeArchive(*Path);
+    }
+  }
 
   // A predicate returning true if a given path is an argument for
   // /wholearchive:, or /wholearchive is enabled globally.
@@ -1458,7 +1462,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
   // are chosen to be exported.
   if (Config->DLL && ((Config->MinGW && Config->Exports.empty()) ||
                       Args.hasArg(OPT_export_all_symbols))) {
-    AutoExporter Exporter;
+    Exporter.initSymbolExcludes();
 
     Symtab->forEachSymbol([=](Symbol *S) {
       auto *Def = dyn_cast<Defined>(S);
index 0584f60..640c2e4 100644 (file)
@@ -19,7 +19,7 @@ using namespace lld::coff;
 using namespace llvm;
 using namespace llvm::COFF;
 
-AutoExporter::AutoExporter() {
+void AutoExporter::initSymbolExcludes() {
   if (Config->Machine == I386) {
     ExcludeSymbols = {
         "__NULL_IMPORT_DESCRIPTOR",
@@ -53,7 +53,9 @@ AutoExporter::AutoExporter() {
         "DllMainCRTStartup",
     };
   }
+}
 
+AutoExporter::AutoExporter() {
   ExcludeLibs = {
       "libgcc",
       "libgcc_s",
@@ -90,6 +92,13 @@ AutoExporter::AutoExporter() {
   };
 }
 
+void AutoExporter::addWholeArchive(StringRef Path) {
+  StringRef LibName = sys::path::filename(Path);
+  // Drop the file extension, to match the processing below.
+  LibName = LibName.substr(0, LibName.rfind('.'));
+  ExcludeLibs.erase(LibName);
+}
+
 bool AutoExporter::shouldExport(Defined *Sym) const {
   if (!Sym || !Sym->isLive() || !Sym->getChunk())
     return false;
index fe6cc55..6511b64 100644 (file)
@@ -23,6 +23,10 @@ class AutoExporter {
 public:
   AutoExporter();
 
+  void initSymbolExcludes();
+
+  void addWholeArchive(StringRef Path);
+
   llvm::StringSet<> ExcludeSymbols;
   llvm::StringSet<> ExcludeLibs;
   llvm::StringSet<> ExcludeObjects;
index 9ec5fd1..3d80603 100644 (file)
@@ -77,6 +77,18 @@ __imp__unexported:
 # CHECK-EXCLUDE-NEXT: foobar @1
 # CHECK-EXCLUDE-NEXT: EOF
 
+# Test that libraries included with -wholearchive: are autoexported, even if
+# they are in a library that otherwise normally would be excluded.
+
+# RUN: lld-link -out:%t.dll -dll -entry:DllMainCRTStartup %t.main.obj -lldmingw %T/libs/crt2.o -wholearchive:%T/libs/libmingwex.a -output-def:%t.def
+# RUN: echo "EOF" >> %t.def
+# RUN: cat %t.def | FileCheck -check-prefix=CHECK-WHOLEARCHIVE %s
+
+# CHECK-WHOLEARCHIVE: EXPORTS
+# CHECK-WHOLEARCHIVE-NEXT: foobar @1
+# CHECK-WHOLEARCHIVE-NEXT: mingwfunc @2
+# CHECK-WHOLEARCHIVE-NEXT: EOF
+
 # Test that we handle import libraries together with -opt:noref.
 
 # RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj