[lld] r315562 - [COFF] Add support for automatically exporting all symbols

Martin Storsjo via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 11 22:37:13 PDT 2017


Author: mstorsjo
Date: Wed Oct 11 22:37:13 2017
New Revision: 315562

URL: http://llvm.org/viewvc/llvm-project?rev=315562&view=rev
Log:
[COFF] Add support for automatically exporting all symbols

GNU ld automatically exports all symbols if no symbols have
been chosen to export via either def files or dllexport attributes.
The same behaviour can also be enabled via the GNU ld option
--export-all-symbols, in case some symbols are marked for export
via a def file or dllexport attribute.

The list of excluded symbols is from GNU ld, minus the
cygwin specific symbols.

Also add support for outputting the actual list of exported
symbols in a def file, as in the GNU ld option --output-def.

These options in GNU ld are documented in
https://sourceware.org/binutils/docs/ld/WIN32.html.

This currently exports all symbols from object files pulled in
from libmingw32 and libmingwex and other static libraries
that are linked in.

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

Added:
    lld/trunk/test/COFF/export-all.s
Modified:
    lld/trunk/COFF/Driver.cpp
    lld/trunk/COFF/Options.td

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=315562&r1=315561&r2=315562&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Wed Oct 11 22:37:13 2017
@@ -547,6 +547,63 @@ static void parseModuleDefs(StringRef Pa
   }
 }
 
