From 28a668f38ccc4c921f96bc303aacfe67bc007de6 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Thu, 6 Dec 2018 15:21:58 -0500 Subject: [PATCH] Stack allocate arguments --- src/apis/emscripten/utils.rs | 33 ++++++++++++++++++++++----------- src/bin/wasmer.rs | 8 ++++---- src/webassembly/instance.rs | 8 ++++++++ 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/apis/emscripten/utils.rs b/src/apis/emscripten/utils.rs index 3d9df7989..d6b4bc83f 100644 --- a/src/apis/emscripten/utils.rs +++ b/src/apis/emscripten/utils.rs @@ -17,30 +17,41 @@ pub fn is_emscripten_module(module: &Module) -> bool { return false; } -pub unsafe fn copy_cstr_into_wasm(instance: &Instance, cstr: *const c_char) -> u32 { +pub unsafe fn copy_cstr_into_wasm(instance: &mut Instance, cstr: *const c_char) -> u32 { let s = CStr::from_ptr(cstr).to_str().unwrap(); - let space_offset = (instance.emscripten_data.as_ref().unwrap().malloc)(s.len() as _, instance); + let cstr_len = s.len(); + let space_offset = (instance.emscripten_data.as_ref().unwrap().stack_alloc)((cstr_len as u32) + 1, instance); let raw_memory = instance.memory_offset_addr(0, space_offset as _) as *mut u8; - let slice = slice::from_raw_parts_mut(raw_memory, s.len()); + let slice = slice::from_raw_parts_mut(raw_memory, cstr_len); for (byte, loc) in s.bytes().zip(slice.iter_mut()) { *loc = byte; } + + *raw_memory.add(cstr_len) = 0; + space_offset } -pub unsafe fn copy_cstr_array_into_wasm(array_count: u32, array: *mut *mut c_char, instance: &Instance) -> u32 { - let array_offset = (instance.emscripten_data.as_ref().unwrap().malloc)((array_count as usize * size_of::()) as _, instance); +pub unsafe fn copy_cstr_array_into_wasm(array_count: u32, array: *mut *mut c_char, instance: &mut Instance) -> u32 { + let array_offset = (instance.emscripten_data.as_ref().unwrap().stack_alloc)((array_count as usize * size_of::()) as _, instance); let array_addr = instance.memory_offset_addr(0, array_offset as _) as *mut u32; - for i in 0..array_count { - let offset = copy_cstr_into_wasm( - instance, - *array.offset(i as isize) - ); - *array_addr.offset(i as isize) = offset; + let array_slice = slice::from_raw_parts_mut(array_addr, array_count as usize); + + for (i, ptr) in array_slice.iter_mut().enumerate() { + let offset = copy_cstr_into_wasm(instance, *array.add(i)); + *ptr = offset; } + // for i in 0..array_count { + // let offset = copy_cstr_into_wasm( + // instance, + // *array.offset(i as isize) + // ); + // *array_addr.offset(i as isize) = offset; + // } + // let first_arg_addr = instance.memory_offset_addr(0, *array_addr.offset(0) as _) as *const i8; // debug!("###### argv[0] = {:?}", CStr::from_ptr(first_arg_addr)); diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index f63c72563..f2b9ef70b 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -68,7 +68,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> { // TODO: We should instantiate after compilation, so we provide the // emscripten environment conditionally based on the module let import_object = apis::generate_emscripten_env(); - let webassembly::ResultObject { module, instance } = + let webassembly::ResultObject { module, mut instance } = webassembly::instantiate(wasm_binary, import_object) .map_err(|err| format!("Can't instantiate the WebAssembly module: {}", err))?; @@ -91,7 +91,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> { let main: extern "C" fn(u32, u32, &webassembly::Instance) = get_instance_function!(instance, func_index); - let (argc, argv) = get_module_arguments(options, &instance); + let (argc, argv) = get_module_arguments(options, &mut instance); return call_protected!(main(argc, argv, &instance)).map_err(|err| format!("{}", err)); // TODO: We should implement emscripten __ATEXIT__ @@ -128,7 +128,7 @@ fn main() { } } -fn get_module_arguments(options: &Run, instance: &webassembly::Instance) -> (u32, u32) { +fn get_module_arguments(options: &Run, instance: &mut webassembly::Instance) -> (u32, u32) { // Application Arguments let mut arg_values: Vec = Vec::new(); let mut arg_addrs: Vec<*const u8> = Vec::new(); @@ -153,7 +153,7 @@ fn get_module_arguments(options: &Run, instance: &webassembly::Instance) -> (u32 // Copy the the arguments into the wasm memory and get offset let argv_offset = unsafe { - copy_cstr_array_into_wasm(argc, argv, &instance) + copy_cstr_array_into_wasm(argc, argv, instance) }; debug!("argc = {:?}", argc); diff --git a/src/webassembly/instance.rs b/src/webassembly/instance.rs index 57c3e1843..c68b33968 100644 --- a/src/webassembly/instance.rs +++ b/src/webassembly/instance.rs @@ -74,6 +74,7 @@ pub struct EmscriptenData { pub free: extern "C" fn(i32, &mut Instance), pub memalign: extern "C" fn (u32, u32, &mut Instance) -> u32, pub memset: extern "C" fn(u32, i32, u32, &mut Instance) -> u32, + pub stack_alloc: extern "C" fn (u32, &mut Instance) -> u32, } impl fmt::Debug for EmscriptenData { @@ -550,11 +551,13 @@ impl Instance { let free_export = module.info.exports.get("_free"); let memalign_export = module.info.exports.get("_memalign"); let memset_export = module.info.exports.get("_memset"); + let stack_alloc_export = module.info.exports.get("stackAlloc"); let mut malloc_addr = 0 as *const u8; let mut free_addr = 0 as *const u8; let mut memalign_addr = 0 as *const u8; let mut memset_addr = 0 as *const u8; + let mut stack_alloc_addr = 0 as _; if malloc_export.is_none() && free_export.is_none() && memalign_export.is_none() && memset_export.is_none() { None @@ -575,11 +578,16 @@ impl Instance { memset_addr = get_function_addr(&memset_index, &import_functions, &functions); } + if let Some(Export::Function(stack_alloc_index)) = stack_alloc_export { + stack_alloc_addr = get_function_addr(&stack_alloc_index, &import_functions, &functions); + } + Some(EmscriptenData { malloc: mem::transmute(malloc_addr), free: mem::transmute(free_addr), memalign: mem::transmute(memalign_addr), memset: mem::transmute(memset_addr), + stack_alloc: mem::transmute(stack_alloc_addr), }) } }