This commit is contained in:
Lachlan Sneff
2019-02-19 15:36:22 -08:00
parent 3c7dc200fa
commit 82eea00a02
20 changed files with 267 additions and 257 deletions

View File

@ -1,4 +1,4 @@
#[cfg(feature = "cache")]
use crate::{
cache::{BackendCache, TrampolineCache},
trampoline::Trampolines,
@ -20,7 +20,7 @@ use std::{
cell::UnsafeCell,
sync::Arc,
};
#[cfg(feature = "cache")]
use wasmer_runtime_core::cache::Error as CacheError;
use wasmer_runtime_core::{
self,
@ -43,16 +43,24 @@ extern "C" {
pub fn __chkstk();
}
fn lookup_func(map: &SliceMap<LocalFuncIndex, usize>, memory: &Memory, local_func_index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
let offset = *map.get(local_func_index)?;
let ptr = unsafe { memory.as_ptr().add(offset) };
NonNull::new(ptr).map(|nonnull| nonnull.cast())
}
#[allow(dead_code)]
pub struct FuncResolverBuilder {
resolver: FuncResolver,
map: Map<LocalFuncIndex, usize>,
memory: Memory,
local_relocs: Map<LocalFuncIndex, Box<[LocalRelocation]>>,
external_relocs: Map<LocalFuncIndex, Box<[ExternalRelocation]>>,
import_len: usize,
}
impl FuncResolverBuilder {
#[cfg(feature = "cache")]
pub fn new_from_backend_cache(
backend_cache: BackendCache,
mut code: Memory,
@ -68,10 +76,8 @@ impl FuncResolverBuilder {
Ok((
Self {
resolver: FuncResolver {
map: backend_cache.offsets,
memory: Arc::new(UnsafeCell::new(code)),
},
map: backend_cache.offsets,
memory: code,
local_relocs: Map::new(),
external_relocs: backend_cache.external_relocs,
import_len: info.imported_functions.len(),
@ -155,7 +161,8 @@ impl FuncResolverBuilder {
let handler_data = HandlerData::new(Arc::new(trap_sink), memory.as_ptr() as _, memory.size());
let mut func_resolver_builder = Self {
resolver: FuncResolver { map, memory: Arc::new(UnsafeCell::new(memory)) },
map,
memory,
local_relocs,
external_relocs,
import_len: info.imported_functions.len(),
@ -171,11 +178,11 @@ impl FuncResolverBuilder {
for ref reloc in relocs.iter() {
let local_func_index = LocalFuncIndex::new(reloc.target.index() - self.import_len);
let target_func_address =
self.resolver.lookup(local_func_index).unwrap().as_ptr() as usize;
lookup_func(&self.map, &self.memory, local_func_index).unwrap().as_ptr() as usize;
// We need the address of the current function
// because these calls are relative.
let func_addr = self.resolver.lookup(index).unwrap().as_ptr() as usize;
let func_addr = lookup_func(&self.map, &self.memory, index).unwrap().as_ptr() as usize;
unsafe {
let reloc_address = func_addr + reloc.offset as usize;
@ -190,127 +197,126 @@ impl FuncResolverBuilder {
}
pub fn finalize(
self,
mut self,
signatures: &SliceMap<SigIndex, Arc<FuncSig>>,
trampolines: Arc<Trampolines>,
handler_data: HandlerData,
) -> CompileResult<(FuncResolver, BackendCache)> {
{
let mut memory = unsafe { (*self.resolver.memory.get()) };
for (index, relocs) in self.external_relocs.iter() {
for ref reloc in relocs.iter() {
let target_func_address: isize = match reloc.target {
RelocationType::LibCall(libcall) => match libcall {
LibCall::CeilF32 => libcalls::ceilf32 as isize,
LibCall::FloorF32 => libcalls::floorf32 as isize,
LibCall::TruncF32 => libcalls::truncf32 as isize,
LibCall::NearestF32 => libcalls::nearbyintf32 as isize,
LibCall::CeilF64 => libcalls::ceilf64 as isize,
LibCall::FloorF64 => libcalls::floorf64 as isize,
LibCall::TruncF64 => libcalls::truncf64 as isize,
LibCall::NearestF64 => libcalls::nearbyintf64 as isize,
#[cfg(all(target_pointer_width = "64", target_os = "windows"))]
LibCall::Probestack => __chkstk as isize,
#[cfg(not(target_os = "windows"))]
LibCall::Probestack => __rust_probestack as isize,
},
RelocationType::Intrinsic(ref name) => match name.as_str() {
"i32print" => i32_print as isize,
"i64print" => i64_print as isize,
"f32print" => f32_print as isize,
"f64print" => f64_print as isize,
"strtdbug" => start_debug as isize,
"enddbug" => end_debug as isize,
_ => Err(CompileError::InternalError {
msg: format!("unexpected intrinsic: {}", name),
})?,
},
RelocationType::VmCall(vmcall) => match vmcall {
VmCall::Local(kind) => match kind {
VmCallKind::StaticMemoryGrow => vmcalls::local_static_memory_grow as _,
VmCallKind::StaticMemorySize => vmcalls::local_static_memory_size as _,
for (index, relocs) in self.external_relocs.iter() {
for ref reloc in relocs.iter() {
let target_func_address: isize = match reloc.target {
RelocationType::LibCall(libcall) => match libcall {
LibCall::CeilF32 => libcalls::ceilf32 as isize,
LibCall::FloorF32 => libcalls::floorf32 as isize,
LibCall::TruncF32 => libcalls::truncf32 as isize,
LibCall::NearestF32 => libcalls::nearbyintf32 as isize,
LibCall::CeilF64 => libcalls::ceilf64 as isize,
LibCall::FloorF64 => libcalls::floorf64 as isize,
LibCall::TruncF64 => libcalls::truncf64 as isize,
LibCall::NearestF64 => libcalls::nearbyintf64 as isize,
#[cfg(all(target_pointer_width = "64", target_os = "windows"))]
LibCall::Probestack => __chkstk as isize,
#[cfg(not(target_os = "windows"))]
LibCall::Probestack => __rust_probestack as isize,
VmCallKind::SharedStaticMemoryGrow => unimplemented!(),
VmCallKind::SharedStaticMemorySize => unimplemented!(),
VmCallKind::DynamicMemoryGrow => {
vmcalls::local_dynamic_memory_grow as _
}
VmCallKind::DynamicMemorySize => {
vmcalls::local_dynamic_memory_size as _
}
},
RelocationType::Intrinsic(ref name) => match name.as_str() {
"i32print" => i32_print as isize,
"i64print" => i64_print as isize,
"f32print" => f32_print as isize,
"f64print" => f64_print as isize,
"strtdbug" => start_debug as isize,
"enddbug" => end_debug as isize,
_ => Err(CompileError::InternalError {
msg: format!("unexpected intrinsic: {}", name),
})?,
},
RelocationType::VmCall(vmcall) => match vmcall {
VmCall::Local(kind) => match kind {
VmCallKind::StaticMemoryGrow => vmcalls::local_static_memory_grow as _,
VmCallKind::StaticMemorySize => vmcalls::local_static_memory_size as _,
VmCallKind::SharedStaticMemoryGrow => unimplemented!(),
VmCallKind::SharedStaticMemorySize => unimplemented!(),
VmCallKind::DynamicMemoryGrow => {
vmcalls::local_dynamic_memory_grow as _
}
VmCallKind::DynamicMemorySize => {
vmcalls::local_dynamic_memory_size as _
}
},
VmCall::Import(kind) => match kind {
VmCallKind::StaticMemoryGrow => {
vmcalls::imported_static_memory_grow as _
}
VmCallKind::StaticMemorySize => {
vmcalls::imported_static_memory_size as _
}
VmCallKind::SharedStaticMemoryGrow => unimplemented!(),
VmCallKind::SharedStaticMemorySize => unimplemented!(),
VmCallKind::DynamicMemoryGrow => {
vmcalls::imported_dynamic_memory_grow as _
}
VmCallKind::DynamicMemorySize => {
vmcalls::imported_dynamic_memory_size as _
}
},
},
RelocationType::Signature(sig_index) => {
let sig_index =
SigRegistry.lookup_sig_index(Arc::clone(&signatures[sig_index]));
sig_index.index() as _
}
};
// We need the address of the current function
// because some of these calls are relative.
let func_addr = self.resolver.lookup(index).unwrap().as_ptr();
// Determine relocation type and apply relocation.
match reloc.reloc {
Reloc::Abs8 => {
let ptr_to_write = (target_func_address as u64)
.checked_add(reloc.addend as u64)
.unwrap();
let empty_space_offset = self.resolver.map[index] + reloc.offset as usize;
let ptr_slice = unsafe {
&mut memory.as_slice_mut()
[empty_space_offset..empty_space_offset + 8]
};
LittleEndian::write_u64(ptr_slice, ptr_to_write);
}
Reloc::X86PCRel4 | Reloc::X86CallPCRel4 => unsafe {
let reloc_address = (func_addr as usize) + reloc.offset as usize;
let reloc_delta = target_func_address
.wrapping_sub(reloc_address as isize)
.wrapping_add(reloc.addend as isize);
write_unaligned(reloc_address as *mut u32, reloc_delta as u32);
VmCall::Import(kind) => match kind {
VmCallKind::StaticMemoryGrow => {
vmcalls::imported_static_memory_grow as _
}
VmCallKind::StaticMemorySize => {
vmcalls::imported_static_memory_size as _
}
VmCallKind::SharedStaticMemoryGrow => unimplemented!(),
VmCallKind::SharedStaticMemorySize => unimplemented!(),
VmCallKind::DynamicMemoryGrow => {
vmcalls::imported_dynamic_memory_grow as _
}
VmCallKind::DynamicMemorySize => {
vmcalls::imported_dynamic_memory_size as _
}
},
},
RelocationType::Signature(sig_index) => {
let sig_index =
SigRegistry.lookup_sig_index(Arc::clone(&signatures[sig_index]));
sig_index.index() as _
}
};
// We need the address of the current function
// because some of these calls are relative.
let func_addr = lookup_func(&self.map, &self.memory, index).unwrap().as_ptr() as usize;
// Determine relocation type and apply relocation.
match reloc.reloc {
Reloc::Abs8 => {
let ptr_to_write = (target_func_address as u64)
.checked_add(reloc.addend as u64)
.unwrap();
let empty_space_offset = self.map[index] + reloc.offset as usize;
let ptr_slice = unsafe {
&mut self.memory.as_slice_mut()
[empty_space_offset..empty_space_offset + 8]
};
LittleEndian::write_u64(ptr_slice, ptr_to_write);
}
Reloc::X86PCRel4 | Reloc::X86CallPCRel4 => unsafe {
let reloc_address = (func_addr as usize) + reloc.offset as usize;
let reloc_delta = target_func_address
.wrapping_sub(reloc_address as isize)
.wrapping_add(reloc.addend as isize);
write_unaligned(reloc_address as *mut u32, reloc_delta as u32);
},
}
}
}
unsafe {
memory
.protect(.., Protect::ReadExec)
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
}
unsafe {
self.memory
.protect(.., Protect::ReadExec)
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
}
let backend_cache = BackendCache {
external_relocs: self.external_relocs.clone(),
offsets: self.resolver.map.clone(),
offsets: self.map.clone(),
trap_sink: handler_data.trap_data,
trampolines: trampolines.to_trampoline_cache(),
};
Ok((self.resolver, backend_cache))
Ok((FuncResolver {
map: self.map,
memory: Arc::new(self.memory),
}, backend_cache))
}
}
@ -320,16 +326,7 @@ unsafe impl Send for FuncResolver {}
/// Resolves a function index to a function address.
pub struct FuncResolver {
map: Map<LocalFuncIndex, usize>,
pub(crate) memory: Arc<UnsafeCell<Memory>>,
}
impl FuncResolver {
fn lookup(&self, local_func_index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
let offset = *self.map.get(local_func_index)?;
let ptr = unsafe { (*self.memory.get()).as_ptr().add(offset) };
NonNull::new(ptr).map(|nonnull| nonnull.cast())
}
pub(crate) memory: Arc<Memory>,
}
// Implements FuncResolver trait.
@ -339,7 +336,7 @@ impl backend::FuncResolver for FuncResolver {
_module: &wasmer_runtime_core::module::ModuleInner,
index: LocalFuncIndex,
) -> Option<NonNull<vm::Func>> {
self.lookup(index)
lookup_func(&self.map, &self.memory, index)
}
}