retour\arch\x86\trampoline/
disasm.rs1use std::slice;
3
4pub struct Disassembler(udis::ud);
6
7impl Disassembler {
8 pub fn new(target: *const ()) -> Disassembler {
10 unsafe {
11 let mut ud = ::std::mem::zeroed();
12 udis::ud_init(&mut ud);
13 udis::ud_set_user_opaque_data(&mut ud, target as *mut _);
14 udis::ud_set_input_hook(&mut ud, Some(Self::udis_read_address));
15 udis::ud_set_mode(&mut ud, (::std::mem::size_of::<usize>() * 8) as u8);
16 Disassembler(ud)
17 }
18 }
19
20 unsafe extern "C" fn udis_read_address(ud: *mut udis::ud) -> libc::c_int {
22 let pointer = udis::ud_get_user_opaque_data(ud) as *mut u8;
23 let result = *pointer;
24 udis::ud_set_user_opaque_data(ud, pointer.offset(1) as *mut _);
25 libc::c_int::from(result)
26 }
27}
28
29pub struct Instruction {
31 address: usize,
32 mnemonic: udis::ud_mnemonic_code,
33 operands: Vec<udis::ud_operand>,
34 bytes: &'static [u8],
35}
36
37impl Instruction {
38 pub unsafe fn new(disasm: &mut Disassembler, address: *const ()) -> Option<Self> {
40 let instruction_bytes = udis::ud_disassemble(&mut disasm.0) as usize;
41 if instruction_bytes > 0 {
42 Some(Instruction {
43 address: address as usize,
44 mnemonic: udis::ud_insn_mnemonic(&disasm.0),
45 operands: disasm.0.operand.to_vec(),
46 bytes: slice::from_raw_parts(address as *const _, instruction_bytes),
47 })
48 } else {
49 None
50 }
51 }
52
53 pub fn address(&self) -> usize {
55 self.address
56 }
57
58 pub fn next_instruction_address(&self) -> usize {
60 self.address() + self.len()
61 }
62
63 pub fn relative_branch_displacement(&self) -> Option<isize> {
65 unsafe {
66 self
67 .operands
68 .iter()
69 .find(|op| op.otype == udis::ud_type::UD_OP_JIMM)
70 .map(|op| match op.size {
71 8 => op.lval.sbyte as isize,
72 32 => op.lval.sdword as isize,
73 _ => unreachable!("Operand size: {}", op.size),
74 })
75 }
76 }
77
78 pub fn rip_operand_displacement(&self) -> Option<isize> {
80 unsafe {
81 self
83 .operands
84 .iter()
85 .find(|op| op.otype == udis::ud_type::UD_OP_MEM && op.base == udis::ud_type::UD_R_RIP)
86 .map(|op| op.lval.sdword as isize)
87 }
88 }
89
90 pub fn is_loop(&self) -> bool {
92 matches!(
93 self.mnemonic,
94 udis::ud_mnemonic_code::UD_Iloop
95 | udis::ud_mnemonic_code::UD_Iloope
96 | udis::ud_mnemonic_code::UD_Iloopne
97 | udis::ud_mnemonic_code::UD_Ijecxz
98 | udis::ud_mnemonic_code::UD_Ijcxz
99 )
100 }
101
102 pub fn is_unconditional_jump(&self) -> bool {
104 self.mnemonic == udis::ud_mnemonic_code::UD_Ijmp
105 }
106
107 pub fn is_call(&self) -> bool {
109 self.mnemonic == udis::ud_mnemonic_code::UD_Icall
110 }
111
112 pub fn is_return(&self) -> bool {
114 self.mnemonic == udis::ud_mnemonic_code::UD_Iret
115 }
116
117 pub unsafe fn as_slice(&self) -> &[u8] {
119 self.bytes
120 }
121
122 pub fn len(&self) -> usize {
124 self.bytes.len()
125 }
126}