Loading projects/mingw-w64/build +1 −1 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ tar xJf $rootdir/gcc-[% c("var/gcc_version") %].tar.xz # CFLAGS_FOR_TARGET. 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++ 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++[% IF c("var/windows-i686") %] --disable-sjlj-exceptions --with-dwarf2[% END %] make -j[% c("buildconf/num_procs") %] all-gcc make install-gcc Loading projects/mingw-w64/config +1 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ var: targets: windows-i686: var: libgcc_dll: libgcc_s_sjlj-1.dll libgcc_dll: libgcc_s_dw2-1.dll arch_deps: - g++-mingw-w64-i686 windows-x86_64: Loading projects/rust/build +0 −10 Original line number Diff line number Diff line Loading @@ -58,16 +58,6 @@ cd /var/tmp/build/rustc-[% c('version') %]-src patch -p1 < $rootdir/fix-build-1.53.0.patch [% END %] [% IF c("var/windows-i686") %] # Cross-compiling for Windows 32bit is currently not possible without any # patches. The reason for that is libstd expecting DWARF unwinding while most # toolchains on Linux, targeting Windows 32bit, use SjLj unwinding. # See: https://github.com/rust-lang/rust/issues/12859 for discussion about # that and https://github.com/rust-lang/rust/pull/49633 for a newer attempt to # fix this problem. We apply the patch from neersighted. patch -p1 < $rootdir/unwind.patch [% END %] mkdir build cd build ../configure --prefix=$distdir --disable-docs --disable-compiler-docs [% c("var/configure_opt") %] Loading projects/rust/config +0 −2 Original line number Diff line number Diff line Loading @@ -99,8 +99,6 @@ input_files: - project: python name: python enable: '[% c("var/linux") %]' - filename: unwind.patch enable: '[% c("var/windows-i686") %]' - filename: 43909.patch name: 43909 enable: '[% ! c("var/ff91esr") %]' Loading projects/rust/unwind.patchdeleted 100644 → 0 +0 −163 Original line number Diff line number Diff line From 90ddcca6235b5f24c57df6a648e8d489c7e3eae5 Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard <bjorn@neersighted.com> Date: Sat, 9 Feb 2019 19:39:23 +0000 Subject: [PATCH] Fix cross-compiling i686-pc-windows-gnu from Linux This is still very rough and serves as a proof-of-concept for fixing Linux -> 32-bit MinGW cross compilation workflow. Currently, clang and GCC's MinGW targets both only support DW2 (DWARF) or SJLJ (Set Jump Long Jump) unwinding on 32-bit Windows. The default for GCC (and the way it is shipped on every major distro) is to use SJLJ on Windows, as DWARF cannot traverse non-DWARF frames. This would work fine, except for the fact that libgcc (our C runtime on the MinGW platform) exports symbols under a different name when configured to use SJLJ-style unwinding, and uses a preprocessor macro internally to alias them. Because of this, we have to detect this scenario and link to the correct symbols ourselves. Linking has been tested with a full bootstrap on both x86_64-unknown-linux-gnu and i686-pc-windows-gnu, as well as cross-compilation of some of my own projects. Obviously, the detection is a bit unrefined. Right now we unconditionally use SJLJ when compiling Linux -> MinGW. I'd like to add feature detection using compiler build flags or autotools-style compilation and object analysis. Input on the best way to proceed here is welcome. Also, currently there is copy-pasted/duplicated code in libunwind. Ideally, this could be reduced, but this would likely require a rethinking of how iOS is special-cased above, to avoid further duplication. Input on how to best structure this file is requested. diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 65a00db3394..e821507c341 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -207,6 +207,11 @@ pub fn std_cargo(builder: &Builder<'_>, target: Interned<String>, cargo: &mut Ca let mut features = builder.std_features(); features.push_str(&compiler_builtins_c_feature); + // FIXME: Temporary detection of SJLJ MinGW compilers. + if builder.config.build.contains("linux") && target == "i686-pc-windows-gnu" { + features.push_str(" sjlj_eh"); + } + cargo .arg("--features") .arg(features) diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index b147aa55b2a..cad4d88caa2 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -68,6 +68,7 @@ panic_immediate_abort = ["core/panic_immediate_abort"] # https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml std_detect_file_io = [] std_detect_dlsym_getauxval = [] +sjlj_eh = ["unwind/sjlj_eh"] [package.metadata.fortanix-sgx] # Maximum possible number of threads when testing diff --git a/src/libtest/Cargo.toml b/src/libtest/Cargo.toml index 170fbb984cf..b1b0be71067 100644 --- a/src/libtest/Cargo.toml +++ b/src/libtest/Cargo.toml @@ -29,3 +29,4 @@ llvm-libunwind = ["std/llvm-libunwind"] panic-unwind = ["std/panic_unwind"] panic_immediate_abort = ["std/panic_immediate_abort"] profiler = ["std/profiler"] +sjlj_eh = ["std/sjlj_eh"] diff --git a/src/libunwind/Cargo.toml b/src/libunwind/Cargo.toml index 77bcfffd506..9d9fc5fbff5 100644 --- a/src/libunwind/Cargo.toml +++ b/src/libunwind/Cargo.toml @@ -26,3 +26,4 @@ cc = { version = "1.0.1" } [features] llvm-libunwind = [] +sjlj_eh = [] diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs index 0c57861f70a..44c767ebfc5 100644 --- a/src/libunwind/libunwind.rs +++ b/src/libunwind/libunwind.rs @@ -79,8 +79,8 @@ pub type _Unwind_Exception_Cleanup_Fn = link(name = "unwind", kind = "static") )] extern "C" { - #[unwind(allowed)] - pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !; + #[cfg_attr(stage0, unwind)] + #[cfg_attr(not(stage0), unwind(allowed))] pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception); pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void; pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr; @@ -222,32 +222,50 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm } // cfg_if! cfg_if::cfg_if! { -if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] { - // Not 32-bit iOS - #[cfg_attr(all(feature = "llvm-libunwind", - any(target_os = "fuchsia", target_os = "linux")), - link(name = "unwind", kind = "static"))] +if #[cfg(all(target_os = "ios", target_arch = "arm"))] { + // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace() extern "C" { - #[unwind(allowed)] - pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code; + #[cfg_attr(stage0, unwind)] + #[cfg_attr(not(stage0), unwind(allowed))] + pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !; + pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code; + } + + #[inline] + pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code { + _Unwind_SjLj_RaiseException(exc) + } + +} else if #[cfg(feature = "sjlj_eh")] { + extern "C" { + #[cfg_attr(stage0, unwind)] + #[cfg_attr(not(stage0), unwind(allowed))] + pub fn _Unwind_SjLj_Resume(e: *mut _Unwind_Exception) -> !; + pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code; pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn, trace_argument: *mut c_void) -> _Unwind_Reason_Code; } -} else { - // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace() - #[cfg_attr(all(feature = "llvm-libunwind", - any(target_os = "fuchsia", target_os = "linux")), - link(name = "unwind", kind = "static"))] - extern "C" { - #[unwind(allowed)] - pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code; + + #[inline] + pub unsafe fn _Unwind_Resume(exc: *mut _Unwind_Exception) -> ! { + _Unwind_SjLj_Resume(exc) } #[inline] pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code { _Unwind_SjLj_RaiseException(exc) } +} else { + extern "C" { + #[cfg_attr(stage0, unwind)] + #[cfg_attr(not(stage0), unwind(allowed))] + pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !; + pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code; + pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn, + trace_argument: *mut c_void) + -> _Unwind_Reason_Code; + } } } // cfg_if! -- 2.28.0 Loading
projects/mingw-w64/build +1 −1 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ tar xJf $rootdir/gcc-[% c("var/gcc_version") %].tar.xz # CFLAGS_FOR_TARGET. 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++ 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++[% IF c("var/windows-i686") %] --disable-sjlj-exceptions --with-dwarf2[% END %] make -j[% c("buildconf/num_procs") %] all-gcc make install-gcc Loading
projects/mingw-w64/config +1 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ var: targets: windows-i686: var: libgcc_dll: libgcc_s_sjlj-1.dll libgcc_dll: libgcc_s_dw2-1.dll arch_deps: - g++-mingw-w64-i686 windows-x86_64: Loading
projects/rust/build +0 −10 Original line number Diff line number Diff line Loading @@ -58,16 +58,6 @@ cd /var/tmp/build/rustc-[% c('version') %]-src patch -p1 < $rootdir/fix-build-1.53.0.patch [% END %] [% IF c("var/windows-i686") %] # Cross-compiling for Windows 32bit is currently not possible without any # patches. The reason for that is libstd expecting DWARF unwinding while most # toolchains on Linux, targeting Windows 32bit, use SjLj unwinding. # See: https://github.com/rust-lang/rust/issues/12859 for discussion about # that and https://github.com/rust-lang/rust/pull/49633 for a newer attempt to # fix this problem. We apply the patch from neersighted. patch -p1 < $rootdir/unwind.patch [% END %] mkdir build cd build ../configure --prefix=$distdir --disable-docs --disable-compiler-docs [% c("var/configure_opt") %] Loading
projects/rust/config +0 −2 Original line number Diff line number Diff line Loading @@ -99,8 +99,6 @@ input_files: - project: python name: python enable: '[% c("var/linux") %]' - filename: unwind.patch enable: '[% c("var/windows-i686") %]' - filename: 43909.patch name: 43909 enable: '[% ! c("var/ff91esr") %]' Loading
projects/rust/unwind.patchdeleted 100644 → 0 +0 −163 Original line number Diff line number Diff line From 90ddcca6235b5f24c57df6a648e8d489c7e3eae5 Mon Sep 17 00:00:00 2001 From: Bjorn Neergaard <bjorn@neersighted.com> Date: Sat, 9 Feb 2019 19:39:23 +0000 Subject: [PATCH] Fix cross-compiling i686-pc-windows-gnu from Linux This is still very rough and serves as a proof-of-concept for fixing Linux -> 32-bit MinGW cross compilation workflow. Currently, clang and GCC's MinGW targets both only support DW2 (DWARF) or SJLJ (Set Jump Long Jump) unwinding on 32-bit Windows. The default for GCC (and the way it is shipped on every major distro) is to use SJLJ on Windows, as DWARF cannot traverse non-DWARF frames. This would work fine, except for the fact that libgcc (our C runtime on the MinGW platform) exports symbols under a different name when configured to use SJLJ-style unwinding, and uses a preprocessor macro internally to alias them. Because of this, we have to detect this scenario and link to the correct symbols ourselves. Linking has been tested with a full bootstrap on both x86_64-unknown-linux-gnu and i686-pc-windows-gnu, as well as cross-compilation of some of my own projects. Obviously, the detection is a bit unrefined. Right now we unconditionally use SJLJ when compiling Linux -> MinGW. I'd like to add feature detection using compiler build flags or autotools-style compilation and object analysis. Input on the best way to proceed here is welcome. Also, currently there is copy-pasted/duplicated code in libunwind. Ideally, this could be reduced, but this would likely require a rethinking of how iOS is special-cased above, to avoid further duplication. Input on how to best structure this file is requested. diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 65a00db3394..e821507c341 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -207,6 +207,11 @@ pub fn std_cargo(builder: &Builder<'_>, target: Interned<String>, cargo: &mut Ca let mut features = builder.std_features(); features.push_str(&compiler_builtins_c_feature); + // FIXME: Temporary detection of SJLJ MinGW compilers. + if builder.config.build.contains("linux") && target == "i686-pc-windows-gnu" { + features.push_str(" sjlj_eh"); + } + cargo .arg("--features") .arg(features) diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index b147aa55b2a..cad4d88caa2 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -68,6 +68,7 @@ panic_immediate_abort = ["core/panic_immediate_abort"] # https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml std_detect_file_io = [] std_detect_dlsym_getauxval = [] +sjlj_eh = ["unwind/sjlj_eh"] [package.metadata.fortanix-sgx] # Maximum possible number of threads when testing diff --git a/src/libtest/Cargo.toml b/src/libtest/Cargo.toml index 170fbb984cf..b1b0be71067 100644 --- a/src/libtest/Cargo.toml +++ b/src/libtest/Cargo.toml @@ -29,3 +29,4 @@ llvm-libunwind = ["std/llvm-libunwind"] panic-unwind = ["std/panic_unwind"] panic_immediate_abort = ["std/panic_immediate_abort"] profiler = ["std/profiler"] +sjlj_eh = ["std/sjlj_eh"] diff --git a/src/libunwind/Cargo.toml b/src/libunwind/Cargo.toml index 77bcfffd506..9d9fc5fbff5 100644 --- a/src/libunwind/Cargo.toml +++ b/src/libunwind/Cargo.toml @@ -26,3 +26,4 @@ cc = { version = "1.0.1" } [features] llvm-libunwind = [] +sjlj_eh = [] diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs index 0c57861f70a..44c767ebfc5 100644 --- a/src/libunwind/libunwind.rs +++ b/src/libunwind/libunwind.rs @@ -79,8 +79,8 @@ pub type _Unwind_Exception_Cleanup_Fn = link(name = "unwind", kind = "static") )] extern "C" { - #[unwind(allowed)] - pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !; + #[cfg_attr(stage0, unwind)] + #[cfg_attr(not(stage0), unwind(allowed))] pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception); pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void; pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr; @@ -222,32 +222,50 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm } // cfg_if! cfg_if::cfg_if! { -if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] { - // Not 32-bit iOS - #[cfg_attr(all(feature = "llvm-libunwind", - any(target_os = "fuchsia", target_os = "linux")), - link(name = "unwind", kind = "static"))] +if #[cfg(all(target_os = "ios", target_arch = "arm"))] { + // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace() extern "C" { - #[unwind(allowed)] - pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code; + #[cfg_attr(stage0, unwind)] + #[cfg_attr(not(stage0), unwind(allowed))] + pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !; + pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code; + } + + #[inline] + pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code { + _Unwind_SjLj_RaiseException(exc) + } + +} else if #[cfg(feature = "sjlj_eh")] { + extern "C" { + #[cfg_attr(stage0, unwind)] + #[cfg_attr(not(stage0), unwind(allowed))] + pub fn _Unwind_SjLj_Resume(e: *mut _Unwind_Exception) -> !; + pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code; pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn, trace_argument: *mut c_void) -> _Unwind_Reason_Code; } -} else { - // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace() - #[cfg_attr(all(feature = "llvm-libunwind", - any(target_os = "fuchsia", target_os = "linux")), - link(name = "unwind", kind = "static"))] - extern "C" { - #[unwind(allowed)] - pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code; + + #[inline] + pub unsafe fn _Unwind_Resume(exc: *mut _Unwind_Exception) -> ! { + _Unwind_SjLj_Resume(exc) } #[inline] pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code { _Unwind_SjLj_RaiseException(exc) } +} else { + extern "C" { + #[cfg_attr(stage0, unwind)] + #[cfg_attr(not(stage0), unwind(allowed))] + pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !; + pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code; + pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn, + trace_argument: *mut c_void) + -> _Unwind_Reason_Code; + } } } // cfg_if! -- 2.28.0