runtime-core/backend: Add comments and cleanup.

This commit is contained in:
losfair 2019-12-17 00:31:47 +08:00
parent 598fbfa44a
commit 57615e5673

View File

@ -76,34 +76,53 @@ impl std::str::FromStr for Backend {
} }
} }
/// The target architecture for code generation.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum Architecture { pub enum Architecture {
/// x86-64.
X64, X64,
/// Aarch64 (ARM64).
Aarch64, Aarch64,
} }
/// The type of an inline breakpoint.
#[repr(u8)] #[repr(u8)]
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum InlineBreakpointType { pub enum InlineBreakpointType {
Trace, /// A middleware invocation breakpoint.
Middleware, Middleware,
Unknown,
} }
/// Information of an inline breakpoint.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct InlineBreakpoint { pub struct InlineBreakpoint {
/// Size in bytes taken by this breakpoint's instruction sequence.
pub size: usize, pub size: usize,
/// Type of the inline breakpoint.
pub ty: InlineBreakpointType, 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<usize> { pub fn get_inline_breakpoint_size(arch: Architecture, backend: Backend) -> Option<usize> {
match (arch, backend) { match (arch, backend) {
(Architecture::X64, Backend::Singlepass) => Some(7), (Architecture::X64, Backend::Singlepass) => Some(INLINE_BREAKPOINT_SIZE_X86_SINGLEPASS),
(Architecture::Aarch64, Backend::Singlepass) => Some(12), (Architecture::Aarch64, Backend::Singlepass) => Some(INLINE_BREAKPOINT_SIZE_AARCH64_SINGLEPASS),
_ => None, _ => 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( pub fn read_inline_breakpoint(
arch: Architecture, arch: Architecture,
backend: Backend, backend: Backend,
@ -112,16 +131,18 @@ pub fn read_inline_breakpoint(
match arch { match arch {
Architecture::X64 => match backend { Architecture::X64 => match backend {
Backend::Singlepass => { Backend::Singlepass => {
if code.len() < 7 { if code.len() < INLINE_BREAKPOINT_SIZE_X86_SINGLEPASS {
None None
} else if &code[..6] == &[0x0f, 0x0b, 0x0f, 0xb9, 0xcd, 0xff] { } else if &code[..INLINE_BREAKPOINT_SIZE_X86_SINGLEPASS - 1] == &[
// ud2 ud (int 0xff) code 0x0f, 0x0b, // ud2
0x0f, 0xb9, // ud
0xcd, 0xff, // int 0xff
] {
Some(InlineBreakpoint { Some(InlineBreakpoint {
size: 7, size: INLINE_BREAKPOINT_SIZE_X86_SINGLEPASS,
ty: match code[6] { ty: match code[INLINE_BREAKPOINT_SIZE_X86_SINGLEPASS - 1] {
0 => InlineBreakpointType::Trace, 0 => InlineBreakpointType::Middleware,
1 => InlineBreakpointType::Middleware, _ => return None,
_ => InlineBreakpointType::Unknown,
}, },
}) })
} else { } else {
@ -132,15 +153,17 @@ pub fn read_inline_breakpoint(
}, },
Architecture::Aarch64 => match backend { Architecture::Aarch64 => match backend {
Backend::Singlepass => { Backend::Singlepass => {
if code.len() < 12 { if code.len() < INLINE_BREAKPOINT_SIZE_AARCH64_SINGLEPASS {
None 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 { Some(InlineBreakpoint {
size: 12, size: INLINE_BREAKPOINT_SIZE_AARCH64_SINGLEPASS,
ty: match code[8] { ty: match code[INLINE_BREAKPOINT_SIZE_AARCH64_SINGLEPASS - 4] {
0 => InlineBreakpointType::Trace, 0 => InlineBreakpointType::Middleware,
1 => InlineBreakpointType::Middleware, _ => return None,
_ => InlineBreakpointType::Unknown,
}, },
}) })
} else { } else {