35
35
//!
36
36
//! Once stack has been unwound down to the handler frame level, unwinding stops
37
37
//! and the last personality routine transfers control to the catch block.
38
- //!
39
- //! ## `eh_personality` and `eh_unwind_resume`
40
- //!
41
- //! These language items are used by the compiler when generating unwind info.
42
- //! The first one is the personality routine described above. The second one
43
- //! allows compilation target to customize the process of resuming unwind at the
44
- //! end of the landing pads. `eh_unwind_resume` is used only if
45
- //! `custom_unwind_resume` flag in the target options is set.
46
38
47
39
#![ allow( private_no_mangle_fns) ]
48
40
@@ -133,23 +125,20 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1
133
125
// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
134
126
// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
135
127
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]
128
+ // Shared version of the default personality routine, which is used directly on
129
+ // most targets and indirectly on Windows x86_64 via SEH.
142
130
#[ 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 {
131
+ unsafe extern "C" fn rust_eh_personality_impl ( version : c_int ,
132
+ actions : uw:: _Unwind_Action ,
133
+ exception_class : uw:: _Unwind_Exception_Class ,
134
+ exception_object : * mut uw:: _Unwind_Exception ,
135
+ context : * mut uw:: _Unwind_Context )
136
+ -> uw:: _Unwind_Reason_Code {
149
137
if version != 1 {
150
138
return uw:: _URC_FATAL_PHASE1_ERROR;
151
139
}
152
- let eh_action = match find_eh_action ( context) {
140
+ let foreign_exception = exception_class != rust_exception_class ( ) ;
141
+ let eh_action = match find_eh_action ( context, foreign_exception) {
153
142
Ok ( action) => action,
154
143
Err ( _) => return uw:: _URC_FATAL_PHASE1_ERROR,
155
144
} ;
@@ -175,6 +164,23 @@ unsafe extern "C" fn rust_eh_personality(version: c_int,
175
164
}
176
165
}
177
166
167
+ // The personality routine for most of our targets, except ARM, which has a slightly different ABI
168
+ // (however, iOS goes here as it uses SjLj unwinding). Also, the 64-bit Windows implementation
169
+ // uses a different personality (below) but eventually also calls rust_eh_personality_impl.
170
+ #[ cfg( all( any( target_os = "ios" , target_os = "netbsd" , not( target_arch = "arm" ) ) ,
171
+ not( all( windows, target_arch = "x86_64" , target_env = "gnu" ) ) ) ) ]
172
+ #[ lang = "eh_personality" ]
173
+ #[ no_mangle]
174
+ #[ allow( unused) ]
175
+ unsafe extern "C" fn rust_eh_personality ( version : c_int ,
176
+ actions : uw:: _Unwind_Action ,
177
+ exception_class : uw:: _Unwind_Exception_Class ,
178
+ exception_object : * mut uw:: _Unwind_Exception ,
179
+ context : * mut uw:: _Unwind_Context )
180
+ -> uw:: _Unwind_Reason_Code {
181
+ rust_eh_personality_impl ( version, actions, exception_class, exception_object, context)
182
+ }
183
+
178
184
// ARM EHABI personality routine.
179
185
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
180
186
#[ cfg( all( target_arch = "arm" , not( target_os = "ios" ) , not( target_os = "netbsd" ) ) ) ]
@@ -215,7 +221,9 @@ unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
215
221
// _Unwind_Context in our libunwind bindings and fetch the required data from there directly,
216
222
// bypassing DWARF compatibility functions.
217
223
218
- let eh_action = match find_eh_action ( context) {
224
+ let exception_class = unsafe { ( * exception_object) . exception_class } ;
225
+ let foreign_exception = exception_class != rust_exception_class ( ) ;
226
+ let eh_action = match find_eh_action ( context, foreign_exception) {
219
227
Ok ( action) => action,
220
228
Err ( _) => return uw:: _URC_FAILURE,
221
229
} ;
@@ -259,7 +267,25 @@ unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
259
267
}
260
268
}
261
269
262
- unsafe fn find_eh_action ( context : * mut uw:: _Unwind_Context )
270
+ // On MinGW targets, the unwinding mechanism is SEH however the unwind handler
271
+ // data (aka LSDA) uses GCC-compatible encoding.
272
+ #[ cfg( all( windows, target_arch = "x86_64" , target_env = "gnu" ) ) ]
273
+ #[ lang = "eh_personality" ]
274
+ #[ no_mangle]
275
+ #[ allow( nonstandard_style) ]
276
+ unsafe extern "C" fn rust_eh_personality ( exceptionRecord : * mut uw:: EXCEPTION_RECORD ,
277
+ establisherFrame : uw:: LPVOID ,
278
+ contextRecord : * mut uw:: CONTEXT ,
279
+ dispatcherContext : * mut uw:: DISPATCHER_CONTEXT )
280
+ -> uw:: EXCEPTION_DISPOSITION {
281
+ uw:: _GCC_specific_handler ( exceptionRecord,
282
+ establisherFrame,
283
+ contextRecord,
284
+ dispatcherContext,
285
+ rust_eh_personality_impl)
286
+ }
287
+
288
+ unsafe fn find_eh_action ( context : * mut uw:: _Unwind_Context , foreign_exception : bool )
263
289
-> Result < EHAction , ( ) >
264
290
{
265
291
let lsda = uw:: _Unwind_GetLanguageSpecificData ( context) as * const u8 ;
@@ -273,11 +299,12 @@ unsafe fn find_eh_action(context: *mut uw::_Unwind_Context)
273
299
get_text_start : & || uw:: _Unwind_GetTextRelBase ( context) ,
274
300
get_data_start : & || uw:: _Unwind_GetDataRelBase ( context) ,
275
301
} ;
276
- eh:: find_eh_action ( lsda, & eh_context)
302
+ eh:: find_eh_action ( lsda, & eh_context, foreign_exception )
277
303
}
278
304
279
305
// See docs in the `unwind` module.
280
- #[ cfg( all( target_os="windows" , target_arch = "x86" , target_env="gnu" ) ) ]
306
+ #[ cfg( bootstrap) ]
307
+ #[ cfg( all( target_os="windows" , any( target_arch = "x86" , target_arch = "x86_64" ) , target_env="gnu" ) ) ]
281
308
#[ lang = "eh_unwind_resume" ]
282
309
#[ unwind( allowed) ]
283
310
unsafe extern "C" fn rust_eh_unwind_resume ( panic_ctx : * mut u8 ) -> ! {
0 commit comments