Function relocations are now working

This commit is contained in:
Syrus Akbary
2018-10-16 00:04:05 +02:00
parent fade076fa4
commit 7f7eff788d
3 changed files with 219 additions and 8 deletions

View File

@ -13,16 +13,17 @@ use memmap::MmapMut;
use region;
use spin::RwLock;
use std::marker::PhantomData;
use std::ptr;
use std::ptr::{self, write_unaligned};
use std::sync::Arc;
use std::{mem, slice};
use std::iter::Iterator;
use super::super::common::slice::{BoundedSlice, UncheckedSlice};
use super::errors::ErrorKind;
use super::memory::LinearMemory;
use super::module::Module;
use super::module::{DataInitializer, Exportable, Export};
use super::relocation::{RelocSink, TrapSink};
use super::relocation::{RelocSink, TrapSink, RelocationType, Reloc};
pub fn protect_codebuf(code_buf: &Vec<u8>) -> Result<(), String> {
@ -149,7 +150,7 @@ impl Instance {
// let mut total_size: usize = 0;
let mut context_and_offsets = Vec::with_capacity(module.info.function_bodies.len());
let mut relocations = Vec::new();
// Compile the functions (from cranelift IR to machine code)
for function_body in module.info.function_bodies.values() {
let mut func_context = Context::for_function(function_body.to_owned());
@ -175,9 +176,98 @@ impl Instance {
functions.push(func_offset);
context_and_offsets.push(func_context);
relocations.push(reloc_sink.func_relocs);
// println!("FUNCTION RELOCATIONS {:?}", reloc_sink.func_relocs)
// total_size += code_size_offset;
}
// For each of the functions used, we see what are the calls inside this functions
// and relocate each call to the proper memory address.
// The relocations are relative to the relocation's address plus four bytes
// TODO: Support architectures other than x64, and other reloc kinds.
for (i, function_relocs) in relocations.iter().enumerate() {
// for r in function_relocs {
for (ref reloc, ref reloc_type) in function_relocs {
let target_func_address: isize = match reloc_type {
RelocationType::Normal(func_index) => {
functions[*func_index as usize].as_ptr() as isize
},
_ => unimplemented!()
// RelocationType::Intrinsic(name) => {
// get_abi_intrinsic(name)?
// },
// RelocationTarget::UserFunc(index) => {
// functions[module.defined_func_index(index).expect(
// "relocation to imported function not supported yet",
// )].as_ptr() as isize
// }
// RelocationTarget::GrowMemory => grow_memory as isize,
// RelocationTarget::CurrentMemory => current_memory as isize,
};
// print!("FUNCTION {:?}", target_func_address);
let body = &mut functions[i];
match reloc.reloc {
Reloc::Abs8 => unsafe {
let reloc_address = body.as_mut_ptr().offset(reloc.offset as isize) as i64;
let reloc_addend = reloc.addend;
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(reloc.offset as isize) as isize;
let reloc_addend = reloc.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"),
}
// let reloc_address = unsafe {
// (target_func_address.to_owned().as_mut_ptr() as *const u8).offset(reloc.offset as isize)
// };
// match reloc.reloc {
// Reloc::Abs8 => {
// unsafe {
// // (reloc_address as *mut usize).write(target_func_address.to_owned().as_ptr() as usize);
// }
// }
// _ => unimplemented!()
// }
// let target_func_address: isize = match r.reloc_target {
// RelocationTarget::UserFunc(index) => {
// functions[module.defined_func_index(index).expect(
// "relocation to imported function not supported yet",
// )].as_ptr() as isize
// }
// RelocationTarget::GrowMemory => grow_memory as isize,
// RelocationTarget::CurrentMemory => current_memory as isize,
// };
// let body = &mut functions[i];
// 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;
// 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"),
// }
}
}
// We only want to allocate in memory if there is more than
// 0 functions. Otherwise reserving a 0-sized memory region
// cause a panic error
@ -338,9 +428,11 @@ impl Instance {
}
}
pub fn invoke(&self, func_index: FuncIndex, _args: Vec<u8>) -> u32 {
let func: fn() -> u32 = self.get_function(func_index);
func()
pub fn invoke(&self, func_index: FuncIndex, _args: Vec<u8>) -> i32 {
let func: fn() -> i32 = self.get_function(func_index);
let result = func();
println!("RESULT {:?}", result);
result
}
pub fn start(&self) {
@ -402,3 +494,25 @@ impl Clone for Instance {
}
}
}
extern "C" fn grow_memory(size: u32, memory_index: u32, vmctx: *mut *mut u8) -> u32 {
unimplemented!();
// unsafe {
// let instance = (*vmctx.offset(4)) as *mut Instance;
// (*instance)
// .memory_mut(memory_index as MemoryIndex)
// .grow(size)
// .unwrap_or(u32::max_value())
// }
}
extern "C" fn current_memory(memory_index: u32, vmctx: *mut *mut u8) -> u32 {
unimplemented!();
// unsafe {
// let instance = (*vmctx.offset(4)) as *mut Instance;
// (*instance)
// .memory_mut(memory_index as MemoryIndex)
// .current_size()
// }
}