1use std::fmt::{self, Debug};
2
3pub use num_traits::FromPrimitive;
4pub use num_traits::ToPrimitive;
5
6use self::py27::Mnemonic;
7
8pub mod py27;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct Instruction<O: Opcode> {
12 pub opcode: O,
13 pub arg: Option<u16>,
14}
15
16#[macro_export]
17macro_rules! Instr {
18 ($opcode:expr) => {
19 ::pydis::opcode::Instruction {
20 opcode: $opcode,
21 arg: None,
22 }
23 };
24 ($opcode:expr, $arg:expr) => {
25 ::pydis::opcode::Instruction {
26 opcode: $opcode,
27 arg: Some($arg),
28 }
29 };
30}
31
32impl<O: Opcode + Debug> fmt::Display for Instruction<O> {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 write!(f, "{:?}", self.opcode)?;
35
36 if let Some(arg) = self.arg {
37 write!(f, " {}", arg)?;
38 }
39
40 Ok(())
41 }
42}
43
44impl<O: Opcode> Instruction<O> {
45 pub fn len(&self) -> usize {
47 std::mem::size_of::<u8>()
48 + if let Some(arg) = self.arg.as_ref() {
49 std::mem::size_of_val(arg)
50 } else {
51 0
52 }
53 }
54}
55
56impl<O: Opcode<Mnemonic = py27::Mnemonic>> Instruction<O> {
57 pub fn stack_adjustment_after(&self) -> isize {
61 match self.opcode.mnemonic() {
62 Mnemonic::STOP_CODE
64 | Mnemonic::NOP
65 | Mnemonic::ROT_TWO
66 | Mnemonic::ROT_THREE
67 | Mnemonic::ROT_FOUR => 0,
68
69 Mnemonic::POP_TOP => -1,
70 Mnemonic::DUP_TOP => 1,
71 Mnemonic::DUP_TOP_TWO => 2,
72 Mnemonic::UNARY_POSITIVE
74 | Mnemonic::UNARY_NEGATIVE
75 | Mnemonic::UNARY_NOT
76 | Mnemonic::UNARY_CONVERT
77 | Mnemonic::UNARY_INVERT
78 | Mnemonic::GET_ITER => 0,
79 Mnemonic::BINARY_POWER
81 | Mnemonic::BINARY_MULTIPLY
82 | Mnemonic::BINARY_DIVIDE
83 | Mnemonic::BINARY_FLOOR_DIVIDE
84 | Mnemonic::BINARY_TRUE_DIVIDE
85 | Mnemonic::BINARY_MODULO
86 | Mnemonic::BINARY_ADD
87 | Mnemonic::BINARY_SUBTRACT
88 | Mnemonic::BINARY_SUBSC
89 | Mnemonic::BINARY_LSHIFT
90 | Mnemonic::BINARY_RSHIFT
91 | Mnemonic::BINARY_AND
92 | Mnemonic::BINARY_XOR
93 | Mnemonic::BINARY_OR => -1,
94 Mnemonic::INPLACE_POWER
96 | Mnemonic::INPLACE_MULTIPLY
97 | Mnemonic::INPLACE_DIVIDE
98 | Mnemonic::INPLACE_FLOOR_DIVIDE
99 | Mnemonic::INPLACE_TRUE_DIVIDE
100 | Mnemonic::INPLACE_MODULO
101 | Mnemonic::INPLACE_ADD
102 | Mnemonic::INPLACE_SUBTRACT
103 | Mnemonic::INPLACE_LSHIFT
104 | Mnemonic::INPLACE_RSHIFT
105 | Mnemonic::INPLACE_AND
106 | Mnemonic::INPLACE_XOR
107 | Mnemonic::INPLACE_OR => -1,
108 Mnemonic::SLICE_0 => 0,
110 Mnemonic::SLICE_1 => -1,
111 Mnemonic::SLICE_2 => -2,
112 Mnemonic::SLICE_3 => -3,
113 Mnemonic::STORE_SLICE_0 => -1,
114 Mnemonic::STORE_SLICE_1 => -2,
115 Mnemonic::STORE_SLICE_2 => -3,
116 Mnemonic::STORE_SLICE_3 => -4,
117 Mnemonic::DELETE_SLICE_0 => -1,
118 Mnemonic::DELETE_SLICE_1 => -2,
119 Mnemonic::DELETE_SLICE_2 => -3,
120 Mnemonic::DELETE_SLICE_3 => -4,
121 Mnemonic::STORE_SUBSCR => -3,
122 Mnemonic::DELETE_SUBSCR => -2,
123 Mnemonic::PRINT_EXPR => -1,
125 Mnemonic::PRINT_ITEM => -1,
126 Mnemonic::PRINT_ITEM_TO => -2,
127 Mnemonic::PRINT_NEWLINE => 0,
128 Mnemonic::PRINT_NEWLINE_TO => -1,
129 Mnemonic::BREAK_LOOP => 0,
130 Mnemonic::CONTINUE_LOOP => 0,
131 Mnemonic::LIST_APPEND => -1,
132 Mnemonic::LOAD_LOCALS => 1,
133 Mnemonic::RETURN_VALUE => 0,
134 Mnemonic::YIELD_VALUE => 0,
135 Mnemonic::IMPORT_STAR => -1,
136 Mnemonic::EXEC_STMT => -3,
137 Mnemonic::POP_BLOCK => 0,
138 Mnemonic::END_FINALLY => 0,
139 Mnemonic::BUILD_CLASS => -3,
140 Mnemonic::SETUP_WITH => 1,
142 Mnemonic::WITH_CLEANUP => {
143 panic!("with_cleanup may require runtime info");
144 }
145 Mnemonic::STORE_NAME => -1,
146 Mnemonic::STORE_FAST => -1,
147 Mnemonic::STORE_DEREF => -1,
148 Mnemonic::SET_ADD => -1,
149 Mnemonic::MAP_ADD => -1,
150 Mnemonic::DELETE_NAME => 0,
151 Mnemonic::UNPACK_SEQUENCE => (self.arg.unwrap() as isize) - 1,
152 Mnemonic::DUP_TOPX => self.arg.unwrap() as isize,
153 Mnemonic::STORE_ATTR => -2,
154 Mnemonic::DELETE_ATTR => -1,
155 Mnemonic::STORE_GLOBAL => -1,
156 Mnemonic::DELETE_GLOBAL => 0,
157 Mnemonic::LOAD_CONST => 1,
158 Mnemonic::LOAD_NAME => 1,
159 Mnemonic::BUILD_TUPLE | Mnemonic::BUILD_LIST | Mnemonic::BUILD_SET => {
160 (self.arg.unwrap() as isize) - 1
161 }
162 Mnemonic::BUILD_MAP => 1,
163 Mnemonic::LOAD_ATTR => 0,
164 Mnemonic::COMPARE_OP => -1,
165 Mnemonic::IMPORT_NAME => -1,
166 Mnemonic::IMPORT_FROM => 1,
167 Mnemonic::JUMP_FORWARD | Mnemonic::JUMP_ABSOLUTE => 0,
168 Mnemonic::POP_JUMP_IF_FALSE | Mnemonic::POP_JUMP_IF_TRUE => -1,
169 Mnemonic::JUMP_IF_FALSE_OR_POP | Mnemonic::JUMP_IF_TRUE_OR_POP => {
170 panic!("JUMP_IF_*_OR_POP requires runtime info");
171 }
172 Mnemonic::FOR_ITER => 1,
173 Mnemonic::LOAD_GLOBAL => 1,
174 Mnemonic::SETUP_LOOP => 0,
175 Mnemonic::SETUP_EXCEPT | Mnemonic::SETUP_FINALLY => {
176 panic!("SETUP_EXCEPT requires runtime info");
177 }
178 Mnemonic::STORE_MAP => -2,
179 Mnemonic::LOAD_FAST => 1,
180 Mnemonic::DELETE_FAST => 0,
181 Mnemonic::LOAD_CLOSURE => 0,
182 Mnemonic::LOAD_DEREF => 1,
183 Mnemonic::RAISE_VARARGS => 0,
184 Mnemonic::CALL_FUNCTION => {
185 let pos_args = self.arg.unwrap() & 0xFF;
186 let kwargs = (self.arg.unwrap() >> 8) & 0xFF;
187 -(pos_args as isize + kwargs as isize + 1) + 1
189 }
190 Mnemonic::MAKE_FUNCTION => -1,
191 Mnemonic::MAKE_CLOSURE => 2 + self.arg.unwrap() as isize,
192 Mnemonic::BUILD_SLICE => 1 - (self.arg.unwrap() as isize),
193 Mnemonic::EXTENDED_ARG => panic!("not supported yet"),
194 Mnemonic::CALL_FUNCTION_VAR | Mnemonic::CALL_FUNCTION_KW => {
195 let pos_args = self.arg.unwrap() & 0xFF;
196 let kwargs = (self.arg.unwrap() >> 8) & 0xFF;
197 -(pos_args as isize + kwargs as isize + 2) + 1
199 }
200 Mnemonic::CALL_FUNCTION_VAR_KW => {
201 let pos_args = self.arg.unwrap() & 0xFF;
202 let kwargs = (self.arg.unwrap() >> 8) & 0xFF;
203 -(pos_args as isize + kwargs as isize + 3) + 1
205 }
206 }
207 }
208}
209
210pub trait Opcode: From<Self::Mnemonic> + Send + Sync + FromPrimitive + ToPrimitive + Copy + Clone + Debug {
213 type Mnemonic;
214
215 fn has_arg(&self) -> bool;
217
218 fn has_extended_arg(&self) -> bool;
220
221 fn has_const(&self) -> bool;
223
224 fn has_comp(&self) -> bool;
226
227 fn is_jump(&self) -> bool {
229 self.is_relative_jump() || self.is_absolute_jump()
230 }
231
232 fn is_other_conditional_jump(&self) -> bool;
233
234 fn is_relative_jump(&self) -> bool;
236
237 fn is_absolute_jump(&self) -> bool;
239
240 fn is_conditional_jump(&self) -> bool;
242
243 fn has_name(&self) -> bool;
245
246 fn has_local(&self) -> bool;
248
249 fn has_free(&self) -> bool;
251
252 fn mnemonic(&self) -> Self::Mnemonic;
253}