hex_patch/app/
instruction.rs

1use std::{collections::HashMap, fmt::Display};
2
3use capstone::Insn;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct Instruction {
7    pub(super) mnemonic: String,
8    pub(super) operands: String,
9    pub(super) virtual_address: u64,
10    pub(super) bytes: Vec<u8>,
11}
12
13impl Instruction {
14    pub fn new(instruction: &Insn, symbols: Option<&HashMap<u64, String>>) -> Self {
15        let mnemonic = instruction.mnemonic().expect("Failed to get mnemonic");
16        let operands = instruction.op_str().expect("Failed to get operands");
17        let operands = operands.split(", ").collect::<Vec<_>>();
18        let mut operands_string = String::new();
19        for (i, operand) in operands.iter().enumerate() {
20            let mut found_symbol = false;
21            if let Some(symbols) = &symbols {
22                if let Some(operand) = operand.strip_prefix("0x") {
23                    if let Ok(operand_address) = u64::from_str_radix(operand, 16) {
24                        if let Some(symbol) = symbols.get(&operand_address) {
25                            found_symbol = true;
26                            operands_string.push_str(symbol);
27                        }
28                    }
29                }
30                if let Some(operand) = operand.strip_prefix("#0x") {
31                    if let Ok(operand_address) = u64::from_str_radix(operand, 16) {
32                        if let Some(symbol) = symbols.get(&operand_address) {
33                            found_symbol = true;
34                            operands_string.push_str(symbol);
35                        }
36                    }
37                }
38            }
39            if !found_symbol {
40                operands_string.push_str(operand);
41            }
42            if i < operands.len() - 1 {
43                operands_string.push_str(", ");
44            }
45        }
46        let virtual_address = instruction.address();
47        let bytes = instruction.bytes().to_vec();
48        Instruction {
49            mnemonic: mnemonic.to_string(),
50            operands: operands_string,
51            virtual_address,
52            bytes,
53        }
54    }
55
56    pub fn mnemonic(&self) -> &str {
57        &self.mnemonic
58    }
59
60    pub fn operands(&self) -> &str {
61        &self.operands
62    }
63
64    pub fn ip(&self) -> u64 {
65        self.virtual_address
66    }
67
68    pub fn len(&self) -> usize {
69        self.bytes.len()
70    }
71
72    pub fn is_empty(&self) -> bool {
73        self.bytes.is_empty()
74    }
75}
76
77impl Display for Instruction {
78    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
79        write!(f, "{} {}", self.mnemonic, self.operands)
80    }
81}