diff --git a/src/apis/emscripten/mod.rs b/src/apis/emscripten/mod.rs index 94619bb8c..f8317ad56 100644 --- a/src/apis/emscripten/mod.rs +++ b/src/apis/emscripten/mod.rs @@ -4,9 +4,11 @@ use crate::webassembly::{ImportObject, ImportValue}; mod memory; mod process; mod io; +mod utils; // SYSCALLS use super::host; +pub use self::utils::is_emscripten_module; pub fn generate_emscripten_env<'a, 'b>() -> ImportObject<&'a str, &'b str> { let mut import_object = ImportObject::new(); diff --git a/src/apis/emscripten/tests/is_emscripten_false.wast b/src/apis/emscripten/tests/is_emscripten_false.wast new file mode 100644 index 000000000..4e4aba9d4 --- /dev/null +++ b/src/apis/emscripten/tests/is_emscripten_false.wast @@ -0,0 +1,9 @@ +(module + (table 0 anyfunc) + (memory $0 1) + (export "memory" (memory $0)) + (export "main" (func $main)) + (func $main (; 1 ;) (result i32) + (i32.const 0) + ) +) diff --git a/src/apis/emscripten/tests/is_emscripten_true.wast b/src/apis/emscripten/tests/is_emscripten_true.wast new file mode 100644 index 000000000..2499e09da --- /dev/null +++ b/src/apis/emscripten/tests/is_emscripten_true.wast @@ -0,0 +1,17 @@ +(module + (type $FUNCSIG$ii (func (param i32) (result i32))) + (import "env" "puts" (func $puts (param i32) (result i32))) + (table 0 anyfunc) + (memory $0 1) + (data (i32.const 16) "hello, world!\00") + (export "memory" (memory $0)) + (export "main" (func $main)) + (func $main (; 1 ;) (result i32) + (drop + (call $puts + (i32.const 16) + ) + ) + (i32.const 0) + ) +) diff --git a/src/apis/emscripten/utils.rs b/src/apis/emscripten/utils.rs new file mode 100644 index 000000000..b6a18ccfb --- /dev/null +++ b/src/apis/emscripten/utils.rs @@ -0,0 +1,35 @@ +use crate::webassembly::module::Module; + +/// We check if a provided module is an Emscripten generated one +pub fn is_emscripten_module(module: &Module) -> bool { + for (module, field) in &module.info.imported_funcs { + if module == "env" { + return true; + } + } + return false; +} + + +#[cfg(test)] +mod tests { + use crate::webassembly::instantiate; + use super::is_emscripten_module; + use super::super::generate_emscripten_env; + + #[test] + fn should_detect_emscripten_files() { + let wasm_bytes = include_wast2wasm_bytes!("tests/is_emscripten_true.wast"); + let import_object = generate_emscripten_env(); + let result_object = instantiate(wasm_bytes, import_object).expect("Not compiled properly"); + assert!(is_emscripten_module(&result_object.module)); + } + + #[test] + fn should_detect_non_emscripten_files() { + let wasm_bytes = include_wast2wasm_bytes!("tests/is_emscripten_false.wast"); + let import_object = generate_emscripten_env(); + let result_object = instantiate(wasm_bytes, import_object).expect("Not compiled properly"); + assert!(!is_emscripten_module(&result_object.module)); + } +} \ No newline at end of file diff --git a/src/apis/mod.rs b/src/apis/mod.rs index 0c83d3b3f..964fa86d6 100644 --- a/src/apis/mod.rs +++ b/src/apis/mod.rs @@ -1,5 +1,4 @@ pub mod emscripten; pub mod host; -pub use self::emscripten::generate_emscripten_env; - +pub use self::emscripten::{generate_emscripten_env, is_emscripten_module}; diff --git a/src/main.rs b/src/main.rs index 1d0ed58a6..c3d3c8ba6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -71,22 +71,32 @@ fn execute_wasm(wasm_path: PathBuf) -> Result<(), String> { wasm_binary = wabt::wat2wasm(wasm_binary) .map_err(|err| format!("Can't convert from wast to wasm: {:?}", err))?; } - + // 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 } = webassembly::instantiate(wasm_binary, import_object) .map_err(|err| format!("Can't instantiate the WebAssembly module: {}", err))?; - // webassembly::utils::print_instance_offsets(&instance); - - let func_index = instance - .start_func - .unwrap_or_else(|| match module.info.exports.get("main").or(module.info.exports.get("_main")) { + if apis::is_emscripten_module(&module) { + let func_index = match module.info.exports.get("main") { Some(&webassembly::Export::Function(index)) => index, - _ => panic!("Main function not found"), - }); - let main: extern fn(u32, u32, &webassembly::Instance) = get_instance_function!(instance, func_index); - main(0, 0, &instance); + _ => panic!("_main emscripten function not found"), + }; + let main: extern fn(u32, u32, &webassembly::Instance) = get_instance_function!(instance, func_index); + main(0, 0, &instance); + } + 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 fn(&webassembly::Instance) = get_instance_function!(instance, func_index); + main(&instance); + } + Ok(()) }