Skip to content

Commit

Permalink
Fix cross-compiling i686-pc-windows-gnu from Linux
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
neersighted authored and Manishearth committed Oct 28, 2018
1 parent 1982f18 commit a643cd3
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 9 deletions.
5 changes: 5 additions & 0 deletions src/bootstrap/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ pub fn std_cargo(builder: &Builder,
cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
}

// FIXME: Temporary detection of SJLJ MinGW compilers.
if build.build.build.contains("linux") && target == "i686-pc-windows-gnu" {
features.push_str(" sjlj_eh");
}

if builder.no_std(target) == Some(true) {
// for no-std targets we only compile a few no_std crates
cargo.arg("--features").arg("c mem")
Expand Down
3 changes: 3 additions & 0 deletions src/libstd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,6 @@ wasm_syscall = []
# the environment for hooking up some thread-related information like the
# current thread id and accessing/getting the current thread's TCB
wasm-bindgen-threads = []

# setjmp / longjmp exception handling for i686-pc-windows-gnu
sjlj_eh = ["unwind/sjlj_eh"]
3 changes: 3 additions & 0 deletions src/libunwind/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ doc = false
core = { path = "../libcore" }
libc = { path = "../rustc/libc_shim" }
compiler_builtins = { path = "../rustc/compiler_builtins_shim" }

[features]
sjlj_eh = []
40 changes: 31 additions & 9 deletions src/libunwind/libunwind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reaso
exception: *mut _Unwind_Exception);
extern "C" {
#[unwind(allowed)]
pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
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;
Expand Down Expand Up @@ -216,26 +215,49 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm
pc
}
}
} // cfg_if!

if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
// Not 32-bit iOS
cfg_if! {
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;
pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
trace_argument: *mut c_void)
-> _Unwind_Reason_Code;
pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
}
} else {
// 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()

#[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" {
#[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;
}

#[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" {
#[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!

0 comments on commit a643cd3

Please sign in to comment.