diff --git a/kernel-1100/src/lib.rs b/kernel-1100/src/lib.rs index 444e5c3..b3e5da3 100644 --- a/kernel-1100/src/lib.rs +++ b/kernel-1100/src/lib.rs @@ -12,7 +12,7 @@ use core::ffi::{c_char, c_int}; use okf::malloc::MallocFlags; use okf::socket::SockAddr; use okf::uio::UioSeg; -use okf::{offset, MappedKernel, StaticMut}; +use okf::{offset, panic_handler, MappedKernel, StaticMut}; mod file; mod lock; @@ -121,3 +121,5 @@ impl okf::Kernel for Kernel { unsafe impl Send for Kernel {} unsafe impl Sync for Kernel {} + +panic_handler!(0x1987C0); diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 7dca902..ff962ac 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -3,6 +3,7 @@ use syn::{parse_macro_input, Error, ItemStruct, LitInt, TraitItem}; mod derive; mod offset; +mod panic_handler; #[proc_macro_derive(MappedKernel)] pub fn derive_mapped_kernel(item: TokenStream) -> TokenStream { @@ -22,3 +23,12 @@ pub fn offset(args: TokenStream, item: TokenStream) -> TokenStream { .unwrap_or_else(Error::into_compile_error) .into() } + +#[proc_macro] +pub fn panic_handler(args: TokenStream) -> TokenStream { + let args = parse_macro_input!(args as LitInt); + + self::panic_handler::transform(args) + .unwrap_or_else(Error::into_compile_error) + .into() +} diff --git a/macros/src/panic_handler.rs b/macros/src/panic_handler.rs new file mode 100644 index 0000000..a444924 --- /dev/null +++ b/macros/src/panic_handler.rs @@ -0,0 +1,53 @@ +use proc_macro2::TokenStream; +use quote::quote; +use syn::LitInt; + +pub fn transform(arg: LitInt) -> syn::Result { + let off: usize = arg.base10_parse()?; + + Ok(quote! { + #[cfg(feature = "panic-handler")] + struct PanicMsg { + buf: [u8; L], + pos: usize, + } + + #[cfg(feature = "panic-handler")] + impl core::fmt::Write for PanicMsg { + fn write_str(&mut self, s: &str) -> core::fmt::Result { + // This method need to be careful not to cause any panic so we don't end up nested panic. + let str = s.as_bytes(); + let end = core::cmp::min(self.pos.saturating_add(str.len()), self.buf.len() - 1); + let buf = unsafe { self.buf.get_unchecked_mut(self.pos..end) }; + + buf.copy_from_slice(unsafe { str.get_unchecked(..buf.len()) }); + self.pos = end; + + Ok(()) + } + } + + #[cfg(feature = "panic-handler")] + #[panic_handler] + fn panic(i: &core::panic::PanicInfo) -> ! { + use core::fmt::Write; + use okf::MappedKernel; + + // Write panic message. + let mut m = PanicMsg { + buf: [0; 1024], + pos: 0, + }; + + write!(m, "{i}").unwrap(); + + // Invoke panic function. + let k = Kernel::default(); + let f = unsafe { k.addr().add(#off) }; + let f: unsafe extern "C" fn(fmt: *const core::ffi::c_char, ...) -> ! = + unsafe { core::mem::transmute(f) }; + + unsafe { f(c"%s".as_ptr(), m.buf.as_ptr()) }; + } + }) +}