[LLD] [COFF] Add a private option for setting the os version separately from subsystem version
The MinGW driver has separate options for OS and subsystem version. Having this available in lld-link allows the MinGW driver to both match GNU ld better and simplifies the code for merging two (potentially mismatching) arguments into one. Differential Revision: https://reviews.llvm.org/D88802
This commit is contained in:
@@ -223,6 +223,8 @@ struct Configuration {
|
||||
uint32_t minorImageVersion = 0;
|
||||
uint32_t majorOSVersion = 6;
|
||||
uint32_t minorOSVersion = 0;
|
||||
uint32_t majorSubsystemVersion = 6;
|
||||
uint32_t minorSubsystemVersion = 0;
|
||||
uint32_t timestamp = 0;
|
||||
uint32_t functionPadMin = 0;
|
||||
bool dynamicBase = true;
|
||||
|
||||
@@ -408,10 +408,17 @@ void LinkerDriver::parseDirectives(InputFile *file) {
|
||||
case OPT_section:
|
||||
parseSection(arg->getValue());
|
||||
break;
|
||||
case OPT_subsystem:
|
||||
case OPT_subsystem: {
|
||||
bool gotVersion = false;
|
||||
parseSubsystem(arg->getValue(), &config->subsystem,
|
||||
&config->majorOSVersion, &config->minorOSVersion);
|
||||
&config->majorSubsystemVersion,
|
||||
&config->minorSubsystemVersion, &gotVersion);
|
||||
if (gotVersion) {
|
||||
config->majorOSVersion = config->majorSubsystemVersion;
|
||||
config->minorOSVersion = config->minorSubsystemVersion;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Only add flags here that link.exe accepts in
|
||||
// `#pragma comment(linker, "/flag")`-generated sections.
|
||||
case OPT_editandcontinue:
|
||||
@@ -1459,8 +1466,18 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
|
||||
|
||||
// Handle /subsystem
|
||||
if (auto *arg = args.getLastArg(OPT_subsystem))
|
||||
parseSubsystem(arg->getValue(), &config->subsystem, &config->majorOSVersion,
|
||||
&config->minorOSVersion);
|
||||
parseSubsystem(arg->getValue(), &config->subsystem,
|
||||
&config->majorSubsystemVersion,
|
||||
&config->minorSubsystemVersion);
|
||||
|
||||
// Handle /osversion
|
||||
if (auto *arg = args.getLastArg(OPT_osversion)) {
|
||||
parseVersion(arg->getValue(), &config->majorOSVersion,
|
||||
&config->minorOSVersion);
|
||||
} else {
|
||||
config->majorOSVersion = config->majorSubsystemVersion;
|
||||
config->minorOSVersion = config->minorSubsystemVersion;
|
||||
}
|
||||
|
||||
// Handle /timestamp
|
||||
if (llvm::opt::Arg *arg = args.getLastArg(OPT_timestamp, OPT_repro)) {
|
||||
|
||||
@@ -168,7 +168,7 @@ void parseVersion(StringRef arg, uint32_t *major, uint32_t *minor);
|
||||
|
||||
// Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
|
||||
void parseSubsystem(StringRef arg, WindowsSubsystem *sys, uint32_t *major,
|
||||
uint32_t *minor);
|
||||
uint32_t *minor, bool *gotVersion = nullptr);
|
||||
|
||||
void parseAlternateName(StringRef);
|
||||
void parseMerge(StringRef);
|
||||
|
||||
@@ -112,7 +112,7 @@ void parseGuard(StringRef fullArg) {
|
||||
|
||||
// Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
|
||||
void parseSubsystem(StringRef arg, WindowsSubsystem *sys, uint32_t *major,
|
||||
uint32_t *minor) {
|
||||
uint32_t *minor, bool *gotVersion) {
|
||||
StringRef sysStr, ver;
|
||||
std::tie(sysStr, ver) = arg.split(',');
|
||||
std::string sysStrLower = sysStr.lower();
|
||||
@@ -132,6 +132,8 @@ void parseSubsystem(StringRef arg, WindowsSubsystem *sys, uint32_t *major,
|
||||
fatal("unknown subsystem: " + sysStr);
|
||||
if (!ver.empty())
|
||||
parseVersion(ver, major, minor);
|
||||
if (gotVersion)
|
||||
*gotVersion = !ver.empty();
|
||||
}
|
||||
|
||||
// Parse a string of the form of "<from>=<to>".
|
||||
|
||||
@@ -9,6 +9,11 @@ class F<string name> : Flag<["/", "-", "/?", "-?"], name>;
|
||||
class P<string name, string help> :
|
||||
Joined<["/", "-", "/?", "-?"], name#":">, HelpText<help>;
|
||||
|
||||
// Same as P<> above, but without help texts, for private undocumented
|
||||
// options.
|
||||
class P_priv<string name> :
|
||||
Joined<["/", "-", "/?", "-?"], name#":">;
|
||||
|
||||
// Boolean flag which can be suffixed by ":no". Using it unsuffixed turns the
|
||||
// flag on and using it suffixed by ":no" turns it off.
|
||||
multiclass B<string name, string help_on, string help_off> {
|
||||
@@ -205,6 +210,7 @@ def include_optional : Joined<["/", "-", "/?", "-?"], "includeoptional:">,
|
||||
def kill_at : F<"kill-at">;
|
||||
def lldmingw : F<"lldmingw">;
|
||||
def noseh : F<"noseh">;
|
||||
def osversion : P_priv<"osversion">;
|
||||
def output_def : Joined<["/", "-", "/?", "-?"], "output-def:">;
|
||||
def pdb_source_path : P<"pdbsourcepath",
|
||||
"Base path used to make relative source file path absolute in PDB">;
|
||||
|
||||
@@ -1373,8 +1373,8 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
|
||||
pe->MinorImageVersion = config->minorImageVersion;
|
||||
pe->MajorOperatingSystemVersion = config->majorOSVersion;
|
||||
pe->MinorOperatingSystemVersion = config->minorOSVersion;
|
||||
pe->MajorSubsystemVersion = config->majorOSVersion;
|
||||
pe->MinorSubsystemVersion = config->minorOSVersion;
|
||||
pe->MajorSubsystemVersion = config->majorSubsystemVersion;
|
||||
pe->MinorSubsystemVersion = config->minorSubsystemVersion;
|
||||
pe->Subsystem = config->subsystem;
|
||||
pe->SizeOfImage = sizeOfImage;
|
||||
pe->SizeOfHeaders = sizeOfHeaders;
|
||||
|
||||
@@ -30,3 +30,21 @@ CHECK3: MajorOperatingSystemVersion: 8
|
||||
CHECK3: MinorOperatingSystemVersion: 9
|
||||
CHECK3: MajorSubsystemVersion: 8
|
||||
CHECK3: MinorSubsystemVersion: 9
|
||||
|
||||
# RUN: lld-link /entry:main /out:%t.exe /osversion:1.2 \
|
||||
# RUN: %p/Inputs/ret42.obj
|
||||
# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK4 %s
|
||||
|
||||
CHECK4: MajorOperatingSystemVersion: 1
|
||||
CHECK4: MinorOperatingSystemVersion: 2
|
||||
CHECK4: MajorSubsystemVersion: 6
|
||||
CHECK4: MinorSubsystemVersion: 0
|
||||
|
||||
# RUN: lld-link /entry:main /out:%t.exe /osversion:1.2 /subsystem:default,3.4 \
|
||||
# RUN: %p/Inputs/ret42.obj
|
||||
# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK5 %s
|
||||
|
||||
CHECK5: MajorOperatingSystemVersion: 1
|
||||
CHECK5: MinorOperatingSystemVersion: 2
|
||||
CHECK5: MajorSubsystemVersion: 3
|
||||
CHECK5: MinorSubsystemVersion: 4
|
||||
|
||||
Reference in New Issue
Block a user