diff --git a/lib/execute/src/lib.rs b/lib/execute/src/lib.rs index 5687996822..af7ab95352 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"), } } } @@ -72,23 +84,28 @@ 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 - )) + // 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( + 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 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]]