X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=library%2Fpanic_unwind%2Fsrc%2Femcc.rs;h=c6d42308596cb2f51ba91c7bc3485a16872413c1;hb=7dc3ace6a962d4c83a1dbd19b3ec9f033356875d;hp=7c233c7c3a1cb0f08626653e4bd218f2ece215fe;hpb=06f049a35535d26d5c8426d4f782f78277b41aa1;p=rust.git diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs index 7c233c7c3a1..c6d42308596 100644 --- a/library/panic_unwind/src/emcc.rs +++ b/library/panic_unwind/src/emcc.rs @@ -47,7 +47,12 @@ unsafe impl Sync for TypeInfo {} name: b"rust_panic\0".as_ptr(), }; +// NOTE(nbdd0121): The `canary` field will be part of stable ABI after `c_unwind` stabilization. +#[repr(C)] struct Exception { + // See `gcc.rs` on why this is present. We already have a static here so just use it. + canary: *const TypeInfo, + // This is necessary because C++ code can capture our exception with // std::exception_ptr and rethrow it multiple times, possibly even in // another thread. @@ -70,27 +75,38 @@ struct CatchData { let catch_data = &*(ptr as *mut CatchData); let adjusted_ptr = __cxa_begin_catch(catch_data.ptr as *mut libc::c_void) as *mut Exception; - let out = if catch_data.is_rust_panic { - let was_caught = (*adjusted_ptr).caught.swap(true, Ordering::SeqCst); - if was_caught { - // Since cleanup() isn't allowed to panic, we just abort instead. - intrinsics::abort(); - } - (*adjusted_ptr).data.take().unwrap() - } else { + if !catch_data.is_rust_panic { super::__rust_foreign_exception(); - }; + } + + let canary = ptr::addr_of!((*adjusted_ptr).canary).read(); + if !ptr::eq(canary, &EXCEPTION_TYPE_INFO) { + super::__rust_foreign_exception(); + } + + let was_caught = (*adjusted_ptr).caught.swap(true, Ordering::SeqCst); + if was_caught { + // Since cleanup() isn't allowed to panic, we just abort instead. + intrinsics::abort(); + } + let out = (*adjusted_ptr).data.take().unwrap(); __cxa_end_catch(); out } pub unsafe fn panic(data: Box) -> u32 { - let sz = mem::size_of_val(&data); - let exception = __cxa_allocate_exception(sz) as *mut Exception; + let exception = __cxa_allocate_exception(mem::size_of::()) as *mut Exception; if exception.is_null() { return uw::_URC_FATAL_PHASE1_ERROR as u32; } - ptr::write(exception, Exception { caught: AtomicBool::new(false), data: Some(data) }); + ptr::write( + exception, + Exception { + canary: &EXCEPTION_TYPE_INFO, + caught: AtomicBool::new(false), + data: Some(data), + }, + ); __cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, exception_cleanup); }