Skip to content

Commit a643cd3

Browse files
neersightedManishearth
authored andcommitted
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.
1 parent 1982f18 commit a643cd3

File tree

4 files changed

+42
-9
lines changed

4 files changed

+42
-9
lines changed

Diff for: src/bootstrap/compile.rs

+5
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ pub fn std_cargo(builder: &Builder,
150150
cargo.env("MACOSX_DEPLOYMENT_TARGET", target);
151151
}
152152

153+
// FIXME: Temporary detection of SJLJ MinGW compilers.
154+
if build.build.build.contains("linux") && target == "i686-pc-windows-gnu" {
155+
features.push_str(" sjlj_eh");
156+
}
157+
153158
if builder.no_std(target) == Some(true) {
154159
// for no-std targets we only compile a few no_std crates
155160
cargo.arg("--features").arg("c mem")

Diff for: src/libstd/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,6 @@ wasm_syscall = []
5858
# the environment for hooking up some thread-related information like the
5959
# current thread id and accessing/getting the current thread's TCB
6060
wasm-bindgen-threads = []
61+
62+
# setjmp / longjmp exception handling for i686-pc-windows-gnu
63+
sjlj_eh = ["unwind/sjlj_eh"]

Diff for: src/libunwind/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@ doc = false
1515
core = { path = "../libcore" }
1616
libc = { path = "../rustc/libc_shim" }
1717
compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
18+
19+
[features]
20+
sjlj_eh = []

Diff for: src/libunwind/libunwind.rs

+31-9
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reaso
8484
exception: *mut _Unwind_Exception);
8585
extern "C" {
8686
#[unwind(allowed)]
87-
pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
8887
pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
8988
pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
9089
pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
@@ -216,26 +215,49 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm
216215
pc
217216
}
218217
}
218+
} // cfg_if!
219219

220-
if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
221-
// Not 32-bit iOS
220+
cfg_if! {
221+
if #[cfg(all(target_os = "ios", target_arch = "arm"))] {
222+
// 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
222223
extern "C" {
223224
#[unwind(allowed)]
224-
pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
225-
pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
226-
trace_argument: *mut c_void)
227-
-> _Unwind_Reason_Code;
225+
pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
226+
pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
228227
}
229-
} else {
230-
// 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
228+
229+
#[inline]
230+
pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
231+
_Unwind_SjLj_RaiseException(exc)
232+
}
233+
234+
} else if #[cfg(feature = "sjlj_eh")] {
231235
extern "C" {
232236
#[unwind(allowed)]
237+
pub fn _Unwind_SjLj_Resume(e: *mut _Unwind_Exception) -> !;
233238
pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
239+
pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
240+
trace_argument: *mut c_void)
241+
-> _Unwind_Reason_Code;
242+
}
243+
244+
#[inline]
245+
pub unsafe fn _Unwind_Resume(exc: *mut _Unwind_Exception) -> ! {
246+
_Unwind_SjLj_Resume(exc)
234247
}
235248

236249
#[inline]
237250
pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
238251
_Unwind_SjLj_RaiseException(exc)
239252
}
253+
} else {
254+
extern "C" {
255+
#[unwind(allowed)]
256+
pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
257+
pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
258+
pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
259+
trace_argument: *mut c_void)
260+
-> _Unwind_Reason_Code;
261+
}
240262
}
241263
} // cfg_if!

0 commit comments

Comments
 (0)