1use crate::engine::{StaticlibEngine, StaticlibEngineInner};
5use crate::serialize::{ModuleMetadata, ModuleMetadataSymbolRegistry};
6use enumset::EnumSet;
7use loupe::MemoryUsage;
8use std::collections::BTreeMap;
9use std::error::Error;
10use std::mem;
11use std::sync::Arc;
12use wasmer_artifact::ArtifactCreate;
13use wasmer_compiler::{
14 CompileError, CpuFeature, Features, OperatingSystem, SymbolRegistry, Triple,
15};
16#[cfg(feature = "compiler")]
17use wasmer_compiler::{
18 CompileModuleInfo, Compiler, FunctionBodyData, ModuleEnvironment, ModuleMiddlewareChain,
19 ModuleTranslationState,
20};
21use wasmer_engine::{
22 Artifact, DeserializeError, InstantiationError, MetadataHeader, SerializeError,
23};
24#[cfg(feature = "compiler")]
25use wasmer_engine::{Engine, Tunables};
26#[cfg(feature = "compiler")]
27use wasmer_object::{emit_compilation, emit_data, get_object_for_target};
28use wasmer_types::entity::EntityRef;
29use wasmer_types::entity::{BoxedSlice, PrimaryMap};
30#[cfg(feature = "compiler")]
31use wasmer_types::DataInitializer;
32use wasmer_types::{
33 FunctionIndex, LocalFunctionIndex, MemoryIndex, ModuleInfo, OwnedDataInitializer,
34 SignatureIndex, TableIndex,
35};
36use wasmer_vm::{
37 FuncDataRegistry, FunctionBodyPtr, MemoryStyle, TableStyle, VMSharedSignatureIndex,
38 VMTrampoline,
39};
40
41#[derive(MemoryUsage)]
43pub struct StaticlibArtifact {
44 metadata: ModuleMetadata,
45 module_bytes: Vec<u8>,
46 finished_functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
47 #[loupe(skip)]
48 finished_function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
49 finished_dynamic_function_trampolines: BoxedSlice<FunctionIndex, FunctionBodyPtr>,
50 signatures: BoxedSlice<SignatureIndex, VMSharedSignatureIndex>,
51 func_data_registry: Arc<FuncDataRegistry>,
52 metadata_length: usize,
54 symbol_registry: ModuleMetadataSymbolRegistry,
55 is_compiled: bool,
56}
57
58#[allow(dead_code)]
59fn to_compile_error(err: impl Error) -> CompileError {
60 CompileError::Codegen(format!("{}", err))
61}
62
63#[allow(dead_code)]
64const WASMER_METADATA_SYMBOL: &[u8] = b"WASMER_METADATA";
65
66impl StaticlibArtifact {
67 #[allow(dead_code)]
69 const MAGIC_HEADER_MH_CIGAM_64: &'static [u8] = &[207, 250, 237, 254];
70
71 #[allow(dead_code)]
73 const MAGIC_HEADER_ELF_32: &'static [u8] = &[0x7f, b'E', b'L', b'F', 1];
74
75 #[allow(dead_code)]
77 const MAGIC_HEADER_ELF_64: &'static [u8] = &[0x7f, b'E', b'L', b'F', 2];
78
79 #[allow(dead_code)]
81 const MAGIC_HEADER_COFF_64: &'static [u8] = &[b'M', b'Z'];
82
83 pub fn is_deserializable(bytes: &[u8]) -> bool {
88 cfg_if::cfg_if! {
89 if #[cfg(all(target_pointer_width = "64", target_vendor="apple"))] {
90 bytes.starts_with(Self::MAGIC_HEADER_MH_CIGAM_64)
91 }
92 else if #[cfg(all(target_pointer_width = "64", target_os="linux"))] {
93 bytes.starts_with(Self::MAGIC_HEADER_ELF_64)
94 }
95 else if #[cfg(all(target_pointer_width = "32", target_os="linux"))] {
96 bytes.starts_with(Self::MAGIC_HEADER_ELF_32)
97 }
98 else if #[cfg(all(target_pointer_width = "64", target_os="windows"))] {
99 bytes.starts_with(Self::MAGIC_HEADER_COFF_64)
100 }
101 else {
102 false
103 }
104 }
105 }
106
107 #[cfg(feature = "compiler")]
108 fn generate_metadata<'data>(
110 data: &'data [u8],
111 features: &Features,
112 compiler: &dyn Compiler,
113 tunables: &dyn Tunables,
114 ) -> Result<
115 (
116 CompileModuleInfo,
117 PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
118 Vec<DataInitializer<'data>>,
119 Option<ModuleTranslationState>,
120 ),
121 CompileError,
122 > {
123 let environ = ModuleEnvironment::new();
124 let translation = environ.translate(data).map_err(CompileError::Wasm)?;
125
126 let mut module = translation.module;
128 let middlewares = compiler.get_middlewares();
129 middlewares.apply_on_module_info(&mut module);
130
131 let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
132 .memories
133 .values()
134 .map(|memory_type| tunables.memory_style(memory_type))
135 .collect();
136 let table_styles: PrimaryMap<TableIndex, TableStyle> = module
137 .tables
138 .values()
139 .map(|table_type| tunables.table_style(table_type))
140 .collect();
141
142 let compile_info = CompileModuleInfo {
143 module: Arc::new(module),
144 features: features.clone(),
145 memory_styles,
146 table_styles,
147 };
148 Ok((
149 compile_info,
150 translation.function_body_inputs,
151 translation.data_initializers,
152 translation.module_translation_state,
153 ))
154 }
155
156 #[cfg(feature = "compiler")]
159 pub fn new(
160 engine: &StaticlibEngine,
161 data: &[u8],
162 tunables: &dyn Tunables,
163 ) -> Result<Self, CompileError> {
164 let mut engine_inner = engine.inner_mut();
165 let target = engine.target();
166 let compiler = engine_inner.compiler()?;
167 let (compile_info, function_body_inputs, data_initializers, module_translation) =
168 Self::generate_metadata(data, engine_inner.features(), compiler, tunables)?;
169
170 let data_initializers = data_initializers
171 .iter()
172 .map(OwnedDataInitializer::new)
173 .collect::<Vec<_>>()
174 .into_boxed_slice();
175
176 let target_triple = target.triple();
177
178 let function_body_lengths = function_body_inputs
182 .keys()
183 .map(|_function_body| 0u64)
184 .collect::<PrimaryMap<LocalFunctionIndex, u64>>();
185
186 let mut metadata = ModuleMetadata {
187 compile_info,
188 prefix: engine_inner.get_prefix(&data),
189 data_initializers,
190 function_body_lengths,
191 cpu_features: target.cpu_features().as_u64(),
192 };
193
194 let serialized_data = bincode::serialize(&metadata).map_err(to_compile_error)?;
212 let mut metadata_binary = vec![];
213 metadata_binary.extend(MetadataHeader::new(serialized_data.len()));
214 metadata_binary.extend(serialized_data);
215 let metadata_length = metadata_binary.len();
216
217 let (compile_info, symbol_registry) = metadata.split();
218
219 let mut module = (*compile_info.module).clone();
220 let middlewares = compiler.get_middlewares();
221 middlewares.apply_on_module_info(&mut module);
222 compile_info.module = Arc::new(module);
223
224 let maybe_obj_bytes = compiler.experimental_native_compile_module(
225 &target,
226 &compile_info,
227 module_translation.as_ref().unwrap(),
228 &function_body_inputs,
229 &symbol_registry,
230 &metadata_binary,
231 );
232
233 let obj_bytes = if let Some(obj_bytes) = maybe_obj_bytes {
234 obj_bytes?
235 } else {
236 let compilation = compiler.compile_module(
237 &target,
238 &metadata.compile_info,
239 module_translation.as_ref().unwrap(),
240 function_body_inputs,
241 )?;
242 let mut obj = get_object_for_target(&target_triple).map_err(to_compile_error)?;
252 emit_data(&mut obj, WASMER_METADATA_SYMBOL, &metadata_binary, 1)
253 .map_err(to_compile_error)?;
254 emit_compilation(&mut obj, compilation, &symbol_registry, &target_triple)
255 .map_err(to_compile_error)?;
256 obj.write().map_err(to_compile_error)?
257 };
258
259 Self::from_parts_crosscompiled(&mut *engine_inner, metadata, obj_bytes, metadata_length)
260 }
261
262 pub fn get_default_extension(triple: &Triple) -> &'static str {
264 match triple.operating_system {
265 OperatingSystem::Windows => "obj",
266 _ => "o",
267 }
268 }
269
270 pub fn from_parts_crosscompiled(
272 engine_inner: &mut StaticlibEngineInner,
273 metadata: ModuleMetadata,
274 module_bytes: Vec<u8>,
275 metadata_length: usize,
276 ) -> Result<Self, CompileError> {
277 let finished_functions: PrimaryMap<LocalFunctionIndex, FunctionBodyPtr> = PrimaryMap::new();
278 let finished_function_call_trampolines: PrimaryMap<SignatureIndex, VMTrampoline> =
279 PrimaryMap::new();
280 let finished_dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBodyPtr> =
281 PrimaryMap::new();
282 let signature_registry = engine_inner.signatures();
283 let signatures = metadata
284 .compile_info
285 .module
286 .signatures
287 .values()
288 .map(|sig| signature_registry.register(sig))
289 .collect::<PrimaryMap<_, _>>();
290
291 let symbol_registry = metadata.get_symbol_registry();
292 Ok(Self {
293 metadata,
294 module_bytes,
295 finished_functions: finished_functions.into_boxed_slice(),
296 finished_function_call_trampolines: finished_function_call_trampolines
297 .into_boxed_slice(),
298 finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
299 .into_boxed_slice(),
300 signatures: signatures.into_boxed_slice(),
301 func_data_registry: engine_inner.func_data().clone(),
302 metadata_length,
303 symbol_registry,
304 is_compiled: true,
305 })
306 }
307
308 #[cfg(not(feature = "compiler"))]
310 pub fn new(_engine: &StaticlibEngine, _data: &[u8]) -> Result<Self, CompileError> {
311 Err(CompileError::Codegen(
312 "Compilation is not enabled in the engine".to_string(),
313 ))
314 }
315
316 pub unsafe fn deserialize(
322 engine: &StaticlibEngine,
323 bytes: &[u8],
324 ) -> Result<Self, DeserializeError> {
325 let metadata_len = MetadataHeader::parse(bytes)?;
326
327 let metadata: ModuleMetadata =
328 bincode::deserialize(&bytes[MetadataHeader::LEN..][..metadata_len]).unwrap();
329
330 const WORD_SIZE: usize = mem::size_of::<usize>();
331 let mut byte_buffer = [0u8; WORD_SIZE];
332
333 let mut cur_offset = MetadataHeader::LEN + metadata_len;
334 byte_buffer[0..WORD_SIZE].clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]);
335 cur_offset += WORD_SIZE;
336
337 let num_finished_functions = usize::from_ne_bytes(byte_buffer);
338 let mut finished_functions = PrimaryMap::new();
339
340 let engine_inner = engine.inner();
341 let signature_registry = engine_inner.signatures();
342 let func_data_registry = engine_inner.func_data().clone();
343 let mut sig_map: BTreeMap<SignatureIndex, VMSharedSignatureIndex> = BTreeMap::new();
344
345 let num_imported_functions = metadata.compile_info.module.num_imported_functions;
346 for i in 0..num_imported_functions {
348 let sig_idx = metadata.compile_info.module.functions[FunctionIndex::new(i)];
349 let func_type = &metadata.compile_info.module.signatures[sig_idx];
350 let vm_shared_idx = signature_registry.register(&func_type);
351 sig_map.insert(sig_idx, vm_shared_idx);
352 }
353 for i in 0..num_finished_functions {
355 let local_func_idx = LocalFunctionIndex::new(i);
356 let func_idx = metadata.compile_info.module.func_index(local_func_idx);
357 let sig_idx = metadata.compile_info.module.functions[func_idx];
358 let func_type = &metadata.compile_info.module.signatures[sig_idx];
359 let vm_shared_idx = signature_registry.register(&func_type);
360 sig_map.insert(sig_idx, vm_shared_idx);
361
362 byte_buffer[0..WORD_SIZE]
363 .clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]);
364 let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
365 cur_offset += WORD_SIZE;
366
367 finished_functions.push(fp);
370 }
371
372 let mut signatures: PrimaryMap<_, VMSharedSignatureIndex> = PrimaryMap::new();
373 for i in 0..(sig_map.len()) {
374 if let Some(shared_idx) = sig_map.get(&SignatureIndex::new(i)) {
375 signatures.push(*shared_idx);
376 } else {
377 panic!("Invalid data, missing sig idx; TODO: handle this error");
378 }
379 }
380
381 let mut finished_function_call_trampolines = PrimaryMap::new();
383 byte_buffer[0..WORD_SIZE].clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]);
384 cur_offset += WORD_SIZE;
385 let num_function_trampolines = usize::from_ne_bytes(byte_buffer);
386 for _ in 0..num_function_trampolines {
387 byte_buffer[0..WORD_SIZE]
388 .clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]);
389 cur_offset += WORD_SIZE;
390 let trampoline_ptr_bytes = usize::from_ne_bytes(byte_buffer);
391 let trampoline = mem::transmute::<usize, VMTrampoline>(trampoline_ptr_bytes);
392 finished_function_call_trampolines.push(trampoline);
393 }
395
396 let mut finished_dynamic_function_trampolines = PrimaryMap::new();
398 byte_buffer[0..WORD_SIZE].clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]);
399 cur_offset += WORD_SIZE;
400 let num_dynamic_trampoline_functions = usize::from_ne_bytes(byte_buffer);
401 for _i in 0..num_dynamic_trampoline_functions {
402 byte_buffer[0..WORD_SIZE]
403 .clone_from_slice(&bytes[cur_offset..(cur_offset + WORD_SIZE)]);
404 let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
405 cur_offset += WORD_SIZE;
406
407 finished_dynamic_function_trampolines.push(fp);
410 }
411
412 let symbol_registry = metadata.get_symbol_registry();
413 Ok(Self {
414 metadata,
415 module_bytes: bytes.to_owned(),
416 finished_functions: finished_functions.into_boxed_slice(),
417 finished_function_call_trampolines: finished_function_call_trampolines
418 .into_boxed_slice(),
419 finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
420 .into_boxed_slice(),
421 signatures: signatures.into_boxed_slice(),
422 func_data_registry,
423 metadata_length: 0,
424 symbol_registry,
425 is_compiled: false,
426 })
427 }
428
429 pub fn symbol_registry(&self) -> &dyn SymbolRegistry {
431 &self.symbol_registry
432 }
433
434 pub fn metadata_length(&self) -> usize {
436 self.metadata_length
437 }
438}
439
440impl ArtifactCreate for StaticlibArtifact {
441 fn module(&self) -> Arc<ModuleInfo> {
442 self.metadata.compile_info.module.clone()
443 }
444
445 fn module_ref(&self) -> &ModuleInfo {
446 &self.metadata.compile_info.module
447 }
448
449 fn module_mut(&mut self) -> Option<&mut ModuleInfo> {
450 Arc::get_mut(&mut self.metadata.compile_info.module)
451 }
452
453 fn features(&self) -> &Features {
454 &self.metadata.compile_info.features
455 }
456
457 fn cpu_features(&self) -> EnumSet<CpuFeature> {
458 EnumSet::from_u64(self.metadata.cpu_features)
459 }
460
461 fn data_initializers(&self) -> &[OwnedDataInitializer] {
462 &*self.metadata.data_initializers
463 }
464
465 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
466 &self.metadata.compile_info.memory_styles
467 }
468
469 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
470 &self.metadata.compile_info.table_styles
471 }
472
473 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
475 Ok(self.module_bytes.clone())
476 }
477}
478impl Artifact for StaticlibArtifact {
479 fn register_frame_info(&self) {
480 }
482
483 fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
484 &self.finished_functions
485 }
486
487 fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline> {
488 &self.finished_function_call_trampolines
489 }
490
491 fn finished_dynamic_function_trampolines(&self) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr> {
492 &self.finished_dynamic_function_trampolines
493 }
494
495 fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSharedSignatureIndex> {
496 &self.signatures
497 }
498
499 fn func_data_registry(&self) -> &FuncDataRegistry {
500 &self.func_data_registry
501 }
502 fn preinstantiate(&self) -> Result<(), InstantiationError> {
503 if self.is_compiled {
504 panic!(
505 "a module built with the staticlib engine must be linked \
506 into the current executable"
507 );
508 }
509 Ok(())
510 }
511}