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
16            .mnemonic()
17            .expect(&t!("errors.instruction_no_mnemonic"));
18        let operands = instruction
19            .op_str()
20            .expect(&t!("errors.instruction_no_operands"));
21        let operands = operands.split(", ").collect::<Vec<_>>();
22        let mut operands_string = String::new();
23        for (i, operand) in operands.iter().enumerate() {
24            let mut found_symbol = false;
25            if let Some(symbols) = &symbols {
26                if let Some(operand) = operand.strip_prefix("0x") {
27                    if let Ok(operand_address) = u64::from_str_radix(operand, 16) {
28                        if let Some(symbol) = symbols.get(&operand_address) {
29                            found_symbol = true;
30                            operands_string.push_str(symbol);
31                        }
32                    }
33                }
34                if let Some(operand) = operand.strip_prefix("#0x") {
35                    if let Ok(operand_address) = u64::from_str_radix(operand, 16) {
36                        if let Some(symbol) = symbols.get(&operand_address) {
37                            found_symbol = true;
38                            operands_string.push_str(symbol);
39                        }
40                    }
41                }
42            }
43            if !found_symbol {
44                operands_string.push_str(operand);
45            }
46            if i < operands.len() - 1 {
47                operands_string.push_str(", ");
48            }
49        }
50        let virtual_address = instruction.address();
51        let bytes = instruction.bytes().to_vec();
52        Instruction {
53            mnemonic: mnemonic.to_string(),
54            operands: operands_string,
55            virtual_address,
56            bytes,
57        }
58    }
59
60    pub fn mnemonic(&self) -> &str {
61        &self.mnemonic
62    }
63
64    pub fn operands(&self) -> &str {
65        &self.operands
66    }
67
68    pub fn ip(&self) -> u64 {
69        self.virtual_address
70    }
71
72    pub fn len(&self) -> usize {
73        self.bytes.len()
74    }
75
76    pub fn is_empty(&self) -> bool {
77        self.bytes.is_empty()
78    }
79}
80
81impl Display for Instruction {
82    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
83        write!(f, "{} {}", self.mnemonic, self.operands)
84    }
85}