diff --git a/lib/clif-backend/src/lib.rs b/lib/clif-backend/src/lib.rs index 88de51e12..d09da6812 100644 --- a/lib/clif-backend/src/lib.rs +++ b/lib/clif-backend/src/lib.rs @@ -16,7 +16,7 @@ use target_lexicon::Triple; use wasmer_runtime_core::cache::{Artifact, Error as CacheError}; use wasmer_runtime_core::{ - backend::{Compiler, Token}, + backend::{Compiler, CompilerConfig, Token}, error::{CompileError, CompileResult}, module::ModuleInner, }; @@ -39,12 +39,17 @@ impl CraneliftCompiler { impl Compiler for CraneliftCompiler { /// Compiles wasm binary to a wasmer module. - fn compile(&self, wasm: &[u8], _: Token) -> CompileResult { + fn compile( + &self, + wasm: &[u8], + compiler_config: CompilerConfig, + _: Token, + ) -> CompileResult { validate(wasm)?; let isa = get_isa(); - let mut module = module::Module::new(); + let mut module = module::Module::new(&compiler_config); let module_env = module_env::ModuleEnv::new(&mut module, &*isa); let func_bodies = module_env.translate(wasm)?; diff --git a/lib/clif-backend/src/module.rs b/lib/clif-backend/src/module.rs index 9e934ee0a..2ae495acd 100644 --- a/lib/clif-backend/src/module.rs +++ b/lib/clif-backend/src/module.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use wasmer_runtime_core::cache::{Artifact, Error as CacheError}; use wasmer_runtime_core::{ - backend::Backend, + backend::{Backend, CompilerConfig}, error::CompileResult, module::{ModuleInfo, ModuleInner, StringTable}, structures::{Map, TypedIndex}, @@ -25,7 +25,7 @@ pub struct Module { } impl Module { - pub fn new() -> Self { + pub fn new(compiler_config: &CompilerConfig) -> Self { Self { info: ModuleInfo { memories: Map::new(), @@ -50,6 +50,7 @@ impl Module { namespace_table: StringTable::new(), name_table: StringTable::new(), + em_symbol_map: compiler_config.symbol_map.clone(), }, } } diff --git a/lib/clif-backend/src/resolver.rs b/lib/clif-backend/src/resolver.rs index 5a3763827..e2706b6e1 100644 --- a/lib/clif-backend/src/resolver.rs +++ b/lib/clif-backend/src/resolver.rs @@ -374,26 +374,26 @@ fn round_up(n: usize, multiple: usize) -> usize { } extern "C" fn i32_print(_ctx: &mut vm::Ctx, n: i32) { - print!(" i32: {},", n); + eprint!(" i32: {},", n); } extern "C" fn i64_print(_ctx: &mut vm::Ctx, n: i64) { - print!(" i64: {},", n); + eprint!(" i64: {},", n); } extern "C" fn f32_print(_ctx: &mut vm::Ctx, n: f32) { - print!(" f32: {},", n); + eprint!(" f32: {},", n); } extern "C" fn f64_print(_ctx: &mut vm::Ctx, n: f64) { - print!(" f64: {},", n); + eprint!(" f64: {},", n); } extern "C" fn start_debug(ctx: &mut vm::Ctx, func_index: u32) { - if let Some(symbol_map) = &ctx.maybe_symbol_map { + if let Some(symbol_map) = unsafe { ctx.borrow_symbol_map() } { if let Some(fn_name) = symbol_map.get(&func_index) { - print!("func ({} ({})), args: [", fn_name, func_index); + eprint!("func ({} ({})), args: [", fn_name, func_index); return; } } - print!("func ({}), args: [", func_index); + eprint!("func ({}), args: [", func_index); } extern "C" fn end_debug(_ctx: &mut vm::Ctx) { - println!(" ]"); + eprintln!(" ]"); } diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index a09909ebe..94c5c87e3 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -14,6 +14,8 @@ use crate::{ }; use std::{any::Any, ptr::NonNull}; +use hashbrown::HashMap; + pub mod sys { pub use crate::sys::*; } @@ -38,11 +40,28 @@ impl Token { } } +/// Configuration data for the compiler +pub struct CompilerConfig { + /// Symbol information generated from emscripten; used for more detailed debug messages + pub symbol_map: Option>, +} + +impl Default for CompilerConfig { + fn default() -> CompilerConfig { + CompilerConfig { symbol_map: None } + } +} + pub trait Compiler { /// Compiles a `Module` from WebAssembly binary format. /// The `CompileToken` parameter ensures that this can only /// be called from inside the runtime. - fn compile(&self, wasm: &[u8], _: Token) -> CompileResult; + fn compile( + &self, + wasm: &[u8], + comp_conf: CompilerConfig, + _: Token, + ) -> CompileResult; unsafe fn from_cache(&self, cache: Artifact, _: Token) -> Result; } diff --git a/lib/runtime-core/src/instance.rs b/lib/runtime-core/src/instance.rs index f2b48f983..0d34bb5a5 100644 --- a/lib/runtime-core/src/instance.rs +++ b/lib/runtime-core/src/instance.rs @@ -13,7 +13,6 @@ use crate::{ types::{FuncIndex, FuncSig, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex, Value}, vm, }; -use hashbrown::HashMap; use std::{mem, sync::Arc}; pub(crate) struct InstanceInner { @@ -45,11 +44,7 @@ pub struct Instance { } impl Instance { - pub(crate) fn new( - module: Arc, - imports: &ImportObject, - maybe_symbol_map: Option>, - ) -> Result { + pub(crate) fn new(module: Arc, imports: &ImportObject) -> Result { // We need the backing and import_backing to create a vm::Ctx, but we need // a vm::Ctx to create a backing and an import_backing. The solution is to create an // uninitialized vm::Ctx and then initialize it in-place. @@ -68,12 +63,7 @@ impl Instance { // Initialize the vm::Ctx in-place after the backing // has been boxed. unsafe { - *inner.vmctx = vm::Ctx::new( - &mut inner.backing, - &mut inner.import_backing, - &module, - maybe_symbol_map, - ) + *inner.vmctx = vm::Ctx::new(&mut inner.backing, &mut inner.import_backing, &module) }; let instance = Instance { diff --git a/lib/runtime-core/src/lib.rs b/lib/runtime-core/src/lib.rs index 663e17534..1565ed621 100644 --- a/lib/runtime-core/src/lib.rs +++ b/lib/runtime-core/src/lib.rs @@ -68,7 +68,19 @@ pub fn compile_with( ) -> CompileResult { let token = backend::Token::generate(); compiler - .compile(wasm, token) + .compile(wasm, Default::default(), token) + .map(|inner| module::Module::new(Arc::new(inner))) +} + +/// The same as `compile_with` but takes a symbol map for use with debugging +pub fn compile_with_config( + wasm: &[u8], + compiler: &dyn backend::Compiler, + compiler_config: backend::CompilerConfig, +) -> CompileResult { + let token = backend::Token::generate(); + compiler + .compile(wasm, compiler_config, token) .map(|inner| module::Module::new(Arc::new(inner))) } diff --git a/lib/runtime-core/src/module.rs b/lib/runtime-core/src/module.rs index a7fe31412..361ffde7d 100644 --- a/lib/runtime-core/src/module.rs +++ b/lib/runtime-core/src/module.rs @@ -56,6 +56,8 @@ pub struct ModuleInfo { pub namespace_table: StringTable, pub name_table: StringTable, + + pub em_symbol_map: Option>, } /// A compiled WebAssembly module. @@ -100,12 +102,8 @@ impl Module { /// # Ok(()) /// # } /// ``` - pub fn instantiate( - &self, - import_object: &ImportObject, - maybe_symbol_map: Option>, - ) -> error::Result { - Instance::new(Arc::clone(&self.inner), import_object, maybe_symbol_map) + pub fn instantiate(&self, import_object: &ImportObject) -> error::Result { + Instance::new(Arc::clone(&self.inner), import_object) } pub fn cache(&self) -> Result { diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index d78bd09fc..394966d79 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -5,9 +5,10 @@ use crate::{ structures::TypedIndex, types::{LocalOrImport, MemoryIndex}, }; -use hashbrown::HashMap; use std::{ffi::c_void, mem, ptr}; +use hashbrown::HashMap; + /// The context of the currently running WebAssembly instance. /// /// @@ -25,8 +26,6 @@ pub struct Ctx { pub data: *mut c_void, pub data_finalizer: Option, - - pub maybe_symbol_map: Option>, } /// The internal context of the currently running WebAssembly instance. @@ -70,7 +69,6 @@ impl Ctx { local_backing: &mut LocalBacking, import_backing: &mut ImportBacking, module: &ModuleInner, - maybe_symbol_map: Option>, ) -> Self { Self { internal: InternalCtx { @@ -93,7 +91,6 @@ impl Ctx { data: ptr::null_mut(), data_finalizer: None, - maybe_symbol_map, } } @@ -126,7 +123,6 @@ impl Ctx { data, data_finalizer: Some(data_finalizer), - maybe_symbol_map: None, } } @@ -162,6 +158,10 @@ impl Ctx { }, } } + + pub unsafe fn borrow_symbol_map(&self) -> &Option> { + &(*self.module).info.em_symbol_map + } } #[doc(hidden)] diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index bcd8cf710..b589aa28b 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -110,7 +110,7 @@ pub mod units { pub mod cache; -use wasmer_runtime_core::backend::Compiler; +use wasmer_runtime_core::backend::{Compiler, CompilerConfig}; /// Compile WebAssembly binary code into a [`Module`]. /// This function is useful if it is necessary to @@ -129,6 +129,13 @@ pub fn compile(wasm: &[u8]) -> error::CompileResult { wasmer_runtime_core::compile_with(&wasm[..], default_compiler()) } +pub fn compile_with_config( + wasm: &[u8], + compiler_config: CompilerConfig, +) -> error::CompileResult { + wasmer_runtime_core::compile_with_config(&wasm[..], default_compiler(), compiler_config) +} + /// Compile and instantiate WebAssembly code without /// creating a [`Module`]. /// @@ -149,7 +156,7 @@ pub fn compile(wasm: &[u8]) -> error::CompileResult { /// depending on the cause of the failure. pub fn instantiate(wasm: &[u8], import_object: &ImportObject) -> error::Result { let module = compile(wasm)?; - module.instantiate(import_object, None) + module.instantiate(import_object) } /// Get a single instance of the default compiler to use. diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index 14989effb..61bd50dac 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -14,6 +14,7 @@ use wasmer::webassembly::InstanceABI; use wasmer::*; use wasmer_emscripten; use wasmer_runtime::cache::{Cache as BaseCache, FileSystemCache, WasmHash, WASMER_VERSION_HASH}; +use wasmer_runtime_core::backend::CompilerConfig; #[derive(Debug, StructOpt)] #[structopt(name = "wasmer", about = "Wasm execution runtime.")] @@ -46,9 +47,9 @@ struct Run { #[structopt(name = "--", raw(multiple = "true"))] args: Vec, - /// Symbol map - #[structopt(long = "symbol-map", parse(from_os_str))] - symbol_map: Option, + /// Emscripten symbol map + #[structopt(long = "em-symbol-map", parse(from_os_str))] + em_symbol_map: Option, } #[derive(Debug, StructOpt)] @@ -103,18 +104,18 @@ fn execute_wasm(options: &Run) -> Result<(), String> { ) })?; - let maybe_symbol_map = if let Some(symbol_map_path) = options.symbol_map.clone() { - let symbol_map_content: String = read_to_string(&symbol_map_path) + let em_symbol_map = if let Some(em_symbol_map_path) = options.em_symbol_map.clone() { + let em_symbol_map_content: String = read_to_string(&em_symbol_map_path) .map_err(|err| { format!( "Can't read symbol map file {}: {}", - symbol_map_path.as_os_str().to_string_lossy(), + em_symbol_map_path.as_os_str().to_string_lossy(), err, ) })? .to_owned(); - let mut symbol_map = HashMap::new(); - for line in symbol_map_content.lines() { + let mut em_symbol_map = HashMap::new(); + for line in em_symbol_map_content.lines() { let mut split = line.split(':'); let num_str = if let Some(ns) = split.next() { ns @@ -138,9 +139,9 @@ fn execute_wasm(options: &Run) -> Result<(), String> { } .to_owned(); - symbol_map.insert(num, name_str); + em_symbol_map.insert(num, name_str); } - Some(symbol_map) + Some(em_symbol_map) } else { None }; @@ -175,9 +176,13 @@ fn execute_wasm(options: &Run) -> Result<(), String> { module } Err(_) => { - let module = webassembly::compile(&wasm_binary[..]) - .map_err(|e| format!("Can't compile module: {:?}", e))?; - + let module = webassembly::compile_with_config( + &wasm_binary[..], + CompilerConfig { + symbol_map: em_symbol_map, + }, + ) + .map_err(|e| format!("Can't compile module: {:?}", e))?; // We try to save the module into a cache file cache.store(hash, module.clone()).unwrap_or_default(); @@ -186,8 +191,13 @@ fn execute_wasm(options: &Run) -> Result<(), String> { }; module } else { - webassembly::compile(&wasm_binary[..]) - .map_err(|e| format!("Can't compile module: {:?}", e))? + webassembly::compile_with_config( + &wasm_binary[..], + CompilerConfig { + symbol_map: em_symbol_map, + }, + ) + .map_err(|e| format!("Can't compile module: {:?}", e))? }; let (_abi, import_object, _em_globals) = if wasmer_emscripten::is_emscripten_module(&module) { @@ -206,7 +216,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> { }; let mut instance = module - .instantiate(&import_object, maybe_symbol_map) + .instantiate(&import_object) .map_err(|e| format!("Can't instantiate module: {:?}", e))?; webassembly::run_instance( diff --git a/src/webassembly.rs b/src/webassembly.rs index 542a5be9d..3b7aeaf8f 100644 --- a/src/webassembly.rs +++ b/src/webassembly.rs @@ -4,6 +4,7 @@ use wasmer_runtime::{ error::{CallResult, Result}, ImportObject, Instance, Module, }; +use wasmer_runtime_core::backend::CompilerConfig; use wasmer_runtime_core::types::Value; use wasmer_emscripten::{is_emscripten_module, run_emscripten_instance}; @@ -42,7 +43,7 @@ pub fn instantiate(buffer_source: &[u8], import_object: ImportObject) -> Result< let module = compile(&buffer_source[..])?; debug!("webassembly - instantiating"); - let instance = module.instantiate(&import_object, None)?; + let instance = module.instantiate(&import_object)?; debug!("webassembly - instance created"); Ok(ResultObject { @@ -76,6 +77,14 @@ pub fn compile(buffer_source: &[u8]) -> Result { Ok(module) } +pub fn compile_with_config( + buffer_source: &[u8], + compiler_config: CompilerConfig, +) -> Result { + let module = runtime::compile_with_config(buffer_source, compiler_config)?; + Ok(module) +} + /// Performs common instance operations needed when an instance is first run /// including data setup, handling arguments and calling a main function pub fn run_instance(