summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2018-08-07 19:10:28 +0000
committerNico Weber <nicolasweber@gmx.de>2018-08-07 19:10:28 +0000
commitf4f5b7eea37926ba8bf9de31c9e9b5aa1e9c746c (patch)
treee3193d41eb3841ac4e9e3ed34bfbad417d3bb90c
parent3b2f6a4b29c92c4d4fafe4964ad164f600608f28 (diff)
downloadbcm5719-llvm-f4f5b7eea37926ba8bf9de31c9e9b5aa1e9c746c.tar.gz
bcm5719-llvm-f4f5b7eea37926ba8bf9de31c9e9b5aa1e9c746c.zip
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 llvm-svn: 339165
-rw-r--r--lld/COFF/Driver.cpp84
-rw-r--r--lld/test/COFF/entry-inference3.test4
-rw-r--r--lld/test/COFF/entry-inference332.test4
-rw-r--r--lld/test/COFF/entry-inference4.test56
4 files changed, 104 insertions, 44 deletions
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp
index 22e7082023f..c21f0b4e3c9 100644
--- a/lld/COFF/Driver.cpp
+++ b/lld/COFF/Driver.cpp
@@ -426,20 +426,23 @@ Symbol *LinkerDriver::addUndefined(StringRef Name) {
// 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 char *> ArgsArr) {
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@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 char *> ArgsArr) {
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@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 char *> ArgsArr) {
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)
diff --git a/lld/test/COFF/entry-inference3.test b/lld/test/COFF/entry-inference3.test
index b5ecef8c8d7..53550f75c6c 100644
--- a/lld/test/COFF/entry-inference3.test
+++ b/lld/test/COFF/entry-inference3.test
@@ -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
diff --git a/lld/test/COFF/entry-inference332.test b/lld/test/COFF/entry-inference332.test
index 5ce31c6b58d..75c557af47e 100644
--- a/lld/test/COFF/entry-inference332.test
+++ b/lld/test/COFF/entry-inference332.test
@@ -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
diff --git a/lld/test/COFF/entry-inference4.test b/lld/test/COFF/entry-inference4.test
new file mode 100644
index 00000000000..513c9cf8f86
--- /dev/null
+++ b/lld/test/COFF/entry-inference4.test
@@ -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
+...
OpenPOWER on IntegriCloud