parent
b9dcdb5fc9
commit
15cc47ee81
|
|
@ -19,10 +19,13 @@
|
|||
namespace lld {
|
||||
namespace coff {
|
||||
|
||||
using llvm::COFF::WindowsSubsystem;
|
||||
|
||||
class Configuration {
|
||||
public:
|
||||
llvm::COFF::MachineTypes MachineType = llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
|
||||
bool Verbose = false;
|
||||
WindowsSubsystem Subsystem = llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI;
|
||||
std::string EntryName = "mainCRTStartup";
|
||||
|
||||
uint64_t ImageBase = 0x140000000;
|
||||
|
|
@ -32,6 +35,8 @@ public:
|
|||
uint64_t HeapCommit = 4096;
|
||||
uint32_t MajorImageVersion = 0;
|
||||
uint32_t MinorImageVersion = 0;
|
||||
uint32_t MajorOSVersion = 6;
|
||||
uint32_t MinorOSVersion = 0;
|
||||
|
||||
bool insertFile(llvm::StringRef Path) {
|
||||
return VisitedFiles.insert(Path.lower()).second;
|
||||
|
|
|
|||
|
|
@ -161,6 +161,16 @@ bool link(int Argc, const char *Argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
// Handle /subsystem
|
||||
if (auto *Arg = Args->getLastArg(OPT_subsystem)) {
|
||||
if (auto EC = parseSubsystem(Arg->getValue(), &Config->Subsystem,
|
||||
&Config->MajorOSVersion,
|
||||
&Config->MinorOSVersion)) {
|
||||
llvm::errs() << "/subsystem: " << EC.message() << "\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse all input files and put all symbols to the symbol table.
|
||||
// The symbol table will take care of name resolution.
|
||||
SymbolTable Symtab;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ namespace lld {
|
|||
namespace coff {
|
||||
|
||||
using llvm::COFF::MachineTypes;
|
||||
using llvm::COFF::WindowsSubsystem;
|
||||
class InputFile;
|
||||
|
||||
ErrorOr<std::unique_ptr<llvm::opt::InputArgList>>
|
||||
|
|
@ -51,6 +52,10 @@ std::error_code parseNumbers(StringRef Arg, uint64_t *Addr,
|
|||
// Minor's default value is 0.
|
||||
std::error_code parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor);
|
||||
|
||||
// Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
|
||||
std::error_code parseSubsystem(StringRef Arg, WindowsSubsystem *Sys,
|
||||
uint32_t *Major, uint32_t *Minor);
|
||||
|
||||
// Create enum with OPT_xxx values for each option in Options.td
|
||||
enum {
|
||||
OPT_INVALID = 0,
|
||||
|
|
|
|||
|
|
@ -152,6 +152,30 @@ std::error_code parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor) {
|
|||
return std::error_code();
|
||||
}
|
||||
|
||||
// Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
|
||||
std::error_code parseSubsystem(StringRef Arg, WindowsSubsystem *Sys,
|
||||
uint32_t *Major, uint32_t *Minor) {
|
||||
StringRef SysStr, Ver;
|
||||
std::tie(SysStr, Ver) = Arg.split(',');
|
||||
*Sys = StringSwitch<WindowsSubsystem>(SysStr.lower())
|
||||
.Case("boot_application", IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)
|
||||
.Case("console", IMAGE_SUBSYSTEM_WINDOWS_CUI)
|
||||
.Case("efi_application", IMAGE_SUBSYSTEM_EFI_APPLICATION)
|
||||
.Case("efi_boot_service_driver", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
|
||||
.Case("efi_rom", IMAGE_SUBSYSTEM_EFI_ROM)
|
||||
.Case("efi_runtime_driver", IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
|
||||
.Case("native", IMAGE_SUBSYSTEM_NATIVE)
|
||||
.Case("posix", IMAGE_SUBSYSTEM_POSIX_CUI)
|
||||
.Case("windows", IMAGE_SUBSYSTEM_WINDOWS_GUI)
|
||||
.Default(IMAGE_SUBSYSTEM_UNKNOWN);
|
||||
if (*Sys == IMAGE_SUBSYSTEM_UNKNOWN)
|
||||
return make_dynamic_error_code(Twine("unknown subsystem: ") + SysStr);
|
||||
if (!Ver.empty())
|
||||
if (auto EC = parseVersion(Ver, Major, Minor))
|
||||
return EC;
|
||||
return std::error_code();
|
||||
}
|
||||
|
||||
// Create OptTable
|
||||
|
||||
// Create prefix string literals used in Options.td
|
||||
|
|
|
|||
|
|
@ -261,9 +261,11 @@ void Writer::writeHeader() {
|
|||
PE->FileAlignment = FileAlignment;
|
||||
PE->MajorImageVersion = Config->MajorImageVersion;
|
||||
PE->MinorImageVersion = Config->MinorImageVersion;
|
||||
PE->MajorOperatingSystemVersion = 6;
|
||||
PE->MajorSubsystemVersion = 6;
|
||||
PE->Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
|
||||
PE->MajorOperatingSystemVersion = Config->MajorOSVersion;
|
||||
PE->MinorOperatingSystemVersion = Config->MinorOSVersion;
|
||||
PE->MajorSubsystemVersion = Config->MajorOSVersion;
|
||||
PE->MinorSubsystemVersion = Config->MinorOSVersion;
|
||||
PE->Subsystem = Config->Subsystem;
|
||||
PE->SizeOfImage = SizeOfImage;
|
||||
PE->SizeOfHeaders = SizeOfHeaders;
|
||||
PE->AddressOfEntryPoint = Entry->getRVA();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
# RUN: lld -flavor link2 /entry:main /out:%t.exe %p/Inputs/ret42.obj
|
||||
# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=DEFAULT %s
|
||||
|
||||
DEFAULT: MajorOperatingSystemVersion: 6
|
||||
DEFAULT: MinorOperatingSystemVersion: 0
|
||||
DEFAULT: MajorSubsystemVersion: 6
|
||||
DEFAULT: MinorSubsystemVersion: 0
|
||||
DEFAULT: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
|
||||
|
||||
# RUN: lld -flavor link2 /entry:main /out:%t.exe /subsystem:windows \
|
||||
# RUN: %p/Inputs/ret42.obj
|
||||
# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
|
||||
|
||||
CHECK1: MajorOperatingSystemVersion: 6
|
||||
CHECK1: MinorOperatingSystemVersion: 0
|
||||
CHECK1: MajorSubsystemVersion: 6
|
||||
CHECK1: MinorSubsystemVersion: 0
|
||||
CHECK1: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI
|
||||
|
||||
# RUN: lld -flavor link2 /entry:main /out:%t.exe /subsystem:windows,8.9 \
|
||||
# RUN: %p/Inputs/ret42.obj
|
||||
# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
|
||||
|
||||
CHECK2: MajorOperatingSystemVersion: 8
|
||||
CHECK2: MinorOperatingSystemVersion: 9
|
||||
CHECK2: MajorSubsystemVersion: 8
|
||||
CHECK2: MinorSubsystemVersion: 9
|
||||
CHECK2: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI
|
||||
Loading…
Reference in New Issue