diff options
| author | Amanieu d'Antras <amanieu@gmail.com> | 2019-10-27 22:33:25 +0000 |
|---|---|---|
| committer | Amanieu d'Antras <amanieu@gmail.com> | 2019-11-03 14:03:21 +0000 |
| commit | ad61c88e729acf9dbbe17493faeedb760c6df08c (patch) | |
| tree | 23b2d2f985ad3edd337566337ac4be4e3a14cd68 /src/libpanic_unwind | |
| parent | 83d6bf49296dd2c365ee3989d114a99db9ca3577 (diff) | |
| download | rust-ad61c88e729acf9dbbe17493faeedb760c6df08c.tar.gz rust-ad61c88e729acf9dbbe17493faeedb760c6df08c.zip | |
Make SEH exceptions use a rust_panic type instead of unsigned __int64*
Diffstat (limited to 'src/libpanic_unwind')
| -rw-r--r-- | src/libpanic_unwind/lib.rs | 1 | ||||
| -rw-r--r-- | src/libpanic_unwind/seh.rs | 95 | ||||
| -rw-r--r-- | src/libpanic_unwind/windows.rs | 86 |
3 files changed, 46 insertions, 136 deletions
diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 50d067b56e4..d2a0ef7b1dd 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -61,7 +61,6 @@ cfg_if::cfg_if! { } mod dwarf; -mod windows; // Entry point for catching an exception, implemented using the `try` intrinsic // in the compiler. diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs index 809e4619812..9e76b92a7d7 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -51,9 +51,7 @@ use alloc::boxed::Box; use core::any::Any; use core::mem; use core::raw; - -use crate::windows as c; -use libc::{c_int, c_uint}; +use libc::{c_int, c_uint, c_void}; // First up, a whole bunch of type definitions. There's a few platform-specific // oddities here, and a lot that's just blatantly copied from LLVM. The purpose @@ -76,18 +74,19 @@ use libc::{c_int, c_uint}; // sort of operation. For example, if you compile this C++ code on MSVC and emit // the LLVM IR: // -// #include <stdin.h> +// #include <stdint.h> +// +// struct rust_panic { +// uint64_t x[2]; +// } // // void foo() { -// uint64_t a[2] = {0, 1}; +// rust_panic a = {0, 1}; // throw a; // } // // That's essentially what we're trying to emulate. Most of the constant values -// below were just copied from LLVM, I'm at least not 100% sure what's going on -// everywhere. For example the `.PA_K\0` and `.PEA_K\0` strings below (stuck in -// the names of a few of these) I'm not actually sure what they do, but it seems -// to mirror what LLVM does! +// below were just copied from LLVM, // // In any case, these structures are all constructed in a similar manner, and // it's just somewhat verbose for us. @@ -98,10 +97,9 @@ use libc::{c_int, c_uint}; #[macro_use] mod imp { pub type ptr_t = *mut u8; - pub const OFFSET: i32 = 4; + #[cfg(bootstrap)] pub const NAME1: [u8; 7] = [b'.', b'P', b'A', b'_', b'K', 0, 0]; - pub const NAME2: [u8; 7] = [b'.', b'P', b'A', b'X', 0, 0, 0]; macro_rules! ptr { (0) => (core::ptr::null_mut()); @@ -113,10 +111,9 @@ mod imp { #[macro_use] mod imp { pub type ptr_t = u32; - pub const OFFSET: i32 = 8; + #[cfg(bootstrap)] pub const NAME1: [u8; 7] = [b'.', b'P', b'E', b'A', b'_', b'K', 0]; - pub const NAME2: [u8; 7] = [b'.', b'P', b'E', b'A', b'X', 0, 0]; extern "C" { pub static __ImageBase: u8; @@ -141,7 +138,7 @@ pub struct _ThrowInfo { #[repr(C)] pub struct _CatchableTypeArray { pub nCatchableTypes: c_int, - pub arrayOfCatchableTypes: [imp::ptr_t; 2], + pub arrayOfCatchableTypes: [imp::ptr_t; 1], } #[repr(C)] @@ -164,9 +161,19 @@ pub struct _PMD { pub struct _TypeDescriptor { pub pVFTable: *const u8, pub spare: *mut u8, + #[cfg(bootstrap)] pub name: [u8; 7], + #[cfg(not(bootstrap))] + pub name: [u8; 11], } +// Note that we intentionally ignore name mangling rules here: we don't want C++ +// to be able to catch Rust panics by simply declaring a `struct rust_panic`. +#[cfg(bootstrap)] +use imp::NAME1 as TYPE_NAME; +#[cfg(not(bootstrap))] +const TYPE_NAME: [u8; 11] = *b"rust_panic\0"; + static mut THROW_INFO: _ThrowInfo = _ThrowInfo { attributes: 0, pnfnUnwind: ptr!(0), @@ -175,31 +182,22 @@ static mut THROW_INFO: _ThrowInfo = _ThrowInfo { }; static mut CATCHABLE_TYPE_ARRAY: _CatchableTypeArray = _CatchableTypeArray { - nCatchableTypes: 2, - arrayOfCatchableTypes: [ptr!(0), ptr!(0)], + nCatchableTypes: 1, + arrayOfCatchableTypes: [ptr!(0)], }; -static mut CATCHABLE_TYPE1: _CatchableType = _CatchableType { - properties: 1, +static mut CATCHABLE_TYPE: _CatchableType = _CatchableType { + properties: 0, pType: ptr!(0), thisDisplacement: _PMD { mdisp: 0, pdisp: -1, vdisp: 0, }, - sizeOrOffset: imp::OFFSET, - copy_function: ptr!(0), -}; - -static mut CATCHABLE_TYPE2: _CatchableType = _CatchableType { - properties: 1, - pType: ptr!(0), - thisDisplacement: _PMD { - mdisp: 0, - pdisp: -1, - vdisp: 0, - }, - sizeOrOffset: imp::OFFSET, + #[cfg(bootstrap)] + sizeOrOffset: mem::size_of::<*mut u64>() as c_int, + #[cfg(not(bootstrap))] + sizeOrOffset: mem::size_of::<[u64; 2]>() as c_int, copy_function: ptr!(0), }; @@ -221,16 +219,10 @@ extern "C" { // // Again, I'm not entirely sure what this is describing, it just seems to work. #[cfg_attr(not(test), lang = "msvc_try_filter")] -static mut TYPE_DESCRIPTOR1: _TypeDescriptor = _TypeDescriptor { +static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _, spare: core::ptr::null_mut(), - name: imp::NAME1, -}; - -static mut TYPE_DESCRIPTOR2: _TypeDescriptor = _TypeDescriptor { - pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _, - spare: core::ptr::null_mut(), - name: imp::NAME2, + name: TYPE_NAME, }; pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 { @@ -246,6 +238,11 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 { let ptrs = mem::transmute::<_, raw::TraitObject>(data); let mut ptrs = [ptrs.data as u64, ptrs.vtable as u64]; let mut ptrs_ptr = ptrs.as_mut_ptr(); + let throw_ptr = if cfg!(bootstrap) { + &mut ptrs_ptr as *mut _ as *mut _ + } else { + ptrs_ptr as *mut _ + }; // This... may seems surprising, and justifiably so. On 32-bit MSVC the // pointers between these structure are just that, pointers. On 64-bit MSVC, @@ -270,17 +267,17 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 { atomic_store(&mut THROW_INFO.pCatchableTypeArray as *mut _ as *mut u32, ptr!(&CATCHABLE_TYPE_ARRAY as *const _) as u32); atomic_store(&mut CATCHABLE_TYPE_ARRAY.arrayOfCatchableTypes[0] as *mut _ as *mut u32, - ptr!(&CATCHABLE_TYPE1 as *const _) as u32); - atomic_store(&mut CATCHABLE_TYPE_ARRAY.arrayOfCatchableTypes[1] as *mut _ as *mut u32, - ptr!(&CATCHABLE_TYPE2 as *const _) as u32); - atomic_store(&mut CATCHABLE_TYPE1.pType as *mut _ as *mut u32, - ptr!(&TYPE_DESCRIPTOR1 as *const _) as u32); - atomic_store(&mut CATCHABLE_TYPE2.pType as *mut _ as *mut u32, - ptr!(&TYPE_DESCRIPTOR2 as *const _) as u32); + ptr!(&CATCHABLE_TYPE as *const _) as u32); + atomic_store(&mut CATCHABLE_TYPE.pType as *mut _ as *mut u32, + ptr!(&TYPE_DESCRIPTOR as *const _) as u32); + + extern "system" { + #[unwind(allowed)] + pub fn _CxxThrowException(pExceptionObject: *mut c_void, pThrowInfo: *mut u8) -> !; + } - c::_CxxThrowException(&mut ptrs_ptr as *mut _ as *mut _, - &mut THROW_INFO as *mut _ as *mut _); - u32::max_value() + _CxxThrowException(throw_ptr, + &mut THROW_INFO as *mut _ as *mut _); } pub fn payload() -> [u64; 2] { diff --git a/src/libpanic_unwind/windows.rs b/src/libpanic_unwind/windows.rs deleted file mode 100644 index 3257a9d25a5..00000000000 --- a/src/libpanic_unwind/windows.rs +++ /dev/null @@ -1,86 +0,0 @@ -#![allow(nonstandard_style)] -#![allow(dead_code)] -#![cfg(windows)] - -use libc::{c_long, c_ulong, c_void}; - -pub type DWORD = c_ulong; -pub type LONG = c_long; -pub type ULONG_PTR = usize; -pub type LPVOID = *mut c_void; - -pub const EXCEPTION_MAXIMUM_PARAMETERS: usize = 15; -pub const EXCEPTION_NONCONTINUABLE: DWORD = 0x1; // Noncontinuable exception -pub const EXCEPTION_UNWINDING: DWORD = 0x2; // Unwind is in progress -pub const EXCEPTION_EXIT_UNWIND: DWORD = 0x4; // Exit unwind is in progress -pub const EXCEPTION_TARGET_UNWIND: DWORD = 0x20; // Target unwind in progress -pub const EXCEPTION_COLLIDED_UNWIND: DWORD = 0x40; // Collided exception handler call -pub const EXCEPTION_UNWIND: DWORD = EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND | - EXCEPTION_TARGET_UNWIND | - EXCEPTION_COLLIDED_UNWIND; - -#[repr(C)] -pub struct EXCEPTION_RECORD { - pub ExceptionCode: DWORD, - pub ExceptionFlags: DWORD, - pub ExceptionRecord: *mut EXCEPTION_RECORD, - pub ExceptionAddress: LPVOID, - pub NumberParameters: DWORD, - pub ExceptionInformation: [LPVOID; EXCEPTION_MAXIMUM_PARAMETERS], -} - -#[repr(C)] -pub struct EXCEPTION_POINTERS { - pub ExceptionRecord: *mut EXCEPTION_RECORD, - pub ContextRecord: *mut CONTEXT, -} - -pub enum UNWIND_HISTORY_TABLE {} - -#[repr(C)] -pub struct RUNTIME_FUNCTION { - pub BeginAddress: DWORD, - pub EndAddress: DWORD, - pub UnwindData: DWORD, -} - -pub enum CONTEXT {} - -#[repr(C)] -pub struct DISPATCHER_CONTEXT { - pub ControlPc: LPVOID, - pub ImageBase: LPVOID, - pub FunctionEntry: *const RUNTIME_FUNCTION, - pub EstablisherFrame: LPVOID, - pub TargetIp: LPVOID, - pub ContextRecord: *const CONTEXT, - pub LanguageHandler: LPVOID, - pub HandlerData: *const u8, - pub HistoryTable: *const UNWIND_HISTORY_TABLE, -} - -#[repr(C)] -pub enum EXCEPTION_DISPOSITION { - ExceptionContinueExecution, - ExceptionContinueSearch, - ExceptionNestedException, - ExceptionCollidedUnwind, -} -pub use self::EXCEPTION_DISPOSITION::*; - -extern "system" { - #[unwind(allowed)] - pub fn RaiseException(dwExceptionCode: DWORD, - dwExceptionFlags: DWORD, - nNumberOfArguments: DWORD, - lpArguments: *const ULONG_PTR); - #[unwind(allowed)] - pub fn RtlUnwindEx(TargetFrame: LPVOID, - TargetIp: LPVOID, - ExceptionRecord: *const EXCEPTION_RECORD, - ReturnValue: LPVOID, - OriginalContext: *const CONTEXT, - HistoryTable: *const UNWIND_HISTORY_TABLE); - #[unwind(allowed)] - pub fn _CxxThrowException(pExceptionObject: *mut c_void, pThrowInfo: *mut u8); -} |
