in executor/src/wamr.rs [102:254]
fn execute(
&self,
_name: String,
arguments: FunctionArguments,
payload: Vec<u8>,
runtime: FunctionRuntime,
) -> anyhow::Result<String> {
let wa_argv: Vec<_> = arguments.into_vec();
let mut error_buf = [0u8; DEFAULT_ERROR_BUF_SIZE];
let entry_name = CString::new("entrypoint").expect("CString::new failed");
set_thread_context(Context::new(runtime))?;
let ret = unsafe { wasm_runtime_init() };
assert!(ret);
// export native function
let export_symbols: [NativeSymbol; 5] = [
NativeSymbol {
symbol: b"teaclave_open_input\0".as_ptr() as _,
func_ptr: wasm_open_input as *const c_void,
signature: b"($)i\0".as_ptr() as _,
attachment: std::ptr::null(),
},
NativeSymbol {
symbol: b"teaclave_create_output\0".as_ptr() as _,
func_ptr: wasm_create_output as *const c_void,
signature: b"($)i\0".as_ptr() as _,
attachment: std::ptr::null(),
},
NativeSymbol {
symbol: b"teaclave_read_file\0".as_ptr() as _,
func_ptr: wasm_read_file as *const c_void,
signature: b"(i*~)i\0".as_ptr() as _,
attachment: std::ptr::null(),
},
NativeSymbol {
symbol: b"teaclave_write_file\0".as_ptr() as _,
func_ptr: wasm_write_file as *const c_void,
signature: b"(i*~)i\0".as_ptr() as _,
attachment: std::ptr::null(),
},
NativeSymbol {
symbol: b"teaclave_close_file\0".as_ptr() as _,
func_ptr: wasm_close_file as *const c_void,
signature: b"(i)i\0".as_ptr() as _,
attachment: std::ptr::null(),
},
];
let register_succeeded = unsafe {
wasm_runtime_register_natives(
b"env\0".as_ptr() as _,
export_symbols.as_ptr(),
export_symbols.len() as u32,
)
};
assert!(register_succeeded);
let module = unsafe {
wasm_runtime_load(
payload.as_ptr(),
payload.len() as u32,
error_buf.as_mut_ptr(),
error_buf.len() as u32,
)
};
assert!((module as usize) != 0);
error_buf = [0u8; DEFAULT_ERROR_BUF_SIZE];
let module_instance = unsafe {
wasm_runtime_instantiate(
module,
DEFAULT_STACK_SIZE,
DEFAULT_HEAP_SIZE,
error_buf.as_mut_ptr(),
error_buf.len() as u32,
)
};
assert!((module_instance as usize) != 0);
let entry_func = unsafe {
wasm_runtime_lookup_function(
module_instance,
entry_name.as_ptr() as _,
std::ptr::null(),
)
};
assert!((entry_func as usize) != 0);
let exec_env = unsafe { wasm_runtime_create_exec_env(module_instance, DEFAULT_STACK_SIZE) };
assert!((exec_env as usize) != 0);
// prepare the arguments
// for best compatibility with Teaclave, the function signature is `int entrypoint(int argc, char* argv[])`
let cstr_argv: Vec<_> = wa_argv
.iter()
.map(|arg| CString::new(arg.as_str()).unwrap())
.collect();
let wasm_argc = 2;
let p_argv: Vec<u32> = cstr_argv
.iter() // do NOT into_iter()
.map(|arg| unsafe {
wasm_runtime_module_dup_data(
module_instance,
arg.as_ptr() as *const u8,
arg.to_bytes_with_nul().len() as u32,
)
})
.collect();
let func_argv = unsafe {
wasm_runtime_module_dup_data(
module_instance,
p_argv.as_ptr() as *const u8,
(p_argv.len() * 4) as u32,
)
};
let wasm_argv: [u32; 2] = [p_argv.len() as u32, func_argv];
let result =
unsafe { wasm_runtime_call_wasm(exec_env, entry_func, wasm_argc, wasm_argv.as_ptr()) };
// clean WAMR allocated memory
let _ = p_argv
.iter()
.map(|addr| unsafe { wasm_runtime_module_free(module_instance, *addr) });
unsafe { wasm_runtime_module_free(module_instance, func_argv) };
let result = if result {
let rv = wasm_argv[0] as c_int;
log::debug!(
"IN WAMicroRuntime::execute after `wasm_runtime_call_wasm`, {:?}",
rv
);
Ok(rv.to_string())
} else {
let error = unsafe { CStr::from_ptr(wasm_runtime_get_exception(module_instance)) };
log::debug!("WAMR ERROR: {:?}", error);
Ok(error.to_str().unwrap().to_string())
};
unsafe { wasm_runtime_deinstantiate(module_instance) };
unsafe { wasm_runtime_unload(module) };
unsafe { wasm_runtime_destroy() };
reset_thread_context()?;
result
}