Skip to content

Commit ecbfb04

Browse files
committed
Apply feedback
1 parent 771e319 commit ecbfb04

File tree

2 files changed

+117
-113
lines changed
  • src
    • libpanic_unwind
    • test/run-make-fulldeps/foreign-exceptions

2 files changed

+117
-113
lines changed

src/libpanic_unwind/gcc.rs

Lines changed: 115 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -172,125 +172,127 @@ unsafe extern "C" fn rust_eh_personality_impl(version: c_int,
172172
}
173173
}
174174

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-
192-
// ARM EHABI personality routine.
193-
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
194-
#[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "netbsd")))]
195-
#[lang = "eh_personality"]
196-
#[no_mangle]
197-
unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
198-
exception_object: *mut uw::_Unwind_Exception,
199-
context: *mut uw::_Unwind_Context)
200-
-> uw::_Unwind_Reason_Code {
201-
let state = state as c_int;
202-
let action = state & uw::_US_ACTION_MASK as c_int;
203-
let search_phase = if action == uw::_US_VIRTUAL_UNWIND_FRAME as c_int {
204-
// Backtraces on ARM will call the personality routine with
205-
// state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases
206-
// we want to continue unwinding the stack, otherwise all our backtraces
207-
// would end at __rust_try
208-
if state & uw::_US_FORCE_UNWIND as c_int != 0 {
209-
return continue_unwind(exception_object, context);
210-
}
211-
true
212-
} else if action == uw::_US_UNWIND_FRAME_STARTING as c_int {
213-
false
214-
} else if action == uw::_US_UNWIND_FRAME_RESUME as c_int {
215-
return continue_unwind(exception_object, context);
216-
} else {
217-
return uw::_URC_FAILURE;
218-
};
219175

220-
// The DWARF unwinder assumes that _Unwind_Context holds things like the function
221-
// and LSDA pointers, however ARM EHABI places them into the exception object.
222-
// To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which
223-
// take only the context pointer, GCC personality routines stash a pointer to exception_object
224-
// in the context, using location reserved for ARM's "scratch register" (r12).
225-
uw::_Unwind_SetGR(context,
226-
uw::UNWIND_POINTER_REG,
227-
exception_object as uw::_Unwind_Ptr);
228-
// ...A more principled approach would be to provide the full definition of ARM's
229-
// _Unwind_Context in our libunwind bindings and fetch the required data from there directly,
230-
// bypassing DWARF compatibility functions.
176+
cfg_if::cfg_if! {
177+
if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "netbsd")))] {
178+
// ARM EHABI personality routine.
179+
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
180+
//
181+
// iOS uses the default routine instead since it uses SjLj unwinding.
182+
#[lang = "eh_personality"]
183+
#[no_mangle]
184+
unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
185+
exception_object: *mut uw::_Unwind_Exception,
186+
context: *mut uw::_Unwind_Context)
187+
-> uw::_Unwind_Reason_Code {
188+
let state = state as c_int;
189+
let action = state & uw::_US_ACTION_MASK as c_int;
190+
let search_phase = if action == uw::_US_VIRTUAL_UNWIND_FRAME as c_int {
191+
// Backtraces on ARM will call the personality routine with
192+
// state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases
193+
// we want to continue unwinding the stack, otherwise all our backtraces
194+
// would end at __rust_try
195+
if state & uw::_US_FORCE_UNWIND as c_int != 0 {
196+
return continue_unwind(exception_object, context);
197+
}
198+
true
199+
} else if action == uw::_US_UNWIND_FRAME_STARTING as c_int {
200+
false
201+
} else if action == uw::_US_UNWIND_FRAME_RESUME as c_int {
202+
return continue_unwind(exception_object, context);
203+
} else {
204+
return uw::_URC_FAILURE;
205+
};
206+
207+
// The DWARF unwinder assumes that _Unwind_Context holds things like the function
208+
// and LSDA pointers, however ARM EHABI places them into the exception object.
209+
// To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which
210+
// take only the context pointer, GCC personality routines stash a pointer to
211+
// exception_object in the context, using location reserved for ARM's
212+
// "scratch register" (r12).
213+
uw::_Unwind_SetGR(context,
214+
uw::UNWIND_POINTER_REG,
215+
exception_object as uw::_Unwind_Ptr);
216+
// ...A more principled approach would be to provide the full definition of ARM's
217+
// _Unwind_Context in our libunwind bindings and fetch the required data from there
218+
// directly, bypassing DWARF compatibility functions.
219+
220+
let exception_class = unsafe { (*exception_object).exception_class };
221+
let foreign_exception = exception_class != rust_exception_class();
222+
let eh_action = match find_eh_action(context, foreign_exception) {
223+
Ok(action) => action,
224+
Err(_) => return uw::_URC_FAILURE,
225+
};
226+
if search_phase {
227+
match eh_action {
228+
EHAction::None |
229+
EHAction::Cleanup(_) => return continue_unwind(exception_object, context),
230+
EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
231+
EHAction::Terminate => return uw::_URC_FAILURE,
232+
}
233+
} else {
234+
match eh_action {
235+
EHAction::None => return continue_unwind(exception_object, context),
236+
EHAction::Cleanup(lpad) |
237+
EHAction::Catch(lpad) => {
238+
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0,
239+
exception_object as uintptr_t);
240+
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
241+
uw::_Unwind_SetIP(context, lpad);
242+
return uw::_URC_INSTALL_CONTEXT;
243+
}
244+
EHAction::Terminate => return uw::_URC_FAILURE,
245+
}
246+
}
231247

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) {
235-
Ok(action) => action,
236-
Err(_) => return uw::_URC_FAILURE,
237-
};
238-
if search_phase {
239-
match eh_action {
240-
EHAction::None |
241-
EHAction::Cleanup(_) => return continue_unwind(exception_object, context),
242-
EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
243-
EHAction::Terminate => return uw::_URC_FAILURE,
244-
}
245-
} else {
246-
match eh_action {
247-
EHAction::None => return continue_unwind(exception_object, context),
248-
EHAction::Cleanup(lpad) |
249-
EHAction::Catch(lpad) => {
250-
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t);
251-
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
252-
uw::_Unwind_SetIP(context, lpad);
253-
return uw::_URC_INSTALL_CONTEXT;
248+
// On ARM EHABI the personality routine is responsible for actually
249+
// unwinding a single stack frame before returning (ARM EHABI Sec. 6.1).
250+
unsafe fn continue_unwind(exception_object: *mut uw::_Unwind_Exception,
251+
context: *mut uw::_Unwind_Context)
252+
-> uw::_Unwind_Reason_Code {
253+
if __gnu_unwind_frame(exception_object, context) == uw::_URC_NO_REASON {
254+
uw::_URC_CONTINUE_UNWIND
255+
} else {
256+
uw::_URC_FAILURE
257+
}
258+
}
259+
// defined in libgcc
260+
extern "C" {
261+
fn __gnu_unwind_frame(exception_object: *mut uw::_Unwind_Exception,
262+
context: *mut uw::_Unwind_Context)
263+
-> uw::_Unwind_Reason_Code;
254264
}
255-
EHAction::Terminate => return uw::_URC_FAILURE,
256265
}
257-
}
258-
259-
// On ARM EHABI the personality routine is responsible for actually
260-
// unwinding a single stack frame before returning (ARM EHABI Sec. 6.1).
261-
unsafe fn continue_unwind(exception_object: *mut uw::_Unwind_Exception,
262-
context: *mut uw::_Unwind_Context)
263-
-> uw::_Unwind_Reason_Code {
264-
if __gnu_unwind_frame(exception_object, context) == uw::_URC_NO_REASON {
265-
uw::_URC_CONTINUE_UNWIND
266-
} else {
267-
uw::_URC_FAILURE
266+
} else if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] {
267+
// On x86_64 MinGW targets, the unwinding mechanism is SEH however the unwind
268+
// handler data (aka LSDA) uses GCC-compatible encoding.
269+
#[lang = "eh_personality"]
270+
#[no_mangle]
271+
#[allow(nonstandard_style)]
272+
unsafe extern "C" fn rust_eh_personality(exceptionRecord: *mut uw::EXCEPTION_RECORD,
273+
establisherFrame: uw::LPVOID,
274+
contextRecord: *mut uw::CONTEXT,
275+
dispatcherContext: *mut uw::DISPATCHER_CONTEXT)
276+
-> uw::EXCEPTION_DISPOSITION {
277+
uw::_GCC_specific_handler(exceptionRecord,
278+
establisherFrame,
279+
contextRecord,
280+
dispatcherContext,
281+
rust_eh_personality_impl)
282+
}
283+
} else {
284+
// The personality routine for most of our targets.
285+
#[lang = "eh_personality"]
286+
#[no_mangle]
287+
unsafe extern "C" fn rust_eh_personality(version: c_int,
288+
actions: uw::_Unwind_Action,
289+
exception_class: uw::_Unwind_Exception_Class,
290+
exception_object: *mut uw::_Unwind_Exception,
291+
context: *mut uw::_Unwind_Context)
292+
-> uw::_Unwind_Reason_Code {
293+
rust_eh_personality_impl(version, actions, exception_class, exception_object, context)
268294
}
269295
}
270-
// defined in libgcc
271-
extern "C" {
272-
fn __gnu_unwind_frame(exception_object: *mut uw::_Unwind_Exception,
273-
context: *mut uw::_Unwind_Context)
274-
-> uw::_Unwind_Reason_Code;
275-
}
276-
}
277-
278-
// On x86_64 MinGW targets, the unwinding mechanism is SEH however the unwind
279-
// handler 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)
294296
}
295297

296298
unsafe fn find_eh_action(context: *mut uw::_Unwind_Context, foreign_exception: bool)

src/test/run-make-fulldeps/foreign-exceptions/foo.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ extern "C" {
2525
}
2626

2727
#[no_mangle]
28+
#[unwind(allowed)]
2829
extern "C" fn rust_catch_callback(cb: extern "C" fn(), rust_ok: &mut bool) {
2930
let _caught_unwind = catch_unwind(AssertUnwindSafe(|| {
3031
let _drop = DropCheck(rust_ok);
@@ -35,6 +36,7 @@ extern "C" fn rust_catch_callback(cb: extern "C" fn(), rust_ok: &mut bool) {
3536
}
3637

3738
fn throw_rust_panic() {
39+
#[unwind(allowed)]
3840
extern "C" fn callback() {
3941
println!("throwing rust panic");
4042
panic!(1234i32);

0 commit comments

Comments
 (0)