1use crate::engine::{DylibEngine, DylibEngineInner};
5use crate::serialize::ModuleMetadata;
6use crate::trampoline::{emit_trampolines, fill_trampoline_table, WASMER_TRAMPOLINES_SYMBOL};
7use enumset::EnumSet;
8use libloading::{Library, Symbol as LibrarySymbol};
9use loupe::MemoryUsage;
10use object::{write::CoffExportStyle, BinaryFormat};
11use std::error::Error;
12use std::fs::{self, File};
13use std::io::{Read, Write};
14use std::path::{Path, PathBuf};
15#[cfg(feature = "compiler")]
16use std::process::Command;
17use std::sync::{Arc, Mutex};
18use tempfile::NamedTempFile;
19use tracing::log::error;
20#[cfg(feature = "compiler")]
21use tracing::trace;
22use wasmer_artifact::ArtifactCreate;
23use wasmer_compiler::{
24 Architecture, CompileError, CompiledFunctionFrameInfo, CpuFeature, Features,
25 FunctionAddressMap, OperatingSystem, Symbol, SymbolRegistry, Triple,
26};
27#[cfg(feature = "compiler")]
28use wasmer_compiler::{
29 CompileModuleInfo, Compiler, FunctionBodyData, ModuleEnvironment, ModuleMiddlewareChain,
30 ModuleTranslationState,
31};
32use wasmer_engine::{
33 register_frame_info, Artifact, DeserializeError, FunctionExtent, GlobalFrameInfoRegistration,
34 InstantiationError, MetadataHeader, SerializeError,
35};
36#[cfg(feature = "compiler")]
37use wasmer_engine::{Engine, Tunables};
38#[cfg(feature = "compiler")]
39use wasmer_object::{emit_compilation, emit_data, get_object_for_target};
40use wasmer_types::entity::{BoxedSlice, PrimaryMap};
41#[cfg(feature = "compiler")]
42use wasmer_types::DataInitializer;
43use wasmer_types::{
44 FunctionIndex, LocalFunctionIndex, MemoryIndex, ModuleInfo, OwnedDataInitializer,
45 SignatureIndex, TableIndex,
46};
47use wasmer_vm::{
48 FuncDataRegistry, FunctionBodyPtr, MemoryStyle, TableStyle, VMFunctionBody,
49 VMSharedSignatureIndex, VMTrampoline,
50};
51
52#[derive(MemoryUsage)]
54pub struct DylibArtifact {
55 dylib_path: PathBuf,
56 is_temporary: bool,
57 metadata: ModuleMetadata,
58 finished_functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
59 #[loupe(skip)]
60 finished_function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
61 finished_dynamic_function_trampolines: BoxedSlice<FunctionIndex, FunctionBodyPtr>,
62 func_data_registry: Arc<FuncDataRegistry>,
63 signatures: BoxedSlice<SignatureIndex, VMSharedSignatureIndex>,
64 frame_info_registration: Mutex<Option<GlobalFrameInfoRegistration>>,
65}
66
67impl Drop for DylibArtifact {
68 fn drop(&mut self) {
69 if self.is_temporary {
70 if let Err(err) = std::fs::remove_file(&self.dylib_path) {
71 error!("cannot delete the temporary dylib artifact: {}", err);
72 }
73 }
74 }
75}
76
77fn to_compile_error(err: impl Error) -> CompileError {
78 CompileError::Codegen(err.to_string())
79}
80
81const WASMER_METADATA_SYMBOL: &[u8] = b"WASMER_METADATA";
82
83impl DylibArtifact {
84 #[allow(dead_code)]
86 const MAGIC_HEADER_MH_CIGAM_64: &'static [u8] = &[207, 250, 237, 254];
87
88 #[allow(dead_code)]
90 const MAGIC_HEADER_ELF_32: &'static [u8] = &[0x7f, b'E', b'L', b'F', 1];
91
92 #[allow(dead_code)]
94 const MAGIC_HEADER_ELF_64: &'static [u8] = &[0x7f, b'E', b'L', b'F', 2];
95
96 #[allow(dead_code)]
98 const MAGIC_HEADER_COFF_64: &'static [u8] = &[b'M', b'Z'];
99
100 pub fn is_deserializable(bytes: &[u8]) -> bool {
105 cfg_if::cfg_if! {
106 if #[cfg(all(target_pointer_width = "64", target_vendor="apple"))] {
107 bytes.starts_with(Self::MAGIC_HEADER_MH_CIGAM_64)
108 }
109 else if #[cfg(all(target_pointer_width = "64", target_os="linux"))] {
110 bytes.starts_with(Self::MAGIC_HEADER_ELF_64)
111 }
112 else if #[cfg(all(target_pointer_width = "32", target_os="linux"))] {
113 bytes.starts_with(Self::MAGIC_HEADER_ELF_32)
114 }
115 else if #[cfg(all(target_pointer_width = "64", target_os="windows"))] {
116 bytes.starts_with(Self::MAGIC_HEADER_COFF_64)
117 }
118 else {
119 false
120 }
121 }
122 }
123
124 #[cfg(feature = "compiler")]
125 fn generate_metadata<'data>(
127 data: &'data [u8],
128 features: &Features,
129 compiler: &dyn Compiler,
130 tunables: &dyn Tunables,
131 ) -> Result<
132 (
133 CompileModuleInfo,
134 PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
135 Vec<DataInitializer<'data>>,
136 Option<ModuleTranslationState>,
137 ),
138 CompileError,
139 > {
140 let environ = ModuleEnvironment::new();
141 let translation = environ.translate(data).map_err(CompileError::Wasm)?;
142
143 let mut module = translation.module;
145 let middlewares = compiler.get_middlewares();
146 middlewares.apply_on_module_info(&mut module);
147
148 let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
149 .memories
150 .values()
151 .map(|memory_type| tunables.memory_style(memory_type))
152 .collect();
153 let table_styles: PrimaryMap<TableIndex, TableStyle> = module
154 .tables
155 .values()
156 .map(|table_type| tunables.table_style(table_type))
157 .collect();
158
159 let compile_info = CompileModuleInfo {
160 module: Arc::new(module),
161 features: features.clone(),
162 memory_styles,
163 table_styles,
164 };
165 Ok((
166 compile_info,
167 translation.function_body_inputs,
168 translation.data_initializers,
169 translation.module_translation_state,
170 ))
171 }
172
173 #[cfg(feature = "compiler")]
176 pub fn new(
177 engine: &DylibEngine,
178 data: &[u8],
179 tunables: &dyn Tunables,
180 ) -> Result<Self, CompileError> {
181 let mut engine_inner = engine.inner_mut();
182 let target = engine.target();
183 let compiler = engine_inner.compiler()?;
184 let (compile_info, function_body_inputs, data_initializers, module_translation) =
185 Self::generate_metadata(data, engine_inner.features(), compiler, tunables)?;
186
187 let data_initializers = data_initializers
188 .iter()
189 .map(OwnedDataInitializer::new)
190 .collect::<Vec<_>>()
191 .into_boxed_slice();
192
193 let target_triple = target.triple();
194
195 let function_body_lengths = function_body_inputs
209 .keys()
210 .map(|_function_body| 0u64)
211 .collect::<PrimaryMap<LocalFunctionIndex, u64>>();
212
213 let function_frame_info = None;
214
215 let mut metadata = ModuleMetadata {
216 compile_info,
217 function_frame_info,
218 prefix: engine_inner.get_prefix(data),
219 data_initializers,
220 function_body_lengths,
221 cpu_features: target.cpu_features().as_u64(),
222 };
223
224 let serialized_data = metadata.serialize()?;
225
226 let mut metadata_binary = vec![];
227 metadata_binary.extend(MetadataHeader::new(serialized_data.len()));
228 metadata_binary.extend(serialized_data);
229
230 let (compile_info, symbol_registry) = metadata.split();
231
232 let maybe_obj_bytes = compiler.experimental_native_compile_module(
233 target,
234 compile_info,
235 module_translation.as_ref().unwrap(),
236 &function_body_inputs,
237 &symbol_registry,
238 &metadata_binary,
239 );
240
241 let mut extra_filepath = None;
242 let filepath = match maybe_obj_bytes {
243 Some(obj_bytes) => {
244 extra_filepath = {
245 let mut obj = get_object_for_target(target_triple).map_err(to_compile_error)?;
247 emit_trampolines(&mut obj, engine.target());
248 if obj.format() == BinaryFormat::Coff {
249 obj.add_coff_exports(CoffExportStyle::Gnu);
250 }
251 let file = tempfile::Builder::new()
252 .prefix("wasmer_dylib_")
253 .suffix(".o")
254 .tempfile()
255 .map_err(to_compile_error)?;
256
257 let (mut file, filepath) = file.keep().map_err(to_compile_error)?;
259 let obj_bytes = obj.write().map_err(to_compile_error)?;
260 file.write_all(&obj_bytes).map_err(to_compile_error)?;
261 Some(filepath)
262 };
263
264 let obj_bytes = obj_bytes?;
266 let file = tempfile::Builder::new()
267 .prefix("wasmer_dylib_")
268 .suffix(".o")
269 .tempfile()
270 .map_err(to_compile_error)?;
271
272 let (mut file, filepath) = file.keep().map_err(to_compile_error)?;
274 file.write_all(&obj_bytes).map_err(to_compile_error)?;
275 filepath
276 }
277 None => {
278 let compilation = compiler.compile_module(
279 target,
280 compile_info,
281 module_translation.as_ref().unwrap(),
282 function_body_inputs,
283 )?;
284 let mut obj = get_object_for_target(target_triple).map_err(to_compile_error)?;
285 emit_trampolines(&mut obj, engine.target());
286 emit_data(
287 &mut obj,
288 WASMER_METADATA_SYMBOL,
289 &metadata_binary,
290 MetadataHeader::ALIGN as u64,
291 )
292 .map_err(to_compile_error)?;
293
294 let frame_info = compilation.get_frame_info();
295
296 emit_compilation(&mut obj, compilation, &symbol_registry, target_triple)
297 .map_err(to_compile_error)?;
298 if obj.format() == BinaryFormat::Coff {
299 obj.add_coff_exports(CoffExportStyle::Gnu);
300 }
301 let file = tempfile::Builder::new()
302 .prefix("wasmer_dylib_")
303 .suffix(".o")
304 .tempfile()
305 .map_err(to_compile_error)?;
306
307 metadata.function_frame_info = Some(frame_info);
308
309 let (mut file, filepath) = file.keep().map_err(to_compile_error)?;
311 let obj_bytes = obj.write().map_err(to_compile_error)?;
312
313 file.write_all(&obj_bytes).map_err(to_compile_error)?;
314 filepath
315 }
316 };
317
318 let output_filepath = {
319 let suffix = format!(".{}", Self::get_default_extension(target_triple));
320 let shared_file = tempfile::Builder::new()
321 .prefix("wasmer_dylib_")
322 .suffix(&suffix)
323 .tempfile()
324 .map_err(to_compile_error)?;
325 shared_file
326 .into_temp_path()
327 .keep()
328 .map_err(to_compile_error)?
329 };
330
331 let is_cross_compiling = engine_inner.is_cross_compiling();
332 let target_triple_str = {
333 let into_str = target_triple.to_string();
334 if into_str == "aarch64-apple-darwin" {
337 "arm64-apple-darwin".to_string()
338 } else {
339 into_str
340 }
341 };
342
343 let ios_compile_target = target_triple.operating_system == OperatingSystem::Ios;
345 let ios_sdk_flag = {
346 if ios_compile_target {
347 if target_triple.architecture == Architecture::X86_64 {
348 "-isysroot/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk"
349 } else {
350 "-isysroot/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk"
351 }
352 } else {
353 ""
354 }
355 };
356 let ios_sdk_lib = {
357 if ios_compile_target {
358 "-lSystem"
359 } else {
360 ""
361 }
362 };
363
364 let fuse_linker = {
366 let ld_install = which::which("ld");
367 if ios_compile_target && ld_install.is_ok() {
368 ld_install.unwrap().into_os_string().into_string().unwrap()
369 } else {
370 "lld".to_string()
371 }
372 };
373
374 let cross_compiling_args: Vec<String> = if is_cross_compiling {
375 vec![
376 format!("--target={}", target_triple_str),
377 format!("-fuse-ld={}", fuse_linker),
378 "-nodefaultlibs".to_string(),
379 "-nostdlib".to_string(),
380 ios_sdk_flag.to_string(),
381 ios_sdk_lib.to_string(),
382 ]
383 } else {
384 if target_triple_str == "arm64-apple-darwin" {
387 vec![format!("--target={}", target_triple_str)]
388 } else {
389 vec![]
390 }
391 };
392 let target_args = match (target_triple.operating_system, is_cross_compiling) {
393 (OperatingSystem::Windows, true) => vec!["-Wl,/force:unresolved,/noentry"],
394 (OperatingSystem::Windows, false) => vec!["-Wl,-undefined,dynamic_lookup"],
395 _ => vec!["-nostartfiles", "-Wl,-undefined,dynamic_lookup"],
396 };
397 trace!(
398 "Compiling for target {} from host {}",
399 target_triple_str,
400 Triple::host().to_string(),
401 );
402
403 let linker = engine_inner.linker().executable();
404 let output = Command::new(linker)
405 .arg(&filepath)
406 .args(&extra_filepath)
407 .arg("-o")
408 .arg(&output_filepath)
409 .args(&target_args)
410 .arg("-shared")
412 .args(&cross_compiling_args)
413 .arg("-v")
414 .output()
415 .map_err(to_compile_error);
416
417 if fs::metadata(&filepath).is_ok() {
418 fs::remove_file(filepath).map_err(to_compile_error)?;
419 }
420 if let Some(filepath) = extra_filepath {
421 if fs::metadata(&filepath).is_ok() {
422 fs::remove_file(filepath).map_err(to_compile_error)?;
423 }
424 }
425
426 let output = output?;
427
428 if !output.status.success() {
429 return Err(CompileError::Codegen(format!(
430 "Shared object file generator failed with:\nstderr:{}\nstdout:{}",
431 String::from_utf8_lossy(&output.stderr).trim_end(),
432 String::from_utf8_lossy(&output.stdout).trim_end()
433 )));
434 }
435
436 trace!("gcc command result {:?}", output);
437
438 let mut artifact = if is_cross_compiling {
439 Self::from_parts_crosscompiled(metadata, output_filepath)
440 } else {
441 let lib = unsafe { Library::new(&output_filepath).map_err(to_compile_error)? };
442 Self::from_parts(&mut engine_inner, metadata, output_filepath, lib)
443 }?;
444 artifact.is_temporary = true;
445
446 Ok(artifact)
447 }
448
449 pub fn get_default_extension(triple: &Triple) -> &'static str {
451 match triple.operating_system {
452 OperatingSystem::Windows => "dll",
453 OperatingSystem::Darwin | OperatingSystem::Ios | OperatingSystem::MacOSX { .. } => {
454 "dylib"
455 }
456 _ => "so",
457 }
458 }
459
460 pub fn from_parts_crosscompiled(
462 metadata: ModuleMetadata,
463 dylib_path: PathBuf,
464 ) -> Result<Self, CompileError> {
465 let finished_functions: PrimaryMap<LocalFunctionIndex, FunctionBodyPtr> = PrimaryMap::new();
466 let finished_function_call_trampolines: PrimaryMap<SignatureIndex, VMTrampoline> =
467 PrimaryMap::new();
468 let finished_dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBodyPtr> =
469 PrimaryMap::new();
470 let signatures: PrimaryMap<SignatureIndex, VMSharedSignatureIndex> = PrimaryMap::new();
471 Ok(Self {
472 dylib_path,
473 is_temporary: false,
474 metadata,
475 finished_functions: finished_functions.into_boxed_slice(),
476 finished_function_call_trampolines: finished_function_call_trampolines
477 .into_boxed_slice(),
478 finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
479 .into_boxed_slice(),
480 func_data_registry: Arc::new(FuncDataRegistry::new()),
481 signatures: signatures.into_boxed_slice(),
482 frame_info_registration: Mutex::new(None),
483 })
484 }
485
486 pub fn from_parts(
488 engine_inner: &mut DylibEngineInner,
489 metadata: ModuleMetadata,
490 dylib_path: PathBuf,
491 lib: Library,
492 ) -> Result<Self, CompileError> {
493 unsafe {
494 let trampolines_symbol: LibrarySymbol<usize> = lib
495 .get(WASMER_TRAMPOLINES_SYMBOL)
496 .expect("missing WASMER_TRAMPOLINES symbol");
497 fill_trampoline_table(trampolines_symbol.into_raw().into_raw() as *mut usize);
498 }
499
500 let mut finished_functions: PrimaryMap<LocalFunctionIndex, FunctionBodyPtr> =
501 PrimaryMap::new();
502 for (function_local_index, _function_len) in metadata.function_body_lengths.iter() {
503 let function_name = metadata
504 .get_symbol_registry()
505 .symbol_to_name(Symbol::LocalFunction(function_local_index));
506 unsafe {
507 let func: LibrarySymbol<unsafe extern "C" fn()> = lib
510 .get(function_name.as_bytes())
511 .map_err(to_compile_error)?;
512 finished_functions.push(FunctionBodyPtr(
513 func.into_raw().into_raw() as *const VMFunctionBody
514 ));
515 }
516 }
517
518 let mut finished_function_call_trampolines: PrimaryMap<SignatureIndex, VMTrampoline> =
520 PrimaryMap::with_capacity(metadata.compile_info.module.signatures.len());
521 for sig_index in metadata.compile_info.module.signatures.keys() {
522 let function_name = metadata
523 .get_symbol_registry()
524 .symbol_to_name(Symbol::FunctionCallTrampoline(sig_index));
525 unsafe {
526 let trampoline: LibrarySymbol<VMTrampoline> = lib
527 .get(function_name.as_bytes())
528 .map_err(to_compile_error)?;
529 let raw = *trampoline.into_raw();
530 finished_function_call_trampolines.push(raw);
531 }
532 }
533
534 let mut finished_dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBodyPtr> =
536 PrimaryMap::with_capacity(metadata.compile_info.module.num_imported_functions);
537 for func_index in metadata
538 .compile_info
539 .module
540 .functions
541 .keys()
542 .take(metadata.compile_info.module.num_imported_functions)
543 {
544 let function_name = metadata
545 .get_symbol_registry()
546 .symbol_to_name(Symbol::DynamicFunctionTrampoline(func_index));
547 unsafe {
548 let trampoline: LibrarySymbol<unsafe extern "C" fn()> = lib
549 .get(function_name.as_bytes())
550 .map_err(to_compile_error)?;
551 finished_dynamic_function_trampolines.push(FunctionBodyPtr(
552 trampoline.into_raw().into_raw() as *const VMFunctionBody,
553 ));
554 }
555 }
556
557 let signatures = {
559 metadata
560 .compile_info
561 .module
562 .signatures
563 .values()
564 .map(|sig| engine_inner.signatures().register(sig))
565 .collect::<PrimaryMap<_, _>>()
566 };
567
568 engine_inner.add_library(lib);
569
570 Ok(Self {
571 dylib_path,
572 is_temporary: false,
573 metadata,
574 finished_functions: finished_functions.into_boxed_slice(),
575 finished_function_call_trampolines: finished_function_call_trampolines
576 .into_boxed_slice(),
577 finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
578 .into_boxed_slice(),
579 func_data_registry: engine_inner.func_data().clone(),
580 signatures: signatures.into_boxed_slice(),
581 frame_info_registration: Mutex::new(None),
582 })
583 }
584
585 #[cfg(not(feature = "compiler"))]
588 pub fn new(_engine: &DylibEngine, _data: &[u8]) -> Result<Self, CompileError> {
589 Err(CompileError::Codegen(
590 "Compilation is not enabled in the engine".to_string(),
591 ))
592 }
593
594 pub unsafe fn deserialize(
600 engine: &DylibEngine,
601 bytes: &[u8],
602 ) -> Result<Self, DeserializeError> {
603 if !Self::is_deserializable(bytes) {
604 return Err(DeserializeError::Incompatible(
605 "The provided bytes are not in any native format Wasmer can understand".to_string(),
606 ));
607 }
608 let named_file = NamedTempFile::new()?;
610 let (mut file, path) = named_file.keep().map_err(|e| e.error)?;
611 file.write_all(bytes)?;
612 let mut artifact = Self::deserialize_from_file_unchecked(engine, &path)?;
615 artifact.is_temporary = true;
616
617 Ok(artifact)
618 }
619
620 pub unsafe fn deserialize_from_file(
626 engine: &DylibEngine,
627 path: &Path,
628 ) -> Result<Self, DeserializeError> {
629 let mut file = File::open(&path)?;
630 let mut buffer = [0; 5];
631 file.read_exact(&mut buffer)?;
633 if !Self::is_deserializable(&buffer) {
634 return Err(DeserializeError::Incompatible(
635 "The provided bytes are not in any native format Wasmer can understand".to_string(),
636 ));
637 }
638 Self::deserialize_from_file_unchecked(engine, path)
639 }
640
641 pub unsafe fn deserialize_from_file_unchecked(
647 engine: &DylibEngine,
648 path: &Path,
649 ) -> Result<Self, DeserializeError> {
650 let lib = Library::new(&path).map_err(|e| {
651 DeserializeError::CorruptedBinary(format!("Library loading failed: {}", e))
652 })?;
653 let shared_path: PathBuf = PathBuf::from(path);
654 let metadata_symbol: LibrarySymbol<*mut [u8; MetadataHeader::LEN]> =
655 lib.get(WASMER_METADATA_SYMBOL).map_err(|e| {
656 DeserializeError::CorruptedBinary(format!(
657 "The provided object file doesn't seem to be generated by Wasmer: {}",
658 e
659 ))
660 })?;
661 use std::slice;
662
663 let metadata = &**metadata_symbol;
664 let metadata_len = MetadataHeader::parse(metadata)?;
665 let metadata_slice: &'static [u8] =
666 slice::from_raw_parts(metadata.as_ptr().add(MetadataHeader::LEN), metadata_len);
667
668 let metadata = ModuleMetadata::deserialize(metadata_slice)?;
669
670 let mut engine_inner = engine.inner_mut();
671
672 Self::from_parts(&mut engine_inner, metadata, shared_path, lib)
673 .map_err(DeserializeError::Compiler)
674 }
675
676 pub fn metadata(&self) -> &ModuleMetadata {
678 &self.metadata
679 }
680}
681
682impl ArtifactCreate for DylibArtifact {
683 fn module(&self) -> Arc<ModuleInfo> {
684 self.metadata.compile_info.module.clone()
685 }
686
687 fn module_ref(&self) -> &ModuleInfo {
688 &self.metadata.compile_info.module
689 }
690
691 fn module_mut(&mut self) -> Option<&mut ModuleInfo> {
692 Arc::get_mut(&mut self.metadata.compile_info.module)
693 }
694
695 fn features(&self) -> &Features {
696 &self.metadata.compile_info.features
697 }
698
699 fn cpu_features(&self) -> enumset::EnumSet<CpuFeature> {
700 EnumSet::from_u64(self.metadata.cpu_features)
701 }
702
703 fn data_initializers(&self) -> &[OwnedDataInitializer] {
704 &*self.metadata.data_initializers
705 }
706
707 fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
708 &self.metadata.compile_info.memory_styles
709 }
710
711 fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
712 &self.metadata.compile_info.table_styles
713 }
714
715 fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
717 Ok(std::fs::read(&self.dylib_path)?)
718 }
719
720 #[cfg(feature = "compiler")]
722 fn serialize_to_file(&self, path: &Path) -> Result<(), SerializeError> {
723 let serialized = self.serialize()?;
724 std::fs::write(&path, serialized)?;
725
726 let has_extension = path.extension().is_some();
738 if has_extension && path.extension().unwrap() == "dylib" {
739 let filename = path.file_name().unwrap().to_str().unwrap();
740 let parent_dir = path.parent().unwrap();
741 let absolute_path = std::fs::canonicalize(&parent_dir)
742 .unwrap()
743 .into_os_string()
744 .into_string()
745 .unwrap();
746
747 Command::new("install_name_tool")
748 .arg("-id")
749 .arg(format!("@executable_path/{}", &filename))
750 .arg(&filename)
751 .current_dir(&absolute_path)
752 .output()?;
753 }
754
755 Ok(())
756 }
757}
758impl Artifact for DylibArtifact {
759 fn register_frame_info(&self) {
760 let mut info = self.frame_info_registration.lock().unwrap();
761
762 if info.is_some() {
763 return;
764 }
765
766 let min_call_trampolines_pointer = self
772 .finished_function_call_trampolines
773 .values()
774 .map(|t| *t as usize)
775 .min()
776 .unwrap_or(0);
777 let min_dynamic_trampolines_pointer = self
778 .finished_dynamic_function_trampolines
779 .values()
780 .map(|t| **t as usize)
781 .min()
782 .unwrap_or(0);
783
784 let fp = self.finished_functions.clone();
785 let mut function_pointers = fp.into_iter().collect::<Vec<_>>();
786
787 function_pointers.sort_by(|(_k1, v1), (_k2, v2)| v2.cmp(v1));
790 let mut iter = function_pointers.into_iter();
791 let mut function_pointers = iter
792 .next()
793 .map(|(index, function_pointer)| {
794 let fp = **function_pointer as usize;
795 let current_size_by_ptr = if fp < min_call_trampolines_pointer {
799 if min_call_trampolines_pointer < min_dynamic_trampolines_pointer
800 || min_dynamic_trampolines_pointer == 0
801 {
802 min_call_trampolines_pointer - fp
803 } else {
804 min_dynamic_trampolines_pointer - fp
805 }
806 } else if fp < min_dynamic_trampolines_pointer {
807 min_dynamic_trampolines_pointer - fp
808 } else {
809 16
816 };
817 let mut prev_pointer = fp;
818 let ptr = function_pointer;
821 let length = current_size_by_ptr;
822 let first = (
823 index,
824 FunctionExtent {
825 ptr: *ptr,
826 length: length,
827 },
828 );
829 std::iter::once(first)
830 .chain(iter.map(|(index, function_pointer)| {
831 let fp = **function_pointer as usize;
832 let current_size_by_ptr = prev_pointer - fp;
840
841 prev_pointer = fp;
842 let ptr = function_pointer;
845 let length = current_size_by_ptr;
846 (
847 index,
848 FunctionExtent {
849 ptr: *ptr,
850 length: length,
851 },
852 )
853 }))
854 .collect::<Vec<_>>()
855 })
856 .unwrap_or_default();
857
858 function_pointers.sort_by(|(k1, _v1), (k2, _v2)| k1.cmp(k2));
860
861 let frame_infos = if self.metadata().function_frame_info.is_some() {
862 self.metadata().function_frame_info.clone().unwrap()
863 } else {
864 function_pointers
865 .iter()
866 .map(|(_, extent)| CompiledFunctionFrameInfo {
867 traps: vec![],
868 address_map: FunctionAddressMap {
869 body_len: extent.length,
870 ..Default::default()
871 },
872 })
873 .collect::<PrimaryMap<LocalFunctionIndex, _>>()
874 };
875
876 let finished_function_extents = function_pointers
877 .into_iter()
878 .map(|(_, function_extent)| function_extent)
879 .collect::<PrimaryMap<LocalFunctionIndex, _>>()
880 .into_boxed_slice();
881
882 *info = register_frame_info(
883 self.metadata.compile_info.module.clone(),
884 &finished_function_extents,
885 frame_infos,
886 );
887 }
888
889 fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
890 &self.finished_functions
891 }
892
893 fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline> {
894 &self.finished_function_call_trampolines
895 }
896
897 fn finished_dynamic_function_trampolines(&self) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr> {
898 &self.finished_dynamic_function_trampolines
899 }
900
901 fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSharedSignatureIndex> {
902 &self.signatures
903 }
904
905 fn func_data_registry(&self) -> &FuncDataRegistry {
906 &self.func_data_registry
907 }
908
909 fn preinstantiate(&self) -> Result<(), InstantiationError> {
910 Ok(())
911 }
912}