From 2262c8a6da2df1fe5e4d8d093d355ebcf7b97623 Mon Sep 17 00:00:00 2001 From: losfair Date: Sat, 27 Apr 2019 16:31:47 +0800 Subject: [PATCH] Finished middleware impl and made a CallTrace middleware --- lib/middleware-common/Cargo.toml | 11 ++ lib/middleware-common/src/call_trace.rs | 27 +++++ lib/middleware-common/src/lib.rs | 9 ++ lib/runtime-core/src/codegen.rs | 112 +++++++++++-------- lib/runtime-core/src/lib.rs | 4 +- lib/runtime-core/src/parse.rs | 57 +++++++--- lib/runtime-core/src/vm.rs | 2 +- lib/singlepass-backend/src/codegen_x64.rs | 121 ++++++++++++++------- lib/singlepass-backend/src/emitter_x64.rs | 6 + lib/singlepass-backend/src/lib.rs | 4 +- lib/singlepass-backend/src/protect_unix.rs | 22 +++- 11 files changed, 266 insertions(+), 109 deletions(-) create mode 100644 lib/middleware-common/Cargo.toml create mode 100644 lib/middleware-common/src/call_trace.rs create mode 100644 lib/middleware-common/src/lib.rs diff --git a/lib/middleware-common/Cargo.toml b/lib/middleware-common/Cargo.toml new file mode 100644 index 000000000..9abb4041a --- /dev/null +++ b/lib/middleware-common/Cargo.toml @@ -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 "] +edition = "2018" + +[dependencies] +wasmer-runtime-core = { path = "../runtime-core", version = "0.3.0" } diff --git a/lib/middleware-common/src/call_trace.rs b/lib/middleware-common/src/call_trace.rs new file mode 100644 index 000000000..2f0879ca6 --- /dev/null +++ b/lib/middleware-common/src/call_trace.rs @@ -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(()) + } +} diff --git a/lib/middleware-common/src/lib.rs b/lib/middleware-common/src/lib.rs new file mode 100644 index 000000000..a61b6e1ec --- /dev/null +++ b/lib/middleware-common/src/lib.rs @@ -0,0 +1,9 @@ +pub mod call_trace; + +#[cfg(test)] +mod tests { + #[test] + fn it_works() { + assert_eq!(2 + 2, 4); + } +} diff --git a/lib/runtime-core/src/codegen.rs b/lib/runtime-core/src/codegen.rs index 8682a6fa8..4beb653d1 100644 --- a/lib/runtime-core/src/codegen.rs +++ b/lib/runtime-core/src/codegen.rs @@ -1,30 +1,33 @@ use crate::{ backend::RunnableModule, - structures::Map, - types::{FuncIndex, FuncSig, SigIndex}, backend::{sys::Memory, Backend, CacheGen, Compiler, CompilerConfig, Token}, cache::{Artifact, Error as CacheError}, error::{CompileError, CompileResult}, module::{ModuleInfo, ModuleInner}, parse::LoadError, + structures::Map, + types::{FuncIndex, FuncSig, SigIndex}, }; -use wasmparser::{Operator, Type as WpType}; -use std::fmt::Debug; use smallvec::SmallVec; +use std::fmt::Debug; use std::marker::PhantomData; +use wasmparser::{Operator, Type as WpType}; pub enum Event<'a, 'b> { Internal(InternalEvent), Wasm(&'b Operator<'a>), } -#[derive(Copy, Clone, Debug)] pub enum InternalEvent { - FunctionBegin, + FunctionBegin(u32), FunctionEnd, - Trace, + Bkpt(Box), + SetInternal(u32), + GetInternal(u32), } +pub struct BkptInfo {} + pub trait ModuleCodeGenerator, RM: RunnableModule, E: Debug> { fn new() -> Self; fn backend_id() -> Backend; @@ -36,10 +39,7 @@ pub trait ModuleCodeGenerator, RM: RunnableModule, fn feed_signatures(&mut self, signatures: Map) -> Result<(), E>; /// Sets function signatures. - fn feed_function_signatures( - &mut self, - assoc: Map, - ) -> Result<(), E>; + fn feed_function_signatures(&mut self, assoc: Map) -> Result<(), E>; /// Adds an import function. fn feed_import_function(&mut self) -> Result<(), E>; @@ -72,23 +72,25 @@ pub struct SimpleStreamingCompilerGen< } impl< - MCG: ModuleCodeGenerator, - FCG: FunctionCodeGenerator, - RM: RunnableModule + 'static, - E: Debug, -> SimpleStreamingCompilerGen { + MCG: ModuleCodeGenerator, + FCG: FunctionCodeGenerator, + RM: RunnableModule + 'static, + E: Debug, + > SimpleStreamingCompilerGen +{ pub fn new() -> StreamingCompiler MiddlewareChain> { StreamingCompiler::new(|| MiddlewareChain::new()) } } impl< - MCG: ModuleCodeGenerator, - FCG: FunctionCodeGenerator, - RM: RunnableModule + 'static, - E: Debug, - CGEN: Fn() -> MiddlewareChain, -> StreamingCompiler { + MCG: ModuleCodeGenerator, + FCG: FunctionCodeGenerator, + RM: RunnableModule + 'static, + E: Debug, + CGEN: Fn() -> MiddlewareChain, + > StreamingCompiler +{ pub fn new(chain_gen: CGEN) -> Self { Self { middleware_chain_generator: chain_gen, @@ -101,12 +103,13 @@ impl< } impl< - MCG: ModuleCodeGenerator, - FCG: FunctionCodeGenerator, - RM: RunnableModule + 'static, - E: Debug, - CGEN: Fn() -> MiddlewareChain, ->Compiler for StreamingCompiler { + MCG: ModuleCodeGenerator, + FCG: FunctionCodeGenerator, + RM: RunnableModule + 'static, + E: Debug, + CGEN: Fn() -> MiddlewareChain, + > Compiler for StreamingCompiler +{ fn compile( &self, wasm: &[u8], @@ -124,10 +127,18 @@ impl< let mut mcg = MCG::new(); let mut chain = (self.middleware_chain_generator)(); - let info = crate::parse::read_module(wasm, MCG::backend_id(), &mut mcg, &mut chain, &compiler_config)?; - let exec_context = mcg.finalize(&info).map_err(|x| CompileError::InternalError { - msg: format!("{:?}", x), - })?; + let info = crate::parse::read_module( + wasm, + 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 { cache_gen: Box::new(Placeholder), runnable_module: Box::new(exec_context), @@ -143,7 +154,7 @@ impl< } pub struct EventSink<'a, 'b> { - buffer: SmallVec<[Event<'a, 'b>; 2]> + buffer: SmallVec<[Event<'a, 'b>; 2]>, } impl<'a, 'b> EventSink<'a, 'b> { @@ -158,16 +169,19 @@ pub struct MiddlewareChain { impl MiddlewareChain { pub fn new() -> MiddlewareChain { - MiddlewareChain { - chain: vec! [], - } + MiddlewareChain { chain: vec![] } } pub fn push(&mut self, m: M) { self.chain.push(Box::new(m)); } - pub(crate) fn run>(&mut self, fcg: Option<&mut FCG>, ev: Event, module_info: &ModuleInfo) -> Result<(), String> { + pub(crate) fn run>( + &mut self, + fcg: Option<&mut FCG>, + ev: Event, + module_info: &ModuleInfo, + ) -> Result<(), String> { let mut sink = EventSink { buffer: SmallVec::new(), }; @@ -180,7 +194,8 @@ impl MiddlewareChain { } if let Some(fcg) = fcg { 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 { type Error: Debug; - fn feed_event( + fn feed_event<'a, 'b: 'a>( &mut self, - op: Event, + op: Event<'a, 'b>, module_info: &ModuleInfo, - sink: &mut EventSink, + sink: &mut EventSink<'a, 'b>, ) -> Result<(), Self::Error>; } pub(crate) trait GenericFunctionMiddleware { - fn feed_event( + fn feed_event<'a, 'b: 'a>( &mut self, - op: Event, + op: Event<'a, 'b>, module_info: &ModuleInfo, - sink: &mut EventSink, + sink: &mut EventSink<'a, 'b>, ) -> Result<(), String>; } impl> GenericFunctionMiddleware for T { - fn feed_event( + fn feed_event<'a, 'b: 'a>( &mut self, - op: Event, + op: Event<'a, 'b>, module_info: &ModuleInfo, - sink: &mut EventSink, + sink: &mut EventSink<'a, 'b>, ) -> Result<(), String> { - ::feed_event(self, op, module_info, sink).map_err(|x| format!("{:?}", x)) + ::feed_event(self, op, module_info, sink) + .map_err(|x| format!("{:?}", x)) } } diff --git a/lib/runtime-core/src/lib.rs b/lib/runtime-core/src/lib.rs index d07af88c1..46c435db5 100644 --- a/lib/runtime-core/src/lib.rs +++ b/lib/runtime-core/src/lib.rs @@ -14,6 +14,7 @@ pub mod backend; mod backing; pub mod cache; +pub mod codegen; pub mod error; pub mod export; pub mod global; @@ -21,6 +22,7 @@ pub mod import; pub mod instance; pub mod memory; pub mod module; +pub mod parse; mod sig_registry; pub mod structures; mod sys; @@ -31,8 +33,6 @@ pub mod units; pub mod vm; #[doc(hidden)] pub mod vmcalls; -pub mod codegen; -pub mod parse; use self::error::CompileResult; #[doc(inline)] diff --git a/lib/runtime-core/src/parse.rs b/lib/runtime-core/src/parse.rs index 4c851d6df..550a1b94f 100644 --- a/lib/runtime-core/src/parse.rs +++ b/lib/runtime-core/src/parse.rs @@ -1,7 +1,7 @@ use crate::codegen::*; -use hashbrown::HashMap; use crate::{ backend::{Backend, CompilerConfig, RunnableModule}, + error::CompileError, module::{ DataInitializer, ExportIndex, ImportName, ModuleInfo, StringTable, StringTableBuilder, TableInitializer, @@ -13,14 +13,14 @@ use crate::{ TableIndex, Type, Value, }, units::Pages, - error::CompileError, }; +use hashbrown::HashMap; +use std::fmt::Debug; use wasmparser::{ BinaryReaderError, Data, DataKind, Element, ElementKind, Export, ExternalKind, FuncType, Import, ImportSectionEntryType, InitExpr, ModuleReader, Operator, SectionCode, Type as WpType, WasmDecoder, }; -use std::fmt::Debug; #[derive(Debug)] pub enum LoadError { @@ -122,7 +122,8 @@ pub fn read_module< let sigindex = SigIndex::new(sigindex as usize); info.imported_functions.push(import_name); 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) => { assert_eq!(table_ty.element_type, WpType::AnyFunc); @@ -192,13 +193,24 @@ pub fn read_module< if func_count == 0 { info.namespace_table = namespace_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_function_signatures(info.func_assoc.clone()).map_err(|x| LoadError::Codegen(format!("{:?}", x)))?; - mcg.check_precondition(&info).map_err(|x| LoadError::Codegen(format!("{:?}", x)))?; + mcg.feed_signatures(info.signatures.clone()) + .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)))?; - middlewares.run(Some(fcg), Event::Internal(InternalEvent::FunctionBegin), &info).map_err(|x| LoadError::Codegen(x))?; + let fcg = mcg + .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 .signatures @@ -210,10 +222,12 @@ pub fn read_module< ) .unwrap(); 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() { - 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; @@ -224,22 +238,33 @@ pub fn read_module< ParserState::Error(err) => return Err(LoadError::Parse(err)), ParserState::FunctionBodyLocals { ref locals } => { 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) => { if !body_begun { 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, _ => unreachable!(), } } - middlewares.run(Some(fcg), Event::Internal(InternalEvent::FunctionEnd), &info).map_err(|x| LoadError::Codegen(x))?; - fcg.finalize().map_err(|x| LoadError::Codegen(format!("{:?}", x)))?; + middlewares + .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) => { let table_index = TableIndex::new(table_index as usize); diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index a1e493f8c..7d9039b7d 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -22,7 +22,7 @@ pub struct Ctx { local_backing: *mut LocalBacking, import_backing: *mut ImportBacking, - pub(crate) module: *const ModuleInner, + pub module: *const ModuleInner, pub data: *mut c_void, pub data_finalizer: Option, diff --git a/lib/singlepass-backend/src/codegen_x64.rs b/lib/singlepass-backend/src/codegen_x64.rs index 0368bc04c..3c40d97d9 100644 --- a/lib/singlepass-backend/src/codegen_x64.rs +++ b/lib/singlepass-backend/src/codegen_x64.rs @@ -11,6 +11,7 @@ use std::ptr::NonNull; use std::{any::Any, collections::HashMap, sync::Arc}; use wasmer_runtime_core::{ backend::{Backend, RunnableModule}, + codegen::*, memory::MemoryType, module::ModuleInfo, structures::{Map, TypedIndex}, @@ -21,7 +22,6 @@ use wasmer_runtime_core::{ }, vm::{self, LocalGlobal, LocalMemory, LocalTable}, vmcalls, - codegen::*, }; use wasmparser::{Operator, Type as WpType}; @@ -135,6 +135,7 @@ pub struct X64FunctionCode { assembler: Option, function_labels: Option)>>, br_table_data: Option>>, + breakpoints: Option>>, returns: SmallVec<[WpType; 1]>, locals: Vec, num_params: usize, @@ -160,6 +161,7 @@ pub struct X64ExecutionContext { function_pointers: Vec, signatures: Arc>, _br_table_data: Vec>, + breakpoints: Arc>>, func_import_count: usize, } @@ -209,12 +211,18 @@ impl RunnableModule for X64ExecutionContext { user_error: *mut Option>, num_params_plus_one: Option>, ) -> bool { + let rm: &Box = &unsafe { &*(*ctx).module }.runnable_module; + let execution_context = unsafe { + ::std::mem::transmute_copy::<&dyn RunnableModule, &X64ExecutionContext>(&&**rm) + }; let args = ::std::slice::from_raw_parts( args, num_params_plus_one.unwrap().as_ptr() as usize - 1, ); 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( args_reverse.as_ptr(), args_reverse.as_ptr().offset(args_reverse.len() as isize), @@ -235,7 +243,9 @@ impl RunnableModule for X64ExecutionContext { } false } - } + }; + protect_unix::BKPT_MAP.with(|x| x.borrow_mut().pop().unwrap()); + ret } unsafe extern "C" fn dummy_trampoline( @@ -267,7 +277,9 @@ pub struct CodegenError { pub message: &'static str, } -impl ModuleCodeGenerator for X64ModuleCodeGenerator { +impl ModuleCodeGenerator + for X64ModuleCodeGenerator +{ fn new() -> X64ModuleCodeGenerator { X64ModuleCodeGenerator { functions: vec![], @@ -288,18 +300,21 @@ impl ModuleCodeGenerator for } fn next_function(&mut self) -> Result<&mut X64FunctionCode, CodegenError> { - let (mut assembler, mut function_labels, br_table_data) = match self.functions.last_mut() { - Some(x) => ( - x.assembler.take().unwrap(), - x.function_labels.take().unwrap(), - x.br_table_data.take().unwrap(), - ), - None => ( - self.assembler.take().unwrap(), - self.function_labels.take().unwrap(), - vec![], - ), - }; + let (mut assembler, mut function_labels, br_table_data, breakpoints) = + match self.functions.last_mut() { + Some(x) => ( + x.assembler.take().unwrap(), + x.function_labels.take().unwrap(), + x.br_table_data.take().unwrap(), + x.breakpoints.take().unwrap(), + ), + None => ( + self.assembler.take().unwrap(), + self.function_labels.take().unwrap(), + vec![], + HashMap::new(), + ), + }; let begin_offset = assembler.offset(); let begin_label_info = function_labels .entry(self.functions.len() + self.func_import_count) @@ -320,6 +335,7 @@ impl ModuleCodeGenerator for assembler: Some(assembler), function_labels: Some(function_labels), br_table_data: Some(br_table_data), + breakpoints: Some(breakpoints), returns: smallvec![], locals: vec![], num_params: 0, @@ -334,8 +350,12 @@ impl ModuleCodeGenerator for } fn finalize(mut self, _: &ModuleInfo) -> Result { - let (assembler, mut br_table_data) = match self.functions.last_mut() { - Some(x) => (x.assembler.take().unwrap(), x.br_table_data.take().unwrap()), + let (assembler, mut br_table_data, breakpoints) = match self.functions.last_mut() { + Some(x) => ( + x.assembler.take().unwrap(), + x.br_table_data.take().unwrap(), + x.breakpoints.take().unwrap(), + ), None => { return Err(CodegenError { message: "no function", @@ -377,11 +397,19 @@ impl ModuleCodeGenerator for out_labels.push(FuncPtr(output.ptr(*offset) as _)); } + let breakpoints: Arc> = Arc::new( + breakpoints + .into_iter() + .map(|(offset, f)| (output.ptr(offset) as usize, f)) + .collect(), + ); + Ok(X64ExecutionContext { code: output, functions: self.functions, signatures: self.signatures.as_ref().unwrap().clone(), _br_table_data: br_table_data, + breakpoints: breakpoints, func_import_count: self.func_import_count, function_pointers: out_labels, }) @@ -1385,35 +1413,32 @@ impl FunctionCodeGenerator for X64FunctionCode { } 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()); let was_unreachable; if self.unreachable_depth > 0 { was_unreachable = true; - match *op { - Operator::Block { .. } | Operator::Loop { .. } | Operator::If { .. } => { - self.unreachable_depth += 1; - } - Operator::End => { - self.unreachable_depth -= 1; - } - Operator::Else => { - // We are in a reachable true branch - if self.unreachable_depth == 1 { - if let Some(IfElseState::If(_)) = - self.control_stack.last().map(|x| x.if_else) - { - self.unreachable_depth -= 1; + + if let Event::Wasm(op) = ev { + match *op { + Operator::Block { .. } | Operator::Loop { .. } | Operator::If { .. } => { + self.unreachable_depth += 1; + } + Operator::End => { + self.unreachable_depth -= 1; + } + Operator::Else => { + // We are in a reachable true branch + if self.unreachable_depth == 1 { + if let Some(IfElseState::If(_)) = + self.control_stack.last().map(|x| x.if_else) + { + self.unreachable_depth -= 1; + } } } + _ => {} } - _ => {} } if self.unreachable_depth > 0 { return Ok(()); @@ -1423,6 +1448,24 @@ impl FunctionCodeGenerator for X64FunctionCode { } 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 { Operator::GetGlobal { global_index } => { let global_index = global_index as usize; diff --git a/lib/singlepass-backend/src/emitter_x64.rs b/lib/singlepass-backend/src/emitter_x64.rs index 8a949f8a5..889b1099d 100644 --- a/lib/singlepass-backend/src/emitter_x64.rs +++ b/lib/singlepass-backend/src/emitter_x64.rs @@ -194,6 +194,8 @@ pub trait Emitter { fn emit_ret(&mut self); fn emit_call_label(&mut self, label: Self::Label); fn emit_call_location(&mut self, loc: Location); + + fn emit_bkpt(&mut self); } macro_rules! unop_gpr { @@ -947,4 +949,8 @@ impl Emitter for Assembler { _ => unreachable!(), } } + + fn emit_bkpt(&mut self) { + dynasm!(self ; int 0x3); + } } diff --git a/lib/singlepass-backend/src/lib.rs b/lib/singlepass-backend/src/lib.rs index 51415a69c..08d977487 100644 --- a/lib/singlepass-backend/src/lib.rs +++ b/lib/singlepass-backend/src/lib.rs @@ -23,8 +23,8 @@ mod emitter_x64; mod machine; mod protect_unix; -pub use codegen_x64::X64ModuleCodeGenerator as ModuleCodeGenerator; pub use codegen_x64::X64FunctionCode as FunctionCodeGenerator; +pub use codegen_x64::X64ModuleCodeGenerator as ModuleCodeGenerator; use wasmer_runtime_core::codegen::SimpleStreamingCompilerGen; pub type SinglePassCompiler = SimpleStreamingCompilerGen< @@ -32,4 +32,4 @@ pub type SinglePassCompiler = SimpleStreamingCompilerGen< codegen_x64::X64FunctionCode, codegen_x64::X64ExecutionContext, codegen_x64::CodegenError, ->; \ No newline at end of file +>; diff --git a/lib/singlepass-backend/src/protect_unix.rs b/lib/singlepass-backend/src/protect_unix.rs index 213db5f6a..b66c77b94 100644 --- a/lib/singlepass-backend/src/protect_unix.rs +++ b/lib/singlepass-backend/src/protect_unix.rs @@ -12,11 +12,15 @@ use libc::{c_int, c_void, siginfo_t}; use nix::sys::signal::{ sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV, + SIGTRAP, }; use std::any::Any; -use std::cell::{Cell, UnsafeCell}; +use std::cell::{Cell, RefCell, UnsafeCell}; +use std::collections::HashMap; use std::ptr; +use std::sync::Arc; use std::sync::Once; +use wasmer_runtime_core::codegen::BkptInfo; use wasmer_runtime_core::typed_func::WasmTrapInfo; extern "C" fn signal_trap_handler( @@ -25,6 +29,20 @@ extern "C" fn signal_trap_handler( ucontext: *mut c_void, ) { 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); } } @@ -44,6 +62,7 @@ pub unsafe fn install_sighandler() { sigaction(SIGILL, &sa).unwrap(); sigaction(SIGSEGV, &sa).unwrap(); sigaction(SIGBUS, &sa).unwrap(); + sigaction(SIGTRAP, &sa).unwrap(); } 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 CURRENT_EXECUTABLE_BUFFER: Cell<*const c_void> = Cell::new(ptr::null()); pub static TRAP_EARLY_DATA: Cell>> = Cell::new(None); + pub static BKPT_MAP: RefCell>>>> = RefCell::new(Vec::new()); } pub unsafe fn trigger_trap() -> ! {