1use std::sync::Arc;
2
3use enumset::EnumSet;
4use rkyv::de::deserializers::SharedDeserializeMap;
5use rkyv::ser::serializers::{
6 AllocScratchError, AllocSerializer, CompositeSerializerError, SharedSerializeMapError,
7};
8use wasmer_compiler::{
9 CompileError, CompileModuleInfo, CompiledFunctionFrameInfo, CpuFeature, CustomSection, Dwarf,
10 Features, FunctionBody, JumpTableOffsets, Relocation, SectionIndex, TrampolinesSection,
11};
12use wasmer_engine::{DeserializeError, Engine};
13use wasmer_types::entity::PrimaryMap;
14use wasmer_types::{
15 ExportIndex, FunctionIndex, ImportIndex, LocalFunctionIndex, OwnedDataInitializer,
16 SignatureIndex,
17};
18use wasmer_vm::Artifact;
19
20const MAGIC_HEADER: [u8; 32] = {
21 let value = *b"\0wasmer-universal\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
22 let _length_must_be_multiple_of_16: bool = [true][value.len() % 16];
23 value
24};
25
26#[derive(Clone, Copy)]
28pub struct UniversalExecutableRef<'a> {
29 buffer: &'a [u8],
30 archive: &'a ArchivedUniversalExecutable,
31}
32
33impl<'a> std::ops::Deref for UniversalExecutableRef<'a> {
34 type Target = ArchivedUniversalExecutable;
35 fn deref(&self) -> &Self::Target {
36 self.archive
37 }
38}
39
40impl<'a> UniversalExecutableRef<'a> {
41 pub fn verify_serialized(data: &[u8]) -> Result<(), &'static str> {
43 if !data.starts_with(&MAGIC_HEADER) {
44 return Err("the provided bytes are not wasmer-universal");
45 }
46 if data.len() < MAGIC_HEADER.len() + 8 {
47 return Err("the data buffer is too small to be valid");
48 }
49 let (remaining, position) = data.split_at(data.len() - 8);
50 let mut position_value = [0u8; 8];
51 position_value.copy_from_slice(position);
52 if u64::from_le_bytes(position_value) > remaining.len() as u64 {
53 return Err("the buffer is malformed");
54 }
55 Ok(())
57 }
58
59 pub unsafe fn deserialize(
67 data: &'a [u8],
68 ) -> Result<UniversalExecutableRef<'a>, DeserializeError> {
69 Self::verify_serialized(data).map_err(|e| DeserializeError::Incompatible(e.to_string()))?;
70 let (archive, position) = data.split_at(data.len() - 8);
71 let mut position_value = [0u8; 8];
72 position_value.copy_from_slice(position);
73 let (_, data) = archive.split_at(MAGIC_HEADER.len());
74 Ok(UniversalExecutableRef {
75 buffer: data,
76 archive: rkyv::archived_value::<UniversalExecutable>(
77 data,
78 u64::from_le_bytes(position_value) as usize,
79 ),
80 })
81 }
82
83 pub fn to_owned(self) -> Result<UniversalExecutable, DeserializeError> {
86 let mut deserializer = SharedDeserializeMap::new();
87 rkyv::Deserialize::deserialize(self.archive, &mut deserializer)
88 .map_err(|e| DeserializeError::CorruptedBinary(format!("{:?}", e)))
89 }
90}
91
92#[derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)]
98pub struct UniversalExecutable {
99 pub(crate) function_bodies: PrimaryMap<LocalFunctionIndex, FunctionBody>,
100 pub(crate) function_relocations: PrimaryMap<LocalFunctionIndex, Vec<Relocation>>,
101 pub(crate) function_jt_offsets: PrimaryMap<LocalFunctionIndex, JumpTableOffsets>,
102 pub(crate) function_frame_info: PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>,
103 pub(crate) function_call_trampolines: PrimaryMap<SignatureIndex, FunctionBody>,
104 pub(crate) dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBody>,
105 pub(crate) custom_sections: PrimaryMap<SectionIndex, CustomSection>,
106 pub(crate) custom_section_relocations: PrimaryMap<SectionIndex, Vec<Relocation>>,
107 pub(crate) debug: Option<Dwarf>,
109 pub(crate) trampolines: Option<TrampolinesSection>,
111 pub(crate) compile_info: CompileModuleInfo,
112 pub(crate) data_initializers: Vec<OwnedDataInitializer>,
113 pub(crate) cpu_features: u64,
114}
115
116#[derive(thiserror::Error, Debug)]
117pub enum ExecutableSerializeError {
118 #[error("could not serialize the executable data")]
119 Executable(
120 #[source]
121 CompositeSerializerError<
122 std::convert::Infallible,
123 AllocScratchError,
124 SharedSerializeMapError,
125 >,
126 ),
127}
128
129impl wasmer_engine::Executable for UniversalExecutable {
130 fn load(
131 &self,
132 engine: &(dyn Engine + 'static),
133 ) -> Result<std::sync::Arc<dyn Artifact>, CompileError> {
134 engine
135 .downcast_ref::<crate::UniversalEngine>()
136 .ok_or(CompileError::EngineDowncast)?
137 .load_universal_executable(self)
138 .map(|a| Arc::new(a) as _)
139 }
140
141 fn features(&self) -> Features {
142 self.compile_info.features.clone()
143 }
144
145 fn cpu_features(&self) -> EnumSet<CpuFeature> {
146 EnumSet::from_u64(self.cpu_features)
147 }
148
149 fn serialize(&self) -> Result<Vec<u8>, Box<(dyn std::error::Error + Send + Sync + 'static)>> {
150 let mut serializer = AllocSerializer::<1024>::default();
158 let pos = rkyv::ser::Serializer::serialize_value(&mut serializer, self)
159 .map_err(ExecutableSerializeError::Executable)? as u64;
160 let pos_bytes = pos.to_le_bytes();
161 let data = serializer.into_serializer().into_inner();
162 let mut out = Vec::with_capacity(MAGIC_HEADER.len() + pos_bytes.len() + data.len());
163 out.extend(&MAGIC_HEADER);
164 out.extend(data.as_slice());
165 out.extend(&pos_bytes);
166 Ok(out)
167 }
168
169 fn function_name(&self, index: FunctionIndex) -> Option<&str> {
170 let module = &self.compile_info.module;
171 for (name, idx) in module.exports.iter() {
173 match idx {
174 &ExportIndex::Function(fi) if fi == index => return Some(&*name),
175 _ => continue,
176 }
177 }
178 if let Some(r) = module.function_names.get(&index) {
179 return Some(&**r);
180 }
181 for ((_, field, _), idx) in module.imports.iter() {
182 match idx {
183 &ImportIndex::Function(fi) if fi == index => return Some(&*field),
184 _ => continue,
185 }
186 }
187 None
188 }
189}
190
191impl<'a> wasmer_engine::Executable for UniversalExecutableRef<'a> {
192 fn load(
193 &self,
194 engine: &(dyn Engine + 'static),
195 ) -> Result<std::sync::Arc<dyn Artifact>, CompileError> {
196 engine
197 .downcast_ref::<crate::UniversalEngine>()
198 .ok_or_else(|| CompileError::Codegen("can't downcast TODO FIXME".into()))?
199 .load_universal_executable_ref(self)
200 .map(|a| Arc::new(a) as _)
201 }
202
203 fn features(&self) -> Features {
204 unrkyv(&self.archive.compile_info.features)
205 }
206
207 fn cpu_features(&self) -> EnumSet<CpuFeature> {
208 EnumSet::from_u64(unrkyv(&self.archive.cpu_features))
209 }
210
211 fn serialize(&self) -> Result<Vec<u8>, Box<dyn std::error::Error + Send + Sync>> {
212 Ok(self.buffer.to_vec())
213 }
214
215 fn function_name(&self, index: FunctionIndex) -> Option<&str> {
216 let module = &self.compile_info.module;
217 for (name, idx) in module.exports.iter() {
219 match idx {
220 &ExportIndex::Function(fi) if fi == index => return Some(&*name),
221 _ => continue,
222 }
223 }
224 if let Some(r) = module.function_names.get(&index) {
225 return Some(&**r);
226 }
227 for ((_, field, _), idx) in module.imports.iter() {
228 match idx {
229 &ImportIndex::Function(fi) if fi == index => return Some(&*field),
230 _ => continue,
231 }
232 }
233 None
234 }
235}
236
237pub(crate) fn unrkyv<T>(archive: &T::Archived) -> T
238where
239 T: rkyv::Archive,
240 T::Archived: rkyv::Deserialize<T, rkyv::Infallible>,
241{
242 Result::<_, std::convert::Infallible>::unwrap(rkyv::Deserialize::deserialize(
243 archive,
244 &mut rkyv::Infallible,
245 ))
246}