Index: COFF/Driver.cpp =================================================================== --- COFF/Driver.cpp +++ COFF/Driver.cpp @@ -1604,10 +1604,15 @@ 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))) { + // In MinGW, if no symbols are chosen to be exported, then all symbols are + // automatically exported by default. This behavior can be forced by the + // -export-all-symbols option, so that it happens even when exports are + // explicitly specified. The automatic behavior can be disabled using the + // -exclude-all-symbols option, so that lld-link behaves like link.exe rather + // than MinGW in the case that nothing is explicitly exported. + if (Config->MinGW && Config->DLL && + ((Config->Exports.empty() && !Args.hasArg(OPT_exclude_all_symbols)) || + Args.hasArg(OPT_export_all_symbols))) { Exporter.initSymbolExcludes(); Symtab->forEachSymbol([=](Symbol *S) { Index: COFF/Options.td =================================================================== --- COFF/Options.td +++ COFF/Options.td @@ -150,6 +150,7 @@ def help_q : Flag<["/?", "-?"], "">, Alias; // LLD extensions +def exclude_all_symbols : F<"exclude-all-symbols">; def export_all_symbols : F<"export-all-symbols">; def kill_at : F<"kill-at">; def lldmingw : F<"lldmingw">; Index: MinGW/Driver.cpp =================================================================== --- MinGW/Driver.cpp +++ MinGW/Driver.cpp @@ -176,6 +176,8 @@ Add("-dll"); if (Args.hasArg(OPT_verbose)) Add("-verbose"); + if (Args.hasArg(OPT_exclude_all_symbols)) + Add("-exclude-all-symbols"); if (Args.hasArg(OPT_export_all_symbols)) Add("-export-all-symbols"); if (Args.hasArg(OPT_large_address_aware)) Index: MinGW/Options.td =================================================================== --- MinGW/Options.td +++ MinGW/Options.td @@ -11,6 +11,8 @@ def dynamicbase: F<"dynamicbase">, HelpText<"Enable ASLR">; def entry: S<"entry">, MetaVarName<"">, HelpText<"Name of entry point symbol">; +def exclude_all_symbols: F<"exclude-all-symbols">, + HelpText<"Don't automatically export any symbols">; def export_all_symbols: F<"export-all-symbols">, HelpText<"Export all symbols even if a def file or dllexport attributes are used">; def gc_sections: F<"gc-sections">, HelpText<"Remove unused sections">; Index: test/COFF/exclude-all.s =================================================================== --- /dev/null +++ test/COFF/exclude-all.s @@ -0,0 +1,31 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -triple=i686-windows-gnu %s -filetype=obj -o %t.obj + +# RUN: lld-link -lldmingw -exclude-all-symbols -dll -out:%t.dll -entry:DllMainCRTStartup@12 %t.obj +# RUN: llvm-readobj -coff-exports %t.dll | FileCheck %s -check-prefix=NO-EXPORTS + +# NO-EXPORTS-NOT: Name: + +.global _foobar +.global _DllMainCRTStartup@12 +.global _dataSym +.text +_DllMainCRTStartup@12: + ret +_foobar: + ret +.data +_dataSym: + .int 4 + +# Test specifying -exclude-all-symbols, on an object file that contains +# dllexport directive for some of the symbols. In this case, the dllexported +# symbols are still exported. + +# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj +# +# RUN: lld-link -out:%t.dll -dll %t.obj -lldmingw -exclude-all-symbols -output-def:%t.def +# RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix=DLLEXPORT %s + +# DLLEXPORT: Name: exportfn3 Index: test/MinGW/driver.test =================================================================== --- test/MinGW/driver.test +++ test/MinGW/driver.test @@ -74,6 +74,9 @@ RUN: ld.lld -### -m i386pep foo.o | FileCheck -check-prefix MINGW-FLAG %s MINGW-FLAG: -lldmingw +RUN: ld.lld -### -m i386pep foo.o --exclude-all-symbols | FileCheck -check-prefix EXCLUDE-ALL %s +EXCLUDE-ALL: -exclude-all-symbols + RUN: ld.lld -### -m i386pep foo.o --export-all-symbols | FileCheck -check-prefix EXPORT-ALL %s EXPORT-ALL: -export-all-symbols