unc_vm_engine/universal/
executable.rs1use crate::DeserializeError;
2use rkyv::de::deserializers::SharedDeserializeMap;
3use rkyv::ser::serializers::{
4 AllocScratchError, AllocSerializer, CompositeSerializerError, SharedSerializeMapError,
5};
6use unc_vm_compiler::{
7 CompileModuleInfo, CompiledFunctionFrameInfo, CustomSection, Dwarf, FunctionBody,
8 JumpTableOffsets, Relocation, SectionIndex, TrampolinesSection,
9};
10use unc_vm_types::entity::PrimaryMap;
11use unc_vm_types::{
12 ExportIndex, FunctionIndex, ImportIndex, LocalFunctionIndex, OwnedDataInitializer,
13 SignatureIndex,
14};
15
16const MAGIC_HEADER: [u8; 32] = {
17 let value = *b"\0uncdvm-universal\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
18 let _length_must_be_multiple_of_16: bool = [true][value.len() % 16];
19 value
20};
21
22#[derive(Clone, Copy)]
24pub struct UniversalExecutableRef<'a> {
25 archive: &'a ArchivedUniversalExecutable,
26}
27
28impl<'a> std::ops::Deref for UniversalExecutableRef<'a> {
29 type Target = ArchivedUniversalExecutable;
30 fn deref(&self) -> &Self::Target {
31 self.archive
32 }
33}
34
35impl<'a> UniversalExecutableRef<'a> {
36 pub fn verify_serialized(data: &[u8]) -> Result<(), &'static str> {
38 if !data.starts_with(&MAGIC_HEADER) {
39 return Err("the provided bytes are not uncvm-universal");
40 }
41 if data.len() < MAGIC_HEADER.len() + 8 {
42 return Err("the data buffer is too small to be valid");
43 }
44 let (remaining, position) = data.split_at(data.len() - 8);
45 let mut position_value = [0u8; 8];
46 position_value.copy_from_slice(position);
47 if u64::from_le_bytes(position_value) > remaining.len() as u64 {
48 return Err("the buffer is malformed");
49 }
50 Ok(())
52 }
53
54 pub unsafe fn deserialize(
62 data: &'a [u8],
63 ) -> Result<UniversalExecutableRef<'a>, DeserializeError> {
64 Self::verify_serialized(data).map_err(|e| DeserializeError::Incompatible(e.to_string()))?;
65 let (archive, position) = data.split_at(data.len() - 8);
66 let mut position_value = [0u8; 8];
67 position_value.copy_from_slice(position);
68 let (_, data) = archive.split_at(MAGIC_HEADER.len());
69 Ok(UniversalExecutableRef {
70 archive: rkyv::archived_value::<UniversalExecutable>(
71 data,
72 u64::from_le_bytes(position_value) as usize,
73 ),
74 })
75 }
76
77 pub fn to_owned(self) -> Result<UniversalExecutable, DeserializeError> {
80 let mut deserializer = SharedDeserializeMap::new();
81 rkyv::Deserialize::deserialize(self.archive, &mut deserializer)
82 .map_err(|e| DeserializeError::CorruptedBinary(format!("{:?}", e)))
83 }
84}
85
86#[derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize)]
92pub struct UniversalExecutable {
93 pub(crate) function_bodies: PrimaryMap<LocalFunctionIndex, FunctionBody>,
94 pub(crate) function_relocations: PrimaryMap<LocalFunctionIndex, Vec<Relocation>>,
95 pub(crate) function_jt_offsets: PrimaryMap<LocalFunctionIndex, JumpTableOffsets>,
96 pub(crate) function_frame_info: PrimaryMap<LocalFunctionIndex, CompiledFunctionFrameInfo>,
97 pub(crate) function_call_trampolines: PrimaryMap<SignatureIndex, FunctionBody>,
98 pub(crate) dynamic_function_trampolines: PrimaryMap<FunctionIndex, FunctionBody>,
99 pub(crate) custom_sections: PrimaryMap<SectionIndex, CustomSection>,
100 pub(crate) custom_section_relocations: PrimaryMap<SectionIndex, Vec<Relocation>>,
101 pub(crate) debug: Option<Dwarf>,
103 pub(crate) trampolines: Option<TrampolinesSection>,
105 pub(crate) compile_info: CompileModuleInfo,
106 pub(crate) data_initializers: Vec<OwnedDataInitializer>,
107 pub(crate) cpu_features: u64,
108}
109
110#[derive(thiserror::Error, Debug)]
111pub enum ExecutableSerializeError {
112 #[error("could not serialize the executable data")]
113 Executable(
114 #[source]
115 CompositeSerializerError<
116 std::convert::Infallible,
117 AllocScratchError,
118 SharedSerializeMapError,
119 >,
120 ),
121}
122
123impl UniversalExecutable {
124 pub fn serialize(
126 &self,
127 ) -> Result<Vec<u8>, Box<(dyn std::error::Error + Send + Sync + 'static)>> {
128 let mut serializer = AllocSerializer::<1024>::default();
136 let pos = rkyv::ser::Serializer::serialize_value(&mut serializer, self)
137 .map_err(ExecutableSerializeError::Executable)? as u64;
138 let pos_bytes = pos.to_le_bytes();
139 let data = serializer.into_serializer().into_inner();
140 let mut out = Vec::with_capacity(MAGIC_HEADER.len() + pos_bytes.len() + data.len());
141 out.extend(&MAGIC_HEADER);
142 out.extend(data.as_slice());
143 out.extend(&pos_bytes);
144 Ok(out)
145 }
146}
147
148impl<'a> UniversalExecutableRef<'a> {
149 pub fn function_name(&self, index: FunctionIndex) -> Option<&str> {
153 let module = &self.compile_info.module;
154 for (name, idx) in module.exports.iter() {
156 match idx {
157 &ExportIndex::Function(fi) if fi == index => return Some(&*name),
158 _ => continue,
159 }
160 }
161 if let Some(r) = module.function_names.get(&index) {
162 return Some(&**r);
163 }
164 for ((_, field, _), idx) in module.imports.iter() {
165 match idx {
166 &ImportIndex::Function(fi) if fi == index => return Some(&*field),
167 _ => continue,
168 }
169 }
170 None
171 }
172}
173
174pub(crate) fn unrkyv<T>(archive: &T::Archived) -> T
175where
176 T: rkyv::Archive,
177 T::Archived: rkyv::Deserialize<T, rkyv::Infallible>,
178{
179 Result::<_, std::convert::Infallible>::unwrap(rkyv::Deserialize::deserialize(
180 archive,
181 &mut rkyv::Infallible,
182 ))
183}