[lld] r339165 - lld-link: Take /SUBSYSTEM into account for automatic /ENTRY detection.
Hans Wennborg via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 30 01:26:53 PDT 2018
Merged this, along with r338877 and r338911, to 7.0 in r341035.
On Tue, Aug 7, 2018 at 9:10 PM, Nico Weber via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> Author: nico
> Date: Tue Aug 7 12:10:28 2018
> New Revision: 339165
>
> URL: http://llvm.org/viewvc/llvm-project?rev=339165&view=rev
> Log:
> lld-link: Take /SUBSYSTEM into account for automatic /ENTRY detection.
>
> If /subsystem:windows is passed, link.exe only looks for WinMain and wWinMain,
> and if /subsystem:console is passed it only looks for main and wmain. lld-link
> used to look for all 4 in both cases. This patch makes lld-link match
> link.exe's behavior.
>
> This requires that the subsystem is known by the time findDefaultEntry() gets
> called. findDefaultEntry() is called before the main link loop, so that the
> loop can mark the entry point as undefined. That means inferSubsystem() has to
> be called above the main loop as well. This in turn means /subsystem: from
> .drectve sections only has an effect on entry point inference for obj files
> passed to lld-link directly (and not in obj files found later in .lib files).
> link.exe seems to ignore /subsystem: for obj files from lib files completely
> (while in lld it's ignored only for entry point detection but it still
> overrides /subsystem: flags passed on the command line for the value that gets
> written in the output file).
>
> Also, if the subsytem isn't needed (e.g. when only writing a /def: lib file and
> not writing a coff file), link.exe doesn't complain if the subsystem isn't
> known, so both subsystem and entry point handling should be below the early
> return lld has for that case.
>
> Fixes PR36523.
> https://reviews.llvm.org/D50316
>
> Added:
> lld/trunk/test/COFF/entry-inference4.test
> Modified:
> lld/trunk/COFF/Driver.cpp
> lld/trunk/test/COFF/entry-inference3.test
> lld/trunk/test/COFF/entry-inference332.test
>
> Modified: lld/trunk/COFF/Driver.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=339165&r1=339164&r2=339165&view=diff
> ==============================================================================
> --- lld/trunk/COFF/Driver.cpp (original)
> +++ lld/trunk/COFF/Driver.cpp Tue Aug 7 12:10:28 2018
> @@ -426,20 +426,23 @@ Symbol *LinkerDriver::addUndefined(Strin
> // each of which corresponds to a user-defined "main" function. This function
> // infers an entry point from a user-defined "main" function.
> StringRef LinkerDriver::findDefaultEntry() {
> - // User-defined main functions and their corresponding entry points.
> - static const char *Entries[][2] = {
> - {"main", "mainCRTStartup"},
> - {"wmain", "wmainCRTStartup"},
> - {"WinMain", "WinMainCRTStartup"},
> - {"wWinMain", "wWinMainCRTStartup"},
> - };
> - for (auto E : Entries) {
> - // As a special case, if /nodefaultlib is given, we directly look for an
> - // entry point. This is because, if no default library is linked, users
> - // need to define an entry point instead of a "main".
> - if (findUnderscoreMangle(E[Config->NoDefaultLibAll]))
> - return mangle(E[1]);
> - }
> + assert(Config->Subsystem != IMAGE_SUBSYSTEM_UNKNOWN &&
> + "must handle /subsystem before calling this");
> +
> + // As a special case, if /nodefaultlib is given, we directly look for an
> + // entry point. This is because, if no default library is linked, users
> + // need to define an entry point instead of a "main".
> + bool FindMain = !Config->NoDefaultLibAll;
> + if (Config->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) {
> + if (findUnderscoreMangle(FindMain ? "WinMain" : "WinMainCRTStartup"))
> + return mangle("WinMainCRTStartup");
> + if (findUnderscoreMangle(FindMain ? "wWinMain" : "wWinMainCRTStartup"))
> + return mangle("wWinMainCRTStartup");
> + }
> + if (findUnderscoreMangle(FindMain ? "main" : "mainCRTStartup"))
> + return mangle("mainCRTStartup");
> + if (findUnderscoreMangle(FindMain ? "wmain" : "wmainCRTStartup"))
> + return mangle("wmainCRTStartup");
> return "";
> }
>
> @@ -1204,25 +1207,6 @@ void LinkerDriver::link(ArrayRef<const c
> error("/dynamicbase:no is not compatible with " +
> machineToStr(Config->Machine));
>
> - // Handle /entry and /dll
> - if (auto *Arg = Args.getLastArg(OPT_entry)) {
> - Config->Entry = addUndefined(mangle(Arg->getValue()));
> - } else if (!Config->Entry && !Config->NoEntry) {
> - if (Args.hasArg(OPT_dll)) {
> - StringRef S = (Config->Machine == I386) ? "__DllMainCRTStartup at 12"
> - : "_DllMainCRTStartup";
> - Config->Entry = addUndefined(S);
> - } else {
> - // Windows specific -- If entry point name is not given, we need to
> - // infer that from user-defined entry name.
> - StringRef S = findDefaultEntry();
> - if (S.empty())
> - fatal("entry point must be defined");
> - Config->Entry = addUndefined(S);
> - log("Entry name inferred: " + S);
> - }
> - }
> -
> // Handle /export
> for (auto *Arg : Args.filtered(OPT_export)) {
> Export E = parseExport(Arg->getValue());
> @@ -1248,6 +1232,34 @@ void LinkerDriver::link(ArrayRef<const c
> return;
> }
>
> + // Windows specific -- if no /subsystem is given, we need to infer
> + // that from entry point name. Must happen before /entry handling,
> + // and after the early return when just writing an import library.
> + if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {
> + Config->Subsystem = inferSubsystem();
> + if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN)
> + fatal("subsystem must be defined");
> + }
> +
> + // Handle /entry and /dll
> + if (auto *Arg = Args.getLastArg(OPT_entry)) {
> + Config->Entry = addUndefined(mangle(Arg->getValue()));
> + } else if (!Config->Entry && !Config->NoEntry) {
> + if (Args.hasArg(OPT_dll)) {
> + StringRef S = (Config->Machine == I386) ? "__DllMainCRTStartup at 12"
> + : "_DllMainCRTStartup";
> + Config->Entry = addUndefined(S);
> + } else {
> + // Windows specific -- If entry point name is not given, we need to
> + // infer that from user-defined entry name.
> + StringRef S = findDefaultEntry();
> + if (S.empty())
> + fatal("entry point must be defined");
> + Config->Entry = addUndefined(S);
> + log("Entry name inferred: " + S);
> + }
> + }
> +
> // Handle /delayload
> for (auto *Arg : Args.filtered(OPT_delayload)) {
> Config->DelayLoads.insert(StringRef(Arg->getValue()).lower());
> @@ -1353,14 +1365,6 @@ void LinkerDriver::link(ArrayRef<const c
> if (errorCount())
> return;
>
> - // Windows specific -- if no /subsystem is given, we need to infer
> - // that from entry point name.
> - if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {
> - Config->Subsystem = inferSubsystem();
> - if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN)
> - fatal("subsystem must be defined");
> - }
> -
> // Handle /safeseh.
> if (Args.hasFlag(OPT_safeseh, OPT_safeseh_no, false)) {
> for (ObjFile *File : ObjFile::Instances)
>
> Modified: lld/trunk/test/COFF/entry-inference3.test
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/entry-inference3.test?rev=339165&r1=339164&r2=339165&view=diff
> ==============================================================================
> --- lld/trunk/test/COFF/entry-inference3.test (original)
> +++ lld/trunk/test/COFF/entry-inference3.test Tue Aug 7 12:10:28 2018
> @@ -1,9 +1,9 @@
> # RUN: sed -e s/ENTRYNAME/mainCRTStartup/ %s | yaml2obj > %t.obj
> -# RUN: not lld-link /out:%t.exe %t.obj /verbose /nodefaultlib > %t.log 2>&1
> +# RUN: lld-link /subsystem:console /out:%t.exe %t.obj /verbose /nodefaultlib > %t.log 2>&1
> # RUN: FileCheck %s < %t.log
>
> # RUN: sed -e s/ENTRYNAME/?mainCRTStartup@@YAHXZ/ %s | yaml2obj > %t.obj
> -# RUN: not lld-link /out:%t.exe %t.obj /verbose /nodefaultlib > %t.log 2>&1
> +# RUN: lld-link /subsystem:console /out:%t.exe %t.obj /verbose /nodefaultlib > %t.log 2>&1
> # RUN: FileCheck %s < %t.log
>
> # CHECK: Entry name inferred: mainCRTStartup
>
> Modified: lld/trunk/test/COFF/entry-inference332.test
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/entry-inference332.test?rev=339165&r1=339164&r2=339165&view=diff
> ==============================================================================
> --- lld/trunk/test/COFF/entry-inference332.test (original)
> +++ lld/trunk/test/COFF/entry-inference332.test Tue Aug 7 12:10:28 2018
> @@ -1,9 +1,9 @@
> # RUN: sed -e s/ENTRYNAME/_mainCRTStartup/ %s | yaml2obj > %t.obj
> -# RUN: not lld-link /out:%t.exe %t.obj /verbose /nodefaultlib > %t.log 2>&1
> +# RUN: lld-link /subsystem:console /out:%t.exe %t.obj /verbose /nodefaultlib > %t.log 2>&1
> # RUN: FileCheck %s < %t.log
>
> # RUN: sed -e s/ENTRYNAME/?mainCRTStartup@@YAHXZ/ %s | yaml2obj > %t.obj
> -# RUN: not lld-link /out:%t.exe %t.obj /verbose /nodefaultlib > %t.log 2>&1
> +# RUN: lld-link /subsystem:console /out:%t.exe %t.obj /verbose /nodefaultlib > %t.log 2>&1
> # RUN: FileCheck %s < %t.log
>
> # CHECK: Entry name inferred: _mainCRTStartup
>
> Added: lld/trunk/test/COFF/entry-inference4.test
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/entry-inference4.test?rev=339165&view=auto
> ==============================================================================
> --- lld/trunk/test/COFF/entry-inference4.test (added)
> +++ lld/trunk/test/COFF/entry-inference4.test Tue Aug 7 12:10:28 2018
> @@ -0,0 +1,56 @@
> +# RUN: sed 's/ENTRY1/WinMain/;s/ENTRY2/main/' %s | yaml2obj > %t.obj
> +# RUN: not lld-link /subsystem:windows /out:%t.exe %t.obj > %t.log 2>&1
> +# RUN: FileCheck -check-prefix=WINMAIN %s < %t.log
> +
> +# RUN: sed 's/ENTRY1/wWinMain/;s/ENTRY2/main/' %s | yaml2obj > %t.obj
> +# RUN: not lld-link /subsystem:windows /out:%t.exe %t.obj > %t.log 2>&1
> +# RUN: FileCheck -check-prefix=WWINMAIN %s < %t.log
> +
> +# RUN: sed 's/ENTRY1/WinMain/;s/ENTRY2/main/' %s | yaml2obj > %t.obj
> +# RUN: not lld-link /subsystem:console /out:%t.exe %t.obj > %t.log 2>&1
> +# RUN: FileCheck -check-prefix=MAIN %s < %t.log
> +
> +# RUN: sed 's/ENTRY1/WinMain/;s/ENTRY2/wmain/' %s | yaml2obj > %t.obj
> +# RUN: not lld-link /subsystem:console /out:%t.exe %t.obj > %t.log 2>&1
> +# RUN: FileCheck -check-prefix=WMAIN %s < %t.log
> +
> +# MAIN: error: <root>: undefined symbol: mainCRTStartup
> +# WMAIN: error: <root>: undefined symbol: wmainCRTStartup
> +# WINMAIN: error: <root>: undefined symbol: WinMainCRTStartup
> +# WWINMAIN: error: <root>: undefined symbol: wWinMainCRTStartup
> +
> +--- !COFF
> +header:
> + Machine: IMAGE_FILE_MACHINE_AMD64
> + Characteristics: []
> +sections:
> + - Name: .text
> + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
> + Alignment: 4
> + SectionData: B82A000000C3
> +symbols:
> + - Name: .text
> + Value: 0
> + SectionNumber: 1
> + SimpleType: IMAGE_SYM_TYPE_NULL
> + ComplexType: IMAGE_SYM_DTYPE_NULL
> + StorageClass: IMAGE_SYM_CLASS_STATIC
> + SectionDefinition:
> + Length: 6
> + NumberOfRelocations: 0
> + NumberOfLinenumbers: 0
> + CheckSum: 0
> + Number: 0
> + - Name: ENTRY1
> + Value: 0
> + SectionNumber: 1
> + SimpleType: IMAGE_SYM_TYPE_NULL
> + ComplexType: IMAGE_SYM_DTYPE_NULL
> + StorageClass: IMAGE_SYM_CLASS_EXTERNAL
> + - Name: ENTRY2
> + Value: 0
> + SectionNumber: 1
> + SimpleType: IMAGE_SYM_TYPE_NULL
> + ComplexType: IMAGE_SYM_DTYPE_NULL
> + StorageClass: IMAGE_SYM_CLASS_EXTERNAL
> +...
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list