]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/sgx/abi/panic.rs
SGX target: improve panic & exit handling
[rust.git] / src / libstd / sys / sgx / abi / panic.rs
1 use super::usercalls::alloc::UserRef;
2 use cmp;
3 use io::{self, Write};
4 use mem;
5
6 extern "C" {
7     fn take_debug_panic_buf_ptr() -> *mut u8;
8     static DEBUG: u8;
9 }
10
11 pub(crate) struct SgxPanicOutput(Option<&'static mut UserRef<[u8]>>);
12
13 fn empty_user_slice() -> &'static mut UserRef<[u8]> {
14     unsafe { UserRef::from_raw_parts_mut(1 as *mut u8, 0) }
15 }
16
17 impl SgxPanicOutput {
18     pub(crate) fn new() -> Option<Self> {
19         if unsafe { DEBUG == 0 } {
20             None
21         } else {
22             Some(SgxPanicOutput(None))
23         }
24     }
25
26     fn init(&mut self) -> &mut &'static mut UserRef<[u8]> {
27         self.0.get_or_insert_with(|| unsafe {
28             let ptr = take_debug_panic_buf_ptr();
29             if ptr.is_null() {
30                 empty_user_slice()
31             } else {
32                 UserRef::from_raw_parts_mut(ptr, 1024)
33             }
34         })
35     }
36 }
37
38 impl Write for SgxPanicOutput {
39     fn write(&mut self, src: &[u8]) -> io::Result<usize> {
40         let dst = mem::replace(self.init(), empty_user_slice());
41         let written = cmp::min(src.len(), dst.len());
42         dst[..written].copy_from_enclave(&src[..written]);
43         self.0 = Some(&mut dst[written..]);
44         Ok(written)
45     }
46
47     fn flush(&mut self) -> io::Result<()> {
48         Ok(())
49     }
50 }
51
52 #[no_mangle]
53 pub extern "C" fn panic_msg(msg: &str) -> ! {
54     let _ = SgxPanicOutput::new().map(|mut out| out.write(msg.as_bytes()));
55     unsafe { usercall_exit(true); }
56 }
57
58 extern "C" { pub fn usercall_exit(panic: bool) -> !; }