diff options
| -rw-r--r-- | lld/include/lld/ReaderWriter/PECOFFTargetInfo.h | 42 | ||||
| -rw-r--r-- | lld/lib/Driver/WinLinkDriver.cpp | 51 | ||||
| -rw-r--r-- | lld/lib/Driver/WinLinkOptions.td | 4 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp | 7 | ||||
| -rw-r--r-- | lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp | 4 | ||||
| -rw-r--r-- | lld/unittests/DriverTests/WinLinkDriverTest.cpp | 13 |
6 files changed, 83 insertions, 38 deletions
diff --git a/lld/include/lld/ReaderWriter/PECOFFTargetInfo.h b/lld/include/lld/ReaderWriter/PECOFFTargetInfo.h index 32c7f3a0100..99b57de16c0 100644 --- a/lld/include/lld/ReaderWriter/PECOFFTargetInfo.h +++ b/lld/include/lld/ReaderWriter/PECOFFTargetInfo.h @@ -23,9 +23,17 @@ namespace lld { class PECOFFTargetInfo : public TargetInfo { public: PECOFFTargetInfo() - : _subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN), + : _stackReserve(1024 * 1024), + _stackCommit(4096), + _subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN), _minOSVersion(6, 0) {} + struct OSVersion { + OSVersion(int v1, int v2) : majorVersion(v1), minorVersion(v2) {} + int majorVersion; + int minorVersion; + }; + virtual error_code parseFile( std::unique_ptr<MemoryBuffer> &mb, std::vector<std::unique_ptr<File>> &result) const; @@ -35,30 +43,20 @@ public: virtual void addPasses(PassManager &pm) const {} - void setSubsystem(llvm::COFF::WindowsSubsystem subsystem) { - _subsystem = subsystem; - } + void setStackReserve(uint64_t size) { _stackReserve = size; } + uint64_t getStackReserve() const { return _stackReserve; } - llvm::COFF::WindowsSubsystem getSubsystem() const { - return _subsystem; - } - - virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const; - virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const; + void setStackCommit(uint64_t size) { _stackCommit = size; } + uint64_t getStackCommit() const { return _stackCommit; } - struct OSVersion { - OSVersion(int v1, int v2) : majorVersion(v1), minorVersion(v2) {} - int majorVersion; - int minorVersion; - }; + void setSubsystem(llvm::COFF::WindowsSubsystem ss) { _subsystem = ss; } + llvm::COFF::WindowsSubsystem getSubsystem() const { return _subsystem; } - void setMinOSVersion(const OSVersion &version) { - _minOSVersion = version; - } + void setMinOSVersion(const OSVersion &version) { _minOSVersion = version; } + OSVersion getMinOSVersion() const { return _minOSVersion; } - OSVersion getMinOSVersion() const { - return _minOSVersion; - } + virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const; + virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const; StringRef allocateString(const StringRef &ref) { char *x = _extraStrings.Allocate<char>(ref.size() + 1); @@ -68,6 +66,8 @@ public: } private: + uint64_t _stackReserve; + uint64_t _stackCommit; llvm::COFF::WindowsSubsystem _subsystem; OSVersion _minOSVersion; diff --git a/lld/lib/Driver/WinLinkDriver.cpp b/lld/lib/Driver/WinLinkDriver.cpp index 8730a9cc22e..e67337ccdd5 100644 --- a/lld/lib/Driver/WinLinkDriver.cpp +++ b/lld/lib/Driver/WinLinkDriver.cpp @@ -66,20 +66,10 @@ int findDoubleDash(int argc, const char *argv[]) { return -1; } -// Returns subsystem type for the given string. -llvm::COFF::WindowsSubsystem stringToWinSubsystem(StringRef str) { - std::string arg(str.lower()); - return llvm::StringSwitch<llvm::COFF::WindowsSubsystem>(arg) - .Case("windows", llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI) - .Case("console", llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI) - .Default(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN); -} - - // Displays error message if the given version does not match with // /^\d+$/. -bool checkOSVersion(StringRef version, const char *errorMessage, - raw_ostream &diagnostics) { +bool checkNumber(StringRef version, const char *errorMessage, + raw_ostream &diagnostics) { if (version.str().find_first_not_of("0123456789") != std::string::npos || version.empty()) { diagnostics << "error: " << errorMessage << version << "\n"; @@ -88,15 +78,41 @@ bool checkOSVersion(StringRef version, const char *errorMessage, return true; } -bool parseMinOSVersion(PECOFFTargetInfo &info, StringRef &osVersion, +// Parse -stack command line option. The form of the option is +// "-stack:stackReserveSize[,stackCommitSize]". +bool parseStackOption(PECOFFTargetInfo &info, const StringRef &arg, + raw_ostream &diagnostics) { + StringRef reserve, commit; + llvm::tie(reserve, commit) = arg.split(','); + if (!checkNumber(reserve, "invalid stack size: ", diagnostics)) + return false; + info.setStackReserve(atoi(reserve.str().c_str())); + if (!commit.empty()) { + if (!checkNumber(commit, "invalid stack size: ", diagnostics)) + return false; + info.setStackCommit(atoi(commit.str().c_str())); + } + return true; +} + +// Returns subsystem type for the given string. +llvm::COFF::WindowsSubsystem stringToWinSubsystem(StringRef str) { + std::string arg(str.lower()); + return llvm::StringSwitch<llvm::COFF::WindowsSubsystem>(arg) + .Case("windows", llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI) + .Case("console", llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI) + .Default(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN); +} + +bool parseMinOSVersion(PECOFFTargetInfo &info, const StringRef &osVersion, raw_ostream &diagnostics) { StringRef majorVersion, minorVersion; llvm::tie(majorVersion, minorVersion) = osVersion.split('.'); if (minorVersion.empty()) minorVersion = "0"; - if (!checkOSVersion(majorVersion, "invalid OS major version: ", diagnostics)) + if (!checkNumber(majorVersion, "invalid OS major version: ", diagnostics)) return false; - if (!checkOSVersion(minorVersion, "invalid OS minor version: ", diagnostics)) + if (!checkNumber(minorVersion, "invalid OS minor version: ", diagnostics)) return false; PECOFFTargetInfo::OSVersion minOSVersion(atoi(majorVersion.str().c_str()), atoi(minorVersion.str().c_str())); @@ -195,6 +211,11 @@ bool WinLinkDriver::parse(int argc, const char *argv[], info.appendLLVMOption((*it)->getValue()); } + // Handle -stack + if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_stack)) + if (!parseStackOption(info, arg->getValue(), diagnostics)) + return true; + // Handle -subsystem if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_subsystem)) if (!parseSubsystemOption(info, arg->getValue(), diagnostics)) diff --git a/lld/lib/Driver/WinLinkOptions.td b/lld/lib/Driver/WinLinkOptions.td index c32ae56cbe6..850814ae6f6 100644 --- a/lld/lib/Driver/WinLinkOptions.td +++ b/lld/lib/Driver/WinLinkOptions.td @@ -9,6 +9,10 @@ def out : Separate<["-", "/"], "out">, HelpText<"Path to file to write output">; def out_c : Joined<["-", "/"], "out:">, Alias<out>; +def stack : Separate<["-", "/"], "stack">, + HelpText<"Size of the stack">; +def stack_c: Joined<["-", "/"], "stack:">, Alias<stack>; + def subsystem : Separate<["-", "/"], "subsystem">, HelpText<"Specify subsystem">; def subsystem_c: Joined<["-", "/"], "subsystem:">, Alias<subsystem>; diff --git a/lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp b/lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp index 516479e65d5..a4c3e7ec4ab 100644 --- a/lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp +++ b/lld/lib/ReaderWriter/PECOFF/PECOFFTargetInfo.cpp @@ -23,6 +23,13 @@ error_code PECOFFTargetInfo::parseFile( } bool PECOFFTargetInfo::validate(raw_ostream &diagnostics) { + if (_stackReserve < _stackCommit) { + diagnostics << "Invalid stack size: reserve size must be equal to or " + << "greater than commit size, but got " + << _stackCommit << " and " << _stackReserve << ".\n"; + return true; + } + _reader = createReaderPECOFF(*this); _writer = createWriterPECOFF(*this); return false; diff --git a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp index af54e275f45..f8e4ae9f13d 100644 --- a/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp +++ b/lld/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp @@ -155,8 +155,8 @@ public: | llvm::COFF::IMAGE_DLL_CHARACTERISTICS_NX_COMPAT | llvm::COFF::IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE; - _peHeader.SizeOfStackReserve = 0x100000; - _peHeader.SizeOfStackCommit = 0x1000; + _peHeader.SizeOfStackReserve = targetInfo.getStackReserve(); + _peHeader.SizeOfStackCommit = targetInfo.getStackCommit(); _peHeader.SizeOfHeapReserve = 0x100000; _peHeader.SizeOfHeapCommit = 0x1000; diff --git a/lld/unittests/DriverTests/WinLinkDriverTest.cpp b/lld/unittests/DriverTests/WinLinkDriverTest.cpp index 0f85a867be4..fc05e42c924 100644 --- a/lld/unittests/DriverTests/WinLinkDriverTest.cpp +++ b/lld/unittests/DriverTests/WinLinkDriverTest.cpp @@ -44,6 +44,8 @@ TEST_F(WinLinkParserTest, Basic) { EXPECT_EQ("c.obj", inputFiles[2]); EXPECT_EQ(6, info->getMinOSVersion().majorVersion); EXPECT_EQ(0, info->getMinOSVersion().minorVersion); + EXPECT_EQ(1024 * 1024, info->getStackReserve()); + EXPECT_EQ(4096, info->getStackCommit()); } TEST_F(WinLinkParserTest, WindowsStyleOption) { @@ -83,4 +85,15 @@ TEST_F(WinLinkParserTest, MinMajorMinorOSVersion) { EXPECT_EQ(1, info->getMinOSVersion().minorVersion); } +TEST_F(WinLinkParserTest, StackReserve) { + parse("link.exe", "-stack", "8192", nullptr); + EXPECT_EQ(8192, info->getStackReserve()); + EXPECT_EQ(4096, info->getStackCommit()); +} + +TEST_F(WinLinkParserTest, StackReserveAndCommit) { + parse("link.exe", "-stack", "16384,8192", nullptr); + EXPECT_EQ(16384, info->getStackReserve()); + EXPECT_EQ(8192, info->getStackCommit()); +} } // end anonymous namespace |

