diff --git a/src/libstd/rt/unwind/gcc.rs b/src/libstd/rt/unwind/gcc.rs new file mode 100644 index 00000000000..39b32a3f08e --- /dev/null +++ b/src/libstd/rt/unwind/gcc.rs @@ -0,0 +1,342 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::v1::*; + +use any::Any; +use boxed; +use libc::c_void; +use rt::libunwind as uw; + +struct Exception { + uwe: uw::_Unwind_Exception, + cause: Option>, +} + +pub unsafe fn panic(data: Box) -> ! { + let exception: Box<_> = box Exception { + uwe: uw::_Unwind_Exception { + exception_class: rust_exception_class(), + exception_cleanup: exception_cleanup, + private: [0; uw::unwinder_private_data_size], + }, + cause: Some(data), + }; + let exception_param = boxed::into_raw(exception) as *mut uw::_Unwind_Exception; + let error = uw::_Unwind_RaiseException(exception_param); + rtabort!("Could not unwind stack, error = {}", error as isize); + + extern fn exception_cleanup(_unwind_code: uw::_Unwind_Reason_Code, + exception: *mut uw::_Unwind_Exception) { + rtdebug!("exception_cleanup()"); + unsafe { + let _: Box = Box::from_raw(exception as *mut Exception); + } + } +} + +pub unsafe fn cleanup(ptr: *mut c_void) -> Box { + let my_ep = ptr as *mut Exception; + rtdebug!("caught {}", (*my_ep).uwe.exception_class); + let cause = (*my_ep).cause.take(); + uw::_Unwind_DeleteException(ptr as *mut _); + cause.unwrap() +} + +// Rust's exception class identifier. This is used by personality routines to +// determine whether the exception was thrown by their own runtime. +fn rust_exception_class() -> uw::_Unwind_Exception_Class { + // M O Z \0 R U S T -- vendor, language + 0x4d4f5a_00_52555354 +} + +// We could implement our personality routine in pure Rust, however exception +// info decoding is tedious. More importantly, personality routines have to +// handle various platform quirks, which are not fun to maintain. For this +// reason, we attempt to reuse personality routine of the C language: +// __gcc_personality_v0. +// +// Since C does not support exception catching, __gcc_personality_v0 simply +// always returns _URC_CONTINUE_UNWIND in search phase, and always returns +// _URC_INSTALL_CONTEXT (i.e. "invoke cleanup code") in cleanup phase. +// +// This is pretty close to Rust's exception handling approach, except that Rust +// does have a single "catch-all" handler at the bottom of each thread's stack. +// So we have two versions of the personality routine: +// - rust_eh_personality, used by all cleanup landing pads, which never catches, +// so the behavior of __gcc_personality_v0 is perfectly adequate there, and +// - rust_eh_personality_catch, used only by rust_try(), which always catches. +// +// Note, however, that for implementation simplicity, rust_eh_personality_catch +// lacks code to install a landing pad, so in order to obtain exception object +// pointer (which it needs to return upstream), rust_try() employs another trick: +// it calls into the nested rust_try_inner(), whose landing pad does not resume +// unwinds. Instead, it extracts the exception pointer and performs a "normal" +// return. +// +// See also: rt/rust_try.ll + +#[cfg(all(not(target_arch = "arm"), + not(all(windows, target_arch = "x86_64")), + not(test)))] +pub mod eabi { + use rt::libunwind as uw; + use libc::c_int; + + extern "C" { + fn __gcc_personality_v0(version: c_int, + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + ue_header: *mut uw::_Unwind_Exception, + context: *mut uw::_Unwind_Context) + -> uw::_Unwind_Reason_Code; + } + + #[lang="eh_personality"] + #[no_mangle] // referenced from rust_try.ll + #[allow(private_no_mangle_fns)] + extern fn rust_eh_personality( + version: c_int, + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + ue_header: *mut uw::_Unwind_Exception, + context: *mut uw::_Unwind_Context + ) -> uw::_Unwind_Reason_Code + { + unsafe { + __gcc_personality_v0(version, actions, exception_class, ue_header, + context) + } + } + + #[no_mangle] // referenced from rust_try.ll + pub extern "C" fn rust_eh_personality_catch( + _version: c_int, + actions: uw::_Unwind_Action, + _exception_class: uw::_Unwind_Exception_Class, + _ue_header: *mut uw::_Unwind_Exception, + _context: *mut uw::_Unwind_Context + ) -> uw::_Unwind_Reason_Code + { + + if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase + uw::_URC_HANDLER_FOUND // catch! + } + else { // cleanup phase + uw::_URC_INSTALL_CONTEXT + } + } +} + +// iOS on armv7 is using SjLj exceptions and therefore requires to use +// a specialized personality routine: __gcc_personality_sj0 + +#[cfg(all(target_os = "ios", target_arch = "arm", not(test)))] +pub mod eabi { + use rt::libunwind as uw; + use libc::c_int; + + extern "C" { + fn __gcc_personality_sj0(version: c_int, + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + ue_header: *mut uw::_Unwind_Exception, + context: *mut uw::_Unwind_Context) + -> uw::_Unwind_Reason_Code; + } + + #[lang="eh_personality"] + #[no_mangle] // referenced from rust_try.ll + pub extern "C" fn rust_eh_personality( + version: c_int, + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + ue_header: *mut uw::_Unwind_Exception, + context: *mut uw::_Unwind_Context + ) -> uw::_Unwind_Reason_Code + { + unsafe { + __gcc_personality_sj0(version, actions, exception_class, ue_header, + context) + } + } + + #[no_mangle] // referenced from rust_try.ll + pub extern "C" fn rust_eh_personality_catch( + _version: c_int, + actions: uw::_Unwind_Action, + _exception_class: uw::_Unwind_Exception_Class, + _ue_header: *mut uw::_Unwind_Exception, + _context: *mut uw::_Unwind_Context + ) -> uw::_Unwind_Reason_Code + { + if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase + uw::_URC_HANDLER_FOUND // catch! + } + else { // cleanup phase + unsafe { + __gcc_personality_sj0(_version, actions, _exception_class, _ue_header, + _context) + } + } + } +} + + +// ARM EHABI uses a slightly different personality routine signature, +// but otherwise works the same. +#[cfg(all(target_arch = "arm", not(target_os = "ios"), not(test)))] +pub mod eabi { + use rt::libunwind as uw; + use libc::c_int; + + extern "C" { + fn __gcc_personality_v0(state: uw::_Unwind_State, + ue_header: *mut uw::_Unwind_Exception, + context: *mut uw::_Unwind_Context) + -> uw::_Unwind_Reason_Code; + } + + #[lang="eh_personality"] + #[no_mangle] // referenced from rust_try.ll + #[allow(private_no_mangle_fns)] + extern "C" fn rust_eh_personality( + state: uw::_Unwind_State, + ue_header: *mut uw::_Unwind_Exception, + context: *mut uw::_Unwind_Context + ) -> uw::_Unwind_Reason_Code + { + unsafe { + __gcc_personality_v0(state, ue_header, context) + } + } + + #[no_mangle] // referenced from rust_try.ll + pub extern "C" fn rust_eh_personality_catch( + state: uw::_Unwind_State, + _ue_header: *mut uw::_Unwind_Exception, + _context: *mut uw::_Unwind_Context + ) -> uw::_Unwind_Reason_Code + { + if (state as c_int & uw::_US_ACTION_MASK as c_int) + == uw::_US_VIRTUAL_UNWIND_FRAME as c_int { // search phase + uw::_URC_HANDLER_FOUND // catch! + } + else { // cleanup phase + uw::_URC_INSTALL_CONTEXT + } + } +} + +// Win64 SEH (see http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx) +// +// This looks a bit convoluted because rather than implementing a native SEH +// handler, GCC reuses the same personality routine as for the other +// architectures by wrapping it with an "API translator" layer +// (_GCC_specific_handler). + +#[cfg(all(windows, target_arch = "x86_64", not(test)))] +#[doc(hidden)] +#[allow(non_camel_case_types, non_snake_case)] +pub mod eabi { + pub use self::EXCEPTION_DISPOSITION::*; + use rt::libunwind as uw; + use libc::{c_void, c_int}; + + #[repr(C)] + pub struct EXCEPTION_RECORD; + #[repr(C)] + pub struct CONTEXT; + #[repr(C)] + pub struct DISPATCHER_CONTEXT; + + #[repr(C)] + #[derive(Copy, Clone)] + pub enum EXCEPTION_DISPOSITION { + ExceptionContinueExecution, + ExceptionContinueSearch, + ExceptionNestedException, + ExceptionCollidedUnwind + } + + type _Unwind_Personality_Fn = + extern "C" fn( + version: c_int, + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + ue_header: *mut uw::_Unwind_Exception, + context: *mut uw::_Unwind_Context + ) -> uw::_Unwind_Reason_Code; + + extern "C" { + fn __gcc_personality_seh0( + exceptionRecord: *mut EXCEPTION_RECORD, + establisherFrame: *mut c_void, + contextRecord: *mut CONTEXT, + dispatcherContext: *mut DISPATCHER_CONTEXT + ) -> EXCEPTION_DISPOSITION; + + fn _GCC_specific_handler( + exceptionRecord: *mut EXCEPTION_RECORD, + establisherFrame: *mut c_void, + contextRecord: *mut CONTEXT, + dispatcherContext: *mut DISPATCHER_CONTEXT, + personality: _Unwind_Personality_Fn + ) -> EXCEPTION_DISPOSITION; + } + + #[lang="eh_personality"] + #[no_mangle] // referenced from rust_try.ll + #[allow(private_no_mangle_fns)] + extern "C" fn rust_eh_personality( + exceptionRecord: *mut EXCEPTION_RECORD, + establisherFrame: *mut c_void, + contextRecord: *mut CONTEXT, + dispatcherContext: *mut DISPATCHER_CONTEXT + ) -> EXCEPTION_DISPOSITION + { + unsafe { + __gcc_personality_seh0(exceptionRecord, establisherFrame, + contextRecord, dispatcherContext) + } + } + + #[no_mangle] // referenced from rust_try.ll + pub extern "C" fn rust_eh_personality_catch( + exceptionRecord: *mut EXCEPTION_RECORD, + establisherFrame: *mut c_void, + contextRecord: *mut CONTEXT, + dispatcherContext: *mut DISPATCHER_CONTEXT + ) -> EXCEPTION_DISPOSITION + { + extern "C" fn inner( + _version: c_int, + actions: uw::_Unwind_Action, + _exception_class: uw::_Unwind_Exception_Class, + _ue_header: *mut uw::_Unwind_Exception, + _context: *mut uw::_Unwind_Context + ) -> uw::_Unwind_Reason_Code + { + if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase + uw::_URC_HANDLER_FOUND // catch! + } + else { // cleanup phase + uw::_URC_INSTALL_CONTEXT + } + } + + unsafe { + _GCC_specific_handler(exceptionRecord, establisherFrame, + contextRecord, dispatcherContext, + inner) + } + } +} + diff --git a/src/libstd/rt/unwind.rs b/src/libstd/rt/unwind/mod.rs similarity index 50% rename from src/libstd/rt/unwind.rs rename to src/libstd/rt/unwind/mod.rs index b24099505ed..9cbe6c40483 100644 --- a/src/libstd/rt/unwind.rs +++ b/src/libstd/rt/unwind/mod.rs @@ -57,6 +57,9 @@ //! //! Currently Rust uses unwind runtime provided by libgcc. +#![allow(dead_code)] +#![allow(unused_imports)] + use prelude::v1::*; use any::Any; @@ -71,12 +74,13 @@ use mem; use sync::atomic::{self, Ordering}; use sys_common::mutex::{Mutex, MUTEX_INIT}; -use rt::libunwind as uw; - -struct Exception { - uwe: uw::_Unwind_Exception, - cause: Option>, -} +// The actual unwinding implementation is cfg'd here, and we've got two current +// implementations. One goes through SEH on Windows and the other goes through +// libgcc via the libunwind-like API. +#[cfg(target_env = "msvc")] #[path = "seh.rs"] #[doc(hidden)] +pub mod imp; +#[cfg(not(target_env = "msvc"))] #[path = "gcc.rs"] #[doc(hidden)] +pub mod imp; pub type Callback = fn(msg: &(Any + Send), file: &'static str, line: u32); @@ -97,6 +101,10 @@ static CALLBACK_CNT: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT; thread_local! { static PANICKING: Cell = Cell::new(false) } +#[link(name = "rustrt_native", kind = "static")] +#[cfg(not(test))] +extern {} + /// Invoke a closure, capturing the cause of panic if one occurs. /// /// This function will return `Ok(())` if the closure did not panic, and will @@ -127,11 +135,7 @@ pub unsafe fn try(f: F) -> Result<(), Box> { return if ep.is_null() { Ok(()) } else { - let my_ep = ep as *mut Exception; - rtdebug!("caught {}", (*my_ep).uwe.exception_class); - let cause = (*my_ep).cause.take(); - uw::_Unwind_DeleteException(ep); - Err(cause.unwrap()) + Err(imp::cleanup(ep)) }; extern fn try_fn(opt_closure: *mut c_void) { @@ -139,17 +143,13 @@ pub unsafe fn try(f: F) -> Result<(), Box> { unsafe { (*opt_closure).take().unwrap()(); } } - #[link(name = "rustrt_native", kind = "static")] - #[cfg(not(test))] - extern {} - extern { // Rust's try-catch // When f(...) returns normally, the return value is null. // When f(...) throws, the return value is a pointer to the caught // exception object. fn rust_try(f: extern fn(*mut c_void), - data: *mut c_void) -> *mut uw::_Unwind_Exception; + data: *mut c_void) -> *mut c_void; } } @@ -164,319 +164,8 @@ pub fn panicking() -> bool { #[allow(private_no_mangle_fns)] fn rust_panic(cause: Box) -> ! { rtdebug!("begin_unwind()"); - unsafe { - let exception: Box<_> = box Exception { - uwe: uw::_Unwind_Exception { - exception_class: rust_exception_class(), - exception_cleanup: exception_cleanup, - private: [0; uw::unwinder_private_data_size], - }, - cause: Some(cause), - }; - let exception_param = boxed::into_raw(exception) as *mut uw::_Unwind_Exception; - let error = uw::_Unwind_RaiseException(exception_param); - rtabort!("Could not unwind stack, error = {}", error as isize) - } - - extern fn exception_cleanup(_unwind_code: uw::_Unwind_Reason_Code, - exception: *mut uw::_Unwind_Exception) { - rtdebug!("exception_cleanup()"); - unsafe { - let _: Box = Box::from_raw(exception as *mut Exception); - } - } -} - -// Rust's exception class identifier. This is used by personality routines to -// determine whether the exception was thrown by their own runtime. -fn rust_exception_class() -> uw::_Unwind_Exception_Class { - // M O Z \0 R U S T -- vendor, language - 0x4d4f5a_00_52555354 -} - -// We could implement our personality routine in pure Rust, however exception -// info decoding is tedious. More importantly, personality routines have to -// handle various platform quirks, which are not fun to maintain. For this -// reason, we attempt to reuse personality routine of the C language: -// __gcc_personality_v0. -// -// Since C does not support exception catching, __gcc_personality_v0 simply -// always returns _URC_CONTINUE_UNWIND in search phase, and always returns -// _URC_INSTALL_CONTEXT (i.e. "invoke cleanup code") in cleanup phase. -// -// This is pretty close to Rust's exception handling approach, except that Rust -// does have a single "catch-all" handler at the bottom of each thread's stack. -// So we have two versions of the personality routine: -// - rust_eh_personality, used by all cleanup landing pads, which never catches, -// so the behavior of __gcc_personality_v0 is perfectly adequate there, and -// - rust_eh_personality_catch, used only by rust_try(), which always catches. -// -// Note, however, that for implementation simplicity, rust_eh_personality_catch -// lacks code to install a landing pad, so in order to obtain exception object -// pointer (which it needs to return upstream), rust_try() employs another trick: -// it calls into the nested rust_try_inner(), whose landing pad does not resume -// unwinds. Instead, it extracts the exception pointer and performs a "normal" -// return. -// -// See also: rt/rust_try.ll - -#[cfg(all(not(target_arch = "arm"), - not(all(windows, target_arch = "x86_64")), - not(test)))] -#[doc(hidden)] -pub mod eabi { - use rt::libunwind as uw; - use libc::c_int; - - extern "C" { - fn __gcc_personality_v0(version: c_int, - actions: uw::_Unwind_Action, - exception_class: uw::_Unwind_Exception_Class, - ue_header: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context) - -> uw::_Unwind_Reason_Code; - } - - #[lang = "eh_personality"] - #[no_mangle] // referenced from rust_try.ll - #[allow(private_no_mangle_fns)] - extern fn rust_eh_personality( - version: c_int, - actions: uw::_Unwind_Action, - exception_class: uw::_Unwind_Exception_Class, - ue_header: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context - ) -> uw::_Unwind_Reason_Code - { - unsafe { - __gcc_personality_v0(version, actions, exception_class, ue_header, - context) - } - } - - #[no_mangle] // referenced from rust_try.ll - pub extern "C" fn rust_eh_personality_catch( - _version: c_int, - actions: uw::_Unwind_Action, - _exception_class: uw::_Unwind_Exception_Class, - _ue_header: *mut uw::_Unwind_Exception, - _context: *mut uw::_Unwind_Context - ) -> uw::_Unwind_Reason_Code - { - - if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase - uw::_URC_HANDLER_FOUND // catch! - } - else { // cleanup phase - uw::_URC_INSTALL_CONTEXT - } - } -} - -// iOS on armv7 is using SjLj exceptions and therefore requires to use -// a specialized personality routine: __gcc_personality_sj0 - -#[cfg(all(target_os = "ios", target_arch = "arm", not(test)))] -#[doc(hidden)] -pub mod eabi { - use rt::libunwind as uw; - use libc::c_int; - - extern "C" { - fn __gcc_personality_sj0(version: c_int, - actions: uw::_Unwind_Action, - exception_class: uw::_Unwind_Exception_Class, - ue_header: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context) - -> uw::_Unwind_Reason_Code; - } - - #[lang = "eh_personality"] - #[no_mangle] // referenced from rust_try.ll - pub extern "C" fn rust_eh_personality( - version: c_int, - actions: uw::_Unwind_Action, - exception_class: uw::_Unwind_Exception_Class, - ue_header: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context - ) -> uw::_Unwind_Reason_Code - { - unsafe { - __gcc_personality_sj0(version, actions, exception_class, ue_header, - context) - } - } - - #[no_mangle] // referenced from rust_try.ll - pub extern "C" fn rust_eh_personality_catch( - _version: c_int, - actions: uw::_Unwind_Action, - _exception_class: uw::_Unwind_Exception_Class, - _ue_header: *mut uw::_Unwind_Exception, - _context: *mut uw::_Unwind_Context - ) -> uw::_Unwind_Reason_Code - { - if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase - uw::_URC_HANDLER_FOUND // catch! - } - else { // cleanup phase - unsafe { - __gcc_personality_sj0(_version, actions, _exception_class, _ue_header, - _context) - } - } - } -} - - -// ARM EHABI uses a slightly different personality routine signature, -// but otherwise works the same. -#[cfg(all(target_arch = "arm", not(target_os = "ios"), not(test)))] -#[doc(hidden)] -pub mod eabi { - use rt::libunwind as uw; - use libc::c_int; - - extern "C" { - fn __gcc_personality_v0(state: uw::_Unwind_State, - ue_header: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context) - -> uw::_Unwind_Reason_Code; - } - - #[lang = "eh_personality"] - #[no_mangle] // referenced from rust_try.ll - #[allow(private_no_mangle_fns)] - extern "C" fn rust_eh_personality( - state: uw::_Unwind_State, - ue_header: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context - ) -> uw::_Unwind_Reason_Code - { - unsafe { - __gcc_personality_v0(state, ue_header, context) - } - } - - #[no_mangle] // referenced from rust_try.ll - pub extern "C" fn rust_eh_personality_catch( - state: uw::_Unwind_State, - _ue_header: *mut uw::_Unwind_Exception, - _context: *mut uw::_Unwind_Context - ) -> uw::_Unwind_Reason_Code - { - if (state as c_int & uw::_US_ACTION_MASK as c_int) - == uw::_US_VIRTUAL_UNWIND_FRAME as c_int { // search phase - uw::_URC_HANDLER_FOUND // catch! - } - else { // cleanup phase - uw::_URC_INSTALL_CONTEXT - } - } -} - -// Win64 SEH (see http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx) -// -// This looks a bit convoluted because rather than implementing a native SEH handler, -// GCC reuses the same personality routine as for the other architectures by wrapping it -// with an "API translator" layer (_GCC_specific_handler). - -#[cfg(all(windows, target_arch = "x86_64", not(test)))] -#[doc(hidden)] -#[allow(non_camel_case_types, non_snake_case)] -pub mod eabi { - pub use self::EXCEPTION_DISPOSITION::*; - use rt::libunwind as uw; - use libc::{c_void, c_int}; - - #[repr(C)] - pub struct EXCEPTION_RECORD; - #[repr(C)] - pub struct CONTEXT; - #[repr(C)] - pub struct DISPATCHER_CONTEXT; - - #[repr(C)] - #[derive(Copy, Clone)] - pub enum EXCEPTION_DISPOSITION { - ExceptionContinueExecution, - ExceptionContinueSearch, - ExceptionNestedException, - ExceptionCollidedUnwind - } - - type _Unwind_Personality_Fn = - extern "C" fn( - version: c_int, - actions: uw::_Unwind_Action, - exception_class: uw::_Unwind_Exception_Class, - ue_header: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context - ) -> uw::_Unwind_Reason_Code; - - extern "C" { - fn __gcc_personality_seh0( - exceptionRecord: *mut EXCEPTION_RECORD, - establisherFrame: *mut c_void, - contextRecord: *mut CONTEXT, - dispatcherContext: *mut DISPATCHER_CONTEXT - ) -> EXCEPTION_DISPOSITION; - - fn _GCC_specific_handler( - exceptionRecord: *mut EXCEPTION_RECORD, - establisherFrame: *mut c_void, - contextRecord: *mut CONTEXT, - dispatcherContext: *mut DISPATCHER_CONTEXT, - personality: _Unwind_Personality_Fn - ) -> EXCEPTION_DISPOSITION; - } - - #[lang = "eh_personality"] - #[no_mangle] // referenced from rust_try.ll - #[allow(private_no_mangle_fns)] - extern "C" fn rust_eh_personality( - exceptionRecord: *mut EXCEPTION_RECORD, - establisherFrame: *mut c_void, - contextRecord: *mut CONTEXT, - dispatcherContext: *mut DISPATCHER_CONTEXT - ) -> EXCEPTION_DISPOSITION - { - unsafe { - __gcc_personality_seh0(exceptionRecord, establisherFrame, - contextRecord, dispatcherContext) - } - } - - #[no_mangle] // referenced from rust_try.ll - pub extern "C" fn rust_eh_personality_catch( - exceptionRecord: *mut EXCEPTION_RECORD, - establisherFrame: *mut c_void, - contextRecord: *mut CONTEXT, - dispatcherContext: *mut DISPATCHER_CONTEXT - ) -> EXCEPTION_DISPOSITION - { - extern "C" fn inner( - _version: c_int, - actions: uw::_Unwind_Action, - _exception_class: uw::_Unwind_Exception_Class, - _ue_header: *mut uw::_Unwind_Exception, - _context: *mut uw::_Unwind_Context - ) -> uw::_Unwind_Reason_Code - { - if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase - uw::_URC_HANDLER_FOUND // catch! - } - else { // cleanup phase - uw::_URC_INSTALL_CONTEXT - } - } - - unsafe { - _GCC_specific_handler(exceptionRecord, establisherFrame, - contextRecord, dispatcherContext, - inner) - } + imp::panic(cause) } } diff --git a/src/libstd/rt/unwind/seh.rs b/src/libstd/rt/unwind/seh.rs new file mode 100644 index 00000000000..a72c1debe14 --- /dev/null +++ b/src/libstd/rt/unwind/seh.rs @@ -0,0 +1,30 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use prelude::v1::*; + +use any::Any; +use intrinsics; +use libc::c_void; + +pub unsafe fn panic(_data: Box) -> ! { + intrinsics::abort(); +} + +pub unsafe fn cleanup(_ptr: *mut c_void) -> Box { + intrinsics::abort(); +} + +#[lang = "eh_personality"] +#[no_mangle] +pub extern fn rust_eh_personality() {} + +#[no_mangle] +pub extern fn rust_eh_personality_catch() {}