-
Notifications
You must be signed in to change notification settings - Fork 78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
capstone: add cs_regs_access #77
base: master
Are you sure you want to change the base?
Changes from 2 commits
c8e130a
35ad1ec
4791dab
67a4617
ada788e
0475878
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -145,6 +145,14 @@ pub struct Insn<'a> { | |
/// `ArchDetail` enum. | ||
pub struct InsnDetail<'a>(pub(crate) &'a cs_detail, pub(crate) Arch); | ||
|
||
/// Contains information about registers accessed by an instruction, either explicitly or implicitly | ||
pub struct InsnRegsAccess { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you manually impl |
||
pub(crate) regs_read: cs_regs, | ||
pub(crate) regs_read_count: u8, | ||
pub(crate) regs_write: cs_regs, | ||
pub(crate) regs_write_count: u8, | ||
} | ||
|
||
impl<'a> Insn<'a> { | ||
/// The mnemonic for the instruction | ||
pub fn mnemonic(&self) -> Option<&str> { | ||
|
@@ -184,6 +192,15 @@ impl<'a> Insn<'a> { | |
pub(crate) unsafe fn detail(&self, arch: Arch) -> InsnDetail { | ||
InsnDetail(&*self.insn.detail, arch) | ||
} | ||
|
||
/// Returns the `RegsAccess` object, if there is one. It is up to the caller to determine | ||
/// the pre-conditions are satisfied. | ||
/// | ||
/// Be careful this is still in early stages and largely untested with various `cs_option` and | ||
/// architecture matrices | ||
pub(crate) unsafe fn regs_access(&self, cs: csh) -> InsnRegsAccess { | ||
InsnRegsAccess::new(cs, &self.insn) | ||
} | ||
} | ||
|
||
impl<'a> Debug for Insn<'a> { | ||
|
@@ -328,6 +345,64 @@ impl<'a> InsnDetail<'a> { | |
} | ||
} | ||
|
||
impl<'a> InsnRegsAccess { | ||
fn new(cs: csh, ins: &cs_insn) -> Self { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any function that can cause undefined behavior should be marked unsafe. However, once you move the error checking (checking return value), then this shouldn't need to be marked unsafe. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have this return a |
||
let mut regs_read = [0u16; 64]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you give an example how to initialize a variable with a type? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like pub type cs_regs = [u16; 64usize]; Just add an explicit type instead of using type inference: let mut regs_read: cs_regs = [0u16; 64]; |
||
let mut regs_read_count = 0u8; | ||
let mut regs_write = [0u16; 64]; | ||
let mut regs_write_count = 0u8; | ||
|
||
unsafe { | ||
cs_regs_access( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. check this return value to create a CsResult |
||
cs, | ||
ins, | ||
regs_read.as_mut_ptr(), | ||
&mut regs_read_count, | ||
regs_write.as_mut_ptr(), | ||
&mut regs_write_count, | ||
); | ||
} | ||
|
||
Self { | ||
regs_read, | ||
regs_read_count, | ||
regs_write, | ||
regs_write_count, | ||
} | ||
} | ||
|
||
/// Returns the explicit and implicit accessed registers | ||
pub fn regs_read(&self) -> RegsIter<RegIdInt> { | ||
RegsIter(self.regs_read[..self.regs_read_count as usize].iter()) | ||
} | ||
|
||
/// Returns the number of explicit and implicit read registers | ||
pub fn regs_read_count(&self) -> u8 { | ||
self.regs_read_count | ||
} | ||
|
||
/// Returns the explicit and implicit write registers | ||
pub fn regs_write(&self) -> RegsIter<RegIdInt> { | ||
RegsIter(self.regs_write[..self.regs_write_count as usize].iter()) | ||
} | ||
|
||
/// Returns the number of explicit and implicit write registers | ||
pub fn regs_write_count(&self) -> u8 { | ||
self.regs_write_count | ||
} | ||
} | ||
|
||
impl Debug for InsnRegsAccess { | ||
tmfink marked this conversation as resolved.
Show resolved
Hide resolved
|
||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { | ||
fmt.debug_struct("RegsAccess") | ||
.field("regs_read", &self.regs_read()) | ||
.field("regs_read_count", &self.regs_read_count()) | ||
.field("regs_write", &self.regs_write()) | ||
.field("regs_write_count", &self.regs_write_count()) | ||
.finish() | ||
} | ||
} | ||
|
||
impl<'a> Debug for InsnDetail<'a> { | ||
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { | ||
fmt.debug_struct("Detail") | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of trying to do all of the error handling here, check the returned integer and convert that to a
CsResult
.You can move that logic into
That way, we don't have to manually track all possible errors that capstone should be handling anyway.
For examples, see
disasm()
. Also,From<capstone_sys::cs_err::Type>
is implemented forError
, so you can use Error::from(capstone_sys_rc)` to do the error parsing for you.