Miasm2
 All Classes Namespaces Files Functions Variables Typedefs Properties Macros
jitcore_python.py
Go to the documentation of this file.
1 import miasm2.jitter.jitcore as jitcore
2 import miasm2.expression.expression as m2_expr
3 import miasm2.jitter.csts as csts
4 from miasm2.expression.simplifications import expr_simp
5 from miasm2.ir.symbexec import symbexec
6 
7 
8 ################################################################################
9 # Util methods for Python jitter #
10 ################################################################################
11 
12 def update_cpu_from_engine(cpu, exec_engine):
13  """Updates @cpu instance according to new CPU values
14  @cpu: JitCpu instance
15  @exec_engine: symbexec instance"""
16 
17  for symbol in exec_engine.symbols:
18  if isinstance(symbol, m2_expr.ExprId):
19  if hasattr(cpu, symbol.name):
20  value = exec_engine.symbols.symbols_id[symbol]
21  if not isinstance(value, m2_expr.ExprInt):
22  raise ValueError("A simplification is missing: %s" % value)
23 
24  setattr(cpu, symbol.name, value.arg.arg)
25  else:
26  raise NotImplementedError("Type not handled: %s" % symbol)
27 
28 
29 def update_engine_from_cpu(cpu, exec_engine):
30  """Updates CPU values according to @cpu instance
31  @cpu: JitCpu instance
32  @exec_engine: symbexec instance"""
33 
34  for symbol in exec_engine.symbols:
35  if isinstance(symbol, m2_expr.ExprId):
36  if hasattr(cpu, symbol.name):
37  value = m2_expr.ExprInt(getattr(cpu, symbol.name),
38  symbol.size)
39  exec_engine.symbols.symbols_id[symbol] = value
40  else:
41  raise NotImplementedError("Type not handled: %s" % symbol)
42 
43 
44 ################################################################################
45 # Python jitter Core #
46 ################################################################################
47 
48 
50  "JiT management, using Miasm2 Symbol Execution engine as backend"
51 
52  def __init__(self, ir_arch, bs=None):
53  super(JitCore_Python, self).__init__(ir_arch, bs)
54  self.symbexec = None
55  self.ir_arch = ir_arch
56 
57  def load(self):
58  "Preload symbols according to current architecture"
59 
60  symbols_init = {}
61  for r in self.ir_arch.arch.regs.all_regs_ids_no_alias:
62  symbols_init[r] = self.ir_arch.arch.regs.regs_init[r]
63 
64  self.symbexec = symbexec(self.ir_arch, symbols_init,
65  func_read = self.func_read,
66  func_write = self.func_write)
67 
68  def func_read(self, expr_mem):
69  """Memory read wrapper for symbolic execution
70  @expr_mem: ExprMem"""
71 
72  addr = expr_mem.arg.arg.arg
73  size = expr_mem.size / 8
74  value = self.cpu.get_mem(addr, size)
75 
76  return m2_expr.ExprInt(int(value[::-1].encode("hex"), 16),
77  expr_mem.size)
78 
79  def func_write(self, symb_exec, dest, data, mem_cache):
80  """Memory read wrapper for symbolic execution
81  @symb_exec: symbexec instance
82  @dest: ExprMem instance
83  @data: Expr instance
84  @mem_cache: dict"""
85 
86  # Get the content to write
87  data = expr_simp(data)
88  if not isinstance(data, m2_expr.ExprInt):
89  raise NotImplementedError("A simplification is missing: %s" % data)
90  to_write = data.arg.arg
91 
92  # Format information
93  addr = dest.arg.arg.arg
94  size = data.size / 8
95  content = hex(to_write).replace("0x", "").replace("L", "")
96  content = "0" * (size * 2 - len(content)) + content
97  content = content.decode("hex")[::-1]
98 
99  # Write in VmMngr context
100  self.cpu.set_mem(addr, content)
101 
102  def jitirblocs(self, label, irblocs):
103  """Create a python function corresponding to an irblocs' group.
104  @label: the label of the irblocs
105  @irblocs: a gorup of irblocs
106  """
107 
108  def myfunc(cpu, vmmngr):
109  """Execute the function according to cpu and vmmngr states
110  @cpu: JitCpu instance
111  @vm: VmMngr instance
112  """
113 
114  # Keep current location in irblocs
115  cur_label = label
116  loop = True
117 
118  # Required to detect new instructions
119  offsets_jitted = set()
120 
121  # Get exec engine
122  exec_engine = self.symbexec
123 
124  # For each irbloc inside irblocs
125  while loop is True:
126 
127  # Get the current bloc
128  loop = False
129  for irb in irblocs:
130  if irb.label == cur_label:
131  loop = True
132  break
133 
134  # Irblocs must end with returning an ExprInt instance
135  assert(loop is not False)
136 
137  # Refresh CPU values according to @cpu instance
138  update_engine_from_cpu(cpu, exec_engine)
139 
140  # Execute current ir bloc
141  for ir, line in zip(irb.irs, irb.lines):
142 
143  # For each new instruction (in assembly)
144  if line.offset not in offsets_jitted:
145  offsets_jitted.add(line.offset)
146 
147  # Log registers values
148  if self.log_regs:
149  update_cpu_from_engine(cpu, exec_engine)
150  cpu.dump_gpregs()
151 
152  # Log instruction
153  if self.log_mn:
154  print "%08x %s" % (line.offset, line)
155 
156  # Check for memory exception
157  if (vmmngr.get_exception() != 0):
158  update_cpu_from_engine(cpu, exec_engine)
159  return line.offset
160 
161  # Eval current instruction (in IR)
162  exec_engine.eval_ir(ir)
163 
164  # Check for memory exception which do not update PC
165  if (vmmngr.get_exception() & csts.EXCEPT_DO_NOT_UPDATE_PC != 0):
166  update_cpu_from_engine(cpu, exec_engine)
167  return line.offset
168 
169  # Get next bloc address
170  ad = expr_simp(exec_engine.eval_expr(self.ir_arch.IRDst))
171 
172  # Updates @cpu instance according to new CPU values
173  update_cpu_from_engine(cpu, exec_engine)
174 
175  # Manage resulting address
176  if isinstance(ad, m2_expr.ExprInt):
177  return ad.arg.arg
178  elif isinstance(ad, m2_expr.ExprId):
179  cur_label = ad.name
180  else:
181  raise NotImplementedError("Type not handled: %s" % ad)
182 
183  # Associate myfunc with current label
184  self.lbl2jitbloc[label.offset] = myfunc
185 
186  def jit_call(self, label, cpu, vmmngr, _breakpoints):
187  """Call the function label with cpu and vmmngr states
188  @label: function's label
189  @cpu: JitCpu instance
190  @vm: VmMngr instance
191  """
192 
193  # Get Python function corresponding to @label
194  fc_ptr = self.lbl2jitbloc[label]
195 
196  self.cpu = cpu
197 
198  # Execute the function
199  return fc_ptr(cpu, vmmngr)
def update_cpu_from_engine
Util methods for Python jitter #.