sel4_panicking_env/
lib.rs1#![no_std]
8#![feature(linkage)]
9
10use core::fmt;
11use core::panic::Location;
12use core::str;
13
14unsafe extern "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 #[unsafe(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]
56macro_rules! register_abort_hook {
57 ($(#[$attrs:meta])* $path:path) => {
58 #[allow(non_snake_case)]
59 const _: () = {
60 $(#[$attrs])*
61 #[unsafe(no_mangle)]
62 fn __sel4_panicking_env__abort_hook(info: ::core::option::Option<&$crate::AbortInfo>) {
63 const F: fn(::core::option::Option<&$crate::AbortInfo>) = $path;
64 F(info)
65 }
66 };
67 };
68}
69
70register_abort_hook!(
71 #[linkage = "weak"]
72 default_abort_hook
73);
74
75fn default_abort_hook(info: Option<&AbortInfo>) {
76 match info {
77 Some(info) => debug_println!("{}", info),
78 None => debug_println!("(aborted)"),
79 }
80}
81
82#[macro_export]
92macro_rules! register_abort_trap {
93 ($(#[$attrs:meta])* $path:path) => {
94 #[allow(non_snake_case)]
95 const _: () = {
96 $(#[$attrs])*
97 #[unsafe(no_mangle)]
98 fn __sel4_panicking_env__abort_trap() -> ! {
99 const F: fn() -> ! = $path;
100 F()
101 }
102 };
103 };
104}
105
106pub fn debug_put_char(c: u8) {
120 unsafe { __sel4_panicking_env__debug_put_char(c) }
121}
122
123struct DebugWrite;
124
125impl fmt::Write for DebugWrite {
126 fn write_str(&mut self, s: &str) -> fmt::Result {
127 for &c in s.as_bytes() {
128 debug_put_char(c)
129 }
130 Ok(())
131 }
132}
133
134#[doc(hidden)]
135pub fn __debug_print_macro_helper(args: fmt::Arguments) {
136 fmt::write(&mut DebugWrite, args).unwrap_or_else(|err| {
137 let _ = fmt::write(&mut DebugWrite, format_args!("({err})"));
139 })
140}
141
142#[macro_export]
144macro_rules! debug_print {
145 ($($arg:tt)*) => ($crate::__debug_print_macro_helper(format_args!($($arg)*)));
146}
147
148#[macro_export]
150macro_rules! debug_println {
151 () => ($crate::debug_println!(""));
152 ($($arg:tt)*) => ($crate::debug_print!("{}\n", format_args!($($arg)*)));
153}
154
155pub struct AbortInfo<'a> {
159 message: Option<&'a fmt::Arguments<'a>>,
160 location: Option<&'a Location<'a>>,
161}
162
163impl AbortInfo<'_> {
164 pub fn message(&self) -> Option<&fmt::Arguments<'_>> {
166 self.message
167 }
168
169 pub fn location(&self) -> Option<&Location<'_>> {
171 self.location
172 }
173}
174
175impl fmt::Display for AbortInfo<'_> {
176 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
177 f.write_str("aborted at ")?;
178 if let Some(location) = self.location {
179 location.fmt(f)?;
180 } else {
181 f.write_str("unknown location")?;
182 }
183 if let Some(message) = self.message {
184 f.write_str(":\n")?;
185 f.write_fmt(*message)?;
186 }
187 Ok(())
188 }
189}
190
191fn abort(info: Option<&AbortInfo>) -> ! {
192 unsafe {
193 __sel4_panicking_env__abort_hook(info);
194 __sel4_panicking_env__abort_trap()
195 }
196}
197
198pub fn abort_without_info() -> ! {
202 abort(None)
203}
204
205#[doc(hidden)]
206#[track_caller]
207pub fn __abort_macro_helper(message: Option<fmt::Arguments>) -> ! {
208 abort(Some(&AbortInfo {
209 message: message.as_ref(),
210 location: Some(Location::caller()),
211 }))
212}
213
214#[macro_export]
244macro_rules! abort {
245 () => ($crate::__abort_macro_helper(::core::option::Option::None));
246 ($($arg:tt)*) => ($crate::__abort_macro_helper(::core::option::Option::Some(format_args!($($arg)*))));
247}