[PECOFF][Driver] Support /version command line option
llvm-svn: 190986
This commit is contained in:
parent
2f7fe8acb3
commit
1bddfc1fc7
|
@ -31,15 +31,15 @@ public:
|
||||||
: _baseAddress(0x400000), _stackReserve(1024 * 1024), _stackCommit(4096),
|
: _baseAddress(0x400000), _stackReserve(1024 * 1024), _stackCommit(4096),
|
||||||
_heapReserve(1024 * 1024), _heapCommit(4096),
|
_heapReserve(1024 * 1024), _heapCommit(4096),
|
||||||
_subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN),
|
_subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN),
|
||||||
_machineType(llvm::COFF::IMAGE_FILE_MACHINE_I386),
|
_machineType(llvm::COFF::IMAGE_FILE_MACHINE_I386), _imageVersion(0, 0),
|
||||||
_minOSVersion(6, 0), _nxCompat(true), _largeAddressAware(false),
|
_minOSVersion(6, 0), _nxCompat(true), _largeAddressAware(false),
|
||||||
_baseRelocationEnabled(true), _terminalServerAware(true),
|
_baseRelocationEnabled(true), _terminalServerAware(true),
|
||||||
_dynamicBaseEnabled(true), _imageType(ImageType::IMAGE_EXE) {
|
_dynamicBaseEnabled(true), _imageType(ImageType::IMAGE_EXE) {
|
||||||
setDeadStripping(true);
|
setDeadStripping(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OSVersion {
|
struct Version {
|
||||||
OSVersion(int v1, int v2) : majorVersion(v1), minorVersion(v2) {}
|
Version(int v1, int v2) : majorVersion(v1), minorVersion(v2) {}
|
||||||
int majorVersion;
|
int majorVersion;
|
||||||
int minorVersion;
|
int minorVersion;
|
||||||
};
|
};
|
||||||
|
@ -108,8 +108,11 @@ public:
|
||||||
void setMachineType(MachineTypes type) { _machineType = type; }
|
void setMachineType(MachineTypes type) { _machineType = type; }
|
||||||
MachineTypes getMachineType() const { return _machineType; }
|
MachineTypes getMachineType() const { return _machineType; }
|
||||||
|
|
||||||
void setMinOSVersion(const OSVersion &version) { _minOSVersion = version; }
|
void setImageVersion(const Version &version) { _imageVersion = version; }
|
||||||
OSVersion getMinOSVersion() const { return _minOSVersion; }
|
Version getImageVersion() const { return _imageVersion; }
|
||||||
|
|
||||||
|
void setMinOSVersion(const Version &version) { _minOSVersion = version; }
|
||||||
|
Version getMinOSVersion() const { return _minOSVersion; }
|
||||||
|
|
||||||
void setNxCompat(bool nxCompat) { _nxCompat = nxCompat; }
|
void setNxCompat(bool nxCompat) { _nxCompat = nxCompat; }
|
||||||
bool isNxCompat() const { return _nxCompat; }
|
bool isNxCompat() const { return _nxCompat; }
|
||||||
|
@ -163,7 +166,8 @@ private:
|
||||||
uint64_t _heapCommit;
|
uint64_t _heapCommit;
|
||||||
WindowsSubsystem _subsystem;
|
WindowsSubsystem _subsystem;
|
||||||
MachineTypes _machineType;
|
MachineTypes _machineType;
|
||||||
OSVersion _minOSVersion;
|
Version _imageVersion;
|
||||||
|
Version _minOSVersion;
|
||||||
bool _nxCompat;
|
bool _nxCompat;
|
||||||
bool _largeAddressAware;
|
bool _largeAddressAware;
|
||||||
bool _baseRelocationEnabled;
|
bool _baseRelocationEnabled;
|
||||||
|
|
|
@ -98,6 +98,20 @@ bool parseMemoryOption(StringRef arg, uint64_t &reserve, uint64_t &commit) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse an argument for /version or /subsystem. The expected string is
|
||||||
|
// "<integer>[.<integer>]".
|
||||||
|
bool parseVersion(StringRef arg, uint32_t &major, uint32_t &minor) {
|
||||||
|
StringRef majorVersion, minorVersion;
|
||||||
|
llvm::tie(majorVersion, minorVersion) = arg.split('.');
|
||||||
|
if (minorVersion.empty())
|
||||||
|
minorVersion = "0";
|
||||||
|
if (majorVersion.getAsInteger(0, major))
|
||||||
|
return true;
|
||||||
|
if (minorVersion.getAsInteger(0, minor))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns subsystem type for the given string.
|
// Returns subsystem type for the given string.
|
||||||
llvm::COFF::WindowsSubsystem stringToWinSubsystem(StringRef str) {
|
llvm::COFF::WindowsSubsystem stringToWinSubsystem(StringRef str) {
|
||||||
return llvm::StringSwitch<llvm::COFF::WindowsSubsystem>(str.lower())
|
return llvm::StringSwitch<llvm::COFF::WindowsSubsystem>(str.lower())
|
||||||
|
@ -326,6 +340,13 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
|
||||||
ctx.setMachineType(type);
|
ctx.setMachineType(type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OPT_version: {
|
||||||
|
uint32_t major, minor;
|
||||||
|
if (parseVersion(inputArg->getValue(), major, minor))
|
||||||
|
return true;
|
||||||
|
ctx.setImageVersion(PECOFFLinkingContext::Version(major, minor));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case OPT_subsystem: {
|
case OPT_subsystem: {
|
||||||
// Parse /subsystem command line option. The form of /subsystem is
|
// Parse /subsystem command line option. The form of /subsystem is
|
||||||
// "subsystem_name[,majorOSVersion[.minorOSVersion]]".
|
// "subsystem_name[,majorOSVersion[.minorOSVersion]]".
|
||||||
|
@ -333,16 +354,10 @@ bool WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ct
|
||||||
llvm::tie(subsystemStr, osVersion) =
|
llvm::tie(subsystemStr, osVersion) =
|
||||||
StringRef(inputArg->getValue()).split(',');
|
StringRef(inputArg->getValue()).split(',');
|
||||||
if (!osVersion.empty()) {
|
if (!osVersion.empty()) {
|
||||||
StringRef majorVersion, minorVersion;
|
uint32_t major, minor;
|
||||||
llvm::tie(majorVersion, minorVersion) = osVersion.split('.');
|
if (parseVersion(osVersion, major, minor))
|
||||||
if (minorVersion.empty())
|
|
||||||
minorVersion = "0";
|
|
||||||
int32_t major, minor;
|
|
||||||
if (majorVersion.getAsInteger(0, major))
|
|
||||||
return true;
|
return true;
|
||||||
if (minorVersion.getAsInteger(0, minor))
|
ctx.setMinOSVersion(PECOFFLinkingContext::Version(major, minor));
|
||||||
return true;
|
|
||||||
ctx.setMinOSVersion(PECOFFLinkingContext::OSVersion(major, minor));
|
|
||||||
}
|
}
|
||||||
// Parse subsystem name.
|
// Parse subsystem name.
|
||||||
llvm::COFF::WindowsSubsystem subsystem =
|
llvm::COFF::WindowsSubsystem subsystem =
|
||||||
|
|
|
@ -20,6 +20,7 @@ defm mllvm : P<"mllvm", "Options to pass to LLVM">;
|
||||||
defm out : P<"out", "Path to file to write output">;
|
defm out : P<"out", "Path to file to write output">;
|
||||||
defm stack : P<"stack", "Size of the stack">;
|
defm stack : P<"stack", "Size of the stack">;
|
||||||
defm machine : P<"machine", "Specify target platform">;
|
defm machine : P<"machine", "Specify target platform">;
|
||||||
|
defm version : P<"version", "Specify a version number in the PE header">;
|
||||||
defm subsystem : P<"subsystem", "Specify subsystem">;
|
defm subsystem : P<"subsystem", "Specify subsystem">;
|
||||||
|
|
||||||
// We cannot use multiclass P because class name "incl" is different
|
// We cannot use multiclass P because class name "incl" is different
|
||||||
|
|
|
@ -179,10 +179,17 @@ public:
|
||||||
// Sections in an executable file on disk should be sector-aligned (512 byte).
|
// Sections in an executable file on disk should be sector-aligned (512 byte).
|
||||||
_peHeader.FileAlignment = SECTOR_SIZE;
|
_peHeader.FileAlignment = SECTOR_SIZE;
|
||||||
|
|
||||||
|
// The version number of the resultant executable/DLL. The number is purely
|
||||||
|
// informative, and neither the linker nor the loader won't use it. User can
|
||||||
|
// set the value using /version command line option. Default is 0.0.
|
||||||
|
PECOFFLinkingContext::Version imageVersion = context.getImageVersion();
|
||||||
|
_peHeader.MajorImageVersion = imageVersion.majorVersion;
|
||||||
|
_peHeader.MinorImageVersion = imageVersion.minorVersion;
|
||||||
|
|
||||||
// The required Windows version number. This is the internal version and
|
// The required Windows version number. This is the internal version and
|
||||||
// shouldn't be confused with product name. Windows 7 is version 6.1 and
|
// shouldn't be confused with product name. Windows 7 is version 6.1 and
|
||||||
// Windows 8 is 6.2, for example.
|
// Windows 8 is 6.2, for example.
|
||||||
PECOFFLinkingContext::OSVersion minOSVersion = context.getMinOSVersion();
|
PECOFFLinkingContext::Version minOSVersion = context.getMinOSVersion();
|
||||||
_peHeader.MajorOperatingSystemVersion = minOSVersion.majorVersion;
|
_peHeader.MajorOperatingSystemVersion = minOSVersion.majorVersion;
|
||||||
_peHeader.MinorOperatingSystemVersion = minOSVersion.minorVersion;
|
_peHeader.MinorOperatingSystemVersion = minOSVersion.minorVersion;
|
||||||
_peHeader.MajorSubsystemVersion = minOSVersion.majorVersion;
|
_peHeader.MajorSubsystemVersion = minOSVersion.majorVersion;
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
#
|
#
|
||||||
# RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t.obj
|
# RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t.obj
|
||||||
#
|
#
|
||||||
# RUN: lld -flavor link /out:%t1 /subsystem:console,3.11 /entry:start \
|
# RUN: lld -flavor link /out:%t1 /subsystem:console,3.11 /version:1.25 \
|
||||||
# RUN: /opt:noref -- %t.obj && llvm-readobj -file-headers %t1 \
|
# RUN: /entry:start /opt:noref -- %t.obj && llvm-readobj -file-headers %t1 \
|
||||||
# RUN: | FileCheck -check-prefix=FILE %s
|
# RUN: | FileCheck -check-prefix=FILE %s
|
||||||
#
|
#
|
||||||
# RUN: lld -flavor link /out:%t1 /entry:start /opt:noref -- %t.obj \
|
# RUN: lld -flavor link /out:%t1 /entry:start /opt:noref -- %t.obj \
|
||||||
|
@ -40,8 +40,8 @@ FILE: SectionAlignment: 4096
|
||||||
FILE: FileAlignment: 512
|
FILE: FileAlignment: 512
|
||||||
FILE: MajorOperatingSystemVersion: 3
|
FILE: MajorOperatingSystemVersion: 3
|
||||||
FILE: MinorOperatingSystemVersion: 11
|
FILE: MinorOperatingSystemVersion: 11
|
||||||
FILE: MajorImageVersion: 0
|
FILE: MajorImageVersion: 1
|
||||||
FILE: MinorImageVersion: 0
|
FILE: MinorImageVersion: 25
|
||||||
FILE: MajorSubsystemVersion: 3
|
FILE: MajorSubsystemVersion: 3
|
||||||
FILE: MinorSubsystemVersion: 11
|
FILE: MinorSubsystemVersion: 11
|
||||||
FILE: SizeOfImage: 8192
|
FILE: SizeOfImage: 8192
|
||||||
|
|
|
@ -111,6 +111,18 @@ TEST_F(WinLinkParserTest, MachineX64) {
|
||||||
EXPECT_TRUE(parse("link.exe", "/machine:x64", "a.obj", nullptr));
|
EXPECT_TRUE(parse("link.exe", "/machine:x64", "a.obj", nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(WinLinkParserTest, MajorImageVersion) {
|
||||||
|
EXPECT_FALSE(parse("link.exe", "/version:7", "foo.o", nullptr));
|
||||||
|
EXPECT_EQ(7, _context.getImageVersion().majorVersion);
|
||||||
|
EXPECT_EQ(0, _context.getImageVersion().minorVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(WinLinkParserTest, MajorMinorImageVersion) {
|
||||||
|
EXPECT_FALSE(parse("link.exe", "/version:72.35", "foo.o", nullptr));
|
||||||
|
EXPECT_EQ(72, _context.getImageVersion().majorVersion);
|
||||||
|
EXPECT_EQ(35, _context.getImageVersion().minorVersion);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(WinLinkParserTest, MinMajorOSVersion) {
|
TEST_F(WinLinkParserTest, MinMajorOSVersion) {
|
||||||
EXPECT_FALSE(parse("link.exe", "/subsystem:windows,3", "foo.o", nullptr));
|
EXPECT_FALSE(parse("link.exe", "/subsystem:windows,3", "foo.o", nullptr));
|
||||||
EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI, _context.getSubsystem());
|
EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI, _context.getSubsystem());
|
||||||
|
|
Loading…
Reference in New Issue