From 18a93f4049f6f9a72eb52aaeac13571f7b18c41a Mon Sep 17 00:00:00 2001 From: woni <81616747+W0ni@users.noreply.github.com> Date: Wed, 6 Sep 2023 18:19:56 +0200 Subject: [PATCH 1/5] Add shifters for instructions that use shifter carry --- miasm/arch/arm/sem.py | 230 ++++++++++++++++++++++++++++-------------- 1 file changed, 154 insertions(+), 76 deletions(-) diff --git a/miasm/arch/arm/sem.py b/miasm/arch/arm/sem.py index e507a0456..0c6234751 100644 --- a/miasm/arch/arm/sem.py +++ b/miasm/arch/arm/sem.py @@ -2,6 +2,7 @@ from future.utils import viewitems, viewvalues from miasm.expression.expression import * +from miasm.expression.simplifications import expr_simp from miasm.ir.ir import Lifter, IRBlock, AssignBlock from miasm.arch.arm.arch import mn_arm, mn_armt from miasm.arch.arm.regs import * @@ -253,6 +254,15 @@ def update_flag_zn(a): return e +# Instructions which use shifter's carry flag: ANDS, BICS, EORS, MOVS/RRX, MVNS, ORNS (TODO), ORRS, TEQ, TST +def compute_rrx_carry(operation): + """ + Returns a tuple (result, carry) corresponding to the RRX computation + @operation: The ExprOp operation + """ + new_cf = operation.args[0][:1] + res = ExprCompose(operation.args[0][1:], cf) + return res, new_cf # XXX TODO: set cf if ROT imm in argument @@ -272,12 +282,12 @@ def update_flag_add_of(op1, op2): def update_flag_sub_cf(op1, op2): - "Compote CF in @op1 - @op2" + "Compute CF in @op1 - @op2" return [ExprAssign(cf, ExprOp("FLAG_SUB_CF", op1, op2) ^ ExprInt(1, 1))] def update_flag_sub_of(op1, op2): - "Compote OF in @op1 - @op2" + "Compute OF in @op1 - @op2" return [ExprAssign(of, ExprOp("FLAG_SUB_OF", op1, op2))] @@ -424,11 +434,18 @@ def add(ir, instr, a, b, c=None): def l_and(ir, instr, a, b, c=None): - e = [] + setflags = (instr.name == 'ANDS') and a != PC if c is None: b, c = a, b + if c.is_op(): + e, extra_ir = _shift_rotate_tpl(ir, instr, a, c, onlyCarry=setflags) + # get back the result + c = e.pop(0).src + else: + e = [] + extra_ir = [] r = b & c - if instr.name == 'ANDS' and a != PC: + if setflags: e += [ExprAssign(zf, ExprOp('FLAG_EQ_AND', b, c))] e += update_flag_nf(r) @@ -436,8 +453,7 @@ def l_and(ir, instr, a, b, c=None): dst = get_dst(a) if dst is not None: e.append(ExprAssign(ir.IRDst, r)) - return e, [] - + return e, extra_ir def sub(ir, instr, a, b, c=None): e = [] @@ -479,9 +495,16 @@ def eor(ir, instr, a, b, c=None): def eors(ir, instr, a, b, c=None): - e = [] + setflags = a != PC if c is None: b, c = a, b + if c.is_op(): + e, extra_ir = _shift_rotate_tpl(ir, instr, a, c, onlyCarry=setflags) + # get back the result + c = e.pop(0).src + else: + e = [] + extra_ir = [] arg1, arg2 = b, c r = arg1 ^ arg2 @@ -492,7 +515,7 @@ def eors(ir, instr, a, b, c=None): dst = get_dst(a) if dst is not None: e.append(ExprAssign(ir.IRDst, r)) - return e, [] + return e, extra_ir def rsb(ir, instr, a, b, c=None): @@ -585,18 +608,32 @@ def rscs(ir, instr, a, b, c=None): def tst(ir, instr, a, b): - e = [] + setflags = a != PC + if b.is_op(): + e, extra_ir = _shift_rotate_tpl(ir, instr, a, b, onlyCarry=setflags) + # get back the result + b = e.pop(0).src + else: + e = [] + extra_ir = [] arg1, arg2 = a, b r = arg1 & arg2 e += [ExprAssign(zf, ExprOp('FLAG_EQ_AND', arg1, arg2))] e += update_flag_nf(r) - return e, [] + return e, extra_ir def teq(ir, instr, a, b, c=None): - e = [] + setflags = a != PC + if b.is_op(): + e, extra_ir = _shift_rotate_tpl(ir, instr, a, b, onlyCarry=setflags) + # get back the result + b = e.pop(0).src + else: + e = [] + extra_ir = [] if c is None: b, c = a, b arg1, arg2 = b, c @@ -605,7 +642,7 @@ def teq(ir, instr, a, b, c=None): e += [ExprAssign(zf, ExprOp('FLAG_EQ_CMP', arg1, arg2))] e += update_flag_nf(r) - return e, [] + return e, extra_ir def l_cmp(ir, instr, a, b, c=None): @@ -653,9 +690,16 @@ def orn(ir, instr, a, b, c=None): def orrs(ir, instr, a, b, c=None): - e = [] + setflags = a != PC if c is None: b, c = a, b + if c.is_op(): + e, extra_ir = _shift_rotate_tpl(ir, instr, a, c, onlyCarry=setflags) + # get back the result + c = e.pop(0).src + else: + e = [] + extra_ir = [] arg1, arg2 = b, c r = arg1 | arg2 @@ -666,10 +710,13 @@ def orrs(ir, instr, a, b, c=None): dst = get_dst(a) if dst is not None: e.append(ExprAssign(ir.IRDst, r)) - return e, [] + return e, extra_ir def mov(ir, instr, a, b): + if b.is_op(): + return _shift_rotate_tpl(ir, instr, a, b, setflags=False) + # TODO handle cf e = [ExprAssign(a, b)] dst = get_dst(a) if dst is not None: @@ -686,10 +733,78 @@ def movt(ir, instr, a, b): return e, [] +def _shift_rotate_tpl(ir, instr, dst, shift_operation, setflags=False, is_not=False, onlyCarry=False): + """ + Template to generate a shift/rotate + A temporary basic block is generated to handle 0-shift + @dst: destination + @shift_operation: the shift/rotate operation (ExprOp) + @setflags: (optional) if set, flags are updated (ZNC) + @onlyCarry: (optional) if set, Z and N flags won't be updated except if setflags is set. + @is_not: (optional) if set, behaves as MVN/MVNS + """ + op = shift_operation.op + # Compute carry (+ result for rrx) + if op == 'rrx': + res, new_cf = compute_rrx_carry(shift_operation) + shifter = ExprInt(1, 8) + elif op in ['<<', '>>', 'a>>']: + shifter = shift_operation.args[1] + if setflags or onlyCarry: + new_cf = ExprOp(op, shift_operation.args[0], shifter - ExprInt(1, size=shifter.size)) + left = op[-1] == '<' + new_cf = new_cf.msb() if left else new_cf[:1] + res = shift_operation + elif op == '>>>': + shifter = shift_operation.args[1] + if setflags or onlyCarry: + new_cf = shift_operation.msb() + res = shift_operation + else: + raise NotImplementedError(f"Unknown shift / rotate operation : {op}") + + # NOT the result and use it for ZN flags computations + if is_not: + res ^= ExprInt(-1, res.size) + # Build basic blocks + e_do = [] + e = [ExprAssign(dst, res)] + if setflags: + e += update_flag_zn(res) + if setflags or onlyCarry: + e_do += [ExprAssign(cf, expr_simp(new_cf))] + # Don't generate conditional shifter on constant + if shifter.is_int(): + if shifter.is_int(0): + # assignement + flags if setflags except cf + return (e, []) + else: + # assignement + flags if setflags + return (e + e_do, []) + + loc_do, loc_do_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) + loc_skip = ir.get_next_loc_key(instr) + loc_skip_expr = ExprLoc(loc_skip, ir.IRDst.size) + isPC = get_dst(dst) + if isPC is not None: + # Not really a Loc in this case + loc_skip_expr = res + e_do.append(ExprAssign(ir.IRDst, loc_skip_expr)) + e.append(ExprAssign( + ir.IRDst, ExprCond(shifter, loc_do_expr, loc_skip_expr))) + return (e, [IRBlock(ir.loc_db, loc_do, [AssignBlock(e_do, instr)])]) + + + def movs(ir, instr, a, b): e = [] + # handle shift / rotate + if b.is_op(): + return _shift_rotate_tpl(ir, instr, a, b, setflags=a != PC) + + e.append(ExprAssign(a, b)) - # XXX TODO check + # TODO handle cf e += [ExprAssign(zf, ExprOp('FLAG_EQ', b))] e += update_flag_nf(b) @@ -700,7 +815,10 @@ def movs(ir, instr, a, b): def mvn(ir, instr, a, b): + if b.is_op(): + return _shift_rotate_tpl(ir, instr, a, b, setflags=False, is_not=True) r = b ^ ExprInt(-1, 32) + # TODO handle cf e = [ExprAssign(a, r)] dst = get_dst(a) if dst is not None: @@ -709,10 +827,12 @@ def mvn(ir, instr, a, b): def mvns(ir, instr, a, b): + if b.is_op(): + return _shift_rotate_tpl(ir, instr, a, b, setflags= a != PC, is_not=True) e = [] r = b ^ ExprInt(-1, 32) e.append(ExprAssign(a, r)) - # XXX TODO check + # TODO handle cf e += [ExprAssign(zf, ExprOp('FLAG_EQ', r))] e += update_flag_nf(r) @@ -774,9 +894,16 @@ def bic(ir, instr, a, b, c=None): def bics(ir, instr, a, b, c=None): - e = [] + setflags = a != PC if c is None: b, c = a, b + if c.is_op(): + e, extra_ir = _shift_rotate_tpl(ir, instr, a, c, onlyCarry=setflags) + # get back the result + c = e.pop(0).src + else: + e = [] + extra_ir = [] tmp1, tmp2 = b, ~c r = tmp1 & tmp2 @@ -787,7 +914,7 @@ def bics(ir, instr, a, b, c=None): dst = get_dst(a) if dst is not None: e.append(ExprAssign(ir.IRDst, r)) - return e, [] + return e, extra_ir def sdiv(ir, instr, a, b, c=None): @@ -1169,100 +1296,53 @@ def und(ir, instr, a, b): e = [] return e, [] -# TODO XXX implement correct CF for shifters def lsr(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b - r = b >> c - e.append(ExprAssign(a, r)) - dst = get_dst(a) - if dst is not None: - e.append(ExprAssign(ir.IRDst, r)) - return e, [] + return _shift_rotate_tpl(ir, instr, a, b >> c, setflags=False) def lsrs(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b - r = b >> c - e.append(ExprAssign(a, r)) - - e += [ExprAssign(zf, ExprOp('FLAG_EQ', r))] - e += update_flag_nf(r) - - dst = get_dst(a) - if dst is not None: - e.append(ExprAssign(ir.IRDst, r)) - return e, [] + return _shift_rotate_tpl(ir, instr, a, b >> c, setflags= a != PC) def asr(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b r = ExprOp("a>>", b, c) - e.append(ExprAssign(a, r)) - dst = get_dst(a) - if dst is not None: - e.append(ExprAssign(ir.IRDst, r)) - return e, [] + return _shift_rotate_tpl(ir, instr, a, r, setflags=False) def asrs(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b r = ExprOp("a>>", b, c) - e.append(ExprAssign(a, r)) - - e += [ExprAssign(zf, ExprOp('FLAG_EQ', r))] - e += update_flag_nf(r) - - dst = get_dst(a) - if dst is not None: - e.append(ExprAssign(ir.IRDst, r)) - return e, [] + return _shift_rotate_tpl(ir, instr, a, r, setflags= a != PC) def lsl(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b - r = b << c - e.append(ExprAssign(a, r)) - dst = get_dst(a) - if dst is not None: - e.append(ExprAssign(ir.IRDst, r)) - return e, [] + return _shift_rotate_tpl(ir, instr, a, b << c, setflags=False) + def lsls(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b - r = b << c - e.append(ExprAssign(a, r)) - - e += [ExprAssign(zf, ExprOp('FLAG_EQ', r))] - e += update_flag_nf(r) - - dst = get_dst(a) - if dst is not None: - e.append(ExprAssign(ir.IRDst, r)) - return e, [] + return _shift_rotate_tpl(ir, instr, a, b << c, setflags= a != PC) def rors(ir, instr, a, b): e = [] r = ExprOp(">>>", a, b) - e.append(ExprAssign(a, r)) - - e += [ExprAssign(zf, ExprOp('FLAG_EQ', r))] - e += update_flag_nf(r) + return _shift_rotate_tpl(ir, instr, a, r, setflags= a != PC) - dst = get_dst(a) - if dst is not None: - e.append(ExprAssign(ir.IRDst, r)) - return e, [] def push(ir, instr, a): @@ -1962,9 +2042,7 @@ def get_ir(self, instr): args = instr.args # ir = get_mnemo_expr(self, self.name.lower(), *args) if len(args) and isinstance(args[-1], ExprOp): - if args[-1].op == 'rrx': - args[-1] = ExprCompose(args[-1].args[0][1:], cf) - elif (args[-1].op in ['<<', '>>', '<>', '<<<', '>>>'] and + if (args[-1].op in ['<<', '>>', '<>', '<<<', '>>>'] and isinstance(args[-1].args[-1], ExprId)): args[-1] = ExprOp(args[-1].op, args[-1].args[0], From bb53a4505ab43662d5ebb9349ecda93eacaa447c Mon Sep 17 00:00:00 2001 From: woni <81616747+W0ni@users.noreply.github.com> Date: Wed, 6 Sep 2023 18:22:39 +0200 Subject: [PATCH 2/5] Add RRX support inside instructions --- miasm/arch/arm/sem.py | 50 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/miasm/arch/arm/sem.py b/miasm/arch/arm/sem.py index 0c6234751..156d8374f 100644 --- a/miasm/arch/arm/sem.py +++ b/miasm/arch/arm/sem.py @@ -405,6 +405,8 @@ def adc(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) arg1, arg2 = b, c r = b + c + cf.zeroExtend(32) if instr.name == 'ADCS' and a != PC: @@ -421,6 +423,8 @@ def add(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) arg1, arg2 = b, c r = b + c if instr.name == 'ADDS' and a != PC: @@ -459,6 +463,8 @@ def sub(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) r = b - c e.append(ExprAssign(a, r)) dst = get_dst(a) @@ -471,6 +477,8 @@ def subs(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) arg1, arg2 = b, c r = b - c e += update_flag_arith_sub_zn(arg1, arg2) @@ -486,6 +494,8 @@ def eor(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) r = b ^ c e.append(ExprAssign(a, r)) dst = get_dst(a) @@ -522,6 +532,8 @@ def rsb(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) arg1, arg2 = c, b r = arg1 - arg2 e.append(ExprAssign(a, r)) @@ -535,6 +547,8 @@ def rsbs(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) arg1, arg2 = c, b r = arg1 - arg2 e += update_flag_arith_sub_zn(arg1, arg2) @@ -550,6 +564,8 @@ def sbc(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) arg1, arg2 = b, c r = arg1 - (arg2 + (~cf).zeroExtend(32)) e.append(ExprAssign(a, r)) @@ -563,6 +579,8 @@ def sbcs(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) arg1, arg2 = b, c r = arg1 - (arg2 + (~cf).zeroExtend(32)) @@ -580,6 +598,8 @@ def rsc(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) arg1, arg2 = c, b r = arg1 - (arg2 + (~cf).zeroExtend(32)) e.append(ExprAssign(a, r)) @@ -593,6 +613,8 @@ def rscs(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) arg1, arg2 = c, b r = arg1 - (arg2 + (~cf).zeroExtend(32)) @@ -659,6 +681,8 @@ def cmn(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) arg1, arg2 = b, c e += update_flag_arith_add_zn(arg1, arg2) e += update_flag_arith_add_co(arg1, arg2) @@ -669,6 +693,8 @@ def orr(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) r = b | c e.append(ExprAssign(a, r)) dst = get_dst(a) @@ -681,6 +707,8 @@ def orn(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) r = ~(b | c) e.append(ExprAssign(a, r)) dst = get_dst(a) @@ -885,6 +913,8 @@ def bic(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) r = b & (c ^ ExprInt(-1, 32)) e.append(ExprAssign(a, r)) dst = get_dst(a) @@ -921,6 +951,8 @@ def sdiv(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) loc_div = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) loc_except = ExprId(ir.loc_db.add_location(), ir.IRDst.size) @@ -952,6 +984,8 @@ def udiv(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) @@ -1015,6 +1049,8 @@ def mul(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) r = b * c e.append(ExprAssign(a, r)) dst = get_dst(a) @@ -1027,6 +1063,8 @@ def muls(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) r = b * c e += update_flag_zn(r) e.append(ExprAssign(a, r)) @@ -1300,6 +1338,8 @@ def lsr(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) return _shift_rotate_tpl(ir, instr, a, b >> c, setflags=False) @@ -1307,12 +1347,16 @@ def lsrs(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) return _shift_rotate_tpl(ir, instr, a, b >> c, setflags= a != PC) def asr(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) r = ExprOp("a>>", b, c) return _shift_rotate_tpl(ir, instr, a, r, setflags=False) @@ -1320,6 +1364,8 @@ def asrs(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) r = ExprOp("a>>", b, c) return _shift_rotate_tpl(ir, instr, a, r, setflags= a != PC) @@ -1327,6 +1373,8 @@ def lsl(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) return _shift_rotate_tpl(ir, instr, a, b << c, setflags=False) @@ -1335,6 +1383,8 @@ def lsls(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b + if c.is_op('rrx'): + c, _ = compute_rrx_carry(c) return _shift_rotate_tpl(ir, instr, a, b << c, setflags= a != PC) From 71e4e09da6816a72905adeea3c0864714353c406 Mon Sep 17 00:00:00 2001 From: woni <81616747+W0ni@users.noreply.github.com> Date: Wed, 13 Sep 2023 10:34:16 +0200 Subject: [PATCH 3/5] Fix disassembly bug --- miasm/arch/arm/arch.py | 4 ++++ test/arch/arm/sem.py | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/miasm/arch/arm/arch.py b/miasm/arch/arm/arch.py index 5ccf5ecab..91c22bd59 100644 --- a/miasm/arch/arm/arch.py +++ b/miasm/arch/arm/arch.py @@ -1148,8 +1148,12 @@ def decode(self, v): shift_op = ExprInt(amount, 32) a = regs_expr[rm] if shift_op == ExprInt(0, 32): + #rrx if shift_type == 3: self.expr = ExprOp(allshifts[4], a) + #asr, lsr + elif shift_type == 1 or shift_type == 2: + self.expr = ExprOp(allshifts[shift_type], a, ExprInt(32, 32)) else: self.expr = a else: diff --git a/test/arch/arm/sem.py b/test/arch/arm/sem.py index a5b6d5eb7..c80b471d8 100755 --- a/test/arch/arm/sem.py +++ b/test/arch/arm/sem.py @@ -81,7 +81,7 @@ def test_shift(self): self.assertEqual( compute('MOV R4, R4 LSR 31', {R4: 0xDEADBEEF, }), {R4: 0x00000001, }) self.assertEqual( - compute('MOV R4, R4 LSR 32', {R4: 0xDEADBEEF, }), {R4: 0xDEADBEEF, }) + compute('MOV R4, R4 LSR 32', {R4: 0xDEADBEEF, }), {R4: 0x0, }) self.assertRaises(ValueError, compute, 'MOV R4, R4 LSR 33') self.assertEqual( compute('MOV R4, R4 LSR R5', {R4: 0xDEADBEEF, R5: 0xBADBAD01, }), {R4: 0x6F56DF77, R5: 0xBADBAD01, }) @@ -93,7 +93,7 @@ def test_shift(self): self.assertEqual( compute('MOV R4, R4 ASR 31', {R4: 0xDEADBEEF, }), {R4: 0xFFFFFFFF, }) self.assertEqual( - compute('MOV R4, R4 ASR 32', {R4: 0xDEADBEEF, }), {R4: 0xDEADBEEF, }) + compute('MOV R4, R4 ASR 32', {R4: 0xDEADBEEF, }), {R4: 0xFFFFFFFF, }) self.assertRaises(ValueError, compute, 'MOV R4, R4 ASR 33') self.assertEqual( compute('MOV R4, R4 ASR R5', {R4: 0xDEADBEEF, R5: 0xBADBAD01, }), {R4: 0xEF56DF77, R5: 0xBADBAD01, }) From 1885f3caa96cd953e6f90a33b5d3863808cbcf40 Mon Sep 17 00:00:00 2001 From: woni <81616747+W0ni@users.noreply.github.com> Date: Wed, 13 Sep 2023 12:39:41 +0200 Subject: [PATCH 4/5] Add tests for MOVS and isThumb utility function --- miasm/arch/arm/sem.py | 3 +++ test/arch/arm/sem.py | 51 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/miasm/arch/arm/sem.py b/miasm/arch/arm/sem.py index 156d8374f..a138ef919 100644 --- a/miasm/arch/arm/sem.py +++ b/miasm/arch/arm/sem.py @@ -391,6 +391,9 @@ def update_flag_arith_subwc_co(arg1, arg2, arg3): e += update_flag_subwc_of(arg1, arg2, arg3) return e +# Utility function for flag computation when it depends on the mode +def isThumb(lifter): + return isinstance(lifter, (Lifter_Armtl, Lifter_Armtb)) def get_dst(a): diff --git a/test/arch/arm/sem.py b/test/arch/arm/sem.py index c80b471d8..343bc063f 100755 --- a/test/arch/arm/sem.py +++ b/test/arch/arm/sem.py @@ -111,6 +111,57 @@ def test_shift(self): cf: 0, R4: 0x6F56DF77, }) self.assertEqual(compute('MOV R4, R4 RRX ', {cf: 1, R4: 0xDEADBEEF, }), { cf: 1, R4: 0xEF56DF77, }) + # S + self.assertEqual( + compute('MOVS R4, R4 ', {R4: 0xDEADBEEF, }), {R4: 0xDEADBEEF, nf: 1, zf: 0,}) + self.assertRaises(ValueError, compute, 'MOVS R4, R4 LSL 0') + self.assertEqual( + compute('MOVS R4, R4 LSL 1', {R4: 0xDEADBEEF, }), {R4: 0xBD5B7DDE, nf: 1, zf: 0, cf: 1,}) + self.assertEqual( + compute('MOVS R4, R4 LSL 16', {R4: 0xDEADBEEF, }), {R4: 0xBEEF0000, nf: 1, zf: 0, cf: 1,}) + self.assertEqual( + compute('MOVS R4, R4 LSL 31', {R4: 0xDEADBEEF, }), {R4: 0x80000000, nf: 1, zf: 0, cf: 1,}) + self.assertRaises(ValueError, compute, 'MOVS R4, R4 LSL 32') + self.assertEqual( + compute('MOVS R4, R4 LSL R5', {R4: 0xDEADBEEF, R5: 0xBADBAD01, }), {R4: 0xBD5B7DDE, R5: 0xBADBAD01, nf: 1, zf: 0, cf: 1,}) + self.assertRaises(ValueError, compute, 'MOVS R4, R4 LSR 0') + self.assertEqual( + compute('MOVS R4, R4 LSR 1', {R4: 0xDEADBEEF, }), {R4: 0x6F56DF77, nf: 0, zf: 0, cf: 1,}) + self.assertEqual( + compute('MOVS R4, R4 LSR 16', {R4: 0xDEADBEEF, }), {R4: 0x0000DEAD, nf: 0, zf: 0, cf: 1,}) + self.assertEqual( + compute('MOVS R4, R4 LSR 31', {R4: 0xDEADBEEF, }), {R4: 0x00000001, nf: 0, zf: 0, cf: 1,}) + self.assertEqual( + compute('MOVS R4, R4 LSR 32', {R4: 0xDEADBEEF, }), {R4: 0x0, nf: 0, zf: 1, cf: 1,}) + self.assertRaises(ValueError, compute, 'MOVS R4, R4 LSR 33') + self.assertEqual( + compute('MOVS R4, R4 LSR R5', {R4: 0xDEADBEEF, R5: 0xBADBAD01, }), {R4: 0x6F56DF77, R5: 0xBADBAD01, nf: 0, zf: 0, cf: 1,}) + self.assertRaises(ValueError, compute, 'MOVS R4, R4 ASR 0') + self.assertEqual( + compute('MOVS R4, R4 ASR 1', {R4: 0xDEADBEEF, }), {R4: 0xEF56DF77, nf: 1, zf: 0, cf: 1,}) + self.assertEqual( + compute('MOVS R4, R4 ASR 16', {R4: 0xDEADBEEF, }), {R4: 0xFFFFDEAD, nf: 1, zf: 0, cf: 1,}) + self.assertEqual( + compute('MOVS R4, R4 ASR 31', {R4: 0xDEADBEEF, }), {R4: 0xFFFFFFFF, nf: 1, zf: 0, cf: 1,}) + self.assertEqual( + compute('MOVS R4, R4 ASR 32', {R4: 0xDEADBEEF, }), {R4: 0xFFFFFFFF, nf: 1, zf: 0, cf: 1,}) + self.assertRaises(ValueError, compute, 'MOVS R4, R4 ASR 33') + self.assertEqual( + compute('MOVS R4, R4 ASR R5', {R4: 0xDEADBEEF, R5: 0xBADBAD01, }), {R4: 0xEF56DF77, R5: 0xBADBAD01, nf: 1, zf: 0, cf: 1,}) + self.assertRaises(ValueError, compute, 'MOVS R4, R4 ROR 0') + self.assertEqual( + compute('MOVS R4, R4 ROR 1', {R4: 0xDEADBEEF, }), {R4: 0xEF56DF77, nf: 1, zf: 0, cf: 1,}) + self.assertEqual( + compute('MOVS R4, R4 ROR 16', {R4: 0xDEADBEEF, }), {R4: 0xBEEFDEAD, nf: 1, zf: 0, cf: 1,}) + self.assertEqual( + compute('MOVS R4, R4 ROR 31', {R4: 0xDEADBEEF, }), {R4: 0xBD5B7DDF, nf: 1, zf: 0, cf: 1,}) + self.assertRaises(ValueError, compute, 'MOVS R4, R4 ROR 32') + self.assertEqual( + compute('MOVS R4, R4 ROR R5', {R4: 0xDEADBEEF, R5: 0xBADBAD01, }), {R4: 0xEF56DF77, R5: 0xBADBAD01, nf: 1, zf: 0, cf: 1,}) + self.assertEqual(compute('MOVS R4, R4 RRX ', {cf: 0, R4: 0xDEADBEEF, }), { + cf: 1, R4: 0x6F56DF77, zf: 0, nf: 0}) + self.assertEqual(compute('MOVS R4, R4 RRX ', {cf: 1, R4: 0xDEADBEEF, }), { + cf: 1, R4: 0xEF56DF77, zf: 0, nf: 1}) def test_ADC(self): # §A8.8.1: ADC{S}{}{} {,} , # From 16cc7d3b374442808b1d653a0cc6c2477a4a750f Mon Sep 17 00:00:00 2001 From: woni <81616747+W0ni@users.noreply.github.com> Date: Thu, 14 Mar 2024 18:20:58 +0100 Subject: [PATCH 5/5] Add MOV and MOVS tests for [AL]SR --- test/arch/arm/arch.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/arch/arm/arch.py b/test/arch/arm/arch.py index 42e807722..a3f3a9742 100644 --- a/test/arch/arm/arch.py +++ b/test/arch/arm/arch.py @@ -241,7 +241,12 @@ def u16swap(i): '110f111e'), ('XXXXXXXX MCRCC p15, 0x0, R8, c2, c0, 0x1', '308f023e'), - + ('XXXXXXXX MOV R4, R4 ASR 0x20', + '4440a0e1'), + ('XXXXXXXX MOV R2, R5 LSR 0x20', + '2520a0e1'), + ('XXXXXXXX MOVS R2, R5 LSR 0x20', + '2520b0e1'), ] ts = time.time()