-
Notifications
You must be signed in to change notification settings - Fork 37
/
instruction.py
81 lines (66 loc) · 2.72 KB
/
instruction.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import dis
class Instruction:
"""
This class represents an instruction.
"""
def __init__(self, opcode, arg, size):
# Numeric code for operation, corresponding to the opcode values
self.opcode = opcode
# Numeric argument to operation(if any), otherwise None
self.arg = arg
# The size of the instruction including the arguement
self.size = size
# Resolved arg value (if known), otherwise same as arg
self.argval = arg
# Human readable name for operation
self.mnemonic = dis.opname[self.opcode]
def is_opcode_valid(self):
"""
Checks whether the instruction is legal. A legal instruction has an opcode
which is understood by the CPython VM.
"""
return self.opcode in dis.opmap.values()
def is_ret(self):
"""
Checks whether the instruction is a return
:return:
"""
return self.opcode == dis.opmap['RETURN_VALUE']
def is_control_flow(self):
"""
Checks whether the instruction cause change of control flow.
A control flow instruction can be conditional or unconditional
:return:
"""
# All control flow instructions
cfIns = (
'JUMP_IF_FALSE_OR_POP', 'JUMP_IF_TRUE_OR_POP', 'JUMP_ABSOLUTE', 'POP_JUMP_IF_FALSE', 'POP_JUMP_IF_TRUE',
'CONTINUE_LOOP', 'FOR_ITER', 'JUMP_FORWARD')
return self.mnemonic in cfIns
def is_conditional(self):
"""
Checks whether the instruction is a conditional control flow instruction.
A conditional control flow instruction has two possible successor instructions.
"""
conditionalIns = (
'JUMP_IF_FALSE_OR_POP', 'JUMP_IF_TRUE_OR_POP', 'POP_JUMP_IF_FALSE', 'POP_JUMP_IF_TRUE', 'FOR_ITER')
return self.is_control_flow() and self.mnemonic in conditionalIns
def is_unconditional(self):
"""
Checks whether the instruction is a conditional control flow instruction.
A conditional control flow instruction has two possible successor instructions.
"""
unconditionalIns = ('JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP')
return self.is_control_flow() and self.mnemonic in unconditionalIns
def has_xref(self):
"""
Checks whether the instruction has xreferences.
"""
return self.mnemonic in ('SETUP_LOOP', 'SETUP_EXCEPT', 'SETUP_FINALLY', 'SETUP_WITH')
def assemble(self):
if self.size == 1:
return chr(self.opcode)
else:
return chr(self.opcode) + chr(self.arg & 0xFF) + chr((self.arg >> 8) & 0xFF)
def __str__(self):
return '{} {} {}'.format(self.opcode, self.mnemonic, self.arg)