sel4_panicking_env/
lib.rs
1#![no_std]
8#![feature(linkage)]
9
10use core::fmt;
11use core::panic::Location;
12use core::str;
13
14extern "Rust" {
15 fn __sel4_panicking_env__debug_put_char(c: u8);
16 fn __sel4_panicking_env__abort_hook(info: Option<&AbortInfo>);
17 fn __sel4_panicking_env__abort_trap() -> !;
18}
19
20#[macro_export]
30macro_rules! register_debug_put_char {
31 ($(#[$attrs:meta])* $path:path) => {
32 #[allow(non_snake_case)]
33 const _: () = {
34 $(#[$attrs])*
35 #[no_mangle]
36 fn __sel4_panicking_env__debug_put_char(c: u8) {
37 const F: fn(u8) = $path;
38 F(c)
39 }
40 };
41 };
42}
43
44#[macro_export]
54macro_rules! register_abort_hook {
55 ($(#[$attrs:meta])* $path:path) => {
56 #[allow(non_snake_case)]
57 const _: () = {
58 $(#[$attrs])*
59 #[no_mangle]
60 fn __sel4_panicking_env__abort_hook(info: ::core::option::Option<&$crate::AbortInfo>) {
61 const F: fn(::core::option::Option<&$crate::AbortInfo>) = $path;
62 F(info)
63 }
64 };
65 };
66}
67
68register_abort_hook!(
69 #[linkage = "weak"]
70 default_abort_hook
71);
72
73fn default_abort_hook(info: Option<&AbortInfo>) {
74 match info {
75 Some(info) => debug_println!("{}", info),
76 None => debug_println!("(aborted)"),
77 }
78}
79
80#[macro_export]
90macro_rules! register_abort_trap {
91 ($(#[$attrs:meta])* $path:path) => {
92 #[allow(non_snake_case)]
93 const _: () = {
94 $(#[$attrs])*
95 #[no_mangle]
96 fn __sel4_panicking_env__abort_trap() -> ! {
97 const F: fn() -> ! = $path;
98 F()
99 }
100 };
101 };
102}
103
104pub fn debug_put_char(c: u8) {
118 unsafe { __sel4_panicking_env__debug_put_char(c) }
119}
120
121struct DebugWrite;
122
123impl fmt::Write for DebugWrite {
124 fn write_str(&mut self, s: &str) -> fmt::Result {
125 for &c in s.as_bytes() {
126 debug_put_char(c)
127 }
128 Ok(())
129 }
130}
131
132#[doc(hidden)]
133pub fn __debug_print_macro_helper(args: fmt::Arguments) {
134 fmt::write(&mut DebugWrite, args).unwrap_or_else(|err| {
135 let _ = fmt::write(&mut DebugWrite, format_args!("({err})"));
137 })
138}
139
140#[macro_export]
142macro_rules! debug_print {
143 ($($arg:tt)*) => ($crate::__debug_print_macro_helper(format_args!($($arg)*)));
144}
145
146#[macro_export]
148macro_rules! debug_println {
149 () => ($crate::debug_println!(""));
150 ($($arg:tt)*) => ($crate::debug_print!("{}\n", format_args!($($arg)*)));
151}
152
153pub struct AbortInfo<'a> {
157 message: Option<&'a fmt::Arguments<'a>>,
158 location: Option<&'a Location<'a>>,
159}
160
161impl AbortInfo<'_> {
162 pub fn message(&self) -> Option<&fmt::Arguments> {
164 self.message
165 }
166
167 pub fn location(&self) -> Option<&Location> {
169 self.location
170 }
171}
172
173impl fmt::Display for AbortInfo<'_> {
174 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
175 f.write_str("aborted at ")?;
176 if let Some(location) = self.location {
177 location.fmt(f)?;
178 } else {
179 f.write_str("unknown location")?;
180 }
181 if let Some(message) = self.message {
182 f.write_str(":\n")?;
183 f.write_fmt(*message)?;
184 }
185 Ok(())
186 }
187}
188
189fn abort(info: Option<&AbortInfo>) -> ! {
190 unsafe {
191 __sel4_panicking_env__abort_hook(info);
192 __sel4_panicking_env__abort_trap()
193 }
194}
195
196pub fn abort_without_info() -> ! {
200 abort(None)
201}
202
203#[doc(hidden)]
204#[track_caller]
205pub fn __abort_macro_helper(message: Option<fmt::Arguments>) -> ! {
206 abort(Some(&AbortInfo {
207 message: message.as_ref(),
208 location: Some(Location::caller()),
209 }))
210}
211
212#[macro_export]
238macro_rules! abort {
239 () => ($crate::__abort_macro_helper(::core::option::Option::None));
240 ($($arg:tt)*) => ($crate::__abort_macro_helper(::core::option::Option::Some(format_args!($($arg)*))));
241}