wasmer_compiler/
serialize.rs

1/*
2 * ! Remove me once rkyv generates doc-comments for fields or generates an #[allow(missing_docs)]
3 * on their own.
4 */
5#![allow(missing_docs)]
6
7use crate::types::{
8    function::{CompiledFunctionFrameInfo, FunctionBody, UnwindInfo, GOT},
9    module::CompileModuleInfo,
10    relocation::Relocation,
11    section::{CustomSection, SectionIndex},
12};
13use enumset::EnumSet;
14use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
15use wasmer_types::{
16    entity::PrimaryMap, target::CpuFeature, DeserializeError, Features, FunctionIndex,
17    LocalFunctionIndex, MemoryIndex, MemoryStyle, ModuleInfo, OwnedDataInitializer, SerializeError,
18    SignatureIndex, TableIndex, TableStyle,
19};
20
21pub use wasmer_types::MetadataHeader;
22
23/// The compilation related data for a serialized modules
24#[derive(Archive, Default, RkyvDeserialize, RkyvSerialize)]
25#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
26#[allow(missing_docs)]
27#[rkyv(derive(Debug))]
28pub struct SerializableCompilation {
29    pub function_bodies: PrimaryMap<LocalFunctionIndex, FunctionBody>,
30    pub function_relocations: PrimaryMap<LocalFunctionIndex, Vec<Relocation>>,
31    pub function_frame_info: PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>,
32    pub function_call_trampolines: PrimaryMap<SignatureIndex, FunctionBody>,
33    pub dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBody>,
34    pub custom_sections: PrimaryMap<SectionIndex, CustomSection>,
35    pub custom_section_relocations: PrimaryMap<SectionIndex, Vec<Relocation>>,
36    // The section indices corresponding to the Dwarf debug info
37    pub unwind_info: UnwindInfo,
38    pub got: GOT,
39    // Custom section containing libcall trampolines.
40    pub libcall_trampolines: SectionIndex,
41    // Length of each libcall trampoline.
42    pub libcall_trampoline_len: u32,
43}
44
45impl SerializableCompilation {
46    /// Serialize a Compilation into bytes
47    /// The bytes will have the following format:
48    /// RKYV serialization (any length) + POS (8 bytes)
49    pub fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
50        rkyv::to_bytes::<rkyv::rancor::Error>(self)
51            .map(|v| v.into_vec())
52            .map_err(|e| SerializeError::Generic(e.to_string()))
53    }
54}
55
56/// Serializable struct that is able to serialize from and to a `ArtifactInfo`.
57#[derive(Archive, RkyvDeserialize, RkyvSerialize)]
58#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
59#[allow(missing_docs)]
60#[rkyv(derive(Debug))]
61pub struct SerializableModule {
62    /// The main serializable compilation object
63    pub compilation: SerializableCompilation,
64    /// Compilation informations
65    pub compile_info: CompileModuleInfo,
66    /// Datas initializers
67    pub data_initializers: Box<[OwnedDataInitializer]>,
68    /// CPU Feature flags for this compilation
69    pub cpu_features: u64,
70}
71
72impl SerializableModule {
73    /// Serialize a Module into bytes
74    /// The bytes will have the following format:
75    /// RKYV serialization (any length) + POS (8 bytes)
76    pub fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
77        rkyv::to_bytes::<rkyv::rancor::Error>(self)
78            .map(|v| v.into_vec())
79            .map_err(|e| SerializeError::Generic(e.to_string()))
80    }
81
82    /// Deserialize a Module from a slice.
83    /// The slice must have the following format:
84    /// RKYV serialization (any length) + POS (8 bytes)
85    ///
86    /// # Safety
87    ///
88    /// This method is unsafe since it deserializes data directly
89    /// from memory.
90    /// Right now we are not doing any extra work for validation, but
91    /// `rkyv` has an option to do bytecheck on the serialized data before
92    /// serializing (via `rkyv::check_archived_value`).
93    pub unsafe fn deserialize_unchecked(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
94        let archived = Self::archive_from_slice(metadata_slice)?;
95        Self::deserialize_from_archive(archived)
96    }
97
98    /// Deserialize a Module from a slice.
99    /// The slice must have the following format:
100    /// RKYV serialization (any length) + POS (8 bytes)
101    ///
102    /// Unlike [`Self::deserialize`], this function will validate the data.
103    ///
104    /// # Safety
105    /// Unsafe because it loads executable code into memory.
106    /// The loaded bytes must be trusted.
107    pub unsafe fn deserialize(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
108        let archived = Self::archive_from_slice_checked(metadata_slice)?;
109        Self::deserialize_from_archive(archived)
110    }
111
112    /// # Safety
113    ///
114    /// This method is unsafe.
115    /// Please check `SerializableModule::deserialize` for more details.
116    pub unsafe fn archive_from_slice(
117        metadata_slice: &[u8],
118    ) -> Result<&ArchivedSerializableModule, DeserializeError> {
119        Ok(rkyv::access_unchecked(metadata_slice))
120    }
121
122    /// Deserialize an archived module.
123    ///
124    /// In contrast to [`Self::deserialize`], this method performs validation
125    /// and is not unsafe.
126    pub fn archive_from_slice_checked(
127        metadata_slice: &[u8],
128    ) -> Result<&ArchivedSerializableModule, DeserializeError> {
129        rkyv::access::<_, rkyv::rancor::Error>(metadata_slice)
130            .map_err(|e| DeserializeError::CorruptedBinary(e.to_string()))
131    }
132
133    /// Deserialize a compilation module from an archive
134    pub fn deserialize_from_archive(
135        archived: &ArchivedSerializableModule,
136    ) -> Result<Self, DeserializeError> {
137        rkyv::deserialize::<_, rkyv::rancor::Error>(archived)
138            .map_err(|e| DeserializeError::CorruptedBinary(e.to_string()))
139    }
140
141    /// Create a `ModuleInfo` for instantiation
142    pub fn create_module_info(&self) -> ModuleInfo {
143        self.compile_info.module.as_ref().clone()
144    }
145
146    /// Returns the `ModuleInfo` for instantiation
147    pub fn module_info(&self) -> &ModuleInfo {
148        &self.compile_info.module
149    }
150
151    /// Returns the features for this Artifact
152    pub fn features(&self) -> &Features {
153        &self.compile_info.features
154    }
155
156    /// Returns the CPU features for this Artifact
157    pub fn cpu_features(&self) -> EnumSet<CpuFeature> {
158        EnumSet::from_u64(self.cpu_features)
159    }
160
161    /// Returns data initializers to pass to `VMInstance::initialize`
162    pub fn data_initializers(&self) -> &[OwnedDataInitializer] {
163        &self.data_initializers
164    }
165
166    /// Returns the memory styles associated with this `Artifact`.
167    pub fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
168        &self.compile_info.memory_styles
169    }
170
171    /// Returns the table plans associated with this `Artifact`.
172    pub fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
173        &self.compile_info.table_styles
174    }
175}