[COFF] Don't do autoexport of symbols from GNU import libraries

This involves adding more generic list of symbol suffixes/prefixes
to ignore for autoexport; adding a few other entries to these lists
as well from the corresponding lists in binutils.

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

git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@343070 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/COFF/MinGW.cpp b/COFF/MinGW.cpp
index cc2f6fb..505a134 100644
--- a/COFF/MinGW.cpp
+++ b/COFF/MinGW.cpp
@@ -20,6 +20,22 @@
 using namespace llvm::COFF;
 
 void AutoExporter::initSymbolExcludes() {
+  ExcludeSymbolPrefixes = {
+      // Import symbols
+      "__imp_",
+      "__IMPORT_DESCRIPTOR_",
+      // Extra import symbols from GNU import libraries
+      "__nm_",
+      // C++ symbols
+      "__rtti_",
+      "__builtin_",
+      // Artifical symbols such as .refptr
+      ".",
+  };
+  ExcludeSymbolSuffixes = {
+      "_iname",
+      "_NULL_THUNK_DATA",
+  };
   if (Config->Machine == I386) {
     ExcludeSymbols = {
         "__NULL_IMPORT_DESCRIPTOR",
@@ -36,6 +52,7 @@
         "_DllEntryPoint@12",
         "_DllMainCRTStartup@12",
     };
+    ExcludeSymbolPrefixes.insert("__head_");
   } else {
     ExcludeSymbols = {
         "__NULL_IMPORT_DESCRIPTOR",
@@ -52,6 +69,7 @@
         "DllEntryPoint",
         "DllMainCRTStartup",
     };
+    ExcludeSymbolPrefixes.insert("_head_");
   }
 }
 
@@ -110,11 +128,12 @@
   if (ExcludeSymbols.count(Sym->getName()))
     return false;
 
-  // Don't export anything that looks like an import symbol (which also can be
-  // a manually defined data symbol with such a name); don't export artificial
-  // symbols like .refptr pointer stubs.
-  if (Sym->getName().startswith("__imp_") || Sym->getName().startswith("."))
-    return false;
+  for (StringRef Prefix : ExcludeSymbolPrefixes.keys())
+    if (Sym->getName().startswith(Prefix))
+      return false;
+  for (StringRef Suffix : ExcludeSymbolSuffixes.keys())
+    if (Sym->getName().endswith(Suffix))
+      return false;
 
   // If a corresponding __imp_ symbol exists and is defined, don't export it.
   if (Symtab->find(("__imp_" + Sym->getName()).str()))
diff --git a/COFF/MinGW.h b/COFF/MinGW.h
index 6511b64..f9c5e3e 100644
--- a/COFF/MinGW.h
+++ b/COFF/MinGW.h
@@ -28,6 +28,8 @@
   void addWholeArchive(StringRef Path);
 
   llvm::StringSet<> ExcludeSymbols;
+  llvm::StringSet<> ExcludeSymbolPrefixes;
+  llvm::StringSet<> ExcludeSymbolSuffixes;
   llvm::StringSet<> ExcludeLibs;
   llvm::StringSet<> ExcludeObjects;
 
diff --git a/test/COFF/imports-gnu-autoexport.s b/test/COFF/imports-gnu-autoexport.s
new file mode 100644
index 0000000..8c204e1
--- /dev/null
+++ b/test/COFF/imports-gnu-autoexport.s
@@ -0,0 +1,25 @@
+# REQUIRES: x86
+#
+# RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-head.s -filetype=obj -o %t-dabcdh.o
+# RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-func.s -filetype=obj -o %t-dabcds00000.o
+# RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-tail.s -filetype=obj -o %t-dabcdt.o
+# RUN: rm -f %t-implib.a
+# RUN: llvm-ar rcs %t-implib.a %t-dabcdh.o %t-dabcds00000.o %t-dabcdt.o
+# RUN: lld-link -lldmingw -dll -out:%t.dll -entry:main -subsystem:console \
+# RUN:   %p/Inputs/hello64.obj %p/Inputs/std64.lib %t-implib.a -include:func
+# RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix=EXPORT %s
+
+# Check that only the single normal symbol was exported, none of the symbols
+# from the import library.
+
+EXPORT:      Export {
+EXPORT-NEXT:   Ordinal: 0
+EXPORT-NEXT:   Name:
+EXPORT-NEXT:   RVA: 0x0
+EXPORT-NEXT: }
+EXPORT-NEXT: Export {
+EXPORT-NEXT:   Ordinal: 1
+EXPORT-NEXT:   Name: main
+EXPORT-NEXT:   RVA: 0x1010
+EXPORT-NEXT: }
+EXPORT-NEXT-EMPTY: