@@ -133,23 +133,20 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1
133133// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
134134// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
135135
136- // The personality routine for most of our targets, except ARM, which has a slightly different ABI
137- // (however, iOS goes here as it uses SjLj unwinding). Also, the 64-bit Windows implementation
138- // lives in seh64_gnu.rs
139- #[ cfg( all( any( target_os = "ios" , target_os = "netbsd" , not( target_arch = "arm" ) ) ) ) ]
140- #[ lang = "eh_personality" ]
141- #[ no_mangle]
136+ // Shared version of the default personality routine, which is used directly on
137+ // most targets and indirectly on Windows x86_64 via SEH.
142138#[ allow( unused) ]
143- unsafe extern "C" fn rust_eh_personality ( version : c_int ,
144- actions : uw:: _Unwind_Action ,
145- exception_class : uw:: _Unwind_Exception_Class ,
146- exception_object : * mut uw:: _Unwind_Exception ,
147- context : * mut uw:: _Unwind_Context )
148- -> uw:: _Unwind_Reason_Code {
139+ unsafe extern "C" fn rust_eh_personality_impl ( version : c_int ,
140+ actions : uw:: _Unwind_Action ,
141+ exception_class : uw:: _Unwind_Exception_Class ,
142+ exception_object : * mut uw:: _Unwind_Exception ,
143+ context : * mut uw:: _Unwind_Context )
144+ -> uw:: _Unwind_Reason_Code {
149145 if version != 1 {
150146 return uw:: _URC_FATAL_PHASE1_ERROR;
151147 }
152- let eh_action = match find_eh_action ( context) {
148+ let foreign_exception = exception_class != rust_exception_class ( ) ;
149+ let eh_action = match find_eh_action ( context, foreign_exception) {
153150 Ok ( action) => action,
154151 Err ( _) => return uw:: _URC_FATAL_PHASE1_ERROR,
155152 } ;
@@ -175,6 +172,23 @@ unsafe extern "C" fn rust_eh_personality(version: c_int,
175172 }
176173}
177174
175+ // The personality routine for most of our targets, except ARM, which has a slightly different ABI
176+ // (however, iOS goes here as it uses SjLj unwinding). Also, the 64-bit Windows implementation
177+ // uses a different personality (below) but eventually also calls rust_eh_personality_impl.
178+ #[ cfg( all( any( target_os = "ios" , target_os = "netbsd" , not( target_arch = "arm" ) ) ,
179+ not( all( windows, target_arch = "x86_64" , target_env = "gnu" ) ) ) ) ]
180+ #[ lang = "eh_personality" ]
181+ #[ no_mangle]
182+ #[ allow( unused) ]
183+ unsafe extern "C" fn rust_eh_personality ( version : c_int ,
184+ actions : uw:: _Unwind_Action ,
185+ exception_class : uw:: _Unwind_Exception_Class ,
186+ exception_object : * mut uw:: _Unwind_Exception ,
187+ context : * mut uw:: _Unwind_Context )
188+ -> uw:: _Unwind_Reason_Code {
189+ rust_eh_personality_impl ( version, actions, exception_class, exception_object, context)
190+ }
191+
178192// ARM EHABI personality routine.
179193// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
180194#[ cfg( all( target_arch = "arm" , not( target_os = "ios" ) , not( target_os = "netbsd" ) ) ) ]
@@ -215,7 +229,9 @@ unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
215229 // _Unwind_Context in our libunwind bindings and fetch the required data from there directly,
216230 // bypassing DWARF compatibility functions.
217231
218- let eh_action = match find_eh_action ( context) {
232+ let exception_class = unsafe { ( * exception_object) . exception_class } ;
233+ let foreign_exception = exception_class != rust_exception_class ( ) ;
234+ let eh_action = match find_eh_action ( context, foreign_exception) {
219235 Ok ( action) => action,
220236 Err ( _) => return uw:: _URC_FAILURE,
221237 } ;
@@ -259,7 +275,25 @@ unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
259275 }
260276}
261277
262- unsafe fn find_eh_action ( context : * mut uw:: _Unwind_Context )
278+ // On MinGW targets, the unwinding mechanism is SEH however the unwind handler
279+ // data (aka LSDA) uses GCC-compatible encoding.
280+ #[ cfg( all( windows, target_arch = "x86_64" , target_env = "gnu" ) ) ]
281+ #[ lang = "eh_personality" ]
282+ #[ no_mangle]
283+ #[ allow( nonstandard_style) ]
284+ unsafe extern "C" fn rust_eh_personality ( exceptionRecord : * mut uw:: EXCEPTION_RECORD ,
285+ establisherFrame : uw:: LPVOID ,
286+ contextRecord : * mut uw:: CONTEXT ,
287+ dispatcherContext : * mut uw:: DISPATCHER_CONTEXT )
288+ -> uw:: EXCEPTION_DISPOSITION {
289+ uw:: _GCC_specific_handler ( exceptionRecord,
290+ establisherFrame,
291+ contextRecord,
292+ dispatcherContext,
293+ rust_eh_personality_impl)
294+ }
295+
296+ unsafe fn find_eh_action ( context : * mut uw:: _Unwind_Context , foreign_exception : bool )
263297 -> Result < EHAction , ( ) >
264298{
265299 let lsda = uw:: _Unwind_GetLanguageSpecificData ( context) as * const u8 ;
@@ -273,11 +307,11 @@ unsafe fn find_eh_action(context: *mut uw::_Unwind_Context)
273307 get_text_start : & || uw:: _Unwind_GetTextRelBase ( context) ,
274308 get_data_start : & || uw:: _Unwind_GetDataRelBase ( context) ,
275309 } ;
276- eh:: find_eh_action ( lsda, & eh_context)
310+ eh:: find_eh_action ( lsda, & eh_context, foreign_exception )
277311}
278312
279313// See docs in the `unwind` module.
280- #[ cfg( all( target_os="windows" , target_arch = "x86" , target_env="gnu" ) ) ]
314+ #[ cfg( all( target_os="windows" , any ( target_arch = "x86" , target_arch = "x86_64" ) , target_env="gnu" ) ) ]
281315#[ lang = "eh_unwind_resume" ]
282316#[ unwind( allowed) ]
283317unsafe extern "C" fn rust_eh_unwind_resume ( panic_ctx : * mut u8 ) -> ! {
0 commit comments