Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor panic_unwind/seh.rs pointer use #123490

Merged
merged 1 commit into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions library/panic_unwind/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#![feature(panic_unwind)]
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(strict_provenance)]
#![feature(exposed_provenance)]
#![feature(rustc_attrs)]
#![panic_runtime]
#![feature(panic_runtime)]
Expand Down
112 changes: 71 additions & 41 deletions library/panic_unwind/src/seh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,58 +109,88 @@ struct Exception {
// [1]: https://www.geoffchappell.com/studies/msvc/language/predefined/

#[cfg(target_arch = "x86")]
#[macro_use]
mod imp {
pub type ptr_t = *mut u8;

macro_rules! ptr {
(0) => {
core::ptr::null_mut()
};
($e:expr) => {
$e as *mut u8
};
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct ptr_t(*mut u8);

impl ptr_t {
pub const fn null() -> Self {
Self(core::ptr::null_mut())
}

pub const fn new(ptr: *mut u8) -> Self {
Self(ptr)
}

pub const fn raw(self) -> *mut u8 {
self.0
}
}
}

#[cfg(not(target_arch = "x86"))]
#[macro_use]
mod imp {
pub type ptr_t = u32;
use core::ptr::addr_of;

// On 64-bit systems, SEH represents pointers as 32-bit offsets from `__ImageBase`.
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct ptr_t(u32);

extern "C" {
pub static __ImageBase: u8;
}

macro_rules! ptr {
(0) => (0);
($e:expr) => {
(($e as usize) - (addr_of!(imp::__ImageBase) as usize)) as u32
impl ptr_t {
pub const fn null() -> Self {
Self(0)
}

pub fn new(ptr: *mut u8) -> Self {
// We need to expose the provenance of the pointer because it is not carried by
// the `u32`, while the FFI needs to have this provenance to excess our statics.
//
// NOTE(niluxv): we could use `MaybeUninit<u32>` instead to leak the provenance
// into the FFI. In theory then the other side would need to do some processing
// to get a pointer with correct provenance, but these system functions aren't
// going to be cross-lang LTOed anyway. However, using expose is shorter and
// requires less unsafe.
let addr: usize = ptr.expose_provenance();
let image_base = unsafe { addr_of!(__ImageBase) }.addr();
let offset: usize = addr - image_base;
Self(offset as u32)
}

pub const fn raw(self) -> u32 {
self.0
}
}
}

use imp::ptr_t;

#[repr(C)]
pub struct _ThrowInfo {
pub attributes: c_uint,
pub pmfnUnwind: imp::ptr_t,
pub pForwardCompat: imp::ptr_t,
pub pCatchableTypeArray: imp::ptr_t,
pub pmfnUnwind: ptr_t,
pub pForwardCompat: ptr_t,
pub pCatchableTypeArray: ptr_t,
}

#[repr(C)]
pub struct _CatchableTypeArray {
pub nCatchableTypes: c_int,
pub arrayOfCatchableTypes: [imp::ptr_t; 1],
pub arrayOfCatchableTypes: [ptr_t; 1],
}

#[repr(C)]
pub struct _CatchableType {
pub properties: c_uint,
pub pType: imp::ptr_t,
pub pType: ptr_t,
pub thisDisplacement: _PMD,
pub sizeOrOffset: c_int,
pub copyFunction: imp::ptr_t,
pub copyFunction: ptr_t,
}

#[repr(C)]
Expand All @@ -186,20 +216,20 @@ const TYPE_NAME: [u8; 11] = *b"rust_panic\0";

static mut THROW_INFO: _ThrowInfo = _ThrowInfo {
attributes: 0,
pmfnUnwind: ptr!(0),
pForwardCompat: ptr!(0),
pCatchableTypeArray: ptr!(0),
pmfnUnwind: ptr_t::null(),
pForwardCompat: ptr_t::null(),
pCatchableTypeArray: ptr_t::null(),
};

static mut CATCHABLE_TYPE_ARRAY: _CatchableTypeArray =
_CatchableTypeArray { nCatchableTypes: 1, arrayOfCatchableTypes: [ptr!(0)] };
_CatchableTypeArray { nCatchableTypes: 1, arrayOfCatchableTypes: [ptr_t::null()] };

static mut CATCHABLE_TYPE: _CatchableType = _CatchableType {
properties: 0,
pType: ptr!(0),
pType: ptr_t::null(),
thisDisplacement: _PMD { mdisp: 0, pdisp: -1, vdisp: 0 },
sizeOrOffset: mem::size_of::<Exception>() as c_int,
copyFunction: ptr!(0),
copyFunction: ptr_t::null(),
};

extern "C" {
Expand Down Expand Up @@ -246,9 +276,9 @@ macro_rules! define_cleanup {
super::__rust_drop_panic();
}
}
unsafe extern $abi2 fn exception_copy(_dest: *mut Exception,
_src: *mut Exception)
-> *mut Exception {
unsafe extern $abi2 fn exception_copy(
_dest: *mut Exception, _src: *mut Exception
) -> *mut Exception {
panic!("Rust panics cannot be copied");
}
}
Expand Down Expand Up @@ -296,24 +326,24 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
// In any case, we basically need to do something like this until we can
// express more operations in statics (and we may never be able to).
atomic_store_seqcst(
addr_of_mut!(THROW_INFO.pmfnUnwind) as *mut u32,
ptr!(exception_cleanup) as u32,
addr_of_mut!(THROW_INFO.pmfnUnwind).cast(),
ptr_t::new(exception_cleanup as *mut u8).raw(),
);
atomic_store_seqcst(
addr_of_mut!(THROW_INFO.pCatchableTypeArray) as *mut u32,
ptr!(addr_of!(CATCHABLE_TYPE_ARRAY)) as u32,
addr_of_mut!(THROW_INFO.pCatchableTypeArray).cast(),
ptr_t::new(addr_of_mut!(CATCHABLE_TYPE_ARRAY).cast()).raw(),
);
atomic_store_seqcst(
addr_of_mut!(CATCHABLE_TYPE_ARRAY.arrayOfCatchableTypes[0]) as *mut u32,
ptr!(addr_of!(CATCHABLE_TYPE)) as u32,
addr_of_mut!(CATCHABLE_TYPE_ARRAY.arrayOfCatchableTypes[0]).cast(),
ptr_t::new(addr_of_mut!(CATCHABLE_TYPE).cast()).raw(),
);
atomic_store_seqcst(
addr_of_mut!(CATCHABLE_TYPE.pType) as *mut u32,
ptr!(addr_of!(TYPE_DESCRIPTOR)) as u32,
addr_of_mut!(CATCHABLE_TYPE.pType).cast(),
ptr_t::new(addr_of_mut!(TYPE_DESCRIPTOR).cast()).raw(),
);
atomic_store_seqcst(
addr_of_mut!(CATCHABLE_TYPE.copyFunction) as *mut u32,
ptr!(exception_copy) as u32,
addr_of_mut!(CATCHABLE_TYPE.copyFunction).cast(),
ptr_t::new(exception_copy as *mut u8).raw(),
);

extern "system-unwind" {
Expand Down
Loading