wasmer_wasix/syscalls/wasix/
reflect_signature.rs1use crate::{WasiEnv, WasiError, state::FunctionLookupError};
2use tracing::{instrument, trace};
3use wasmer::{FunctionEnvMut, MemorySize, Type, WasmPtr, WasmSlice};
4use wasmer_wasix_types::wasi::{Bool, Errno, ReflectionResult, WasmValueType};
5
6fn serialize_types(types: &[Type]) -> Result<Vec<WasmValueType>, Errno> {
7 types
8 .iter()
9 .map(|t| {
10 WasmValueType::try_from(*t).map_err(|_| {
11 trace!("Cannot convert type {} to WasmValueType", t);
12 Errno::Inval
13 })
14 })
15 .collect::<Result<Vec<_>, _>>()
16}
17
18#[instrument(
32 level = "trace",
33 skip_all,
34 fields(
35 %function_id,
36 argument_types_ptr = argument_types.offset().into(),
37 argument_types_len,
38 result_types_ptr = result_types.offset().into(),
39 result_types_len,
40 result = result.offset().into()),
41 ret
42)]
43pub fn reflect_signature<M: MemorySize>(
44 mut ctx: FunctionEnvMut<'_, WasiEnv>,
45 function_id: u32,
46 argument_types: WasmPtr<WasmValueType, M>,
47 argument_types_len: u16,
48 result_types: WasmPtr<WasmValueType, M>,
49 result_types_len: u16,
50 result: WasmPtr<ReflectionResult, M>,
51) -> Result<Errno, WasiError> {
52 let (env, mut store) = ctx.data_and_store_mut();
53
54 let function_lookup_result = env
55 .inner()
56 .indirect_function_table_lookup(&mut store, function_id);
57
58 let memory = unsafe { env.memory_view(&store) };
59 let signature_info = result.deref(&memory);
60
61 let function = match function_lookup_result {
63 Ok(f) => f,
64 Err(e) => {
65 let cacheable = match e {
66 FunctionLookupError::Empty(_) => {
67 if env.inner().is_closure(function_id) {
68 Bool::False
69 } else {
70 Bool::True
71 }
72 }
73 FunctionLookupError::OutOfBounds(_) => Bool::False,
74 _ => Bool::True,
75 };
76 trace!(
77 "Failed to look up function in indirect function table: {}",
78 e
79 );
80 wasi_try_mem_ok!(signature_info.write(ReflectionResult {
81 cacheable,
82 arguments: 0,
83 results: 0,
84 }));
85 return Ok(e.into());
86 }
87 };
88
89 let is_closure = env.inner().is_closure(function_id);
90 let cacheable = if is_closure { Bool::False } else { Bool::True };
91
92 let function_type = function.ty(&store);
93 let arguments = function_type.params();
94 let results = function_type.results();
95
96 wasi_try_mem_ok!(signature_info.write(ReflectionResult {
97 cacheable,
98 arguments: arguments.len() as u16,
99 results: results.len() as u16,
100 }));
101
102 if (arguments.len() as u16 > argument_types_len) {
103 trace!(
104 "Provided arguments buffer is too small {}/{}",
105 argument_types_len,
106 arguments.len()
107 );
108 return Ok(Errno::Overflow);
109 }
110 if (results.len() as u16 > result_types_len) {
111 trace!(
112 "Provided results buffer is too small {}/{}",
113 result_types_len,
114 results.len()
115 );
116 return Ok(Errno::Overflow);
117 }
118
119 let serialized_argument_types = wasi_try_ok!(serialize_types(function_type.params()));
120 let serialized_result_types = wasi_try_ok!(serialize_types(function_type.results()));
121
122 let mut argument_types_slice = wasi_try_mem_ok!(WasmSlice::<WasmValueType>::new(
123 &memory,
124 argument_types.offset().into(),
125 arguments.len() as u64
126 ));
127 let mut result_types_slice = wasi_try_mem_ok!(WasmSlice::<WasmValueType>::new(
128 &memory,
129 result_types.offset().into(),
130 results.len() as u64
131 ));
132
133 wasi_try_mem_ok!(argument_types_slice.write_slice(&serialized_argument_types));
134 wasi_try_mem_ok!(result_types_slice.write_slice(&serialized_result_types));
135
136 Ok(Errno::Success)
137}