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
15pub struct LibraryHandle {
17 comp: ObjID,
18 id: LibraryId,
19}
20
21impl Monitor {
22 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 let lib = dynlink
37 .get_library(handle.id)
38 .map_err(|_| GenericError::Internal)?;
39 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 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 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 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 pub fn drop_library_handle(&self, caller: ObjID, desc: Descriptor) {
110 self.library_handles
112 .write(ThreadKey::get().unwrap())
113 .remove(caller, desc);
114 }
115}