lucet_runtime_internals/
module.rs1mod dl;
2mod mock;
3mod sparse_page_data;
4
5pub use crate::module::dl::DlModule;
6pub use crate::module::mock::{MockExportBuilder, MockModuleBuilder};
7pub use lucet_module::{
8 FunctionHandle, FunctionIndex, FunctionPointer, FunctionSpec, Global, GlobalSpec, GlobalValue,
9 HeapSpec, Signature, TableElement, TrapCode, TrapManifest, ValueType,
10};
11
12use crate::alloc::Limits;
13use crate::error::Error;
14use libc::c_void;
15
16#[derive(Clone, Debug)]
23pub struct AddrDetails {
24 pub in_module_code: bool,
25 pub file_name: Option<String>,
26 pub sym_name: Option<String>,
27}
28
29pub trait Module: ModuleInternal {
34 fn initial_globals_size(&self) -> usize {
36 self.globals().len() * std::mem::size_of::<u64>()
37 }
38}
39
40pub trait ModuleInternal: Send + Sync {
41 fn is_instruction_count_instrumented(&self) -> bool;
45
46 fn heap_spec(&self) -> Option<&HeapSpec>;
47
48 fn globals(&self) -> &[GlobalSpec<'_>];
53
54 fn get_sparse_page_data(&self, page: usize) -> Option<&[u8]>;
55
56 fn sparse_page_data_len(&self) -> usize;
58
59 fn table_elements(&self) -> Result<&[TableElement], Error>;
61
62 fn get_export_func(&self, sym: &str) -> Result<FunctionHandle, Error>;
63
64 fn get_func_from_idx(&self, table_id: u32, func_id: u32) -> Result<FunctionHandle, Error>;
65
66 fn get_start_func(&self) -> Result<Option<FunctionHandle>, Error>;
67
68 fn function_manifest(&self) -> &[FunctionSpec];
69
70 fn addr_details(&self, addr: *const c_void) -> Result<Option<AddrDetails>, Error>;
71
72 fn get_signature(&self, fn_id: FunctionIndex) -> &Signature;
73
74 fn function_handle_from_ptr(&self, ptr: FunctionPointer) -> FunctionHandle {
75 let id = self
76 .function_manifest()
77 .iter()
78 .enumerate()
79 .find(|(_, fn_spec)| fn_spec.ptr() == ptr)
80 .map(|(fn_id, _)| FunctionIndex::from_u32(fn_id as u32))
81 .expect("valid function pointer");
82
83 FunctionHandle { ptr, id }
84 }
85
86 fn lookup_trapcode(&self, rip: *const c_void) -> Option<TrapCode> {
90 for fn_spec in self.function_manifest() {
91 if let Some(offset) = fn_spec.relative_addr(rip as u64) {
92 return fn_spec.traps().and_then(|traps| traps.lookup_addr(offset));
97 }
98 }
99 None
100 }
101
102 fn validate_runtime_spec(&self, limits: &Limits) -> Result<(), Error> {
107 if let Some(heap) = self.heap_spec() {
109 if heap.reserved_size > std::u32::MAX as u64 + 1
113 || heap.guard_size > std::u32::MAX as u64 + 1
114 {
115 return Err(lucet_incorrect_module!(
116 "heap spec sizes would overflow: {:?}",
117 heap
118 ));
119 }
120
121 if heap.reserved_size as usize + heap.guard_size as usize
122 > limits.heap_address_space_size
123 {
124 bail_limits_exceeded!("heap spec reserved and guard size: {:?}", heap);
125 }
126
127 if heap.initial_size as usize > limits.heap_memory_size {
128 bail_limits_exceeded!("heap spec initial size: {:?}", heap);
129 }
130
131 if heap.initial_size > heap.reserved_size {
132 return Err(lucet_incorrect_module!(
133 "initial heap size greater than reserved size: {:?}",
134 heap
135 ));
136 }
137 }
138
139 if self.globals().len() * std::mem::size_of::<u64>() > limits.globals_size {
140 bail_limits_exceeded!("globals exceed limits");
141 }
142
143 Ok(())
144 }
145}