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>(
|
||||
uc: *mut uc_engine,
|
||||
reg: sys::RegisterARM64,
|
||||
cp_reg: *const sys::RegisterARM64_CP,
|
||||
cp_reg: *const sys::RegisterARM64CP,
|
||||
user_data: *mut UcHook<D, F>,
|
||||
) -> bool
|
||||
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 mut user_data_uc = Unicorn {
|
||||
|
||||
@@ -573,7 +573,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
}
|
||||
|
||||
/// 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();
|
||||
match curr_arch {
|
||||
#[cfg(feature = "arch_arm")]
|
||||
@@ -585,14 +585,33 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
uc_reg_read(
|
||||
self.get_handle(),
|
||||
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()
|
||||
}
|
||||
|
||||
/// 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();
|
||||
match curr_arch {
|
||||
#[cfg(feature = "arch_aarch64")]
|
||||
@@ -600,17 +619,33 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
_ => return Err(uc_error::ARCH),
|
||||
}
|
||||
|
||||
let regid = RegisterARM64::CP_REG;
|
||||
let mut reg = RegisterARM64_CP {
|
||||
crn: 0,
|
||||
crm: 0,
|
||||
op0: 0,
|
||||
op1: 0,
|
||||
op2: 0,
|
||||
val: 0,
|
||||
};
|
||||
unsafe {
|
||||
uc_reg_read(
|
||||
self.get_handle(),
|
||||
RegisterARM64::CP_REG.into(),
|
||||
core::ptr::from_mut(reg).cast(),
|
||||
)
|
||||
}
|
||||
.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")]
|
||||
@@ -925,7 +960,7 @@ impl<'a, D> Unicorn<'a, D> {
|
||||
callback: F,
|
||||
) -> Result<UcHookId, uc_error>
|
||||
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 user_data = Box::new(hook::UcHook {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use super::*;
|
||||
use crate::{ArmCpuModel, RegisterARM, RegisterARM_CP, TcgOpCode, TcgOpFlag, uc_error};
|
||||
use crate::{ArmCpuModel, RegisterARM, RegisterARMCP, TcgOpCode, TcgOpFlag, uc_error};
|
||||
|
||||
#[test]
|
||||
fn test_arm_nop() {
|
||||
@@ -600,16 +600,7 @@ fn test_arm_mem_access_abort() {
|
||||
#[test]
|
||||
fn test_arm_read_sctlr() {
|
||||
let uc = Unicorn::new(Arch::ARM, Mode::ARM).unwrap();
|
||||
let mut reg = RegisterARM_CP {
|
||||
cp: 15,
|
||||
is64: 0,
|
||||
sec: 0,
|
||||
crn: 1,
|
||||
crm: 0,
|
||||
opc1: 0,
|
||||
opc2: 0,
|
||||
val: 0,
|
||||
};
|
||||
let mut reg = RegisterARMCP::new().cp(15).crn(1);
|
||||
uc.reg_read_arm_coproc(&mut reg).unwrap();
|
||||
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)
|
||||
.unwrap();
|
||||
|
||||
let mut reg = RegisterARM_CP {
|
||||
cp: 15,
|
||||
is64: 0,
|
||||
sec: 0,
|
||||
crn: 1,
|
||||
crm: 0,
|
||||
opc1: 0,
|
||||
opc2: 0,
|
||||
val: 0,
|
||||
};
|
||||
let mut reg = RegisterARMCP::new().cp(15).crn(1);
|
||||
uc.reg_read_arm_coproc(&mut reg).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)
|
||||
.unwrap();
|
||||
|
||||
let mut reg = RegisterARM_CP {
|
||||
cp: 15,
|
||||
is64: 0,
|
||||
sec: 0,
|
||||
crn: 1,
|
||||
crm: 0,
|
||||
opc1: 0,
|
||||
opc2: 0,
|
||||
val: 0,
|
||||
};
|
||||
let mut reg = RegisterARMCP::new().cp(15).crn(1);
|
||||
uc.reg_read_arm_coproc(&mut reg).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::*;
|
||||
|
||||
@@ -142,7 +142,8 @@ fn test_arm64_v8_pac() {
|
||||
fn test_arm64_read_sctlr() {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ fn test_ppc32_add() {
|
||||
|
||||
// https://www.ibm.com/docs/en/aix/7.2?topic=set-fadd-fa-floating-add-instruction
|
||||
#[test]
|
||||
// #[ignore = "Crashes on Windows & some Linux distros"]
|
||||
fn test_ppc32_fadd() {
|
||||
let code = [
|
||||
0xfc, 0xc4, 0x28, 0x2a, // fadd 6, 4, 5
|
||||
|
||||
@@ -227,7 +227,7 @@ impl ParseCallbacks for Renamer {
|
||||
return original_item_name
|
||||
.strip_prefix("uc_")
|
||||
.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") {
|
||||
|
||||
@@ -113,6 +113,131 @@ impl ControlType {
|
||||
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 {
|
||||
fn from(value: M68kCpuModel) -> Self {
|
||||
value as Self
|
||||
|
||||
Reference in New Issue
Block a user