twizzler_rt_abi/
core.rs

1//! Low-level runtime functionality.
2
3/// Type for exit code.
4pub type ExitCode = crate::bindings::exit_code;
5use crate::{
6    error::{GenericError, TwzError},
7    nk,
8};
9
10/// Exit with the provided error code. If the main thread for a program
11/// exits, the remaining threads will exit as well.
12pub fn twz_rt_exit(code: ExitCode) -> ! {
13    unsafe {
14        nk!(crate::bindings::twz_rt_exit(code));
15        unreachable!()
16    }
17}
18
19/// Abort execution due to unrecoverable language error.
20pub fn twz_rt_abort() -> ! {
21    unsafe {
22        nk!(crate::bindings::twz_rt_abort());
23        unreachable!()
24    }
25}
26
27/// Call this before calling main, after initializing the runtime.
28/// If this function returns None, then call main. Otherwise, act
29/// as if main returned the provided [ExitCode].
30pub fn twz_rt_pre_main_hook() -> Option<ExitCode> {
31    unsafe { nk!(crate::bindings::twz_rt_pre_main_hook().into()) }
32}
33
34impl From<crate::bindings::option_exit_code> for Option<ExitCode> {
35    #[inline]
36    fn from(value: crate::bindings::option_exit_code) -> Self {
37        if value.is_some == 0 {
38            None
39        } else {
40            Some(value.value)
41        }
42    }
43}
44
45/// Call this after return from main, before running destructors.
46pub fn twz_rt_post_main_hook() {
47    unsafe {
48        nk!(crate::bindings::twz_rt_post_main_hook());
49    }
50}
51
52/// Called by security context code on compartment entry
53pub fn twz_rt_cross_compartment_entry() -> Result<(), TwzError> {
54    unsafe {
55        if nk!(crate::bindings::twz_rt_cross_compartment_entry()) {
56            Ok(())
57        } else {
58            Err(GenericError::AccessDenied.into())
59        }
60    }
61}
62
63pub use crate::bindings::{
64    basic_aux as BasicAux, basic_return as BasicReturn, comp_init_info as CompartmentInitInfo,
65    ctor_set as CtorSet, init_info_ptrs as InitInfoPtrs, minimal_init_info as MinimalInitInfo,
66    runtime_info as RuntimeInfo, RUNTIME_INIT_COMP, RUNTIME_INIT_MIN, RUNTIME_INIT_MONITOR,
67};
68
69// Safety: this holds functions pointers, but these pointers have 'static lifetime.
70unsafe impl Send for CtorSet {}
71
72// Safety: this holds functions pointers, but these pointers have 'static lifetime.
73unsafe impl Sync for CtorSet {}
74
75unsafe impl Send for RuntimeInfo {}
76unsafe impl Sync for RuntimeInfo {}
77unsafe impl Send for CompartmentInitInfo {}
78unsafe impl Sync for CompartmentInitInfo {}
79
80/// The entry point for the runtime. Not for public use.
81pub fn twz_rt_runtime_entry(
82    info: *const RuntimeInfo,
83    std_entry: unsafe extern "C-unwind" fn(BasicAux) -> BasicReturn,
84    main: usize,
85) -> ! {
86    unsafe {
87        nk!(crate::bindings::twz_rt_runtime_entry(
88            info,
89            Some(std_entry),
90            main
91        ));
92        unreachable!()
93    }
94}
95
96#[cfg(all(feature = "rt0"))]
97pub mod rt0 {
98    //! rt0 defines a collection of functions that the basic Rust ABI expects to be defined by some
99    //! part of the C runtime:
100    //!
101    //!   - __tls_get_addr for handling non-local TLS regions.
102
103    use super::{BasicAux, BasicReturn, RuntimeInfo};
104
105    // The C-based entry point coming from arch-specific assembly _start function.
106    #[no_mangle]
107    pub unsafe extern "C" fn __rust_entry_from_c(arg: usize, main: usize) -> ! {
108        // Just trampoline to rust-abi code.
109        rust_entry(arg as *const _, main)
110    }
111
112    /// Entry point for Rust code wishing to start from rt0.
113    ///
114    /// # Safety
115    /// Do not call this unless you are bootstrapping a runtime.
116    pub unsafe fn rust_entry(arg: *const RuntimeInfo, main: usize) -> ! {
117        // All we need to do is grab the runtime and call its init function. We want to
118        // do as little as possible here.
119        #[cfg(target_os = "twizzler")]
120        {
121            super::twz_rt_runtime_entry(arg, std_entry_from_runtime, main)
122        }
123        #[cfg(not(target_os = "twizzler"))]
124        {
125            panic!("")
126        }
127    }
128
129    #[cfg(target_os = "twizzler")]
130    extern "C-unwind" {
131        fn std_entry_from_runtime(aux: BasicAux) -> BasicReturn;
132    }
133}