+// Get a sorted list of symbols not to automatically export
+// when exporting all global symbols for MinGW.
+static StringSet<> getExportExcludeSymbols() {
+  if (Config->Machine == I386)
+    return {
+        "__NULL_IMPORT_DESCRIPTOR",
+        "__pei386_runtime_relocator",
+        "_do_pseudo_reloc",
+       "_impure_ptr",
+        "__impure_ptr",
+        "__fmode",
+        "_environ",
+        "___dso_handle",
+        // These are the MinGW names that differ from the standard
+        // ones (lacking an extra underscore).
+        "_DllMain at 12",
+        "_DllEntryPoint at 12",
+        "_DllMainCRTStartup at 12",
+    };
+
+  return {
+      "_NULL_IMPORT_DESCRIPTOR",
+      "_pei386_runtime_relocator",
+      "do_pseudo_reloc",
+      "impure_ptr",
+      "_impure_ptr",
+      "_fmode",
+      "environ",
+      "__dso_handle",
+      // These are the MinGW names that differ from the standard
+      // ones (lacking an extra underscore).
+      "DllMain",
+      "DllEntryPoint",
+      "DllMainCRTStartup",
+  };
+}
+
+// This is MinGW specific.
+static void writeDefFile(StringRef Name) {
+  std::error_code EC;
+  raw_fd_ostream OS(Name, EC, sys::fs::F_None);
+  if (EC)
+    fatal("cannot open " + Name + ": " + EC.message());
+
+  OS << "EXPORTS\n";
+  for (Export &E : Config->Exports) {
+    OS << "    " << E.ExportName << " "
+       << "@" << E.Ordinal;
+    if (auto *Def = dyn_cast_or_null<Defined>(E.Sym)) {
+      if (Def && Def->getChunk() &&
+          !(Def->getChunk()->getPermissions() & IMAGE_SCN_MEM_EXECUTE))
+        OS << " DATA";
+    }
+    OS << "\n";
+  }
+}
+
 // A helper function for filterBitcodeFiles.
 static bool needsRebuilding(MemoryBufferRef MB) {
   // The MSVC linker doesn't support thin archives, so if it's a thin
@@ -1197,6 +1254,25 @@ void LinkerDriver::link(ArrayRef<const c
       return;
   }
 
+  // In MinGW, all symbols are automatically exported if no symbols
+  // are chosen to be exported.
+  if (Config->DLL && ((Config->MinGW && Config->Exports.empty()) ||
+                      Args.hasArg(OPT_export_all_symbols))) {
+    StringSet<> ExcludeSymbols = getExportExcludeSymbols();
+
+    Symtab->forEachSymbol([=](Symbol *S) {
+      auto *Def = dyn_cast<Defined>(S->body());
+      if (!Def || !Def->isLive() || !Def->getChunk())
+        return;
+      if (ExcludeSymbols.count(Def->getName()))
+        return;
+      Export E;
+      E.Name = Def->getName();
+      E.Sym = Def;
+      Config->Exports.push_back(E);
+    });
+  }
+
   // Windows specific -- when we are creating a .dll file, we also
   // need to create a .lib file.
   if (!Config->Exports.empty() || Config->DLL) {
@@ -1205,6 +1281,10 @@ void LinkerDriver::link(ArrayRef<const c
     assignExportOrdinals();
   }
 
+  // Handle /output-def (MinGW specific).
+  if (auto *Arg = Args.getLastArg(OPT_output_def))
+    writeDefFile(Arg->getValue());
+
   // Set extra alignment for .comm symbols
   for (auto Pair : Config->AlignComm) {
     StringRef Name = Pair.first;

Modified: lld/trunk/COFF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Options.td?rev=315562&r1=315561&r2=315562&view=diff
==============================================================================
--- lld/trunk/COFF/Options.td (original)
+++ lld/trunk/COFF/Options.td Wed Oct 11 22:37:13 2017
@@ -102,10 +102,12 @@ def help : F<"help">;
 def help_q : Flag<["/?", "-?"], "">, Alias<help>;
 
 // LLD extensions
+def export_all_symbols : F<"export-all-symbols">;
 def nopdb : F<"nopdb">, HelpText<"Disable PDB generation for DWARF users">;
 def nosymtab : F<"nosymtab">;
 def lldmingw : F<"lldmingw">;
 def msvclto : F<"msvclto">;
+def output_def : Joined<["/", "-"], "output-def:">;
 def rsp_quoting : Joined<["--"], "rsp-quoting=">,
   HelpText<"Quoting style for response files, 'windows' (default) or 'posix'">;
 

Added: lld/trunk/test/COFF/export-all.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/export-all.s?rev=315562&view=auto
==============================================================================
--- lld/trunk/test/COFF/export-all.s (added)
+++ lld/trunk/test/COFF/export-all.s Wed Oct 11 22:37:13 2017
@@ -0,0 +1,38 @@
+# REQEUIRES: x86
+
+# RUN: llvm-mc -triple=i686-windows-gnu %s -filetype=obj -o %t.obj
+
+# RUN: lld-link -lldmingw -dll -out:%t.dll -entry:DllMainCRTStartup at 12 %t.obj -implib:%t.lib
+# RUN: llvm-readobj -coff-exports %t.dll | FileCheck %s
+
+# CHECK-NOT: Name: DllMainCRTStartup
+# CHECK: Name: foobar
+
+.global _foobar
+.global _DllMainCRTStartup at 12
+.text
+_DllMainCRTStartup at 12:
+  ret
+_foobar:
+  ret
+
+# Test specifying -export-all-symbols, on an object file that contains axi
+# dllexport directive for some of the symbols.
+
+# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj
+#
+# RUN: lld-link -out:%t.dll -dll %t.obj -lldmingw -export-all-symbols -output-def:%t.def
+# RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix=CHECK2 %s
+# RUN: cat %t.def | FileCheck -check-prefix=CHECK2-DEF %s
+
+# Note, this will actually export _DllMainCRTStartup as well, since
+# it uses the standard spelling in this object file, not the MinGW one.
+
+# CHECK2: Name: exportfn1
+# CHECK2: Name: exportfn2
+# CHECK2: Name: exportfn3
+
+# CHECK2-DEF: EXPORTS
+# CHECK2-DEF: exportfn1 @3
+# CHECK2-DEF: exportfn2 @4
+# CHECK2-DEF: exportfn3 @5




More information about the llvm-commits mailing list