@@ -133,23 +133,20 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1
133
133
// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
134
134
// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
135
135
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.
142
138
#[ 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 {
149
145
if version != 1 {
150
146
return uw:: _URC_FATAL_PHASE1_ERROR;
151
147
}
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) {
153
150
Ok ( action) => action,
154
151
Err ( _) => return uw:: _URC_FATAL_PHASE1_ERROR,
155
152
} ;
@@ -175,6 +172,23 @@ unsafe extern "C" fn rust_eh_personality(version: c_int,
175
172
}
176
173
}
177
174
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
+
178
192
// ARM EHABI personality routine.
179
193
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
180
194
#[ 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,
215
229
// _Unwind_Context in our libunwind bindings and fetch the required data from there directly,
216
230
// bypassing DWARF compatibility functions.
217
231
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) {
219
235
Ok ( action) => action,
220
236
Err ( _) => return uw:: _URC_FAILURE,
221
237
} ;
@@ -259,7 +275,25 @@ unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
259
275
}
260
276
}
261
277
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 )
263
297
-> Result < EHAction , ( ) >
264
298
{
265
299
let lsda = uw:: _Unwind_GetLanguageSpecificData ( context) as * const u8 ;
@@ -273,11 +307,11 @@ unsafe fn find_eh_action(context: *mut uw::_Unwind_Context)
273
307
get_text_start : & || uw:: _Unwind_GetTextRelBase ( context) ,
274
308
get_data_start : & || uw:: _Unwind_GetDataRelBase ( context) ,
275
309
} ;
276
- eh:: find_eh_action ( lsda, & eh_context)
310
+ eh:: find_eh_action ( lsda, & eh_context, foreign_exception )
277
311
}
278
312
279
313
// 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" ) ) ]
281
315
#[ lang = "eh_unwind_resume" ]
282
316
#[ unwind( allowed) ]
283
317
unsafe extern "C" fn rust_eh_unwind_resume ( panic_ctx : * mut u8 ) -> ! {
0 commit comments