Skip to content
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

Implementing Clone for the Insn and cs_insn Structures #165

Closed
wants to merge 1 commit into from

Conversation

c3rb3ru5d3d53c
Copy link

Typically, when writing more complex code using capstone we can collect cs_insn structures on their own.

For example, we can create a list of cs_insn structures in Python without them going out of scope.

Currently this is not appearing to be possible in capstone-rs because the Insn and cs_insn structures only being accessed by reference when contained in Instructions iterator.

Most of the work on implementing the clone functionality has already been done for cs_detail structure and others.

This PR simply implements clone for both cs_insn and Insn structures, so it is possible to store these for later use in more complex projects.

Here is an example of using this functionality:

pub fn disassemble_instruction(&self, address: u64) -> Result<Insn, Error> {
        let instructions = match self.disassemble_instructions(address, 1) {
            Ok(instructions) => instructions,
            Err(error) => return Err(Error::new(ErrorKind::Other, "failed to disassemble instruction")),
        };
        let instruction: Insn<'_> = instructions.iter().next().unwrap().clone();
        return Ok(instruction);
    }

It also helps for when we need to iterate a single instruction at a time collecting them for later post-processing.

This becomes an issue when having to unpack from the Instructions iterator and only getting references without the possibility of cloning for later use.

This should not break any other features, it simply continues what was already done with cs_detail and other places clone has already been implemented in the capstone-rs project.

That being said, this is my first Rust-based PR, so proceed with caution.

Thank you 😄

@c3rb3ru5d3d53c
Copy link
Author

Nightly only appeared to have failed due to an unrelated cargo update segmentation fault, not sure why that is the case, all other tests appear to pass.

@tmfink
Copy link
Member

tmfink commented Nov 16, 2024

@c3rb3ru5d3d53c thanks for your PR! Sorry I have not had time to review the PR (yet).
Also, I allowed the rest of the tests to run--there are some tests failing.

@@ -15715,6 +15715,21 @@ pub struct cs_insn {
#[doc = " Pointer to cs_detail.\n NOTE: detail pointer is only valid when both requirements below are met:\n (1) CS_OP_DETAIL = CS_OPT_ON\n (2) Engine is not in Skipdata mode (CS_OP_SKIPDATA option set to CS_OPT_ON)\n\n NOTE 2: when in Skipdata mode, or when detail mode is OFF, even if this pointer\n is not NULL, its content is still irrelevant."]
pub detail: *mut cs_detail,
}

impl Clone for cs_insn {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is pre-generated using bindgen in the capstone-sys build.rs and should not be modified directly.

When capstone-sys is built with the "use_bindgen" feature, this file is completely ignored and bindgen is used to generate bindings from scratch.

Instead, look at how you can modify the build.rs file to generate the file how you would want.

@tmfink
Copy link
Member

tmfink commented Nov 16, 2024

I think what you want is provided by the OwnedInsn type which avoids holding a reference.

You can see an example in the test_owned_insn() function:

fn test_owned_insn() {
let cs = Capstone::new()
.x86()
.mode(x86::ArchMode::Mode64)
.detail(true)
.build()
.unwrap();
let insns = cs.disasm_all(X86_CODE, START_TEST_ADDR).unwrap();
let owned: Vec<OwnedInsn> = insns.iter().map(|i| i.into()).collect();
for (insn, owned) in insns.iter().zip(&owned) {
assert_eq!(format!("{:?}", insn), format!("{:?}", owned));
}
}

I'll close this PR for now, but feel free to comment on it if you think it should be re-opened.

@tmfink tmfink closed this Nov 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants