1use crate::entity::PrimaryMap;
2use crate::{
3 compilation::target::CpuFeature, CompileModuleInfo, CompiledFunctionFrameInfo, CustomSection,
4 DeserializeError, Dwarf, Features, FunctionBody, FunctionIndex, LocalFunctionIndex,
5 MemoryIndex, MemoryStyle, ModuleInfo, OwnedDataInitializer, Relocation, SectionIndex,
6 SerializeError, SignatureIndex, TableIndex, TableStyle,
7};
8use enumset::EnumSet;
9use rkyv::check_archived_value;
10use rkyv::{
11 archived_value, de::deserializers::SharedDeserializeMap, ser::serializers::AllocSerializer,
12 ser::Serializer as RkyvSerializer, Archive, CheckBytes, Deserialize as RkyvDeserialize,
13 Serialize as RkyvSerialize,
14};
15use std::convert::TryInto;
16use std::mem;
17
18#[derive(Archive, Default, RkyvDeserialize, RkyvSerialize)]
20#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
21#[allow(missing_docs)]
22#[archive_attr(derive(CheckBytes, Debug))]
23pub struct SerializableCompilation {
24 pub function_bodies: PrimaryMap<LocalFunctionIndex, FunctionBody>,
25 pub function_relocations: PrimaryMap<LocalFunctionIndex, Vec<Relocation>>,
26 pub function_frame_info: PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>,
27 pub function_call_trampolines: PrimaryMap<SignatureIndex, FunctionBody>,
28 pub dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBody>,
29 pub custom_sections: PrimaryMap<SectionIndex, CustomSection>,
30 pub custom_section_relocations: PrimaryMap<SectionIndex, Vec<Relocation>>,
31 pub debug: Option<Dwarf>,
33 pub libcall_trampolines: SectionIndex,
35 pub libcall_trampoline_len: u32,
37}
38
39impl SerializableCompilation {
40 pub fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
44 let mut serializer = AllocSerializer::<4096>::default();
45 let pos = serializer
46 .serialize_value(self)
47 .map_err(to_serialize_error)? as u64;
48 let mut serialized_data = serializer.into_serializer().into_inner();
49 serialized_data.extend_from_slice(&pos.to_le_bytes());
50 Ok(serialized_data.to_vec())
51 }
52}
53
54#[derive(Archive, RkyvDeserialize, RkyvSerialize)]
56#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
57#[allow(missing_docs)]
58#[archive_attr(derive(CheckBytes, Debug))]
59pub struct SerializableModule {
60 pub compilation: SerializableCompilation,
62 pub compile_info: CompileModuleInfo,
64 pub data_initializers: Box<[OwnedDataInitializer]>,
66 pub cpu_features: u64,
68}
69
70fn to_serialize_error(err: impl std::error::Error) -> SerializeError {
71 SerializeError::Generic(format!("{}", err))
72}
73
74impl SerializableModule {
75 pub fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
79 let mut serializer = AllocSerializer::<4096>::default();
80 let pos = serializer
81 .serialize_value(self)
82 .map_err(to_serialize_error)? as u64;
83 let mut serialized_data = serializer.into_serializer().into_inner();
84 serialized_data.extend_from_slice(&pos.to_le_bytes());
85 Ok(serialized_data.to_vec())
86 }
87
88 pub unsafe fn deserialize_unchecked(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
100 let archived = Self::archive_from_slice(metadata_slice)?;
101 Self::deserialize_from_archive(archived)
102 }
103
104 pub unsafe fn deserialize(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
114 let archived = Self::archive_from_slice_checked(metadata_slice)?;
115 Self::deserialize_from_archive(archived)
116 }
117
118 pub unsafe fn archive_from_slice(
123 metadata_slice: &[u8],
124 ) -> Result<&ArchivedSerializableModule, DeserializeError> {
125 if metadata_slice.len() < 8 {
126 return Err(DeserializeError::Incompatible(
127 "invalid serialized data".into(),
128 ));
129 }
130 let mut pos: [u8; 8] = Default::default();
131 pos.copy_from_slice(&metadata_slice[metadata_slice.len() - 8..metadata_slice.len()]);
132 let pos: u64 = u64::from_le_bytes(pos);
133 Ok(archived_value::<Self>(
134 &metadata_slice[..metadata_slice.len() - 8],
135 pos as usize,
136 ))
137 }
138
139 pub fn archive_from_slice_checked(
144 metadata_slice: &[u8],
145 ) -> Result<&ArchivedSerializableModule, DeserializeError> {
146 if metadata_slice.len() < 8 {
147 return Err(DeserializeError::Incompatible(
148 "invalid serialized data".into(),
149 ));
150 }
151 let mut pos: [u8; 8] = Default::default();
152 pos.copy_from_slice(&metadata_slice[metadata_slice.len() - 8..metadata_slice.len()]);
153 let pos: u64 = u64::from_le_bytes(pos);
154 check_archived_value::<Self>(&metadata_slice[..metadata_slice.len() - 8], pos as usize)
155 .map_err(|err| DeserializeError::CorruptedBinary(err.to_string()))
156 }
157
158 pub fn deserialize_from_archive(
160 archived: &ArchivedSerializableModule,
161 ) -> Result<Self, DeserializeError> {
162 let mut deserializer = SharedDeserializeMap::new();
163 RkyvDeserialize::deserialize(archived, &mut deserializer)
164 .map_err(|e| DeserializeError::CorruptedBinary(format!("{:?}", e)))
165 }
166
167 pub fn create_module_info(&self) -> ModuleInfo {
169 self.compile_info.module.as_ref().clone()
170 }
171
172 pub fn module_info(&self) -> &ModuleInfo {
174 &self.compile_info.module
175 }
176
177 pub fn features(&self) -> &Features {
179 &self.compile_info.features
180 }
181
182 pub fn cpu_features(&self) -> EnumSet<CpuFeature> {
184 EnumSet::from_u64(self.cpu_features)
185 }
186
187 pub fn data_initializers(&self) -> &[OwnedDataInitializer] {
189 &self.data_initializers
190 }
191
192 pub fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
194 &self.compile_info.memory_styles
195 }
196
197 pub fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
199 &self.compile_info.table_styles
200 }
201}
202
203#[repr(C)]
206#[derive(Clone, Copy)]
207pub struct MetadataHeader {
208 magic: [u8; 8],
209 version: u32,
210 len: u32,
211}
212
213impl MetadataHeader {
214 pub const CURRENT_VERSION: u32 = 7;
217
218 const MAGIC: [u8; 8] = *b"WASMER\0\0";
220
221 pub const LEN: usize = 16;
223
224 pub const ALIGN: usize = 16;
226
227 pub fn new(len: usize) -> Self {
229 Self {
230 magic: Self::MAGIC,
231 version: Self::CURRENT_VERSION,
232 len: len.try_into().expect("metadata exceeds maximum length"),
233 }
234 }
235
236 pub fn into_bytes(self) -> [u8; 16] {
238 unsafe { mem::transmute(self) }
239 }
240
241 pub fn parse(bytes: &[u8]) -> Result<usize, DeserializeError> {
243 if bytes.as_ptr() as usize % 8 != 0 {
244 return Err(DeserializeError::CorruptedBinary(
245 "misaligned metadata".to_string(),
246 ));
247 }
248 let bytes: [u8; 16] = bytes
249 .get(..16)
250 .ok_or_else(|| {
251 DeserializeError::CorruptedBinary("invalid metadata header".to_string())
252 })?
253 .try_into()
254 .unwrap();
255 let header: Self = unsafe { mem::transmute(bytes) };
256 if header.magic != Self::MAGIC {
257 return Err(DeserializeError::Incompatible(
258 "The provided bytes were not serialized by Wasmer".to_string(),
259 ));
260 }
261 if header.version != Self::CURRENT_VERSION {
262 return Err(DeserializeError::Incompatible(
263 "The provided bytes were serialized by an incompatible version of Wasmer"
264 .to_string(),
265 ));
266 }
267 Ok(header.len as usize)
268 }
269}