feat(rust): improve ARM CP register ergonomics (#2160)
This commit is contained in:
@@ -215,11 +215,11 @@ where
|
|||||||
pub unsafe extern "C" fn insn_sys_hook_proxy_arm64<D, F>(
|
pub unsafe extern "C" fn insn_sys_hook_proxy_arm64<D, F>(
|
||||||
uc: *mut uc_engine,
|
uc: *mut uc_engine,
|
||||||
reg: sys::RegisterARM64,
|
reg: sys::RegisterARM64,
|
||||||
cp_reg: *const sys::RegisterARM64_CP,
|
cp_reg: *const sys::RegisterARM64CP,
|
||||||
user_data: *mut UcHook<D, F>,
|
user_data: *mut UcHook<D, F>,
|
||||||
) -> bool
|
) -> bool
|
||||||
where
|
where
|
||||||
F: FnMut(&mut crate::Unicorn<D>, sys::RegisterARM64, &sys::RegisterARM64_CP) -> bool,
|
F: FnMut(&mut crate::Unicorn<D>, sys::RegisterARM64, &sys::RegisterARM64CP) -> bool,
|
||||||
{
|
{
|
||||||
let user_data = unsafe { &mut *user_data };
|
let user_data = unsafe { &mut *user_data };
|
||||||
let mut user_data_uc = Unicorn {
|
let mut user_data_uc = Unicorn {
|
||||||
|
|||||||
@@ -573,7 +573,7 @@ impl<'a, D> Unicorn<'a, D> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Read ARM Coprocessor register
|
/// Read ARM Coprocessor register
|
||||||
pub fn reg_read_arm_coproc(&self, reg: &mut RegisterARM_CP) -> Result<(), uc_error> {
|
pub fn reg_read_arm_coproc(&self, reg: &mut RegisterARMCP) -> Result<(), uc_error> {
|
||||||
let curr_arch = self.get_arch();
|
let curr_arch = self.get_arch();
|
||||||
match curr_arch {
|
match curr_arch {
|
||||||
#[cfg(feature = "arch_arm")]
|
#[cfg(feature = "arch_arm")]
|
||||||
@@ -585,14 +585,33 @@ impl<'a, D> Unicorn<'a, D> {
|
|||||||
uc_reg_read(
|
uc_reg_read(
|
||||||
self.get_handle(),
|
self.get_handle(),
|
||||||
RegisterARM::CP_REG.into(),
|
RegisterARM::CP_REG.into(),
|
||||||
core::ptr::from_mut::<RegisterARM_CP>(reg).cast(),
|
core::ptr::from_mut(reg).cast(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write ARM Coprocessor register
|
||||||
|
pub fn reg_write_arm_coproc(&mut self, reg: &RegisterARMCP) -> Result<(), uc_error> {
|
||||||
|
let curr_arch = self.get_arch();
|
||||||
|
match curr_arch {
|
||||||
|
#[cfg(feature = "arch_arm")]
|
||||||
|
Arch::ARM => {}
|
||||||
|
_ => return Err(uc_error::ARCH),
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
uc_reg_write(
|
||||||
|
self.get_handle(),
|
||||||
|
RegisterARM::CP_REG.into(),
|
||||||
|
core::ptr::from_ref(reg).cast(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read ARM64 Coprocessor register
|
/// Read ARM64 Coprocessor register
|
||||||
pub fn reg_read_arm64_coproc(&self) -> Result<RegisterARM64_CP, uc_error> {
|
pub fn reg_read_arm64_coproc(&self, reg: &mut RegisterARM64CP) -> Result<(), uc_error> {
|
||||||
let curr_arch = self.get_arch();
|
let curr_arch = self.get_arch();
|
||||||
match curr_arch {
|
match curr_arch {
|
||||||
#[cfg(feature = "arch_aarch64")]
|
#[cfg(feature = "arch_aarch64")]
|
||||||
@@ -600,17 +619,33 @@ impl<'a, D> Unicorn<'a, D> {
|
|||||||
_ => return Err(uc_error::ARCH),
|
_ => return Err(uc_error::ARCH),
|
||||||
}
|
}
|
||||||
|
|
||||||
let regid = RegisterARM64::CP_REG;
|
unsafe {
|
||||||
let mut reg = RegisterARM64_CP {
|
uc_reg_read(
|
||||||
crn: 0,
|
self.get_handle(),
|
||||||
crm: 0,
|
RegisterARM64::CP_REG.into(),
|
||||||
op0: 0,
|
core::ptr::from_mut(reg).cast(),
|
||||||
op1: 0,
|
)
|
||||||
op2: 0,
|
}
|
||||||
val: 0,
|
.and(Ok(()))
|
||||||
};
|
}
|
||||||
|
|
||||||
unsafe { uc_reg_read(self.get_handle(), regid as i32, (&raw mut reg).cast()) }.and(Ok(reg))
|
/// Write ARM64 Coprocessor register
|
||||||
|
pub fn reg_write_arm64_coproc(&mut self, reg: &RegisterARM64CP) -> Result<(), uc_error> {
|
||||||
|
let curr_arch = self.get_arch();
|
||||||
|
match curr_arch {
|
||||||
|
#[cfg(feature = "arch_aarch64")]
|
||||||
|
Arch::ARM64 => {}
|
||||||
|
_ => return Err(uc_error::ARCH),
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
uc_reg_write(
|
||||||
|
self.get_handle(),
|
||||||
|
RegisterARM64::CP_REG.into(),
|
||||||
|
core::ptr::from_ref(reg).cast(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.and(Ok(()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "arch_arm")]
|
#[cfg(feature = "arch_arm")]
|
||||||
@@ -925,7 +960,7 @@ impl<'a, D> Unicorn<'a, D> {
|
|||||||
callback: F,
|
callback: F,
|
||||||
) -> Result<UcHookId, uc_error>
|
) -> Result<UcHookId, uc_error>
|
||||||
where
|
where
|
||||||
F: FnMut(&mut Unicorn<D>, RegisterARM64, &RegisterARM64_CP) -> bool + 'a,
|
F: FnMut(&mut Unicorn<D>, RegisterARM64, &RegisterARM64CP) -> bool + 'a,
|
||||||
{
|
{
|
||||||
let mut hook_id = 0;
|
let mut hook_id = 0;
|
||||||
let mut user_data = Box::new(hook::UcHook {
|
let mut user_data = Box::new(hook::UcHook {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::{ArmCpuModel, RegisterARM, RegisterARM_CP, TcgOpCode, TcgOpFlag, uc_error};
|
use crate::{ArmCpuModel, RegisterARM, RegisterARMCP, TcgOpCode, TcgOpFlag, uc_error};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_arm_nop() {
|
fn test_arm_nop() {
|
||||||
@@ -600,16 +600,7 @@ fn test_arm_mem_access_abort() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_arm_read_sctlr() {
|
fn test_arm_read_sctlr() {
|
||||||
let uc = Unicorn::new(Arch::ARM, Mode::ARM).unwrap();
|
let uc = Unicorn::new(Arch::ARM, Mode::ARM).unwrap();
|
||||||
let mut reg = RegisterARM_CP {
|
let mut reg = RegisterARMCP::new().cp(15).crn(1);
|
||||||
cp: 15,
|
|
||||||
is64: 0,
|
|
||||||
sec: 0,
|
|
||||||
crn: 1,
|
|
||||||
crm: 0,
|
|
||||||
opc1: 0,
|
|
||||||
opc2: 0,
|
|
||||||
val: 0,
|
|
||||||
};
|
|
||||||
uc.reg_read_arm_coproc(&mut reg).unwrap();
|
uc.reg_read_arm_coproc(&mut reg).unwrap();
|
||||||
assert_eq!((reg.val >> 31) & 1, 0);
|
assert_eq!((reg.val >> 31) & 1, 0);
|
||||||
}
|
}
|
||||||
@@ -620,16 +611,7 @@ fn test_arm_be_cpsr_sctlr() {
|
|||||||
uc.ctl_set_cpu_model(ArmCpuModel::Model_1176 as i32)
|
uc.ctl_set_cpu_model(ArmCpuModel::Model_1176 as i32)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut reg = RegisterARM_CP {
|
let mut reg = RegisterARMCP::new().cp(15).crn(1);
|
||||||
cp: 15,
|
|
||||||
is64: 0,
|
|
||||||
sec: 0,
|
|
||||||
crn: 1,
|
|
||||||
crm: 0,
|
|
||||||
opc1: 0,
|
|
||||||
opc2: 0,
|
|
||||||
val: 0,
|
|
||||||
};
|
|
||||||
uc.reg_read_arm_coproc(&mut reg).unwrap();
|
uc.reg_read_arm_coproc(&mut reg).unwrap();
|
||||||
let cpsr = uc.reg_read(RegisterARM::CPSR).unwrap();
|
let cpsr = uc.reg_read(RegisterARM::CPSR).unwrap();
|
||||||
|
|
||||||
@@ -640,16 +622,7 @@ fn test_arm_be_cpsr_sctlr() {
|
|||||||
uc.ctl_set_cpu_model(ArmCpuModel::CORTEX_A15 as i32)
|
uc.ctl_set_cpu_model(ArmCpuModel::CORTEX_A15 as i32)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut reg = RegisterARM_CP {
|
let mut reg = RegisterARMCP::new().cp(15).crn(1);
|
||||||
cp: 15,
|
|
||||||
is64: 0,
|
|
||||||
sec: 0,
|
|
||||||
crn: 1,
|
|
||||||
crm: 0,
|
|
||||||
opc1: 0,
|
|
||||||
opc2: 0,
|
|
||||||
val: 0,
|
|
||||||
};
|
|
||||||
uc.reg_read_arm_coproc(&mut reg).unwrap();
|
uc.reg_read_arm_coproc(&mut reg).unwrap();
|
||||||
let cpsr = uc.reg_read(RegisterARM::CPSR).unwrap();
|
let cpsr = uc.reg_read(RegisterARM::CPSR).unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use unicorn_engine_sys::{Arm64CpuModel, Arm64Insn, RegisterARM64};
|
use unicorn_engine_sys::{Arm64CpuModel, Arm64Insn, RegisterARM64, RegisterARM64CP};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@@ -142,7 +142,8 @@ fn test_arm64_v8_pac() {
|
|||||||
fn test_arm64_read_sctlr() {
|
fn test_arm64_read_sctlr() {
|
||||||
let uc = Unicorn::new(Arch::ARM64, Mode::ARM | Mode::LITTLE_ENDIAN).unwrap();
|
let uc = Unicorn::new(Arch::ARM64, Mode::ARM | Mode::LITTLE_ENDIAN).unwrap();
|
||||||
|
|
||||||
let reg = uc.reg_read_arm64_coproc().unwrap();
|
let mut reg = RegisterARM64CP::new().crn(1).op0(0b11);
|
||||||
|
uc.reg_read_arm64_coproc(&mut reg).unwrap();
|
||||||
|
|
||||||
assert_eq!(reg.val >> 58, 0);
|
assert_eq!(reg.val >> 58, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ fn test_ppc32_add() {
|
|||||||
|
|
||||||
// https://www.ibm.com/docs/en/aix/7.2?topic=set-fadd-fa-floating-add-instruction
|
// https://www.ibm.com/docs/en/aix/7.2?topic=set-fadd-fa-floating-add-instruction
|
||||||
#[test]
|
#[test]
|
||||||
// #[ignore = "Crashes on Windows & some Linux distros"]
|
|
||||||
fn test_ppc32_fadd() {
|
fn test_ppc32_fadd() {
|
||||||
let code = [
|
let code = [
|
||||||
0xfc, 0xc4, 0x28, 0x2a, // fadd 6, 4, 5
|
0xfc, 0xc4, 0x28, 0x2a, // fadd 6, 4, 5
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ impl ParseCallbacks for Renamer {
|
|||||||
return original_item_name
|
return original_item_name
|
||||||
.strip_prefix("uc_")
|
.strip_prefix("uc_")
|
||||||
.and_then(|suffix| suffix.strip_suffix("_reg"))
|
.and_then(|suffix| suffix.strip_suffix("_reg"))
|
||||||
.map(|suffix| format!("Register{}", suffix.to_uppercase()));
|
.map(|suffix| format!("Register{}", suffix.replace('_', "").to_uppercase()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if original_item_name.ends_with("_insn") {
|
if original_item_name.ends_with("_insn") {
|
||||||
|
|||||||
@@ -113,6 +113,131 @@ impl ControlType {
|
|||||||
pub const IO_WRITE: Self = Self(1 << 30);
|
pub const IO_WRITE: Self = Self(1 << 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for RegisterARMCP {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterARMCP {
|
||||||
|
#[must_use]
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
cp: 0,
|
||||||
|
is64: 0,
|
||||||
|
sec: 0,
|
||||||
|
crn: 0,
|
||||||
|
crm: 0,
|
||||||
|
opc1: 0,
|
||||||
|
opc2: 0,
|
||||||
|
val: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn cp(mut self, cp: u32) -> Self {
|
||||||
|
self.cp = cp;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn is64(mut self, is64: u32) -> Self {
|
||||||
|
self.is64 = is64;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn sec(mut self, sec: u32) -> Self {
|
||||||
|
self.sec = sec;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn crn(mut self, crn: u32) -> Self {
|
||||||
|
self.crn = crn;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn crm(mut self, crm: u32) -> Self {
|
||||||
|
self.crm = crm;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn opc1(mut self, opc1: u32) -> Self {
|
||||||
|
self.opc1 = opc1;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn opc2(mut self, opc2: u32) -> Self {
|
||||||
|
self.opc2 = opc2;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn val(mut self, val: u64) -> Self {
|
||||||
|
self.val = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RegisterARM64CP {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RegisterARM64CP {
|
||||||
|
#[must_use]
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
crn: 0,
|
||||||
|
crm: 0,
|
||||||
|
op0: 0,
|
||||||
|
op1: 0,
|
||||||
|
op2: 0,
|
||||||
|
val: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[must_use]
|
||||||
|
pub const fn crn(mut self, crn: u32) -> Self {
|
||||||
|
self.crn = crn;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn crm(mut self, crm: u32) -> Self {
|
||||||
|
self.crm = crm;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn op0(mut self, op0: u32) -> Self {
|
||||||
|
self.op0 = op0;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn op1(mut self, op1: u32) -> Self {
|
||||||
|
self.op1 = op1;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn op2(mut self, op2: u32) -> Self {
|
||||||
|
self.op2 = op2;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn val(mut self, val: u64) -> Self {
|
||||||
|
self.val = val;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<M68kCpuModel> for i32 {
|
impl From<M68kCpuModel> for i32 {
|
||||||
fn from(value: M68kCpuModel) -> Self {
|
fn from(value: M68kCpuModel) -> Self {
|
||||||
value as Self
|
value as Self
|
||||||
|
|||||||
Reference in New Issue
Block a user