diff --git a/CHANGELOG.md b/CHANGELOG.md index 47878fd1b65..dfedc2635df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - [#1009](https://github.com/wasmerio/wasmer/pull/1009) Enable LLVM verifier for all tests, add new llvm-backend-tests crate. - [#1022](https://github.com/wasmerio/wasmer/pull/1022) Add caching support for Singlepass backend. - [#1004](https://github.com/wasmerio/wasmer/pull/1004) Add the Auto backend to enable to adapt backend usage depending on wasm file executed. +- [#1068](https://github.com/wasmerio/wasmer/pull/1068) Various cleanups for the singlepass backend on AArch64. ## 0.11.0 - 2019-11-22 diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index a1647817660..ce750797f5e 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -76,34 +76,55 @@ impl std::str::FromStr for Backend { } } +/// The target architecture for code generation. #[derive(Copy, Clone, Debug)] pub enum Architecture { + /// x86-64. X64, + + /// Aarch64 (ARM64). Aarch64, } +/// The type of an inline breakpoint. #[repr(u8)] #[derive(Copy, Clone, Debug)] pub enum InlineBreakpointType { - Trace, + /// A middleware invocation breakpoint. Middleware, - Unknown, } +/// Information of an inline breakpoint. #[derive(Clone, Debug)] pub struct InlineBreakpoint { + /// Size in bytes taken by this breakpoint's instruction sequence. pub size: usize, + + /// Type of the inline breakpoint. pub ty: InlineBreakpointType, } +/// Inline breakpoint size for (x86-64, singlepass). +pub const INLINE_BREAKPOINT_SIZE_X86_SINGLEPASS: usize = 7; + +/// Inline breakpoint size for (aarch64, singlepass). +pub const INLINE_BREAKPOINT_SIZE_AARCH64_SINGLEPASS: usize = 12; + +/// Returns the inline breakpoint size corresponding to an (Architecture, Backend) pair. pub fn get_inline_breakpoint_size(arch: Architecture, backend: Backend) -> Option { match (arch, backend) { - (Architecture::X64, Backend::Singlepass) => Some(7), - (Architecture::Aarch64, Backend::Singlepass) => Some(12), + (Architecture::X64, Backend::Singlepass) => Some(INLINE_BREAKPOINT_SIZE_X86_SINGLEPASS), + (Architecture::Aarch64, Backend::Singlepass) => { + Some(INLINE_BREAKPOINT_SIZE_AARCH64_SINGLEPASS) + } _ => None, } } +/// Attempts to read an inline breakpoint from the code. +/// +/// Inline breakpoints are detected by special instruction sequences that never +/// appear in valid code. pub fn read_inline_breakpoint( arch: Architecture, backend: Backend, @@ -112,16 +133,20 @@ pub fn read_inline_breakpoint( match arch { Architecture::X64 => match backend { Backend::Singlepass => { - if code.len() < 7 { + if code.len() < INLINE_BREAKPOINT_SIZE_X86_SINGLEPASS { None - } else if &code[..6] == &[0x0f, 0x0b, 0x0f, 0xb9, 0xcd, 0xff] { - // ud2 ud (int 0xff) code + } else if &code[..INLINE_BREAKPOINT_SIZE_X86_SINGLEPASS - 1] + == &[ + 0x0f, 0x0b, // ud2 + 0x0f, 0xb9, // ud + 0xcd, 0xff, // int 0xff + ] + { Some(InlineBreakpoint { - size: 7, - ty: match code[6] { - 0 => InlineBreakpointType::Trace, - 1 => InlineBreakpointType::Middleware, - _ => InlineBreakpointType::Unknown, + size: INLINE_BREAKPOINT_SIZE_X86_SINGLEPASS, + ty: match code[INLINE_BREAKPOINT_SIZE_X86_SINGLEPASS - 1] { + 0 => InlineBreakpointType::Middleware, + _ => return None, }, }) } else { @@ -132,15 +157,19 @@ pub fn read_inline_breakpoint( }, Architecture::Aarch64 => match backend { Backend::Singlepass => { - if code.len() < 12 { + if code.len() < INLINE_BREAKPOINT_SIZE_AARCH64_SINGLEPASS { None - } else if &code[..8] == &[0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff] { + } else if &code[..INLINE_BREAKPOINT_SIZE_AARCH64_SINGLEPASS - 4] + == &[ + 0, 0, 0, 0, // udf #0 + 0xff, 0xff, 0x00, 0x00, // udf #65535 + ] + { Some(InlineBreakpoint { - size: 12, - ty: match code[8] { - 0 => InlineBreakpointType::Trace, - 1 => InlineBreakpointType::Middleware, - _ => InlineBreakpointType::Unknown, + size: INLINE_BREAKPOINT_SIZE_AARCH64_SINGLEPASS, + ty: match code[INLINE_BREAKPOINT_SIZE_AARCH64_SINGLEPASS - 4] { + 0 => InlineBreakpointType::Middleware, + _ => return None, }, }) } else { diff --git a/lib/runtime-core/src/fault.rs b/lib/runtime-core/src/fault.rs index 89d5b800ea7..6aae5334976 100644 --- a/lib/runtime-core/src/fault.rs +++ b/lib/runtime-core/src/fault.rs @@ -305,7 +305,6 @@ extern "C" fn signal_trap_handler( std::slice::from_raw_parts(ip as *const u8, magic_size), ) { match ib.ty { - InlineBreakpointType::Trace => {} InlineBreakpointType::Middleware => { let out: Option>> = with_breakpoint_map(|bkpt_map| { @@ -321,7 +320,6 @@ extern "C" fn signal_trap_handler( unwind_result = e; } } - _ => println!("Unknown breakpoint type: {:?}", ib.ty), } fault.ip.set(ip + magic_size); @@ -464,10 +462,7 @@ pub struct FaultInfo { impl FaultInfo { /// Parses the stack and builds an execution state image. pub unsafe fn read_stack(&self, max_depth: Option) -> Option { - let rsp = match self.known_registers[X64Register::GPR(GPR::RSP).to_index().0] { - Some(x) => x, - None => return None, - }; + let rsp = self.known_registers[X64Register::GPR(GPR::RSP).to_index().0]?; Some(CURRENT_CODE_VERSIONS.with(|versions| { let versions = versions.borrow(); diff --git a/lib/runtime-core/src/state.rs b/lib/runtime-core/src/state.rs index 7465f735e84..fedbc745b73 100644 --- a/lib/runtime-core/src/state.rs +++ b/lib/runtime-core/src/state.rs @@ -1063,7 +1063,6 @@ pub mod x64 { let mut is_baseline: Option = None; for version in versions() { - //println!("Lookup IP: {:x}", ret_addr); match version .msm .lookup_call_ip(ret_addr as usize, version.base) @@ -1251,7 +1250,6 @@ pub mod x64 { stack: wasm_stack, locals: wasm_locals, }; - //println!("WFS = {:?}", wfs); results.push(wfs); } diff --git a/lib/singlepass-backend/src/translator_aarch64.rs b/lib/singlepass-backend/src/translator_aarch64.rs index 0c2b7a6ecbf..7ec94f560cd 100644 --- a/lib/singlepass-backend/src/translator_aarch64.rs +++ b/lib/singlepass-backend/src/translator_aarch64.rs @@ -1673,8 +1673,8 @@ impl Emitter for Assembler { fn emit_inline_breakpoint(&mut self, ty: InlineBreakpointType) { dynasm!(self - ; .dword 0 - ; .dword -1 + ; .dword 0x00000000 + ; .dword 0x0000ffff ; .dword (ty as u8 as i32) ); }