You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bddisasm/bindings/rsbddisasm/bddisasm/src/cpu_modes.rs

148 lines
4.3 KiB

/*
* Copyright (c) 2021 Bitdefender
* SPDX-License-Identifier: Apache-2.0
*/
//! Offers information about the CPU modes in which an instruction is supported.
//!
//! # Examples
//!
//! ```
//! # use std::error::Error;
//! #
//! # fn main() -> Result<(), Box<dyn Error>> {
//! use bddisasm::decoded_instruction::{DecodedInstruction, DecodeMode, Mnemonic, OperandSize};
//!
//! // `VMXON qword ptr [rax]`
//! let ins = DecodedInstruction::decode(&[0xf3, 0x0f, 0xc7, 0x30], DecodeMode::Bits64)?;
//! let modes = ins.valid_cpu_modes();
//!
//! // Check if the instruction is available from user mode
//! if modes.privilege_level.ring3 {
//! println!("Available in user mode");
//! } else {
//! println!("Not available in user mode");
//! }
//!
//! # Ok(())
//! # }
extern crate bddisasm_sys as ffi;
// TODO: maybe use something like the `bitflags` crate and have all these as flags?
/// Privilege levels (rings) in which an instruction is supported.
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct PrivilegeLevel {
pub ring0: bool,
pub ring1: bool,
pub ring2: bool,
pub ring3: bool,
}
/// Operating modes in which an instruction is supported.
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct OperatingMode {
/// The instruction is valid in real mode.
pub real: bool,
/// The instruction is valid in Virtual 8086 mode.
pub v8086: bool,
/// The instruction is valid in protected mode (32 bit).
pub protected: bool,
/// The instruction is valid in compatibility mode (32 bit in 64 bit).
pub compat: bool,
/// The instruction is valid in long mode.
pub long: bool,
}
/// Special modes - these may be active inside other modes (example: `TSX` in `Long mode`).
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct SpecialModes {
/// The instruction is valid in System Management Mode.
pub smm: bool,
/// The instruction is valid outside System Management Mode.
pub smm_off: bool,
/// The instruction is valid in SGX mode.
pub sgx: bool,
/// The instruction is valid outside SGX mode.
pub sgx_off: bool,
/// The instruction is valid in transactional regions.
pub tsx: bool,
/// The instruction is valid in transactional regions.
pub tsx_off: bool,
}
/// VMX mode - they engulf all the other modes.
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct VmxMode {
/// The instruction is valid in VMX root mode.
pub root: bool,
/// The instruction is valid in VMX non root mode.
pub non_root: bool,
/// The instruction is valid in VMX root SEAM.
pub root_seam: bool,
/// The instruction is valid in VMX non-root SEAM.
pub non_root_seam: bool,
/// The instruction is valid outside VMX operation.
pub off: bool,
}
/// Indicates in which modes the instruction is valid in
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct CpuModes {
pub privilege_level: PrivilegeLevel,
pub operating_mode: OperatingMode,
pub special_modes: SpecialModes,
pub vmx: VmxMode,
}
#[doc(hidden)]
impl From<ffi::ND_VALID_MODES> for CpuModes {
fn from(raw: ffi::ND_VALID_MODES) -> CpuModes {
let raw = unsafe { raw.__bindgen_anon_1 };
CpuModes {
privilege_level: PrivilegeLevel {
ring0: raw.Ring0() != 0,
ring1: raw.Ring1() != 0,
ring2: raw.Ring2() != 0,
ring3: raw.Ring3() != 0,
},
operating_mode: OperatingMode {
real: raw.Real() != 0,
v8086: raw.V8086() != 0,
protected: raw.Protected() != 0,
compat: raw.Compat() != 0,
long: raw.Long() != 0,
},
special_modes: SpecialModes {
smm: raw.Smm() != 0,
smm_off: raw.SmmOff() != 0,
sgx: raw.Sgx() != 0,
sgx_off: raw.SgxOff() != 0,
tsx: raw.Tsx() != 0,
tsx_off: raw.TsxOff() != 0,
},
vmx: VmxMode {
root: raw.VmxRoot() != 0,
non_root: raw.VmxNonRoot() != 0,
root_seam: raw.VmxRootSeam() != 0,
non_root_seam: raw.VmxNonRootSeam() != 0,
off: raw.VmxOff() != 0,
},
}
}
}