virtual_machine/
environment.rs1use core::{
2 ffi::{CStr, c_void},
3 marker::PhantomData,
4};
5
6use alloc::{
7 boxed::Box,
8 string::{String, ToString},
9 vec::Vec,
10};
11use wamr_rust_sdk::{
12 sys::{
13 wasm_exec_env_t, wasm_module_inst_t, wasm_runtime_addr_app_to_native,
14 wasm_runtime_addr_native_to_app, wasm_runtime_call_indirect, wasm_runtime_create_exec_env,
15 wasm_runtime_get_custom_data, wasm_runtime_get_exception,
16 wasm_runtime_get_exec_env_singleton, wasm_runtime_get_module_inst,
17 wasm_runtime_set_custom_data, wasm_runtime_set_instruction_count_limit,
18 wasm_runtime_validate_app_addr, wasm_runtime_validate_native_addr,
19 },
20 value::WasmValue,
21};
22
23use crate::{CustomData, Error, Instance, Result, WasmPointer, WasmUsize};
24
25pub type EnvironmentPointer = wasm_exec_env_t;
26
27#[derive(Debug, Clone, Copy)]
28pub struct Environment<'a>(EnvironmentPointer, PhantomData<&'a ()>);
29
30unsafe impl Send for Environment<'_> {}
31
32unsafe impl Sync for Environment<'_> {}
33
34impl Environment<'_> {
35 pub fn from_raw_pointer(raw_pointer: EnvironmentPointer) -> Result<Self> {
36 if raw_pointer.is_null() {
37 return Err(Error::InvalidPointer);
38 }
39
40 Ok(Self(raw_pointer as EnvironmentPointer, PhantomData))
41 }
42
43 pub fn from_instance(instance: &Instance) -> Result<Self> {
44 let instance_pointer = instance.get_inner_reference().get_inner_instance();
45
46 if instance_pointer.is_null() {
47 return Err(Error::InvalidPointer);
48 }
49 Ok(Self(
50 unsafe { wasm_runtime_get_exec_env_singleton(instance_pointer) },
51 PhantomData,
52 ))
53 }
54
55 pub fn get_or_initialize_custom_data(&self) -> Result<&CustomData> {
56 unsafe {
57 let custom_data =
58 wasm_runtime_get_custom_data(self.get_instance_pointer()) as *const CustomData;
59
60 let custom_data = if custom_data.is_null() {
61 let task = abi::get_instance().get_current_task_identifier();
62
63 let custom_data = Box::new(CustomData::new(task));
64
65 wasm_runtime_set_custom_data(
66 self.get_instance_pointer(),
67 Box::into_raw(custom_data) as *mut c_void,
68 );
69
70 wasm_runtime_get_custom_data(self.get_instance_pointer()) as *const CustomData
71 } else {
72 custom_data
73 };
74
75 Ok(&*custom_data)
76 }
77 }
78
79 pub unsafe fn convert_to_native_pointer<T>(&self, address: WasmPointer) -> Option<*mut T> {
84 unsafe {
85 let pointer =
86 wasm_runtime_addr_app_to_native(self.get_instance_pointer(), address as u64);
87
88 if pointer.is_null() {
89 return None;
90 }
91
92 Some(pointer as *mut T)
93 }
94 }
95
96 pub unsafe fn convert_to_wasm_pointer<T>(&self, pointer: *const T) -> WasmPointer {
101 unsafe {
102 wasm_runtime_addr_native_to_app(self.get_instance_pointer(), pointer as *mut c_void)
103 as WasmPointer
104 }
105 }
106
107 pub fn validate_wasm_pointer(&self, address: WasmPointer, size: WasmUsize) -> bool {
108 unsafe {
109 wasm_runtime_validate_app_addr(self.get_instance_pointer(), address as u64, size as u64)
110 }
111 }
112
113 pub fn validate_native_pointer<T>(&self, pointer: *const T, size: u64) -> bool {
114 unsafe {
115 wasm_runtime_validate_native_addr(
116 self.get_instance_pointer(),
117 pointer as *mut c_void,
118 size,
119 )
120 }
121 }
122
123 pub fn call_indirect_function(
126 &self,
127 function_index: u32,
128 parameters: &Vec<WasmValue>,
129 ) -> Result<()> {
130 let mut arguments = Vec::new();
131
132 for parameter in parameters {
133 arguments.append(&mut parameter.encode());
134 }
135
136 if arguments.is_empty() {
137 arguments.append(&mut WasmValue::I32(0).encode());
138 }
139
140 if !unsafe {
141 wasm_runtime_call_indirect(
142 self.0,
143 function_index,
144 arguments.len() as u32,
145 arguments.as_mut_ptr(),
146 )
147 } {
148 let exception_message =
149 unsafe { wasm_runtime_get_exception(self.get_instance_pointer()) };
150 let exception_message = unsafe { CStr::from_ptr(exception_message) };
151 let exception_message =
152 String::from_utf8_lossy(exception_message.to_bytes()).to_string();
153
154 return Err(Error::ExecutionError(exception_message));
155 }
156
157 Ok(())
158 }
159
160 pub fn create_environment(&self, stack_size: usize) -> Result<Self> {
163 let execution_environment =
164 unsafe { wasm_runtime_create_exec_env(self.get_instance_pointer(), stack_size as u32) };
165
166 if execution_environment.is_null() {
167 return Err(Error::ExecutionError(
168 "Execution environment creation failed".to_string(),
169 ));
170 }
171
172 Ok(Self(execution_environment, PhantomData))
173 }
174
175 fn get_instance_pointer(&self) -> wasm_module_inst_t {
185 unsafe { wasm_runtime_get_module_inst(self.0) }
186 }
187
188 #[allow(dead_code)]
189 pub(crate) fn get_inner_reference(&self) -> EnvironmentPointer {
190 self.0
191 }
192}