From 9d41135fe30df498be4e9fb426a8e8d8cf71f9f3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 17 May 2018 20:39:19 -0700 Subject: [PATCH 1/4] Translate from function-body index to function-index-space index. The wasm function index space consists of the index space of the imported functions concatenated with the index space of the defined functions. When iterating through function definitions, it's necessary to adjust the index when a function-index-space index is needed. --- lib/runtime/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/runtime/src/lib.rs b/lib/runtime/src/lib.rs index 45a3ac8c3a..e8e5d54600 100644 --- a/lib/runtime/src/lib.rs +++ b/lib/runtime/src/lib.rs @@ -569,7 +569,8 @@ impl<'data, 'module> ModuleTranslation<'data, 'module> { ) -> Result<(Compilation<'module>, Relocations), String> { let mut functions = Vec::new(); let mut relocations = Vec::new(); - for (func_index, input) in self.lazy.function_body_inputs.iter().enumerate() { + for (i, input) in self.lazy.function_body_inputs.iter().enumerate() { + let func_index = i + self.module.imported_funcs.len(); let mut context = cretonne_codegen::Context::new(); context.func.name = get_func_name(func_index); context.func.signature = self.module.signatures[self.module.functions[func_index]] From d162f8bc59ff395c0bb06a091868e29567c76891 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 17 May 2018 23:27:00 -0700 Subject: [PATCH 2/4] Implement Abs8 relocations, and fix X86PCRel4 relocations. With new versions of cretonne-codegen: - Non-colocated calls are emitted as a movabs with an indirect call. This uses an Abs8 relocation. - Colocated calls are emitted as direct calls, but the "+ 4" adjustment is now folded into the addend, so we don't need to handle it explicitly in the X86PCRel4 code anymore. --- lib/execute/src/lib.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/execute/src/lib.rs b/lib/execute/src/lib.rs index 5687996822..5b1d939b14 100644 --- a/lib/execute/src/lib.rs +++ b/lib/execute/src/lib.rs @@ -8,6 +8,7 @@ extern crate region; extern crate wasmstandalone_runtime; use cretonne_codegen::isa::TargetIsa; +use cretonne_codegen::binemit::Reloc; use std::mem::transmute; use region::Protection; use region::protect; @@ -41,11 +42,22 @@ fn relocate(compilation: &mut Compilation, relocations: &wasmstandalone_runtime: for ref r in function_relocs { let target_func_address: isize = compilation.functions[r.func_index].as_ptr() as isize; let body = &mut compilation.functions[i]; - unsafe { - let reloc_address = body.as_mut_ptr().offset(r.offset as isize + 4) as isize; - let reloc_addend = r.addend as isize; - let reloc_delta_i32 = (target_func_address - reloc_address + reloc_addend) as i32; - write_unaligned(reloc_address as *mut i32, reloc_delta_i32); + match r.reloc { + Reloc::Abs8 => unsafe { + let reloc_address = body.as_mut_ptr().offset(r.offset as isize) as i64; + let reloc_addend = r.addend as i64; + let reloc_abs = target_func_address as i64 + reloc_addend; + write_unaligned(reloc_address as *mut i64, reloc_abs); + }, + Reloc::X86PCRel4 => unsafe { + let reloc_address = body.as_mut_ptr().offset(r.offset as isize) as isize; + let reloc_addend = r.addend as isize; + // TODO: Handle overflow. + let reloc_delta_i32 = (target_func_address - reloc_address + reloc_addend) as + i32; + write_unaligned(reloc_address as *mut i32, reloc_delta_i32); + }, + _ => panic!("unsupported reloc kind"), } } } From 52f1171485313d84036c5bd1d9d8ef27694d2b8d Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 17 May 2018 23:56:05 -0700 Subject: [PATCH 3/4] Make all the function bodies executable, not just the start function. --- lib/execute/src/lib.rs | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/lib/execute/src/lib.rs b/lib/execute/src/lib.rs index 5b1d939b14..0e98adca15 100644 --- a/lib/execute/src/lib.rs +++ b/lib/execute/src/lib.rs @@ -84,23 +84,26 @@ pub fn execute( let start_index = compilation.module.start_func.ok_or_else(|| { String::from("No start function defined, aborting execution") })?; - let code_buf = &compilation.functions[start_index]; - match unsafe { - protect( - code_buf.as_ptr(), - code_buf.len(), - Protection::ReadWriteExecute, - ) - } { - Ok(()) => (), - Err(err) => { - return Err(format!( - "failed to give executable permission to code: {}", - err - )) + for code_buf in &compilation.functions { + match unsafe { + protect( + code_buf.as_ptr(), + code_buf.len(), + Protection::ReadWriteExecute, + ) + } { + Ok(()) => (), + Err(err) => { + return Err(format!( + "failed to give executable permission to code: {}", + err + )) + } } } + let code_buf = &compilation.functions[start_index]; + let vmctx = make_vmctx(instance); // Rather than writing inline assembly to jump to the code region, we use the fact that From 46a772ba67ffb54dfbd743297d0bf6de153f20d2 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 17 May 2018 23:59:40 -0700 Subject: [PATCH 4/4] Add a TODO about avoiding ReadWriteExecute mappings. --- lib/execute/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/execute/src/lib.rs b/lib/execute/src/lib.rs index 0e98adca15..af7ab95352 100644 --- a/lib/execute/src/lib.rs +++ b/lib/execute/src/lib.rs @@ -84,6 +84,8 @@ pub fn execute( let start_index = compilation.module.start_func.ok_or_else(|| { String::from("No start function defined, aborting execution") })?; + // TODO: Put all the function bodies into a page-aligned memory region, and + // then make them ReadExecute rather than ReadWriteExecute. for code_buf in &compilation.functions { match unsafe { protect(