dynlink/context/
runtime.rs

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