commit d40f58678503123fcbacbbbcd6c19b37e167ab86 Author: Georg Koppen gk@torproject.org Date: Sat Sep 5 11:25:23 2020 +0000
Bug 40071: Be explicit about no SEH with mingw-w64 on 32bit systems --- projects/clang-source/build | 7 ++ projects/clang-source/config | 2 + projects/clang-source/no-seh.patch | 145 +++++++++++++++++++++++++++++++++++++ projects/firefox/build | 2 + projects/mingw-w64/build | 4 +- rbm.conf | 4 +- 6 files changed, 161 insertions(+), 3 deletions(-)
diff --git a/projects/clang-source/build b/projects/clang-source/build index 860b8e4..d94fcbe 100644 --- a/projects/clang-source/build +++ b/projects/clang-source/build @@ -19,6 +19,13 @@ mv clang-tools-extra-[% c("version") %].src llvm/tools/clang/tools/extra mv libcxx-[% c("version") %].src llvm/projects/libcxx mv libcxxabi-[% c("version") %].src llvm/projects/libcxxabi mv lld-[% c("version") %].src llvm/tools/lld +[% IF c("var/windows-i686") %] + # mingw-w64 does not support SEH on 32bit systems. Make it possible to + # explicitly disable it. + cd llvm/tools + patch -p1 < $rootdir/no-seh.patch + cd ../../ +[% END %] mv compiler-rt-[% c("version") %].src llvm/projects/compiler-rt # We need libunwind only for mingw-w64-clang, don't include it as tightly by # putting it into projects/ diff --git a/projects/clang-source/config b/projects/clang-source/config index d0ae90c..8adb18e 100644 --- a/projects/clang-source/config +++ b/projects/clang-source/config @@ -30,3 +30,5 @@ input_files: name: libunwind file_gpg_id: 1 - filename: 43909.patch + - filename: no-seh.patch + enable: '[% c("var/windows-i686") %]' diff --git a/projects/clang-source/no-seh.patch b/projects/clang-source/no-seh.patch new file mode 100644 index 0000000..1a52e40 --- /dev/null +++ b/projects/clang-source/no-seh.patch @@ -0,0 +1,145 @@ +From 38cbe873d45cf3c881ef4113b48193edfd418f43 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Martin=20Storsj=C3=B6?= martin@martin.st +Date: Mon, 27 Jul 2020 23:44:41 +0300 +Subject: [PATCH] Implement the --no-seh flag + +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 + +diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h +index 4b62cd05f4f..17ea0f8bcab 100644 +--- a/lld/COFF/Config.h ++++ b/lld/COFF/Config.h +@@ -135,6 +135,7 @@ struct Configuration { + bool safeSEH = false; + Symbol *sehTable = nullptr; + Symbol *sehCount = nullptr; ++ bool noSEH = false; + + // Used for /opt:lldlto=N + unsigned ltoo = 2; +diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp +index 15d6fb5121a..b569df07601 100644 +--- a/lld/COFF/Driver.cpp ++++ b/lld/COFF/Driver.cpp +@@ -1574,9 +1574,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)) +diff --git a/lld/COFF/Options.td b/lld/COFF/Options.td +index 024b7be8f78..c7e2a5ea57e 100644 +--- a/lld/COFF/Options.td ++++ b/lld/COFF/Options.td +@@ -171,6 +171,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">; +diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp +index 5736281958f..aead781d38b 100644 +--- a/lld/COFF/Writer.cpp ++++ b/lld/COFF/Writer.cpp +@@ -1352,7 +1352,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; +diff --git a/lld/MinGW/Driver.cpp b/lld/MinGW/Driver.cpp +index be1b757e45b..1d292817cfb 100644 +--- a/lld/MinGW/Driver.cpp ++++ b/lld/MinGW/Driver.cpp +@@ -249,6 +249,8 @@ bool mingw::link(ArrayRef<const char *> argsArr, raw_ostream &diag) { + 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)) +diff --git a/lld/MinGW/Options.td b/lld/MinGW/Options.td +index 86400433d04..931cf264837 100644 +--- a/lld/MinGW/Options.td ++++ b/lld/MinGW/Options.td +@@ -45,6 +45,7 @@ def minor_subsystem_version_eq: Joined<["--"], "minor-subsystem-version=">, + Alias<minor_subsystem_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">, +@@ -104,7 +105,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">; +diff --git a/lld/test/COFF/noseh.s b/lld/test/COFF/noseh.s +new file mode 100644 +index 00000000000..44295228622 +--- /dev/null ++++ b/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 +diff --git a/lld/test/MinGW/driver.test b/lld/test/MinGW/driver.test +index b8bc2ddea8a..1d53205927b 100644 +--- a/lld/test/MinGW/driver.test ++++ b/lld/test/MinGW/driver.test +@@ -204,3 +204,7 @@ APPCONTAINER: -appcontainer + RUN: ld.lld -### -m i386pep foo.o -delayload user32.dll --delayload shell32.dll | FileCheck -check-prefix DELAYLOAD %s + RUN: ld.lld -### -m i386pep foo.o -delayload=user32.dll --delayload=shell32.dll | FileCheck -check-prefix DELAYLOAD %s + DELAYLOAD: -delayload:user32.dll -delayload:shell32.dll ++ ++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 +-- +2.28.0 + diff --git a/projects/firefox/build b/projects/firefox/build index d3c7139..63be146 100644 --- a/projects/firefox/build +++ b/projects/firefox/build @@ -77,6 +77,8 @@ fi # Make sure widl is not inserting random timestamps, see #21837. export WIDL_TIME_OVERRIDE="0" patch -p1 < $rootdir/nsis-uninstall.patch + # mingw-w64 does not support SEH on 32bit systems. Be explicit about that. + export LDFLAGS="[% c('var/flag_noSEH') %]" [% END -%]
[% IF c("var/namecoin") %] diff --git a/projects/mingw-w64/build b/projects/mingw-w64/build index c5fcda6..155c531 100644 --- a/projects/mingw-w64/build +++ b/projects/mingw-w64/build @@ -24,7 +24,7 @@ cd gcc tar xJf $rootdir/gcc-[% c("var/gcc_version") %].tar.xz # LDFLAGS_FOR_TARGET does not work for some reason. Thus, we take # CFLAGS_FOR_TARGET. -export CFLAGS_FOR_TARGET="-Wl,--nxcompat -Wl,--dynamicbase -Wl,--no-insert-timestamp" +export CFLAGS_FOR_TARGET="-Wl,--nxcompat -Wl,--dynamicbase -Wl,--no-insert-timestamp [% c('var/flag_noSEH') %]" # Rust requires enabling pthreads gcc-[% c("var/gcc_version") %]/configure --prefix=$distdir --target=[% c("arch") %]-w64-mingw32 --with-gnu-ld --with-gnu-as --disable-multilib --enable-threads=posix --enable-languages=c,c++ make -j[% c("buildconf/num_procs") %] all-gcc @@ -40,7 +40,7 @@ make install mkdir -p /var/tmp/build/builddir/mingw-w64/mingw-w64-pthread cd /var/tmp/build/builddir/mingw-w64/mingw-w64-pthread /var/tmp/build/[% project %]-[% c("version") %]/mingw-w64-libraries/winpthreads/configure \ - LDFLAGS="-Wl,--dynamicbase -Wl,--nxcompat -Wl,--enable-reloc-section -Wl,--no-insert-timestamp" \ + LDFLAGS="-Wl,--dynamicbase -Wl,--nxcompat -Wl,--enable-reloc-section -Wl,--no-insert-timestamp [% c('var/flag_noSEH') %]" \ --host=[% c("arch") %]-w64-mingw32 --prefix=$distdir/[% c("arch") %]-w64-mingw32 make -j[% c("buildconf/num_procs") %] make install diff --git a/rbm.conf b/rbm.conf index b5dff53..9ee4f18 100644 --- a/rbm.conf +++ b/rbm.conf @@ -368,6 +368,8 @@ targets: windows-i686: 1 windows-x86_64: 0 osname: windows-i686 + # mingw-w64 does not support SEH on 32bit systems. Be explicit about that. + flag_noSEH: '-Wl,--no-seh' windows: var: windows: 1 @@ -376,7 +378,7 @@ targets: arch: amd64 configure_opt: '--host=[% c("arch") %]-w64-mingw32 CFLAGS="[% c("var/CFLAGS") %]" LDFLAGS="[% c("var/LDFLAGS") %]" [% c("var/configure_opt_project") %]' CFLAGS: '-fstack-protector-strong -fno-strict-overflow -Wno-missing-field-initializers -Wformat -Wformat-security [% c("var/flag_mwindows") %]' - LDFLAGS: '-Wl,--dynamicbase -Wl,--nxcompat -Wl,--enable-reloc-section -Wl,--no-insert-timestamp -lssp -L$gcclibs [% c("var/flag_HEASLR") %] [% c("var/flag_mwindows") %]' + LDFLAGS: '-Wl,--dynamicbase -Wl,--nxcompat -Wl,--enable-reloc-section -Wl,--no-insert-timestamp -lssp -L$gcclibs [% c("var/flag_HEASLR") %] [% c("var/flag_noSEH") %] [% c("var/flag_mwindows") %]' flag_mwindows: '-mwindows' compiler: mingw-w64 faketime_path: /usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1