wasmer_engine_object_file/
artifact.rs1use crate::engine::{ObjectFileEngine, ObjectFileEngineInner};
5use crate::serialize::{ModuleMetadata, ModuleMetadataSymbolRegistry};
6use std::collections::BTreeMap;
7use std::error::Error;
8use std::mem;
9use std::sync::Arc;
10use wasmer_compiler::{CompileError, Features, OperatingSystem, SymbolRegistry, Triple};
11#[cfg(feature = "compiler")]
12use wasmer_compiler::{
13 CompileModuleInfo, FunctionBodyData, ModuleEnvironment, ModuleTranslationState,
14};
15use wasmer_engine::{Artifact, DeserializeError, InstantiationError, SerializeError};
16#[cfg(feature = "compiler")]
17use wasmer_engine::{Engine, Tunables};
18#[cfg(feature = "compiler")]
19use wasmer_object::{emit_compilation, emit_data, get_object_for_target};
20use wasmer_types::entity::EntityRef;
21use wasmer_types::entity::{BoxedSlice, PrimaryMap};
22#[cfg(feature = "compiler")]
23use wasmer_types::DataInitializer;
24use wasmer_types::{
25 FunctionIndex, LocalFunctionIndex, MemoryIndex, OwnedDataInitializer, SignatureIndex,
26 TableIndex,
27};
28use wasmer_vm::{
29 FunctionBodyPtr, MemoryStyle, ModuleInfo, TableStyle, VMSharedSignatureIndex, VMTrampoline,
30};
31
32pub struct ObjectFileArtifact {
34 metadata: ModuleMetadata,
35 module_bytes: Vec<u8>,
36 finished_functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
37 finished_function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
38 finished_dynamic_function_trampolines: BoxedSlice<FunctionIndex, FunctionBodyPtr>,
39 signatures: BoxedSlice<SignatureIndex, VMSharedSignatureIndex>,
40 metadata_length: usize,
42 symbol_registry: ModuleMetadataSymbolRegistry,
43}
44
45#[allow(dead_code)]
46fn to_compile_error(err: impl Error) -> CompileError {
47 CompileError::Codegen(format!("{}", err))
48}
49
50#[allow(dead_code)]
51const WASMER_METADATA_SYMBOL: &[u8] = b"WASMER_METADATA";
52
53impl ObjectFileArtifact {
54 #[allow(dead_code)]
56 const MAGIC_HEADER_MH_CIGAM_64: &'static [u8] = &[207, 250, 237, 254];
57
58 #[allow(dead_code)]
60 const MAGIC_HEADER_ELF_32: &'static [u8] = &[0x7f, b'E', b'L', b'F', 1];
61
62 #[allow(dead_code)]
64 const MAGIC_HEADER_ELF_64: &'static [u8] = &[0x7f, b'E', b'L', b'F', 2];
65
66 #[allow(dead_code)]
68 const MAGIC_HEADER_COFF_64: &'static [u8] = &[b'M', b'Z'];
69
70 pub fn is_deserializable(bytes: &[u8]) -> bool {
75 cfg_if::cfg_if! {
76 if #[cfg(all(target_pointer_width = "64", target_os="macos"))] {
77 bytes.starts_with(Self::MAGIC_HEADER_MH_CIGAM_64)
78 }
79 else if #[cfg(all(target_pointer_width = "64", target_os="linux"))] {
80 bytes.starts_with(Self::MAGIC_HEADER_ELF_64)
81 }
82 else if #[cfg(all(target_pointer_width = "32", target_os="linux"))] {
83 bytes.starts_with(Self::MAGIC_HEADER_ELF_32)
84 }
85 else if #[cfg(all(target_pointer_width = "64", target_os="windows"))] {
86 bytes.starts_with(Self::MAGIC_HEADER_COFF_64)
87 }
88 else {
89 false
90 }
91 }
92 }
93
94 #[cfg(feature = "compiler")]
95 fn generate_metadata<'data>(
97 data: &'data [u8],
98 features: &Features,
99 tunables: &dyn Tunables,
100 ) -> Result<
101 (
102 CompileModuleInfo,
103 PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
104 Vec<DataInitializer<'data>>,
105 Option<ModuleTranslationState>,
106 ),
107 CompileError,
108 > {
109 let environ = ModuleEnvironment::new();
110 let translation = environ.translate(data).map_err(CompileError::Wasm)?;
111 let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = translation
112 .module
113 .memories
114 .values()
115 .map(|memory_type| tunables.memory_style(memory_type))
116 .collect();
117 let table_styles: PrimaryMap<TableIndex, TableStyle> = translation
118 .module
119 .tables
120 .values()
121 .map(|table_type| tunables.table_style(table_type))
122 .collect();
123 let compile_info = CompileModuleInfo {
124 module: Arc::new(translation.module),
125 features: features.clone(),
126 memory_styles,
127 table_styles,
128 };
129
130 Ok((
131 compile_info,
132 translation.function_body_inputs,
133 translation.data_initializers,
134 translation.module_translation_state,
135 ))
136 }
137
138 #[cfg(feature = "compiler")]
141 pub fn new(
142 engine: &ObjectFileEngine,
143 data: &[u8],
144 tunables: &dyn Tunables,
145 ) -> Result<Self, CompileError> {
146 let mut engine_inner = engine.inner_mut();
147 let target = engine.target();
148 let compiler = engine_inner.compiler()?;
149 let (compile_info, function_body_inputs, data_initializers, module_translation) =
150 Self::generate_metadata(data, engine_inner.features(), tunables)?;
151
152 let data_initializers = data_initializers
153 .iter()
154 .map(OwnedDataInitializer::new)
155 .collect::<Vec<_>>()
156 .into_boxed_slice();
157
158 let target_triple = target.triple();
159
160 let function_body_lengths = function_body_inputs
164 .keys()
165 .map(|_function_body| 0u64)
166 .collect::<PrimaryMap<LocalFunctionIndex, u64>>();
167
168 let mut metadata = ModuleMetadata {
169 compile_info,
170 prefix: engine_inner.get_prefix(&data),
171 data_initializers,
172 function_body_lengths,
173 };
174
175 let serialized_data = bincode::serialize(&metadata).map_err(to_compile_error)?;
193 let mut metadata_binary = vec![0; 10];
194 let mut writable = &mut metadata_binary[..];
195 leb128::write::unsigned(&mut writable, serialized_data.len() as u64)
196 .expect("Should write number");
197 metadata_binary.extend(serialized_data);
198 let metadata_length = metadata_binary.len();
199
200 let (compile_info, symbol_registry) = metadata.split();
201 let maybe_obj_bytes = compiler.experimental_native_compile_module(
202 &target,
203 compile_info,
204 module_translation.as_ref().unwrap(),
205 &function_body_inputs,
206 &symbol_registry,
207 &metadata_binary,
208 );
209
210 let obj_bytes = if let Some(obj_bytes) = maybe_obj_bytes {
211 obj_bytes?
212 } else {
213 let compilation = compiler.compile_module(
214 &target,
215 &mut metadata.compile_info,
216 module_translation.as_ref().unwrap(),
217 function_body_inputs,
218 )?;
219 let mut obj = get_object_for_target(&target_triple).map_err(to_compile_error)?;
229 emit_data(&mut obj, WASMER_METADATA_SYMBOL, &metadata_binary)
230 .map_err(to_compile_error)?;
231 emit_compilation(&mut obj, compilation, &symbol_registry, &target_triple)
232 .map_err(to_compile_error)?;
233 obj.write().map_err(to_compile_error)?
234 };
235
236 Self::from_parts_crosscompiled(&mut *engine_inner, metadata, obj_bytes, metadata_length)
237 }
238
239 pub fn get_default_extension(triple: &Triple) -> &'static str {
241 match triple.operating_system {
242 OperatingSystem::Windows => "obj",
243 _ => "o",
244 }
245 }
246
247 pub fn from_parts_crosscompiled(
249 engine_inner: &mut ObjectFileEngineInner,
250 metadata: ModuleMetadata,
251 module_bytes: Vec<u8>,
252 metadata_length: usize,
253 ) -> Result<Self, CompileError> {
254 let finished_functions: PrimaryMap<LocalFunctionIndex, FunctionBodyPtr> = PrimaryMap::new();
255 let finished_function_call_trampolines: PrimaryMap<SignatureIndex, VMTrampoline> =
256 PrimaryMap::new();
257 let finished_dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBodyPtr> =
258 PrimaryMap::new();
259 let signature_registry = engine_inner.signatures();
260 let signatures = metadata
261 .compile_info
262 .module
263 .signatures
264 .values()
265 .map(|sig| signature_registry.register(sig))
266 .collect::<PrimaryMap<_, _>>();
267
268 let symbol_registry = metadata.get_symbol_registry();
269 Ok(Self {
270 metadata,
271 module_bytes,
272 finished_functions: finished_functions.into_boxed_slice(),
273 finished_function_call_trampolines: finished_function_call_trampolines
274 .into_boxed_slice(),
275 finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
276 .into_boxed_slice(),
277 signatures: signatures.into_boxed_slice(),
278 metadata_length,
279 symbol_registry,
280 })
281 }
282
283 #[cfg(not(feature = "compiler"))]
285 pub fn new(_engine: &ObjectFileEngine, _data: &[u8]) -> Result<Self, CompileError> {
286 Err(CompileError::Codegen(
287 "Compilation is not enabled in the engine".to_string(),
288 ))
289 }
290
291 pub unsafe fn deserialize(
297 engine: &ObjectFileEngine,
298 bytes: &[u8],
299 ) -> Result<Self, DeserializeError> {
300 let mut reader = bytes;
301 let data_len = leb128::read::unsigned(&mut reader).unwrap() as usize;
302
303 let metadata: ModuleMetadata = bincode::deserialize(&bytes[10..(data_len + 10)]).unwrap();
304
305 const WORD_SIZE: usize = mem::size_of::<usize>();
306 let mut byte_buffer = [0u8; WORD_SIZE];
307
308 let mut cur_offset = data_len + 10;
309 byte_buffer[0..WORD_SIZE].clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]);
310 cur_offset += WORD_SIZE;
311
312 let num_finished_functions = usize::from_ne_bytes(byte_buffer);
313 let mut finished_functions = PrimaryMap::new();
314
315 let engine_inner = engine.inner();
316 let signature_registry = engine_inner.signatures();
317 let mut sig_map: BTreeMap<SignatureIndex, VMSharedSignatureIndex> = BTreeMap::new();
318
319 for i in 0..num_finished_functions {
321 let sig_idx = metadata.compile_info.module.functions[FunctionIndex::new(i)];
322 let func_type = &metadata.compile_info.module.signatures[sig_idx];
323 let vm_shared_idx = signature_registry.register(&func_type);
324 sig_map.insert(sig_idx, vm_shared_idx);
325
326 byte_buffer[0..WORD_SIZE]
327 .clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]);
328 let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
329 cur_offset += WORD_SIZE;
330
331 finished_functions.push(fp);
334 }
335
336 let mut signatures: PrimaryMap<_, VMSharedSignatureIndex> = PrimaryMap::new();
337 for i in 0..(sig_map.len()) {
338 if let Some(shared_idx) = sig_map.get(&SignatureIndex::new(i)) {
339 signatures.push(*shared_idx);
340 } else {
341 panic!("Invalid data, missing sig idx; TODO: handle this error");
342 }
343 }
344
345 let mut finished_function_call_trampolines = PrimaryMap::new();
347 byte_buffer[0..WORD_SIZE].clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]);
348 cur_offset += WORD_SIZE;
349 let num_function_trampolines = usize::from_ne_bytes(byte_buffer);
350 for _ in 0..num_function_trampolines {
351 byte_buffer[0..WORD_SIZE]
352 .clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]);
353 cur_offset += WORD_SIZE;
354 let trampoline_ptr_bytes = usize::from_ne_bytes(byte_buffer);
355 let trampoline = mem::transmute::<usize, VMTrampoline>(trampoline_ptr_bytes);
356 finished_function_call_trampolines.push(trampoline);
357 }
359
360 let mut finished_dynamic_function_trampolines = PrimaryMap::new();
362 byte_buffer[0..WORD_SIZE].clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]);
363 cur_offset += WORD_SIZE;
364 let num_dynamic_trampoline_functions = usize::from_ne_bytes(byte_buffer);
365 for _i in 0..num_dynamic_trampoline_functions {
366 byte_buffer[0..WORD_SIZE]
367 .clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]);
368 let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
369 cur_offset += WORD_SIZE;
370
371 finished_dynamic_function_trampolines.push(fp);
374 }
375
376 let symbol_registry = metadata.get_symbol_registry();
377 Ok(Self {
378 metadata,
379 module_bytes: bytes.to_owned(),
380 finished_functions: finished_functions.into_boxed_slice(),
381 finished_function_call_trampolines: finished_function_call_trampolines
382 .into_boxed_slice(),
383 finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
384 .into_boxed_slice(),
385 signatures: signatures.into_boxed_slice(),
386 metadata_length: 0,
387 symbol_registry,
388 })
389 }
390
391 pub fn symbol_registry(&self) -> &dyn SymbolRegistry {
393 &self.symbol_registry
394 }
395
396 pub fn metadata_length(&self) -> usize {
398 self.metadata_length
399 }
400}
401
402impl Artifact for ObjectFileArtifact {
403 fn module(&self) -> Arc<ModuleInfo> {
404 self.metadata.compile_info.module.clone()
405 }
406
407 fn module_ref(&self) -> &ModuleInfo {
408 &self.metadata.compile_info.module
409 }
410
411 fn module_mut(&mut self) -> Option<&mut ModuleInfo> {
412 Arc::get_mut(&mut self.metadata.compile_info.module)
413 }
414
415 fn register_frame_info(&self) {
416 }
418
419 fn features(&self) -> &Features {
420 &self.metadata.compile_info.features
421 }
422
423 fn data_initializers(&self) -> &[OwnedDataInitializer] {
424 &*self.metadata.data_initializers
425 }
426
427 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
428 &self.metadata.compile_info.memory_styles
429 }
430
431 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
432 &self.metadata.compile_info.table_styles
433 }
434
435 fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
436 &self.finished_functions
437 }
438
439 fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline> {
440 &self.finished_function_call_trampolines
441 }
442
443 fn finished_dynamic_function_trampolines(&self) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr> {
444 &self.finished_dynamic_function_trampolines
445 }
446
447 fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSharedSignatureIndex> {
448 &self.signatures
449 }
450
451 fn preinstantiate(&self) -> Result<(), InstantiationError> {
452 Ok(())
453 }
454
455 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
457 Ok(self.module_bytes.clone())
458 }
459}