mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 06:15:33 +00:00
Finished middleware impl and made a CallTrace middleware
This commit is contained in:
parent
eca8ccdbd4
commit
2262c8a6da
11
lib/middleware-common/Cargo.toml
Normal file
11
lib/middleware-common/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "wasmer-middleware-common"
|
||||||
|
version = "0.3.0"
|
||||||
|
repository = "https://github.com/wasmerio/wasmer"
|
||||||
|
description = "Wasmer runtime common middlewares"
|
||||||
|
license = "MIT"
|
||||||
|
authors = ["The Wasmer Engineering Team <engineering@wasmer.io>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" }
|
27
lib/middleware-common/src/call_trace.rs
Normal file
27
lib/middleware-common/src/call_trace.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use wasmer_runtime_core::{
|
||||||
|
codegen::{Event, EventSink, FunctionMiddleware, InternalEvent},
|
||||||
|
module::ModuleInfo,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct CallTrace;
|
||||||
|
|
||||||
|
impl FunctionMiddleware for CallTrace {
|
||||||
|
type Error = String;
|
||||||
|
fn feed_event<'a, 'b: 'a>(
|
||||||
|
&mut self,
|
||||||
|
op: Event<'a, 'b>,
|
||||||
|
module_info: &ModuleInfo,
|
||||||
|
sink: &mut EventSink<'a, 'b>,
|
||||||
|
) -> Result<(), Self::Error> {
|
||||||
|
match op {
|
||||||
|
Event::Internal(InternalEvent::FunctionBegin(id)) => {
|
||||||
|
sink.push(Event::Internal(InternalEvent::Bkpt(Box::new(move |_| {
|
||||||
|
println!("func ({})", id);
|
||||||
|
}))))
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
sink.push(op);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
9
lib/middleware-common/src/lib.rs
Normal file
9
lib/middleware-common/src/lib.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
pub mod call_trace;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn it_works() {
|
||||||
|
assert_eq!(2 + 2, 4);
|
||||||
|
}
|
||||||
|
}
|
@ -1,30 +1,33 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
backend::RunnableModule,
|
backend::RunnableModule,
|
||||||
structures::Map,
|
|
||||||
types::{FuncIndex, FuncSig, SigIndex},
|
|
||||||
backend::{sys::Memory, Backend, CacheGen, Compiler, CompilerConfig, Token},
|
backend::{sys::Memory, Backend, CacheGen, Compiler, CompilerConfig, Token},
|
||||||
cache::{Artifact, Error as CacheError},
|
cache::{Artifact, Error as CacheError},
|
||||||
error::{CompileError, CompileResult},
|
error::{CompileError, CompileResult},
|
||||||
module::{ModuleInfo, ModuleInner},
|
module::{ModuleInfo, ModuleInner},
|
||||||
parse::LoadError,
|
parse::LoadError,
|
||||||
|
structures::Map,
|
||||||
|
types::{FuncIndex, FuncSig, SigIndex},
|
||||||
};
|
};
|
||||||
use wasmparser::{Operator, Type as WpType};
|
|
||||||
use std::fmt::Debug;
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
use std::fmt::Debug;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use wasmparser::{Operator, Type as WpType};
|
||||||
|
|
||||||
pub enum Event<'a, 'b> {
|
pub enum Event<'a, 'b> {
|
||||||
Internal(InternalEvent),
|
Internal(InternalEvent),
|
||||||
Wasm(&'b Operator<'a>),
|
Wasm(&'b Operator<'a>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
pub enum InternalEvent {
|
pub enum InternalEvent {
|
||||||
FunctionBegin,
|
FunctionBegin(u32),
|
||||||
FunctionEnd,
|
FunctionEnd,
|
||||||
Trace,
|
Bkpt(Box<Fn(BkptInfo) + Send + Sync + 'static>),
|
||||||
|
SetInternal(u32),
|
||||||
|
GetInternal(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct BkptInfo {}
|
||||||
|
|
||||||
pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator<E>, RM: RunnableModule, E: Debug> {
|
pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator<E>, RM: RunnableModule, E: Debug> {
|
||||||
fn new() -> Self;
|
fn new() -> Self;
|
||||||
fn backend_id() -> Backend;
|
fn backend_id() -> Backend;
|
||||||
@ -36,10 +39,7 @@ pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator<E>, RM: RunnableModule,
|
|||||||
fn feed_signatures(&mut self, signatures: Map<SigIndex, FuncSig>) -> Result<(), E>;
|
fn feed_signatures(&mut self, signatures: Map<SigIndex, FuncSig>) -> Result<(), E>;
|
||||||
|
|
||||||
/// Sets function signatures.
|
/// Sets function signatures.
|
||||||
fn feed_function_signatures(
|
fn feed_function_signatures(&mut self, assoc: Map<FuncIndex, SigIndex>) -> Result<(), E>;
|
||||||
&mut self,
|
|
||||||
assoc: Map<FuncIndex, SigIndex>,
|
|
||||||
) -> Result<(), E>;
|
|
||||||
|
|
||||||
/// Adds an import function.
|
/// Adds an import function.
|
||||||
fn feed_import_function(&mut self) -> Result<(), E>;
|
fn feed_import_function(&mut self) -> Result<(), E>;
|
||||||
@ -72,23 +72,25 @@ pub struct SimpleStreamingCompilerGen<
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
||||||
FCG: FunctionCodeGenerator<E>,
|
FCG: FunctionCodeGenerator<E>,
|
||||||
RM: RunnableModule + 'static,
|
RM: RunnableModule + 'static,
|
||||||
E: Debug,
|
E: Debug,
|
||||||
> SimpleStreamingCompilerGen<MCG, FCG, RM, E> {
|
> SimpleStreamingCompilerGen<MCG, FCG, RM, E>
|
||||||
|
{
|
||||||
pub fn new() -> StreamingCompiler<MCG, FCG, RM, E, impl Fn() -> MiddlewareChain> {
|
pub fn new() -> StreamingCompiler<MCG, FCG, RM, E, impl Fn() -> MiddlewareChain> {
|
||||||
StreamingCompiler::new(|| MiddlewareChain::new())
|
StreamingCompiler::new(|| MiddlewareChain::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
||||||
FCG: FunctionCodeGenerator<E>,
|
FCG: FunctionCodeGenerator<E>,
|
||||||
RM: RunnableModule + 'static,
|
RM: RunnableModule + 'static,
|
||||||
E: Debug,
|
E: Debug,
|
||||||
CGEN: Fn() -> MiddlewareChain,
|
CGEN: Fn() -> MiddlewareChain,
|
||||||
> StreamingCompiler<MCG, FCG, RM, E, CGEN> {
|
> StreamingCompiler<MCG, FCG, RM, E, CGEN>
|
||||||
|
{
|
||||||
pub fn new(chain_gen: CGEN) -> Self {
|
pub fn new(chain_gen: CGEN) -> Self {
|
||||||
Self {
|
Self {
|
||||||
middleware_chain_generator: chain_gen,
|
middleware_chain_generator: chain_gen,
|
||||||
@ -101,12 +103,13 @@ impl<
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<
|
||||||
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
||||||
FCG: FunctionCodeGenerator<E>,
|
FCG: FunctionCodeGenerator<E>,
|
||||||
RM: RunnableModule + 'static,
|
RM: RunnableModule + 'static,
|
||||||
E: Debug,
|
E: Debug,
|
||||||
CGEN: Fn() -> MiddlewareChain,
|
CGEN: Fn() -> MiddlewareChain,
|
||||||
>Compiler for StreamingCompiler<MCG, FCG, RM, E, CGEN> {
|
> Compiler for StreamingCompiler<MCG, FCG, RM, E, CGEN>
|
||||||
|
{
|
||||||
fn compile(
|
fn compile(
|
||||||
&self,
|
&self,
|
||||||
wasm: &[u8],
|
wasm: &[u8],
|
||||||
@ -124,10 +127,18 @@ impl<
|
|||||||
|
|
||||||
let mut mcg = MCG::new();
|
let mut mcg = MCG::new();
|
||||||
let mut chain = (self.middleware_chain_generator)();
|
let mut chain = (self.middleware_chain_generator)();
|
||||||
let info = crate::parse::read_module(wasm, MCG::backend_id(), &mut mcg, &mut chain, &compiler_config)?;
|
let info = crate::parse::read_module(
|
||||||
let exec_context = mcg.finalize(&info).map_err(|x| CompileError::InternalError {
|
wasm,
|
||||||
msg: format!("{:?}", x),
|
MCG::backend_id(),
|
||||||
})?;
|
&mut mcg,
|
||||||
|
&mut chain,
|
||||||
|
&compiler_config,
|
||||||
|
)?;
|
||||||
|
let exec_context = mcg
|
||||||
|
.finalize(&info)
|
||||||
|
.map_err(|x| CompileError::InternalError {
|
||||||
|
msg: format!("{:?}", x),
|
||||||
|
})?;
|
||||||
Ok(ModuleInner {
|
Ok(ModuleInner {
|
||||||
cache_gen: Box::new(Placeholder),
|
cache_gen: Box::new(Placeholder),
|
||||||
runnable_module: Box::new(exec_context),
|
runnable_module: Box::new(exec_context),
|
||||||
@ -143,7 +154,7 @@ impl<
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventSink<'a, 'b> {
|
pub struct EventSink<'a, 'b> {
|
||||||
buffer: SmallVec<[Event<'a, 'b>; 2]>
|
buffer: SmallVec<[Event<'a, 'b>; 2]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> EventSink<'a, 'b> {
|
impl<'a, 'b> EventSink<'a, 'b> {
|
||||||
@ -158,16 +169,19 @@ pub struct MiddlewareChain {
|
|||||||
|
|
||||||
impl MiddlewareChain {
|
impl MiddlewareChain {
|
||||||
pub fn new() -> MiddlewareChain {
|
pub fn new() -> MiddlewareChain {
|
||||||
MiddlewareChain {
|
MiddlewareChain { chain: vec![] }
|
||||||
chain: vec! [],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push<M: FunctionMiddleware + 'static>(&mut self, m: M) {
|
pub fn push<M: FunctionMiddleware + 'static>(&mut self, m: M) {
|
||||||
self.chain.push(Box::new(m));
|
self.chain.push(Box::new(m));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn run<E: Debug, FCG: FunctionCodeGenerator<E>>(&mut self, fcg: Option<&mut FCG>, ev: Event, module_info: &ModuleInfo) -> Result<(), String> {
|
pub(crate) fn run<E: Debug, FCG: FunctionCodeGenerator<E>>(
|
||||||
|
&mut self,
|
||||||
|
fcg: Option<&mut FCG>,
|
||||||
|
ev: Event,
|
||||||
|
module_info: &ModuleInfo,
|
||||||
|
) -> Result<(), String> {
|
||||||
let mut sink = EventSink {
|
let mut sink = EventSink {
|
||||||
buffer: SmallVec::new(),
|
buffer: SmallVec::new(),
|
||||||
};
|
};
|
||||||
@ -180,7 +194,8 @@ impl MiddlewareChain {
|
|||||||
}
|
}
|
||||||
if let Some(fcg) = fcg {
|
if let Some(fcg) = fcg {
|
||||||
for ev in sink.buffer {
|
for ev in sink.buffer {
|
||||||
fcg.feed_event(ev, module_info).map_err(|x| format!("{:?}", x))?;
|
fcg.feed_event(ev, module_info)
|
||||||
|
.map_err(|x| format!("{:?}", x))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,31 +205,32 @@ impl MiddlewareChain {
|
|||||||
|
|
||||||
pub trait FunctionMiddleware {
|
pub trait FunctionMiddleware {
|
||||||
type Error: Debug;
|
type Error: Debug;
|
||||||
fn feed_event(
|
fn feed_event<'a, 'b: 'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
op: Event,
|
op: Event<'a, 'b>,
|
||||||
module_info: &ModuleInfo,
|
module_info: &ModuleInfo,
|
||||||
sink: &mut EventSink,
|
sink: &mut EventSink<'a, 'b>,
|
||||||
) -> Result<(), Self::Error>;
|
) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait GenericFunctionMiddleware {
|
pub(crate) trait GenericFunctionMiddleware {
|
||||||
fn feed_event(
|
fn feed_event<'a, 'b: 'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
op: Event,
|
op: Event<'a, 'b>,
|
||||||
module_info: &ModuleInfo,
|
module_info: &ModuleInfo,
|
||||||
sink: &mut EventSink,
|
sink: &mut EventSink<'a, 'b>,
|
||||||
) -> Result<(), String>;
|
) -> Result<(), String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Debug, T: FunctionMiddleware<Error = E>> GenericFunctionMiddleware for T {
|
impl<E: Debug, T: FunctionMiddleware<Error = E>> GenericFunctionMiddleware for T {
|
||||||
fn feed_event(
|
fn feed_event<'a, 'b: 'a>(
|
||||||
&mut self,
|
&mut self,
|
||||||
op: Event,
|
op: Event<'a, 'b>,
|
||||||
module_info: &ModuleInfo,
|
module_info: &ModuleInfo,
|
||||||
sink: &mut EventSink,
|
sink: &mut EventSink<'a, 'b>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
<Self as FunctionMiddleware>::feed_event(self, op, module_info, sink).map_err(|x| format!("{:?}", x))
|
<Self as FunctionMiddleware>::feed_event(self, op, module_info, sink)
|
||||||
|
.map_err(|x| format!("{:?}", x))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ pub mod backend;
|
|||||||
mod backing;
|
mod backing;
|
||||||
|
|
||||||
pub mod cache;
|
pub mod cache;
|
||||||
|
pub mod codegen;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod export;
|
pub mod export;
|
||||||
pub mod global;
|
pub mod global;
|
||||||
@ -21,6 +22,7 @@ pub mod import;
|
|||||||
pub mod instance;
|
pub mod instance;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
pub mod module;
|
pub mod module;
|
||||||
|
pub mod parse;
|
||||||
mod sig_registry;
|
mod sig_registry;
|
||||||
pub mod structures;
|
pub mod structures;
|
||||||
mod sys;
|
mod sys;
|
||||||
@ -31,8 +33,6 @@ pub mod units;
|
|||||||
pub mod vm;
|
pub mod vm;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod vmcalls;
|
pub mod vmcalls;
|
||||||
pub mod codegen;
|
|
||||||
pub mod parse;
|
|
||||||
|
|
||||||
use self::error::CompileResult;
|
use self::error::CompileResult;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::codegen::*;
|
use crate::codegen::*;
|
||||||
use hashbrown::HashMap;
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{Backend, CompilerConfig, RunnableModule},
|
backend::{Backend, CompilerConfig, RunnableModule},
|
||||||
|
error::CompileError,
|
||||||
module::{
|
module::{
|
||||||
DataInitializer, ExportIndex, ImportName, ModuleInfo, StringTable, StringTableBuilder,
|
DataInitializer, ExportIndex, ImportName, ModuleInfo, StringTable, StringTableBuilder,
|
||||||
TableInitializer,
|
TableInitializer,
|
||||||
@ -13,14 +13,14 @@ use crate::{
|
|||||||
TableIndex, Type, Value,
|
TableIndex, Type, Value,
|
||||||
},
|
},
|
||||||
units::Pages,
|
units::Pages,
|
||||||
error::CompileError,
|
|
||||||
};
|
};
|
||||||
|
use hashbrown::HashMap;
|
||||||
|
use std::fmt::Debug;
|
||||||
use wasmparser::{
|
use wasmparser::{
|
||||||
BinaryReaderError, Data, DataKind, Element, ElementKind, Export, ExternalKind, FuncType,
|
BinaryReaderError, Data, DataKind, Element, ElementKind, Export, ExternalKind, FuncType,
|
||||||
Import, ImportSectionEntryType, InitExpr, ModuleReader, Operator, SectionCode, Type as WpType,
|
Import, ImportSectionEntryType, InitExpr, ModuleReader, Operator, SectionCode, Type as WpType,
|
||||||
WasmDecoder,
|
WasmDecoder,
|
||||||
};
|
};
|
||||||
use std::fmt::Debug;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum LoadError {
|
pub enum LoadError {
|
||||||
@ -122,7 +122,8 @@ pub fn read_module<
|
|||||||
let sigindex = SigIndex::new(sigindex as usize);
|
let sigindex = SigIndex::new(sigindex as usize);
|
||||||
info.imported_functions.push(import_name);
|
info.imported_functions.push(import_name);
|
||||||
info.func_assoc.push(sigindex);
|
info.func_assoc.push(sigindex);
|
||||||
mcg.feed_import_function().map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
mcg.feed_import_function()
|
||||||
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
}
|
}
|
||||||
ImportSectionEntryType::Table(table_ty) => {
|
ImportSectionEntryType::Table(table_ty) => {
|
||||||
assert_eq!(table_ty.element_type, WpType::AnyFunc);
|
assert_eq!(table_ty.element_type, WpType::AnyFunc);
|
||||||
@ -192,13 +193,24 @@ pub fn read_module<
|
|||||||
if func_count == 0 {
|
if func_count == 0 {
|
||||||
info.namespace_table = namespace_builder.take().unwrap().finish();
|
info.namespace_table = namespace_builder.take().unwrap().finish();
|
||||||
info.name_table = name_builder.take().unwrap().finish();
|
info.name_table = name_builder.take().unwrap().finish();
|
||||||
mcg.feed_signatures(info.signatures.clone()).map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
mcg.feed_signatures(info.signatures.clone())
|
||||||
mcg.feed_function_signatures(info.func_assoc.clone()).map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
mcg.check_precondition(&info).map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
mcg.feed_function_signatures(info.func_assoc.clone())
|
||||||
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
|
mcg.check_precondition(&info)
|
||||||
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let fcg = mcg.next_function().map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
let fcg = mcg
|
||||||
middlewares.run(Some(fcg), Event::Internal(InternalEvent::FunctionBegin), &info).map_err(|x| LoadError::Codegen(x))?;
|
.next_function()
|
||||||
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
|
middlewares
|
||||||
|
.run(
|
||||||
|
Some(fcg),
|
||||||
|
Event::Internal(InternalEvent::FunctionBegin(id as u32)),
|
||||||
|
&info,
|
||||||
|
)
|
||||||
|
.map_err(|x| LoadError::Codegen(x))?;
|
||||||
|
|
||||||
let sig = info
|
let sig = info
|
||||||
.signatures
|
.signatures
|
||||||
@ -210,10 +222,12 @@ pub fn read_module<
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
for ret in sig.returns() {
|
for ret in sig.returns() {
|
||||||
fcg.feed_return(type_to_wp_type(*ret)).map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
fcg.feed_return(type_to_wp_type(*ret))
|
||||||
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
}
|
}
|
||||||
for param in sig.params() {
|
for param in sig.params() {
|
||||||
fcg.feed_param(type_to_wp_type(*param)).map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
fcg.feed_param(type_to_wp_type(*param))
|
||||||
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut body_begun = false;
|
let mut body_begun = false;
|
||||||
@ -224,22 +238,33 @@ pub fn read_module<
|
|||||||
ParserState::Error(err) => return Err(LoadError::Parse(err)),
|
ParserState::Error(err) => return Err(LoadError::Parse(err)),
|
||||||
ParserState::FunctionBodyLocals { ref locals } => {
|
ParserState::FunctionBodyLocals { ref locals } => {
|
||||||
for &(count, ty) in locals.iter() {
|
for &(count, ty) in locals.iter() {
|
||||||
fcg.feed_local(ty, count as usize).map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
fcg.feed_local(ty, count as usize)
|
||||||
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ParserState::CodeOperator(ref op) => {
|
ParserState::CodeOperator(ref op) => {
|
||||||
if !body_begun {
|
if !body_begun {
|
||||||
body_begun = true;
|
body_begun = true;
|
||||||
fcg.begin_body().map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
fcg.begin_body()
|
||||||
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
}
|
}
|
||||||
middlewares.run(Some(fcg), Event::Wasm(op), &info).map_err(|x| LoadError::Codegen(x))?;
|
middlewares
|
||||||
|
.run(Some(fcg), Event::Wasm(op), &info)
|
||||||
|
.map_err(|x| LoadError::Codegen(x))?;
|
||||||
}
|
}
|
||||||
ParserState::EndFunctionBody => break,
|
ParserState::EndFunctionBody => break,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
middlewares.run(Some(fcg), Event::Internal(InternalEvent::FunctionEnd), &info).map_err(|x| LoadError::Codegen(x))?;
|
middlewares
|
||||||
fcg.finalize().map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
.run(
|
||||||
|
Some(fcg),
|
||||||
|
Event::Internal(InternalEvent::FunctionEnd),
|
||||||
|
&info,
|
||||||
|
)
|
||||||
|
.map_err(|x| LoadError::Codegen(x))?;
|
||||||
|
fcg.finalize()
|
||||||
|
.map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
|
||||||
}
|
}
|
||||||
ParserState::BeginActiveElementSectionEntry(table_index) => {
|
ParserState::BeginActiveElementSectionEntry(table_index) => {
|
||||||
let table_index = TableIndex::new(table_index as usize);
|
let table_index = TableIndex::new(table_index as usize);
|
||||||
|
@ -22,7 +22,7 @@ pub struct Ctx {
|
|||||||
|
|
||||||
local_backing: *mut LocalBacking,
|
local_backing: *mut LocalBacking,
|
||||||
import_backing: *mut ImportBacking,
|
import_backing: *mut ImportBacking,
|
||||||
pub(crate) module: *const ModuleInner,
|
pub module: *const ModuleInner,
|
||||||
|
|
||||||
pub data: *mut c_void,
|
pub data: *mut c_void,
|
||||||
pub data_finalizer: Option<fn(data: *mut c_void)>,
|
pub data_finalizer: Option<fn(data: *mut c_void)>,
|
||||||
|
@ -11,6 +11,7 @@ use std::ptr::NonNull;
|
|||||||
use std::{any::Any, collections::HashMap, sync::Arc};
|
use std::{any::Any, collections::HashMap, sync::Arc};
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
backend::{Backend, RunnableModule},
|
backend::{Backend, RunnableModule},
|
||||||
|
codegen::*,
|
||||||
memory::MemoryType,
|
memory::MemoryType,
|
||||||
module::ModuleInfo,
|
module::ModuleInfo,
|
||||||
structures::{Map, TypedIndex},
|
structures::{Map, TypedIndex},
|
||||||
@ -21,7 +22,6 @@ use wasmer_runtime_core::{
|
|||||||
},
|
},
|
||||||
vm::{self, LocalGlobal, LocalMemory, LocalTable},
|
vm::{self, LocalGlobal, LocalMemory, LocalTable},
|
||||||
vmcalls,
|
vmcalls,
|
||||||
codegen::*,
|
|
||||||
};
|
};
|
||||||
use wasmparser::{Operator, Type as WpType};
|
use wasmparser::{Operator, Type as WpType};
|
||||||
|
|
||||||
@ -135,6 +135,7 @@ pub struct X64FunctionCode {
|
|||||||
assembler: Option<Assembler>,
|
assembler: Option<Assembler>,
|
||||||
function_labels: Option<HashMap<usize, (DynamicLabel, Option<AssemblyOffset>)>>,
|
function_labels: Option<HashMap<usize, (DynamicLabel, Option<AssemblyOffset>)>>,
|
||||||
br_table_data: Option<Vec<Vec<usize>>>,
|
br_table_data: Option<Vec<Vec<usize>>>,
|
||||||
|
breakpoints: Option<HashMap<AssemblyOffset, Box<Fn(BkptInfo) + Send + Sync + 'static>>>,
|
||||||
returns: SmallVec<[WpType; 1]>,
|
returns: SmallVec<[WpType; 1]>,
|
||||||
locals: Vec<Location>,
|
locals: Vec<Location>,
|
||||||
num_params: usize,
|
num_params: usize,
|
||||||
@ -160,6 +161,7 @@ pub struct X64ExecutionContext {
|
|||||||
function_pointers: Vec<FuncPtr>,
|
function_pointers: Vec<FuncPtr>,
|
||||||
signatures: Arc<Map<SigIndex, FuncSig>>,
|
signatures: Arc<Map<SigIndex, FuncSig>>,
|
||||||
_br_table_data: Vec<Vec<usize>>,
|
_br_table_data: Vec<Vec<usize>>,
|
||||||
|
breakpoints: Arc<HashMap<usize, Box<Fn(BkptInfo) + Send + Sync + 'static>>>,
|
||||||
func_import_count: usize,
|
func_import_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,12 +211,18 @@ impl RunnableModule for X64ExecutionContext {
|
|||||||
user_error: *mut Option<Box<dyn Any>>,
|
user_error: *mut Option<Box<dyn Any>>,
|
||||||
num_params_plus_one: Option<NonNull<c_void>>,
|
num_params_plus_one: Option<NonNull<c_void>>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
let rm: &Box<dyn RunnableModule> = &unsafe { &*(*ctx).module }.runnable_module;
|
||||||
|
let execution_context = unsafe {
|
||||||
|
::std::mem::transmute_copy::<&dyn RunnableModule, &X64ExecutionContext>(&&**rm)
|
||||||
|
};
|
||||||
let args = ::std::slice::from_raw_parts(
|
let args = ::std::slice::from_raw_parts(
|
||||||
args,
|
args,
|
||||||
num_params_plus_one.unwrap().as_ptr() as usize - 1,
|
num_params_plus_one.unwrap().as_ptr() as usize - 1,
|
||||||
);
|
);
|
||||||
let args_reverse: SmallVec<[u64; 8]> = args.iter().cloned().rev().collect();
|
let args_reverse: SmallVec<[u64; 8]> = args.iter().cloned().rev().collect();
|
||||||
match protect_unix::call_protected(|| {
|
protect_unix::BKPT_MAP
|
||||||
|
.with(|x| x.borrow_mut().push(execution_context.breakpoints.clone()));
|
||||||
|
let ret = match protect_unix::call_protected(|| {
|
||||||
CONSTRUCT_STACK_AND_CALL_WASM(
|
CONSTRUCT_STACK_AND_CALL_WASM(
|
||||||
args_reverse.as_ptr(),
|
args_reverse.as_ptr(),
|
||||||
args_reverse.as_ptr().offset(args_reverse.len() as isize),
|
args_reverse.as_ptr().offset(args_reverse.len() as isize),
|
||||||
@ -235,7 +243,9 @@ impl RunnableModule for X64ExecutionContext {
|
|||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
protect_unix::BKPT_MAP.with(|x| x.borrow_mut().pop().unwrap());
|
||||||
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe extern "C" fn dummy_trampoline(
|
unsafe extern "C" fn dummy_trampoline(
|
||||||
@ -267,7 +277,9 @@ pub struct CodegenError {
|
|||||||
pub message: &'static str,
|
pub message: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError> for X64ModuleCodeGenerator {
|
impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError>
|
||||||
|
for X64ModuleCodeGenerator
|
||||||
|
{
|
||||||
fn new() -> X64ModuleCodeGenerator {
|
fn new() -> X64ModuleCodeGenerator {
|
||||||
X64ModuleCodeGenerator {
|
X64ModuleCodeGenerator {
|
||||||
functions: vec![],
|
functions: vec![],
|
||||||
@ -288,18 +300,21 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError> for
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn next_function(&mut self) -> Result<&mut X64FunctionCode, CodegenError> {
|
fn next_function(&mut self) -> Result<&mut X64FunctionCode, CodegenError> {
|
||||||
let (mut assembler, mut function_labels, br_table_data) = match self.functions.last_mut() {
|
let (mut assembler, mut function_labels, br_table_data, breakpoints) =
|
||||||
Some(x) => (
|
match self.functions.last_mut() {
|
||||||
x.assembler.take().unwrap(),
|
Some(x) => (
|
||||||
x.function_labels.take().unwrap(),
|
x.assembler.take().unwrap(),
|
||||||
x.br_table_data.take().unwrap(),
|
x.function_labels.take().unwrap(),
|
||||||
),
|
x.br_table_data.take().unwrap(),
|
||||||
None => (
|
x.breakpoints.take().unwrap(),
|
||||||
self.assembler.take().unwrap(),
|
),
|
||||||
self.function_labels.take().unwrap(),
|
None => (
|
||||||
vec![],
|
self.assembler.take().unwrap(),
|
||||||
),
|
self.function_labels.take().unwrap(),
|
||||||
};
|
vec![],
|
||||||
|
HashMap::new(),
|
||||||
|
),
|
||||||
|
};
|
||||||
let begin_offset = assembler.offset();
|
let begin_offset = assembler.offset();
|
||||||
let begin_label_info = function_labels
|
let begin_label_info = function_labels
|
||||||
.entry(self.functions.len() + self.func_import_count)
|
.entry(self.functions.len() + self.func_import_count)
|
||||||
@ -320,6 +335,7 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError> for
|
|||||||
assembler: Some(assembler),
|
assembler: Some(assembler),
|
||||||
function_labels: Some(function_labels),
|
function_labels: Some(function_labels),
|
||||||
br_table_data: Some(br_table_data),
|
br_table_data: Some(br_table_data),
|
||||||
|
breakpoints: Some(breakpoints),
|
||||||
returns: smallvec![],
|
returns: smallvec![],
|
||||||
locals: vec![],
|
locals: vec![],
|
||||||
num_params: 0,
|
num_params: 0,
|
||||||
@ -334,8 +350,12 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError> for
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn finalize(mut self, _: &ModuleInfo) -> Result<X64ExecutionContext, CodegenError> {
|
fn finalize(mut self, _: &ModuleInfo) -> Result<X64ExecutionContext, CodegenError> {
|
||||||
let (assembler, mut br_table_data) = match self.functions.last_mut() {
|
let (assembler, mut br_table_data, breakpoints) = match self.functions.last_mut() {
|
||||||
Some(x) => (x.assembler.take().unwrap(), x.br_table_data.take().unwrap()),
|
Some(x) => (
|
||||||
|
x.assembler.take().unwrap(),
|
||||||
|
x.br_table_data.take().unwrap(),
|
||||||
|
x.breakpoints.take().unwrap(),
|
||||||
|
),
|
||||||
None => {
|
None => {
|
||||||
return Err(CodegenError {
|
return Err(CodegenError {
|
||||||
message: "no function",
|
message: "no function",
|
||||||
@ -377,11 +397,19 @@ impl ModuleCodeGenerator<X64FunctionCode, X64ExecutionContext, CodegenError> for
|
|||||||
out_labels.push(FuncPtr(output.ptr(*offset) as _));
|
out_labels.push(FuncPtr(output.ptr(*offset) as _));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let breakpoints: Arc<HashMap<_, _>> = Arc::new(
|
||||||
|
breakpoints
|
||||||
|
.into_iter()
|
||||||
|
.map(|(offset, f)| (output.ptr(offset) as usize, f))
|
||||||
|
.collect(),
|
||||||
|
);
|
||||||
|
|
||||||
Ok(X64ExecutionContext {
|
Ok(X64ExecutionContext {
|
||||||
code: output,
|
code: output,
|
||||||
functions: self.functions,
|
functions: self.functions,
|
||||||
signatures: self.signatures.as_ref().unwrap().clone(),
|
signatures: self.signatures.as_ref().unwrap().clone(),
|
||||||
_br_table_data: br_table_data,
|
_br_table_data: br_table_data,
|
||||||
|
breakpoints: breakpoints,
|
||||||
func_import_count: self.func_import_count,
|
func_import_count: self.func_import_count,
|
||||||
function_pointers: out_labels,
|
function_pointers: out_labels,
|
||||||
})
|
})
|
||||||
@ -1385,35 +1413,32 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn feed_event(&mut self, ev: Event, module_info: &ModuleInfo) -> Result<(), CodegenError> {
|
fn feed_event(&mut self, ev: Event, module_info: &ModuleInfo) -> Result<(), CodegenError> {
|
||||||
let op = match ev {
|
|
||||||
Event::Wasm(x) => x,
|
|
||||||
Event::Internal(x) => {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
//println!("{:?} {}", op, self.value_stack.len());
|
//println!("{:?} {}", op, self.value_stack.len());
|
||||||
let was_unreachable;
|
let was_unreachable;
|
||||||
|
|
||||||
if self.unreachable_depth > 0 {
|
if self.unreachable_depth > 0 {
|
||||||
was_unreachable = true;
|
was_unreachable = true;
|
||||||
match *op {
|
|
||||||
Operator::Block { .. } | Operator::Loop { .. } | Operator::If { .. } => {
|
if let Event::Wasm(op) = ev {
|
||||||
self.unreachable_depth += 1;
|
match *op {
|
||||||
}
|
Operator::Block { .. } | Operator::Loop { .. } | Operator::If { .. } => {
|
||||||
Operator::End => {
|
self.unreachable_depth += 1;
|
||||||
self.unreachable_depth -= 1;
|
}
|
||||||
}
|
Operator::End => {
|
||||||
Operator::Else => {
|
self.unreachable_depth -= 1;
|
||||||
// We are in a reachable true branch
|
}
|
||||||
if self.unreachable_depth == 1 {
|
Operator::Else => {
|
||||||
if let Some(IfElseState::If(_)) =
|
// We are in a reachable true branch
|
||||||
self.control_stack.last().map(|x| x.if_else)
|
if self.unreachable_depth == 1 {
|
||||||
{
|
if let Some(IfElseState::If(_)) =
|
||||||
self.unreachable_depth -= 1;
|
self.control_stack.last().map(|x| x.if_else)
|
||||||
|
{
|
||||||
|
self.unreachable_depth -= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
if self.unreachable_depth > 0 {
|
if self.unreachable_depth > 0 {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
@ -1423,6 +1448,24 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let a = self.assembler.as_mut().unwrap();
|
let a = self.assembler.as_mut().unwrap();
|
||||||
|
|
||||||
|
let op = match ev {
|
||||||
|
Event::Wasm(x) => x,
|
||||||
|
Event::Internal(x) => {
|
||||||
|
match x {
|
||||||
|
InternalEvent::Bkpt(callback) => {
|
||||||
|
a.emit_bkpt();
|
||||||
|
self.breakpoints
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.insert(a.get_offset(), callback);
|
||||||
|
}
|
||||||
|
InternalEvent::FunctionBegin(_) | InternalEvent::FunctionEnd => {}
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
};
|
||||||
match *op {
|
match *op {
|
||||||
Operator::GetGlobal { global_index } => {
|
Operator::GetGlobal { global_index } => {
|
||||||
let global_index = global_index as usize;
|
let global_index = global_index as usize;
|
||||||
|
@ -194,6 +194,8 @@ pub trait Emitter {
|
|||||||
fn emit_ret(&mut self);
|
fn emit_ret(&mut self);
|
||||||
fn emit_call_label(&mut self, label: Self::Label);
|
fn emit_call_label(&mut self, label: Self::Label);
|
||||||
fn emit_call_location(&mut self, loc: Location);
|
fn emit_call_location(&mut self, loc: Location);
|
||||||
|
|
||||||
|
fn emit_bkpt(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! unop_gpr {
|
macro_rules! unop_gpr {
|
||||||
@ -947,4 +949,8 @@ impl Emitter for Assembler {
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emit_bkpt(&mut self) {
|
||||||
|
dynasm!(self ; int 0x3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,8 @@ mod emitter_x64;
|
|||||||
mod machine;
|
mod machine;
|
||||||
mod protect_unix;
|
mod protect_unix;
|
||||||
|
|
||||||
pub use codegen_x64::X64ModuleCodeGenerator as ModuleCodeGenerator;
|
|
||||||
pub use codegen_x64::X64FunctionCode as FunctionCodeGenerator;
|
pub use codegen_x64::X64FunctionCode as FunctionCodeGenerator;
|
||||||
|
pub use codegen_x64::X64ModuleCodeGenerator as ModuleCodeGenerator;
|
||||||
|
|
||||||
use wasmer_runtime_core::codegen::SimpleStreamingCompilerGen;
|
use wasmer_runtime_core::codegen::SimpleStreamingCompilerGen;
|
||||||
pub type SinglePassCompiler = SimpleStreamingCompilerGen<
|
pub type SinglePassCompiler = SimpleStreamingCompilerGen<
|
||||||
@ -32,4 +32,4 @@ pub type SinglePassCompiler = SimpleStreamingCompilerGen<
|
|||||||
codegen_x64::X64FunctionCode,
|
codegen_x64::X64FunctionCode,
|
||||||
codegen_x64::X64ExecutionContext,
|
codegen_x64::X64ExecutionContext,
|
||||||
codegen_x64::CodegenError,
|
codegen_x64::CodegenError,
|
||||||
>;
|
>;
|
||||||
|
@ -12,11 +12,15 @@
|
|||||||
use libc::{c_int, c_void, siginfo_t};
|
use libc::{c_int, c_void, siginfo_t};
|
||||||
use nix::sys::signal::{
|
use nix::sys::signal::{
|
||||||
sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
|
sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
|
||||||
|
SIGTRAP,
|
||||||
};
|
};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::cell::{Cell, UnsafeCell};
|
use std::cell::{Cell, RefCell, UnsafeCell};
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use std::sync::Arc;
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
|
use wasmer_runtime_core::codegen::BkptInfo;
|
||||||
use wasmer_runtime_core::typed_func::WasmTrapInfo;
|
use wasmer_runtime_core::typed_func::WasmTrapInfo;
|
||||||
|
|
||||||
extern "C" fn signal_trap_handler(
|
extern "C" fn signal_trap_handler(
|
||||||
@ -25,6 +29,20 @@ extern "C" fn signal_trap_handler(
|
|||||||
ucontext: *mut c_void,
|
ucontext: *mut c_void,
|
||||||
) {
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
match Signal::from_c_int(signum) {
|
||||||
|
Ok(SIGTRAP) => {
|
||||||
|
let (_, ip) = get_faulting_addr_and_ip(siginfo as _, ucontext);
|
||||||
|
let bkpt_map = BKPT_MAP.with(|x| x.borrow().last().map(|x| x.clone()));
|
||||||
|
if let Some(bkpt_map) = bkpt_map {
|
||||||
|
if let Some(ref x) = bkpt_map.get(&(ip as usize)) {
|
||||||
|
(x)(BkptInfo {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
do_unwind(signum, siginfo as _, ucontext);
|
do_unwind(signum, siginfo as _, ucontext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -44,6 +62,7 @@ pub unsafe fn install_sighandler() {
|
|||||||
sigaction(SIGILL, &sa).unwrap();
|
sigaction(SIGILL, &sa).unwrap();
|
||||||
sigaction(SIGSEGV, &sa).unwrap();
|
sigaction(SIGSEGV, &sa).unwrap();
|
||||||
sigaction(SIGBUS, &sa).unwrap();
|
sigaction(SIGBUS, &sa).unwrap();
|
||||||
|
sigaction(SIGTRAP, &sa).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
const SETJMP_BUFFER_LEN: usize = 27;
|
const SETJMP_BUFFER_LEN: usize = 27;
|
||||||
@ -54,6 +73,7 @@ thread_local! {
|
|||||||
pub static CAUGHT_ADDRESSES: Cell<(*const c_void, *const c_void)> = Cell::new((ptr::null(), ptr::null()));
|
pub static CAUGHT_ADDRESSES: Cell<(*const c_void, *const c_void)> = Cell::new((ptr::null(), ptr::null()));
|
||||||
pub static CURRENT_EXECUTABLE_BUFFER: Cell<*const c_void> = Cell::new(ptr::null());
|
pub static CURRENT_EXECUTABLE_BUFFER: Cell<*const c_void> = Cell::new(ptr::null());
|
||||||
pub static TRAP_EARLY_DATA: Cell<Option<Box<dyn Any>>> = Cell::new(None);
|
pub static TRAP_EARLY_DATA: Cell<Option<Box<dyn Any>>> = Cell::new(None);
|
||||||
|
pub static BKPT_MAP: RefCell<Vec<Arc<HashMap<usize, Box<Fn(BkptInfo) + Send + Sync + 'static>>>>> = RefCell::new(Vec::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn trigger_trap() -> ! {
|
pub unsafe fn trigger_trap() -> ! {
|
||||||
|
Loading…
Reference in New Issue
Block a user