diff options
| -rw-r--r-- | miasm2/arch/mips32/sem.py | 705 | ||||
| -rw-r--r-- | miasm2/core/sembuilder.py | 206 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_arm.c | 2 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_mips32.c | 2 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_msp430.c | 2 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_x86.c | 2 | ||||
| -rw-r--r-- | test/core/sembuilder.py | 37 |
7 files changed, 495 insertions, 461 deletions
diff --git a/miasm2/arch/mips32/sem.py b/miasm2/arch/mips32/sem.py index 0d62cc58..7eb9dcae 100644 --- a/miasm2/arch/mips32/sem.py +++ b/miasm2/arch/mips32/sem.py @@ -10,356 +10,304 @@ ctx = {"R_LO": R_LO, "R_HI": R_HI, "PC": PC, "RA": RA} -ctx.update(m2_expr.__dict__) sbuild = SemBuilder(ctx) @sbuild.parse -def addiu(Arg1, Arg2, Arg3): - """Adds a register @Arg3 and a sign-extended immediate value @Arg2 and - stores the result in a register @Arg1""" - Arg1 = Arg2 + Arg3 +def addiu(arg1, arg2, arg3): + """Adds a register @arg3 and a sign-extended immediate value @arg2 and + stores the result in a register @arg1""" + arg1 = arg2 + arg3 @sbuild.parse -def lw(Arg1, Arg2): - "A word is loaded into a register @Arg1 from the specified address @Arg2." - Arg1 = Arg2 +def lw(arg1, arg2): + "A word is loaded into a register @arg1 from the specified address @arg2." + arg1 = arg2 @sbuild.parse -def sw(Arg1, Arg2): - "The contents of @Arg2 is stored at the specified address @Arg1." - Arg2 = Arg1 +def sw(arg1, arg2): + "The contents of @arg2 is stored at the specified address @arg1." + arg2 = arg1 @sbuild.parse -def jal(Arg1): - "Jumps to the calculated address @Arg1 and stores the return address in $RA" - PC = Arg1 - ir.IRDst = Arg1 +def jal(arg1): + "Jumps to the calculated address @arg1 and stores the return address in $RA" + PC = arg1 + ir.IRDst = arg1 RA = ExprId(ir.get_next_break_label(instr)) @sbuild.parse -def jalr(Arg1, Arg2): - """Jump to an address stored in a register @Arg1, and store the return - address in another register @Arg2""" - PC = Arg1 - ir.IRDst = Arg1 - Arg2 = ExprId(ir.get_next_break_label(instr)) +def jalr(arg1, arg2): + """Jump to an address stored in a register @arg1, and store the return + address in another register @arg2""" + PC = arg1 + ir.IRDst = arg1 + arg2 = ExprId(ir.get_next_break_label(instr)) @sbuild.parse -def bal(Arg1): - PC = Arg1 - ir.IRDst = Arg1 +def bal(arg1): + PC = arg1 + ir.IRDst = arg1 RA = ExprId(ir.get_next_break_label(instr)) @sbuild.parse -def l_b(Arg1): - PC = Arg1 - ir.IRDst = Arg1 +def l_b(arg1): + PC = arg1 + ir.IRDst = arg1 @sbuild.parse -def lbu(Arg1, Arg2): - """A byte is loaded (unsigned extended) into a register @Arg1 from the - specified address @Arg2.""" - Arg1 = mem8[Arg2.arg].zeroExtend(32) +def lbu(arg1, arg2): + """A byte is loaded (unsigned extended) into a register @arg1 from the + specified address @arg2.""" + arg1 = mem8[arg2.arg].zeroExtend(32) @sbuild.parse -def lhu(Arg1, Arg2): - """A word is loaded (unsigned extended) into a register @Arg1 from the - specified address @Arg2.""" - Arg1 = mem16[Arg2.arg].zeroExtend(32) +def lhu(arg1, arg2): + """A word is loaded (unsigned extended) into a register @arg1 from the + specified address @arg2.""" + arg1 = mem16[arg2.arg].zeroExtend(32) @sbuild.parse -def lb(Arg1, Arg2): - "A byte is loaded into a register @Arg1 from the specified address @Arg2." - Arg1 = mem8[Arg2.arg].signExtend(32) +def lb(arg1, arg2): + "A byte is loaded into a register @arg1 from the specified address @arg2." + arg1 = mem8[arg2.arg].signExtend(32) @sbuild.parse -def beq(Arg1, Arg2, Arg3): - "Branches on @Arg3 if the quantities of two registers @Arg1, @Arg2 are eq" - dst = ExprId(ir.get_next_break_label(instr)) if Arg1 - Arg2 else Arg3 +def beq(arg1, arg2, arg3): + "Branches on @arg3 if the quantities of two registers @arg1, @arg2 are eq" + dst = ExprId(ir.get_next_break_label(instr)) if arg1 - arg2 else arg3 PC = dst ir.IRDst = dst @sbuild.parse -def bgez(Arg1, Arg2): - """Branches on @Arg2 if the quantities of register @Arg1 is greater than or +def bgez(arg1, arg2): + """Branches on @arg2 if the quantities of register @arg1 is greater than or equal to zero""" - dst = ExprId(ir.get_next_break_label(instr)) if Arg1.msb() else Arg2 + dst = ExprId(ir.get_next_break_label(instr)) if arg1.msb() else arg2 PC = dst ir.IRDst = dst @sbuild.parse -def bne(Arg1, Arg2, Arg3): - """Branches on @Arg3 if the quantities of two registers @Arg1, @Arg2 are NOT +def bne(arg1, arg2, arg3): + """Branches on @arg3 if the quantities of two registers @arg1, @arg2 are NOT equal""" - dst = Arg3 if Arg1 - Arg2 else ExprId(ir.get_next_break_label(instr)) + dst = arg3 if arg1 - arg2 else ExprId(ir.get_next_break_label(instr)) PC = dst ir.IRDst = dst @sbuild.parse -def lui(Arg1, Arg2): - """The immediate value @Arg2 is shifted left 16 bits and stored in the - register @Arg1. The lower 16 bits are zeroes.""" - Arg1 = ExprCompose([(i16(0), 0, 16), (Arg2[:16], 16, 32)]) +def lui(arg1, arg2): + """The immediate value @arg2 is shifted left 16 bits and stored in the + register @arg1. The lower 16 bits are zeroes.""" + arg1 = ExprCompose([(i16(0), 0, 16), (arg2[:16], 16, 32)]) @sbuild.parse def nop(): """Do nothing""" @sbuild.parse -def j(Arg1): - """Jump to an address @Arg1""" - PC = Arg1 - ir.IRDst = Arg1 +def j(arg1): + """Jump to an address @arg1""" + PC = arg1 + ir.IRDst = arg1 @sbuild.parse -def l_or(Arg1, Arg2, Arg3): - """Bitwise logical ors two registers @Arg2, @Arg3 and stores the result in a - register @Arg1""" - Arg1 = Arg2 | Arg3 +def l_or(arg1, arg2, arg3): + """Bitwise logical ors two registers @arg2, @arg3 and stores the result in a + register @arg1""" + arg1 = arg2 | arg3 @sbuild.parse -def nor(Arg1, Arg2, Arg3): - """Bitwise logical Nors two registers @Arg2, @Arg3 and stores the result in - a register @Arg1""" - Arg1 = (Arg2 | Arg3) ^ i32(-1) +def nor(arg1, arg2, arg3): + """Bitwise logical Nors two registers @arg2, @arg3 and stores the result in + a register @arg1""" + arg1 = (arg2 | arg3) ^ i32(-1) @sbuild.parse -def l_and(Arg1, Arg2, Arg3): - """Bitwise logical ands two registers @Arg2, @Arg3 and stores the result in - a register @Arg1""" - Arg1 = Arg2 & Arg3 +def l_and(arg1, arg2, arg3): + """Bitwise logical ands two registers @arg2, @arg3 and stores the result in + a register @arg1""" + arg1 = arg2 & arg3 -def ext(ir, instr, a, b, c, d): - e = [] - pos = int(c.arg) - size = int(d.arg) - e.append(m2_expr.ExprAff(a, b[pos:pos+size].zeroExtend(32))) - return e, [] +@sbuild.parse +def ext(arg1, arg2, arg3, arg4): + pos = int(arg3.arg) + size = int(arg4.arg) + arg1 = arg2[pos:pos + size].zeroExtend(32) -def mul(ir, instr, a, b, c): - """Multiplies @b by $c and stores the result in @a.""" - e = [] - e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('imul', b, c))) - return e, [] +@sbuild.parse +def mul(arg1, arg2, arg3): + """Multiplies @arg2 by $arg3 and stores the result in @arg1.""" + arg1 = 'imul'(arg2, arg3) -def sltu(ir, instr, a, x, y): - """If @y is less than @x (unsigned), @a is set to one. It gets zero +@sbuild.parse +def sltu(arg1, arg2, arg3): + """If @arg3 is less than @arg2 (unsigned), @arg1 is set to one. It gets zero otherwise.""" - e = [] - value = (((x - y) ^ ((x ^ y) & ((x - y) ^ x))) ^ x ^ y).msb().zeroExtend(32) - e.append(m2_expr.ExprAff(a, value)) - return e, [] + arg1 = (((arg2 - arg3) ^ ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))) ^ arg2 ^ arg3).msb().zeroExtend(32) -def slt(ir, instr, a, x, y): - """If @y is less than @x (signed), @a is set to one. It gets zero +@sbuild.parse +def slt(arg1, arg2, arg3): + """If @arg3 is less than @arg2 (signed), @arg1 is set to one. It gets zero otherwise.""" - e = [] - value = ((x - y) ^ ((x ^ y) & ((x - y) ^ x))).zeroExtend(32) - e.append(m2_expr.ExprAff(a, value)) - return e, [] - -def l_sub(ir, instr, a, b, c): - e = [] - e.append(m2_expr.ExprAff(a, b-c)) - return e, [] - -def sb(ir, instr, a, b): - "The least significant byte of @a is stored at the specified address @b." - e = [] - b = m2_expr.ExprMem(b.arg, 8) - e.append(m2_expr.ExprAff(b, a[:8])) - return e, [] + arg1 = ((arg2 - arg3) ^ ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))).zeroExtend(32) -def sh(ir, instr, a, b): - e = [] - b = m2_expr.ExprMem(b.arg, 16) - e.append(m2_expr.ExprAff(b, a[:16])) - return e, [] +@sbuild.parse +def l_sub(arg1, arg2, arg3): + arg1 = arg2 - arg3 -def movn(ir, instr, a, b, c): - lbl_do = m2_expr.ExprId(ir.gen_label(), 32) - lbl_skip = m2_expr.ExprId(ir.get_next_instr(instr), 32) - e_do = [] - e_do.append(m2_expr.ExprAff(a, b)) - e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip)) - e = [] - e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(c, lbl_do, lbl_skip))) +@sbuild.parse +def sb(arg1, arg2): + """The least significant byte of @arg1 is stored at the specified address + @arg2.""" + mem8[arg2.arg] = arg1[:8] - return e, [irbloc(lbl_do.name, [e_do], [])] +@sbuild.parse +def sh(arg1, arg2): + mem16[arg2.arg] = arg1[:16] -def movz(ir, instr, a, b, c): - lbl_do = m2_expr.ExprId(ir.gen_label(), 32) - lbl_skip = m2_expr.ExprId(ir.get_next_instr(instr), 32) - e_do = [] - e_do.append(m2_expr.ExprAff(a, b)) - e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip)) - e = [] - e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(c, lbl_skip, lbl_do))) +@sbuild.parse +def movn(arg1, arg2, arg3): + if arg3: + arg1 = arg2 - return e, [irbloc(lbl_do.name, [e_do], [])] +@sbuild.parse +def movz(arg1, arg2, arg3): + if not arg3: + arg1 = arg2 -def srl(ir, instr, a, b, c): - """Shifts a register value @b right by the shift amount @c and places the - value in the destination register @a. Zeroes are shifted in.""" - e = [] - e.append(m2_expr.ExprAff(a, b >> c)) - return e, [] +@sbuild.parse +def srl(arg1, arg2, arg3): + """Shifts arg1 register value @arg2 right by the shift amount @arg3 and + places the value in the destination register @arg1. + Zeroes are shifted in.""" + arg1 = arg2 >> arg3 -def sra(ir, instr, a, b, c): - """Shifts a register value @b right by the shift amount @c and places the - value in the destination register @a. The sign bit is shifted in.""" - e = [] - e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('a>>', b, c))) - return e, [] +@sbuild.parse +def sra(arg1, arg2, arg3): + """Shifts arg1 register value @arg2 right by the shift amount @arg3 and + places the value in the destination register @arg1. The sign bit is shifted + in.""" + arg1 = 'a>>'(arg2, arg3) -def srav(ir, instr, a, b, c): - e = [] - value = m2_expr.ExprOp('a>>', b, c&m2_expr.ExprInt32(0x1F)) - e.append(m2_expr.ExprAff(a, value)) - return e, [] +@sbuild.parse +def srav(arg1, arg2, arg3): + arg1 = 'a>>'(arg2, arg3 & i32(0x1F)) -def sll(ir, instr, a, b, c): - e = [] - e.append(m2_expr.ExprAff(a, b<<c)) - return e, [] +@sbuild.parse +def sll(arg1, arg2, arg3): + arg1 = arg2 << arg3 -def srlv(ir, instr, a, b, c): - """Shifts a register value @b right by the amount specified in @c and places - the value in the destination register @a. Zeroes are shifted in.""" - e = [] - e.append(m2_expr.ExprAff(a, b >> (c & m2_expr.ExprInt32(0x1F)))) - return e, [] +@sbuild.parse +def srlv(arg1, arg2, arg3): + """Shifts a register value @arg2 right by the amount specified in @arg3 and + places the value in the destination register @arg1. + Zeroes are shifted in.""" + arg1 = arg2 >> (arg3 & i32(0x1F)) -def sllv(ir, instr, a, b, c): - """Shifts a register value @b left by the amount specified in @c and places - the value in the destination register @a. Zeroes are shifted in.""" - e = [] - e.append(m2_expr.ExprAff(a, b << (c & m2_expr.ExprInt32(0x1F)))) - return e, [] +@sbuild.parse +def sllv(arg1, arg2, arg3): + """Shifts a register value @arg2 left by the amount specified in @arg3 and + places the value in the destination register @arg1. + Zeroes are shifted in.""" + arg1 = arg2 << (arg3 & i32(0x1F)) -def l_xor(ir, instr, a, b, c): - """Exclusive ors two registers @b, @c and stores the result in a register - @c""" - e = [] - e.append(m2_expr.ExprAff(a, b^c)) - return e, [] +@sbuild.parse +def l_xor(arg1, arg2, arg3): + """Exclusive ors two registers @arg2, @arg3 and stores the result in a + register @arg3""" + arg1 = arg2 ^ arg3 -def seb(ir, instr, a, b): - e = [] - e.append(m2_expr.ExprAff(a, b[:8].signExtend(32))) - return e, [] +@sbuild.parse +def seb(arg1, arg2): + arg1 = arg2[:8].signExtend(32) -def seh(ir, instr, a, b): - e = [] - e.append(m2_expr.ExprAff(a, b[:16].signExtend(32))) - return e, [] +@sbuild.parse +def seh(arg1, arg2): + arg1 = arg2[:16].signExtend(32) -def bltz(ir, instr, a, b): - """Branches on @b if the register @a is less than zero""" - e = [] - n = m2_expr.ExprId(ir.get_next_break_label(instr)) - dst_o = m2_expr.ExprCond(a.msb(), b, n) - e = [m2_expr.ExprAff(PC, dst_o), - m2_expr.ExprAff(ir.IRDst, dst_o) - ] - return e, [] +@sbuild.parse +def bltz(arg1, arg2): + """Branches on @arg2 if the register @arg1 is less than zero""" + dst_o = arg2 if arg1.msb() else ExprId(ir.get_next_break_label(instr)) + PC = dst_o + ir.IRDst = dst_o -def blez(ir, instr, a, b): - """Branches on @b if the register @a is less than or equal to zero""" - e = [] - n = m2_expr.ExprId(ir.get_next_break_label(instr)) - cond = m2_expr.ExprCond(a, m2_expr.ExprInt1(1), - m2_expr.ExprInt1(0)) | a.msb() - dst_o = m2_expr.ExprCond(cond, b, n) - e = [m2_expr.ExprAff(PC, dst_o), - m2_expr.ExprAff(ir.IRDst, dst_o) - ] - return e, [] +@sbuild.parse +def blez(arg1, arg2): + """Branches on @arg2 if the register @arg1 is less than or equal to zero""" + cond = (i1(1) if arg1 else i1(0)) | arg1.msb() + dst_o = arg2 if cond else ExprId(ir.get_next_break_label(instr)) + PC = dst_o + ir.IRDst = dst_o -def bgtz(ir, instr, a, b): - """Branches on @b if the register @a is greater than zero""" - e = [] - n = m2_expr.ExprId(ir.get_next_break_label(instr)) - cond = m2_expr.ExprCond(a, m2_expr.ExprInt1(1), - m2_expr.ExprInt1(0)) | a.msb() - dst_o = m2_expr.ExprCond(cond, n, b) - e = [m2_expr.ExprAff(PC, dst_o), - m2_expr.ExprAff(ir.IRDst, dst_o) - ] - return e, [] +@sbuild.parse +def bgtz(arg1, arg2): + """Branches on @arg2 if the register @arg1 is greater than zero""" + cond = (i1(1) if arg1 else i1(0)) | arg1.msb() + dst_o = ExprId(ir.get_next_break_label(instr)) if cond else arg2 + PC = dst_o + ir.IRDst = dst_o -def wsbh(ir, instr, a, b): - e = [m2_expr.ExprAff(a, m2_expr.ExprCompose([(b[8:16], 0, 8), - (b[0:8] , 8, 16), - (b[24:32], 16, 24), - (b[16:24], 24, 32)]))] - return e, [] +@sbuild.parse +def wsbh(arg1, arg2): + arg1 = ExprCompose([(arg2[8:16], 0, 8), + (arg2[0:8] , 8, 16), + (arg2[24:32], 16, 24), + (arg2[16:24], 24, 32)]) -def rotr(ir, instr, a, b, c): - e = [] - e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('>>>', b, c))) - return e, [] +@sbuild.parse +def rotr(arg1, arg2, arg3): + arg1 = '>>>'(arg2, arg3) -def add_d(ir, instr, a, b, c): +@sbuild.parse +def add_d(arg1, arg2, arg3): # XXX TODO check - e = [] - e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fadd', b, c))) - return e, [] + arg1 = 'fadd'(arg2, arg3) -def sub_d(ir, instr, a, b, c): +@sbuild.parse +def sub_d(arg1, arg2, arg3): # XXX TODO check - e = [] - e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fsub', b, c))) - return e, [] + arg1 = 'fsub'(arg2, arg3) -def div_d(ir, instr, a, b, c): +@sbuild.parse +def div_d(arg1, arg2, arg3): # XXX TODO check - e = [] - e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fdiv', b, c))) - return e, [] + arg1 = 'fdiv'(arg2, arg3) -def mul_d(ir, instr, a, b, c): +@sbuild.parse +def mul_d(arg1, arg2, arg3): # XXX TODO check - e = [] - e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fmul', b, c))) - return e, [] + arg1 = 'fmul'(arg2, arg3) -def mov_d(ir, instr, a, b): +@sbuild.parse +def mov_d(arg1, arg2): # XXX TODO check - e = [] - e.append(m2_expr.ExprAff(a, b)) - return e, [] + arg1 = arg2 -def mfc0(ir, instr, a, b): - e = [] - e.append(m2_expr.ExprAff(a, b)) - return e, [] +@sbuild.parse +def mfc0(arg1, arg2): + arg1 = arg2 -def mfc1(ir, instr, a, b): - e = [] - e.append(m2_expr.ExprAff(a, b)) - return e, [] +@sbuild.parse +def mfc1(arg1, arg2): + arg1 = arg2 -def mtc0(ir, instr, a, b): - e = [] - e.append(m2_expr.ExprAff(b, a)) - return e, [] +@sbuild.parse +def mtc0(arg1, arg2): + arg2 = arg1 -def mtc1(ir, instr, a, b): - e = [] - e.append(m2_expr.ExprAff(b, a)) - return e, [] +@sbuild.parse +def mtc1(arg1, arg2): + arg2 = arg1 -def tlbwi(ir, instr): - # TODO XXX - e = [] - return e, [] +@sbuild.parse +def tlbwi(): + "TODO XXX" -def tlbp(ir, instr): - # TODO XXX - e = [] - return e, [] +@sbuild.parse +def tlbp(): + "TODO XXX" def ins(ir, instr, a, b, c, d): e = [] @@ -378,179 +326,106 @@ def ins(ir, instr, a, b, c, d): return e, [] -def lwc1(ir, instr, a, b): - e = [] - src = m2_expr.ExprOp('mem_%.2d_to_single' % b.size, b) - e.append(m2_expr.ExprAff(a, src)) - return e, [] +@sbuild.parse +def lwc1(arg1, arg2): + arg1 = ('mem_%.2d_to_single' % arg2.size)(arg2) -def swc1(ir, instr, a, b): - e = [] - src = m2_expr.ExprOp('single_to_mem_%.2d' % a.size, a) - e.append(m2_expr.ExprAff(b, src)) - return e, [] +@sbuild.parse +def swc1(arg1, arg2): + arg2 = ('single_to_mem_%.2d' % arg1.size)(arg1) -def c_lt_d(ir, instr, a, b, c): - e = [] - e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fcomp_lt', b, c))) - return e, [] +@sbuild.parse +def c_lt_d(arg1, arg2, arg3): + arg1 = 'fcomp_lt'(arg2, arg3) -def c_eq_d(ir, instr, a, b, c): - e = [] - e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fcomp_eq', b, c))) - return e, [] +@sbuild.parse +def c_eq_d(arg1, arg2, arg3): + arg1 = 'fcomp_eq'(arg2, arg3) -def c_le_d(ir, instr, a, b, c): - e = [] - e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('fcomp_le', b, c))) - return e, [] +@sbuild.parse +def c_le_d(arg1, arg2, arg3): + arg1 = 'fcomp_le'(arg2, arg3) -def bc1t(ir, instr, a, b): - e = [] - n = m2_expr.ExprId(ir.get_next_break_label(instr)) - dst_o = m2_expr.ExprCond(a, b, n) - e = [m2_expr.ExprAff(PC, dst_o)] - e.append(m2_expr.ExprAff(ir.IRDst, dst_o)) - return e, [] +@sbuild.parse +def bc1t(arg1, arg2): + dst_o = arg2 if arg1 else ExprId(ir.get_next_break_label(instr)) + PC = dst_o + ir.IRDst = dst_o -def bc1f(ir, instr, a, b): - e = [] - n = m2_expr.ExprId(ir.get_next_break_label(instr)) - dst_o = m2_expr.ExprCond(a, n, b) - e = [m2_expr.ExprAff(PC, dst_o)] - e.append(m2_expr.ExprAff(ir.IRDst, dst_o)) - return e, [] +@sbuild.parse +def bc1f(arg1, arg2): + dst_o = ExprId(ir.get_next_break_label(instr)) if arg1 else arg2 + PC = dst_o + ir.IRDst = dst_o -def cvt_d_w(ir, instr, a, b): - e = [] +@sbuild.parse +def cvt_d_w(arg1, arg2): # TODO XXX - e.append(m2_expr.ExprAff(a, m2_expr.ExprOp('flt_d_w', b))) - return e, [] + arg1 = 'flt_d_w'(arg2) -def mult(ir, instr, a, b): - """Multiplies (signed) @a by @b and stores the result in $R_HI:$R_LO""" - e = [] - size = a.size - r = a.signExtend(size * 2) * b.signExtend(size * 2) +@sbuild.parse +def mult(arg1, arg2): + """Multiplies (signed) @arg1 by @arg2 and stores the result in $R_HI:$R_LO""" + size = arg1.size + result = arg1.signExtend(size * 2) * arg2.signExtend(size * 2) + R_LO = result[:32] + R_HI = result[32:] - e.append(m2_expr.ExprAff(R_LO, r[:32])) - e.append(m2_expr.ExprAff(R_HI, r[32:])) - return e, [] +@sbuild.parse +def multu(arg1, arg2): + """Multiplies (unsigned) @arg1 by @arg2 and stores the result in $R_HI:$R_LO""" + size = arg1.size + result = arg1.zeroExtend(size * 2) * arg2.zeroExtend(size * 2) + R_LO = result[:32] + R_HI = result[32:] -def multu(ir, instr, a, b): - """Multiplies (unsigned) @a by @b and stores the result in $R_HI:$R_LO""" - e = [] - size = a.size - r = a.zeroExtend(size * 2) * b.zeroExtend(size * 2) +@sbuild.parse +def mfhi(arg1): + "The contents of register $R_HI are moved to the specified register @arg1." + arg1 = R_HI - e.append(m2_expr.ExprAff(R_LO, r[:32])) - e.append(m2_expr.ExprAff(R_HI, r[32:])) - return e, [] +@sbuild.parse +def mflo(arg1): + "The contents of register R_LO are moved to the specified register @arg1." + arg1 = R_LO -def mfhi(ir, instr, a): - "The contents of register $R_HI are moved to the specified register @a." - e = [] - e.append(m2_expr.ExprAff(a, R_HI)) - return e, [] +@sbuild.parse +def di(arg1): + "NOP" -def mflo(ir, instr, a): - "The contents of register R_LO are moved to the specified register @a." - e = [] - e.append(m2_expr.ExprAff(a, R_LO)) - return e, [] +@sbuild.parse +def ei(arg1): + "NOP" -def di(ir, instr, a): - return [], [] - -def ei(ir, instr, a): - return [], [] - -def ehb(ir, instr, a): - return [], [] - -mnemo_func = { - "addiu": addiu, - "addu": addiu, - "lw" : lw, - "sw" : sw, - "sh" : sh, - "sb" : sb, - "jalr" : jalr, - "jal" : jal, - "bal" : bal, - "b" : l_b, - "lbu" : lbu, - "lhu" : lhu, - "lb" : lb, - "beq" : beq, - "bgez" : bgez, - "bltz" : bltz, - "bgtz" : bgtz, - "bne" : bne, - "lui" : lui, - "nop" : nop, - "j" : j, - "jr" : j, - "ori" : l_or, - "or" : l_or, - "nor" : nor, - "and" : l_and, - "andi" : l_and, - "ext" : ext, - "mul" : mul, - "sltu" : sltu, - "slt" : slt, - "slti" : slt, - "sltiu" : sltu, - "subu" : l_sub, - "movn" : movn, - "movz" : movz, - "srl" : srl, - "sra" : sra, - "srav" : srav, - "sll" : sll, - "srlv" : srlv, - "sllv" : sllv, - "xori" : l_xor, - "xor" : l_xor, - "seb" : seb, - "seh" : seh, - "bltz" : bltz, - "blez" : blez, - "wsbh" : wsbh, - "rotr" : rotr, - # "mfc0" : mfc0, - # "mfc1" : mfc1, - # "mtc0" : mtc0, - # "mtc1" : mtc1, - "tlbwi" : tlbwi, - "tlbp" : tlbp, - "ins" : ins, - - "add.d" : add_d, - "sub.d" : sub_d, - "div.d" : div_d, - "mul.d" : mul_d, - "mov.d" : mov_d, - "lwc1" : lwc1, - "swc1" : swc1, - "c.lt.d" : c_lt_d, - "c.eq.d" : c_eq_d, - "c.le.d" : c_le_d, - "bc1t" : bc1t, - "bc1f" : bc1f, - "cvt.d.w":cvt_d_w, - "mult" : mult, - "multu" : multu, - - "mfhi" : mfhi, - "mflo" : mflo, - - "di" : di, - "ei" : ei, - "ehb" : ehb, - - } +@sbuild.parse +def ehb(arg1): + "NOP" + +mnemo_func = sbuild.functions +mnemo_func.update({ + 'add.d': add_d, + 'addu': addiu, + 'and': l_and, + 'andi': l_and, + 'b': l_b, + 'c.eq.d': c_eq_d, + 'c.le.d': c_le_d, + 'c.lt.d': c_lt_d, + 'cvt.d.w': cvt_d_w, + 'div.d': div_d, + 'ins': ins, + 'jr': j, + 'mov.d': mov_d, + 'mul.d': mul_d, + 'or': l_or, + 'ori': l_or, + 'slti': slt, + 'sltiu': sltu, + 'sub.d': sub_d, + 'subu': l_sub, + 'xor': l_xor, + 'xori': l_xor, +}) def get_mnemo_expr(ir, instr, *args): instr, extra_ir = mnemo_func[instr.name.lower()](ir, instr, *args) diff --git a/miasm2/core/sembuilder.py b/miasm2/core/sembuilder.py index 34271960..985a6a65 100644 --- a/miasm2/core/sembuilder.py +++ b/miasm2/core/sembuilder.py @@ -4,6 +4,9 @@ import inspect import ast import re +import miasm2.expression.expression as m2_expr +from miasm2.ir.ir import irbloc + class MiasmTransformer(ast.NodeTransformer): """AST visitor translating DSL to Miasm expression @@ -11,6 +14,8 @@ class MiasmTransformer(ast.NodeTransformer): memX[Y] -> ExprMem(Y, X) iX(Y) -> ExprIntX(Y) X if Y else Z -> ExprCond(Y, X, Z) + 'X'(Y) -> ExprOp('X', Y) + ('X' % Y)(Z) -> ExprOp('X' % Y, Z) """ # Parsers @@ -20,23 +25,40 @@ class MiasmTransformer(ast.NodeTransformer): # Visitors def visit_Call(self, node): - """iX(Y) -> ExprIntX(Y)""" - # Match the function name - if not isinstance(node.func, ast.Name): + """iX(Y) -> ExprIntX(Y), + 'X'(Y) -> ExprOp('X', Y), ('X' % Y)(Z) -> ExprOp('X' % Y, Z)""" + if isinstance(node.func, ast.Name): + # iX(Y) -> ExprIntX(Y) + fc_name = node.func.id + + # Match the function name + new_name = fc_name + integer = self.parse_integer.search(fc_name) + + # Do replacement + if integer is not None: + new_name = "ExprInt%s" % integer.groups()[0] + + # Replace in the node + node.func.id = new_name + + elif (isinstance(node.func, ast.Str) or + (isinstance(node.func, ast.BinOp) and + isinstance(node.func.op, ast.Mod) and + isinstance(node.func.left, ast.Str))): + # 'op'(args...) -> ExprOp('op', args...) + # ('op' % (fmt))(args...) -> ExprOp('op' % (fmt), args...) + op_name = node.func + + # Do replacement + node.func = ast.Name(id="ExprOp", ctx=ast.Load()) + node.args[0:0] = [op_name] + node.args = map(self.visit, node.args) + + else: # TODO: launch visitor on node - return node - - fc_name = node.func.id - new_name = fc_name - integer = self.parse_integer.search(fc_name) - - # Do replacement - if integer is not None: - new_name = "ExprInt%s" % integer.groups()[0] + pass - # Replace in the node - node.func.id = new_name - # TODO: launch visitor on node return node def visit_Subscript(self, node): @@ -80,22 +102,40 @@ class SemBuilder(object): """Create a SemBuilder @ctx: context dictionnary used during parsing """ - self.ctx = dict(ctx) + # Init self.transformer = MiasmTransformer() - - def parse(self, func): - """Function decorator, returning a correct method from a pseudo-Python - one""" - - # Get the function AST - parsed = ast.parse(inspect.getsource(func)) - fc_ast = parsed.body[0] - argument_names = [name.id for name in fc_ast.args.args] - body = [] - - # AffBlock of the current instruction - new_ast = [] - for statement in fc_ast.body: + self._ctx = dict(m2_expr.__dict__) + self._ctx["irbloc"] = irbloc + self._functions = {} + + # Update context + self._ctx.update(ctx) + + @property + def functions(self): + """Return a dictionnary name -> func of parsed functions""" + return self._functions.copy() + + @staticmethod + def _create_labels(): + """Return the AST standing for label creations""" + out = ast.parse("lbl_end = ExprId(ir.get_next_instr(instr))").body + out += ast.parse("lbl_if = ExprId(ir.gen_label())").body + return out + + def _parse_body(self, body, argument_names): + """Recursive function transforming a @body to a block expression + Return: + - AST to append to body (real python statements) + - a list of blocks, ie list of affblock, ie list of ExprAff (AST)""" + + # Init + ## Real instructions + real_body = [] + ## Final blocks + blocks = [[[]]] + + for statement in body: if isinstance(statement, ast.Assign): src = self.transformer.visit(statement.value) @@ -103,10 +143,11 @@ class SemBuilder(object): if (isinstance(dst, ast.Name) and dst.id not in argument_names and - dst.id not in self.ctx): + dst.id not in self._ctx): + # Real variable declaration statement.value = src - body.append(statement) + real_body.append(statement) continue dst.ctx = ast.Load() @@ -118,22 +159,112 @@ class SemBuilder(object): starargs=None, kwargs=None) - new_ast.append(res) + blocks[-1][-1].append(res) elif (isinstance(statement, ast.Expr) and isinstance(statement.value, ast.Str)): # String (docstring, comment, ...) -> keep it - body.append(statement) + real_body.append(statement) + + elif (isinstance(statement, ast.If) and + not statement.orelse): + # Create jumps : ir.IRDst = lbl_if if cond else lbl_end + cond = statement.test + real_body += self._create_labels() + + lbl_end = ast.Name(id='lbl_end', ctx=ast.Load()) + lbl_if = ast.Name(id='lbl_if', ctx=ast.Load()) + dst = ast.Call(func=ast.Name(id='ExprCond', + ctx=ast.Load()), + args=[cond, + lbl_if, + lbl_end], + keywords=[], + starargs=None, + kwargs=None) + + if (isinstance(cond, ast.UnaryOp) and + isinstance(cond.op, ast.Not)): + ## if not cond -> switch exprCond + dst.args[1:] = dst.args[1:][::-1] + dst.args[0] = cond.operand + + IRDst = ast.Attribute(value=ast.Name(id='ir', + ctx=ast.Load()), + attr='IRDst', ctx=ast.Load()) + blocks[-1][-1].append(ast.Call(func=ast.Name(id='ExprAff', + ctx=ast.Load()), + args=[IRDst, dst], + keywords=[], + starargs=None, + kwargs=None)) + + # Create the new blocks + sub_blocks, sub_body = self._parse_body(statement.body, + argument_names) + if len(sub_blocks) > 1: + raise RuntimeError("Imbricated if unimplemented") + + ## Close the last block + jmp_end = ast.Call(func=ast.Name(id='ExprAff', + ctx=ast.Load()), + args=[IRDst, lbl_end], + keywords=[], + starargs=None, + kwargs=None) + sub_blocks[-1][-1].append(jmp_end) + sub_blocks[-1][-1] = ast.List(elts=sub_blocks[-1][-1], + ctx=ast.Load()) + sub_blocks[-1] = ast.List(elts=sub_blocks[-1], + ctx=ast.Load()) + + ## Replace the block with a call to 'irbloc' + lbl_if_name = ast.Attribute(value=ast.Name(id='lbl_if', + ctx=ast.Load()), + attr='name', ctx=ast.Load()) + + sub_blocks[-1] = ast.Call(func=ast.Name(id='irbloc', + ctx=ast.Load()), + args=[lbl_if_name, + sub_blocks[-1]], + keywords=[], + starargs=None, + kwargs=None) + blocks += sub_blocks + real_body += sub_body + + # Prepare a new block for following statement + blocks.append([[]]) + else: # TODO: real var, +=, /=, -=, <<=, >>=, if/else, ... raise RuntimeError("Unimplemented %s" % statement) + return blocks, real_body + + def parse(self, func): + """Function decorator, returning a correct method from a pseudo-Python + one""" + + # Get the function AST + parsed = ast.parse(inspect.getsource(func)) + fc_ast = parsed.body[0] + argument_names = [name.id for name in fc_ast.args.args] + + # Translate (blocks[0][0] is the current instr) + blocks, body = self._parse_body(fc_ast.body, argument_names) + # Build the new function fc_ast.args.args[0:0] = [ast.Name(id='ir', ctx=ast.Param()), ast.Name(id='instr', ctx=ast.Param())] - body.append(ast.Return(value=ast.Tuple(elts=[ast.List(elts=new_ast, + cur_instr = blocks[0][0] + if len(blocks[-1][0]) == 0: + ## Last block can be empty + blocks.pop() + other_blocks = blocks[1:] + body.append(ast.Return(value=ast.Tuple(elts=[ast.List(elts=cur_instr, ctx=ast.Load()), - ast.List(elts=[], + ast.List(elts=other_blocks, ctx=ast.Load())], ctx=ast.Load()))) @@ -148,8 +279,9 @@ class SemBuilder(object): # Compile according to the context fixed = ast.fix_missing_locations(ret) codeobj = compile(fixed, '<string>', 'exec') - ctx = self.ctx.copy() + ctx = self._ctx.copy() eval(codeobj, ctx) # Get the function back + self._functions[fc_ast.name] = ctx[fc_ast.name] return ctx[fc_ast.name] diff --git a/miasm2/jitter/arch/JitCore_arm.c b/miasm2/jitter/arch/JitCore_arm.c index 92027c25..b2550194 100644 --- a/miasm2/jitter/arch/JitCore_arm.c +++ b/miasm2/jitter/arch/JitCore_arm.c @@ -165,7 +165,7 @@ PyObject* cpu_get_exception(JitCpu* self, PyObject* args) -void check_automod(JitCpu* jitcpu, uint64_t addr, int size) +void check_automod(JitCpu* jitcpu, uint64_t addr, uint64_t size) { PyObject *result; diff --git a/miasm2/jitter/arch/JitCore_mips32.c b/miasm2/jitter/arch/JitCore_mips32.c index 4cd016cf..c8f8fb81 100644 --- a/miasm2/jitter/arch/JitCore_mips32.c +++ b/miasm2/jitter/arch/JitCore_mips32.c @@ -209,7 +209,7 @@ PyObject* cpu_get_exception(JitCpu* self, PyObject* args) -void check_automod(JitCpu* jitcpu, uint64_t addr, int size) +void check_automod(JitCpu* jitcpu, uint64_t addr, uint64_t size) { PyObject *result; diff --git a/miasm2/jitter/arch/JitCore_msp430.c b/miasm2/jitter/arch/JitCore_msp430.c index e4f26de1..3a34248a 100644 --- a/miasm2/jitter/arch/JitCore_msp430.c +++ b/miasm2/jitter/arch/JitCore_msp430.c @@ -182,7 +182,7 @@ PyObject* cpu_get_exception(JitCpu* self, PyObject* args) -void check_automod(JitCpu* jitcpu, uint64_t addr, int size) +void check_automod(JitCpu* jitcpu, uint64_t addr, uint64_t size) { PyObject *result; diff --git a/miasm2/jitter/arch/JitCore_x86.c b/miasm2/jitter/arch/JitCore_x86.c index a5bbb7bc..baa66755 100644 --- a/miasm2/jitter/arch/JitCore_x86.c +++ b/miasm2/jitter/arch/JitCore_x86.c @@ -307,7 +307,7 @@ IMOD(64) -void check_automod(JitCpu* jitcpu, uint64_t addr, int size) +void check_automod(JitCpu* jitcpu, uint64_t addr, uint64_t size) { PyObject *result; diff --git a/test/core/sembuilder.py b/test/core/sembuilder.py index 3c1b7d3f..468e3ef5 100644 --- a/test/core/sembuilder.py +++ b/test/core/sembuilder.py @@ -3,7 +3,20 @@ from pdb import pm from miasm2.core.sembuilder import SemBuilder import miasm2.expression.expression as m2_expr +from miasm2.core.asmbloc import asm_label +# Test classes +class IR(object): + + IRDst = m2_expr.ExprId("IRDst") + + def get_next_instr(self, _): + return asm_label("NEXT") + + def gen_label(self): + return asm_label("GEN") + +# Test sb = SemBuilder(m2_expr.__dict__) @sb.parse @@ -13,13 +26,27 @@ def test(Arg1, Arg2, Arg3): mem32[Arg1] = Arg2 mem32[Arg2] = Arg3 + i32(4) - mem32[Arg1] Arg3 = Arg3 if Arg2 else i32(0) - tmpvar = i32(2) - Arg2 = tmpvar + tmpvar = 'myop'(i32(2)) + Arg2 = ('myopsize%d' % Arg1.size)(tmpvar, Arg1) + + if not Arg1: + Arg2 = Arg3 a = m2_expr.ExprId('A') b = m2_expr.ExprId('B') c = m2_expr.ExprId('C') -ir = None +ir = IR() instr = None -print test(ir, instr, a, b, c) -print test.__doc__ +res = test(ir, instr, a, b, c) + +print "[+] Returned:" +print res +print "[+] DocString:", test.__doc__ + +print "[+] Cur instr:" +for statement in res[0]: + print statement + +print "[+] Blocks:" +for block in res[1]: + print block |