diff --git a/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp b/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp index 6364e81089d1..d0c72c31a777 100644 --- a/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp +++ b/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp @@ -11,6 +11,7 @@ #include "GroupedSectionsPass.h" #include "IdataPass.h" #include "LinkerGeneratedSymbolFile.h" +#include "SetSubsystemPass.h" #include "lld/Core/PassManager.h" #include "lld/Passes/LayoutPass.h" @@ -204,6 +205,7 @@ PECOFFLinkingContext::stringFromRelocKind(Reference::Kind kind) const { } void PECOFFLinkingContext::addPasses(PassManager &pm) { + pm.add(std::unique_ptr(new pecoff::SetSubsystemPass(*this))); pm.add(std::unique_ptr(new pecoff::GroupedSectionsPass())); pm.add(std::unique_ptr(new pecoff::IdataPass(*this))); pm.add(std::unique_ptr(new LayoutPass())); diff --git a/lld/lib/ReaderWriter/PECOFF/SetSubsystemPass.h b/lld/lib/ReaderWriter/PECOFF/SetSubsystemPass.h new file mode 100644 index 000000000000..a785137e6463 --- /dev/null +++ b/lld/lib/ReaderWriter/PECOFF/SetSubsystemPass.h @@ -0,0 +1,56 @@ +//===- lib/ReaderWriter/PECOFF/SetSubsystemPass.h -------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_READER_WRITER_PE_COFF_SET_SUBSYSTEM_PASS_H +#define LLD_READER_WRITER_PE_COFF_SET_SUBSYSTEM_PASS_H + +#include "lld/ReaderWriter/PECOFFLinkingContext.h" + +using llvm::COFF::WindowsSubsystem::IMAGE_SUBSYSTEM_UNKNOWN; +using llvm::COFF::WindowsSubsystem::IMAGE_SUBSYSTEM_WINDOWS_CUI; +using llvm::COFF::WindowsSubsystem::IMAGE_SUBSYSTEM_WINDOWS_GUI; + +namespace lld { +namespace pecoff { + +/// If "main" or "wmain" is defined, /subsystem:console is the default. If +/// "WinMain" or "wWinMain" is defined, /subsystem:windows is the default. +class SetSubsystemPass : public lld::Pass { +public: + SetSubsystemPass(PECOFFLinkingContext &ctx) : _ctx(ctx) {} + + virtual void perform(std::unique_ptr &file) { + if (_ctx.getSubsystem() != IMAGE_SUBSYSTEM_UNKNOWN) + return; + StringRef main = _ctx.decorateSymbol("main"); + StringRef wmain = _ctx.decorateSymbol("wmain"); + StringRef winmain = _ctx.decorateSymbol("WinMain"); + StringRef wwinmain = _ctx.decorateSymbol("wWinMain"); + for (auto *atom : file->defined()) { + StringRef s = atom->name(); + if (s == main || s == wmain) { + _ctx.setSubsystem(IMAGE_SUBSYSTEM_WINDOWS_CUI); + return; + } + if (s == winmain || s == wwinmain) { + _ctx.setSubsystem(IMAGE_SUBSYSTEM_WINDOWS_GUI); + return; + } + } + llvm_unreachable("Failed to infer the subsystem."); + } + +private: + PECOFFLinkingContext &_ctx; +}; + +} // namespace pecoff +} // namespace lld + +#endif diff --git a/lld/test/pecoff/Inputs/subsystem.main.yaml b/lld/test/pecoff/Inputs/subsystem.main.yaml new file mode 100644 index 000000000000..e13f45cde4e1 --- /dev/null +++ b/lld/test/pecoff/Inputs/subsystem.main.yaml @@ -0,0 +1,25 @@ +--- +header: + Machine: IMAGE_FILE_MACHINE_I386 + 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 + NumberOfAuxSymbols: 1 + AuxiliaryData: 060000000000000000000000000000000000 + - Name: _main + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/lld/test/pecoff/Inputs/subsystem.winmain.yaml b/lld/test/pecoff/Inputs/subsystem.winmain.yaml new file mode 100644 index 000000000000..a8a6b6277afb --- /dev/null +++ b/lld/test/pecoff/Inputs/subsystem.winmain.yaml @@ -0,0 +1,25 @@ +--- +header: + Machine: IMAGE_FILE_MACHINE_I386 + 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 + NumberOfAuxSymbols: 1 + AuxiliaryData: 060000000000000000000000000000000000 + - Name: _WinMain + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... diff --git a/lld/test/pecoff/baseaddr.test b/lld/test/pecoff/baseaddr.test index 4f1daf866452..9ee49c696e8a 100644 --- a/lld/test/pecoff/baseaddr.test +++ b/lld/test/pecoff/baseaddr.test @@ -1,9 +1,11 @@ # RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t.obj # -# RUN: lld -flavor link /out:%t1 /opt:noref -- %t.obj \ +# RUN: lld -flavor link /out:%t1 /opt:noref /subsystem:console /force \ +# RUN: -- %t.obj \ # RUN: && llvm-readobj -file-headers %t1 | FileCheck -check-prefix=DEFAULT %s # -# RUN: lld -flavor link /out:%t1 /opt:noref /base:8388608 -- %t.obj \ +# RUN: lld -flavor link /out:%t1 /opt:noref /base:8388608 /subsystem:console \ +# RUN: /force -- %t.obj \ # RUN: && llvm-readobj -file-headers %t1 | FileCheck -check-prefix=BASE %s DEFAULT: ImageBase: 0x400000 @@ -11,7 +13,7 @@ DEFAULT: ImageBase: 0x400000 BASE: ImageBase: 0x800000 -# RUN: not lld -flavor link /base:3 -- %t.obj >& %t.log +# RUN: not lld -flavor link /base:3 /subsystem:console -- %t.obj >& %t.log # RUN: FileCheck -check-prefix=ERROR %s < %t.log ERROR: Base address have to be multiple of 64K, but got 3 diff --git a/lld/test/pecoff/dosstub.test b/lld/test/pecoff/dosstub.test index 4cbb1bf2c0c4..f0458501704d 100644 --- a/lld/test/pecoff/dosstub.test +++ b/lld/test/pecoff/dosstub.test @@ -1,7 +1,8 @@ # RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t.obj # RUN: echo "MZ Hello world" > %t.stub -# RUN: lld -flavor link /out:%t.exe /entry:start /stub:%t.stub -- %t.obj +# RUN: lld -flavor link /out:%t.exe /entry:start /subsystem:console \ +# RUN: /stub:%t.stub -- %t.obj # RUN: FileCheck -check-prefix=FILE %s < %t.exe # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=READOBJ %s diff --git a/lld/test/pecoff/options.test b/lld/test/pecoff/options.test index f6831d1a5c44..be32558b5de4 100644 --- a/lld/test/pecoff/options.test +++ b/lld/test/pecoff/options.test @@ -2,26 +2,31 @@ # # RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t.obj -# RUN: lld -flavor link /align:8192 /out:%t.exe /entry:start -- %t.obj \ +# RUN: lld -flavor link /align:8192 /out:%t.exe /entry:start \ +# RUN: /subsystem:console -- %t.obj \ # RUN: && llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=ALIGN %s ALIGN: SectionAlignment: 8192 -# RUN: lld -flavor link /allowbind:no /out:%t.exe /entry:start -- %t.obj \ +# RUN: lld -flavor link /allowbind:no /out:%t.exe /entry:start \ +# RUN: /subsystem:console -- %t.obj \ # RUN: && llvm-readobj -file-headers %t.exe \ # RUN: | FileCheck -check-prefix=NOBIND %s NOBIND: IMAGE_DLL_CHARACTERISTICS_NO_BIND -# RUN: lld -flavor link /allowisolation:no /out:%t.exe /entry:start -- %t.obj \ +# RUN: lld -flavor link /allowisolation:no /out:%t.exe /entry:start \ +# RUN: /subsystem:console -- %t.obj \ # RUN: && llvm-readobj -file-headers %t.exe \ # RUN: | FileCheck -check-prefix=NOISOLATION %s NOISOLATION: IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION -# RUN: lld -flavor link /swaprun:cd /out:%t.exe /entry:start -- %t.obj \ +# RUN: lld -flavor link /swaprun:cd /out:%t.exe /entry:start \ +# RUN: /subsystem:console -- %t.obj \ # RUN: && llvm-readobj -file-headers %t.exe \ # RUN: | FileCheck -check-prefix=SWAPRUNCD %s SWAPRUNCD: IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP -# RUN: lld -flavor link /swaprun:net /out:%t.exe /entry:start -- %t.obj \ +# RUN: lld -flavor link /swaprun:net /out:%t.exe /entry:start \ +# RUN: /subsystem:console -- %t.obj \ # RUN: && llvm-readobj -file-headers %t.exe \ # RUN: | FileCheck -check-prefix=SWAPRUNNET %s SWAPRUNNET: IMAGE_FILE_NET_RUN_FROM_SWAP diff --git a/lld/test/pecoff/subsystem.test b/lld/test/pecoff/subsystem.test new file mode 100644 index 000000000000..3ed3572bf231 --- /dev/null +++ b/lld/test/pecoff/subsystem.test @@ -0,0 +1,12 @@ +# RUN: yaml2obj %p/Inputs/subsystem.main.yaml > %t.main.obj +# RUN: yaml2obj %p/Inputs/subsystem.winmain.yaml > %t.winmain.obj +# +# RUN: lld -flavor link /out:%t.main.exe -- %t.main.obj +# RUN: llvm-readobj -file-headers %t.main.exe | FileCheck -check-prefix=MAIN %s +# +# RUN: lld -flavor link /out:%t.winmain.exe -- %t.winmain.obj +# RUN: llvm-readobj -file-headers %t.winmain.exe | \ +# RUN: FileCheck -check-prefix=WINMAIN %s + +MAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI +WINMAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI diff --git a/lld/test/pecoff/trivial.test b/lld/test/pecoff/trivial.test index d3949c98ae9d..8d48aa5eba93 100644 --- a/lld/test/pecoff/trivial.test +++ b/lld/test/pecoff/trivial.test @@ -8,7 +8,8 @@ # RUN: /entry:start /opt:noref -- %t.obj && llvm-readobj -file-headers %t1 \ # RUN: | FileCheck -check-prefix=FILE %s # -# RUN: lld -flavor link /out:%t1 /entry:start /opt:noref -- %t.obj \ +# RUN: lld -flavor link /out:%t1 /subsystem:console /entry:start /opt:noref \ +# RUN: -- %t.obj \ # RUN: && llvm-readobj -sections %t1 | FileCheck -check-prefix=SECTIONS %s FILE: Format: COFF-i386