Skip to content

Commit

Permalink
Work on panic rt for rust stdlib
Browse files Browse the repository at this point in the history
  • Loading branch information
chorman0773 committed Jun 24, 2023
1 parent 4f1a3e5 commit e433d92
Show file tree
Hide file tree
Showing 22 changed files with 455 additions and 46 deletions.
6 changes: 3 additions & 3 deletions lcrust/libraries/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ hostedtargs:=@hostedtargs@

target:= @target@

LIBRARIES = core alloc
LIBRARIES = core alloc lcrust_panic

ifneq (,$(findstring $(target),$(hostedtargs)))
LIBRARIES += std proc_macro
Expand All @@ -19,6 +19,6 @@ all:
stamp: $(foreach lib,$(LIBRARIES),lib$(lib))
touch stamp

lib$(lib): lib$(lib)/stamp


libcore:
+$(MAKE)
78 changes: 78 additions & 0 deletions lcrust/libraries/configure.ac
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
AC_INIT

AC_CONFIG_MACRO_DIRS([../m4/])

AC_PROG_CC

AC_PROG_INSTALL
AC_PROG_LN_S

AC_CANONICAL_HOST

LCRUST_PROG_RUSTC
LCRUST_RUSTC_VERSION

AC_ARG_VAR([LCCC_])

if test x$rustc_is_lccc != xyes
then
AC_MSG_ERROR([Cannot compile lcrust libraries except on lccc])
fi

AC_ARG_WITH([abi-version],[Override the default abi version],[
case "$enableval" in
yes )
abi_version=0
;;
no )
abi_version=no
;;
* )
if test "$enableval" -le 0
then
abi_version="$enableval"
else
AC_MSG_ERROR([Invalid abi-version $enableval. abi-version must be less than or equal to the current version, 0])
fi
;;
],[
abi_version=0
])

if x$abi_version != xno
then
RUSTFLAGS="$RUSTFLAGS -Z build-abi=$abi_version --cfg abi_version=\"$abi_version\""
fi

AC_ARG_ENABLE([randomize-danging],[Randomize the output of NonNull::dangling()],[
if x$enableval \= xyes
then
RUSTFLAGS="$RUSTFLAGS --cfg feature=\"randomize-dangling\""
fi
])

AC_ARG_ENABLE([randomize-layout],[Randomize struct layout by passing -Z repr-rust-layout=randomize to rustc],[
if x$enableval \= xyes
then
RUSTFLAGS="$RUSTFLAGS -Z repr-rust-layout=randomize"
fi
])

AC_ARG_WITH([rustlibdir],[Sets the directory to install rust binaries into],[
case "$enableval" in
[\\/]* )
rustlibdir="$enableval"
;;
yes | no )
AC_MSG_ERROR([--with-rustlibdir must specify an argument])
;;
* )
rustlibdir="$${libdir}/$enableval"
;;
],[
rustlibdir='${libdir}/rust/lcrust'
])

AC_SUBST([rustlibdir abi_version])

AC_CONFIG_FILES(Makefile)
13 changes: 13 additions & 0 deletions lcrust/libraries/lcrust_panic/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "lcrust_panic"
version = "0.1.0"
authors = ["Connor Horman <chorman64@gmail.com>"]
edition = "2018"
license = "BSD-2-Clause-Patent"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

[features]
unwind=[]
16 changes: 16 additions & 0 deletions lcrust/libraries/lcrust_panic/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#![no_std]
#![feature(lcrust_attributes, thread_local)]
#![lcrust::mangle_as = "std"]

extern crate alloc;

pub(crate) mod rt;

#[cfg(feature="unwind")]
pub mod panic {
pub mod foreign;
}

pub mod panicking {
pub mod lcrust;
}
9 changes: 9 additions & 0 deletions lcrust/libraries/lcrust_panic/src/panic/foreign.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use crate:rt::panic::ForeignExceptionType;

pub struct ForeignPanic(pub(crate) *mut ForeignExceptionType);

impl Drop for ForeignPanic{
fn drop(&mut self){
unsafe{crate::panicking::lcrust::dispose_foreign_exception(self.0)}
}
}
34 changes: 34 additions & 0 deletions lcrust/libraries/lcrust_panic/src/panicking/lcrust.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

use core::panic::Location;
use core::fmt::FormatArgs;

extern "lcrust-v0"{
#[link_name = "_ZNSt9panicking5lcrust7abort_fmtERK_ZNSt5panic8LocationE_ZNSt3fmt10FormatArgsE"]
#[lcrust::unsafe_import]
pub fn abort_fmt(panic_origin: &Location, args: FormatArgs) -> !;
#[link_name = "_ZNSt9panicking5lcrust14abort_no_messagev"]
#[]
pub fn abort_no_message() -> !;
}

struct PrintOrDefault<'a>(Option<&'a str>, &'a str);

impl core::fmt::Display for PrintOrDefault<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
if let Some(st) = self.0 {
f.write_str(st)
} else {
f.write_str(self.1)
}
}
}

pub extern "lcrust-v0" fn abort(panic_origin: &Location, msg: Option<&str>) -> !{

// SAFETY: std::panicking::lcrust::abort_fmt is a safe function
unsafe{abort_fmt(panic_origin, format_args!("{}",PrintOrDefault(msg,"Explicit Panic")))}
}


#[cfg(feature="unwind")]
include!("unwind.rs");
139 changes: 139 additions & 0 deletions lcrust/libraries/lcrust_panic/src/panicking/unwind.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@

