Skip to content

Commit

Permalink
[LLD] [MinGW] Implement the --no-seh flag
Browse files Browse the repository at this point in the history
Previously this flag was just ignored. If set, set the
IMAGE_DLL_CHARACTERISTICS_NO_SEH bit, regardless of the normal safeSEH
machinery.

In mingw configurations, the safeSEH bit might not be set in e.g. object
files built from handwritten assembly, making it impossible to use the
normal safeseh flag. As mingw setups don't generally use SEH on 32 bit
x86 at all, it should be fine to set that flag bit though - hook up
the existing GNU ld flag for controlling that.

Differential Revision: https://reviews.llvm.org/D84701
  • Loading branch information
mstorsjo committed Jul 28, 2020
1 parent 5608f28 commit 745eb02
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 5 deletions.
1 change: 1 addition & 0 deletions lld/COFF/Config.h
Expand Up @@ -140,6 +140,7 @@ struct Configuration {
bool safeSEH = false;
Symbol *sehTable = nullptr;
Symbol *sehCount = nullptr;
bool noSEH = false;

// Used for /opt:lldlto=N
unsigned ltoo = 2;
Expand Down
7 changes: 4 additions & 3 deletions lld/COFF/Driver.cpp
Expand Up @@ -1700,9 +1700,10 @@ void LinkerDriver::link(ArrayRef<const char *> argsArr) {
config->wordsize = config->is64() ? 8 : 4;

// Handle /safeseh, x86 only, on by default, except for mingw.
if (config->machine == I386 &&
args.hasFlag(OPT_safeseh, OPT_safeseh_no, !config->mingw))
config->safeSEH = true;
if (config->machine == I386) {
config->safeSEH = args.hasFlag(OPT_safeseh, OPT_safeseh_no, !config->mingw);
config->noSEH = args.hasArg(OPT_noseh);
}

// Handle /functionpadmin
for (auto *arg : args.filtered(OPT_functionpadmin, OPT_functionpadmin_opt))
Expand Down
1 change: 1 addition & 0 deletions lld/COFF/Options.td
Expand Up @@ -204,6 +204,7 @@ def include_optional : Joined<["/", "-", "/?", "-?"], "includeoptional:">,
HelpText<"Add symbol as undefined, but allow it to remain undefined">;
def kill_at : F<"kill-at">;
def lldmingw : F<"lldmingw">;
def noseh : F<"noseh">;
def output_def : Joined<["/", "-", "/?", "-?"], "output-def:">;
def pdb_source_path : P<"pdbsourcepath",
"Base path used to make relative source file path absolute in PDB">;
Expand Down
2 changes: 1 addition & 1 deletion lld/COFF/Writer.cpp
Expand Up @@ -1393,7 +1393,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_GUARD_CF;
if (config->integrityCheck)
pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY;
if (setNoSEHCharacteristic)
if (setNoSEHCharacteristic || config->noSEH)
pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_SEH;
if (config->terminalServerAware)
pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE;
Expand Down
2 changes: 2 additions & 0 deletions lld/MinGW/Driver.cpp
Expand Up @@ -288,6 +288,8 @@ bool mingw::link(ArrayRef<const char *> argsArr, bool canExitEarly,
add("-kill-at");
if (args.hasArg(OPT_appcontainer))
add("-appcontainer");
if (args.hasArg(OPT_no_seh))
add("-noseh");

if (args.getLastArgValue(OPT_m) != "thumb2pe" &&
args.getLastArgValue(OPT_m) != "arm64pe" && !args.hasArg(OPT_dynamicbase))
Expand Down
2 changes: 1 addition & 1 deletion lld/MinGW/Options.td
Expand Up @@ -56,6 +56,7 @@ defm minor_subsystem_version: EqLong<"minor-subsystem-version",
"Set the OS and subsystem minor version">;
def no_insert_timestamp: F<"no-insert-timestamp">,
HelpText<"Don't include PE header timestamp">;
def no_seh: F<"no-seh">, HelpText<"Set the 'no SEH' flag in the executable">;
def no_whole_archive: F<"no-whole-archive">,
HelpText<"No longer include all object files for following archives">;
def large_address_aware: Flag<["--"], "large-address-aware">,
Expand Down Expand Up @@ -111,7 +112,6 @@ def: Flag<["--"], "full-shutdown">;
def: F<"high-entropy-va">;
def: S<"major-image-version">;
def: S<"minor-image-version">;
def: F<"no-seh">;
def: F<"nxcompat">;
def: F<"pic-executable">;
def: S<"plugin">;
Expand Down
19 changes: 19 additions & 0 deletions lld/test/COFF/noseh.s
@@ -0,0 +1,19 @@
# REQUIRES: x86
# RUN: llvm-mc -triple i686-w64-mingw32 %s -filetype=obj -o %t.obj
# RUN: lld-link -lldmingw %t.obj -out:%t.exe -entry:main
# RUN: llvm-readobj --file-headers %t.exe | FileCheck %s --check-prefix=DEFAULT
# RUN: lld-link -lldmingw %t.obj -out:%t.noseh.exe -entry:main -noseh
# RUN: llvm-readobj --file-headers %t.noseh.exe | FileCheck %s --check-prefix=NOSEH

# DEFAULT: Characteristics [
# DEFAULT-NOT: IMAGE_DLL_CHARACTERISTICS_NO_SEH
# DEFAULT: ]

# NOSEH: Characteristics [
# NOSEH: IMAGE_DLL_CHARACTERISTICS_NO_SEH
# NOSEH: ]

.text
.globl _main
_main:
ret
4 changes: 4 additions & 0 deletions lld/test/MinGW/driver.test
Expand Up @@ -256,3 +256,7 @@ RUN: ld.lld -### -m i386pep foo.o -section-alignment 0x2000 | FileCheck -check-p
RUN: ld.lld -### -m i386pep foo.o --section-alignment=0x2000 | FileCheck -check-prefix ALIGN %s
RUN: ld.lld -### -m i386pep foo.o -section-alignment=0x2000 | FileCheck -check-prefix ALIGN %s
ALIGN: -align:0x2000

RUN: ld.lld -### -m i386pe foo.o -no-seh | FileCheck -check-prefix NOSEH %s
RUN: ld.lld -### -m i386pe foo.o --no-seh | FileCheck -check-prefix NOSEH %s
NOSEH: -noseh

0 comments on commit 745eb02

Please sign in to comment.