about summary refs log tree commit diff
path: root/src/libpanic_unwind
diff options
context:
space:
mode:
authorAmanieu d'Antras <amanieu@gmail.com>2019-10-27 22:33:25 +0000
committerAmanieu d'Antras <amanieu@gmail.com>2019-11-03 14:03:21 +0000
commitad61c88e729acf9dbbe17493faeedb760c6df08c (patch)
tree23b2d2f985ad3edd337566337ac4be4e3a14cd68 /src/libpanic_unwind
parent83d6bf49296dd2c365ee3989d114a99db9ca3577 (diff)
downloadrust-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.rs1
-rw-r--r--src/libpanic_unwind/seh.rs95
-rw-r--r--src/libpanic_unwind/windows.rs86
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);
-}