1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use std::alloc::Layout;

use twizzler_abi::object::MAX_SIZE;

use super::{Context, LoadedOrUnloaded};
use crate::{
    library::{CtorInfo, LibraryId},
    tls::TlsRegion,
    DynlinkError,
};

#[repr(C)]
pub struct RuntimeInitInfo {
    pub tls_region: TlsRegion,
    pub ctx: *const u8,
    pub root_name: String,
    pub used_slots: Vec<usize>,
    pub ctors: Vec<CtorInfo>,
    pub bootstrap_alloc_slot: usize,
}

// Safety: the pointers involved here are used for a one-time handoff during bootstrap.
unsafe impl Send for RuntimeInitInfo {}
unsafe impl Sync for RuntimeInitInfo {}

impl RuntimeInitInfo {
    pub(crate) fn new(
        tls_region: TlsRegion,
        ctx: &Context,
        root_name: String,
        ctors: Vec<CtorInfo>,
    ) -> Self {
        let alloc_test = unsafe { std::alloc::alloc(Layout::from_size_align(16, 8).unwrap()) }
            as usize
            / MAX_SIZE;
        Self {
            tls_region,
            ctx: ctx as *const _ as *const u8,
            root_name,
            used_slots: vec![],
            ctors,
            bootstrap_alloc_slot: alloc_test,
        }
    }
}

impl Context {
    /// Build up a list of constructors to call for a library and its dependencies.
    pub fn build_ctors_list(&self, root_id: LibraryId) -> Result<Vec<CtorInfo>, DynlinkError> {
        let mut ctors = vec![];
        self.with_dfs_postorder(root_id, |lib| match lib {
            LoadedOrUnloaded::Unloaded(_) => {}
            LoadedOrUnloaded::Loaded(lib) => {
                ctors.push(lib.ctors);
            }
        });
        Ok(ctors)
    }

    /// Build the runtime handoff info for bootstrapping the Twizzler runtime.
    pub fn build_runtime_info(
        &self,
        root_id: LibraryId,
        tls: TlsRegion,
    ) -> Result<RuntimeInitInfo, DynlinkError> {
        let ctors = self.build_ctors_list(root_id)?;
        Ok(RuntimeInitInfo::new(
            tls,
            self,
            self.get_library(root_id)?.name.to_string(),
            ctors,
        ))
    }
}