1use crate::{
2 functions::{
3 ExportFunction, FunctionIndex, FunctionMetadata, ImportFunction, OwnedFunctionMetadata,
4 },
5 globals::GlobalSpec,
6 linear_memory::{HeapSpec, LinearMemorySpec, SparseData},
7 types::Signature,
8 Error,
9};
10use derivative::Derivative;
11use minisign::SignatureBones;
12use serde::{Deserialize, Serialize};
13use serde_big_array::big_array;
14
15pub const MODULE_DATA_SYM: &str = "lucet_module_data";
16
17big_array! {
18 BigArray;
19 SignatureBones::BYTES,
20}
21
22#[derive(Derivative, Serialize, Deserialize)]
31#[derivative(Debug)]
32pub struct ModuleData<'a> {
33 #[serde(borrow)]
34 linear_memory: Option<LinearMemorySpec<'a>>,
35 #[serde(borrow)]
36 globals_spec: Vec<GlobalSpec<'a>>,
37 #[serde(borrow)]
38 function_info: Vec<FunctionMetadata<'a>>,
39 #[serde(borrow)]
40 import_functions: Vec<ImportFunction<'a>>,
41 #[serde(borrow)]
42 export_functions: Vec<ExportFunction<'a>>,
43 signatures: Vec<Signature>,
44 #[serde(with = "BigArray")]
45 #[derivative(Debug = "ignore")]
46 module_signature: [u8; SignatureBones::BYTES],
47 features: ModuleFeatures,
48}
49
50#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
51pub struct ModuleFeatures {
52 pub sse3: bool,
53 pub ssse3: bool,
54 pub sse41: bool,
55 pub sse42: bool,
56 pub avx: bool,
57 pub bmi1: bool,
58 pub bmi2: bool,
59 pub lzcnt: bool,
60 pub popcnt: bool,
61 pub instruction_count: bool,
62 _hidden: (),
63}
64
65impl ModuleFeatures {
66 pub fn none() -> Self {
67 Self {
68 sse3: false,
69 ssse3: false,
70 sse41: false,
71 sse42: false,
72 avx: false,
73 bmi1: false,
74 bmi2: false,
75 lzcnt: false,
76 popcnt: false,
77 instruction_count: false,
78 _hidden: (),
79 }
80 }
81}
82
83impl<'a> ModuleData<'a> {
84 pub fn new(
85 linear_memory: Option<LinearMemorySpec<'a>>,
86 globals_spec: Vec<GlobalSpec<'a>>,
87 function_info: Vec<FunctionMetadata<'a>>,
88 import_functions: Vec<ImportFunction<'a>>,
89 export_functions: Vec<ExportFunction<'a>>,
90 signatures: Vec<Signature>,
91 features: ModuleFeatures,
92 ) -> Self {
93 Self {
94 linear_memory,
95 globals_spec,
96 function_info,
97 import_functions,
98 export_functions,
99 signatures,
100 module_signature: [0u8; SignatureBones::BYTES],
101 features,
102 }
103 }
104
105 pub fn heap_spec(&self) -> Option<&HeapSpec> {
106 if let Some(ref linear_memory) = self.linear_memory {
107 Some(&linear_memory.heap)
108 } else {
109 None
110 }
111 }
112
113 pub fn sparse_data(&self) -> Option<&SparseData<'a>> {
114 if let Some(ref linear_memory) = self.linear_memory {
115 Some(&linear_memory.initializer)
116 } else {
117 None
118 }
119 }
120
121 pub fn globals_spec(&self) -> &[GlobalSpec<'a>] {
122 &self.globals_spec
123 }
124
125 pub fn function_info(&self) -> &[FunctionMetadata<'a>] {
126 &self.function_info
127 }
128
129 pub fn import_functions(&self) -> &[ImportFunction<'_>] {
130 &self.import_functions
131 }
132
133 pub fn export_functions(&self) -> &[ExportFunction<'_>] {
134 &self.export_functions
135 }
136
137 pub fn get_signature(&self, fn_id: FunctionIndex) -> &Signature {
142 let sig_idx = self.function_info[fn_id.as_u32() as usize].signature;
143 &self.signatures[sig_idx.as_u32() as usize]
144 }
145
146 pub fn get_export_func_id(&self, name: &str) -> Option<FunctionIndex> {
147 self.export_functions
148 .iter()
149 .find(|export| export.names.contains(&name))
150 .map(|export| export.fn_idx)
151 }
152
153 pub fn signatures(&self) -> &[Signature] {
154 &self.signatures
155 }
156
157 pub fn get_module_signature(&self) -> &[u8] {
158 &self.module_signature
159 }
160
161 pub fn features(&self) -> &ModuleFeatures {
162 &self.features
163 }
164
165 pub fn patch_module_signature(
166 module_data_bin: &'a [u8],
167 module_signature: &[u8],
168 ) -> Result<Vec<u8>, Error> {
169 assert_eq!(module_signature.len(), SignatureBones::BYTES);
170 let mut module_data = Self::deserialize(module_data_bin)?;
171 module_data
172 .module_signature
173 .copy_from_slice(module_signature);
174 let patched_module_data_bin = module_data.serialize()?;
175 assert_eq!(patched_module_data_bin.len(), module_data_bin.len());
176 Ok(patched_module_data_bin)
177 }
178
179 pub fn clear_module_signature(module_data_bin: &'a [u8]) -> Result<Vec<u8>, Error> {
180 let module_signature = vec![0u8; SignatureBones::BYTES];
181 Self::patch_module_signature(module_data_bin, &module_signature)
182 }
183
184 pub fn serialize(&self) -> Result<Vec<u8>, Error> {
186 bincode::serialize(self).map_err(Error::SerializationError)
187 }
188
189 pub fn deserialize(buf: &'a [u8]) -> Result<ModuleData<'a>, Error> {
191 bincode::deserialize(buf).map_err(Error::DeserializationError)
192 }
193}
194
195use crate::{
196 functions::{OwnedExportFunction, OwnedImportFunction},
197 globals::OwnedGlobalSpec,
198 linear_memory::{OwnedLinearMemorySpec, OwnedSparseData},
199};
200
201pub struct OwnedModuleData {
207 linear_memory: Option<OwnedLinearMemorySpec>,
208 globals_spec: Vec<OwnedGlobalSpec>,
209 function_info: Vec<OwnedFunctionMetadata>,
210 imports: Vec<OwnedImportFunction>,
211 exports: Vec<OwnedExportFunction>,
212 signatures: Vec<Signature>,
213 features: ModuleFeatures,
214}
215
216impl OwnedModuleData {
217 pub fn new(
218 linear_memory: Option<OwnedLinearMemorySpec>,
219 globals_spec: Vec<OwnedGlobalSpec>,
220 function_info: Vec<OwnedFunctionMetadata>,
221 imports: Vec<OwnedImportFunction>,
222 exports: Vec<OwnedExportFunction>,
223 signatures: Vec<Signature>,
224 features: ModuleFeatures,
225 ) -> Self {
226 Self {
227 linear_memory,
228 globals_spec,
229 function_info,
230 imports,
231 exports,
232 signatures,
233 features,
234 }
235 }
236
237 pub fn to_ref<'a>(&'a self) -> ModuleData<'a> {
240 ModuleData::new(
241 if let Some(ref owned_linear_memory) = self.linear_memory {
242 Some(owned_linear_memory.to_ref())
243 } else {
244 None
245 },
246 self.globals_spec.iter().map(|gs| gs.to_ref()).collect(),
247 self.function_info
248 .iter()
249 .map(|info| info.to_ref())
250 .collect(),
251 self.imports.iter().map(|imp| imp.to_ref()).collect(),
252 self.exports.iter().map(|exp| exp.to_ref()).collect(),
253 self.signatures.clone(),
254 self.features.clone(),
255 )
256 }
257
258 pub fn empty() -> Self {
259 Self::new(
260 None,
261 vec![],
262 vec![],
263 vec![],
264 vec![],
265 vec![],
266 ModuleFeatures::none(),
267 )
268 }
269
270 pub fn with_heap_spec(mut self, heap_spec: HeapSpec) -> Self {
271 if let Some(ref mut linear_memory) = self.linear_memory {
272 linear_memory.heap = heap_spec;
273 } else {
274 self.linear_memory = Some(OwnedLinearMemorySpec {
275 heap: heap_spec,
276 initializer: OwnedSparseData::new(vec![]).unwrap(),
277 });
278 }
279 self
280 }
281}
282
283impl Default for OwnedModuleData {
284 fn default() -> Self {
285 OwnedModuleData::empty()
286 }
287}