[PECOFF] Driver support for /SAFESEH option.

Syntactically /SAFESEH is a boolean flag -- you can pass /SAFESEH or /SAFESEH:no.

The meaning of /SAFESEH is as follows.

 - If /SAFESEH is specified, the linker will produce an executable with SEH table.
   If any input files are not compatible with SEH, it's an error.
 - If /SAFESEH:no is specified, the linker will not emit SEH table even if all
   input files are compatible with SEH.
 - If no option is specified, the linker emits SEH table if all input files are
   compatible with SEH.

llvm-svn: 201895
This commit is contained in:
Rui Ueyama 2014-02-21 22:30:43 +00:00
parent 695fdb3bc2
commit d9e7c22ee4
4 changed files with 39 additions and 2 deletions

View File

@ -46,7 +46,8 @@ public:
_terminalServerAware(true), _dynamicBaseEnabled(true),
_createManifest(true), _embedManifest(false), _manifestId(1),
_manifestLevel("'asInvoker'"), _manifestUiAccess("'false'"),
_isDll(false), _dosStub(llvm::makeArrayRef(DEFAULT_DOS_STUB)) {
_isDll(false), _requireSEH(false), _noSEH(false),
_dosStub(llvm::makeArrayRef(DEFAULT_DOS_STUB)) {
setDeadStripping(true);
}
@ -194,6 +195,15 @@ public:
void setIsDll(bool val) { _isDll = val; }
bool isDll() const { return _isDll; }
void setSafeSEH(bool val) {
if (val)
_requireSEH = true;
else
_noSEH = true;
}
bool requireSEH() const { return _requireSEH; }
bool noSEH() const { return _noSEH; }
StringRef getOutputSectionName(StringRef sectionName) const;
bool addSectionRenaming(raw_ostream &diagnostics,
StringRef from, StringRef to);
@ -288,6 +298,16 @@ private:
std::string _manifestDependency;
bool _isDll;
// True if /SAFESEH option is specified. Valid only for x86. If true, LLD will
// produce an image with SEH table. If any modules were not compatible with
// SEH, LLD will exit with an error.
bool _requireSEH;
// True if /SAFESEH:no option is specified. Valid only for x86. If true, LLD
// will not produce an image with SEH table even if all input object files are
// compatible with SEH.
bool _noSEH;
// The set to store /nodefaultlib arguments.
std::set<std::string> _noDefaultLibs;

View File

@ -1047,6 +1047,7 @@ WinLinkDriver::parse(int argc, const char *argv[], PECOFFLinkingContext &ctx,
DEFINE_BOOLEAN_FLAG(allowisolation, setAllowIsolation);
DEFINE_BOOLEAN_FLAG(dynamicbase, setDynamicBaseEnabled);
DEFINE_BOOLEAN_FLAG(tsaware, setTerminalServerAware);
DEFINE_BOOLEAN_FLAG(safeseh, setSafeSEH);
#undef DEFINE_BOOLEAN_FLAG

View File

@ -78,6 +78,7 @@ defm tsaware : B<"tsaware", "Create non-Terminal Server aware executable">;
defm allowisolation : B<"allowisolation", "Set NO_ISOLATION bit">;
defm dynamicbase : B<"dynamicbase",
"Disable address space layout randomization">;
defm safeseh : B<"safeseh", "Produce an image with Safe Exception Handler">;
def help : F<"help">;
def help_q : Flag<["/?", "-?"], "">, Alias<help>;
@ -113,4 +114,3 @@ def tlbout : QF<"tlbout">;
def verbose_all : QF<"verbose">;
defm wx : QB<"wx">;
defm safeseh : QB<"safeseh">;

View File

@ -442,6 +442,22 @@ TEST_F(WinLinkParserTest, NoEntryError) {
EXPECT_EQ("/noentry must be specified with /dll\n", errorMessage());
}
//
// Tests for SEH.
//
TEST_F(WinLinkParserTest, SafeSEH) {
EXPECT_TRUE(parse("link.exe", "/safeseh", "a.obj", nullptr));
EXPECT_TRUE(_context.requireSEH());
EXPECT_FALSE(_context.noSEH());
}
TEST_F(WinLinkParserTest, NoSafeSEH) {
EXPECT_TRUE(parse("link.exe", "/safeseh:no", "a.obj", nullptr));
EXPECT_FALSE(_context.requireSEH());
EXPECT_TRUE(_context.noSEH());
}
//
// Tests for boolean flags.
//