dynlink/context/
runtime.rs

1use std::alloc::Layout;
2
3use twizzler_abi::object::MAX_SIZE;
4use twizzler_rt_abi::core::CtorSet;
5
6use super::{Context, LoadedOrUnloaded};
7use crate::{compartment::CompartmentId, library::LibraryId, tls::TlsRegion, DynlinkError};
8
9#[repr(C)]
10pub struct RuntimeInitInfo {
11    pub tls_region: TlsRegion,
12    pub ctx: *const u8,
13    pub root_name: String,
14    pub used_slots: Vec<usize>,
15    pub ctors: Vec<CtorSet>,
16    pub bootstrap_alloc_slot: usize,
17}
18
19// Safety: the pointers involved here are used for a one-time handoff during bootstrap.
20unsafe impl Send for RuntimeInitInfo {}
21unsafe impl Sync for RuntimeInitInfo {}
22
23impl RuntimeInitInfo {
24    pub(crate) fn new(
25        tls_region: TlsRegion,
26        ctx: &Context,
27        root_name: String,
28        ctors: Vec<CtorSet>,
29    ) -> Self {
30        let alloc_test = unsafe { std::alloc::alloc(Layout::from_size_align(16, 8).unwrap()) }
31            as usize
32            / MAX_SIZE;
33        Self {
34            tls_region,
35            ctx: ctx as *const _ as *const u8,
36            root_name,
37            used_slots: vec![],
38            ctors,
39            bootstrap_alloc_slot: alloc_test,
40        }
41    }
42}
43
44impl Context {
45    /// Build up a list of constructors to call for a library and its dependencies.
46    pub fn build_ctors_list(
47        &self,
48        root_id: LibraryId,
49        comp: Option<CompartmentId>,
50    ) -> Result<Vec<CtorSet>, DynlinkError> {
51        let mut ctors = vec![];
52        self.with_dfs_postorder(root_id, |lib| match lib {
53            LoadedOrUnloaded::Unloaded(_) => {}
54            LoadedOrUnloaded::Loaded(lib) => {
55                if let Some(comp) = comp {
56                    if comp == lib.comp_id {
57                        ctors.push(lib.ctors);
58                    }
59                } else {
60                    ctors.push(lib.ctors);
61                }
62            }
63        });
64        Ok(ctors)
65    }
66
67    /// Build the runtime handoff info for bootstrapping the Twizzler runtime.
68    pub fn build_runtime_info(
69        &self,
70        root_id: LibraryId,
71        tls: TlsRegion,
72    ) -> Result<RuntimeInitInfo, DynlinkError> {
73        let ctors = self.build_ctors_list(root_id, None)?;
74        Ok(RuntimeInitInfo::new(
75            tls,
76            self,
77            self.get_library(root_id)?.name.to_string(),
78            ctors,
79        ))
80    }
81}