mirror of https://github.com/rust-lang/rust.git
Use pointers instead of `usize` addresses for landing pads
This bring unwind and personality code more in line with strict-provenance
This commit is contained in:
parent
fa6d1e7512
commit
e7a3c341dd
|
@ -63,7 +63,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
|
|||
_uwe: uw::_Unwind_Exception {
|
||||
exception_class: rust_exception_class(),
|
||||
exception_cleanup,
|
||||
private: [0; uw::unwinder_private_data_size],
|
||||
private: [core::ptr::null(); uw::unwinder_private_data_size],
|
||||
},
|
||||
canary: &CANARY,
|
||||
cause: data,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! Parsing of GCC-style Language-Specific Data Area (LSDA)
|
||||
//! For details see:
|
||||
//! * <https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html>
|
||||
//! * <https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html>
|
||||
//! * <https://itanium-cxx-abi.github.io/cxx-abi/exceptions.pdf>
|
||||
//! * <https://www.airs.com/blog/archives/460>
|
||||
//! * <https://www.airs.com/blog/archives/464>
|
||||
|
@ -37,17 +38,19 @@ pub const DW_EH_PE_indirect: u8 = 0x80;
|
|||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct EHContext<'a> {
|
||||
pub ip: usize, // Current instruction pointer
|
||||
pub func_start: usize, // Address of the current function
|
||||
pub get_text_start: &'a dyn Fn() -> usize, // Get address of the code section
|
||||
pub get_data_start: &'a dyn Fn() -> usize, // Get address of the data section
|
||||
pub ip: *const u8, // Current instruction pointer
|
||||
pub func_start: *const u8, // Pointer to the current function
|
||||
pub get_text_start: &'a dyn Fn() -> *const u8, // Get pointer to the code section
|
||||
pub get_data_start: &'a dyn Fn() -> *const u8, // Get pointer to the data section
|
||||
}
|
||||
|
||||
/// Landing pad.
|
||||
type LPad = *const u8;
|
||||
pub enum EHAction {
|
||||
None,
|
||||
Cleanup(usize),
|
||||
Catch(usize),
|
||||
Filter(usize),
|
||||
Cleanup(LPad),
|
||||
Catch(LPad),
|
||||
Filter(LPad),
|
||||
Terminate,
|
||||
}
|
||||
|
||||
|
@ -82,21 +85,21 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
|
|||
|
||||
if !USING_SJLJ_EXCEPTIONS {
|
||||
while reader.ptr < action_table {
|
||||
let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding)?;
|
||||
let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding)?;
|
||||
let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding)?;
|
||||
let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding)?.addr();
|
||||
let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding)?.addr();
|
||||
let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding)?.addr();
|
||||
let cs_action_entry = reader.read_uleb128();
|
||||
// Callsite table is sorted by cs_start, so if we've passed the ip, we
|
||||
// may stop searching.
|
||||
if ip < func_start + cs_start {
|
||||
if ip < func_start.wrapping_add(cs_start) {
|
||||
break;
|
||||
}
|
||||
if ip < func_start + cs_start + cs_len {
|
||||
if ip < func_start.wrapping_add(cs_start + cs_len) {
|
||||
if cs_lpad == 0 {
|
||||
return Ok(EHAction::None);
|
||||
} else {
|
||||
let lpad = lpad_base + cs_lpad;
|
||||
return Ok(interpret_cs_action(action_table as *mut u8, cs_action_entry, lpad));
|
||||
let lpad = lpad_base.wrapping_add(cs_lpad);
|
||||
return Ok(interpret_cs_action(action_table, cs_action_entry, lpad));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,12 +109,12 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
|
|||
// SjLj version:
|
||||
// The "IP" is an index into the call-site table, with two exceptions:
|
||||
// -1 means 'no-action', and 0 means 'terminate'.
|
||||
match ip as isize {
|
||||
match ip.addr() as isize {
|
||||
-1 => return Ok(EHAction::None),
|
||||
0 => return Ok(EHAction::Terminate),
|
||||
_ => (),
|
||||
}
|
||||
let mut idx = ip;
|
||||
let mut idx = ip.addr();
|
||||
loop {
|
||||
let cs_lpad = reader.read_uleb128();
|
||||
let cs_action_entry = reader.read_uleb128();
|
||||
|
@ -119,17 +122,18 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
|
|||
if idx == 0 {
|
||||
// Can never have null landing pad for sjlj -- that would have
|
||||
// been indicated by a -1 call site index.
|
||||
let lpad = (cs_lpad + 1) as usize;
|
||||
return Ok(interpret_cs_action(action_table as *mut u8, cs_action_entry, lpad));
|
||||
// FIXME(strict provenance)
|
||||
let lpad = ptr::from_exposed_addr((cs_lpad + 1) as usize);
|
||||
return Ok(interpret_cs_action(action_table, cs_action_entry, lpad));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn interpret_cs_action(
|
||||
action_table: *mut u8,
|
||||
action_table: *const u8,
|
||||
cs_action_entry: u64,
|
||||
lpad: usize,
|
||||
lpad: LPad,
|
||||
) -> EHAction {
|
||||
if cs_action_entry == 0 {
|
||||
// If cs_action_entry is 0 then this is a cleanup (Drop::drop). We run these
|
||||
|
@ -138,7 +142,7 @@ unsafe fn interpret_cs_action(
|
|||
} else {
|
||||
// If lpad != 0 and cs_action_entry != 0, we have to check ttype_index.
|
||||
// If ttype_index == 0 under the condition, we take cleanup action.
|
||||
let action_record = (action_table as *mut u8).offset(cs_action_entry as isize - 1);
|
||||
let action_record = action_table.offset(cs_action_entry as isize - 1);
|
||||
let mut action_reader = DwarfReader::new(action_record);
|
||||
let ttype_index = action_reader.read_sleb128();
|
||||
if ttype_index == 0 {
|
||||
|
@ -161,15 +165,16 @@ unsafe fn read_encoded_pointer(
|
|||
reader: &mut DwarfReader,
|
||||
context: &EHContext<'_>,
|
||||
encoding: u8,
|
||||
) -> Result<usize, ()> {
|
||||
) -> Result<*const u8, ()> {
|
||||
if encoding == DW_EH_PE_omit {
|
||||
return Err(());
|
||||
}
|
||||
|
||||
// DW_EH_PE_aligned implies it's an absolute pointer value
|
||||
if encoding == DW_EH_PE_aligned {
|
||||
reader.ptr = reader.ptr.with_addr(round_up(reader.ptr.addr(), mem::size_of::<usize>())?);
|
||||
return Ok(reader.read::<usize>());
|
||||
reader.ptr =
|
||||
reader.ptr.with_addr(round_up(reader.ptr.addr(), mem::size_of::<*const u8>())?);
|
||||
return Ok(reader.read::<*const u8>());
|
||||
}
|
||||
|
||||
let mut result = match encoding & 0x0F {
|
||||
|
@ -190,18 +195,21 @@ unsafe fn read_encoded_pointer(
|
|||
// relative to address of the encoded value, despite the name
|
||||
DW_EH_PE_pcrel => reader.ptr.expose_addr(),
|
||||
DW_EH_PE_funcrel => {
|
||||
if context.func_start == 0 {
|
||||
if context.func_start.is_null() {
|
||||
return Err(());
|
||||
}
|
||||
context.func_start
|
||||
context.func_start.expose_addr()
|
||||
}
|
||||
DW_EH_PE_textrel => (*context.get_text_start)(),
|
||||
DW_EH_PE_datarel => (*context.get_data_start)(),
|
||||
DW_EH_PE_textrel => (*context.get_text_start)().expose_addr(),
|
||||
DW_EH_PE_datarel => (*context.get_data_start)().expose_addr(),
|
||||
_ => return Err(()),
|
||||
};
|
||||
|
||||
// FIXME(strict provenance)
|
||||
let mut result: *const u8 = ptr::from_exposed_addr::<u8>(result);
|
||||
|
||||
if encoding & DW_EH_PE_indirect != 0 {
|
||||
result = *ptr::from_exposed_addr::<usize>(result);
|
||||
result = *(result.cast::<*const u8>());
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
|
||||
use super::dwarf::eh::{self, EHAction, EHContext};
|
||||
use crate::ffi::c_int;
|
||||
use libc::uintptr_t;
|
||||
use unwind as uw;
|
||||
|
||||
// Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
|
||||
|
@ -160,9 +159,9 @@ cfg_if::cfg_if! {
|
|||
uw::_Unwind_SetGR(
|
||||
context,
|
||||
UNWIND_DATA_REG.0,
|
||||
exception_object as uintptr_t,
|
||||
exception_object as uw::_Unwind_Ptr,
|
||||
);
|
||||
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
|
||||
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null());
|
||||
uw::_Unwind_SetIP(context, lpad);
|
||||
return uw::_URC_INSTALL_CONTEXT;
|
||||
}
|
||||
|
@ -222,9 +221,9 @@ cfg_if::cfg_if! {
|
|||
uw::_Unwind_SetGR(
|
||||
context,
|
||||
UNWIND_DATA_REG.0,
|
||||
exception_object as uintptr_t,
|
||||
exception_object.cast(),
|
||||
);
|
||||
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
|
||||
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null());
|
||||
uw::_Unwind_SetIP(context, lpad);
|
||||
uw::_URC_INSTALL_CONTEXT
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#![feature(staged_api)]
|
||||
#![feature(c_unwind)]
|
||||
#![feature(cfg_target_abi)]
|
||||
#![feature(strict_provenance)]
|
||||
#![cfg_attr(not(target_env = "msvc"), feature(libc))]
|
||||
#![allow(internal_features)]
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#![allow(nonstandard_style)]
|
||||
|
||||
use libc::{c_int, c_void, uintptr_t};
|
||||
use libc::{c_int, c_void};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
|
@ -19,8 +19,8 @@ pub enum _Unwind_Reason_Code {
|
|||
pub use _Unwind_Reason_Code::*;
|
||||
|
||||
pub type _Unwind_Exception_Class = u64;
|
||||
pub type _Unwind_Word = uintptr_t;
|
||||
pub type _Unwind_Ptr = uintptr_t;
|
||||
pub type _Unwind_Word = *const u8;
|
||||
pub type _Unwind_Ptr = *const u8;
|
||||
pub type _Unwind_Trace_Fn =
|
||||
extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut c_void) -> _Unwind_Reason_Code;
|
||||
|
||||
|
@ -214,7 +214,7 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe
|
|||
// On Android or ARM/Linux, these are implemented as macros:
|
||||
|
||||
pub unsafe fn _Unwind_GetGR(ctx: *mut _Unwind_Context, reg_index: c_int) -> _Unwind_Word {
|
||||
let mut val: _Unwind_Word = 0;
|
||||
let mut val: _Unwind_Word = core::ptr::null();
|
||||
_Unwind_VRS_Get(ctx, _UVRSC_CORE, reg_index as _Unwind_Word, _UVRSD_UINT32,
|
||||
&mut val as *mut _ as *mut c_void);
|
||||
val
|
||||
|
@ -229,14 +229,14 @@ if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", targe
|
|||
pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context)
|
||||
-> _Unwind_Word {
|
||||
let val = _Unwind_GetGR(ctx, UNWIND_IP_REG);
|
||||
(val & !1) as _Unwind_Word
|
||||
val.map_addr(|v| v & !1)
|
||||
}
|
||||
|
||||
pub unsafe fn _Unwind_SetIP(ctx: *mut _Unwind_Context,
|
||||
value: _Unwind_Word) {
|
||||
// Propagate thumb bit to instruction pointer
|
||||
let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG) & 1;
|
||||
let value = value | thumb_state;
|
||||
let thumb_state = _Unwind_GetGR(ctx, UNWIND_IP_REG).addr() & 1;
|
||||
let value = value.map_addr(|v| v | thumb_state);
|
||||
_Unwind_SetGR(ctx, UNWIND_IP_REG, value);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue