diff options
Diffstat (limited to 'src/libstd/sys/common')
| -rw-r--r-- | src/libstd/sys/common/libunwind.rs | 51 | ||||
| -rw-r--r-- | src/libstd/sys/common/unwind/gcc.rs | 33 | ||||
| -rw-r--r-- | src/libstd/sys/common/unwind/mod.rs | 41 | ||||
| -rw-r--r-- | src/libstd/sys/common/unwind/seh64_gnu.rs | 11 |
4 files changed, 81 insertions, 55 deletions
diff --git a/src/libstd/sys/common/libunwind.rs b/src/libstd/sys/common/libunwind.rs index da7ebbf4ed3..75bb11216e1 100644 --- a/src/libstd/sys/common/libunwind.rs +++ b/src/libstd/sys/common/libunwind.rs @@ -99,35 +99,23 @@ pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception); -#[cfg(any(all(target_os = "linux", not(target_env = "musl")), - target_os = "freebsd"))] -#[link(name = "gcc_s")] -extern {} - -#[cfg(all(target_os = "linux", target_env = "musl", not(test)))] -#[link(name = "unwind", kind = "static")] -extern {} - -#[cfg(any(target_os = "android", target_os = "openbsd"))] -#[link(name = "gcc")] -extern {} - -#[cfg(all(target_os = "netbsd", not(target_vendor = "rumprun")))] -#[link(name = "gcc")] -extern {} - -#[cfg(all(target_os = "netbsd", target_vendor = "rumprun"))] -#[link(name = "unwind")] -extern {} - -#[cfg(target_os = "dragonfly")] -#[link(name = "gcc_pic")] -extern {} - -#[cfg(target_os = "bitrig")] -#[link(name = "c++abi")] -extern {} - +#[cfg_attr(any(all(target_os = "linux", not(target_env = "musl")), + target_os = "freebsd"), + link(name = "gcc_s"))] +#[cfg_attr(all(target_os = "linux", target_env = "musl", not(test)), + link(name = "unwind", kind = "static"))] +#[cfg_attr(any(target_os = "android", target_os = "openbsd"), + link(name = "gcc"))] +#[cfg_attr(all(target_os = "netbsd", not(target_vendor = "rumprun")), + link(name = "gcc"))] +#[cfg_attr(all(target_os = "netbsd", target_vendor = "rumprun"), + link(name = "unwind"))] +#[cfg_attr(target_os = "dragonfly", + link(name = "gcc_pic"))] +#[cfg_attr(target_os = "bitrig", + link(name = "c++abi"))] +#[cfg_attr(all(target_os = "windows", target_env="gnu"), + link(name = "gcc_eh"))] extern "C" { // iOS on armv7 uses SjLj exceptions and requires to link // against corresponding routine (..._SjLj_...) @@ -142,6 +130,11 @@ extern "C" { -> _Unwind_Reason_Code; pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception); + + // remove cfg after new snapshot + #[cfg(not(all(stage0, target_os="windows", target_arch="x86_64")))] + #[unwind] + pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !; } // ... and now we just providing access to SjLj counterspart diff --git a/src/libstd/sys/common/unwind/gcc.rs b/src/libstd/sys/common/unwind/gcc.rs index 361cef08c11..0a598b55951 100644 --- a/src/libstd/sys/common/unwind/gcc.rs +++ b/src/libstd/sys/common/unwind/gcc.rs @@ -231,3 +231,36 @@ pub mod eabi { } } } + +// See docs in the `unwind` module. +#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu", not(test)))] +#[lang = "eh_unwind_resume"] +#[unwind] +unsafe extern fn rust_eh_unwind_resume(panic_ctx: *mut u8) -> ! { + uw::_Unwind_Resume(panic_ctx as *mut uw::_Unwind_Exception); +} + +#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))] +pub mod eh_frame_registry { + // The implementation of stack unwinding is (for now) deferred to libgcc_eh, however Rust + // crates use these Rust-specific entry points to avoid potential clashes with GCC runtime. + // See also: rtbegin.rs, `unwind` module. + + #[link(name = "gcc_eh")] + extern { + fn __register_frame_info(eh_frame_begin: *const u8, object: *mut u8); + fn __deregister_frame_info(eh_frame_begin: *const u8, object: *mut u8); + } + #[cfg(not(test))] + #[no_mangle] + pub unsafe extern fn rust_eh_register_frames(eh_frame_begin: *const u8, + object: *mut u8) { + __register_frame_info(eh_frame_begin, object); + } + #[cfg(not(test))] + #[no_mangle] + pub unsafe extern fn rust_eh_unregister_frames(eh_frame_begin: *const u8, + object: *mut u8) { + __deregister_frame_info(eh_frame_begin, object); + } +} diff --git a/src/libstd/sys/common/unwind/mod.rs b/src/libstd/sys/common/unwind/mod.rs index d87ab56d4e1..e455d163ed9 100644 --- a/src/libstd/sys/common/unwind/mod.rs +++ b/src/libstd/sys/common/unwind/mod.rs @@ -34,28 +34,35 @@ //! object being thrown, and to decide whether it should be caught at that stack //! frame. Once the handler frame has been identified, cleanup phase begins. //! -//! In the cleanup phase, personality routines invoke cleanup code associated -//! with their stack frames (i.e. destructors). Once stack has been unwound down -//! to the handler frame level, unwinding stops and the last personality routine -//! transfers control to its catch block. +//! In the cleanup phase, the unwinder invokes each personality routine again. +//! This time it decides which (if any) cleanup code needs to be run for +//! the current stack frame. If so, the control is transferred to a special branch +//! in the function body, the "landing pad", which invokes destructors, frees memory, +//! etc. At the end of the landing pad, control is transferred back to the unwinder +//! and unwinding resumes. //! -//! ## Frame unwind info registration +//! Once stack has been unwound down to the handler frame level, unwinding stops +//! and the last personality routine transfers control to the catch block. //! -//! Each module has its own frame unwind info section (usually ".eh_frame"), and -//! unwinder needs to know about all of them in order for unwinding to be able to -//! cross module boundaries. +//! ## `eh_personality` and `eh_unwind_resume` //! -//! On some platforms, like Linux, this is achieved by dynamically enumerating -//! currently loaded modules via the dl_iterate_phdr() API and finding all -//! .eh_frame sections. +//! These language items are used by the compiler when generating unwind info. +//! The first one is the personality routine described above. The second one +//! allows compilation target to customize the process of resuming unwind at the +//! end of the landing pads. `eh_unwind_resume` is used only if `custom_unwind_resume` +//! flag in the target options is set. //! -//! Others, like Windows, require modules to actively register their unwind info -//! sections by calling __register_frame_info() API at startup. In the latter -//! case it is essential that there is only one copy of the unwinder runtime in -//! the process. This is usually achieved by linking to the dynamic version of -//! the unwind runtime. +//! ## Frame unwind info registration //! -//! Currently Rust uses unwind runtime provided by libgcc. +//! Each module's image contains a frame unwind info section (usually ".eh_frame"). +//! When a module is loaded/unloaded into the process, the unwinder must be informed +//! about the location of this section in memory. The methods of achieving that vary +//! by the platform. +//! On some (e.g. Linux), the unwinder can discover unwind info sections on its own +//! (by dynamically enumerating currently loaded modules via the dl_iterate_phdr() API +//! and finding their ".eh_frame" sections); +//! Others, like Windows, require modules to actively register their unwind info +//! sections via unwinder API (see `rust_eh_register_frames`/`rust_eh_unregister_frames`). #![allow(dead_code)] #![allow(unused_imports)] diff --git a/src/libstd/sys/common/unwind/seh64_gnu.rs b/src/libstd/sys/common/unwind/seh64_gnu.rs index 9478678fda9..92f059d68e1 100644 --- a/src/libstd/sys/common/unwind/seh64_gnu.rs +++ b/src/libstd/sys/common/unwind/seh64_gnu.rs @@ -190,17 +190,10 @@ unsafe extern fn rust_eh_personality( ExceptionContinueSearch } -// The `resume` instruction, found at the end of the landing pads, and whose job -// is to resume stack unwinding, is typically lowered by LLVM into a call to -// `_Unwind_Resume` routine. To avoid confusion with the same symbol exported -// from libgcc, we redirect it to `rust_eh_unwind_resume`. -// Since resolution of this symbol is done by the linker, `rust_eh_unwind_resume` -// must be marked `pub` + `#[no_mangle]`. (Can we make it a lang item?) - -#[lang = "eh_unwind_resume"] #[cfg(not(test))] +#[lang = "eh_unwind_resume"] #[unwind] -unsafe extern fn rust_eh_unwind_resume(panic_ctx: LPVOID) { +unsafe extern fn rust_eh_unwind_resume(panic_ctx: LPVOID) -> ! { let params = [panic_ctx as ULONG_PTR]; RaiseException(RUST_PANIC, EXCEPTION_NONCONTINUABLE, |
