Miasm2
 All Classes Namespaces Files Functions Variables Typedefs Properties Macros
sem.py
Go to the documentation of this file.
1 import miasm2.expression.expression as m2_expr
2 from miasm2.ir.ir import ir, irbloc
3 from miasm2.arch.mips32.arch import mn_mips32
4 from miasm2.arch.mips32.regs import R_LO, R_HI, PC, RA
5 from miasm2.core.sembuilder import SemBuilder
6 
7 
8 # SemBuilder context
9 ctx = {"R_LO": R_LO,
10  "R_HI": R_HI,
11  "PC": PC,
12  "RA": RA}
13 sbuild = SemBuilder(ctx)
14 
15 
16 @sbuild.parse
17 def addiu(arg1, arg2, arg3):
18  """Adds a register @arg3 and a sign-extended immediate value @arg2 and
19  stores the result in a register @arg1"""
20  arg1 = arg2 + arg3
21 
22 @sbuild.parse
23 def lw(arg1, arg2):
24  "A word is loaded into a register @arg1 from the specified address @arg2."
25  arg1 = arg2
26 
27 @sbuild.parse
28 def sw(arg1, arg2):
29  "The contents of @arg2 is stored at the specified address @arg1."
30  arg2 = arg1
31 
32 @sbuild.parse
33 def jal(arg1):
34  "Jumps to the calculated address @arg1 and stores the return address in $RA"
35  PC = arg1
36  ir.IRDst = arg1
37  RA = ExprId(ir.get_next_break_label(instr))
38 
39 @sbuild.parse
40 def jalr(arg1, arg2):
41  """Jump to an address stored in a register @arg1, and store the return
42  address in another register @arg2"""
43  PC = arg1
44  ir.IRDst = arg1
45  arg2 = ExprId(ir.get_next_break_label(instr))
46 
47 @sbuild.parse
48 def bal(arg1):
49  PC = arg1
50  ir.IRDst = arg1
51  RA = ExprId(ir.get_next_break_label(instr))
52 
53 @sbuild.parse
54 def l_b(arg1):
55  PC = arg1
56  ir.IRDst = arg1
57 
58 @sbuild.parse
59 def lbu(arg1, arg2):
60  """A byte is loaded (unsigned extended) into a register @arg1 from the
61  specified address @arg2."""
62  arg1 = mem8[arg2.arg].zeroExtend(32)
63 
64 @sbuild.parse
65 def lhu(arg1, arg2):
66  """A word is loaded (unsigned extended) into a register @arg1 from the
67  specified address @arg2."""
68  arg1 = mem16[arg2.arg].zeroExtend(32)
69 
70 @sbuild.parse
71 def lb(arg1, arg2):
72  "A byte is loaded into a register @arg1 from the specified address @arg2."
73  arg1 = mem8[arg2.arg].signExtend(32)
74 
75 @sbuild.parse
76 def beq(arg1, arg2, arg3):
77  "Branches on @arg3 if the quantities of two registers @arg1, @arg2 are eq"
78  dst = ExprId(ir.get_next_break_label(instr)) if arg1 - arg2 else arg3
79  PC = dst
80  ir.IRDst = dst
81 
82 @sbuild.parse
83 def bgez(arg1, arg2):
84  """Branches on @arg2 if the quantities of register @arg1 is greater than or
85  equal to zero"""
86  dst = ExprId(ir.get_next_break_label(instr)) if arg1.msb() else arg2
87  PC = dst
88  ir.IRDst = dst
89 
90 @sbuild.parse
91 def bne(arg1, arg2, arg3):
92  """Branches on @arg3 if the quantities of two registers @arg1, @arg2 are NOT
93  equal"""
94  dst = arg3 if arg1 - arg2 else ExprId(ir.get_next_break_label(instr))
95  PC = dst
96  ir.IRDst = dst
97 
98 @sbuild.parse
99 def lui(arg1, arg2):
100  """The immediate value @arg2 is shifted left 16 bits and stored in the
101  register @arg1. The lower 16 bits are zeroes."""
102  arg1 = ExprCompose([(i16(0), 0, 16), (arg2[:16], 16, 32)])
103 
104 @sbuild.parse
105 def nop():
106  """Do nothing"""
107 
108 @sbuild.parse
109 def j(arg1):
110  """Jump to an address @arg1"""
111  PC = arg1
112  ir.IRDst = arg1
113 
114 @sbuild.parse
115 def l_or(arg1, arg2, arg3):
116  """Bitwise logical ors two registers @arg2, @arg3 and stores the result in a
117  register @arg1"""
118  arg1 = arg2 | arg3
119 
120 @sbuild.parse
121 def nor(arg1, arg2, arg3):
122  """Bitwise logical Nors two registers @arg2, @arg3 and stores the result in
123  a register @arg1"""
124  arg1 = (arg2 | arg3) ^ i32(-1)
125 
126 @sbuild.parse
127 def l_and(arg1, arg2, arg3):
128  """Bitwise logical ands two registers @arg2, @arg3 and stores the result in
129  a register @arg1"""
130  arg1 = arg2 & arg3
131 
132 @sbuild.parse
133 def ext(arg1, arg2, arg3, arg4):
134  pos = int(arg3.arg)
135  size = int(arg4.arg)
136  arg1 = arg2[pos:pos + size].zeroExtend(32)
137 
138 @sbuild.parse
139 def mul(arg1, arg2, arg3):
140  """Multiplies @arg2 by $arg3 and stores the result in @arg1."""
141  arg1 = 'imul'(arg2, arg3)
142 
143 @sbuild.parse
144 def sltu(arg1, arg2, arg3):
145  """If @arg3 is less than @arg2 (unsigned), @arg1 is set to one. It gets zero
146  otherwise."""
147  arg1 = (((arg2 - arg3) ^ ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))) ^ arg2 ^ arg3).msb().zeroExtend(32)
148 
149 @sbuild.parse
150 def slt(arg1, arg2, arg3):
151  """If @arg3 is less than @arg2 (signed), @arg1 is set to one. It gets zero
152  otherwise."""
153  arg1 = ((arg2 - arg3) ^ ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))).msb().zeroExtend(32)
154 
155 @sbuild.parse
156 def l_sub(arg1, arg2, arg3):
157  arg1 = arg2 - arg3
158 
159 @sbuild.parse
160 def sb(arg1, arg2):
161  """The least significant byte of @arg1 is stored at the specified address
162  @arg2."""
163  mem8[arg2.arg] = arg1[:8]
164 
165 @sbuild.parse
166 def sh(arg1, arg2):
167  mem16[arg2.arg] = arg1[:16]
168 
169 @sbuild.parse
170 def movn(arg1, arg2, arg3):
171  if arg3:
172  arg1 = arg2
173 
174 @sbuild.parse
175 def movz(arg1, arg2, arg3):
176  if not arg3:
177  arg1 = arg2
178 
179 @sbuild.parse
180 def srl(arg1, arg2, arg3):
181  """Shifts arg1 register value @arg2 right by the shift amount @arg3 and
182  places the value in the destination register @arg1.
183  Zeroes are shifted in."""
184  arg1 = arg2 >> arg3
185 
186 @sbuild.parse
187 def sra(arg1, arg2, arg3):
188  """Shifts arg1 register value @arg2 right by the shift amount @arg3 and
189  places the value in the destination register @arg1. The sign bit is shifted
190  in."""
191  arg1 = 'a>>'(arg2, arg3)
192 
193 @sbuild.parse
194 def srav(arg1, arg2, arg3):
195  arg1 = 'a>>'(arg2, arg3 & i32(0x1F))
196 
197 @sbuild.parse
198 def sll(arg1, arg2, arg3):
199  arg1 = arg2 << arg3
200 
201 @sbuild.parse
202 def srlv(arg1, arg2, arg3):
203  """Shifts a register value @arg2 right by the amount specified in @arg3 and
204  places the value in the destination register @arg1.
205  Zeroes are shifted in."""
206  arg1 = arg2 >> (arg3 & i32(0x1F))
207 
208 @sbuild.parse
209 def sllv(arg1, arg2, arg3):
210  """Shifts a register value @arg2 left by the amount specified in @arg3 and
211  places the value in the destination register @arg1.
212  Zeroes are shifted in."""
213  arg1 = arg2 << (arg3 & i32(0x1F))
214 
215 @sbuild.parse
216 def l_xor(arg1, arg2, arg3):
217  """Exclusive ors two registers @arg2, @arg3 and stores the result in a
218  register @arg3"""
219  arg1 = arg2 ^ arg3
220 
221 @sbuild.parse
222 def seb(arg1, arg2):
223  arg1 = arg2[:8].signExtend(32)
224 
225 @sbuild.parse
226 def seh(arg1, arg2):
227  arg1 = arg2[:16].signExtend(32)
228 
229 @sbuild.parse
230 def bltz(arg1, arg2):
231  """Branches on @arg2 if the register @arg1 is less than zero"""
232  dst_o = arg2 if arg1.msb() else ExprId(ir.get_next_break_label(instr))
233  PC = dst_o
234  ir.IRDst = dst_o
235 
236 @sbuild.parse
237 def blez(arg1, arg2):
238  """Branches on @arg2 if the register @arg1 is less than or equal to zero"""
239  cond = (i1(1) if arg1 else i1(0)) | arg1.msb()
240  dst_o = arg2 if cond else ExprId(ir.get_next_break_label(instr))
241  PC = dst_o
242  ir.IRDst = dst_o
243 
244 @sbuild.parse
245 def bgtz(arg1, arg2):
246  """Branches on @arg2 if the register @arg1 is greater than zero"""
247  cond = (i1(1) if arg1 else i1(0)) | arg1.msb()
248  dst_o = ExprId(ir.get_next_break_label(instr)) if cond else arg2
249  PC = dst_o
250  ir.IRDst = dst_o
251 
252 @sbuild.parse
253 def wsbh(arg1, arg2):
254  arg1 = ExprCompose([(arg2[8:16], 0, 8),
255  (arg2[0:8] , 8, 16),
256  (arg2[24:32], 16, 24),
257  (arg2[16:24], 24, 32)])
258 
259 @sbuild.parse
260 def rotr(arg1, arg2, arg3):
261  arg1 = '>>>'(arg2, arg3)
262 
263 @sbuild.parse
264 def add_d(arg1, arg2, arg3):
265  # XXX TODO check
266  arg1 = 'fadd'(arg2, arg3)
267 
268 @sbuild.parse
269 def sub_d(arg1, arg2, arg3):
270  # XXX TODO check
271  arg1 = 'fsub'(arg2, arg3)
272 
273 @sbuild.parse
274 def div_d(arg1, arg2, arg3):
275  # XXX TODO check
276  arg1 = 'fdiv'(arg2, arg3)
277 
278 @sbuild.parse
279 def mul_d(arg1, arg2, arg3):
280  # XXX TODO check
281  arg1 = 'fmul'(arg2, arg3)
282 
283 @sbuild.parse
284 def mov_d(arg1, arg2):
285  # XXX TODO check
286  arg1 = arg2
287 
288 @sbuild.parse
289 def mfc0(arg1, arg2):
290  arg1 = arg2
291 
292 @sbuild.parse
293 def mfc1(arg1, arg2):
294  arg1 = arg2
295 
296 @sbuild.parse
297 def mtc0(arg1, arg2):
298  arg2 = arg1
299 
300 @sbuild.parse
301 def mtc1(arg1, arg2):
302  arg2 = arg1
303 
304 @sbuild.parse
305 def tlbwi():
306  "TODO XXX"
307 
308 @sbuild.parse
309 def tlbp():
310  "TODO XXX"
311 
312 def ins(ir, instr, a, b, c, d):
313  e = []
314  pos = int(c.arg)
315  l = int(d.arg)
316 
317  my_slices = []
318  if pos != 0:
319  my_slices.append((a[:pos], 0, pos))
320  if l != 0:
321  my_slices.append((b[:l], pos, pos+l))
322  if pos + l != 32:
323  my_slices.append((a[pos+l:], pos+l, 32))
324  r = m2_expr.ExprCompose(my_slices)
325  e.append(m2_expr.ExprAff(a, r))
326  return e, []
327 
328 
329 @sbuild.parse
330 def lwc1(arg1, arg2):
331  arg1 = ('mem_%.2d_to_single' % arg2.size)(arg2)
332 
333 @sbuild.parse
334 def swc1(arg1, arg2):
335  arg2 = ('single_to_mem_%.2d' % arg1.size)(arg1)
336 
337 @sbuild.parse
338 def c_lt_d(arg1, arg2, arg3):
339  arg1 = 'fcomp_lt'(arg2, arg3)
340 
341 @sbuild.parse
342 def c_eq_d(arg1, arg2, arg3):
343  arg1 = 'fcomp_eq'(arg2, arg3)
344 
345 @sbuild.parse
346 def c_le_d(arg1, arg2, arg3):
347  arg1 = 'fcomp_le'(arg2, arg3)
348 
349 @sbuild.parse
350 def bc1t(arg1, arg2):
351  dst_o = arg2 if arg1 else ExprId(ir.get_next_break_label(instr))
352  PC = dst_o
353  ir.IRDst = dst_o
354 
355 @sbuild.parse
356 def bc1f(arg1, arg2):
357  dst_o = ExprId(ir.get_next_break_label(instr)) if arg1 else arg2
358  PC = dst_o
359  ir.IRDst = dst_o
360 
361 @sbuild.parse
362 def cvt_d_w(arg1, arg2):
363  # TODO XXX
364  arg1 = 'flt_d_w'(arg2)
365 
366 @sbuild.parse
367 def mult(arg1, arg2):
368  """Multiplies (signed) @arg1 by @arg2 and stores the result in $R_HI:$R_LO"""
369  size = arg1.size
370  result = arg1.signExtend(size * 2) * arg2.signExtend(size * 2)
371  R_LO = result[:32]
372  R_HI = result[32:]
373 
374 @sbuild.parse
375 def multu(arg1, arg2):
376  """Multiplies (unsigned) @arg1 by @arg2 and stores the result in $R_HI:$R_LO"""
377  size = arg1.size
378  result = arg1.zeroExtend(size * 2) * arg2.zeroExtend(size * 2)
379  R_LO = result[:32]
380  R_HI = result[32:]
381 
382 @sbuild.parse
383 def mfhi(arg1):
384  "The contents of register $R_HI are moved to the specified register @arg1."
385  arg1 = R_HI
386 
387 @sbuild.parse
388 def mflo(arg1):
389  "The contents of register R_LO are moved to the specified register @arg1."
390  arg1 = R_LO
391 
392 @sbuild.parse
393 def di(arg1):
394  "NOP"
395 
396 @sbuild.parse
397 def ei(arg1):
398  "NOP"
399 
400 @sbuild.parse
401 def ehb(arg1):
402  "NOP"
403 
404 mnemo_func = sbuild.functions
405 mnemo_func.update({
406  'add.d': add_d,
407  'addu': addiu,
408  'and': l_and,
409  'andi': l_and,
410  'b': l_b,
411  'c.eq.d': c_eq_d,
412  'c.le.d': c_le_d,
413  'c.lt.d': c_lt_d,
414  'cvt.d.w': cvt_d_w,
415  'div.d': div_d,
416  'ins': ins,
417  'jr': j,
418  'mov.d': mov_d,
419  'mul.d': mul_d,
420  'or': l_or,
421  'ori': l_or,
422  'slti': slt,
423  'sltiu': sltu,
424  'sub.d': sub_d,
425  'subu': l_sub,
426  'xor': l_xor,
427  'xori': l_xor,
428 })
429 
430 def get_mnemo_expr(ir, instr, *args):
431  instr, extra_ir = mnemo_func[instr.name.lower()](ir, instr, *args)
432  return instr, extra_ir
433 
434 class ir_mips32l(ir):
435 
436  def __init__(self, symbol_pool=None):
437  ir.__init__(self, mn_mips32, 'l', symbol_pool)
438  self.pc = mn_mips32.getpc()
439  self.sp = mn_mips32.getsp()
440  self.IRDst = m2_expr.ExprId('IRDst', 32)
441 
442  def get_ir(self, instr):
443  args = instr.args
444  instr_ir, extra_ir = get_mnemo_expr(self, instr, *args)
445 
446  for i, x in enumerate(instr_ir):
447  x = m2_expr.ExprAff(x.dst, x.src.replace_expr(
448  {self.pc: m2_expr.ExprInt32(instr.offset + 4)}))
449  instr_ir[i] = x
450  for b in extra_ir:
451  for irs in b.irs:
452  for i, x in enumerate(irs):
453  x = m2_expr.ExprAff(x.dst, x.src.replace_expr(
454  {self.pc: m2_expr.ExprInt32(instr.offset + 4)}))
455  irs[i] = x
456  return instr_ir, extra_ir
457 
458  def get_next_instr(self, instr):
459  l = self.symbol_pool.getby_offset_create(instr.offset + 4)
460  return l
461 
462  def get_next_break_label(self, instr):
463  l = self.symbol_pool.getby_offset_create(instr.offset + 8)
464  return l
465  """
466  def add_bloc(self, bloc, gen_pc_updt = False):
467  c = None
468  ir_blocs_all = []
469  for l in bloc.lines:
470  if c is None:
471  # print 'new c'
472  label = self.get_label(l)
473  c = irbloc(label, [], [])
474  ir_blocs_all.append(c)
475  bloc_dst = None
476  # print 'Translate', l
477  dst, ir_bloc_cur, ir_blocs_extra = self.instr2ir(l)
478  # print ir_bloc_cur
479  # for xxx in ir_bloc_cur:
480  # print "\t", xxx
481  assert((dst is None) or (bloc_dst is None))
482  bloc_dst = dst
483  #if bloc_dst is not None:
484  # c.dst = bloc_dst
485  if dst is not None:
486  ir_bloc_cur.append(m2_expr.ExprAff(PC_FETCH, dst))
487  c.dst = PC_FETCH
488  if gen_pc_updt is not False:
489  self.gen_pc_update(c, l)
490 
491  c.irs.append(ir_bloc_cur)
492  c.lines.append(l)
493  if ir_blocs_extra:
494  # print 'split'
495  for b in ir_blocs_extra:
496  b.lines = [l] * len(b.irs)
497  ir_blocs_all += ir_blocs_extra
498  c = None
499  self.post_add_bloc(bloc, ir_blocs_all)
500  return ir_blocs_all
501  """
502 
504  def __init__(self, symbol_pool=None):
505  ir.__init__(self, mn_mips32, 'b', symbol_pool)
506  self.pc = mn_mips32.getpc()
507  self.sp = mn_mips32.getsp()
508  self.IRDst = m2_expr.ExprId('IRDst', 32)