def test_and3(self): """Test AND3 execution""" # AND3 Rn,Rm,imm16 exec_instruction("AND3 R1, R2, 0", [(ExprId("R2", 32), ExprInt(1, 32))], [(ExprId("R1", 32), ExprInt(0, 32))])
def test_ldc(self): """Test LDC execution""" # LDC Rn,imm5 exec_instruction("LDC R1, SAR", [(ExprId("SAR", 32), ExprInt(0x28, 32))], [(ExprId("R1", 32), ExprInt(0x28, 32))])
def from_ExprOp(self, expr): if expr.op in self.op_no_translate: args = list(map(self.from_expr, expr.args)) if len(expr.args) == 1: return "((%s %s) & 0x%x)" % (expr.op, args[0], (1 << expr.size) - 1) else: return "((%s) & 0x%x)" % ((" %s " % expr.op).join(args), (1 << expr.size) - 1) elif expr.op == "parity": return "(%s & 0x1)" % self.from_expr(expr.args[0]) elif expr.op == "==": return self.from_expr( ExprCond(expr.args[0] - expr.args[1], ExprInt(0, 1), ExprInt(1, 1))) elif expr.op in ["<<<", ">>>"]: amount_raw = expr.args[1] amount = expr.args[1] % ExprInt(amount_raw.size, expr.size) amount_inv = ExprInt(expr.size, expr.size) - amount if expr.op == "<<<": amount, amount_inv = amount_inv, amount part1 = "(%s >> %s)" % (self.from_expr( expr.args[0]), self.from_expr(amount)) part2 = "(%s << %s)" % (self.from_expr( expr.args[0]), self.from_expr(amount_inv)) return "((%s | %s) &0x%x)" % (part1, part2, int(expr.mask)) raise NotImplementedError("Unknown operator: %s" % expr.op)
def mem_read(self, expr_mem): if not expr_mem.ptr.is_int(): return super(ESETrackModif, self).mem_read(expr_mem) dst_addr = int(expr_mem.ptr) # Split access in atomic accesses out = [] for addr in range(dst_addr, dst_addr + expr_mem.size // 8): if addr in self.dse_memory_range: # Symbolize memory access out.append(self.dse_memory_to_expr(addr)) continue atomic_access = ExprMem(ExprInt(addr, expr_mem.ptr.size), 8) if atomic_access in self.symbols: out.append( super(EmulatedSymbExec, self).mem_read(atomic_access)) else: # Get concrete value atomic_access = ExprMem(ExprInt(addr, expr_mem.ptr.size), 8) out.append(super(ESETrackModif, self).mem_read(atomic_access)) if len(out) == 1: # Trivial case (optimization) return out[0] # Simplify for constant merging (ex: {ExprInt(1, 8), ExprInt(2, 8)}) return self.expr_simp(ExprCompose(*out))
def test_jsr(self): """Test JSR execution""" # JSR Rm exec_instruction("JSR R1", [(ExprId("R1", 32), ExprInt(0x2807, 32))], [(ExprId("PC", 32), ExprInt(0x2807, 32)), (ExprId("LP", 32), ExprInt(0x2, 32))])
def test_or(self): """Test OR execution""" # OR Rn, Rm exec_instruction("OR R1, R2", [(ExprId("R1", 32), ExprInt(1, 32)), (ExprId("R2", 32), ExprInt(1, 32))], [(ExprId("R1", 32), ExprInt(1, 32))])
def test_stc(self): """Test STC execution""" # STC Rn,imm5 exec_instruction("STC R1, SAR", [(ExprId("R1", 32), ExprInt(0x28, 32))], [(ExprId("SAR", 32), ExprInt(0x28, 32))])
def test_xor3(self): """Test XOR3 execution""" # XOR3 Rn,Rm,imm16 exec_instruction("XOR3 R1, R2, 1", [(ExprId("R2", 32), ExprInt(0, 32))], [(ExprId("R1", 32), ExprInt(1, 32))])
def test_nor(self): """Test NOR execution""" # NOR Rn, Rm exec_instruction("NOR R1, R2", [(ExprId("R1", 32), ExprInt(1, 32)), (ExprId("R2", 32), ExprInt(0, 32))], [(ExprId("R1", 32), ExprInt(0xFFFFFFFE, 32))])
def test_and(self): """Test AND execution""" # AND Rn, Rm exec_instruction("AND R1, R2", [(ExprId("R1", 32), ExprInt(1, 32)), (ExprId("R2", 32), ExprInt(0, 32))], [(ExprId("R1", 32), ExprInt(0, 32))])
def test_dbreak(self): """Test DBREAK execution""" # DBREAK exec_instruction("DBREAK", [(ExprId("DBG", 32), ExprInt(0, 32))], [(ExprId("DBG", 32), ExprInt(0b10, 32))])
def mba(size: int) -> Expr: """Generate exemplary MBA expression (for testing/debug purposes)""" v0 = ExprId("v0", size) v1 = ExprId("v1", size) v2 = ExprId("v2", size) return (((v1 ^ v2) + ((v1 & v2) << ExprInt(1, size))) | v0) + (( (v1 ^ v2) + ((v1 & v2) << ExprInt(1, size))) & v0)
def test_sub(self): """Test SUB execution""" # SUB Rn,Rm exec_instruction("SUB R1, R2", [(ExprId("R1", 32), ExprInt(0x28, 32)), (ExprId("R2", 32), ExprInt(0x7, 32))], [(ExprId("R1", 32), ExprInt(0x21, 32))])
def simp_cond(_, expr): """ Common simplifications on ExprCond. Eval exprcond src1/src2 with satifiable/unsatisfiable condition propagation """ if (not expr.cond.is_int()) and expr.cond.size == 1: src1 = expr.src1.replace_expr({expr.cond: ExprInt(1, 1)}) src2 = expr.src2.replace_expr({expr.cond: ExprInt(0, 1)}) if src1 != expr.src1 or src2 != expr.src2: return ExprCond(expr.cond, src1, src2) # -A ? B:C => A ? B:C if expr.cond.is_op('-') and len(expr.cond.args) == 1: expr = ExprCond(expr.cond.args[0], expr.src1, expr.src2) # a?x:x elif expr.src1 == expr.src2: expr = expr.src1 # int ? A:B => A or B elif expr.cond.is_int(): if expr.cond.arg == 0: expr = expr.src2 else: expr = expr.src1 # a?(a?b:c):x => a?b:x elif expr.src1.is_cond() and expr.cond == expr.src1.cond: expr = ExprCond(expr.cond, expr.src1.src1, expr.src2) # a?x:(a?b:c) => a?x:c elif expr.src2.is_cond() and expr.cond == expr.src2.cond: expr = ExprCond(expr.cond, expr.src1, expr.src2.src2) # a|int ? b:c => b with int != 0 elif (expr.cond.is_op('|') and expr.cond.args[1].is_int() and expr.cond.args[1].arg != 0): return expr.src1 # (C?int1:int2)?(A:B) => elif (expr.cond.is_cond() and expr.cond.src1.is_int() and expr.cond.src2.is_int()): int1 = expr.cond.src1.arg.arg int2 = expr.cond.src2.arg.arg if int1 and int2: expr = expr.src1 elif int1 == 0 and int2 == 0: expr = expr.src2 elif int1 == 0 and int2: expr = ExprCond(expr.cond.cond, expr.src2, expr.src1) elif int1 and int2 == 0: expr = ExprCond(expr.cond.cond, expr.src1, expr.src2) elif expr.cond.is_compose(): # {0, X, 0}?(A:B) => X?(A:B) args = [arg for arg in expr.cond.args if not arg.is_int(0)] if len(args) == 1: arg = args.pop() return ExprCond(arg, expr.src1, expr.src2) elif len(args) < len(expr.cond.args): return ExprCond(ExprCompose(*args), expr.src1, expr.src2) return expr
def test_bsetm(self): """Test BSETM execution""" # BSETM (Rm),imm3 exec_instruction("BSETM (R1), 1", [(ExprId("R1", 32), ExprInt(0x28, 32)), (ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x1, 8))], [(ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x3, 8))])
def test_sl2ad3(self): """Test SL2AD3 execution""" # SL2AD3 R0,Rn,Rm exec_instruction("SL2AD3 R0, R1, R2", [(ExprId("R1", 32), ExprInt(0x2, 32)), (ExprId("R2", 32), ExprInt(0x20, 32))], [(ExprId("R0", 32), ExprInt(0x28, 32))])
def test_erepeat(self): """Test EREPEAT execution""" # EREPEAT disp17.align2 exec_instruction("EREPEAT 0x42", [(ExprId("PC", 32), ExprInt(0, 32))], [(ExprId("RPB", 32), ExprInt(4, 32)), (ExprId("RPE", 32), ExprInt(0x43, 32))])
def test_btstm(self): """Test BTSTM execution""" # BTSTM R0,(Rm),imm3 exec_instruction("BTSTM R0, (R1), 1", [(ExprId("R1", 32), ExprInt(0x28, 32)), (ExprMem(ExprInt(0x28, 32), 8), ExprInt(0x2, 8))], [(ExprId("R0", 32), ExprInt(0x2, 32))])
def bne(rn, rm, disp16): """BNE - Branch if the two registers are not equal.""" # if(Rn!=Rm) PC <- PC +SignExt((disp17)16..1||0) dst = disp16 if (rn - rm) else ExprLoc(ir.get_next_break_loc_key(instr), 32) take_jmp = ExprInt(1, 32) if (rn - rm) else ExprInt(0, 32) PC = dst ir.IRDst = dst
def cset(ir, instr, arg1, arg2): e = [] cond_expr = cond2expr[arg2.name] e.append( ExprAssign( arg1, ExprCond(cond_expr, ExprInt(1, arg1.size), ExprInt(0, arg1.size)))) return e, []
def blti(reg_test, imm4, disp16): """BLTI - Branch if the register is lower than imm4.""" # if(Rn< ZeroExt(imm4)) PC <- PC +SignExt((disp17)16..1||0) - (Signed comparison) dst = disp16 if compute_s_inf(reg_test, imm4) else ExprLoc(ir.get_next_break_loc_key(instr), 32) take_jmp = ExprInt(1, 32) if compute_s_inf(reg_test, imm4) else ExprInt(0, 32) PC = dst ir.IRDst = dst
def beqi(reg_test, imm4, disp16): """BEQI - Branch if the register stores imm4.""" # if(Rn==ZeroExt(imm4)) PC <- PC +SignExt((disp17)16..1||0) dst = ExprLoc(ir.get_next_break_loc_key(instr), 32) if (reg_test - imm4) else disp16 take_jmp = ExprInt(0, 32) if (reg_test - imm4) else ExprInt(1, 32) PC = dst ir.IRDst = dst
def bnei(reg_test, imm4, disp16): """BNEI - Branch if the register does not store imm4.""" # if(Rn!=ZeroExt(imm4)) PC <- PC+SignExt((disp17)16..1||0) dst = disp16 if (reg_test - imm4) else ExprLoc(ir.get_next_break_loc_key(instr), 32) take_jmp = ExprInt(1, 32) if (reg_test - imm4) else ExprInt(0, 32) PC = dst ir.IRDst = dst
def bnez(reg_test, disp8): """BNEZ - Branch if the register does not store zero.""" # if(Rn!=0) PC <- PC + SignExt((disp8)7..1||0) dst = disp8 if reg_test else ExprLoc(ir.get_next_break_loc_key(instr), 32) take_jmp = ExprInt(1, 32) if reg_test else ExprInt(0, 32) PC = dst ir.IRDst = dst
def beqz(reg_test, disp8): """BEQZ - Branch if the register stores zero.""" # if(Rn==0) PC <- PC +SignExt((disp8)7..1||0) dst = ExprLoc(ir.get_next_break_loc_key(instr), 32) if reg_test else disp8 take_jmp = ExprInt(0, 32) if reg_test else ExprInt(1, 32) PC = dst ir.IRDst = dst
def test_lwcpi(self): """Test LWCPI execution""" # LWCPI CRn[0-15],(Rm+) exec_instruction("LWCPI C1, (R2+)", [(ExprId("R2", 32), ExprInt(0x11, 32)), (ExprMem(ExprInt(0x10, 32), 32), ExprInt(0xABCD, 32))], [(ExprId("C1", 32), ExprInt(0xABCD, 32)), (ExprId("R2", 32), ExprInt(0x15, 32))])
def bgei(reg_test, imm4, disp16): """BGEI - Branch if the register is greater or equal to imm4.""" # if(Rn>=ZeroExt(imm4)) PC <- PC +SignExt((disp17)16..1||0) - (Signed comparison) cond = i32(1) if ExprOp(TOK_EQUAL, reg_test, imm4) else compute_s_inf(imm4, reg_test).zeroExtend(32) dst = disp16 if cond else ExprLoc(ir.get_next_break_loc_key(instr), 32) take_jmp = ExprInt(1, 32) if cond else ExprInt(0, 32) PC = dst ir.IRDst = dst
def test_movh(self): """Test MOVH execution""" # MOVH Rn,imm16 exec_instruction("MOVH R1, 1", [], [(ExprId("R1", 32), ExprInt(0x10000, 32))]) exec_instruction("MOVH R1, 0xFFFF", [], [(ExprId("R1", 32), ExprInt(0xFFFF0000, 32))])
def test_smcpi(self): """Test SMCPI execution""" # SMCPI CRn[0-15],(Rm+) exec_instruction("SMCPI C1, (R2+)", [(ExprId("C1", 32), ExprInt(0x28071010, 32)), (ExprId("R2", 32), ExprInt(0x17, 32))], [(ExprMem(ExprInt(0x10, 32), 32), ExprInt(0x28071010, 32)), (ExprId("R2", 32), ExprInt(0x1F, 32))])
def check(self): regs = self.dse.lifter.arch.regs value = self.dse.eval_expr(regs.EDX) # The expected value should contains '<<', showing it has been in the # corresponding generated label expected = ExprOp( '<<', regs.EDX, ExprCompose(regs.ECX[0:8], ExprInt(0x0, 24)) & ExprInt(0x1F, 32)) assert value == expected