From 02477b6e5e3a859a5eb3ff3ce1ec104c297e6b83 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Wed, 28 Nov 2018 13:25:08 -0800 Subject: [PATCH] Added support for conditional emscripten --- src/apis/emscripten/env.rs | 4 +-- src/apis/emscripten/mod.rs | 4 +++ src/apis/emscripten/time.rs | 2 +- src/apis/emscripten/utils.rs | 2 +- src/bin/wasmer.rs | 2 +- src/webassembly/instance.rs | 57 +++++++++++++++++++++++------------- src/webassembly/mod.rs | 2 ++ 7 files changed, 48 insertions(+), 25 deletions(-) diff --git a/src/apis/emscripten/env.rs b/src/apis/emscripten/env.rs index 8d5d76583..f4726239f 100644 --- a/src/apis/emscripten/env.rs +++ b/src/apis/emscripten/env.rs @@ -45,7 +45,7 @@ pub extern "C" fn _getpwnam(name_ptr: c_int, instance: &mut Instance) -> c_int { unsafe { let passwd = &*libc_getpwnam(name.as_ptr()); let passwd_struct_offset = - (instance.emscripten_data.malloc)(mem::size_of::() as _, instance); + (instance.emscripten_data.as_ref().unwrap().malloc)(mem::size_of::() as _, instance); let passwd_struct_ptr = instance.memory_offset_addr(0, passwd_struct_offset as _) as *mut GuestPasswd; @@ -80,7 +80,7 @@ pub extern "C" fn _getgrnam(name_ptr: c_int, instance: &mut Instance) -> c_int { unsafe { let group = &*libc_getgrnam(name.as_ptr()); let group_struct_offset = - (instance.emscripten_data.malloc)(mem::size_of::() as _, instance); + (instance.emscripten_data.as_ref().unwrap().malloc)(mem::size_of::() as _, instance); let group_struct_ptr = instance.memory_offset_addr(0, group_struct_offset as _) as *mut GuestGroup; diff --git a/src/apis/emscripten/mod.rs b/src/apis/emscripten/mod.rs index cd3eb63ab..5c6861ec9 100644 --- a/src/apis/emscripten/mod.rs +++ b/src/apis/emscripten/mod.rs @@ -52,6 +52,10 @@ fn dynamictop_ptr(static_bump: u32) -> u32 { pub fn emscripten_set_up_memory(memory: &mut LinearMemory) { let dynamictop_ptr = dynamictop_ptr(STATIC_BUMP) as usize; + // We avoid failures of setting the u32 + if (dynamictop_ptr > memory.len()) { + return; + } let mem = &mut memory[dynamictop_ptr..dynamictop_ptr + mem::size_of::()]; LittleEndian::write_u32(mem, dynamic_base(STATIC_BUMP)); } diff --git a/src/apis/emscripten/time.rs b/src/apis/emscripten/time.rs index f36ebc3ba..76c9c5376 100644 --- a/src/apis/emscripten/time.rs +++ b/src/apis/emscripten/time.rs @@ -87,7 +87,7 @@ pub extern "C" fn _localtime(time_p: u32, instance: &mut Instance) -> c_int { // Webassembly allocation let tm_struct_offset = - (instance.emscripten_data.malloc)(mem::size_of::() as _, instance); + (instance.emscripten_data.as_ref().unwrap().malloc)(mem::size_of::() as _, instance); let tm_struct_ptr = instance.memory_offset_addr(0, tm_struct_offset as _) as *mut GuestTm; // Initializing diff --git a/src/apis/emscripten/utils.rs b/src/apis/emscripten/utils.rs index 0b13aaea3..22a9d199e 100644 --- a/src/apis/emscripten/utils.rs +++ b/src/apis/emscripten/utils.rs @@ -18,7 +18,7 @@ pub fn is_emscripten_module(module: &Module) -> bool { 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.malloc)(s.len() as _, instance); + let space_offset = (instance.emscripten_data.as_ref().unwrap().malloc)(s.len() as _, 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()); diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index abab5a970..ca31259cc 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -61,7 +61,7 @@ fn execute_wasm(wasm_path: PathBuf) -> Result<(), String> { webassembly::instantiate(wasm_binary, import_object) .map_err(|err| format!("Can't instantiate the WebAssembly module: {}", err))?; - if apis::is_emscripten_module(&module) { + if instance.emscripten_data.as_ref().is_some() { let func_index = match module.info.exports.get("_main") { Some(&webassembly::Export::Function(index)) => index, _ => panic!("_main emscripten function not found"), diff --git a/src/webassembly/instance.rs b/src/webassembly/instance.rs index e4a8ca7d9..60be26aad 100644 --- a/src/webassembly/instance.rs +++ b/src/webassembly/instance.rs @@ -111,7 +111,7 @@ pub struct Instance { pub start_func: Option, // Region start memory location // code_base: *const (), - pub emscripten_data: EmscriptenData, + pub emscripten_data: Option, } /// Contains pointers to data (heaps, globals, tables) needed @@ -135,6 +135,7 @@ pub struct InstanceOptions { pub mock_missing_imports: bool, pub mock_missing_globals: bool, pub mock_missing_tables: bool, + pub use_emscripten: bool, pub isa: Box, } @@ -478,7 +479,11 @@ impl Instance { let to_init = &mut mem[offset..offset + init.data.len()]; to_init.copy_from_slice(&init.data); } - crate::apis::emscripten::emscripten_set_up_memory(&mut memories[0]); + if options.use_emscripten { + debug!("emscripten::setup memory"); + crate::apis::emscripten::emscripten_set_up_memory(&mut memories[0]); + debug!("emscripten::finish setup memory"); + } } let start_func: Option = @@ -504,27 +509,39 @@ impl Instance { tables: tables_pointer[..].into(), }; - let emscripten_data = unsafe { - let malloc_index = - if let Some(Export::Function(index)) = module.info.exports.get("_malloc") { - index - } else { - panic!("Unable to find _malloc export") - }; - let malloc_addr = get_function_addr(&malloc_index, &import_functions, &functions); + let emscripten_data = if options.use_emscripten { + unsafe { + debug!("emscripten::initiating data"); + let malloc_export = module.info.exports.get("_malloc"); + let free_export = module.info.exports.get("_free"); + if malloc_export.is_none() || free_export.is_none() { + None + } + else { + let malloc_index = if let Some(Export::Function(malloc_index)) = malloc_export { + malloc_index + } + else { + panic!("Expected malloc function") + }; + let malloc_addr = get_function_addr(&malloc_index, &import_functions, &functions); - let free_index = if let Some(Export::Function(index)) = module.info.exports.get("_free") - { - index - } else { - panic!("Unable to find _free export") - }; - let free_addr = get_function_addr(&free_index, &import_functions, &functions); + let free_index = if let Some(Export::Function(free_index)) = free_export { + free_index + } + else { + panic!("Expected free export function") + }; + let free_addr = get_function_addr(&free_index, &import_functions, &functions); - EmscriptenData { - malloc: mem::transmute(malloc_addr), - free: mem::transmute(free_addr), + Some(EmscriptenData { + malloc: mem::transmute(malloc_addr), + free: mem::transmute(free_addr), + }) + } } + } else { + None }; Ok(Instance { diff --git a/src/webassembly/mod.rs b/src/webassembly/mod.rs index 7913b2a59..f62aa2e1e 100644 --- a/src/webassembly/mod.rs +++ b/src/webassembly/mod.rs @@ -22,6 +22,7 @@ pub use self::import_object::{ImportObject, ImportValue}; pub use self::instance::{Instance, InstanceOptions}; pub use self::memory::LinearMemory; pub use self::module::{Export, Module, ModuleInfo}; +use crate::apis::is_emscripten_module; pub struct ResultObject { /// A webassembly::Module object representing the compiled WebAssembly module. @@ -69,6 +70,7 @@ pub fn instantiate( mock_missing_imports: true, mock_missing_globals: true, mock_missing_tables: true, + use_emscripten: is_emscripten_module(&module), isa: isa, }, )?;