2019-10-30 13:01:31 +01:00
|
|
|
use crate::{
|
2020-04-24 13:21:45 -07:00
|
|
|
relocation::{TrapData, TrapSink},
|
2019-10-30 13:01:31 +01:00
|
|
|
resolver::FuncResolver,
|
|
|
|
trampoline::Trampolines,
|
|
|
|
};
|
2019-02-07 17:08:42 -08:00
|
|
|
use libc::c_void;
|
2020-04-24 13:21:45 -07:00
|
|
|
use std::{cell::Cell, ptr::NonNull, sync::Arc};
|
2019-01-22 13:02:06 -06:00
|
|
|
use wasmer_runtime_core::{
|
2020-04-24 13:21:45 -07:00
|
|
|
backend::RunnableModule,
|
2020-04-23 12:40:35 -07:00
|
|
|
error::{InvokeError, RuntimeError},
|
2019-04-12 10:27:14 -07:00
|
|
|
module::ModuleInfo,
|
2020-02-06 23:49:50 +08:00
|
|
|
typed_func::{Trampoline, Wasm},
|
2019-04-12 10:27:14 -07:00
|
|
|
types::{LocalFuncIndex, SigIndex},
|
|
|
|
vm,
|
2019-01-18 13:29:43 -08:00
|
|
|
};
|
|
|
|
|
2019-02-07 17:08:42 -08:00
|
|
|
#[cfg(unix)]
|
|
|
|
mod unix;
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
mod windows;
|
|
|
|
|
|
|
|
#[cfg(unix)]
|
|
|
|
pub use self::unix::*;
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
pub use self::windows::*;
|
|
|
|
|
2019-02-08 13:08:03 -08:00
|
|
|
thread_local! {
|
2020-04-23 12:40:35 -07:00
|
|
|
pub static TRAP_EARLY_DATA: Cell<Option<RuntimeError>> = Cell::new(None);
|
2019-02-08 13:08:03 -08:00
|
|
|
}
|
|
|
|
|
2019-01-18 13:29:43 -08:00
|
|
|
pub struct Caller {
|
2019-01-18 16:45:30 -08:00
|
|
|
handler_data: HandlerData,
|
2019-02-19 09:58:01 -08:00
|
|
|
trampolines: Arc<Trampolines>,
|
2019-04-12 09:58:29 -07:00
|
|
|
resolver: FuncResolver,
|
2019-01-18 13:29:43 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Caller {
|
2019-02-20 16:41:41 -08:00
|
|
|
pub fn new(
|
|
|
|
handler_data: HandlerData,
|
|
|
|
trampolines: Arc<Trampolines>,
|
2019-04-12 09:58:29 -07:00
|
|
|
resolver: FuncResolver,
|
2019-02-20 16:41:41 -08:00
|
|
|
) -> Self {
|
2019-01-18 16:45:30 -08:00
|
|
|
Self {
|
|
|
|
handler_data,
|
2019-01-22 15:00:27 -08:00
|
|
|
trampolines,
|
2019-04-12 09:58:29 -07:00
|
|
|
resolver,
|
2019-01-18 16:45:30 -08:00
|
|
|
}
|
2019-01-18 13:29:43 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-12 09:58:29 -07:00
|
|
|
impl RunnableModule for Caller {
|
|
|
|
fn get_func(&self, _: &ModuleInfo, func_index: LocalFuncIndex) -> Option<NonNull<vm::Func>> {
|
|
|
|
self.resolver.lookup(func_index)
|
2019-01-18 13:29:43 -08:00
|
|
|
}
|
2019-02-08 13:08:03 -08:00
|
|
|
|
2019-04-12 09:58:29 -07:00
|
|
|
fn get_trampoline(&self, _: &ModuleInfo, sig_index: SigIndex) -> Option<Wasm> {
|
2019-04-09 15:53:01 -07:00
|
|
|
unsafe extern "C" fn invoke(
|
2019-10-30 13:01:31 +01:00
|
|
|
trampoline: Trampoline,
|
2019-04-09 15:53:01 -07:00
|
|
|
ctx: *mut vm::Ctx,
|
|
|
|
func: NonNull<vm::Func>,
|
|
|
|
args: *const u64,
|
|
|
|
rets: *mut u64,
|
2020-04-23 12:40:35 -07:00
|
|
|
error_out: *mut Option<InvokeError>,
|
2019-04-09 15:53:01 -07:00
|
|
|
invoke_env: Option<NonNull<c_void>>,
|
|
|
|
) -> bool {
|
|
|
|
let handler_data = &*invoke_env.unwrap().cast().as_ptr();
|
|
|
|
|
|
|
|
#[cfg(not(target_os = "windows"))]
|
2019-04-12 10:27:14 -07:00
|
|
|
let res = call_protected(handler_data, || {
|
2019-04-09 15:53:01 -07:00
|
|
|
// Leap of faith.
|
|
|
|
trampoline(ctx, func, args, rets);
|
2019-04-22 15:06:40 -07:00
|
|
|
});
|
2019-04-09 15:53:01 -07:00
|
|
|
|
|
|
|
// the trampoline is called from C on windows
|
|
|
|
#[cfg(target_os = "windows")]
|
2019-04-22 15:06:40 -07:00
|
|
|
let res = call_protected(handler_data, trampoline, ctx, func, args, rets);
|
2019-04-09 15:53:01 -07:00
|
|
|
|
2019-04-22 15:06:40 -07:00
|
|
|
match res {
|
|
|
|
Err(err) => {
|
2020-04-23 12:40:35 -07:00
|
|
|
// probably makes the most sense to actually do a translation here to a
|
|
|
|
// a generic type defined in runtime-core
|
|
|
|
// TODO: figure out _this_ error return story
|
2020-04-24 13:21:45 -07:00
|
|
|
*error_out = Some(err);
|
2019-04-22 15:06:40 -07:00
|
|
|
false
|
|
|
|
}
|
|
|
|
Ok(()) => true,
|
|
|
|
}
|
2019-04-09 15:53:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
let trampoline = self
|
|
|
|
.trampolines
|
|
|
|
.lookup(sig_index)
|
|
|
|
.expect("that trampoline doesn't exist");
|
|
|
|
|
|
|
|
Some(unsafe {
|
|
|
|
Wasm::from_raw_parts(
|
|
|
|
trampoline,
|
|
|
|
invoke,
|
|
|
|
Some(NonNull::from(&self.handler_data).cast()),
|
|
|
|
)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-04-23 12:40:35 -07:00
|
|
|
unsafe fn do_early_trap(&self, data: RuntimeError) -> ! {
|
2019-04-18 10:00:15 -07:00
|
|
|
TRAP_EARLY_DATA.with(|cell| cell.set(Some(data)));
|
|
|
|
trigger_trap()
|
2019-02-08 13:08:03 -08:00
|
|
|
}
|
2019-01-18 13:29:43 -08:00
|
|
|
}
|
|
|
|
|
2019-02-07 17:08:42 -08:00
|
|
|
unsafe impl Send for HandlerData {}
|
|
|
|
unsafe impl Sync for HandlerData {}
|
|
|
|
|
2019-02-19 09:58:01 -08:00
|
|
|
#[derive(Clone)]
|
2019-02-07 17:08:42 -08:00
|
|
|
pub struct HandlerData {
|
2019-02-19 09:58:01 -08:00
|
|
|
pub trap_data: Arc<TrapSink>,
|
2019-02-07 17:08:42 -08:00
|
|
|
exec_buffer_ptr: *const c_void,
|
|
|
|
exec_buffer_size: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl HandlerData {
|
|
|
|
pub fn new(
|
2019-02-19 09:58:01 -08:00
|
|
|
trap_data: Arc<TrapSink>,
|
2019-02-07 17:08:42 -08:00
|
|
|
exec_buffer_ptr: *const c_void,
|
|
|
|
exec_buffer_size: usize,
|
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
trap_data,
|
|
|
|
exec_buffer_ptr,
|
|
|
|
exec_buffer_size,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn lookup(&self, ip: *const c_void) -> Option<TrapData> {
|
|
|
|
let ip = ip as usize;
|
|
|
|
let buffer_ptr = self.exec_buffer_ptr as usize;
|
|
|
|
|
|
|
|
if buffer_ptr <= ip && ip < buffer_ptr + self.exec_buffer_size {
|
|
|
|
let offset = ip - buffer_ptr;
|
|
|
|
self.trap_data.lookup(offset)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|