diff options
Diffstat (limited to 'library/std/src/sys/pal')
| -rw-r--r-- | library/std/src/sys/pal/mod.rs | 1 | ||||
| -rw-r--r-- | library/std/src/sys/pal/personality/dwarf/eh.rs | 257 | ||||
| -rw-r--r-- | library/std/src/sys/pal/personality/dwarf/mod.rs | 73 | ||||
| -rw-r--r-- | library/std/src/sys/pal/personality/dwarf/tests.rs | 19 | ||||
| -rw-r--r-- | library/std/src/sys/pal/personality/emcc.rs | 20 | ||||
| -rw-r--r-- | library/std/src/sys/pal/personality/gcc.rs | 293 | ||||
| -rw-r--r-- | library/std/src/sys/pal/personality/mod.rs | 47 |
7 files changed, 0 insertions, 710 deletions
diff --git a/library/std/src/sys/pal/mod.rs b/library/std/src/sys/pal/mod.rs index 88420bd3612..66b2a4b8885 100644 --- a/library/std/src/sys/pal/mod.rs +++ b/library/std/src/sys/pal/mod.rs @@ -23,7 +23,6 @@ #![allow(missing_debug_implementations)] pub mod common; -mod personality; cfg_if::cfg_if! { if #[cfg(unix)] { diff --git a/library/std/src/sys/pal/personality/dwarf/eh.rs b/library/std/src/sys/pal/personality/dwarf/eh.rs deleted file mode 100644 index a78084de0fa..00000000000 --- a/library/std/src/sys/pal/personality/dwarf/eh.rs +++ /dev/null @@ -1,257 +0,0 @@ -//! 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> -//! -//! A reference implementation may be found in the GCC source tree -//! (`<root>/libgcc/unwind-c.c` as of this writing). - -#![allow(non_upper_case_globals)] -#![allow(unused)] - -use super::DwarfReader; -use core::mem; -use core::ptr; - -pub const DW_EH_PE_omit: u8 = 0xFF; -pub const DW_EH_PE_absptr: u8 = 0x00; - -pub const DW_EH_PE_uleb128: u8 = 0x01; -pub const DW_EH_PE_udata2: u8 = 0x02; -pub const DW_EH_PE_udata4: u8 = 0x03; -pub const DW_EH_PE_udata8: u8 = 0x04; -pub const DW_EH_PE_sleb128: u8 = 0x09; -pub const DW_EH_PE_sdata2: u8 = 0x0A; -pub const DW_EH_PE_sdata4: u8 = 0x0B; -pub const DW_EH_PE_sdata8: u8 = 0x0C; - -pub const DW_EH_PE_pcrel: u8 = 0x10; -pub const DW_EH_PE_textrel: u8 = 0x20; -pub const DW_EH_PE_datarel: u8 = 0x30; -pub const DW_EH_PE_funcrel: u8 = 0x40; -pub const DW_EH_PE_aligned: u8 = 0x50; - -pub const DW_EH_PE_indirect: u8 = 0x80; - -#[derive(Copy, Clone)] -pub struct EHContext<'a> { - 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(LPad), - Catch(LPad), - Filter(LPad), - Terminate, -} - -pub const USING_SJLJ_EXCEPTIONS: bool = cfg!(all(target_os = "ios", target_arch = "arm")); - -pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result<EHAction, ()> { - if lsda.is_null() { - return Ok(EHAction::None); - } - - let func_start = context.func_start; - let mut reader = DwarfReader::new(lsda); - - let start_encoding = reader.read::<u8>(); - // base address for landing pad offsets - let lpad_base = if start_encoding != DW_EH_PE_omit { - read_encoded_pointer(&mut reader, context, start_encoding)? - } else { - func_start - }; - - let ttype_encoding = reader.read::<u8>(); - if ttype_encoding != DW_EH_PE_omit { - // Rust doesn't analyze exception types, so we don't care about the type table - reader.read_uleb128(); - } - - let call_site_encoding = reader.read::<u8>(); - let call_site_table_length = reader.read_uleb128(); - let action_table = reader.ptr.add(call_site_table_length as usize); - let ip = context.ip; - - if !USING_SJLJ_EXCEPTIONS { - // read the callsite table - while reader.ptr < action_table { - // these are offsets rather than pointers; - let cs_start = read_encoded_offset(&mut reader, call_site_encoding)?; - let cs_len = read_encoded_offset(&mut reader, call_site_encoding)?; - let cs_lpad = read_encoded_offset(&mut reader, call_site_encoding)?; - 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.wrapping_add(cs_start) { - break; - } - if ip < func_start.wrapping_add(cs_start + cs_len) { - if cs_lpad == 0 { - return Ok(EHAction::None); - } else { - let lpad = lpad_base.wrapping_add(cs_lpad); - return Ok(interpret_cs_action(action_table, cs_action_entry, lpad)); - } - } - } - // Ip is not present in the table. This indicates a nounwind call. - Ok(EHAction::Terminate) - } else { - // 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.addr() as isize { - -1 => return Ok(EHAction::None), - 0 => return Ok(EHAction::Terminate), - _ => (), - } - let mut idx = ip.addr(); - loop { - let cs_lpad = reader.read_uleb128(); - let cs_action_entry = reader.read_uleb128(); - idx -= 1; - if idx == 0 { - // Can never have null landing pad for sjlj -- that would have - // been indicated by a -1 call site index. - // 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: *const u8, - cs_action_entry: u64, - lpad: LPad, -) -> EHAction { - if cs_action_entry == 0 { - // If cs_action_entry is 0 then this is a cleanup (Drop::drop). We run these - // for both Rust panics and foreign exceptions. - EHAction::Cleanup(lpad) - } 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.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 { - EHAction::Cleanup(lpad) - } else if ttype_index > 0 { - // Stop unwinding Rust panics at catch_unwind. - EHAction::Catch(lpad) - } else { - EHAction::Filter(lpad) - } - } -} - -#[inline] -fn round_up(unrounded: usize, align: usize) -> Result<usize, ()> { - if align.is_power_of_two() { Ok((unrounded + align - 1) & !(align - 1)) } else { Err(()) } -} - -/// Read a offset (`usize`) from `reader` whose encoding is described by `encoding`. -/// -/// `encoding` must be a [DWARF Exception Header Encoding as described by the LSB spec][LSB-dwarf-ext]. -/// In addition the upper ("application") part must be zero. -/// -/// # Errors -/// Returns `Err` if `encoding` -/// * is not a valid DWARF Exception Header Encoding, -/// * is `DW_EH_PE_omit`, or -/// * has a non-zero application part. -/// -/// [LSB-dwarf-ext]: https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html -unsafe fn read_encoded_offset(reader: &mut DwarfReader, encoding: u8) -> Result<usize, ()> { - if encoding == DW_EH_PE_omit || encoding & 0xF0 != 0 { - return Err(()); - } - let result = match encoding & 0x0F { - // despite the name, LLVM also uses absptr for offsets instead of pointers - DW_EH_PE_absptr => reader.read::<usize>(), - DW_EH_PE_uleb128 => reader.read_uleb128() as usize, - DW_EH_PE_udata2 => reader.read::<u16>() as usize, - DW_EH_PE_udata4 => reader.read::<u32>() as usize, - DW_EH_PE_udata8 => reader.read::<u64>() as usize, - DW_EH_PE_sleb128 => reader.read_sleb128() as usize, - DW_EH_PE_sdata2 => reader.read::<i16>() as usize, - DW_EH_PE_sdata4 => reader.read::<i32>() as usize, - DW_EH_PE_sdata8 => reader.read::<i64>() as usize, - _ => return Err(()), - }; - Ok(result) -} - -/// Read a pointer from `reader` whose encoding is described by `encoding`. -/// -/// `encoding` must be a [DWARF Exception Header Encoding as described by the LSB spec][LSB-dwarf-ext]. -/// -/// # Errors -/// Returns `Err` if `encoding` -/// * is not a valid DWARF Exception Header Encoding, -/// * is `DW_EH_PE_omit`, or -/// * combines `DW_EH_PE_absptr` or `DW_EH_PE_aligned` application part with an integer encoding -/// (not `DW_EH_PE_absptr`) in the value format part. -/// -/// [LSB-dwarf-ext]: https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html -unsafe fn read_encoded_pointer( - reader: &mut DwarfReader, - context: &EHContext<'_>, - encoding: u8, -) -> Result<*const u8, ()> { - if encoding == DW_EH_PE_omit { - return Err(()); - } - - let base_ptr = match encoding & 0x70 { - DW_EH_PE_absptr => core::ptr::null(), - // relative to address of the encoded value, despite the name - DW_EH_PE_pcrel => reader.ptr, - DW_EH_PE_funcrel => { - if context.func_start.is_null() { - return Err(()); - } - context.func_start - } - DW_EH_PE_textrel => (*context.get_text_start)(), - DW_EH_PE_datarel => (*context.get_data_start)(), - // aligned means the value is aligned to the size of a pointer - DW_EH_PE_aligned => { - reader.ptr = - reader.ptr.with_addr(round_up(reader.ptr.addr(), mem::size_of::<*const u8>())?); - core::ptr::null() - } - _ => return Err(()), - }; - - let mut ptr = if base_ptr.is_null() { - // any value encoding other than absptr would be nonsensical here; - // there would be no source of pointer provenance - if encoding & 0x0F != DW_EH_PE_absptr { - return Err(()); - } - reader.read::<*const u8>() - } else { - let offset = read_encoded_offset(reader, encoding & 0x0F)?; - base_ptr.wrapping_add(offset) - }; - - if encoding & DW_EH_PE_indirect != 0 { - ptr = *(ptr.cast::<*const u8>()); - } - - Ok(ptr) -} diff --git a/library/std/src/sys/pal/personality/dwarf/mod.rs b/library/std/src/sys/pal/personality/dwarf/mod.rs deleted file mode 100644 index 652fbe95a14..00000000000 --- a/library/std/src/sys/pal/personality/dwarf/mod.rs +++ /dev/null @@ -1,73 +0,0 @@ -//! Utilities for parsing DWARF-encoded data streams. -//! See <http://www.dwarfstd.org>, -//! DWARF-4 standard, Section 7 - "Data Representation" - -// This module is used only by x86_64-pc-windows-gnu for now, but we -// are compiling it everywhere to avoid regressions. -#![allow(unused)] - -#[cfg(test)] -mod tests; - -pub mod eh; - -use core::mem; - -pub struct DwarfReader { - pub ptr: *const u8, -} - -#[repr(C, packed)] -struct Unaligned<T>(T); - -impl DwarfReader { - pub fn new(ptr: *const u8) -> DwarfReader { - DwarfReader { ptr } - } - - // DWARF streams are packed, so e.g., a u32 would not necessarily be aligned - // on a 4-byte boundary. This may cause problems on platforms with strict - // alignment requirements. By wrapping data in a "packed" struct, we are - // telling the backend to generate "misalignment-safe" code. - pub unsafe fn read<T: Copy>(&mut self) -> T { - let Unaligned(result) = *(self.ptr as *const Unaligned<T>); - self.ptr = self.ptr.add(mem::size_of::<T>()); - result - } - - // ULEB128 and SLEB128 encodings are defined in Section 7.6 - "Variable - // Length Data". - pub unsafe fn read_uleb128(&mut self) -> u64 { - let mut shift: usize = 0; - let mut result: u64 = 0; - let mut byte: u8; - loop { - byte = self.read::<u8>(); - result |= ((byte & 0x7F) as u64) << shift; - shift += 7; - if byte & 0x80 == 0 { - break; - } - } - result - } - - pub unsafe fn read_sleb128(&mut self) -> i64 { - let mut shift: u32 = 0; - let mut result: u64 = 0; - let mut byte: u8; - loop { - byte = self.read::<u8>(); - result |= ((byte & 0x7F) as u64) << shift; - shift += 7; - if byte & 0x80 == 0 { - break; - } - } - // sign-extend - if shift < u64::BITS && (byte & 0x40) != 0 { - result |= (!0 as u64) << shift; - } - result as i64 - } -} diff --git a/library/std/src/sys/pal/personality/dwarf/tests.rs b/library/std/src/sys/pal/personality/dwarf/tests.rs deleted file mode 100644 index 1644f37083a..00000000000 --- a/library/std/src/sys/pal/personality/dwarf/tests.rs +++ /dev/null @@ -1,19 +0,0 @@ -use super::*; - -#[test] -fn dwarf_reader() { - let encoded: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 0xE5, 0x8E, 0x26, 0x9B, 0xF1, 0x59, 0xFF, 0xFF]; - - let mut reader = DwarfReader::new(encoded.as_ptr()); - - unsafe { - assert!(reader.read::<u8>() == u8::to_be(1u8)); - assert!(reader.read::<u16>() == u16::to_be(0x0203)); - assert!(reader.read::<u32>() == u32::to_be(0x04050607)); - - assert!(reader.read_uleb128() == 624485); - assert!(reader.read_sleb128() == -624485); - - assert!(reader.read::<i8>() == i8::to_be(-1)); - } -} diff --git a/library/std/src/sys/pal/personality/emcc.rs b/library/std/src/sys/pal/personality/emcc.rs deleted file mode 100644 index cb52ae89b19..00000000000 --- a/library/std/src/sys/pal/personality/emcc.rs +++ /dev/null @@ -1,20 +0,0 @@ -//! On Emscripten Rust panics are wrapped in C++ exceptions, so we just forward -//! to `__gxx_personality_v0` which is provided by Emscripten. - -use crate::ffi::c_int; -use unwind as uw; - -// This is required by the compiler to exist (e.g., it's a lang item), but it's -// never actually called by the compiler. Emscripten EH doesn't use a -// personality function at all, it instead uses __cxa_find_matching_catch. -// Wasm error handling would use __gxx_personality_wasm0. -#[lang = "eh_personality"] -unsafe extern "C" fn rust_eh_personality( - _version: c_int, - _actions: uw::_Unwind_Action, - _exception_class: uw::_Unwind_Exception_Class, - _exception_object: *mut uw::_Unwind_Exception, - _context: *mut uw::_Unwind_Context, -) -> uw::_Unwind_Reason_Code { - core::intrinsics::abort() -} diff --git a/library/std/src/sys/pal/personality/gcc.rs b/library/std/src/sys/pal/personality/gcc.rs deleted file mode 100644 index 6f317131145..00000000000 --- a/library/std/src/sys/pal/personality/gcc.rs +++ /dev/null @@ -1,293 +0,0 @@ -//! Implementation of panics backed by libgcc/libunwind (in some form). -//! -//! For background on exception handling and stack unwinding please see -//! "Exception Handling in LLVM" (llvm.org/docs/ExceptionHandling.html) and -//! documents linked from it. -//! These are also good reads: -//! * <https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html> -//! * <https://monoinfinito.wordpress.com/series/exception-handling-in-c/> -//! * <https://www.airs.com/blog/index.php?s=exception+frames> -//! -//! ## A brief summary -//! -//! Exception handling happens in two phases: a search phase and a cleanup -//! phase. -//! -//! In both phases the unwinder walks stack frames from top to bottom using -//! information from the stack frame unwind sections of the current process's -//! modules ("module" here refers to an OS module, i.e., an executable or a -//! dynamic library). -//! -//! For each stack frame, it invokes the associated "personality routine", whose -//! address is also stored in the unwind info section. -//! -//! In the search phase, the job of a personality routine is to examine -//! exception object being thrown, and to decide whether it should be caught at -//! that stack frame. Once the handler frame has been identified, cleanup phase -//! begins. -//! -//! In the cleanup phase, the unwinder invokes each personality routine again. -//! This time it decides which (if any) cleanup code needs to be run for -//! the current stack frame. If so, the control is transferred to a special -//! branch in the function body, the "landing pad", which invokes destructors, -//! frees memory, etc. At the end of the landing pad, control is transferred -//! back to the unwinder and unwinding resumes. -//! -//! Once stack has been unwound down to the handler frame level, unwinding stops -//! and the last personality routine transfers control to the catch block. - -use super::dwarf::eh::{self, EHAction, EHContext}; -use crate::ffi::c_int; -use unwind as uw; - -// Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister() -// and TargetLowering::getExceptionSelectorRegister() for each architecture, -// then mapped to DWARF register numbers via register definition tables -// (typically <arch>RegisterInfo.td, search for "DwarfRegNum"). -// See also https://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register. - -#[cfg(target_arch = "x86")] -const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX - -#[cfg(target_arch = "x86_64")] -const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX - -#[cfg(any(target_arch = "arm", target_arch = "aarch64"))] -const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 / X0, X1 - -#[cfg(target_arch = "m68k")] -const UNWIND_DATA_REG: (i32, i32) = (0, 1); // D0, D1 - -#[cfg(any( - target_arch = "mips", - target_arch = "mips32r6", - target_arch = "mips64", - target_arch = "mips64r6" -))] -const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1 - -#[cfg(target_arch = "csky")] -const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 - -#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))] -const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4 - -#[cfg(target_arch = "s390x")] -const UNWIND_DATA_REG: (i32, i32) = (6, 7); // R6, R7 - -#[cfg(any(target_arch = "sparc", target_arch = "sparc64"))] -const UNWIND_DATA_REG: (i32, i32) = (24, 25); // I0, I1 - -#[cfg(target_arch = "hexagon")] -const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 - -#[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))] -const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11 - -#[cfg(target_arch = "loongarch64")] -const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1 - -// The following code is based on GCC's C and C++ personality routines. For reference, see: -// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc -// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c - -cfg_if::cfg_if! { - if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "tvos"), not(target_os = "watchos"), not(target_os = "netbsd")))] { - // ARM EHABI personality routine. - // https://web.archive.org/web/20190728160938/https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf - // - // iOS uses the default routine instead since it uses SjLj unwinding. - #[lang = "eh_personality"] - unsafe extern "C" fn rust_eh_personality( - state: uw::_Unwind_State, - exception_object: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context, - ) -> uw::_Unwind_Reason_Code { - let state = state as c_int; - let action = state & uw::_US_ACTION_MASK as c_int; - let search_phase = if action == uw::_US_VIRTUAL_UNWIND_FRAME as c_int { - // Backtraces on ARM will call the personality routine with - // state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases - // we want to continue unwinding the stack, otherwise all our backtraces - // would end at __rust_try - if state & uw::_US_FORCE_UNWIND as c_int != 0 { - return continue_unwind(exception_object, context); - } - true - } else if action == uw::_US_UNWIND_FRAME_STARTING as c_int { - false - } else if action == uw::_US_UNWIND_FRAME_RESUME as c_int { - return continue_unwind(exception_object, context); - } else { - return uw::_URC_FAILURE; - }; - - // The DWARF unwinder assumes that _Unwind_Context holds things like the function - // and LSDA pointers, however ARM EHABI places them into the exception object. - // To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which - // take only the context pointer, GCC personality routines stash a pointer to - // exception_object in the context, using location reserved for ARM's - // "scratch register" (r12). - uw::_Unwind_SetGR(context, uw::UNWIND_POINTER_REG, exception_object as uw::_Unwind_Ptr); - // ...A more principled approach would be to provide the full definition of ARM's - // _Unwind_Context in our libunwind bindings and fetch the required data from there - // directly, bypassing DWARF compatibility functions. - - let eh_action = match find_eh_action(context) { - Ok(action) => action, - Err(_) => return uw::_URC_FAILURE, - }; - if search_phase { - match eh_action { - EHAction::None | EHAction::Cleanup(_) => { - return continue_unwind(exception_object, context); - } - EHAction::Catch(_) | EHAction::Filter(_) => { - // EHABI requires the personality routine to update the - // SP value in the barrier cache of the exception object. - (*exception_object).private[5] = - uw::_Unwind_GetGR(context, uw::UNWIND_SP_REG); - return uw::_URC_HANDLER_FOUND; - } - EHAction::Terminate => return uw::_URC_FAILURE, - } - } else { - match eh_action { - EHAction::None => return continue_unwind(exception_object, context), - EHAction::Filter(_) if state & uw::_US_FORCE_UNWIND as c_int != 0 => return continue_unwind(exception_object, context), - EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => { - uw::_Unwind_SetGR( - context, - UNWIND_DATA_REG.0, - exception_object as uw::_Unwind_Ptr, - ); - uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null()); - uw::_Unwind_SetIP(context, lpad); - return uw::_URC_INSTALL_CONTEXT; - } - EHAction::Terminate => return uw::_URC_FAILURE, - } - } - - // On ARM EHABI the personality routine is responsible for actually - // unwinding a single stack frame before returning (ARM EHABI Sec. 6.1). - unsafe fn continue_unwind( - exception_object: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context, - ) -> uw::_Unwind_Reason_Code { - if __gnu_unwind_frame(exception_object, context) == uw::_URC_NO_REASON { - uw::_URC_CONTINUE_UNWIND - } else { - uw::_URC_FAILURE - } - } - // defined in libgcc - extern "C" { - fn __gnu_unwind_frame( - exception_object: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context, - ) -> uw::_Unwind_Reason_Code; - } - } - } else { - // Default personality routine, which is used directly on most targets - // and indirectly on Windows x86_64 via SEH. - unsafe extern "C" fn rust_eh_personality_impl( - version: c_int, - actions: uw::_Unwind_Action, - _exception_class: uw::_Unwind_Exception_Class, - exception_object: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context, - ) -> uw::_Unwind_Reason_Code { - if version != 1 { - return uw::_URC_FATAL_PHASE1_ERROR; - } - let eh_action = match find_eh_action(context) { - Ok(action) => action, - Err(_) => return uw::_URC_FATAL_PHASE1_ERROR, - }; - if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 { - match eh_action { - EHAction::None | EHAction::Cleanup(_) => uw::_URC_CONTINUE_UNWIND, - EHAction::Catch(_) | EHAction::Filter(_) => uw::_URC_HANDLER_FOUND, - EHAction::Terminate => uw::_URC_FATAL_PHASE1_ERROR, - } - } else { - match eh_action { - EHAction::None => uw::_URC_CONTINUE_UNWIND, - // Forced unwinding hits a terminate action. - EHAction::Filter(_) if actions as i32 & uw::_UA_FORCE_UNWIND as i32 != 0 => uw::_URC_CONTINUE_UNWIND, - EHAction::Cleanup(lpad) | EHAction::Catch(lpad) | EHAction::Filter(lpad) => { - uw::_Unwind_SetGR( - context, - UNWIND_DATA_REG.0, - exception_object.cast(), - ); - uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, core::ptr::null()); - uw::_Unwind_SetIP(context, lpad); - uw::_URC_INSTALL_CONTEXT - } - EHAction::Terminate => uw::_URC_FATAL_PHASE2_ERROR, - } - } - } - - cfg_if::cfg_if! { - if #[cfg(all(windows, any(target_arch = "aarch64", target_arch = "x86_64"), target_env = "gnu"))] { - // On x86_64 MinGW targets, the unwinding mechanism is SEH however the unwind - // handler data (aka LSDA) uses GCC-compatible encoding. - #[lang = "eh_personality"] - #[allow(nonstandard_style)] - unsafe extern "C" fn rust_eh_personality( - exceptionRecord: *mut uw::EXCEPTION_RECORD, - establisherFrame: uw::LPVOID, - contextRecord: *mut uw::CONTEXT, - dispatcherContext: *mut uw::DISPATCHER_CONTEXT, - ) -> uw::EXCEPTION_DISPOSITION { - uw::_GCC_specific_handler( - exceptionRecord, - establisherFrame, - contextRecord, - dispatcherContext, - rust_eh_personality_impl, - ) - } - } else { - // The personality routine for most of our targets. - #[lang = "eh_personality"] - unsafe extern "C" fn rust_eh_personality( - version: c_int, - actions: uw::_Unwind_Action, - exception_class: uw::_Unwind_Exception_Class, - exception_object: *mut uw::_Unwind_Exception, - context: *mut uw::_Unwind_Context, - ) -> uw::_Unwind_Reason_Code { - rust_eh_personality_impl( - version, - actions, - exception_class, - exception_object, - context, - ) - } - } - } - } -} - -unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> Result<EHAction, ()> { - let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8; - let mut ip_before_instr: c_int = 0; - let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr); - let eh_context = EHContext { - // The return address points 1 byte past the call instruction, - // which could be in the next IP range in LSDA range table. - // - // `ip = -1` has special meaning, so use wrapping sub to allow for that - ip: if ip_before_instr != 0 { ip } else { ip.wrapping_sub(1) }, - func_start: uw::_Unwind_GetRegionStart(context), - get_text_start: &|| uw::_Unwind_GetTextRelBase(context), - get_data_start: &|| uw::_Unwind_GetDataRelBase(context), - }; - eh::find_eh_action(lsda, &eh_context) -} diff --git a/library/std/src/sys/pal/personality/mod.rs b/library/std/src/sys/pal/personality/mod.rs deleted file mode 100644 index d37b8ce6346..00000000000 --- a/library/std/src/sys/pal/personality/mod.rs +++ /dev/null @@ -1,47 +0,0 @@ -//! This module contains the implementation of the `eh_personality` lang item. -//! -//! The actual implementation is heavily dependent on the target since Rust -//! tries to use the native stack unwinding mechanism whenever possible. -//! -//! This personality function is still required with `-C panic=abort` because -//! it is used to catch foreign exceptions from `extern "C-unwind"` and turn -//! them into aborts. -//! -//! Additionally, ARM EHABI uses the personality function when generating -//! backtraces. - -mod dwarf; - -#[cfg(not(any(test, doctest)))] -cfg_if::cfg_if! { - if #[cfg(target_os = "emscripten")] { - mod emcc; - } else if #[cfg(target_env = "msvc")] { - // This is required by the compiler to exist (e.g., it's a lang item), - // but it's never actually called by the compiler because - // _CxxFrameHandler3 is the personality function that is always used. - // Hence this is just an aborting stub. - #[lang = "eh_personality"] - fn rust_eh_personality() { - core::intrinsics::abort() - } - } else if #[cfg(any( - all(target_family = "windows", target_env = "gnu"), - target_os = "psp", - target_os = "xous", - target_os = "solid_asp3", - all(target_family = "unix", not(target_os = "espidf"), not(target_os = "l4re")), - all(target_vendor = "fortanix", target_env = "sgx"), - ))] { - mod gcc; - } else { - // Targets that don't support unwinding. - // - family=wasm - // - os=none ("bare metal" targets) - // - os=uefi - // - os=espidf - // - os=hermit - // - nvptx64-nvidia-cuda - // - arch=avr - } -} |
