Implement basic panic handler
This commit is contained in:
parent
af031eb4b1
commit
6e74064c7f
@ -22,6 +22,7 @@ personality = []
|
||||
personality-dummy = []
|
||||
print = ["libc"]
|
||||
panic = ["alloc"]
|
||||
panic-handler = ["print", "panic"]
|
||||
system-alloc = []
|
||||
default = ["dwarf-expr", "hide-trace", "fde-phdr", "fde-registry"]
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
feature(lang_items)
|
||||
)]
|
||||
#![cfg_attr(feature = "panic", feature(core_intrinsics))]
|
||||
#![cfg_attr(feature = "panic-handler", feature(thread_local))]
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![warn(unsafe_op_in_unsafe_fn)]
|
||||
#![no_std]
|
||||
@ -31,5 +32,8 @@ mod personality_dummy;
|
||||
#[cfg(feature = "panic")]
|
||||
pub mod panic;
|
||||
|
||||
#[cfg(feature = "panic-handler")]
|
||||
pub mod panic_handler;
|
||||
|
||||
#[cfg(feature = "system-alloc")]
|
||||
mod system_alloc;
|
||||
|
24
src/panic.rs
24
src/panic.rs
@ -3,6 +3,8 @@ use core::any::Any;
|
||||
use core::mem::ManuallyDrop;
|
||||
|
||||
use crate::abi::*;
|
||||
#[cfg(feature = "panic-handler")]
|
||||
pub use crate::panic_handler::*;
|
||||
|
||||
#[repr(C)]
|
||||
struct Exception {
|
||||
@ -20,7 +22,14 @@ pub fn begin_panic(payload: Box<dyn Any + Send>) -> UnwindReasonCode {
|
||||
unsafe {
|
||||
let _ = Box::from_raw(exception as *mut Exception);
|
||||
}
|
||||
core::intrinsics::abort();
|
||||
#[cfg(feature = "panic-handler")]
|
||||
{
|
||||
drop_panic();
|
||||
}
|
||||
#[cfg(not(feature = "panic-handler"))]
|
||||
{
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
}
|
||||
|
||||
let mut unwind_ex = UnwindException::new();
|
||||
@ -38,7 +47,18 @@ unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send + 'static> {
|
||||
let exception = payload as *mut UnwindException;
|
||||
if unsafe { (*exception).exception_class } != RUST_EXCEPTION_CLASS {
|
||||
unsafe { _Unwind_DeleteException(exception) };
|
||||
core::intrinsics::abort();
|
||||
#[cfg(feature = "panic-handler")]
|
||||
{
|
||||
foreign_exception();
|
||||
}
|
||||
#[cfg(not(feature = "panic-handler"))]
|
||||
{
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "panic-handler")]
|
||||
{
|
||||
panic_caught();
|
||||
}
|
||||
let unwind_ex = unsafe { Box::from_raw(exception as *mut Exception) };
|
||||
unwind_ex.payload
|
||||
|
48
src/panic_handler.rs
Normal file
48
src/panic_handler.rs
Normal file
@ -0,0 +1,48 @@
|
||||
use crate::print::*;
|
||||
use alloc::boxed::Box;
|
||||
use core::any::Any;
|
||||
use core::cell::Cell;
|
||||
use core::panic::{Location, PanicInfo};
|
||||
|
||||
#[thread_local]
|
||||
static PANIC_COUNT: Cell<usize> = Cell::new(0);
|
||||
|
||||
#[link(name = "c")]
|
||||
extern "C" {}
|
||||
|
||||
pub(crate) fn drop_panic() {
|
||||
eprintln!("Rust panics must be rethrown");
|
||||
}
|
||||
|
||||
pub(crate) fn foreign_exception() {
|
||||
eprintln!("Rust cannot catch foreign exceptions");
|
||||
}
|
||||
|
||||
pub(crate) fn panic_caught() {
|
||||
PANIC_COUNT.set(0);
|
||||
}
|
||||
|
||||
fn do_panic(msg: Box<dyn Any + Send>) -> ! {
|
||||
if PANIC_COUNT.get() >= 1 {
|
||||
eprintln!("thread panicked while processing panic. aborting.");
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
PANIC_COUNT.set(1);
|
||||
let code = crate::panic::begin_panic(Box::new(msg));
|
||||
eprintln!("failed to initiate panic, error {}", code.0);
|
||||
core::intrinsics::abort();
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo<'_>) -> ! {
|
||||
eprintln!("{}", info);
|
||||
|
||||
struct NoPayload;
|
||||
do_panic(Box::new(NoPayload))
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn panic_any<M: 'static + Any + Send>(msg: M) -> ! {
|
||||
eprintln!("panicked at {}", Location::caller());
|
||||
do_panic(Box::new(msg))
|
||||
}
|
Loading…
Reference in New Issue
Block a user