wasmer_compiler/engine/
artifact.rs

1//! Define `Artifact`, based on `ArtifactBuild`
2//! to allow compiling and instantiating to be done as separate steps.
3
4use std::sync::{
5    Arc,
6    atomic::{AtomicUsize, Ordering::SeqCst},
7};
8
9#[cfg(feature = "compiler")]
10use crate::ModuleEnvironment;
11use crate::{
12    ArtifactBuild, ArtifactBuildFromArchive, ArtifactCreate, Engine, EngineInner, Features,
13    FrameInfosVariant, FunctionExtent, GlobalFrameInfoRegistration, InstantiationError, Tunables,
14    engine::{link::link_module, resolver::resolve_tags},
15    lib::std::vec::IntoIter,
16    register_frame_info, resolve_imports,
17    serialize::{MetadataHeader, SerializableModule},
18    types::relocation::{RelocationLike, RelocationTarget},
19};
20#[cfg(feature = "static-artifact-create")]
21use crate::{Compiler, FunctionBodyData, ModuleTranslationState, types::module::CompileModuleInfo};
22#[cfg(any(feature = "static-artifact-create", feature = "static-artifact-load"))]
23use crate::{serialize::SerializableCompilation, types::symbols::ModuleMetadata};
24
25use enumset::EnumSet;
26use shared_buffer::OwnedBuffer;
27
28#[cfg(any(feature = "static-artifact-create", feature = "static-artifact-load"))]
29use std::mem;
30
31#[cfg(feature = "static-artifact-create")]
32use crate::object::{
33    Object, ObjectMetadataBuilder, emit_compilation, emit_data, get_object_for_target,
34};
35
36use wasmer_types::{
37    ArchivedDataInitializerLocation, ArchivedOwnedDataInitializer, CompilationProgressCallback,
38    CompileError, DataInitializer, DataInitializerLike, DataInitializerLocation,
39    DataInitializerLocationLike, DeserializeError, FunctionIndex, LocalFunctionIndex, MemoryIndex,
40    ModuleInfo, OwnedDataInitializer, SerializeError, SignatureIndex, TableIndex,
41    entity::{BoxedSlice, PrimaryMap},
42    target::{CpuFeature, Target},
43};
44
45use wasmer_vm::{
46    FunctionBodyPtr, InstanceAllocator, MemoryStyle, StoreObjects, TableStyle, TrapHandlerFn,
47    VMConfig, VMExtern, VMInstance, VMSignatureHash, VMTrampoline,
48};
49
50#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
51pub struct AllocatedArtifact {
52    // This shows if the frame info has been registered already or not.
53    // Because the 'GlobalFrameInfoRegistration' ownership can be transferred to EngineInner
54    // this bool is needed to track the status, as 'frame_info_registration' will be None
55    // after the ownership is transferred.
56    frame_info_registered: bool,
57    // frame_info_registered is not staying there but transferred to CodeMemory from EngineInner
58    // using 'Artifact::take_frame_info_registration' method
59    // so the GloabelFrameInfo and MMap stays in sync and get dropped at the same time
60    frame_info_registration: Option<GlobalFrameInfoRegistration>,
61    finished_functions: BoxedSlice<LocalFunctionIndex, FunctionBodyPtr>,
62
63    #[cfg_attr(feature = "artifact-size", loupe(skip))]
64    finished_function_call_trampolines: BoxedSlice<SignatureIndex, VMTrampoline>,
65    finished_dynamic_function_trampolines: BoxedSlice<FunctionIndex, FunctionBodyPtr>,
66    signatures: BoxedSlice<SignatureIndex, VMSignatureHash>,
67    finished_function_lengths: BoxedSlice<LocalFunctionIndex, usize>,
68}
69
70#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
71#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
72#[repr(transparent)]
73/// A unique identifier for an Artifact.
74pub struct ArtifactId {
75    id: usize,
76}
77
78impl ArtifactId {
79    /// Format this identifier as a string.
80    pub fn id(&self) -> String {
81        format!("{}", self.id)
82    }
83}
84
85impl Clone for ArtifactId {
86    fn clone(&self) -> Self {
87        Self::default()
88    }
89}
90
91impl Default for ArtifactId {
92    fn default() -> Self {
93        static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
94        Self {
95            id: NEXT_ID.fetch_add(1, SeqCst),
96        }
97    }
98}
99
100/// A compiled wasm module, ready to be instantiated.
101#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
102pub struct Artifact {
103    id: ArtifactId,
104    artifact: ArtifactBuildVariant,
105    // The artifact will only be allocated in memory in case we can execute it
106    // (that means, if the target != host then this will be None).
107    allocated: Option<AllocatedArtifact>,
108}
109
110/// Artifacts may be created as the result of the compilation of a wasm
111/// module, corresponding to `ArtifactBuildVariant::Plain`, or loaded
112/// from an archive, corresponding to `ArtifactBuildVariant::Archived`.
113#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
114#[allow(clippy::large_enum_variant)]
115pub enum ArtifactBuildVariant {
116    Plain(ArtifactBuild),
117    Archived(ArtifactBuildFromArchive),
118}
119
120impl Artifact {
121    /// Compile a data buffer into a `ArtifactBuild`, which may then be instantiated.
122    #[cfg(feature = "compiler")]
123    pub fn new(
124        engine: &Engine,
125        data: &[u8],
126        tunables: &dyn Tunables,
127        progress_callback: Option<CompilationProgressCallback>,
128    ) -> Result<Self, CompileError> {
129        let mut inner_engine = engine.inner_mut();
130        let environ = ModuleEnvironment::new();
131        let translation = environ.translate(data).map_err(CompileError::Wasm)?;
132        let module = translation.module;
133        let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
134            .memories
135            .values()
136            .map(|memory_type| tunables.memory_style(memory_type))
137            .collect();
138        let table_styles: PrimaryMap<TableIndex, TableStyle> = module
139            .tables
140            .values()
141            .map(|table_type| tunables.table_style(table_type))
142            .collect();
143
144        let artifact = ArtifactBuild::new(
145            &mut inner_engine,
146            data,
147            engine.target(),
148            memory_styles,
149            table_styles,
150            progress_callback.as_ref(),
151        )?;
152
153        Self::from_parts(
154            &mut inner_engine,
155            ArtifactBuildVariant::Plain(artifact),
156            engine.target(),
157        )
158        .map_err(|e| match e {
159            DeserializeError::Compiler(c) => c,
160
161            // `from_parts` only ever returns `CompileError`s when an
162            // `ArtifactBuildVariant::Plain` is passed in. Other cases
163            // of `DeserializeError` can only happen when an
164            // `ArtifactBuildVariant::Archived` is passed in. We don't
165            // wish to change the return type of this method because
166            // a. it makes no sense and b. it would be a breaking change,
167            // hence this match block and the other cases being
168            // unreachable.
169            _ => unreachable!(),
170        })
171    }
172
173    /// This indicates if the Artifact is allocated and can be run by the current
174    /// host. In case it can't be run (for example, if the artifact is cross compiled to
175    /// other architecture), it will return false.
176    pub fn allocated(&self) -> bool {
177        self.allocated.is_some()
178    }
179
180    /// A unique identifier for this object.
181    ///
182    /// This exists to allow us to compare two Artifacts for equality. Otherwise,
183    /// comparing two trait objects unsafely relies on implementation details
184    /// of trait representation.
185    pub fn id(&self) -> &ArtifactId {
186        &self.id
187    }
188
189    /// Compile a data buffer into a `ArtifactBuild`, which may then be instantiated.
190    #[cfg(not(feature = "compiler"))]
191    pub fn new(_engine: &Engine, _data: &[u8]) -> Result<Self, CompileError> {
192        Err(CompileError::Codegen(
193            "Compilation is not enabled in the engine".to_string(),
194        ))
195    }
196
197    /// Deserialize a serialized artifact.
198    ///
199    /// # Safety
200    /// This function loads executable code into memory.
201    /// You must trust the loaded bytes to be valid for the chosen engine and
202    /// for the host CPU architecture.
203    /// In contrast to [`Self::deserialize_unchecked`] the artifact layout is
204    /// validated, which increases safety.
205    pub unsafe fn deserialize(
206        engine: &Engine,
207        bytes: OwnedBuffer,
208    ) -> Result<Self, DeserializeError> {
209        unsafe {
210            if !ArtifactBuild::is_deserializable(bytes.as_ref()) {
211                let static_artifact = Self::deserialize_object(engine, bytes);
212                match static_artifact {
213                    Ok(v) => {
214                        return Ok(v);
215                    }
216                    Err(e) => {
217                        return Err(DeserializeError::Incompatible(format!(
218                            "The provided bytes are not a Wasmer engine artifact: {e}"
219                        )));
220                    }
221                }
222            }
223
224            let artifact = ArtifactBuildFromArchive::try_new(bytes, |bytes| {
225                let bytes =
226                    Self::get_byte_slice(bytes, ArtifactBuild::MAGIC_HEADER.len(), bytes.len())?;
227
228                let metadata_len = MetadataHeader::parse(bytes)?;
229                let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
230                let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
231
232                SerializableModule::archive_from_slice_checked(metadata_slice)
233            })?;
234
235            let mut inner_engine = engine.inner_mut();
236            Self::from_parts(
237                &mut inner_engine,
238                ArtifactBuildVariant::Archived(artifact),
239                engine.target(),
240            )
241        }
242    }
243
244    /// Deserialize a serialized artifact.
245    ///
246    /// NOTE: You should prefer [`Self::deserialize`].
247    ///
248    /// # Safety
249    /// See [`Self::deserialize`].
250    /// In contrast to the above, this function skips artifact layout validation,
251    /// which increases the risk of loading invalid artifacts.
252    pub unsafe fn deserialize_unchecked(
253        engine: &Engine,
254        bytes: OwnedBuffer,
255    ) -> Result<Self, DeserializeError> {
256        unsafe {
257            if !ArtifactBuild::is_deserializable(bytes.as_ref()) {
258                let static_artifact = Self::deserialize_object(engine, bytes);
259                match static_artifact {
260                    Ok(v) => {
261                        return Ok(v);
262                    }
263                    Err(e) => {
264                        return Err(DeserializeError::Incompatible(format!(
265                            "The provided bytes are not a Wasmer engine artifact: {e}"
266                        )));
267                    }
268                }
269            }
270
271            let artifact = ArtifactBuildFromArchive::try_new(bytes, |bytes| {
272                let bytes =
273                    Self::get_byte_slice(bytes, ArtifactBuild::MAGIC_HEADER.len(), bytes.len())?;
274
275                let metadata_len = MetadataHeader::parse(bytes)?;
276                let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
277                let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
278
279                SerializableModule::archive_from_slice(metadata_slice)
280            })?;
281
282            let mut inner_engine = engine.inner_mut();
283            Self::from_parts(
284                &mut inner_engine,
285                ArtifactBuildVariant::Archived(artifact),
286                engine.target(),
287            )
288        }
289    }
290
291    /// Construct a `ArtifactBuild` from component parts.
292    pub fn from_parts(
293        engine_inner: &mut EngineInner,
294        artifact: ArtifactBuildVariant,
295        target: &Target,
296    ) -> Result<Self, DeserializeError> {
297        if !target.is_native() {
298            return Ok(Self {
299                id: Default::default(),
300                artifact,
301                allocated: None,
302            });
303        } else {
304            // check if cpu features are compatible before anything else
305            let cpu_features = artifact.cpu_features();
306            if !target.cpu_features().is_superset(cpu_features) {
307                return Err(DeserializeError::Incompatible(format!(
308                    "Some CPU Features needed for the artifact are missing: {:?}",
309                    cpu_features.difference(*target.cpu_features())
310                )));
311            }
312        }
313        let module_info = artifact.module_info();
314        let (
315            finished_functions,
316            finished_function_call_trampolines,
317            finished_dynamic_function_trampolines,
318            custom_sections,
319        ) = match &artifact {
320            ArtifactBuildVariant::Plain(p) => engine_inner.allocate(
321                module_info,
322                p.get_function_bodies_ref().values(),
323                p.get_function_call_trampolines_ref().values(),
324                p.get_dynamic_function_trampolines_ref().values(),
325                p.get_custom_sections_ref().values(),
326            )?,
327            ArtifactBuildVariant::Archived(a) => engine_inner.allocate(
328                module_info,
329                a.get_function_bodies_ref().values(),
330                a.get_function_call_trampolines_ref().values(),
331                a.get_dynamic_function_trampolines_ref().values(),
332                a.get_custom_sections_ref().values(),
333            )?,
334        };
335
336        let get_got_address: Box<dyn Fn(RelocationTarget) -> Option<usize>> = match &artifact {
337            ArtifactBuildVariant::Plain(p) => {
338                if let Some(got) = p.get_got_ref().index {
339                    let relocs: Vec<_> = p.get_custom_section_relocations_ref()[got]
340                        .iter()
341                        .map(|v| (v.reloc_target, v.offset))
342                        .collect();
343                    let got_base = custom_sections[got].0 as usize;
344                    Box::new(move |t: RelocationTarget| {
345                        relocs
346                            .iter()
347                            .find(|(v, _)| v == &t)
348                            .map(|(_, o)| got_base + (*o as usize))
349                    })
350                } else {
351                    Box::new(|_: RelocationTarget| None)
352                }
353            }
354
355            ArtifactBuildVariant::Archived(p) => {
356                if let Some(got) = p.get_got_ref().index {
357                    let relocs: Vec<_> = p.get_custom_section_relocations_ref()[got]
358                        .iter()
359                        .map(|v| (v.reloc_target(), v.offset))
360                        .collect();
361                    let got_base = custom_sections[got].0 as usize;
362                    Box::new(move |t: RelocationTarget| {
363                        relocs
364                            .iter()
365                            .find(|(v, _)| v == &t)
366                            .map(|(_, o)| got_base + (o.to_native() as usize))
367                    })
368                } else {
369                    Box::new(|_: RelocationTarget| None)
370                }
371            }
372        };
373
374        match &artifact {
375            ArtifactBuildVariant::Plain(p) => link_module(
376                module_info,
377                &finished_functions,
378                &finished_dynamic_function_trampolines,
379                p.get_function_relocations()
380                    .iter()
381                    .map(|(k, v)| (k, v.iter())),
382                &custom_sections,
383                p.get_custom_section_relocations_ref()
384                    .iter()
385                    .map(|(k, v)| (k, v.iter())),
386                p.get_libcall_trampolines(),
387                p.get_libcall_trampoline_len(),
388                &get_got_address,
389            ),
390            ArtifactBuildVariant::Archived(a) => link_module(
391                module_info,
392                &finished_functions,
393                &finished_dynamic_function_trampolines,
394                a.get_function_relocations()
395                    .iter()
396                    .map(|(k, v)| (k, v.iter())),
397                &custom_sections,
398                a.get_custom_section_relocations_ref()
399                    .iter()
400                    .map(|(k, v)| (k, v.iter())),
401                a.get_libcall_trampolines(),
402                a.get_libcall_trampoline_len(),
403                &get_got_address,
404            ),
405        };
406
407        // Compute indices into the shared signature table.
408        let signatures = {
409            let signature_registry = engine_inner.signatures();
410            module_info
411                .signatures
412                .values()
413                .zip(module_info.signature_hashes.values())
414                .map(|(sig, sig_hash)| signature_registry.register(sig, *sig_hash))
415                .collect::<PrimaryMap<_, _>>()
416        };
417
418        #[allow(unused_variables)]
419        let eh_frame = match &artifact {
420            ArtifactBuildVariant::Plain(p) => p.get_unwind_info().eh_frame.map(|v| unsafe {
421                std::slice::from_raw_parts(
422                    *custom_sections[v],
423                    p.get_custom_sections_ref()[v].bytes.len(),
424                )
425            }),
426            ArtifactBuildVariant::Archived(a) => a.get_unwind_info().eh_frame.map(|v| unsafe {
427                std::slice::from_raw_parts(
428                    *custom_sections[v],
429                    a.get_custom_sections_ref()[v].bytes.len(),
430                )
431            }),
432        };
433        #[allow(unused_variables)]
434        let compact_unwind = match &artifact {
435            ArtifactBuildVariant::Plain(p) => p.get_unwind_info().compact_unwind.map(|v| unsafe {
436                std::slice::from_raw_parts(
437                    *custom_sections[v],
438                    p.get_custom_sections_ref()[v].bytes.len(),
439                )
440            }),
441            ArtifactBuildVariant::Archived(a) => {
442                a.get_unwind_info().compact_unwind.map(|v| unsafe {
443                    std::slice::from_raw_parts(
444                        *custom_sections[v],
445                        a.get_custom_sections_ref()[v].bytes.len(),
446                    )
447                })
448            }
449        };
450
451        #[cfg(all(not(target_arch = "wasm32"), feature = "compiler"))]
452        {
453            engine_inner.register_perfmap(&finished_functions, module_info)?;
454        }
455
456        // Make all code compiled thus far executable.
457        engine_inner.publish_compiled_code();
458
459        #[cfg(all(target_os = "macos", target_arch = "aarch64"))]
460        if let Some(compact_unwind) = compact_unwind {
461            engine_inner.publish_compact_unwind(
462                compact_unwind,
463                get_got_address(RelocationTarget::LibCall(wasmer_vm::LibCall::EHPersonality)),
464            )?;
465        }
466        #[cfg(not(any(
467            target_arch = "wasm32",
468            all(target_os = "macos", target_arch = "aarch64")
469        )))]
470        engine_inner.publish_eh_frame(eh_frame)?;
471
472        drop(get_got_address);
473
474        let finished_function_lengths = finished_functions
475            .values()
476            .map(|extent| extent.length)
477            .collect::<PrimaryMap<LocalFunctionIndex, usize>>()
478            .into_boxed_slice();
479        let finished_functions = finished_functions
480            .values()
481            .map(|extent| extent.ptr)
482            .collect::<PrimaryMap<LocalFunctionIndex, FunctionBodyPtr>>()
483            .into_boxed_slice();
484        let finished_function_call_trampolines =
485            finished_function_call_trampolines.into_boxed_slice();
486        let finished_dynamic_function_trampolines =
487            finished_dynamic_function_trampolines.into_boxed_slice();
488        let signatures = signatures.into_boxed_slice();
489
490        let mut artifact = Self {
491            id: Default::default(),
492            artifact,
493            allocated: Some(AllocatedArtifact {
494                frame_info_registered: false,
495                frame_info_registration: None,
496                finished_functions,
497                finished_function_call_trampolines,
498                finished_dynamic_function_trampolines,
499                signatures,
500                finished_function_lengths,
501            }),
502        };
503
504        artifact
505            .internal_register_frame_info()
506            .map_err(|e| DeserializeError::CorruptedBinary(format!("{e:?}")))?;
507        if let Some(frame_info) = artifact.internal_take_frame_info_registration() {
508            engine_inner.register_frame_info(frame_info);
509        }
510
511        Ok(artifact)
512    }
513
514    /// Check if the provided bytes look like a serialized `ArtifactBuild`.
515    pub fn is_deserializable(bytes: &[u8]) -> bool {
516        ArtifactBuild::is_deserializable(bytes)
517    }
518}
519
520impl PartialEq for Artifact {
521    fn eq(&self, other: &Self) -> bool {
522        self.id == other.id
523    }
524}
525impl Eq for Artifact {}
526
527impl std::fmt::Debug for Artifact {
528    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
529        f.debug_struct("Artifact")
530            .field("artifact_id", &self.id)
531            .field("module_info", &self.module_info())
532            .finish()
533    }
534}
535
536impl<'a> ArtifactCreate<'a> for Artifact {
537    type OwnedDataInitializer = <ArtifactBuildVariant as ArtifactCreate<'a>>::OwnedDataInitializer;
538    type OwnedDataInitializerIterator =
539        <ArtifactBuildVariant as ArtifactCreate<'a>>::OwnedDataInitializerIterator;
540
541    fn set_module_info_name(&mut self, name: String) -> bool {
542        self.artifact.set_module_info_name(name)
543    }
544
545    fn create_module_info(&self) -> Arc<ModuleInfo> {
546        self.artifact.create_module_info()
547    }
548
549    fn module_info(&self) -> &ModuleInfo {
550        self.artifact.module_info()
551    }
552
553    fn features(&self) -> &Features {
554        self.artifact.features()
555    }
556
557    fn cpu_features(&self) -> EnumSet<CpuFeature> {
558        self.artifact.cpu_features()
559    }
560
561    fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
562        self.artifact.data_initializers()
563    }
564
565    fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
566        self.artifact.memory_styles()
567    }
568
569    fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
570        self.artifact.table_styles()
571    }
572
573    fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
574        self.artifact.serialize()
575    }
576}
577
578impl<'a> ArtifactCreate<'a> for ArtifactBuildVariant {
579    type OwnedDataInitializer = OwnedDataInitializerVariant<'a>;
580    type OwnedDataInitializerIterator = IntoIter<Self::OwnedDataInitializer>;
581
582    fn create_module_info(&self) -> Arc<ModuleInfo> {
583        match self {
584            Self::Plain(artifact) => artifact.create_module_info(),
585            Self::Archived(artifact) => artifact.create_module_info(),
586        }
587    }
588
589    fn set_module_info_name(&mut self, name: String) -> bool {
590        match self {
591            Self::Plain(artifact) => artifact.set_module_info_name(name),
592            Self::Archived(artifact) => artifact.set_module_info_name(name),
593        }
594    }
595
596    fn module_info(&self) -> &ModuleInfo {
597        match self {
598            Self::Plain(artifact) => artifact.module_info(),
599            Self::Archived(artifact) => artifact.module_info(),
600        }
601    }
602
603    fn features(&self) -> &Features {
604        match self {
605            Self::Plain(artifact) => artifact.features(),
606            Self::Archived(artifact) => artifact.features(),
607        }
608    }
609
610    fn cpu_features(&self) -> EnumSet<CpuFeature> {
611        match self {
612            Self::Plain(artifact) => artifact.cpu_features(),
613            Self::Archived(artifact) => artifact.cpu_features(),
614        }
615    }
616
617    fn memory_styles(&self) -> &PrimaryMap<MemoryIndex, MemoryStyle> {
618        match self {
619            Self::Plain(artifact) => artifact.memory_styles(),
620            Self::Archived(artifact) => artifact.memory_styles(),
621        }
622    }
623
624    fn table_styles(&self) -> &PrimaryMap<TableIndex, TableStyle> {
625        match self {
626            Self::Plain(artifact) => artifact.table_styles(),
627            Self::Archived(artifact) => artifact.table_styles(),
628        }
629    }
630
631    fn data_initializers(&'a self) -> Self::OwnedDataInitializerIterator {
632        match self {
633            Self::Plain(artifact) => artifact
634                .data_initializers()
635                .map(OwnedDataInitializerVariant::Plain)
636                .collect::<Vec<_>>()
637                .into_iter(),
638            Self::Archived(artifact) => artifact
639                .data_initializers()
640                .map(OwnedDataInitializerVariant::Archived)
641                .collect::<Vec<_>>()
642                .into_iter(),
643        }
644    }
645
646    fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
647        match self {
648            Self::Plain(artifact) => artifact.serialize(),
649            Self::Archived(artifact) => artifact.serialize(),
650        }
651    }
652}
653
654#[derive(Clone, Copy)]
655pub enum OwnedDataInitializerVariant<'a> {
656    Plain(&'a OwnedDataInitializer),
657    Archived(&'a ArchivedOwnedDataInitializer),
658}
659
660impl<'a> DataInitializerLike<'a> for OwnedDataInitializerVariant<'a> {
661    type Location = DataInitializerLocationVariant<'a>;
662
663    fn location(&self) -> Self::Location {
664        match self {
665            Self::Plain(plain) => DataInitializerLocationVariant::Plain(plain.location()),
666            Self::Archived(archived) => {
667                DataInitializerLocationVariant::Archived(archived.location())
668            }
669        }
670    }
671
672    fn data(&self) -> &'a [u8] {
673        match self {
674            Self::Plain(plain) => plain.data(),
675            Self::Archived(archived) => archived.data(),
676        }
677    }
678}
679
680#[derive(Clone, Copy)]
681pub enum DataInitializerLocationVariant<'a> {
682    Plain(&'a DataInitializerLocation),
683    Archived(&'a ArchivedDataInitializerLocation),
684}
685
686impl DataInitializerLocationVariant<'_> {
687    pub fn clone_to_plain(&self) -> DataInitializerLocation {
688        match self {
689            Self::Plain(p) => (*p).clone(),
690            Self::Archived(a) => DataInitializerLocation {
691                memory_index: a.memory_index(),
692                offset_expr: a.offset_expr(),
693            },
694        }
695    }
696}
697
698impl DataInitializerLocationLike for DataInitializerLocationVariant<'_> {
699    fn memory_index(&self) -> MemoryIndex {
700        match self {
701            Self::Plain(plain) => plain.memory_index(),
702            Self::Archived(archived) => archived.memory_index(),
703        }
704    }
705
706    fn offset_expr(&self) -> wasmer_types::InitExpr {
707        match self {
708            Self::Plain(plain) => plain.offset_expr(),
709            Self::Archived(archived) => archived.offset_expr(),
710        }
711    }
712}
713
714impl Artifact {
715    fn internal_register_frame_info(&mut self) -> Result<(), DeserializeError> {
716        if self
717            .allocated
718            .as_ref()
719            .expect("It must be allocated")
720            .frame_info_registered
721        {
722            return Ok(()); // already done
723        }
724
725        let finished_function_extents = self
726            .allocated
727            .as_ref()
728            .expect("It must be allocated")
729            .finished_functions
730            .values()
731            .copied()
732            .zip(
733                self.allocated
734                    .as_ref()
735                    .expect("It must be allocated")
736                    .finished_function_lengths
737                    .values()
738                    .copied(),
739            )
740            .map(|(ptr, length)| FunctionExtent { ptr, length })
741            .collect::<PrimaryMap<LocalFunctionIndex, _>>()
742            .into_boxed_slice();
743
744        let frame_info_registration = &mut self
745            .allocated
746            .as_mut()
747            .expect("It must be allocated")
748            .frame_info_registration;
749
750        *frame_info_registration = register_frame_info(
751            self.artifact.create_module_info(),
752            &finished_function_extents,
753            match &self.artifact {
754                ArtifactBuildVariant::Plain(p) => {
755                    FrameInfosVariant::Owned(p.get_frame_info_ref().clone())
756                }
757                ArtifactBuildVariant::Archived(a) => FrameInfosVariant::Archived(a.clone()),
758            },
759        );
760
761        self.allocated
762            .as_mut()
763            .expect("It must be allocated")
764            .frame_info_registered = true;
765
766        Ok(())
767    }
768
769    fn internal_take_frame_info_registration(&mut self) -> Option<GlobalFrameInfoRegistration> {
770        let frame_info_registration = &mut self
771            .allocated
772            .as_mut()
773            .expect("It must be allocated")
774            .frame_info_registration;
775
776        frame_info_registration.take()
777    }
778
779    /// Returns the functions allocated in memory or this `Artifact`
780    /// ready to be run.
781    pub fn finished_functions(&self) -> &BoxedSlice<LocalFunctionIndex, FunctionBodyPtr> {
782        &self
783            .allocated
784            .as_ref()
785            .expect("It must be allocated")
786            .finished_functions
787    }
788
789    /// Returns the start address and byte length of each locally-defined
790    /// function body in this artifact.
791    ///
792    /// Returns `None` for cross-compiled artifacts (where the artifact has not
793    /// been allocated into the host process).
794    ///
795    /// # Security
796    ///
797    /// The returned addresses are host-process pointers. They are not stable
798    /// across runs and must not be forwarded to untrusted parties, as they
799    /// reveal ASLR layout information.
800    pub fn finished_function_extents(
801        &self,
802    ) -> Option<Vec<(LocalFunctionIndex, FunctionExtent)>> {
803        let allocated = self.allocated.as_ref()?;
804        assert_eq!(
805            allocated.finished_functions.len(),
806            allocated.finished_function_lengths.len(),
807            "finished_functions and finished_function_lengths must have equal length"
808        );
809        Some(
810            allocated
811                .finished_functions
812                .iter()
813                .map(|(index, &ptr)| {
814                    let length = allocated.finished_function_lengths[index];
815                    (index, FunctionExtent { ptr, length })
816                })
817                .collect(),
818        )
819    }
820
821    /// Returns the function call trampolines allocated in memory of this
822    /// `Artifact`, ready to be run.
823    pub fn finished_function_call_trampolines(&self) -> &BoxedSlice<SignatureIndex, VMTrampoline> {
824        &self
825            .allocated
826            .as_ref()
827            .expect("It must be allocated")
828            .finished_function_call_trampolines
829    }
830
831    /// Returns the dynamic function trampolines allocated in memory
832    /// of this `Artifact`, ready to be run.
833    pub fn finished_dynamic_function_trampolines(
834        &self,
835    ) -> &BoxedSlice<FunctionIndex, FunctionBodyPtr> {
836        &self
837            .allocated
838            .as_ref()
839            .expect("It must be allocated")
840            .finished_dynamic_function_trampolines
841    }
842
843    /// Returns the associated VM signatures for this `Artifact`.
844    pub fn signatures(&self) -> &BoxedSlice<SignatureIndex, VMSignatureHash> {
845        &self
846            .allocated
847            .as_ref()
848            .expect("It must be allocated")
849            .signatures
850    }
851
852    /// Do preinstantiation logic that is executed before instantiating
853    #[allow(clippy::result_large_err)]
854    pub fn preinstantiate(&self) -> Result<(), InstantiationError> {
855        Ok(())
856    }
857
858    /// Crate an `Instance` from this `Artifact`.
859    ///
860    /// # Safety
861    ///
862    /// See [`VMInstance::new`].
863    #[allow(clippy::result_large_err)]
864    pub unsafe fn instantiate(
865        &self,
866        tunables: &dyn Tunables,
867        imports: &[VMExtern],
868        context: &mut StoreObjects,
869    ) -> Result<VMInstance, InstantiationError> {
870        unsafe {
871            // Validate the CPU features this module was compiled with against the
872            // host CPU features.
873            let host_cpu_features = CpuFeature::for_host();
874            if !host_cpu_features.is_superset(self.cpu_features()) {
875                return Err(InstantiationError::CpuFeature(format!(
876                    "{:?}",
877                    self.cpu_features().difference(host_cpu_features)
878                )));
879            }
880
881            self.preinstantiate()?;
882
883            let module = self.create_module_info();
884
885            let tags = resolve_tags(&module, imports, context).map_err(InstantiationError::Link)?;
886
887            let imports = resolve_imports(
888                &module,
889                imports,
890                context,
891                self.finished_dynamic_function_trampolines(),
892                self.memory_styles(),
893                self.table_styles(),
894            )
895            .map_err(InstantiationError::Link)?;
896
897            // Get pointers to where metadata about local memories should live in VM memory.
898            // Get pointers to where metadata about local tables should live in VM memory.
899
900            let (
901                allocator,
902                memory_definition_locations,
903                table_definition_locations,
904                global_definition_locations,
905            ) = InstanceAllocator::new(&module);
906            let finished_memories = tunables
907                .create_memories(
908                    context,
909                    &module,
910                    self.memory_styles(),
911                    &memory_definition_locations,
912                )
913                .map_err(InstantiationError::Link)?
914                .into_boxed_slice();
915            let finished_tables = tunables
916                .create_tables(
917                    context,
918                    &module,
919                    self.table_styles(),
920                    &table_definition_locations,
921                )
922                .map_err(InstantiationError::Link)?
923                .into_boxed_slice();
924            let finished_globals = tunables
925                .create_globals(context, &module, &global_definition_locations)
926                .map_err(InstantiationError::Link)?
927                .into_boxed_slice();
928
929            let handle = VMInstance::new(
930                allocator,
931                module,
932                context,
933                self.finished_functions().clone(),
934                self.finished_function_call_trampolines().clone(),
935                finished_memories,
936                finished_tables,
937                finished_globals,
938                tags,
939                imports,
940                self.signatures().clone(),
941            )
942            .map_err(InstantiationError::Start)?;
943            Ok(handle)
944        }
945    }
946
947    /// Finishes the instantiation of a just created `VMInstance`.
948    ///
949    /// # Safety
950    ///
951    /// See [`VMInstance::finish_instantiation`].
952    #[allow(clippy::result_large_err)]
953    pub unsafe fn finish_instantiation(
954        &self,
955        config: &VMConfig,
956        trap_handler: Option<*const TrapHandlerFn<'static>>,
957        handle: &mut VMInstance,
958    ) -> Result<(), InstantiationError> {
959        unsafe {
960            let data_initializers = self
961                .data_initializers()
962                .map(|init| DataInitializer {
963                    location: init.location().clone_to_plain(),
964                    data: init.data(),
965                })
966                .collect::<Vec<_>>();
967            handle
968                .finish_instantiation(config, trap_handler, &data_initializers)
969                .map_err(InstantiationError::Start)
970        }
971    }
972
973    #[allow(clippy::type_complexity)]
974    #[cfg(feature = "static-artifact-create")]
975    /// Generate a compilation
976    pub fn generate_metadata<'data>(
977        data: &'data [u8],
978        compiler: &dyn Compiler,
979        tunables: &dyn Tunables,
980        features: &Features,
981    ) -> Result<
982        (
983            CompileModuleInfo,
984            PrimaryMap<LocalFunctionIndex, FunctionBodyData<'data>>,
985            Vec<DataInitializer<'data>>,
986            Option<ModuleTranslationState>,
987        ),
988        CompileError,
989    > {
990        let environ = ModuleEnvironment::new();
991        let translation = environ.translate(data).map_err(CompileError::Wasm)?;
992
993        // We try to apply the middleware first
994        use crate::translator::ModuleMiddlewareChain;
995        let mut module = translation.module;
996        let middlewares = compiler.get_middlewares();
997        middlewares
998            .apply_on_module_info(&mut module)
999            .map_err(|e| CompileError::MiddlewareError(e.to_string()))?;
1000
1001        let memory_styles: PrimaryMap<MemoryIndex, MemoryStyle> = module
1002            .memories
1003            .values()
1004            .map(|memory_type| tunables.memory_style(memory_type))
1005            .collect();
1006        let table_styles: PrimaryMap<TableIndex, TableStyle> = module
1007            .tables
1008            .values()
1009            .map(|table_type| tunables.table_style(table_type))
1010            .collect();
1011
1012        let compile_info = CompileModuleInfo {
1013            module: Arc::new(module),
1014            features: features.clone(),
1015            memory_styles,
1016            table_styles,
1017        };
1018        Ok((
1019            compile_info,
1020            translation.function_body_inputs,
1021            translation.data_initializers,
1022            translation.module_translation_state,
1023        ))
1024    }
1025
1026    /// Generate the metadata object for the module
1027    #[cfg(feature = "static-artifact-create")]
1028    #[allow(clippy::type_complexity)]
1029    pub fn metadata<'a>(
1030        compiler: &dyn Compiler,
1031        data: &'a [u8],
1032        metadata_prefix: Option<&str>,
1033        target: &Target,
1034        tunables: &dyn Tunables,
1035        features: &Features,
1036    ) -> Result<
1037        (
1038            ModuleMetadata,
1039            Option<ModuleTranslationState>,
1040            PrimaryMap<LocalFunctionIndex, FunctionBodyData<'a>>,
1041        ),
1042        CompileError,
1043    > {
1044        #[allow(dead_code)]
1045        let (compile_info, function_body_inputs, data_initializers, module_translation) =
1046            Self::generate_metadata(data, compiler, tunables, features)?;
1047
1048        let data_initializers = data_initializers
1049            .iter()
1050            .map(OwnedDataInitializer::new)
1051            .collect::<Vec<_>>()
1052            .into_boxed_slice();
1053
1054        // TODO: we currently supply all-zero function body lengths.
1055        // We don't know the lengths until they're compiled, yet we have to
1056        // supply the metadata as an input to the compile.
1057        let function_body_lengths = function_body_inputs
1058            .keys()
1059            .map(|_function_body| 0u64)
1060            .collect::<PrimaryMap<LocalFunctionIndex, u64>>();
1061
1062        let metadata = ModuleMetadata {
1063            compile_info,
1064            prefix: metadata_prefix.map(|s| s.to_string()).unwrap_or_default(),
1065            data_initializers,
1066            function_body_lengths,
1067            cpu_features: target.cpu_features().as_u64(),
1068        };
1069
1070        Ok((metadata, module_translation, function_body_inputs))
1071    }
1072
1073    /// Compile a module into an object file, which can be statically linked against.
1074    ///
1075    /// The `metadata_prefix` is an optional prefix for the object name to make the
1076    /// function names in the object file unique. When set, the function names will
1077    /// be `wasmer_function_{prefix}_{id}` and the object metadata will be addressable
1078    /// using `WASMER_METADATA_{prefix}_LENGTH` and `WASMER_METADATA_{prefix}_DATA`.
1079    ///
1080    #[cfg(feature = "static-artifact-create")]
1081    pub fn generate_object<'data>(
1082        compiler: &dyn Compiler,
1083        data: &[u8],
1084        metadata_prefix: Option<&str>,
1085        target: &'data Target,
1086        tunables: &dyn Tunables,
1087        features: &Features,
1088    ) -> Result<
1089        (
1090            ModuleInfo,
1091            Object<'data>,
1092            usize,
1093            Box<dyn crate::types::symbols::SymbolRegistry>,
1094        ),
1095        CompileError,
1096    > {
1097        use crate::types::symbols::{ModuleMetadataSymbolRegistry, SymbolRegistry};
1098
1099        fn to_compile_error(err: impl std::error::Error) -> CompileError {
1100            CompileError::Codegen(format!("{err}"))
1101        }
1102
1103        let target_triple = target.triple();
1104        let (mut metadata, module_translation, function_body_inputs) =
1105            Self::metadata(compiler, data, metadata_prefix, target, tunables, features)
1106                .map_err(to_compile_error)?;
1107
1108        /*
1109        In the C file we need:
1110        - imports
1111        - exports
1112
1113        to construct an api::Module which is a Store (can be passed in via argument) and an
1114        Arc<dyn Artifact> which means this struct which includes:
1115        - CompileModuleInfo
1116        - Features
1117        - ModuleInfo
1118        - MemoryIndex -> MemoryStyle
1119        - TableIndex -> TableStyle
1120        - LocalFunctionIndex -> FunctionBodyPtr // finished functions
1121        - FunctionIndex -> FunctionBodyPtr // finished dynamic function trampolines
1122        - SignatureIndex -> VMSignatureHash // signatures
1123         */
1124
1125        let mut metadata_builder =
1126            ObjectMetadataBuilder::new(&metadata, target_triple).map_err(to_compile_error)?;
1127
1128        let (_compile_info, symbol_registry) = metadata.split();
1129
1130        let compilation: crate::types::function::Compilation = compiler.compile_module(
1131            target,
1132            &metadata.compile_info,
1133            module_translation.as_ref().unwrap(),
1134            function_body_inputs,
1135            None,
1136        )?;
1137        let mut obj = get_object_for_target(target_triple).map_err(to_compile_error)?;
1138
1139        let object_name = ModuleMetadataSymbolRegistry {
1140            prefix: metadata_prefix.unwrap_or_default().to_string(),
1141        }
1142        .symbol_to_name(crate::types::symbols::Symbol::Metadata);
1143
1144        let default_align = match target_triple.architecture {
1145            target_lexicon::Architecture::Aarch64(_) => {
1146                if matches!(
1147                    target_triple.operating_system,
1148                    target_lexicon::OperatingSystem::Darwin(_)
1149                ) {
1150                    8
1151                } else {
1152                    4
1153                }
1154            }
1155            _ => 1,
1156        };
1157
1158        // MetadataHeader::parse requires that metadata must be aligned
1159        // by 8 bytes.
1160        let offset = emit_data(
1161            &mut obj,
1162            object_name.as_bytes(),
1163            metadata_builder.placeholder_data(),
1164            std::cmp::max(8, default_align),
1165        )
1166        .map_err(to_compile_error)?;
1167        metadata_builder.set_section_offset(offset);
1168
1169        emit_compilation(
1170            &mut obj,
1171            compilation,
1172            &symbol_registry,
1173            target_triple,
1174            &metadata_builder,
1175        )
1176        .map_err(to_compile_error)?;
1177        Ok((
1178            Arc::try_unwrap(metadata.compile_info.module).unwrap(),
1179            obj,
1180            metadata_builder.placeholder_data().len(),
1181            Box::new(symbol_registry),
1182        ))
1183    }
1184
1185    /// Deserialize a ArtifactBuild from an object file
1186    ///
1187    /// # Safety
1188    /// The object must be a valid static object generated by wasmer.
1189    #[cfg(not(feature = "static-artifact-load"))]
1190    pub unsafe fn deserialize_object(
1191        _engine: &Engine,
1192        _bytes: OwnedBuffer,
1193    ) -> Result<Self, DeserializeError> {
1194        Err(DeserializeError::Compiler(
1195            CompileError::UnsupportedFeature("static load is not compiled in".to_string()),
1196        ))
1197    }
1198
1199    fn get_byte_slice(input: &[u8], start: usize, end: usize) -> Result<&[u8], DeserializeError> {
1200        if (start == end && input.len() > start)
1201            || (start < end && input.len() > start && input.len() >= end)
1202        {
1203            Ok(&input[start..end])
1204        } else {
1205            Err(DeserializeError::InvalidByteLength {
1206                expected: end - start,
1207                got: input.len(),
1208            })
1209        }
1210    }
1211
1212    /// Deserialize a ArtifactBuild from an object file
1213    ///
1214    /// # Safety
1215    /// The object must be a valid static object generated by wasmer.
1216    #[cfg(feature = "static-artifact-load")]
1217    pub unsafe fn deserialize_object(
1218        engine: &Engine,
1219        bytes: OwnedBuffer,
1220    ) -> Result<Self, DeserializeError> {
1221        unsafe {
1222            let bytes = bytes.as_slice();
1223            let metadata_len = MetadataHeader::parse(bytes)?;
1224            let metadata_slice = Self::get_byte_slice(bytes, MetadataHeader::LEN, bytes.len())?;
1225            let metadata_slice = Self::get_byte_slice(metadata_slice, 0, metadata_len)?;
1226            let metadata: ModuleMetadata = ModuleMetadata::deserialize(metadata_slice)?;
1227
1228            const WORD_SIZE: usize = mem::size_of::<usize>();
1229            let mut byte_buffer = [0u8; WORD_SIZE];
1230
1231            let mut cur_offset = MetadataHeader::LEN + metadata_len;
1232
1233            let byte_buffer_slice =
1234                Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1235            byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1236            cur_offset += WORD_SIZE;
1237
1238            let num_finished_functions = usize::from_ne_bytes(byte_buffer);
1239            let mut finished_functions: PrimaryMap<LocalFunctionIndex, FunctionBodyPtr> =
1240                PrimaryMap::new();
1241
1242            let engine_inner = engine.inner();
1243            let signature_registry = engine_inner.signatures();
1244
1245            // read finished functions in order now...
1246            for _i in 0..num_finished_functions {
1247                let byte_buffer_slice =
1248                    Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1249                byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1250                let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
1251                cur_offset += WORD_SIZE;
1252
1253                // TODO: we can read back the length here if we serialize it. This will improve debug output.
1254                finished_functions.push(fp);
1255            }
1256
1257            // We register all the signatures
1258            let signatures = {
1259                let module = &metadata.compile_info.module;
1260                module
1261                    .signatures
1262                    .values()
1263                    .zip(module.signature_hashes.values())
1264                    .map(|(sig, sig_hash)| signature_registry.register(sig, *sig_hash))
1265                    .collect::<PrimaryMap<_, _>>()
1266            };
1267
1268            // read trampolines in order
1269            let mut finished_function_call_trampolines = PrimaryMap::new();
1270
1271            let byte_buffer_slice =
1272                Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1273            byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1274            cur_offset += WORD_SIZE;
1275            let num_function_trampolines = usize::from_ne_bytes(byte_buffer);
1276            for _ in 0..num_function_trampolines {
1277                let byte_buffer_slice =
1278                    Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1279                byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1280                cur_offset += WORD_SIZE;
1281                let trampoline_ptr_bytes = usize::from_ne_bytes(byte_buffer);
1282                let trampoline = mem::transmute::<usize, VMTrampoline>(trampoline_ptr_bytes);
1283                finished_function_call_trampolines.push(trampoline);
1284                // TODO: we can read back the length here if we serialize it. This will improve debug output.
1285            }
1286
1287            // read dynamic function trampolines in order now...
1288            let mut finished_dynamic_function_trampolines = PrimaryMap::new();
1289            let byte_buffer_slice =
1290                Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1291            byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1292            cur_offset += WORD_SIZE;
1293            let num_dynamic_trampoline_functions = usize::from_ne_bytes(byte_buffer);
1294            for _i in 0..num_dynamic_trampoline_functions {
1295                let byte_buffer_slice =
1296                    Self::get_byte_slice(bytes, cur_offset, cur_offset + WORD_SIZE)?;
1297                byte_buffer[0..WORD_SIZE].clone_from_slice(byte_buffer_slice);
1298                let fp = FunctionBodyPtr(usize::from_ne_bytes(byte_buffer) as _);
1299                cur_offset += WORD_SIZE;
1300
1301                // TODO: we can read back the length here if we serialize it. This will improve debug output.
1302
1303                finished_dynamic_function_trampolines.push(fp);
1304            }
1305
1306            let artifact = ArtifactBuild::from_serializable(SerializableModule {
1307                compilation: SerializableCompilation::default(),
1308                compile_info: metadata.compile_info,
1309                data_initializers: metadata.data_initializers,
1310                cpu_features: metadata.cpu_features,
1311            });
1312
1313            let finished_function_lengths = finished_functions
1314                .values()
1315                .map(|_| 0)
1316                .collect::<PrimaryMap<LocalFunctionIndex, usize>>()
1317                .into_boxed_slice();
1318
1319            Ok(Self {
1320                id: Default::default(),
1321                artifact: ArtifactBuildVariant::Plain(artifact),
1322                allocated: Some(AllocatedArtifact {
1323                    frame_info_registered: false,
1324                    frame_info_registration: None,
1325                    finished_functions: finished_functions.into_boxed_slice(),
1326                    finished_function_call_trampolines: finished_function_call_trampolines
1327                        .into_boxed_slice(),
1328                    finished_dynamic_function_trampolines: finished_dynamic_function_trampolines
1329                        .into_boxed_slice(),
1330                    signatures: signatures.into_boxed_slice(),
1331                    finished_function_lengths,
1332                }),
1333            })
1334        }
1335    }
1336}