monitor/mon/
library.rs

1use dynlink::library::LibraryId;
2use happylock::ThreadKey;
3use secgate::util::Descriptor;
4use twizzler_abi::object::{MAX_SIZE, NULLPAGE_SIZE};
5use twizzler_rt_abi::{
6    bindings::link_map,
7    debug::LinkMap,
8    error::{ArgumentError, GenericError, ResourceError, TwzError},
9    object::ObjID,
10};
11
12use super::Monitor;
13use crate::gates::LibraryInfo;
14
15/// A handle to a library.
16pub struct LibraryHandle {
17    comp: ObjID,
18    id: LibraryId,
19}
20
21impl Monitor {
22    /// Get LibraryInfo for a given library handle. Note that this will write to the
23    /// compartment-thread's simple buffer.
24    pub fn get_library_info(
25        &self,
26        instance: ObjID,
27        thread: ObjID,
28        desc: Descriptor,
29    ) -> Result<LibraryInfo, TwzError> {
30        let (_, ref mut comps, ref dynlink, ref libhandles, _) =
31            *self.locks.lock(ThreadKey::get().unwrap());
32        let handle = libhandles
33            .lookup(instance, desc)
34            .ok_or(ArgumentError::InvalidArgument)?;
35        // TODO: dynlink err map
36        let lib = dynlink
37            .get_library(handle.id)
38            .map_err(|_| GenericError::Internal)?;
39        // write the library name to the per-thread simple buffer
40        let pt = comps.get_mut(instance)?.get_per_thread(thread);
41        let name_len = pt.write_bytes(lib.name.as_bytes());
42        let dynamic_ptr = lib.dynamic_ptr();
43        Ok(LibraryInfo {
44            name_len,
45            compartment_id: handle.comp,
46            objid: lib.full_obj.id(),
47            slot: lib.full_obj.load_addr() / MAX_SIZE,
48            start: (lib.full_obj.load_addr() + NULLPAGE_SIZE) as *mut _,
49            len: MAX_SIZE - NULLPAGE_SIZE * 2,
50            dl_info: twizzler_rt_abi::debug::DlPhdrInfo {
51                addr: lib.base_addr(),
52                name: core::ptr::null(),
53                phdr: lib.get_phdrs_raw().ok_or(GenericError::Internal)?.0 as *const _,
54                phnum: lib.get_phdrs_raw().ok_or(GenericError::Internal)?.1 as u32,
55                adds: 0,
56                subs: 0,
57                tls_modid: lib.tls_id.map(|t| t.tls_id()).unwrap_or(0) as usize,
58                tls_data: core::ptr::null_mut(),
59            },
60            desc,
61            link_map: LinkMap(link_map {
62                next: core::ptr::null_mut(),
63                prev: core::ptr::null_mut(),
64                name: core::ptr::null_mut(),
65                ld: dynamic_ptr.unwrap_or(core::ptr::null_mut()).cast(),
66                addr: lib.base_addr(),
67            }),
68        })
69    }
70
71    /// Open a handle to the n'th library for a compartment.
72    pub fn get_library_handle(
73        &self,
74        caller: ObjID,
75        comp: Option<Descriptor>,
76        num: usize,
77    ) -> Result<Descriptor, TwzError> {
78        let (_, ref mut comps, ref dynlink, ref mut handles, ref comphandles) =
79            *self.locks.lock(ThreadKey::get().unwrap());
80        let comp_id = comp
81            .map(|comp| comphandles.lookup(caller, comp).map(|ch| ch.instance))
82            .unwrap_or(Some(caller))
83            .ok_or(TwzError::INVALID_ARGUMENT)?;
84        let rc = comps.get(comp_id)?;
85        // TODO: dynlink err map
86        let dcomp = dynlink
87            .get_compartment(rc.compartment_id)
88            .map_err(|_| GenericError::Internal)?;
89        let id = dcomp
90            .library_ids()
91            .nth(num)
92            .ok_or(TwzError::INVALID_ARGUMENT)?;
93        handles
94            .insert(caller, LibraryHandle { comp: comp_id, id })
95            .ok_or(ResourceError::OutOfResources.into())
96    }
97
98    /// Load a library in the given compartment.
99    pub fn load_library(
100        &self,
101        _caller: ObjID,
102        _id: ObjID,
103        _comp: Option<Descriptor>,
104    ) -> Result<Descriptor, TwzError> {
105        todo!()
106    }
107
108    /// Drop a library handle.
109    pub fn drop_library_handle(&self, caller: ObjID, desc: Descriptor) {
110        //tracing::info!("drop: {}", desc);
111        self.library_handles
112            .write(ThreadKey::get().unwrap())
113            .remove(caller, desc);
114    }
115}