wasmer_engine_dylib/
serialize.rs

1use loupe::MemoryUsage;
2use rkyv::{
3    archived_value, de::deserializers::SharedDeserializeMap, ser::serializers::AllocSerializer,
4    ser::Serializer as RkyvSerializer, Archive, Deserialize as RkyvDeserialize,
5    Serialize as RkyvSerialize,
6};
7use serde::{Deserialize, Serialize};
8use std::error::Error;
9use wasmer_compiler::{
10    CompileError, CompileModuleInfo, CompiledFunctionFrameInfo, SectionIndex, Symbol,
11    SymbolRegistry,
12};
13use wasmer_engine::DeserializeError;
14use wasmer_types::entity::{EntityRef, PrimaryMap};
15use wasmer_types::{FunctionIndex, LocalFunctionIndex, OwnedDataInitializer, SignatureIndex};
16
17fn to_compile_error(err: impl Error) -> CompileError {
18    CompileError::Codegen(format!("{}", err))
19}
20
21/// Serializable struct that represents the compiled metadata.
22#[derive(
23    Serialize,
24    Deserialize,
25    Debug,
26    MemoryUsage,
27    RkyvSerialize,
28    RkyvDeserialize,
29    Archive,
30    PartialEq,
31    Eq,
32)]
33pub struct ModuleMetadata {
34    pub compile_info: CompileModuleInfo,
35    pub function_frame_info: Option<PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>>,
36    pub prefix: String,
37    pub data_initializers: Box<[OwnedDataInitializer]>,
38    // The function body lengths (used to find function by address)
39    pub function_body_lengths: PrimaryMap<LocalFunctionIndex, u64>,
40    pub cpu_features: u64,
41}
42
43pub struct ModuleMetadataSymbolRegistry<'a> {
44    pub prefix: &'a String,
45}
46
47impl ModuleMetadata {
48    pub fn split(&'_ mut self) -> (&'_ mut CompileModuleInfo, ModuleMetadataSymbolRegistry<'_>) {
49        let compile_info = &mut self.compile_info;
50        let symbol_registry = ModuleMetadataSymbolRegistry {
51            prefix: &self.prefix,
52        };
53        (compile_info, symbol_registry)
54    }
55
56    pub fn get_symbol_registry(&'_ self) -> ModuleMetadataSymbolRegistry<'_> {
57        ModuleMetadataSymbolRegistry {
58            prefix: &self.prefix,
59        }
60    }
61
62    pub fn serialize(&mut self) -> Result<Vec<u8>, CompileError> {
63        let mut serializer = AllocSerializer::<4096>::default();
64        let pos = serializer.serialize_value(self).map_err(to_compile_error)? as u64;
65        let mut serialized_data = serializer.into_serializer().into_inner();
66        serialized_data.extend_from_slice(&pos.to_le_bytes());
67        Ok(serialized_data.to_vec())
68    }
69
70    pub unsafe fn deserialize(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
71        let archived = Self::archive_from_slice(metadata_slice)?;
72        Self::deserialize_from_archive(archived)
73    }
74
75    unsafe fn archive_from_slice(
76        metadata_slice: &[u8],
77    ) -> Result<&ArchivedModuleMetadata, DeserializeError> {
78        let mut pos: [u8; 8] = Default::default();
79        pos.copy_from_slice(&metadata_slice[metadata_slice.len() - 8..metadata_slice.len()]);
80        let pos: u64 = u64::from_le_bytes(pos);
81        Ok(archived_value::<Self>(
82            &metadata_slice[..metadata_slice.len() - 8],
83            pos as usize,
84        ))
85    }
86
87    pub fn deserialize_from_archive(
88        archived: &ArchivedModuleMetadata,
89    ) -> Result<Self, DeserializeError> {
90        let mut deserializer = SharedDeserializeMap::new();
91        RkyvDeserialize::deserialize(archived, &mut deserializer)
92            .map_err(|e| DeserializeError::CorruptedBinary(format!("{:?}", e)))
93    }
94}
95
96impl<'a> SymbolRegistry for ModuleMetadataSymbolRegistry<'a> {
97    fn symbol_to_name(&self, symbol: Symbol) -> String {
98        match symbol {
99            Symbol::LocalFunction(index) => {
100                format!("wasmer_function_{}_{}", self.prefix, index.index())
101            }
102            Symbol::Section(index) => format!("wasmer_section_{}_{}", self.prefix, index.index()),
103            Symbol::FunctionCallTrampoline(index) => {
104                format!(
105                    "wasmer_trampoline_function_call_{}_{}",
106                    self.prefix,
107                    index.index()
108                )
109            }
110            Symbol::DynamicFunctionTrampoline(index) => {
111                format!(
112                    "wasmer_trampoline_dynamic_function_{}_{}",
113                    self.prefix,
114                    index.index()
115                )
116            }
117        }
118    }
119
120    fn name_to_symbol(&self, name: &str) -> Option<Symbol> {
121        if let Some(index) = name.strip_prefix(&format!("wasmer_function_{}_", self.prefix)) {
122            index
123                .parse::<u32>()
124                .ok()
125                .map(|index| Symbol::LocalFunction(LocalFunctionIndex::from_u32(index)))
126        } else if let Some(index) = name.strip_prefix(&format!("wasmer_section_{}_", self.prefix)) {
127            index
128                .parse::<u32>()
129                .ok()
130                .map(|index| Symbol::Section(SectionIndex::from_u32(index)))
131        } else if let Some(index) =
132            name.strip_prefix(&format!("wasmer_trampoline_function_call_{}_", self.prefix))
133        {
134            index
135                .parse::<u32>()
136                .ok()
137                .map(|index| Symbol::FunctionCallTrampoline(SignatureIndex::from_u32(index)))
138        } else if let Some(index) = name.strip_prefix(&format!(
139            "wasmer_trampoline_dynamic_function_{}_",
140            self.prefix
141        )) {
142            index
143                .parse::<u32>()
144                .ok()
145                .map(|index| Symbol::DynamicFunctionTrampoline(FunctionIndex::from_u32(index)))
146        } else {
147            None
148        }
149    }
150}