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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
import miasm2.jitter.jitcore as jitcore
import miasm2.expression.expression as m2_expr
import miasm2.jitter.csts as csts
from miasm2.expression.simplifications import ExpressionSimplifier
from miasm2.jitter.emulatedsymbexec import EmulatedSymbExec
################################################################################
# Python jitter Core #
################################################################################
class JitCore_Python(jitcore.JitCore):
"JiT management, using Miasm2 Symbol Execution engine as backend"
SymbExecClass = EmulatedSymbExec
def __init__(self, ir_arch, bs=None):
super(JitCore_Python, self).__init__(ir_arch, bs)
self.ir_arch = ir_arch
# CPU & VM (None for now) will be set later
expr_simp = ExpressionSimplifier()
expr_simp.enable_passes(ExpressionSimplifier.PASS_COMMONS)
self.symbexec = self.SymbExecClass(None, None, self.ir_arch, {},
sb_expr_simp=expr_simp)
self.symbexec.enable_emulated_simplifications()
def set_cpu_vm(self, cpu, vm):
self.symbexec.cpu = cpu
self.symbexec.vm = vm
def load(self):
"Preload symbols according to current architecture"
self.symbexec.reset_regs()
def jitirblocs(self, loc_key, irblocks):
"""Create a python function corresponding to an irblocks' group.
@loc_key: the loc_key of the irblocks
@irblocks: a gorup of irblocks
"""
def myfunc(cpu):
"""Execute the function according to cpu and vmmngr states
@cpu: JitCpu instance
"""
# Get virtual memory handler
vmmngr = cpu.vmmngr
# Keep current location in irblocks
cur_loc_key = loc_key
# Required to detect new instructions
offsets_jitted = set()
# Get exec engine
exec_engine = self.symbexec
expr_simp = exec_engine.expr_simp
known_loc_keys = set(irb.loc_key for irb in irblocks)
# For each irbloc inside irblocks
while True:
# Get the current bloc
for irb in irblocks:
if irb.loc_key == cur_loc_key:
break
else:
raise RuntimeError("Irblocks must end with returning an "
"ExprInt instance")
# Refresh CPU values according to @cpu instance
exec_engine.update_engine_from_cpu()
# Execute current ir bloc
for assignblk in irb:
instr = assignblk.instr
# For each new instruction (in assembly)
if instr is not None and instr.offset not in offsets_jitted:
# Test exceptions
vmmngr.check_invalid_code_blocs()
vmmngr.check_memory_breakpoint()
if vmmngr.get_exception():
exec_engine.update_cpu_from_engine()
return instr.offset
offsets_jitted.add(instr.offset)
# Log registers values
if self.log_regs:
exec_engine.update_cpu_from_engine()
exec_engine.cpu.dump_gpregs()
# Log instruction
if self.log_mn:
print "%08x %s" % (instr.offset, instr)
# Check for exception
if (vmmngr.get_exception() != 0 or
cpu.get_exception() != 0):
exec_engine.update_cpu_from_engine()
return instr.offset
# Eval current instruction (in IR)
exec_engine.eval_updt_assignblk(assignblk)
# Check for exceptions which do not update PC
exec_engine.update_cpu_from_engine()
if (vmmngr.get_exception() & csts.EXCEPT_DO_NOT_UPDATE_PC != 0 or
cpu.get_exception() > csts.EXCEPT_NUM_UPDT_EIP):
return instr.offset
vmmngr.check_invalid_code_blocs()
vmmngr.check_memory_breakpoint()
# Get next bloc address
ad = expr_simp(exec_engine.eval_expr(self.ir_arch.IRDst))
# Updates @cpu instance according to new CPU values
exec_engine.update_cpu_from_engine()
# Manage resulting address
if isinstance(ad, m2_expr.ExprInt):
return ad.arg.arg
elif isinstance(ad, m2_expr.ExprLoc):
cur_loc_key = ad.loc_key
else:
raise NotImplementedError("Type not handled: %s" % ad)
# Associate myfunc with current loc_key
offset = self.ir_arch.symbol_pool.loc_key_to_offset(loc_key)
assert offset is not None
self.loc_key_to_jit_block[offset] = myfunc
def exec_wrapper(self, loc_key, cpu, _loc_key_to_jit_block, _breakpoints,
_max_exec_per_call):
"""Call the function @loc_key with @cpu
@loc_key: function's loc_key
@cpu: JitCpu instance
"""
# Get Python function corresponding to @loc_key
fc_ptr = self.loc_key_to_jit_block[loc_key]
# Execute the function
return fc_ptr(cpu)
|