From f9612898ab6b811bb3eece180f4b61b53d7920a1 Mon Sep 17 00:00:00 2001 From: matejcik Date: Wed, 24 Aug 2022 17:03:55 +0200 Subject: [PATCH] feat(core/rust): improved error reporting --- core/embed/rust/src/lib.rs | 8 +- core/embed/rust/src/trezorhal/common.rs | 100 ----------------- core/embed/rust/src/trezorhal/fatal_error.rs | 108 +++++++++++++++++++ core/embed/rust/src/trezorhal/mod.rs | 2 +- 4 files changed, 114 insertions(+), 104 deletions(-) delete mode 100644 core/embed/rust/src/trezorhal/common.rs create mode 100644 core/embed/rust/src/trezorhal/fatal_error.rs diff --git a/core/embed/rust/src/lib.rs b/core/embed/rust/src/lib.rs index 0a48f279c9..b403a2fd7c 100644 --- a/core/embed/rust/src/lib.rs +++ b/core/embed/rust/src/lib.rs @@ -35,10 +35,12 @@ pub mod ui; fn panic_debug(panic_info: &core::panic::PanicInfo) -> ! { // Filling at least the file and line information, if available. // TODO: find out how to display message from panic_info.message() + if let Some(location) = panic_info.location() { - trezorhal::common::__fatal_error("", "rs", location.file(), location.line(), ""); + let file = location.file(); + trezorhal::fatal_error::__fatal_error("", "rs", file, location.line(), ""); } else { - trezorhal::common::__fatal_error("", "rs", "", 0, ""); + trezorhal::fatal_error::__fatal_error("", "rs", "", 0, ""); } } @@ -56,7 +58,7 @@ fn panic(_info: &core::panic::PanicInfo) -> ! { // raises a Hard Fault on hardware. // // Otherwise, use `unwrap!` macro from trezorhal. - trezorhal::common::__fatal_error("", "rs", "", 0, ""); + fatal_error!("", "rs"); } #[cfg(not(target_arch = "arm"))] diff --git a/core/embed/rust/src/trezorhal/common.rs b/core/embed/rust/src/trezorhal/common.rs deleted file mode 100644 index fcd183f892..0000000000 --- a/core/embed/rust/src/trezorhal/common.rs +++ /dev/null @@ -1,100 +0,0 @@ -mod ffi { - extern "C" { - // trezorhal/common.c - pub fn __fatal_error( - expr: *const cty::c_char, - msg: *const cty::c_char, - file: *const cty::c_char, - line: i32, - func: *const cty::c_char, - ) -> !; - } -} - -pub fn __fatal_error(expr: &str, msg: &str, file: &str, line: u32, func: &str) -> ! { - const MAX_LEN: usize = 50 + 1; // Leave space for the null terminator. - - fn as_cstr_buf(s: &str) -> [cty::c_char; MAX_LEN] { - let mut buf = [0 as cty::c_char; MAX_LEN]; - for (i, c) in s.as_bytes().iter().enumerate() { - if i >= MAX_LEN { - break; - } - buf[i] = *c as cty::c_char; - } - buf[MAX_LEN - 1] = 0; - buf - } - - let expr_buf = as_cstr_buf(expr); - let msg_buf = as_cstr_buf(msg); - let file_buf = as_cstr_buf(file); - let func_buf = as_cstr_buf(func); - - unsafe { - ffi::__fatal_error( - expr_buf.as_ptr(), - msg_buf.as_ptr(), - file_buf.as_ptr(), - line as i32, - func_buf.as_ptr(), - ); - } -} - -pub trait UnwrapOrFatalError { - fn unwrap_or_fatal_error(self, expr: &str, msg: &str, file: &str, line: u32, func: &str) -> T; -} - -impl UnwrapOrFatalError for Option { - fn unwrap_or_fatal_error(self, expr: &str, msg: &str, file: &str, line: u32, func: &str) -> T { - match self { - Some(x) => x, - None => __fatal_error(expr, msg, file, line, func), - } - } -} - -impl UnwrapOrFatalError for Result { - fn unwrap_or_fatal_error(self, expr: &str, msg: &str, file: &str, line: u32, func: &str) -> T { - match self { - Ok(x) => x, - Err(_) => __fatal_error(expr, msg, file, line, func), - } - } -} - -macro_rules! function_name { - () => {{ - fn f() {} - fn type_name_of(_: T) -> &'static str { - core::any::type_name::() - } - let name = type_name_of(f); - name.get(..name.len() - 3).unwrap_or("") - }}; -} - -macro_rules! unwrap { - ($e:expr, $msg:expr) => {{ - use crate::trezorhal::common::UnwrapOrFatalError; - $e.unwrap_or_fatal_error("unwrap failed", $msg, file!(), line!(), function_name!()) - }}; - ($expr:expr) => { - unwrap!($expr, "") - }; -} - -macro_rules! ensure { - ($what:expr, $error:expr) => { - if !($what) { - fatal_error!(stringify!($what), $error); - } - }; -} - -macro_rules! fatal_error { - ($expr:expr, $msg:expr) => {{ - crate::trezorhal::common::__fatal_error($expr, $msg, file!(), line!(), function_name!()); - }}; -} diff --git a/core/embed/rust/src/trezorhal/fatal_error.rs b/core/embed/rust/src/trezorhal/fatal_error.rs new file mode 100644 index 0000000000..551462b3bf --- /dev/null +++ b/core/embed/rust/src/trezorhal/fatal_error.rs @@ -0,0 +1,108 @@ +mod ffi { + extern "C" { + // trezorhal/common.c + pub fn shutdown() -> !; + } +} + +use crate::ui::screens::screen_fatal_error; +#[cfg(not(feature = "bootloader"))] +use heapless::String; + +#[cfg(not(feature = "bootloader"))] +use crate::ui::util::u32_to_str; + +fn shutdown() -> ! { + unsafe { ffi::shutdown() } +} + +#[cfg(feature = "bootloader")] +pub fn __fatal_error(_expr: &str, _msg: &str, _file: &str, _line: u32, _func: &str) -> ! { + screen_fatal_error(Some("BL.rs"), "BL.rs"); + shutdown() +} + +#[cfg(not(feature = "bootloader"))] +pub fn __fatal_error(_expr: &str, msg: &str, file: &str, line: u32, _func: &str) -> ! { + let mut buf: String<256> = String::new(); + let _ = buf.push_str(file); // Nothing we can do if this fails + let _ = buf.push_str(": "); + + let mut line_buf = [0u8; 10]; + if let Some(text) = u32_to_str(line, &mut line_buf) { + let _ = buf.push_str(text); + } + + screen_fatal_error(Some(msg), buf.as_str()); + shutdown() +} + +pub trait UnwrapOrFatalError { + fn unwrap_or_fatal_error(self, expr: &str, msg: &str, file: &str, line: u32, func: &str) -> T; +} + +impl UnwrapOrFatalError for Option { + fn unwrap_or_fatal_error(self, expr: &str, msg: &str, file: &str, line: u32, func: &str) -> T { + match self { + Some(x) => x, + None => __fatal_error(expr, msg, file, line, func), + } + } +} + +impl UnwrapOrFatalError for Result { + fn unwrap_or_fatal_error(self, expr: &str, msg: &str, file: &str, line: u32, func: &str) -> T { + match self { + Ok(x) => x, + Err(_) => __fatal_error(expr, msg, file, line, func), + } + } +} + +macro_rules! function_name { + () => {{ + #[cfg(not(feature = "bootloader"))] + { + fn f() {} + fn type_name_of(_: T) -> &'static str { + core::any::type_name::() + } + let name = type_name_of(f); + name.get(..name.len() - 3).unwrap_or("") + } + #[cfg(feature = "bootloader")] + { + "" + } + }}; +} + +macro_rules! unwrap { + ($e:expr, $msg:expr) => {{ + use crate::trezorhal::fatal_error::UnwrapOrFatalError; + $e.unwrap_or_fatal_error(stringify!($e), $msg, file!(), line!(), function_name!()) + }}; + ($expr:expr) => { + unwrap!($expr, "unwrap failed") + }; +} + +macro_rules! ensure { + ($what:expr, $error:expr) => { + if !($what) { + fatal_error!(stringify!($what), $error); + } + }; +} + +macro_rules! fatal_error { + ($expr:expr, $msg:expr) => {{ + crate::trezorhal::fatal_error::__fatal_error( + stringify!($expr), + $msg, + file!(), + line!(), + function_name!(), + ); + }}; +} diff --git a/core/embed/rust/src/trezorhal/mod.rs b/core/embed/rust/src/trezorhal/mod.rs index a2b60ae599..3a2e7002f7 100644 --- a/core/embed/rust/src/trezorhal/mod.rs +++ b/core/embed/rust/src/trezorhal/mod.rs @@ -1,7 +1,7 @@ pub mod bip39; #[macro_use] #[allow(unused_macros)] -pub mod common; +pub mod fatal_error; #[cfg(feature = "ui")] pub mod display; #[cfg(feature = "dma2d")]