lucet_module_data/
module_data.rs

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 minisign::SignatureBones;
11use serde::{Deserialize, Serialize};
12
13/// The metadata (and some data) for a Lucet module.
14///
15/// The lifetime parameter exists to support zero-copy deserialization for the `&str` and `&[u8]`
16/// fields at the leaves of the structure. For a variant with owned types at the leaves, see
17/// [`OwnedModuleData`](owned/struct.OwnedModuleData.html).
18///
19/// The goal is for this structure to eventually include everything except the code for the guest
20/// functions themselves.
21#[derive(Debug, Serialize, Deserialize)]
22pub struct ModuleData<'a> {
23    #[serde(borrow)]
24    linear_memory: Option<LinearMemorySpec<'a>>,
25    #[serde(borrow)]
26    globals_spec: Vec<GlobalSpec<'a>>,
27    #[serde(borrow)]
28    function_info: Vec<FunctionMetadata<'a>>,
29    #[serde(borrow)]
30    import_functions: Vec<ImportFunction<'a>>,
31    #[serde(borrow)]
32    export_functions: Vec<ExportFunction<'a>>,
33    signatures: Vec<Signature>,
34    module_signature: Vec<u8>,
35}
36
37impl<'a> ModuleData<'a> {
38    pub fn new(
39        linear_memory: Option<LinearMemorySpec<'a>>,
40        globals_spec: Vec<GlobalSpec<'a>>,
41        function_info: Vec<FunctionMetadata<'a>>,
42        import_functions: Vec<ImportFunction<'a>>,
43        export_functions: Vec<ExportFunction<'a>>,
44        signatures: Vec<Signature>,
45    ) -> Self {
46        let module_signature = vec![0u8; SignatureBones::BYTES];
47        Self {
48            linear_memory,
49            globals_spec,
50            function_info,
51            import_functions,
52            export_functions,
53            signatures,
54            module_signature,
55        }
56    }
57
58    pub fn heap_spec(&self) -> Option<&HeapSpec> {
59        if let Some(ref linear_memory) = self.linear_memory {
60            Some(&linear_memory.heap)
61        } else {
62            None
63        }
64    }
65
66    pub fn sparse_data(&self) -> Option<&SparseData<'a>> {
67        if let Some(ref linear_memory) = self.linear_memory {
68            Some(&linear_memory.initializer)
69        } else {
70            None
71        }
72    }
73
74    pub fn globals_spec(&self) -> &[GlobalSpec<'a>] {
75        &self.globals_spec
76    }
77
78    pub fn function_info(&self) -> &[FunctionMetadata<'a>] {
79        &self.function_info
80    }
81
82    pub fn import_functions(&self) -> &[ImportFunction<'_>] {
83        &self.import_functions
84    }
85
86    pub fn export_functions(&self) -> &[ExportFunction<'_>] {
87        &self.export_functions
88    }
89
90    // Function index here is a different index space than `get_func_from_idx`, which
91    // uses function index as an index into a table of function elements.
92    //
93    // This is an index of all functions in the module.
94    pub fn get_signature(&self, fn_id: FunctionIndex) -> &Signature {
95        let sig_idx = self.function_info[fn_id.as_u32() as usize].signature;
96        &self.signatures[sig_idx.as_u32() as usize]
97    }
98
99    pub fn get_export_func_id(&self, name: &str) -> Option<FunctionIndex> {
100        self.export_functions
101            .iter()
102            .find(|export| export.names.contains(&name))
103            .map(|export| export.fn_idx)
104    }
105
106    pub fn signatures(&self) -> &[Signature] {
107        &self.signatures
108    }
109
110    pub fn get_module_signature(&self) -> &[u8] {
111        &self.module_signature
112    }
113
114    pub fn patch_module_signature(
115        module_data_bin: &'a [u8],
116        module_signature: &[u8],
117    ) -> Result<Vec<u8>, Error> {
118        assert_eq!(module_signature.len(), SignatureBones::BYTES);
119        let mut module_data = Self::deserialize(module_data_bin)?;
120        module_data
121            .module_signature
122            .copy_from_slice(module_signature);
123        let patched_module_data_bin = module_data.serialize()?;
124        assert_eq!(patched_module_data_bin.len(), module_data_bin.len());
125        Ok(patched_module_data_bin)
126    }
127
128    pub fn clear_module_signature(module_data_bin: &'a [u8]) -> Result<Vec<u8>, Error> {
129        let module_signature = vec![0u8; SignatureBones::BYTES];
130        Self::patch_module_signature(module_data_bin, &module_signature)
131    }
132
133    /// Serialize to [`bincode`](https://github.com/TyOverby/bincode).
134    pub fn serialize(&self) -> Result<Vec<u8>, Error> {
135        bincode::serialize(self).map_err(Error::SerializationError)
136    }
137
138    /// Deserialize from [`bincode`](https://github.com/TyOverby/bincode).
139    pub fn deserialize(buf: &'a [u8]) -> Result<ModuleData<'a>, Error> {
140        bincode::deserialize(buf).map_err(Error::DeserializationError)
141    }
142}
143
144use crate::{
145    functions::{OwnedExportFunction, OwnedImportFunction},
146    globals::OwnedGlobalSpec,
147    linear_memory::{OwnedLinearMemorySpec, OwnedSparseData},
148};
149
150/// The metadata (and some data) for a Lucet module.
151///
152/// This is a version of [`ModuleData`](../struct.ModuleData.html) with owned types throughout,
153/// rather than references to support zero-copy deserialization. This type is useful when directly
154/// building up a value to be serialized.
155pub struct OwnedModuleData {
156    linear_memory: Option<OwnedLinearMemorySpec>,
157    globals_spec: Vec<OwnedGlobalSpec>,
158    function_info: Vec<OwnedFunctionMetadata>,
159    imports: Vec<OwnedImportFunction>,
160    exports: Vec<OwnedExportFunction>,
161    signatures: Vec<Signature>,
162}
163
164impl OwnedModuleData {
165    pub fn new(
166        linear_memory: Option<OwnedLinearMemorySpec>,
167        globals_spec: Vec<OwnedGlobalSpec>,
168        function_info: Vec<OwnedFunctionMetadata>,
169        imports: Vec<OwnedImportFunction>,
170        exports: Vec<OwnedExportFunction>,
171        signatures: Vec<Signature>,
172    ) -> Self {
173        Self {
174            linear_memory,
175            globals_spec,
176            function_info,
177            imports,
178            exports,
179            signatures,
180        }
181    }
182
183    /// Create a [`ModuleData`](../struct.ModuleData.html) backed by the values in this
184    /// `OwnedModuleData`.
185    pub fn to_ref<'a>(&'a self) -> ModuleData<'a> {
186        ModuleData::new(
187            if let Some(ref owned_linear_memory) = self.linear_memory {
188                Some(owned_linear_memory.to_ref())
189            } else {
190                None
191            },
192            self.globals_spec.iter().map(|gs| gs.to_ref()).collect(),
193            self.function_info
194                .iter()
195                .map(|info| info.to_ref())
196                .collect(),
197            self.imports.iter().map(|imp| imp.to_ref()).collect(),
198            self.exports.iter().map(|exp| exp.to_ref()).collect(),
199            self.signatures.clone(),
200        )
201    }
202
203    pub fn empty() -> Self {
204        Self::new(None, vec![], vec![], vec![], vec![], vec![])
205    }
206
207    pub fn with_heap_spec(mut self, heap_spec: HeapSpec) -> Self {
208        if let Some(ref mut linear_memory) = self.linear_memory {
209            linear_memory.heap = heap_spec;
210        } else {
211            self.linear_memory = Some(OwnedLinearMemorySpec {
212                heap: heap_spec,
213                initializer: OwnedSparseData::new(vec![]).unwrap(),
214            });
215        }
216        self
217    }
218}
219
220impl Default for OwnedModuleData {
221    fn default() -> Self {
222        OwnedModuleData::empty()
223    }
224}