pub use crate::rt::unwind::sys::{ForeignExceptionType,PanicUnwindInfo};

use crate::rt::unwind::sys::{__dispose_foreign_exception,__begin_unwind};

use core::cell::Cell;
use core::any::Any;

#[thread_local]
static PANIC_COUNT: Cell<usize> = Cell::new(0);


#[cfg_attr(define_lang_items, lang = "lcrust_increment_panic_count_symbol")]
pub unsafe fn increment_panic_count() -> usize{
PANIC_COUNT.replace(PANIC_COUNT.get().add_unchecked(1))
}

#[cfg_attr(define_lang_items, lang = "lcrust_decrement_panic_count_symbol")]
pub unsafe fn decrement_panic_count() -> usize{
PANIC_COUNT.replace(PANIC_COUNT.get().sub_unchecked(1))
}

#[cfg_attr(define_lang_items, lang = "lcrust_panic_count_symbol")]
pub fn panic_count() -> usize{
PANIC_COUNT.get()
}

#[cfg_attr(define_lang_items, lang = "lcrust_dispose_foreign_exception_symbol")]
pub unsafe fn dispose_foreign_exception(p: *mut ForeignExceptionType){
__dispose_foreign_exception(p)
}

#[track_caller]
#[cfg_attr(define_lang_items, lang = "lcrust_allocate_exception_symbol")]
pub fn __allocate_exception(obj_layout: Layout) -> *mut PanicUnwindInfo {
let base_layout = Layout::of::<PanicUnwindInfo>();

let (layout, _) = base_layout.extend(obj_layout).unwrap_or_else(|| {
abort_fmt(
Location::caller(),
format_args!(
"Allocation Failure in panic runtime - object with size {} cannot be panicked with",
obj_layout.size()
),
)
});

let layout = layout.pad_to_align();

// SAFETY: `layout` is non-zero size because it as at least `base_layout`
let ptr = unsafe { alloc::alloc::alloc(layout) };

if ptr.is_null() {
abort_fmt(Location::caller(), format_args!("Allocation Failure in panic runtime - global allocator returned OOM for allocation of size {}",layout.size()));
}

ptr.cast()
}

#[repr(lcrust_v0)]
struct AnyVtable {
size: usize,
align: usize,
destructor: Option<unsafe extern "lcrust-v0" fn(*mut ())>,
reserved_dealloc: Option<unsafe extern "lcrust-v0" fn(*mut ())>,
typeid: unsafe extern "lcrust-v0" fn(*mut ()) -> core::any::TypeId,
}

#[track_caller]
#[cfg_attr(define_lang_items, lang = "lcrust_deallocate_excepton_symbol")]
pub unsafe fn __deallocate_exception(obj: *mut PanicUnwindInfo) {
let base_layout = Layout::of::<PanicUnwindInfo>();

let vtable: core::ptr::DynMetadata<dyn Any> = (*obj).vtable;

let vtable_access = core::mem::transmute::<&'static AnyVtable>(vtable);

let obj_layout = Layout::from_size_align_unchecked(vtable_access.size, vtable_access.align);

let layout = base_layout
.extend(obj_layout)
.unwrap_unchecked()
.0
.pad_to_align();

alloc::alloc::dealloc(obj.cast, layout)
}

#[track_caller]
#[cfg_attr(define_lang_items, lang = "lcrust_begin_catch_native_symbol")]
pub unsafe fn begin_catch_native(p: *mut PanicUnwindInfo) -> *mut dyn Any{
let vtable: core::ptr::DynMetadata<dyn Any> = (*obj).vtable;

let vtable_access = core::mem::transmute::<&'static AnyVtable>(vtable);

let obj_layout = Layout::from_size_align_unchecked(vtable_access.size, vtable_access.align);

let objptr = unsafe{p.cast::<u8>().add(core;:mem::size_of::<PanicUnwindInfo>())
.add((*obj).tail_size)
.map_addr(|a| (a + vtable_access.align.sub_unchecked()) & !vtable_access.align)};

let ptr = if obj_layout.size()==0{
obj_layout.dangling().as_mut()
}else{
unsafe{alloc::alloc::alloc(obj_layout)}
};

if ptr.is_null(){
abort_fmt(Location::caller(),format_args!("Failed to allocate returned exception with layout: size={}, align={}",vtable_access.size,table_access.align))
}

decrement_panic_count();

// Safety: `ptr` is freshly allocated

unsafe{core::ptr::copy_nonoverlapping(objptr,ptr,vtable_access.size)};

__deallocate_exception(p);

core::ptr::from_raw_parts(ptr.cast(),vtable)

}

#[cold]
#[track_caller]
#[inline(never)]
#[cfg_attr(define_lang_items, lang = "lcrust_begin_unwind_symbol")]
pub unsafe fn begin_unwind(o: *mut PanicUnwindInfo) -> !{
__begin_unwind(o)
}


#[cfg_attr(define_lang_items, lang = "lcrust_catch_unwind_landing_pad_symbol")]
pub unsafe fn catch_unwind_landing_pad(_: *mut dyn FnOnce()->*mut !, p: *mut ForeignExceptionType) -> Result<*mut !,Box<dyn Any>>{
Err(__catch_unwind_landing_pad(p))
}



6 changes: 6 additions & 0 deletions lcrust/libraries/lcrust_panic/src/rt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#[cfg(feature = "unwind")]
pub mod unwind {
mod sys;

pub use sys::*;
}
Loading

0 comments on commit e433d92

Please sign in to comment.