Open bcantrill opened 4 years ago
Thanks for filing the issue! As you pointed out, this will mostly be solved once we fix #68.
It seems like you probably have the right idea that we should always call cs_regs_access
when in detail mode. However, cs_regs_access
only seems to be supported on x86, arm, and arm64, so we don't want to error out if a call fails (just ignore).
Just hit this. Are you planning on fixing this? If you are busy, is the fix something I can help with?
@vn-ki I did not make any plans to implement this myself. I would greatly appreciate help with this! Would you like to open a PR? I would be happy to help with any questions you have.
The reason I have not gotten to this is that the support is limited to only a few architectures, which potentially complicates the implementation. Some open questions:
1) Should regs_read()
/regs_write()
always call cs_regs_access
?
2) How should we manage the lifetimes? Should we just copy into Rust-managed memory?
If you open a PR, please reference this issue (#84) and the original #63.
@tmfink I'll be happy to open a PR.
Some ideas:
capstone::InsnDetail
corresponding to regs_read and regs_write. Depending on the architecture, we can return the one from cs_detail
or the one from cs_regs_access
. The initialization of these new two arrays would be at the time of construction when calling capstone::Capstone::insn_detail
. Capstone::reg_access(&Insn)
function which will call the cs_regs_access
and return a InsnRegs(CapstoneRegs, CapstoneRegs)
(lifetime shouldn't be an issue here since we are returning two fixed length arrays. Unless we want the regs to not live longer than the instruction). This is what the python binding seem to be doing, see details api and regs_access API.I think approach 1 would be less confusing for the end user while approach 2 would be more inline with what upstream thinks is idiomatic (which might mean less headaches with future updates). Also with approach 2, maybe the user will have less of a headache if they want these regs to outlive the instruction?
Tell me if you think of any of these ones are good or if you had some other ideas?
@vn-ki Thanks for the proposals. My thoughts after thinking for a few days:
cs_regs_access()
when callingcs_regs_access()
API
Capstone
or InsnDetail
I think I favor approach 1. We already bend over backwards to adapt to Capstone's "interesting" C API.
Some notes when implementing:
regs_read
/regs_write
, I suggest using a Option<Box<cs_regs>>
Option
when one of InsnDetail::{regs_read, regs_write}
are called.MaybeUnit
to avoid the "zeroizing" cost; initialization only happens once per Capstone
instanceHi, is @vn-ki still working on this?
The instruction detail provided via
InsnDetail
'sregs_write()
andregs_read()
only return a subset of the registers written to or read from.For example, running the C-based
cstool
:In contrast, running the capstone-rs-based
cstool
:The problem -- alluded to in #63 -- is that the C-based consumers are explicitly calling
cs_regs_access()
while the Rust-based consumers have no way of knowing that this must be called. There are a number of ways of fixing this, but it seems that callinginsn_detail()
should return anInsnDetail
for whichregs_write()
/regs_read()
return correct data -- and therefore thatinsn_detail()
should explicitly make the call tocs_regs_access()
.Here is a diff that implements this:
Running with this diff, the capstone-rs-based
cstool
has the correct results: