From 00d23d10dc48c6bb9d57ba96d4a748d85d77d0c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Wed, 17 Dec 2025 22:22:01 +0100 Subject: [PATCH] [LLD] [COFF] Fix implicit DLL entry point for MinGW (#171680) Previously, LLD would always set the implicit entry point for DLLs to the symbol that is prefixed with an underscore. However, mingw-w64 defines it without that underscore. This change fixes that by adding a special branch for MinGW. Also, it simplifies tests that use MinGW style DLL entry symbol by skipping the entry point argument. Note, tests that use MSVC style DLL entry symbol and LLD in MinGW mode, will now require using explicit entry point. I believe this is sensible. When an explicit entry point is passed, i.e. LLD is called by Clang or GCC, there will be no observable difference. Fixes https://github.com/llvm/llvm-project/issues/171441 (cherry picked from commit 2824225d27cc6706bf89408b1c8fda62ad3f0a3f) --- lld/COFF/Driver.cpp | 11 +++++++++-- lld/test/COFF/autoimport-arm-code.s | 2 +- lld/test/COFF/autoimport-arm-data.s | 2 +- lld/test/COFF/autoimport-arm64-code.s | 2 +- lld/test/COFF/autoimport-arm64-data.s | 2 +- lld/test/COFF/autoimport-debug.s | 2 +- lld/test/COFF/autoimport-gc.s | 2 +- lld/test/COFF/autoimport-lto.ll | 2 +- lld/test/COFF/autoimport-refptr.s | 2 +- lld/test/COFF/autoimport-x86.s | 2 +- lld/test/COFF/exclude-all.s | 4 ++-- lld/test/COFF/export-all.s | 8 ++++---- 12 files changed, 24 insertions(+), 17 deletions(-) diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 570b8f9d05906..24ae81f2ae7f7 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -1490,6 +1490,14 @@ getVFS(COFFLinkerContext &ctx, const opt::InputArgList &args) { return nullptr; } +static StringRef DllDefaultEntryPoint(MachineTypes machine, bool mingw) { + if (mingw) { + return (machine == I386) ? "_DllMainCRTStartup@12" : "DllMainCRTStartup"; + } else { + return (machine == I386) ? "__DllMainCRTStartup@12" : "_DllMainCRTStartup"; + } +} + constexpr const char *lldsaveTempsValues[] = { "resolution", "preopt", "promote", "internalize", "import", "opt", "precodegen", "prelink", "combinedindex"}; @@ -2378,8 +2386,7 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { symtab.entry = symtab.addGCRoot(symtab.mangle(arg->getValue()), true); } else if (!symtab.entry && !config->noEntry) { if (args.hasArg(OPT_dll)) { - StringRef s = (config->machine == I386) ? "__DllMainCRTStartup@12" - : "_DllMainCRTStartup"; + StringRef s = DllDefaultEntryPoint(config->machine, config->mingw); symtab.entry = symtab.addGCRoot(s, true); } else if (config->driverWdm) { // /driver:wdm implies /entry:_NtProcessStartup diff --git a/lld/test/COFF/autoimport-arm-code.s b/lld/test/COFF/autoimport-arm-code.s index 562a1a959e38b..8d7cc7f5cb019 100644 --- a/lld/test/COFF/autoimport-arm-code.s +++ b/lld/test/COFF/autoimport-arm-code.s @@ -2,7 +2,7 @@ # RUN: echo -e ".global variable\n.global DllMainCRTStartup\n.thumb\n.text\nDllMainCRTStartup:\nbx lr\n.data\nvariable:\n.long 42" > %t-lib.s # RUN: llvm-mc -triple=armv7-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj -# RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib +# RUN: lld-link -out:%t-lib.dll -dll %t-lib.obj -lldmingw -implib:%t-lib.lib # RUN: llvm-mc -triple=armv7-windows-gnu %s -filetype=obj -o %t.obj # RUN: not lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib 2>&1 | FileCheck %s diff --git a/lld/test/COFF/autoimport-arm-data.s b/lld/test/COFF/autoimport-arm-data.s index 82c66f0989d49..efc19f7f1865d 100644 --- a/lld/test/COFF/autoimport-arm-data.s +++ b/lld/test/COFF/autoimport-arm-data.s @@ -2,7 +2,7 @@ # RUN: echo -e ".global variable\n.global DllMainCRTStartup\n.thumb\n.text\nDllMainCRTStartup:\nbx lr\n.data\nvariable:\n.long 42" > %t-lib.s # RUN: llvm-mc -triple=armv7-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj -# RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib +# RUN: lld-link -out:%t-lib.dll -dll %t-lib.obj -lldmingw -implib:%t-lib.lib # RUN: llvm-mc -triple=armv7-windows-gnu %s -filetype=obj -o %t.obj # RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose diff --git a/lld/test/COFF/autoimport-arm64-code.s b/lld/test/COFF/autoimport-arm64-code.s index 9f5cc8f894255..b7cddf9bac040 100644 --- a/lld/test/COFF/autoimport-arm64-code.s +++ b/lld/test/COFF/autoimport-arm64-code.s @@ -2,7 +2,7 @@ # RUN: echo -e ".global variable\n.global DllMainCRTStartup\n.text\nDllMainCRTStartup:\nret\n.data\nvariable:\n.long 42" > %t-lib.s # RUN: llvm-mc -triple=aarch64-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj -# RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib +# RUN: lld-link -out:%t-lib.dll -dll %t-lib.obj -lldmingw -implib:%t-lib.lib # RUN: llvm-mc -triple=aarch64-windows-gnu %s -filetype=obj -o %t.obj # RUN: not lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib 2>&1 | FileCheck %s diff --git a/lld/test/COFF/autoimport-arm64-data.s b/lld/test/COFF/autoimport-arm64-data.s index 7934e2a969257..f3f16bc5210a4 100644 --- a/lld/test/COFF/autoimport-arm64-data.s +++ b/lld/test/COFF/autoimport-arm64-data.s @@ -2,7 +2,7 @@ # RUN: echo -e ".global variable\n.global DllMainCRTStartup\n.text\nDllMainCRTStartup:\nret\n.data\nvariable:\n.long 42" > %t-lib.s # RUN: llvm-mc -triple=aarch64-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj -# RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib +# RUN: lld-link -out:%t-lib.dll -dll %t-lib.obj -lldmingw -implib:%t-lib.lib # RUN: llvm-mc -triple=aarch64-windows-gnu %s -filetype=obj -o %t.obj # RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose diff --git a/lld/test/COFF/autoimport-debug.s b/lld/test/COFF/autoimport-debug.s index 1f31a2b9e554f..5865dac8d0d18 100644 --- a/lld/test/COFF/autoimport-debug.s +++ b/lld/test/COFF/autoimport-debug.s @@ -10,7 +10,7 @@ ## debug info. # RUN: llvm-mc -triple=x86_64-windows-gnu %t.dir/lib.s -filetype=obj -o %t.dir/lib.obj -# RUN: lld-link -out:%t.dir/lib.dll -dll -entry:DllMainCRTStartup %t.dir/lib.obj -lldmingw -implib:%t.dir/lib.lib +# RUN: lld-link -out:%t.dir/lib.dll -dll %t.dir/lib.obj -lldmingw -implib:%t.dir/lib.lib # RUN: llvm-mc -triple=x86_64-windows-gnu %t.dir/main.s -filetype=obj -o %t.dir/main.obj # RUN: lld-link -lldmingw -out:%t.dir/main.exe -entry:main %t.dir/main.obj %t.dir/lib.lib -opt:noref -debug:dwarf -runtime-pseudo-reloc:no diff --git a/lld/test/COFF/autoimport-gc.s b/lld/test/COFF/autoimport-gc.s index fef6c02eba82f..f97fe4f534d27 100644 --- a/lld/test/COFF/autoimport-gc.s +++ b/lld/test/COFF/autoimport-gc.s @@ -2,7 +2,7 @@ # RUN: split-file %s %t.dir # RUN: llvm-mc -triple=x86_64-windows-gnu %t.dir/lib.s -filetype=obj -o %t.dir/lib.obj -# RUN: lld-link -out:%t.dir/lib.dll -dll -entry:DllMainCRTStartup %t.dir/lib.obj -lldmingw -implib:%t.dir/lib.lib +# RUN: lld-link -out:%t.dir/lib.dll -dll %t.dir/lib.obj -lldmingw -implib:%t.dir/lib.lib # RUN: llvm-mc -triple=x86_64-windows-gnu %t.dir/main.s -filetype=obj -o %t.dir/main.obj # RUN: lld-link -lldmingw -out:%t.dir/main.exe -entry:main %t.dir/main.obj %t.dir/lib.lib -opt:ref -debug:dwarf diff --git a/lld/test/COFF/autoimport-lto.ll b/lld/test/COFF/autoimport-lto.ll index 94210e43cda6c..9a63d2f232d4e 100644 --- a/lld/test/COFF/autoimport-lto.ll +++ b/lld/test/COFF/autoimport-lto.ll @@ -2,7 +2,7 @@ ; RUN: echo -e ".global variable\n.global DllMainCRTStartup\n.text\nDllMainCRTStartup:\nret\n.data\nvariable:\n.long 42" > %t-lib.s ; RUN: llvm-mc -triple=x86_64-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj -; RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib +; RUN: lld-link -out:%t-lib.dll -dll %t-lib.obj -lldmingw -implib:%t-lib.lib ; RUN: llvm-as -o %t.obj %s ; RUN: lld-link -lldmingw -out:%t.exe -entry:entry %t.obj %t-lib.lib diff --git a/lld/test/COFF/autoimport-refptr.s b/lld/test/COFF/autoimport-refptr.s index 4071d6be0809e..b087dd9363553 100644 --- a/lld/test/COFF/autoimport-refptr.s +++ b/lld/test/COFF/autoimport-refptr.s @@ -2,7 +2,7 @@ # RUN: echo -e ".global variable\n.global DllMainCRTStartup\n.text\nDllMainCRTStartup:\nret\n.data\nvariable:\n.long 42" > %t-lib.s # RUN: llvm-mc -triple=x86_64-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj -# RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib +# RUN: lld-link -out:%t-lib.dll -dll %t-lib.obj -lldmingw -implib:%t-lib.lib # RUN: llvm-mc -triple=x86_64-windows-gnu %s -defsym listptrs=1 -filetype=obj -o %t.obj # RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose diff --git a/lld/test/COFF/autoimport-x86.s b/lld/test/COFF/autoimport-x86.s index 5d7c9c2c3fa58..39f2457a8259d 100644 --- a/lld/test/COFF/autoimport-x86.s +++ b/lld/test/COFF/autoimport-x86.s @@ -2,7 +2,7 @@ # RUN: echo -e ".global variable\n.global DllMainCRTStartup\n.text\nDllMainCRTStartup:\nret\n.data\nvariable:\n.long 42" > %t-lib.s # RUN: llvm-mc -triple=x86_64-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj -# RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib +# RUN: lld-link -out:%t-lib.dll -dll %t-lib.obj -lldmingw -implib:%t-lib.lib # RUN: llvm-mc -triple=x86_64-windows-gnu -defsym listptrs=1 %s -filetype=obj -o %t.obj # RUN: lld-link -lldmingw -debug:symtab -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose diff --git a/lld/test/COFF/exclude-all.s b/lld/test/COFF/exclude-all.s index f1977836b18cf..03dc0ddc6296e 100644 --- a/lld/test/COFF/exclude-all.s +++ b/lld/test/COFF/exclude-all.s @@ -2,7 +2,7 @@ # 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: lld-link -lldmingw -exclude-all-symbols -dll -out:%t.dll %t.obj # RUN: llvm-readobj --coff-exports %t.dll | FileCheck %s -check-prefix=NO-EXPORTS # NO-EXPORTS-NOT: Name: @@ -25,7 +25,7 @@ _dataSym: # RUN: yaml2obj %p/Inputs/export.yaml -o %t.obj # -# RUN: lld-link -safeseh:no -out:%t.dll -dll %t.obj -lldmingw -exclude-all-symbols -output-def:%t.def +# RUN: lld-link -safeseh:no -out:%t.dll -dll %t.obj -lldmingw -exclude-all-symbols -entry:_DllMainCRTStartup -output-def:%t.def # RUN: llvm-readobj --coff-exports %t.dll | FileCheck -check-prefix=DLLEXPORT %s # DLLEXPORT: Name: exportfn3 diff --git a/lld/test/COFF/export-all.s b/lld/test/COFF/export-all.s index cd0a6f5f7b35a..70266f37809ca 100644 --- a/lld/test/COFF/export-all.s +++ b/lld/test/COFF/export-all.s @@ -2,7 +2,7 @@ # RUN: llvm-mc -triple=i686-windows-gnu %s -filetype=obj -o %t.obj -# RUN: lld-link -lldmingw -dll -out:%t.dll -entry:DllMainCRTStartup@12 %t.obj -implib:%t.lib +# RUN: lld-link -lldmingw -dll -out:%t.dll %t.obj -implib:%t.lib # RUN: llvm-readobj --coff-exports %t.dll | grep Name: | FileCheck %s # RUN: llvm-readobj --coff-exports %t.dll | FileCheck %s --check-prefix=CHECK-RVA # RUN: llvm-readobj %t.lib | FileCheck -check-prefix=IMPLIB %s @@ -57,7 +57,7 @@ __imp__unexported: # RUN: yaml2obj %p/Inputs/export.yaml -o %t.obj # -# RUN: lld-link -safeseh:no -out:%t.dll -dll %t.obj -lldmingw -export-all-symbols -output-def:%t.def +# RUN: lld-link -safeseh:no -out:%t.dll -dll %t.obj -lldmingw -export-all-symbols -entry:_DllMainCRTStartup -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 @@ -88,7 +88,7 @@ __imp__unexported: # RUN: llvm-ar rcs %t.dir/libs/libmingwex.a %t.dir/libs/mingwfunc.o # RUN: echo -e ".global crtfunc\n.text\ncrtfunc:\nret\n" > %t.dir/libs/crtfunc.s # RUN: llvm-mc -triple=x86_64-windows-gnu %t.dir/libs/crtfunc.s -filetype=obj -o %t.dir/libs/crt2.o -# RUN: lld-link -safeseh:no -out:%t.dll -dll -entry:DllMainCRTStartup %t.main.obj -lldmingw %t.dir/libs/crt2.o %t.dir/libs/libmingwex.a -output-def:%t.def +# RUN: lld-link -safeseh:no -out:%t.dll -dll %t.main.obj -lldmingw %t.dir/libs/crt2.o %t.dir/libs/libmingwex.a -output-def:%t.def # RUN: echo "EOF" >> %t.def # RUN: cat %t.def | FileCheck -check-prefix=CHECK-EXCLUDE %s @@ -99,7 +99,7 @@ __imp__unexported: # Test that libraries included with -wholearchive: are autoexported, even if # they are in a library that otherwise normally would be excluded. -# RUN: lld-link -safeseh:no -out:%t.dll -dll -entry:DllMainCRTStartup %t.main.obj -lldmingw %t.dir/libs/crt2.o -wholearchive:%t.dir/libs/libmingwex.a -output-def:%t.def +# RUN: lld-link -safeseh:no -out:%t.dll -dll %t.main.obj -lldmingw %t.dir/libs/crt2.o -wholearchive:%t.dir/libs/libmingwex.a -output-def:%t.def # RUN: echo "EOF" >> %t.def # RUN: cat %t.def | FileCheck -check-prefix=CHECK-WHOLEARCHIVE %s