wasmer_runtime_core_near/
module.rs

1//! This module contains the types to manipulate and access Wasm modules.
2//!
3//! A Wasm module is the artifact of compiling WebAssembly. Wasm modules are not executable
4//! until they're instantiated with imports (via [`ImportObject`]).
5use crate::{
6    backend::RunnableModule,
7    cache::{Artifact, Error as CacheError},
8    error,
9    import::ImportObject,
10    structures::{Map, TypedIndex},
11    types::{
12        ExportDescriptor, FuncIndex, FuncSig, GlobalDescriptor, GlobalIndex, GlobalInit,
13        ImportDescriptor, ImportedFuncIndex, ImportedGlobalIndex, ImportedMemoryIndex,
14        ImportedTableIndex, Initializer, LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex,
15        MemoryDescriptor, MemoryIndex, SigIndex, TableDescriptor, TableIndex,
16    },
17    Instance,
18};
19
20use crate::backend::CacheGen;
21#[cfg(feature = "generate-debug-information")]
22use crate::jit_debug;
23use borsh::{BorshDeserialize, BorshSerialize};
24use core::convert::TryFrom;
25use indexmap::IndexMap;
26use std::collections::HashMap;
27use std::hash::Hash;
28use std::io::Write;
29use std::sync::Arc;
30
31/// This is used to instantiate a new WebAssembly module.
32#[doc(hidden)]
33pub struct ModuleInner {
34    pub runnable_module: Arc<Box<dyn RunnableModule>>,
35    pub cache_gen: Box<dyn CacheGen>,
36    pub info: ModuleInfo,
37}
38
39/// Wrapper of IndexMap to impl BorshSerialize and BorshDeserialize on it
40#[derive(Clone, Debug, Serialize, Deserialize, Default)]
41pub struct ExportsMap {
42    /// Actual IndexMap
43    pub map: IndexMap<String, ExportIndex>,
44}
45
46/// Container for module data including memories, globals, tables, imports, and exports.
47#[derive(Clone, Debug, Serialize, Deserialize, BorshSerialize, BorshDeserialize)]
48pub struct ModuleInfo {
49    /// Map of memory index to memory descriptors.
50    // This are strictly local and the typesystem ensures that.
51    pub memories: Map<LocalMemoryIndex, MemoryDescriptor>,
52    /// Map of global index to global descriptors.
53    pub globals: Map<LocalGlobalIndex, GlobalInit>,
54    /// Map of table index to table descriptors.
55    pub tables: Map<LocalTableIndex, TableDescriptor>,
56
57    /// Map of imported function index to import name.
58    // These are strictly imported and the typesystem ensures that.
59    pub imported_functions: Map<ImportedFuncIndex, ImportName>,
60    /// Map of imported memory index to import name and memory descriptor.
61    pub imported_memories: Map<ImportedMemoryIndex, (ImportName, MemoryDescriptor)>,
62    /// Map of imported table index to import name and table descriptor.
63    pub imported_tables: Map<ImportedTableIndex, (ImportName, TableDescriptor)>,
64    /// Map of imported global index to import name and global descriptor.
65    pub imported_globals: Map<ImportedGlobalIndex, (ImportName, GlobalDescriptor)>,
66
67    /// Map of string to export index.
68    // Implementation note: this should maintain the order that the exports appear in the
69    // Wasm module.  Be careful not to use APIs that may break the order!
70    // Side note, because this is public we can't actually guarantee that it will remain
71    // in order.
72    pub exports: ExportsMap,
73
74    /// Vector of data initializers.
75    pub data_initializers: Vec<DataInitializer>,
76    /// Vector of table initializers.
77    pub elem_initializers: Vec<TableInitializer>,
78
79    /// Index of optional start function.
80    pub start_func: Option<FuncIndex>,
81
82    /// Map function index to signature index.
83    pub func_assoc: Map<FuncIndex, SigIndex>,
84    /// Map signature index to function signature.
85    pub signatures: Map<SigIndex, FuncSig>,
86    /// Backend.
87    pub backend: String,
88
89    /// Table of namespace indexes.
90    pub namespace_table: StringTable<NamespaceIndex>,
91    /// Table of name indexes.
92    pub name_table: StringTable<NameIndex>,
93
94    /// Symbol information from emscripten.
95    pub em_symbol_map: Option<HashMap<u32, String>>,
96
97    /// Custom sections.
98    pub custom_sections: HashMap<String, Vec<Vec<u8>>>,
99
100    /// Flag controlling whether or not debug information for use in a debugger
101    /// will be generated.
102    pub generate_debug_info: bool,
103
104    #[cfg(feature = "generate-debug-information")]
105    #[serde(skip)]
106    #[borsh(skip)]
107    /// Resource manager of debug information being used by a debugger.
108    pub(crate) debug_info_manager: jit_debug::JitCodeDebugInfoManager,
109}
110
111impl BorshSerialize for ExportsMap {
112    fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
113        u32::try_from(self.map.len())
114            .map_err(|_| std::io::ErrorKind::InvalidInput)?
115            .serialize(writer)?;
116        for (key, value) in &self.map {
117            key.serialize(writer)?;
118            value.serialize(writer)?;
119        }
120        Ok(())
121    }
122}
123
124impl BorshDeserialize for ExportsMap {
125    fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
126        let len = u32::deserialize_reader(reader)?;
127        // TODO(16): return capacity allocation when we can safely do that.
128        let mut result = IndexMap::with_capacity(len as usize);
129
130        for _ in 0..len {
131            let key = String::deserialize_reader(reader)?;
132            let value = ExportIndex::deserialize_reader(reader)?;
133            result.insert(key, value);
134        }
135        Ok(ExportsMap { map: result })
136    }
137}
138
139impl ModuleInfo {
140    /// Creates custom section info from the given wasm file.
141    pub fn import_custom_sections(&mut self, wasm: &[u8]) -> crate::error::ParseResult<()> {
142        let mut parser = wasmparser::ModuleReader::new(wasm)?;
143        while !parser.eof() {
144            let section = parser.read()?;
145            if let wasmparser::SectionCode::Custom { name, kind: _ } = section.code {
146                let mut reader = section.get_binary_reader();
147                let len = reader.bytes_remaining();
148                let bytes = reader.read_bytes(len)?;
149                let data = bytes.to_vec();
150                let name = name.to_string();
151                let entry: &mut Vec<Vec<u8>> = self.custom_sections.entry(name).or_default();
152                entry.push(data);
153            }
154        }
155        Ok(())
156    }
157}
158
159/// A compiled WebAssembly module.
160///
161/// `Module` is returned by the [`compile_with`][] function.
162///
163/// [`compile_with`]: crate::compile_with
164pub struct Module {
165    inner: Arc<ModuleInner>,
166}
167
168impl Module {
169    pub(crate) fn new(inner: Arc<ModuleInner>) -> Self {
170        Module { inner }
171    }
172
173    /// Instantiate a WebAssembly module with the provided [`ImportObject`].
174    ///
175    /// [`ImportObject`]: struct.ImportObject.html
176    ///
177    /// # Note:
178    /// Instantiating a `Module` will also call the function designated as `start`
179    /// in the WebAssembly module, if there is one.
180    ///
181    /// # Usage:
182    /// ```
183    /// # use wasmer_runtime_core::error::Result;
184    /// # use wasmer_runtime_core::Module;
185    /// # use wasmer_runtime_core::imports;
186    /// # fn instantiate(module: &Module) -> Result<()> {
187    /// let import_object = imports! {
188    ///     // ...
189    /// };
190    /// let instance = module.instantiate(&import_object)?;
191    /// // ...
192    /// # Ok(())
193    /// # }
194    /// ```
195    pub fn instantiate(&self, import_object: &ImportObject) -> error::Result<Instance> {
196        Instance::new(Arc::clone(&self.inner), import_object)
197    }
198
199    /// Create a cache artifact from this module.
200    pub fn cache(&self) -> Result<Artifact, CacheError> {
201        let (backend_metadata, code) = self.inner.cache_gen.generate_cache()?;
202        Ok(Artifact::from_parts(
203            Box::new(self.inner.info.clone()),
204            backend_metadata,
205            code,
206        ))
207    }
208
209    /// Get the module data for this module.
210    pub fn info(&self) -> &ModuleInfo {
211        &self.inner.info
212    }
213
214    /// Get the [`ExportDescriptor`]s of the exports this [`Module`] provides.
215    pub fn exports(&self) -> Vec<ExportDescriptor> {
216        self.inner.exports()
217    }
218
219    /// Get the [`ImportDescriptor`]s describing the imports this [`Module`]
220    /// requires to be instantiated.
221    pub fn imports(&self) -> Vec<ImportDescriptor> {
222        let mut out = Vec::with_capacity(
223            self.inner.info.imported_functions.len()
224                + self.inner.info.imported_memories.len()
225                + self.inner.info.imported_tables.len()
226                + self.inner.info.imported_globals.len(),
227        );
228
229        /// Lookup the (namespace, name) in the [`ModuleInfo`] by index.
230        fn get_import_name(
231            info: &ModuleInfo,
232            &ImportName {
233                namespace_index,
234                name_index,
235            }: &ImportName,
236        ) -> (String, String) {
237            let namespace = info.namespace_table.get(namespace_index).to_string();
238            let name = info.name_table.get(name_index).to_string();
239
240            (namespace, name)
241        }
242
243        let info = &self.inner.info;
244
245        let imported_functions = info.imported_functions.iter().map(|(idx, import_name)| {
246            let (namespace, name) = get_import_name(info, import_name);
247            let sig = info
248                .signatures
249                .get(*info.func_assoc.get(FuncIndex::new(idx.index())).unwrap())
250                .unwrap();
251            ImportDescriptor {
252                namespace,
253                name,
254                ty: sig.into(),
255            }
256        });
257        let imported_memories =
258            info.imported_memories
259                .values()
260                .map(|(import_name, memory_descriptor)| {
261                    let (namespace, name) = get_import_name(info, import_name);
262                    ImportDescriptor {
263                        namespace,
264                        name,
265                        ty: memory_descriptor.into(),
266                    }
267                });
268        let imported_tables =
269            info.imported_tables
270                .values()
271                .map(|(import_name, table_descriptor)| {
272                    let (namespace, name) = get_import_name(info, import_name);
273                    ImportDescriptor {
274                        namespace,
275                        name,
276                        ty: table_descriptor.into(),
277                    }
278                });
279        let imported_globals =
280            info.imported_globals
281                .values()
282                .map(|(import_name, global_descriptor)| {
283                    let (namespace, name) = get_import_name(info, import_name);
284                    ImportDescriptor {
285                        namespace,
286                        name,
287                        ty: global_descriptor.into(),
288                    }
289                });
290
291        out.extend(imported_functions);
292        out.extend(imported_memories);
293        out.extend(imported_tables);
294        out.extend(imported_globals);
295        out
296    }
297
298    /// Get the custom sections matching the given name.
299    pub fn custom_sections(&self, key: impl AsRef<str>) -> Option<&[Vec<u8>]> {
300        let key = key.as_ref();
301        self.inner.info.custom_sections.get(key).map(|v| v.as_ref())
302    }
303}
304
305impl Clone for Module {
306    fn clone(&self) -> Self {
307        Self {
308            inner: Arc::clone(&self.inner),
309        }
310    }
311}
312
313impl ModuleInner {
314    /// Iterate over the [`ExportDescriptor`]s of the exports that this module provides.
315    pub(crate) fn exports_iter(&self) -> impl Iterator<Item = ExportDescriptor> + '_ {
316        self.info
317            .exports
318            .map
319            .iter()
320            .map(move |(name, &ei)| ExportDescriptor {
321                name,
322                ty: match ei {
323                    ExportIndex::Func(f_idx) => {
324                        let sig_idx = self.info.func_assoc[f_idx].into();
325                        self.info.signatures[sig_idx].clone().into()
326                    }
327                    ExportIndex::Global(g_idx) => {
328                        let info = &self.info;
329                        let local_global_idx =
330                            LocalGlobalIndex::new(g_idx.index() - info.imported_globals.len());
331                        info.globals[local_global_idx].desc.into()
332                    }
333                    ExportIndex::Memory(m_idx) => {
334                        let info = &self.info;
335                        let local_memory_idx =
336                            LocalMemoryIndex::new(m_idx.index() - info.imported_memories.len());
337                        info.memories[local_memory_idx].into()
338                    }
339                    ExportIndex::Table(t_idx) => {
340                        let info = &self.info;
341                        let local_table_idx =
342                            LocalTableIndex::new(t_idx.index() - info.imported_tables.len());
343                        info.tables[local_table_idx].into()
344                    }
345                },
346            })
347    }
348
349    /// Get the [`ExportDescriptor`]s of the exports this [`Module`] provides.
350    pub fn exports(&self) -> Vec<ExportDescriptor> {
351        self.exports_iter().collect()
352    }
353}
354
355#[doc(hidden)]
356#[derive(Serialize, Deserialize, Debug, Clone, BorshSerialize, BorshDeserialize)]
357pub struct ImportName {
358    pub namespace_index: NamespaceIndex,
359    pub name_index: NameIndex,
360}
361
362/// A wrapper around the [`TypedIndex`]es for Wasm functions, Wasm memories,
363/// Wasm globals, and Wasm tables.
364///
365/// Used in [`ModuleInfo`] to access function signatures ([`SigIndex`]s,
366/// [`FuncSig`]), [`GlobalInit`]s, [`MemoryDescriptor`]s, and
367/// [`TableDescriptor`]s.
368#[derive(
369    Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, BorshSerialize, BorshDeserialize,
370)]
371pub enum ExportIndex {
372    /// Function export index. [`FuncIndex`] is a type-safe handle referring to
373    /// a Wasm function.
374    Func(FuncIndex),
375    /// Memory export index. [`MemoryIndex`] is a type-safe handle referring to
376    /// a Wasm memory.
377    Memory(MemoryIndex),
378    /// Global export index. [`GlobalIndex`] is a type-safe handle referring to
379    /// a Wasm global.
380    Global(GlobalIndex),
381    /// Table export index. [`TableIndex`] is a type-safe handle referring to
382    /// to a Wasm table.
383    Table(TableIndex),
384}
385
386/// A data initializer for linear memory.
387#[derive(Serialize, Deserialize, Debug, Clone, BorshSerialize, BorshDeserialize)]
388pub struct DataInitializer {
389    /// The index of the memory to initialize.
390    pub memory_index: MemoryIndex,
391    /// Either a constant offset or a `get_global`
392    pub base: Initializer,
393    /// The initialization data.
394    #[cfg_attr(feature = "cache", serde(with = "serde_bytes"))]
395    pub data: Vec<u8>,
396}
397
398/// A WebAssembly table initializer.
399#[derive(Serialize, Deserialize, Debug, Clone, BorshSerialize, BorshDeserialize)]
400pub struct TableInitializer {
401    /// The index of a table to initialize.
402    pub table_index: TableIndex,
403    /// Either a constant offset or a `get_global`
404    pub base: Initializer,
405    /// The values to write into the table elements.
406    pub elements: Vec<FuncIndex>,
407}
408
409/// String table builder.
410pub struct StringTableBuilder<K: TypedIndex> {
411    map: IndexMap<String, (K, u32, u32)>,
412    buffer: String,
413    count: u32,
414}
415
416impl<K: TypedIndex> StringTableBuilder<K> {
417    /// Creates a new [`StringTableBuilder`].
418    pub fn new() -> Self {
419        Self {
420            map: IndexMap::new(),
421            buffer: String::new(),
422            count: 0,
423        }
424    }
425
426    /// Register a new string into table.
427    pub fn register<S>(&mut self, s: S) -> K
428    where
429        S: Into<String> + AsRef<str>,
430    {
431        let s_str = s.as_ref();
432
433        if self.map.contains_key(s_str) {
434            self.map[s_str].0
435        } else {
436            let offset = self.buffer.len();
437            let length = s_str.len();
438            let index = TypedIndex::new(self.count as _);
439
440            self.buffer.push_str(s_str);
441            self.map
442                .insert(s.into(), (index, offset as u32, length as u32));
443            self.count += 1;
444
445            index
446        }
447    }
448
449    /// Finish building the [`StringTable`].
450    pub fn finish(self) -> StringTable<K> {
451        let table = self
452            .map
453            .values()
454            .map(|(_, offset, length)| (*offset, *length))
455            .collect();
456
457        StringTable {
458            table,
459            buffer: self.buffer,
460        }
461    }
462}
463
464/// A map of index to string.
465#[derive(Serialize, Deserialize, Debug, Clone, BorshSerialize, BorshDeserialize)]
466pub struct StringTable<K: TypedIndex> {
467    table: Map<K, (u32, u32)>,
468    buffer: String,
469}
470
471impl<K: TypedIndex> StringTable<K> {
472    /// Creates a `StringTable`.
473    pub fn new() -> Self {
474        Self {
475            table: Map::new(),
476            buffer: String::new(),
477        }
478    }
479
480    /// Gets a reference to a string at the given index.
481    pub fn get(&self, index: K) -> &str {
482        let (offset, length) = self.table[index];
483        let offset = offset as usize;
484        let length = length as usize;
485
486        &self.buffer[offset..offset + length]
487    }
488}
489
490/// A type-safe handle referring to a module namespace.
491#[derive(
492    Serialize,
493    Deserialize,
494    Debug,
495    Copy,
496    Clone,
497    PartialEq,
498    Eq,
499    Hash,
500    BorshSerialize,
501    BorshDeserialize,
502)]
503pub struct NamespaceIndex(u32);
504
505impl TypedIndex for NamespaceIndex {
506    #[doc(hidden)]
507    fn new(index: usize) -> Self {
508        NamespaceIndex(index as _)
509    }
510
511    #[doc(hidden)]
512    fn index(&self) -> usize {
513        self.0 as usize
514    }
515}
516
517/// A type-safe handle referring to a name in a module namespace.
518#[derive(
519    Serialize,
520    Deserialize,
521    Debug,
522    Copy,
523    Clone,
524    PartialEq,
525    Eq,
526    Hash,
527    BorshSerialize,
528    BorshDeserialize,
529)]
530pub struct NameIndex(u32);
531
532impl TypedIndex for NameIndex {
533    #[doc(hidden)]
534    fn new(index: usize) -> Self {
535        NameIndex(index as _)
536    }
537
538    #[doc(hidden)]
539    fn index(&self) -> usize {
540        self.0 as usize
541    }
542}