Skip to content

Commit 14e855c

Browse files
authored
Add regs_access (#149)
1 parent 478d765 commit 14e855c

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

capstone-rs/src/capstone.rs

+67
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ use crate::instruction::{Insn, InsnDetail, InsnGroupId, InsnId, Instructions, Re
1414

1515
use {crate::ffi::str_from_cstr_ptr, alloc::string::ToString, libc::c_uint};
1616

17+
/// This is taken from the [python bindings](https://github.com/capstone-engine/capstone/blob/5fb8a423d4455cade99b12912142fd3a0c10d957/bindings/python/capstone/__init__.py#L929)
18+
const MAX_NUM_REGISTERS: usize = 64;
19+
1720
/// An instance of the capstone disassembler
1821
///
1922
/// Create with an instance with [`.new()`](Self::new) and disassemble bytes with [`.disasm_all()`](Self::disasm_all).
@@ -100,6 +103,11 @@ impl Iterator for EmptyExtraModeIter {
100103
}
101104
}
102105

106+
pub struct RegAccess {
107+
pub read: Vec<RegId>,
108+
pub write: Vec<RegId>,
109+
}
110+
103111
impl Capstone {
104112
/// Create a new instance of the decompiler using the builder pattern interface.
105113
/// This is the recommended interface to `Capstone`.
@@ -365,6 +373,65 @@ impl Capstone {
365373
}
366374
}
367375

376+
/// Get the registers are which are read to and written to
377+
pub fn regs_access_buf(&self, insn: &Insn) -> CsResult<RegAccess> {
378+
let mut read = Vec::new();
379+
let mut write = Vec::new();
380+
381+
self.regs_access(insn, &mut read, &mut write)?;
382+
383+
Ok(RegAccess { read, write })
384+
}
385+
386+
/// Get the registers are which are read to and written to\
387+
/// the registers are pushed to the back of the provided buffers
388+
pub fn regs_access(
389+
&self,
390+
insn: &Insn,
391+
read: &mut Vec<RegId>,
392+
write: &mut Vec<RegId>,
393+
) -> CsResult<()> {
394+
if cfg!(feature = "full") {
395+
let mut regs_read_count: u8 = 0;
396+
let mut regs_write_count: u8 = 0;
397+
398+
let mut regs_write = [0u16; MAX_NUM_REGISTERS];
399+
let mut regs_read = [0u16; MAX_NUM_REGISTERS];
400+
401+
let err = unsafe {
402+
cs_regs_access(
403+
self.csh(),
404+
&insn.insn as *const cs_insn,
405+
&mut regs_read as *mut _,
406+
&mut regs_read_count as *mut _,
407+
&mut regs_write as *mut _,
408+
&mut regs_write_count as *mut _,
409+
)
410+
};
411+
412+
if err != cs_err::CS_ERR_OK {
413+
return Err(err.into());
414+
}
415+
416+
read.extend(
417+
regs_read
418+
.iter()
419+
.take(regs_read_count as usize)
420+
.map(|x| RegId(*x)),
421+
);
422+
write.extend(
423+
regs_write
424+
.iter()
425+
.take(regs_write_count as usize)
426+
.map(|x| RegId(*x)),
427+
);
428+
429+
Ok(())
430+
} else {
431+
Err(Error::DetailOff)
432+
}
433+
}
434+
368435
/// Converts a group id `group_id` to a `String` containing the group name.
369436
/// Unavailable in Diet mode
370437
pub fn group_name(&self, group_id: InsnGroupId) -> Option<String> {

0 commit comments

Comments
 (0)