wasmer_types/compilation/
symbols.rs

1//! This module define the required structures for compilation symbols.
2use crate::{
3    entity::{EntityRef, PrimaryMap},
4    CompileModuleInfo, DeserializeError, FunctionIndex, LocalFunctionIndex, OwnedDataInitializer,
5    SectionIndex, SerializeError, SignatureIndex,
6};
7use rkyv::{
8    archived_value, check_archived_value, de::deserializers::SharedDeserializeMap,
9    ser::serializers::AllocSerializer, ser::Serializer as RkyvSerializer, Archive,
10    Deserialize as RkyvDeserialize, Serialize as RkyvSerialize,
11};
12#[cfg(feature = "enable-serde")]
13use serde::{Deserialize, Serialize};
14
15/// The kinds of wasmer_types objects that might be found in a native object file.
16#[derive(
17    RkyvSerialize, RkyvDeserialize, Archive, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug,
18)]
19#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
20#[archive(as = "Self")]
21pub enum Symbol {
22    /// A metadata section, indexed by a unique prefix
23    /// (usually the wasm file SHA256 hash)
24    Metadata,
25
26    /// A function defined in the wasm.
27    LocalFunction(LocalFunctionIndex),
28
29    /// A wasm section.
30    Section(SectionIndex),
31
32    /// The function call trampoline for a given signature.
33    FunctionCallTrampoline(SignatureIndex),
34
35    /// The dynamic function trampoline for a given function.
36    DynamicFunctionTrampoline(FunctionIndex),
37}
38
39/// This trait facilitates symbol name lookups in a native object file.
40pub trait SymbolRegistry: Send + Sync {
41    /// Given a `Symbol` it returns the name for that symbol in the object file
42    fn symbol_to_name(&self, symbol: Symbol) -> String;
43
44    /// Given a name it returns the `Symbol` for that name in the object file
45    ///
46    /// This function is the inverse of [`SymbolRegistry::symbol_to_name`]
47    fn name_to_symbol(&self, name: &str) -> Option<Symbol>;
48}
49
50/// Serializable struct that represents the compiled metadata.
51#[derive(Debug, RkyvSerialize, RkyvDeserialize, Archive)]
52#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
53#[archive_attr(derive(rkyv::CheckBytes, Debug))]
54pub struct ModuleMetadata {
55    /// Compile info
56    pub compile_info: CompileModuleInfo,
57    /// Prefix for function etc symbols
58    pub prefix: String,
59    /// Data initializers
60    pub data_initializers: Box<[OwnedDataInitializer]>,
61    /// The function body lengths (used to find function by address)
62    pub function_body_lengths: PrimaryMap<LocalFunctionIndex, u64>,
63    /// CPU features used (See [`CpuFeature`](crate::CpuFeature))
64    pub cpu_features: u64,
65}
66
67/// A simple metadata registry
68pub struct ModuleMetadataSymbolRegistry {
69    /// Symbol prefix stirng
70    pub prefix: String,
71}
72
73impl ModuleMetadata {
74    /// Get mutable ref to compile info and a copy of the registry
75    pub fn split(&mut self) -> (&mut CompileModuleInfo, ModuleMetadataSymbolRegistry) {
76        let compile_info = &mut self.compile_info;
77        let symbol_registry = ModuleMetadataSymbolRegistry {
78            prefix: self.prefix.clone(),
79        };
80        (compile_info, symbol_registry)
81    }
82
83    /// Returns symbol registry.
84    pub fn get_symbol_registry(&self) -> ModuleMetadataSymbolRegistry {
85        ModuleMetadataSymbolRegistry {
86            prefix: self.prefix.clone(),
87        }
88    }
89    /// Serialize a Module into bytes
90    /// The bytes will have the following format:
91    /// RKYV serialization (any length) + POS (8 bytes)
92    pub fn serialize(&self) -> Result<Vec<u8>, SerializeError> {
93        let mut serializer = AllocSerializer::<4096>::default();
94        let pos = serializer
95            .serialize_value(self)
96            .map_err(|err| SerializeError::Generic(format!("{}", err)))? as u64;
97        let mut serialized_data = serializer.into_serializer().into_inner();
98        serialized_data.extend_from_slice(&pos.to_le_bytes());
99        Ok(serialized_data.to_vec())
100    }
101
102    /// Deserialize a Module from a slice.
103    /// The slice must have the following format:
104    /// RKYV serialization (any length) + POS (8 bytes)
105    ///
106    /// # Safety
107    ///
108    /// This method is unsafe since it deserializes data directly
109    /// from memory.
110    /// Right now we are not doing any extra work for validation, but
111    /// `rkyv` has an option to do bytecheck on the serialized data before
112    /// serializing (via `rkyv::check_archived_value`).
113    pub unsafe fn deserialize_unchecked(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
114        let archived = Self::archive_from_slice(metadata_slice)?;
115        Self::deserialize_from_archive(archived)
116    }
117
118    /// Deserialize a Module from a slice.
119    /// The slice must have the following format:
120    /// RKYV serialization (any length) + POS (8 bytes)
121    pub fn deserialize(metadata_slice: &[u8]) -> Result<Self, DeserializeError> {
122        let archived = Self::archive_from_slice_checked(metadata_slice)?;
123        Self::deserialize_from_archive(archived)
124    }
125
126    /// # Safety
127    ///
128    /// This method is unsafe.
129    /// Please check `ModuleMetadata::deserialize` for more details.
130    unsafe fn archive_from_slice(
131        metadata_slice: &[u8],
132    ) -> Result<&ArchivedModuleMetadata, DeserializeError> {
133        if metadata_slice.len() < 8 {
134            return Err(DeserializeError::Incompatible(
135                "invalid serialized ModuleMetadata".into(),
136            ));
137        }
138        let mut pos: [u8; 8] = Default::default();
139        pos.copy_from_slice(&metadata_slice[metadata_slice.len() - 8..metadata_slice.len()]);
140        let pos: u64 = u64::from_le_bytes(pos);
141        Ok(archived_value::<Self>(
142            &metadata_slice[..metadata_slice.len() - 8],
143            pos as usize,
144        ))
145    }
146
147    /// # Safety
148    ///
149    /// This method is unsafe.
150    /// Please check `ModuleMetadata::deserialize` for more details.
151    fn archive_from_slice_checked(
152        metadata_slice: &[u8],
153    ) -> Result<&ArchivedModuleMetadata, DeserializeError> {
154        if metadata_slice.len() < 8 {
155            return Err(DeserializeError::Incompatible(
156                "invalid serialized ModuleMetadata".into(),
157            ));
158        }
159        let mut pos: [u8; 8] = Default::default();
160        pos.copy_from_slice(&metadata_slice[metadata_slice.len() - 8..metadata_slice.len()]);
161        let pos: u64 = u64::from_le_bytes(pos);
162        check_archived_value::<Self>(&metadata_slice[..metadata_slice.len() - 8], pos as usize)
163            .map_err(|e| DeserializeError::CorruptedBinary(e.to_string()))
164    }
165
166    /// Deserialize a compilation module from an archive
167    pub fn deserialize_from_archive(
168        archived: &ArchivedModuleMetadata,
169    ) -> Result<Self, DeserializeError> {
170        let mut deserializer = SharedDeserializeMap::new();
171        RkyvDeserialize::deserialize(archived, &mut deserializer)
172            .map_err(|e| DeserializeError::CorruptedBinary(format!("{:?}", e)))
173    }
174}
175
176impl SymbolRegistry for ModuleMetadataSymbolRegistry {
177    fn symbol_to_name(&self, symbol: Symbol) -> String {
178        match symbol {
179            Symbol::Metadata => {
180                format!("WASMER_METADATA_{}", self.prefix.to_uppercase())
181            }
182            Symbol::LocalFunction(index) => {
183                format!("wasmer_function_{}_{}", self.prefix, index.index())
184            }
185            Symbol::Section(index) => format!("wasmer_section_{}_{}", self.prefix, index.index()),
186            Symbol::FunctionCallTrampoline(index) => {
187                format!(
188                    "wasmer_trampoline_function_call_{}_{}",
189                    self.prefix,
190                    index.index()
191                )
192            }
193            Symbol::DynamicFunctionTrampoline(index) => {
194                format!(
195                    "wasmer_trampoline_dynamic_function_{}_{}",
196                    self.prefix,
197                    index.index()
198                )
199            }
200        }
201    }
202
203    fn name_to_symbol(&self, name: &str) -> Option<Symbol> {
204        if name == self.symbol_to_name(Symbol::Metadata) {
205            Some(Symbol::Metadata)
206        } else if let Some(index) = name.strip_prefix(&format!("wasmer_function_{}_", self.prefix))
207        {
208            index
209                .parse::<u32>()
210                .ok()
211                .map(|index| Symbol::LocalFunction(LocalFunctionIndex::from_u32(index)))
212        } else if let Some(index) = name.strip_prefix(&format!("wasmer_section_{}_", self.prefix)) {
213            index
214                .parse::<u32>()
215                .ok()
216                .map(|index| Symbol::Section(SectionIndex::from_u32(index)))
217        } else if let Some(index) =
218            name.strip_prefix(&format!("wasmer_trampoline_function_call_{}_", self.prefix))
219        {
220            index
221                .parse::<u32>()
222                .ok()
223                .map(|index| Symbol::FunctionCallTrampoline(SignatureIndex::from_u32(index)))
224        } else if let Some(index) = name.strip_prefix(&format!(
225            "wasmer_trampoline_dynamic_function_{}_",
226            self.prefix
227        )) {
228            index
229                .parse::<u32>()
230                .ok()
231                .map(|index| Symbol::DynamicFunctionTrampoline(FunctionIndex::from_u32(index)))
232        } else {
233            None
234        }
235    }
236}