From 44a745e4f5f503307783e6fda1b53c5f12398bee Mon Sep 17 00:00:00 2001 From: Syrus Date: Mon, 10 Dec 2018 16:23:14 -0800 Subject: [PATCH] Added start_instance function --- src/bin/wasmer.rs | 88 +-------------------------------------- src/webassembly/mod.rs | 93 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 87 deletions(-) diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index e15ef0d7c..76a6096f4 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -7,7 +7,6 @@ use std::io::Read; use std::path::PathBuf; use std::process::exit; -use apis::emscripten::{allocate_on_stack, allocate_cstr_on_stack}; use structopt::StructOpt; use wasmer::*; @@ -72,41 +71,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> { webassembly::instantiate(wasm_binary, import_object) .map_err(|err| format!("Can't instantiate the WebAssembly module: {}", err))?; - if apis::emscripten::is_emscripten_module(&module) { - - // Emscripten __ATINIT__ - if let Some(&webassembly::Export::Function(environ_constructor_index)) = module.info.exports.get("___emscripten_environ_constructor") { - debug!("emscripten::___emscripten_environ_constructor"); - let ___emscripten_environ_constructor: extern "C" fn(&webassembly::Instance) = - get_instance_function!(instance, environ_constructor_index); - call_protected!(___emscripten_environ_constructor(&instance)).map_err(|err| format!("{}", err))?; - }; - - // TODO: We also need to handle TTY.init() and SOCKFS.root = FS.mount(SOCKFS, {}, null) - let func_index = match module.info.exports.get("_main") { - Some(&webassembly::Export::Function(index)) => index, - _ => panic!("_main emscripten function not found"), - }; - - let main: extern "C" fn(u32, u32, &webassembly::Instance) = - get_instance_function!(instance, func_index); - - let (argc, argv) = store_module_arguments(options, &mut instance); - - return call_protected!(main(argc, argv, &instance)).map_err(|err| format!("{}", err)); - // TODO: We should implement emscripten __ATEXIT__ - } else { - let func_index = - instance - .start_func - .unwrap_or_else(|| match module.info.exports.get("main") { - Some(&webassembly::Export::Function(index)) => index, - _ => panic!("Main function not found"), - }); - let main: extern "C" fn(&webassembly::Instance) = - get_instance_function!(instance, func_index); - return call_protected!(main(&instance)).map_err(|err| format!("{}", err)); - } + webassembly::start_instance(&module, &mut instance, options.path.to_str().unwrap(), options.args.iter().map(|arg| arg.as_str()).collect()) } fn run(options: Run) { @@ -127,54 +92,3 @@ fn main() { CLIOptions::SelfUpdate => update::self_update(), } } - -fn store_module_arguments(options: &Run, instance: &mut webassembly::Instance) -> (u32, u32) { - let argc = options.args.len() + 1; - - let (argv_offset, argv_slice): (_, &mut [u32]) = unsafe { allocate_on_stack(((argc + 1) * 4) as u32, instance) }; - assert!(argv_slice.len() >= 1); - - argv_slice[0] = unsafe { allocate_cstr_on_stack(options.path.to_str().unwrap(), instance).0 }; - - for (slot, arg) in argv_slice[1..argc].iter_mut().zip(options.args.iter()) { - *slot = unsafe { allocate_cstr_on_stack(&arg, instance).0 }; - } - - argv_slice[argc] = 0; - - (argc as u32, argv_offset) -} - -// 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(); -// let arg_length = options.args.len() + 1; - -// arg_values.reserve_exact(arg_length); -// arg_addrs.reserve_exact(arg_length); - -// // Push name of wasm file -// arg_values.push(format!("{}\0", options.path.to_str().unwrap())); -// arg_addrs.push(arg_values[0].as_ptr()); - -// // Push additional arguments -// for (i, arg) in options.args.iter().enumerate() { -// arg_values.push(format!("{}\0", arg)); -// arg_addrs.push(arg_values[i + 1].as_ptr()); -// } - -// // Get argument count and pointer to addresses -// let argv = arg_addrs.as_ptr() as *mut *mut i8; -// let argc = arg_length as u32; - -// // Copy the the arguments into the wasm memory and get offset -// let argv_offset = unsafe { -// copy_cstr_array_into_wasm(argc, argv, instance) -// }; - -// debug!("argc = {:?}", argc); -// debug!("argv = {:?}", arg_addrs); - -// (argc, argv_offset) -// } diff --git a/src/webassembly/mod.rs b/src/webassembly/mod.rs index 2b1b45a24..bf65cc6e8 100644 --- a/src/webassembly/mod.rs +++ b/src/webassembly/mod.rs @@ -140,3 +140,96 @@ pub fn validate_or_error(bytes: &[u8]) -> Result<(), ErrorKind> { } } } + + +use apis::emscripten::{allocate_on_stack, allocate_cstr_on_stack}; + +fn store_module_arguments(path: &str, args: Vec<&str>, instance: &mut Instance) -> (u32, u32) { + let argc = args.len() + 1; + + let (argv_offset, argv_slice): (_, &mut [u32]) = unsafe { allocate_on_stack(((argc + 1) * 4) as u32, instance) }; + assert!(argv_slice.len() >= 1); + + argv_slice[0] = unsafe { allocate_cstr_on_stack(path, instance).0 }; + + for (slot, arg) in argv_slice[1..argc].iter_mut().zip(args.iter()) { + *slot = unsafe { allocate_cstr_on_stack(&arg, instance).0 }; + } + + argv_slice[argc] = 0; + + (argc as u32, argv_offset) +} + +// 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(); +// let arg_length = options.args.len() + 1; + +// arg_values.reserve_exact(arg_length); +// arg_addrs.reserve_exact(arg_length); + +// // Push name of wasm file +// arg_values.push(format!("{}\0", options.path.to_str().unwrap())); +// arg_addrs.push(arg_values[0].as_ptr()); + +// // Push additional arguments +// for (i, arg) in options.args.iter().enumerate() { +// arg_values.push(format!("{}\0", arg)); +// arg_addrs.push(arg_values[i + 1].as_ptr()); +// } + +// // Get argument count and pointer to addresses +// let argv = arg_addrs.as_ptr() as *mut *mut i8; +// let argc = arg_length as u32; + +// // Copy the the arguments into the wasm memory and get offset +// let argv_offset = unsafe { +// copy_cstr_array_into_wasm(argc, argv, instance) +// }; + +// debug!("argc = {:?}", argc); +// debug!("argv = {:?}", arg_addrs); + +// (argc, argv_offset) +// } + + +pub fn start_instance(module: &Module, instance: &mut Instance, path: &str, args: Vec<&str>) -> Result<(), String> { + if is_emscripten_module(&module) { + + // Emscripten __ATINIT__ + if let Some(&Export::Function(environ_constructor_index)) = module.info.exports.get("___emscripten_environ_constructor") { + debug!("emscripten::___emscripten_environ_constructor"); + let ___emscripten_environ_constructor: extern "C" fn(&Instance) = + get_instance_function!(instance, environ_constructor_index); + call_protected!(___emscripten_environ_constructor(&instance)).map_err(|err| format!("{}", err))?; + }; + + // TODO: We also need to handle TTY.init() and SOCKFS.root = FS.mount(SOCKFS, {}, null) + let func_index = match module.info.exports.get("_main") { + Some(&Export::Function(index)) => index, + _ => panic!("_main emscripten function not found"), + }; + + let main: extern "C" fn(u32, u32, &Instance) = + get_instance_function!(instance, func_index); + + let (argc, argv) = store_module_arguments(path, args, instance); + + return call_protected!(main(argc, argv, &instance)).map_err(|err| format!("{}", err)); + // TODO: We should implement emscripten __ATEXIT__ + } else { + let func_index = + instance + .start_func + .unwrap_or_else(|| match module.info.exports.get("main") { + Some(&Export::Function(index)) => index, + _ => panic!("Main function not found"), + }); + let main: extern "C" fn(&Instance) = + get_instance_function!(instance, func_index); + return call_protected!(main(&instance)).map_err(|err| format!("{}", err)); + } +}