diff options
| -rw-r--r-- | .travis.yml | 21 | ||||
| -rw-r--r-- | miasm2/arch/aarch64/arch.py | 6 | ||||
| -rw-r--r-- | miasm2/arch/aarch64/sem.py | 74 | ||||
| -rw-r--r-- | miasm2/core/bin_stream_ida.py | 6 | ||||
| -rw-r--r-- | miasm2/expression/simplifications.py | 10 | ||||
| -rw-r--r-- | miasm2/expression/simplifications_common.py | 417 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_aarch64.c | 8 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_arm.c | 9 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_mep.c | 9 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_msp430.c | 7 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_ppc32.c | 7 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_x86.c | 28 | ||||
| -rw-r--r-- | miasm2/jitter/jitcore.py | 12 | ||||
| -rw-r--r-- | miasm2/jitter/jitcore_python.py | 209 | ||||
| -rw-r--r-- | miasm2/jitter/llvmconvert.py | 2 | ||||
| -rw-r--r-- | miasm2/jitter/vm_mngr_py.c | 4 | ||||
| -rw-r--r-- | test/arch/aarch64/arch.py | 20 | ||||
| -rw-r--r-- | test/expression/simplifications.py | 176 | ||||
| -rwxr-xr-x | test/test_all.py | 5 |
19 files changed, 851 insertions, 179 deletions
diff --git a/.travis.yml b/.travis.yml index 8253cb24..f5c55368 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,14 +11,17 @@ addons: env: global: CXX=g++-5 LLVM_CONFIG=llvm-config-6.0 matrix: - - MIASM_TEST_TAG=regression - - MIASM_TEST_TAG=example - - MIASM_TEST_TAG=long - - MIASM_TEST_TAG=llvm - - MIASM_TEST_TAG=gcc - - MIASM_TEST_TAG=z3 - - MIASM_TEST_TAG=qemu - - MIASM_TEST_TAG=cparser + - MIASM_TEST_EXTRA_ARG="-o regression -t long,python,llvm,gcc,z3,qemu,cparser" + - MIASM_TEST_EXTRA_ARG="-o example -t long,python,llvm,gcc,z3,qemu,cparser" + - MIASM_TEST_EXTRA_ARG="-o long" + - MIASM_TEST_EXTRA_ARG="-o qemu -t llvm,gcc" + - MIASM_TEST_EXTRA_ARG="-o qemu -t python,gcc" + - MIASM_TEST_EXTRA_ARG="-o qemu -t python,llvm" + - MIASM_TEST_EXTRA_ARG="-o llvm -t qemu,long" + - MIASM_TEST_EXTRA_ARG="-o gcc -t qemu,long" + - MIASM_TEST_EXTRA_ARG="-o python -t qemu,long" + - MIASM_TEST_EXTRA_ARG="-o z3" + - MIASM_TEST_EXTRA_ARG="-o cparser" before_script: - pip install -r optional_requirements.txt # codespell @@ -28,4 +31,4 @@ before_script: # install - python setup.py build build_ext - python setup.py install -script: cd test && python test_all.py -o=$MIASM_TEST_TAG && git ls-files -o --exclude-standard +script: cd test && python test_all.py $MIASM_TEST_EXTRA_ARG && git ls-files -o --exclude-standard diff --git a/miasm2/arch/aarch64/arch.py b/miasm2/arch/aarch64/arch.py index 38cffc47..91554233 100644 --- a/miasm2/arch/aarch64/arch.py +++ b/miasm2/arch/aarch64/arch.py @@ -2155,3 +2155,9 @@ aarch64op("stlxp", [bs('1'), sf, bs('001000'), bs('0'), bs('0'), bs('1'), rs32, aarch64op("dsb", [bs('1101010100'), bs('0000110011'), crm, bs('1'), bs('00'), bs('11111')], [crm]) aarch64op("dmb", [bs('1101010100'), bs('0000110011'), crm, bs('1'), bs('01'), bs('11111')], [crm]) aarch64op("isb", [bs('1101010100'), bs('0000110011'), crm, bs('1'), bs('10'), bs('11111')], [crm]) + +stacctype = bs_mod_name(l=1, fname='order', mn_mod=['', 'L']) +ltacctype = bs_mod_name(l=1, fname='order', mn_mod=['', 'A']) + + +aarch64op("casp", [bs('0'), sf, bs('001000'), bs('0'), ltacctype, bs('1'), rs, stacctype, bs('11111'), rn64_deref_nooff, rt], [rs, rt, rn64_deref_nooff]) diff --git a/miasm2/arch/aarch64/sem.py b/miasm2/arch/aarch64/sem.py index 0a03a151..e4702a4f 100644 --- a/miasm2/arch/aarch64/sem.py +++ b/miasm2/arch/aarch64/sem.py @@ -1200,6 +1200,74 @@ def clz(ir, instr, arg1, arg2): e.append(ExprAssign(arg1, ExprOp('cntleadzeros', arg2))) return e, [] +def casp(ir, instr, arg1, arg2, arg3): + # XXX TODO: memory barrier + e = [] + if arg1.size == 32: + regs = gpregs32_expr + else: + regs = gpregs64_expr + index1 = regs.index(arg1) + index2 = regs.index(arg2) + + # TODO endianness + comp_value = ExprCompose(regs[index1], regs[index1 + 1]) + new_value = ExprCompose(regs[index2], regs[index2 + 1]) + assert arg3.is_op('preinc') + ptr = arg3.args[0] + data = ExprMem(ptr, comp_value.size) + + loc_store = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) + loc_do = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) + loc_next = ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) + + e.append(ExprAssign(ir.IRDst, ExprCond(ExprOp("FLAG_EQ_CMP", data, comp_value), loc_do, loc_store))) + + e_store = [] + e_store.append(ExprAssign(data, new_value)) + e_store.append(ExprAssign(ir.IRDst, loc_do)) + blk_store = IRBlock(loc_store.loc_key, [AssignBlock(e_store, instr)]) + + e_do = [] + e_do.append(ExprAssign(regs[index1], data[:data.size / 2])) + e_do.append(ExprAssign(regs[index1 + 1], data[data.size / 2:])) + e_do.append(ExprAssign(ir.IRDst, loc_next)) + blk_do = IRBlock(loc_do.loc_key, [AssignBlock(e_do, instr)]) + + return e, [blk_store, blk_do] + + +@sbuild.parse +def umaddl(arg1, arg2, arg3, arg4): + arg1 = arg2.zeroExtend(arg1.size) * arg3.zeroExtend(arg1.size) + arg4 + + +@sbuild.parse +def umsubbl(arg1, arg2, arg3, arg4): + arg1 = arg2.zeroExtend(arg1.size) * arg3.zeroExtend(arg1.size) + arg4 + + +@sbuild.parse +def umull(arg1, arg2, arg3): + arg1 = (arg2.zeroExtend(64) * arg3.zeroExtend(64)) + + +@sbuild.parse +def umulh(arg1, arg2, arg3): + arg1 = (arg2.zeroExtend(128) * arg3.zeroExtend(128))[64:] + + +@sbuild.parse +def smulh(arg1, arg2, arg3): + arg1 = (arg2.signExtend(128) * arg3.signExtend(128))[64:] + + +@sbuild.parse +def smull(arg1, arg2, arg3): + arg1 = (arg2.signExtend(64) * arg3.signExtend(64))[64:] + + + mnemo_func = sbuild.functions mnemo_func.update({ 'and': and_l, @@ -1292,6 +1360,12 @@ mnemo_func.update({ 'fcmpe': fcmpe, 'clz': clz, + # XXX TODO: memory barrier + 'casp':casp, + 'caspl':casp, + 'caspa':casp, + 'caspal':casp, + }) diff --git a/miasm2/core/bin_stream_ida.py b/miasm2/core/bin_stream_ida.py index de7bc971..f63077bf 100644 --- a/miasm2/core/bin_stream_ida.py +++ b/miasm2/core/bin_stream_ida.py @@ -1,5 +1,6 @@ from idc import Byte, SegEnd from idautils import Segments +from idaapi import is_mapped from miasm2.core.bin_stream import bin_stream_str @@ -14,7 +15,10 @@ class bin_stream_ida(bin_stream_str): def _getbytes(self, start, l=1): o = "" for ad in xrange(l): - o += chr(Byte(ad + start - self.shift)) + offset = ad + start - self.shift + if not is_mapped(offset): + raise IOError("not enough bytes") + o += chr(Byte(offset)) return o def readbs(self, l=1): diff --git a/miasm2/expression/simplifications.py b/miasm2/expression/simplifications.py index 3f50fc1a..8ea9c41f 100644 --- a/miasm2/expression/simplifications.py +++ b/miasm2/expression/simplifications.py @@ -49,24 +49,32 @@ class ExpressionSimplifier(object): simplifications_common.simp_ext_eq_ext, simplifications_common.simp_cmp_int, + simplifications_common.simp_sign_inf_zeroext, simplifications_common.simp_cmp_int_int, simplifications_common.simp_ext_cst, + simplifications_common.simp_zeroext_and_cst_eq_cst, + simplifications_common.simp_test_signext_inf, + simplifications_common.simp_test_zeroext_inf, ], m2_expr.ExprSlice: [ simplifications_common.simp_slice, simplifications_common.simp_slice_of_ext, + simplifications_common.simp_slice_of_op_ext, ], m2_expr.ExprCompose: [simplifications_common.simp_compose], m2_expr.ExprCond: [ simplifications_common.simp_cond, + simplifications_common.simp_cond_zeroext, # CC op simplifications_common.simp_cond_flag, simplifications_common.simp_cmp_int_arg, simplifications_common.simp_cond_eq_zero, - + simplifications_common.simp_x_and_cst_eq_cst, + simplifications_common.simp_cond_logic_ext, + simplifications_common.simp_cond_sign_bit, ], m2_expr.ExprMem: [simplifications_common.simp_mem], diff --git a/miasm2/expression/simplifications_common.py b/miasm2/expression/simplifications_common.py index ab0f7ad9..f7171091 100644 --- a/miasm2/expression/simplifications_common.py +++ b/miasm2/expression/simplifications_common.py @@ -382,7 +382,7 @@ def simp_cst_propagation(e_s, expr): return ExprOp(op_name, *args) -def simp_cond_op_int(e_s, expr): +def simp_cond_op_int(_, expr): "Extract conditions from operations" @@ -606,10 +606,11 @@ def simp_compose(e_s, expr): return ExprCompose(*args) -def simp_cond(e_s, expr): - "Common simplifications on ExprCond" - # eval exprcond src1/src2 with satifiable/unsatisfiable condition - # propagation +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)}) @@ -666,10 +667,11 @@ def simp_cond(e_s, expr): return expr -def simp_mem(e_s, expr): - "Common simplifications on ExprMem" - - # @32[x?a:b] => x?@32[a]:@32[b] +def simp_mem(_, expr): + """ + Common simplifications on ExprMem: + @32[x?a:b] => x?@32[a]:@32[b] + """ if expr.ptr.is_cond(): cond = expr.ptr ret = ExprCond(cond.cond, @@ -682,6 +684,15 @@ def simp_mem(e_s, expr): def test_cc_eq_args(expr, *sons_op): + """ + Return True if expression's arguments match the list in sons_op, and their + sub arguments are identical. Ex: + CC_S<=( + FLAG_SIGN_SUB(A, B), + FLAG_SUB_OF(A, B), + FLAG_EQ_CMP(A, B) + ) + """ if not expr.is_op(): return False if len(expr.args) != len(sons_op): @@ -694,7 +705,11 @@ def test_cc_eq_args(expr, *sons_op): return len(all_args) == 1 -def simp_cc_conds(expr_simp, expr): +def simp_cc_conds(_, expr): + """ + High level simplifications. Example: + CC_U<(FLAG_SUB_CF(A, B) => A <u B + """ if (expr.is_op("CC_U>=") and test_cc_eq_args( expr, @@ -702,8 +717,8 @@ def simp_cc_conds(expr_simp, expr): )): expr = ExprCond( ExprOp(TOK_INF_UNSIGNED, *expr.args[0].args), - ExprInt(0, 1), - ExprInt(1, 1)) + ExprInt(0, expr.size), + ExprInt(1, expr.size)) elif (expr.is_op("CC_U<") and test_cc_eq_args( @@ -726,8 +741,8 @@ def simp_cc_conds(expr_simp, expr): )): expr = ExprCond( ExprOp(TOK_INF_SIGNED, *expr.args[0].args), - ExprInt(0, 1), - ExprInt(1, 1) + ExprInt(0, expr.size), + ExprInt(1, expr.size) ) elif (expr.is_op("CC_EQ") and @@ -746,8 +761,8 @@ def simp_cc_conds(expr_simp, expr): arg = expr.args[0].args[0] expr = ExprCond( ExprOp(TOK_EQUAL,arg, ExprInt(0, arg.size)), - ExprInt(0, 1), - ExprInt(1, 1) + ExprInt(0, expr.size), + ExprInt(1, expr.size) ) elif (expr.is_op("CC_NE") and test_cc_eq_args( @@ -756,8 +771,8 @@ def simp_cc_conds(expr_simp, expr): )): expr = ExprCond( ExprOp(TOK_EQUAL, *expr.args[0].args), - ExprInt(0, 1), - ExprInt(1, 1) + ExprInt(0, expr.size), + ExprInt(1, expr.size) ) elif (expr.is_op("CC_EQ") and @@ -781,8 +796,8 @@ def simp_cc_conds(expr_simp, expr): )): expr = ExprCond( ExprOp("&", *expr.args[0].args), - ExprInt(0, 1), - ExprInt(1, 1) + ExprInt(0, expr.size), + ExprInt(1, expr.size) ) elif (expr.is_op("CC_S>") and @@ -794,8 +809,8 @@ def simp_cc_conds(expr_simp, expr): )): expr = ExprCond( ExprOp(TOK_INF_EQUAL_SIGNED, *expr.args[0].args), - ExprInt(0, 1), - ExprInt(1, 1) + ExprInt(0, expr.size), + ExprInt(1, expr.size) ) elif (expr.is_op("CC_S>") and @@ -806,8 +821,8 @@ def simp_cc_conds(expr_simp, expr): expr.args[1].is_int(0)): expr = ExprCond( ExprOp(TOK_INF_EQUAL_SIGNED, *expr.args[0].args), - ExprInt(0, 1), - ExprInt(1, 1) + ExprInt(0, expr.size), + ExprInt(1, expr.size) ) @@ -820,8 +835,8 @@ def simp_cc_conds(expr_simp, expr): )): expr = ExprCond( ExprOp(TOK_INF_SIGNED, *expr.args[0].args), - ExprInt(0, 1), - ExprInt(1, 1) + ExprInt(0, expr.size), + ExprInt(1, expr.size) ) elif (expr.is_op("CC_S<") and @@ -865,8 +880,8 @@ def simp_cc_conds(expr_simp, expr): )): expr = ExprCond( ExprOp(TOK_INF_EQUAL_UNSIGNED, *expr.args[0].args), - ExprInt(0, 1), - ExprInt(1, 1) + ExprInt(0, expr.size), + ExprInt(1, expr.size) ) elif (expr.is_op("CC_S<") and @@ -882,8 +897,8 @@ def simp_cc_conds(expr_simp, expr): -def simp_cond_flag(expr_simp, expr): - # FLAG_EQ_CMP(X, Y)?A:B => (X == Y)?A:B +def simp_cond_flag(_, expr): + """FLAG_EQ_CMP(X, Y)?A:B => (X == Y)?A:B""" cond = expr.cond if cond.is_op("FLAG_EQ_CMP"): return ExprCond(ExprOp(TOK_EQUAL, *cond.args), expr.src1, expr.src2) @@ -891,8 +906,10 @@ def simp_cond_flag(expr_simp, expr): def simp_cmp_int(expr_simp, expr): - # ({X, 0} == int) => X == int[:] - # X + int1 == int2 => X == int2-int1 + """ + ({X, 0} == int) => X == int[:] + X + int1 == int2 => X == int2-int1 + """ if (expr.is_op(TOK_EQUAL) and expr.args[1].is_int() and expr.args[0].is_compose() and @@ -931,7 +948,7 @@ def simp_cmp_int(expr_simp, expr): -def simp_cmp_int_arg(expr_simp, expr): +def simp_cmp_int_arg(_, expr): """ (0x10 <= R0) ? A:B => @@ -971,10 +988,8 @@ def simp_cmp_int_arg(expr_simp, expr): return ExprCond(ExprOp(op, arg1, arg2), src1, src2) - - -def simp_subwc_cf(expr_s, expr): - # SUBWC_CF(A, B, SUB_CF(C, D)) => SUB_CF({A, C}, {B, D}) +def simp_subwc_cf(_, expr): + """SUBWC_CF(A, B, SUB_CF(C, D)) => SUB_CF({A, C}, {B, D})""" if not expr.is_op('FLAG_SUBWC_CF'): return expr op3 = expr.args[2] @@ -987,8 +1002,8 @@ def simp_subwc_cf(expr_s, expr): return ExprOp("FLAG_SUB_CF", op1, op2) -def simp_subwc_of(expr_s, expr): - # SUBWC_OF(A, B, SUB_CF(C, D)) => SUB_OF({A, C}, {B, D}) +def simp_subwc_of(_, expr): + """SUBWC_OF(A, B, SUB_CF(C, D)) => SUB_OF({A, C}, {B, D})""" if not expr.is_op('FLAG_SUBWC_OF'): return expr op3 = expr.args[2] @@ -1001,8 +1016,8 @@ def simp_subwc_of(expr_s, expr): return ExprOp("FLAG_SUB_OF", op1, op2) -def simp_sign_subwc_cf(expr_s, expr): - # SIGN_SUBWC(A, B, SUB_CF(C, D)) => SIGN_SUB({A, C}, {B, D}) +def simp_sign_subwc_cf(_, expr): + """SIGN_SUBWC(A, B, SUB_CF(C, D)) => SIGN_SUB({A, C}, {B, D})""" if not expr.is_op('FLAG_SIGN_SUBWC'): return expr op3 = expr.args[2] @@ -1014,8 +1029,8 @@ def simp_sign_subwc_cf(expr_s, expr): return ExprOp("FLAG_SIGN_SUB", op1, op2) -def simp_double_zeroext(expr_s, expr): - # A.zeroExt(X).zeroExt(Y) => A.zeroExt(Y) +def simp_double_zeroext(_, expr): + """A.zeroExt(X).zeroExt(Y) => A.zeroExt(Y)""" if not (expr.is_op() and expr.op.startswith("zeroExt")): return expr arg1 = expr.args[0] @@ -1024,8 +1039,8 @@ def simp_double_zeroext(expr_s, expr): arg2 = arg1.args[0] return ExprOp(expr.op, arg2) -def simp_double_signext(expr_s, expr): - # A.signExt(X).signExt(Y) => A.signExt(Y) +def simp_double_signext(_, expr): + """A.signExt(X).signExt(Y) => A.signExt(Y)""" if not (expr.is_op() and expr.op.startswith("signExt")): return expr arg1 = expr.args[0] @@ -1034,8 +1049,8 @@ def simp_double_signext(expr_s, expr): arg2 = arg1.args[0] return ExprOp(expr.op, arg2) -def simp_zeroext_eq_cst(expr_s, expr): - # A.zeroExt(X) == int => A == int[:A.size] +def simp_zeroext_eq_cst(_, expr): + """A.zeroExt(X) == int => A == int[:A.size]""" if not expr.is_op(TOK_EQUAL): return expr arg1, arg2 = expr.args @@ -1046,12 +1061,31 @@ def simp_zeroext_eq_cst(expr_s, expr): src = arg1.args[0] if int(arg2) > (1 << src.size): # Always false - return ExprInt(0, 1) + return ExprInt(0, expr.size) return ExprOp(TOK_EQUAL, src, ExprInt(int(arg2), src.size)) -def simp_ext_eq_ext(expr_s, expr): - # A.zeroExt(X) == B.zeroExt(X) => A == B - # A.signExt(X) == B.signExt(X) => A == B +def simp_cond_zeroext(_, expr): + """ + X.zeroExt()?(A:B) => X ? A:B + X.signExt()?(A:B) => X ? A:B + """ + if not ( + expr.cond.is_op() and + ( + expr.cond.op.startswith("zeroExt") or + expr.cond.op.startswith("signExt") + ) + ): + return expr + + ret = ExprCond(expr.cond.args[0], expr.src1, expr.src2) + return ret + +def simp_ext_eq_ext(_, expr): + """ + A.zeroExt(X) == B.zeroExt(X) => A == B + A.signExt(X) == B.signExt(X) => A == B + """ if not expr.is_op(TOK_EQUAL): return expr arg1, arg2 = expr.args @@ -1064,8 +1098,8 @@ def simp_ext_eq_ext(expr_s, expr): return expr return ExprOp(TOK_EQUAL, arg1.args[0], arg2.args[0]) -def simp_cond_eq_zero(expr_s, expr): - # (X == 0)?(A:B) => X?(B:A) +def simp_cond_eq_zero(_, expr): + """(X == 0)?(A:B) => X?(B:A)""" cond = expr.cond if not cond.is_op(TOK_EQUAL): return expr @@ -1075,13 +1109,122 @@ def simp_cond_eq_zero(expr_s, expr): new_expr = ExprCond(arg1, expr.src2, expr.src1) return new_expr +def simp_sign_inf_zeroext(expr_s, expr): + """ + /!\ Ensure before: X.zeroExt(X.size) => X + + X.zeroExt() <s 0 => 0 + X.zeroExt() <=s 0 => X == 0 -def simp_cmp_int_int(expr_s, expr): - # IntA <s IntB => int - # IntA <u IntB => int - # IntA <=s IntB => int - # IntA <=u IntB => int - # IntA == IntB => int + X.zeroExt() <s cst => X.zeroExt() <u cst (cst positive) + X.zeroExt() <=s cst => X.zeroExt() <=u cst (cst positive) + + X.zeroExt() <s cst => 0 (cst negative) + X.zeroExt() <=s cst => 0 (cst negative) + + """ + if not (expr.is_op(TOK_INF_SIGNED) or expr.is_op(TOK_INF_EQUAL_SIGNED)): + return expr + arg1, arg2 = expr.args + if not arg2.is_int(): + return expr + if not (arg1.is_op() and arg1.op.startswith("zeroExt")): + return expr + src = arg1.args[0] + assert src.size < arg1.size + + # If cst is zero + if arg2.is_int(0): + if expr.is_op(TOK_INF_SIGNED): + # X.zeroExt() <s 0 => 0 + return ExprInt(0, expr.size) + else: + # X.zeroExt() <=s 0 => X == 0 + return ExprOp(TOK_EQUAL, src, ExprInt(0, src.size)) + + # cst is not zero + cst = int(arg2) + if cst & (1 << (arg2.size - 1)): + # cst is negative + return ExprInt(0, expr.size) + # cst is positive + if expr.is_op(TOK_INF_SIGNED): + # X.zeroExt() <s cst => X.zeroExt() <u cst (cst positive) + return ExprOp(TOK_INF_UNSIGNED, src, expr_s(arg2[:src.size])) + # X.zeroExt() <=s cst => X.zeroExt() <=u cst (cst positive) + return ExprOp(TOK_INF_EQUAL_UNSIGNED, src, expr_s(arg2[:src.size])) + + +def simp_zeroext_and_cst_eq_cst(expr_s, expr): + """ + A.zeroExt(X) & ... & int == int => A & ... & int[:A.size] == int[:A.size] + """ + if not expr.is_op(TOK_EQUAL): + return expr + arg1, arg2 = expr.args + if not arg2.is_int(): + return expr + if not arg1.is_op('&'): + return expr + is_ok = True + sizes = set() + for arg in arg1.args: + if arg.is_int(): + continue + if (arg.is_op() and + arg.op.startswith("zeroExt")): + sizes.add(arg.args[0].size) + continue + is_ok = False + break + if not is_ok: + return expr + if len(sizes) != 1: + return expr + size = list(sizes)[0] + if int(arg2) > ((1 << size) - 1): + return expr + args = [expr_s(arg[:size]) for arg in arg1.args] + left = ExprOp('&', *args) + right = expr_s(arg2[:size]) + ret = ExprOp(TOK_EQUAL, left, right) + return ret + + +def test_one_bit_set(arg): + """ + Return True if arg has form 1 << X + """ + return arg != 0 and ((arg & (arg - 1)) == 0) + +def simp_x_and_cst_eq_cst(_, expr): + """ + (x & ... & onebitmask == onebitmask) ? A:B => (x & ... & onebitmask) ? A:B + """ + cond = expr.cond + if not cond.is_op(TOK_EQUAL): + return expr + arg1, mask2 = cond.args + if not mask2.is_int(): + return expr + if not test_one_bit_set(int(mask2)): + return expr + if not arg1.is_op('&'): + return expr + mask1 = arg1.args[-1] + if mask1 != mask2: + return expr + cond = ExprOp('&', *arg1.args) + return ExprCond(cond, expr.src1, expr.src2) + +def simp_cmp_int_int(_, expr): + """ + IntA <s IntB => int + IntA <u IntB => int + IntA <=s IntB => int + IntA <=u IntB => int + IntA == IntB => int + """ if expr.op not in [ TOK_EQUAL, TOK_INF_SIGNED, TOK_INF_UNSIGNED, @@ -1094,8 +1237,7 @@ def simp_cmp_int_int(expr_s, expr): if expr.is_op(TOK_EQUAL): if int_a == int_b: return ExprInt(1, 1) - else: - return ExprInt(0, 1) + return ExprInt(0, expr.size) if expr.op in [TOK_INF_SIGNED, TOK_INF_EQUAL_SIGNED]: int_a = int(mod_size2int[int_a.size](int(int_a))) @@ -1116,9 +1258,11 @@ def simp_cmp_int_int(expr_s, expr): return ExprInt(ret, 1) -def simp_ext_cst(expr_s, expr): - # Int.zeroExt(X) => Int - # Int.signExt(X) => Int +def simp_ext_cst(_, expr): + """ + Int.zeroExt(X) => Int + Int.signExt(X) => Int + """ if not (expr.op.startswith("zeroExt") or expr.op.startswith("signExt")): return expr arg = expr.args[0] @@ -1132,31 +1276,150 @@ def simp_ext_cst(expr_s, expr): return ret -def simp_slice_of_ext(expr_s, expr): - # zeroExt(X)[0:size(X)] => X - if expr.start != 0: - return expr +def simp_slice_of_ext(_, expr): + """ + C.zeroExt(X)[A:B] => 0 if A >= size(C) + C.zeroExt(X)[A:B] => C[A:B] if B <= size(C) + A.zeroExt(X)[0:Y] => A.zeroExt(Y) + """ if not expr.arg.is_op(): return expr if not expr.arg.op.startswith("zeroExt"): return expr arg = expr.arg.args[0] - if arg.size != expr.size: + + if expr.start >= arg.size: + # C.zeroExt(X)[A:B] => 0 if A >= size(C) + return ExprInt(0, expr.size) + if expr.stop <= arg.size: + # C.zeroExt(X)[A:B] => C[A:B] if B <= size(C) + return arg[expr.start:expr.stop] + if expr.start == 0: + # A.zeroExt(X)[0:Y] => A.zeroExt(Y) + return arg.zeroExtend(expr.stop) + return expr + +def simp_slice_of_op_ext(expr_s, expr): + """(X.zeroExt() + ... + Int)[0:8] => X + ... + int[:]""" + if expr.start != 0: + return expr + src = expr.arg + if not src.is_op("+"): + return expr + is_ok = True + for arg in src.args: + if arg.is_int(): + continue + if (arg.is_op() and + arg.op.startswith("zeroExt") and + arg.args[0].size == expr.stop): + continue + is_ok = False + break + if not is_ok: + return expr + args = [expr_s(arg[:expr.stop]) for arg in src.args] + return ExprOp("+", *args) + + +def simp_cond_logic_ext(expr_s, expr): + """(X.zeroExt() + ... + Int) ? A:B => X + ... + int[:] ? A:B""" + cond = expr.cond + if not cond.is_op(): + return expr + if cond.op not in ["&", "^", "|"]: + return expr + is_ok = True + sizes = set() + for arg in cond.args: + if arg.is_int(): + continue + if (arg.is_op() and + arg.op.startswith("zeroExt")): + sizes.add(arg.args[0].size) + continue + is_ok = False + break + if not is_ok: + return expr + if len(sizes) != 1: + return expr + size = list(sizes)[0] + args = [expr_s(arg[:size]) for arg in cond.args] + cond = ExprOp(cond.op, *args) + return ExprCond(cond, expr.src1, expr.src2) + + +def simp_cond_sign_bit(_, expr): + """(a & .. & 0x80000000) ? A:B => (a & ...) <s 0 ? A:B""" + cond = expr.cond + if not cond.is_op('&'): + return expr + last = cond.args[-1] + if not last.is_int(1 << (last.size - 1)): + return expr + zero = ExprInt(0, expr.cond.size) + if len(cond.args) == 2: + args = [cond.args[0], zero] + else: + args = [ExprOp('&', *list(cond.args[:-1])), zero] + cond = ExprOp(TOK_INF_SIGNED, *args) + return ExprCond(cond, expr.src1, expr.src2) + + +def simp_test_signext_inf(expr_s, expr): + """A.signExt() <s int => A <s int[:]""" + if not (expr.is_op(TOK_INF_SIGNED) or expr.is_op(TOK_INF_EQUAL_SIGNED)): + return expr + arg, cst = expr.args + if not (arg.is_op() and arg.op.startswith("signExt")): return expr - return arg + if not cst.is_int(): + return expr + base = arg.args[0] + tmp = int(mod_size2int[cst.size](int(cst))) + if -(1 << (base.size - 1)) <= tmp < (1 << (base.size - 1)): + # Can trunc integer + return ExprOp(expr.op, base, expr_s(cst[:base.size])) + if (tmp >= (1 << (base.size - 1)) or + tmp < -(1 << (base.size - 1)) ): + return ExprInt(1, 1) + return expr -def simp_add_multiple(expr_s, expr): - # X + X => 2 * X - # X + X * int1 => X * (1 + int1) - # X * int1 + (- X) => X * (int1 - 1) - # X + (X << int1) => X * (1 + 2 ** int1) - # Correct even if addition overflow/underflow + +def simp_test_zeroext_inf(expr_s, expr): + """A.zeroExt() <u int => A <u int[:]""" + if not (expr.is_op(TOK_INF_UNSIGNED) or expr.is_op(TOK_INF_EQUAL_UNSIGNED)): + return expr + arg, cst = expr.args + if not (arg.is_op() and arg.op.startswith("zeroExt")): + return expr + if not cst.is_int(): + return expr + base = arg.args[0] + tmp = int(mod_size2uint[cst.size](int(cst))) + if 0 <= tmp < (1 << base.size): + # Can trunc integer + return ExprOp(expr.op, base, expr_s(cst[:base.size])) + if tmp >= (1 << base.size): + return ExprInt(1, 1) + return expr + + +def simp_add_multiple(_, expr): + """ + X + X => 2 * X + X + X * int1 => X * (1 + int1) + X * int1 + (- X) => X * (int1 - 1) + X + (X << int1) => X * (1 + 2 ** int1) + Correct even if addition overflow/underflow + """ if not expr.is_op('+'): return expr # Extract each argument and its counter operands = {} - for i, arg in enumerate(expr.args): + for arg in expr.args: if arg.is_op('*') and arg.args[1].is_int(): base_expr, factor = arg.args operands[base_expr] = operands.get(base_expr, 0) + int(factor) diff --git a/miasm2/jitter/arch/JitCore_aarch64.c b/miasm2/jitter/arch/JitCore_aarch64.c index fc51848a..d8b6d0f9 100644 --- a/miasm2/jitter/arch/JitCore_aarch64.c +++ b/miasm2/jitter/arch/JitCore_aarch64.c @@ -194,6 +194,12 @@ PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args) } +PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args) +{ + return cpu_dump_gpregs(self, args); +} + + PyObject* cpu_set_exception(JitCpu* self, PyObject* args) { PyObject *item1; @@ -294,6 +300,8 @@ static PyMethodDef JitCpu_methods[] = { "X"}, {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, "X"}, + {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, + "X"}, {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, "X"}, {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, diff --git a/miasm2/jitter/arch/JitCore_arm.c b/miasm2/jitter/arch/JitCore_arm.c index 4f1fd254..dca341d3 100644 --- a/miasm2/jitter/arch/JitCore_arm.c +++ b/miasm2/jitter/arch/JitCore_arm.c @@ -157,6 +157,13 @@ PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args) } +PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args) +{ + return cpu_dump_gpregs(self, args); +} + + + PyObject* cpu_set_exception(JitCpu* self, PyObject* args) { PyObject *item1; @@ -276,6 +283,8 @@ static PyMethodDef JitCpu_methods[] = { "X"}, {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, "X"}, + {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, + "X"}, {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, "X"}, {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, diff --git a/miasm2/jitter/arch/JitCore_mep.c b/miasm2/jitter/arch/JitCore_mep.c index 44f36290..a089e84f 100644 --- a/miasm2/jitter/arch/JitCore_mep.c +++ b/miasm2/jitter/arch/JitCore_mep.c @@ -223,6 +223,10 @@ PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args) return Py_None; } +PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args) +{ + return cpu_dump_gpregs(self, args); +} PyObject* cpu_set_exception(JitCpu* self, PyObject* args) { @@ -244,10 +248,6 @@ PyObject* cpu_get_exception(JitCpu* self, PyObject* args) return PyLong_FromUnsignedLongLong((uint64_t)(((vm_cpu_t*)self->cpu)->exception_flags)); } - - - - void check_automod(JitCpu* jitcpu, uint64_t addr, uint64_t size) { PyObject *result; @@ -322,6 +322,7 @@ static PyMemberDef JitCpu_members[] = { static PyMethodDef JitCpu_methods[] = { {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, "X"}, {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, "X"}, + {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, "X"}, {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, "X"}, {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, "X"}, {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, "X"}, diff --git a/miasm2/jitter/arch/JitCore_msp430.c b/miasm2/jitter/arch/JitCore_msp430.c index 12a42782..69f179a4 100644 --- a/miasm2/jitter/arch/JitCore_msp430.c +++ b/miasm2/jitter/arch/JitCore_msp430.c @@ -158,6 +158,11 @@ PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args) return Py_None; } +PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args) +{ + return cpu_dump_gpregs(self, args); +} + PyObject* cpu_set_exception(JitCpu* self, PyObject* args) { @@ -259,6 +264,8 @@ static PyMethodDef JitCpu_methods[] = { "X"}, {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, "X"}, + {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, + "X"}, {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, "X"}, {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, diff --git a/miasm2/jitter/arch/JitCore_ppc32.c b/miasm2/jitter/arch/JitCore_ppc32.c index dfc46c91..e1a3fcd5 100644 --- a/miasm2/jitter/arch/JitCore_ppc32.c +++ b/miasm2/jitter/arch/JitCore_ppc32.c @@ -109,6 +109,12 @@ cpu_dump_gpregs(JitCpu *self, PyObject *args) { } PyObject * +cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args) +{ + return cpu_dump_gpregs(self, args); +} + +PyObject * cpu_set_exception(JitCpu *self, PyObject *args) { PyObject *item1; uint64_t i; @@ -208,6 +214,7 @@ static PyMemberDef JitCpu_members[] = { static PyMethodDef JitCpu_methods[] = { {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, "X"}, {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, "X"}, + {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, "X"}, {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, "X"}, {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, "X"}, {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, "X"}, diff --git a/miasm2/jitter/arch/JitCore_x86.c b/miasm2/jitter/arch/JitCore_x86.c index b711f40b..fa47b324 100644 --- a/miasm2/jitter/arch/JitCore_x86.c +++ b/miasm2/jitter/arch/JitCore_x86.c @@ -349,6 +349,32 @@ PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args) } +PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args) +{ + vm_cpu_t* vmcpu; + PyObject *item1; + uint64_t attrib; + + if (!PyArg_ParseTuple(args, "O", &item1)) + RAISE(PyExc_TypeError,"Cannot parse arguments"); + + PyGetInt(item1, attrib); + + vmcpu = self->cpu; + if (attrib == 16 || attrib == 32) + dump_gpregs_32(vmcpu); + else if (attrib == 64) + dump_gpregs_64(vmcpu); + else { + RAISE(PyExc_TypeError,"Bad attrib"); + } + + Py_INCREF(Py_None); + return Py_None; +} + + + PyObject* cpu_set_exception(JitCpu* self, PyObject* args) { PyObject *item1; @@ -484,6 +510,8 @@ static PyMethodDef JitCpu_methods[] = { "X"}, {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, "X"}, + {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, + "X"}, {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, "X"}, {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, diff --git a/miasm2/jitter/jitcore.py b/miasm2/jitter/jitcore.py index fc5cf35e..78e27244 100644 --- a/miasm2/jitter/jitcore.py +++ b/miasm2/jitter/jitcore.py @@ -114,21 +114,11 @@ class JitCore(object): for a, b in self.blocks_mem_interval: vm.add_code_bloc(a, b + 1) - def jit_irblocks(self, label, irblocks): - """JiT a group of irblocks. - @label: the label of the irblocks - @irblocks: a group of irblocks - """ - - raise NotImplementedError("Abstract class") - def add_block(self, block): """Add a block to JiT and JiT it. @block: asm_bloc to add """ - irblocks = self.ir_arch.add_asmblock_to_ircfg(block, self.ircfg, gen_pc_updt = True) - block.blocks = irblocks - self.jit_irblocks(block.loc_key, irblocks) + raise NotImplementedError("Abstract class") def disasm_and_jit_block(self, addr, vm): """Disassemble a new block and JiT it diff --git a/miasm2/jitter/jitcore_python.py b/miasm2/jitter/jitcore_python.py index dd4c543e..fdd5c2ae 100644 --- a/miasm2/jitter/jitcore_python.py +++ b/miasm2/jitter/jitcore_python.py @@ -1,5 +1,5 @@ import miasm2.jitter.jitcore as jitcore -import miasm2.expression.expression as m2_expr +from miasm2.expression.expression import ExprInt, ExprLoc import miasm2.jitter.csts as csts from miasm2.expression.simplifications import expr_simp_explicit from miasm2.jitter.emulatedsymbexec import EmulatedSymbExec @@ -36,12 +36,38 @@ class JitCore_Python(jitcore.JitCore): "Preload symbols according to current architecture" self.symbexec.reset_regs() - def jit_irblocks(self, loc_key, irblocks): - """Create a python function corresponding to an irblocks' group. - @loc_key: the loc_key of the irblocks - @irblocks: a group of irblocks + def arch_specific(self): + """Return arch specific information for the current architecture""" + arch = self.ir_arch.arch + has_delayslot = False + if arch.name == "mips32": + from miasm2.arch.mips32.jit import mipsCGen + cgen_class = mipsCGen + has_delayslot = True + elif arch.name == "arm": + from miasm2.arch.arm.jit import arm_CGen + cgen_class = arm_CGen + else: + from miasm2.jitter.codegen import CGen + cgen_class = CGen + return cgen_class(self.ir_arch), has_delayslot + + def add_block(self, asmblock): + """Create a python function corresponding to an AsmBlock + @asmblock: AsmBlock """ + # TODO: merge duplicate code with CGen, llvmconvert + codegen, has_delayslot = self.arch_specific() + irblocks_list = codegen.block2assignblks(asmblock) + instr_offsets = [line.offset for line in asmblock.lines] + + loc_db = self.ir_arch.loc_db + local_loc_keys = [] + for irblocks in irblocks_list: + for irblock in irblocks: + local_loc_keys.append(irblock.loc_key) + def myfunc(cpu): """Execute the function according to cpu and vmmngr states @cpu: JitCpu instance @@ -49,86 +75,131 @@ class JitCore_Python(jitcore.JitCore): # Get virtual memory handler vmmngr = cpu.vmmngr - # Keep current location in irblocks - cur_loc_key = loc_key - - # Required to detect new instructions - offsets_jitted = set() - - # Get exec engine + # Get execution engine (EmulatedSymbExec instance) exec_engine = self.symbexec - expr_simp = exec_engine.expr_simp - # For each irbloc inside irblocks - while True: - # Get the current bloc - for irb in irblocks: - if irb.loc_key == cur_loc_key: - break + # Refresh CPU values according to @cpu instance + exec_engine.update_engine_from_cpu() - else: - raise RuntimeError("Irblocks must end with returning an " - "ExprInt instance") - - # Refresh CPU values according to @cpu instance - exec_engine.update_engine_from_cpu() - - # Execute current ir bloc - for assignblk in irb: - instr = assignblk.instr - # For each new instruction (in assembly) - if instr is not None and instr.offset not in offsets_jitted: - # Test exceptions - vmmngr.check_invalid_code_blocs() - vmmngr.check_memory_breakpoint() - if vmmngr.get_exception(): - exec_engine.update_cpu_from_engine() - return instr.offset + # Get initial loc_key + cur_loc_key = asmblock.loc_key - offsets_jitted.add(instr.offset) + # Update PC helper + update_pc = lambda value: setattr(cpu, self.ir_arch.pc.name, value) - # Log registers values - if self.log_regs: - exec_engine.update_cpu_from_engine() - exec_engine.cpu.dump_gpregs() + while True: + # Retrieve the expected irblock + for instr, irblocks in zip(asmblock.lines, irblocks_list): + for index, irblock in enumerate(irblocks): + if irblock.loc_key == cur_loc_key: + break + else: + continue + break + else: + raise RuntimeError("Unable to find the block for %r" % cur_loc_key) + + instr_attrib, irblocks_attributes = codegen.get_attributes( + instr, irblocks, self.log_mn, self.log_regs + ) + irblock_attributes = irblocks_attributes[index] + + # Do IRBlock + new_irblock = self.ir_arch.irbloc_fix_regs_for_mode( + irblock, self.ir_arch.attrib + ) + if index == 0: + # Pre code + if instr_attrib.log_mn: + print "%.8X %s" % ( + instr_attrib.instr.offset, + instr_attrib.instr.to_string(loc_db) + ) + + # Exec IRBlock + instr = instr_attrib.instr + + for index, assignblk in enumerate(irblock): + attributes = irblock_attributes[index] - # Log instruction - if self.log_mn: - print "%08x %s" % (instr.offset, instr) + # Eval current instruction (in IR) + exec_engine.eval_updt_assignblk(assignblk) - # Check for exception - if (vmmngr.get_exception() != 0 or - cpu.get_exception() != 0): - exec_engine.update_cpu_from_engine() + # Check memory access / write exception + # TODO: insert a check between memory reads and writes + if attributes.mem_read or attributes.mem_write: + # Restricted exception + flag = ~csts.EXCEPT_CODE_AUTOMOD & csts.EXCEPT_DO_NOT_UPDATE_PC + if (vmmngr.get_exception() & flag != 0): + # Do not update registers + update_pc(instr.offset) return instr.offset - # Eval current instruction (in IR) - exec_engine.eval_updt_assignblk(assignblk) - # Check for exceptions which do not update PC + # Update registers values exec_engine.update_cpu_from_engine() - if (vmmngr.get_exception() & csts.EXCEPT_DO_NOT_UPDATE_PC != 0 or - cpu.get_exception() > csts.EXCEPT_NUM_UPDT_EIP): - return instr.offset - - vmmngr.check_invalid_code_blocs() - vmmngr.check_memory_breakpoint() - # Get next bloc address - ad = expr_simp(exec_engine.eval_expr(self.ir_arch.IRDst)) + # Check post assignblk exception flags + if attributes.set_exception: + # Restricted exception + if cpu.get_exception() > csts.EXCEPT_NUM_UPDT_EIP: + # Update PC + update_pc(instr.offset) + return instr.offset - # Updates @cpu instance according to new CPU values - exec_engine.update_cpu_from_engine() + dst = exec_engine.eval_expr(self.ir_arch.IRDst) + if dst.is_int(): + loc_key = loc_db.get_or_create_offset_location(int(dst)) + dst = ExprLoc(loc_key, dst.size) + + assert dst.is_loc() + loc_key = dst.loc_key + offset = loc_db.get_location_offset(loc_key) + if offset is None: + # Avoid checks on generated label + cur_loc_key = loc_key + continue + + if instr_attrib.log_regs: + update_pc(offset) + cpu.dump_gpregs_with_attrib(self.ir_arch.attrib) + + # Post-instr checks + if instr_attrib.mem_read | instr_attrib.mem_write: + vmmngr.check_memory_breakpoint() + vmmngr.check_invalid_code_blocs() + if vmmngr.get_exception(): + update_pc(offset) + return offset + + if instr_attrib.set_exception: + if cpu.get_exception(): + update_pc(offset) + return offset + + if instr_attrib.mem_read | instr_attrib.mem_write: + vmmngr.reset_memory_access() # Manage resulting address - if isinstance(ad, m2_expr.ExprInt): - return ad.arg.arg - elif isinstance(ad, m2_expr.ExprLoc): - cur_loc_key = ad.loc_key - else: - raise NotImplementedError("Type not handled: %s" % ad) + if (loc_key in local_loc_keys and + offset > instr.offset): + # Forward local jump + # Note: a backward local jump has to be promoted to extern, + # for max_exec_per_call support + cur_loc_key = loc_key + continue + + # Delay slot + if has_delayslot: + delay_slot_set = exec_engine.eval_expr(codegen.delay_slot_set) + if delay_slot_set.is_int() and int(delay_slot_set) != 0: + return int(exec_engine.eval_expr(codegen.delay_slot_dst)) + + # Extern of asmblock, must have an offset + assert offset is not None + return offset # Associate myfunc with current loc_key - offset = self.ir_arch.loc_db.get_location_offset(loc_key) + offset = loc_db.get_location_offset(asmblock.loc_key) assert offset is not None self.offset_to_jitted_func[offset] = myfunc diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py index 5230bdbe..41461c3a 100644 --- a/miasm2/jitter/llvmconvert.py +++ b/miasm2/jitter/llvmconvert.py @@ -1297,7 +1297,7 @@ class LLVMFunction(object): # Update PC for dump_gpregs PC = self.llvm_context.PC t_size = LLVMType.IntType(PC.size) - dst = self.builder.zext(t_size(pc_value), LLVMType.IntType(PC.size)) + dst = self.builder.zext(t_size(pc_value), t_size) self.affect(dst, PC) fc_ptr = self.mod.get_global(self.llvm_context.logging_func) diff --git a/miasm2/jitter/vm_mngr_py.c b/miasm2/jitter/vm_mngr_py.c index 5ff436bf..93de9bb4 100644 --- a/miasm2/jitter/vm_mngr_py.c +++ b/miasm2/jitter/vm_mngr_py.c @@ -248,7 +248,6 @@ PyObject* vm_get_u8(VmMngr* self, PyObject* args) PyObject *py_addr; uint64_t addr; - uint64_t size; PyObject *obj_out; char * buf_out; int ret; @@ -276,7 +275,6 @@ PyObject* vm_get_u16(VmMngr* self, PyObject* args) PyObject *py_addr; uint64_t addr; - uint64_t size; PyObject *obj_out; char * buf_out; int ret; @@ -304,7 +302,6 @@ PyObject* vm_get_u32(VmMngr* self, PyObject* args) PyObject *py_addr; uint64_t addr; - uint64_t size; PyObject *obj_out; char * buf_out; int ret; @@ -333,7 +330,6 @@ PyObject* vm_get_u64(VmMngr* self, PyObject* args) PyObject *py_addr; uint64_t addr; - uint64_t size; PyObject *obj_out; char * buf_out; int ret; diff --git a/test/arch/aarch64/arch.py b/test/arch/aarch64/arch.py index cba175e6..46a4514b 100644 --- a/test/arch/aarch64/arch.py +++ b/test/arch/aarch64/arch.py @@ -7,6 +7,7 @@ from miasm2.core.locationdb import LocationDB loc_db = LocationDB() reg_tests_aarch64 = [ + ("XXXXXXXX MOV W1, WZR", "E1031F2A"), ("XXXXXXXX TST W5, W3", @@ -1794,6 +1795,25 @@ reg_tests_aarch64 = [ ("XXXXXXXX ORR X8, 0x0, 0x1000100010001", "E88300B2"), + + ("XXXXXXXX CASP X0, X2, [X4]", + "827C2048"), + ("XXXXXXXX CASPL X0, X2, [X4]", + "82FC2048"), + ("XXXXXXXX CASPA X0, X2, [X4]", + "827C6048"), + ("XXXXXXXX CASPAL X0, X2, [X4]", + "82FC6048"), + + ("XXXXXXXX CASP W0, W2, [X4]", + "827C2008"), + ("XXXXXXXX CASPL W0, W2, [X4]", + "82FC2008"), + ("XXXXXXXX CASPA W0, W2, [X4]", + "827C6008"), + ("XXXXXXXX CASPAL W0, W2, [X4]", + "82FC6008"), + ] diff --git a/test/expression/simplifications.py b/test/expression/simplifications.py index cc3606e4..5bca3fa9 100644 --- a/test/expression/simplifications.py +++ b/test/expression/simplifications.py @@ -446,6 +446,9 @@ to_test = [(ExprInt(1, 32) - ExprInt(1, 32), ExprInt(0, 32)), (ExprOp("signExt_16", ExprInt(0x8, 8)), ExprInt(0x8, 16)), (ExprOp("signExt_16", ExprInt(-0x8, 8)), ExprInt(-0x8, 16)), + (ExprCond(a8.zeroExtend(32), a, b), ExprCond(a8, a, b)), + + (- (i2*a), a * im2), (a + a, a * i2), (ExprOp('+', a, a), a * i2), @@ -516,6 +519,179 @@ to_test = [ (ExprOp(TOK_EQUAL, a8.zeroExtend(32), b8.zeroExtend(32)), ExprOp(TOK_EQUAL, a8, b8)), (ExprOp(TOK_EQUAL, a8.signExtend(32), b8.signExtend(32)), ExprOp(TOK_EQUAL, a8, b8)), + (ExprOp(TOK_INF_EQUAL_SIGNED, a8.zeroExtend(32), i0), ExprOp(TOK_EQUAL, a8, ExprInt(0, 8))), + + ((a8.zeroExtend(32) + b8.zeroExtend(32) + ExprInt(1, 32))[0:8], a8 + b8 + ExprInt(1, 8)), + + (ExprCond(a8.zeroExtend(32), a, b), ExprCond(a8, a, b)), + (ExprCond(a8.signExtend(32), a, b), ExprCond(a8, a, b)), + + + ( + ExprOp( + TOK_EQUAL, + a8.zeroExtend(32) & b8.zeroExtend(32) & ExprInt(0x12, 32), + i1 + ), + ExprOp( + TOK_EQUAL, + a8 & b8 & ExprInt(0x12, 8), + ExprInt(1, 8) + ) + ), + + ( + ExprCond( + ExprOp( + TOK_EQUAL, + a & b & ExprInt(0x80, 32), + ExprInt(0x80, 32) + ), a, b + ), + ExprCond(a & b & ExprInt(0x80, 32), a, b) + ), + + + + ( + ExprCond( + a8.zeroExtend(32) & b8.zeroExtend(32) & ExprInt(0x12, 32), + a, b + ), + ExprCond( + a8 & b8 & ExprInt(0x12, 8), + a, b + ), + ), + + + (a8.zeroExtend(32)[:8], a8), + (a.zeroExtend(64)[:32], a), + (a.zeroExtend(64)[:8], a[:8]), + (a8.zeroExtend(32)[:16], a8.zeroExtend(16)), + + ( + ExprCond( + a & ExprInt(0x80000000, 32), + a, b + ), + ExprCond( + ExprOp(TOK_INF_SIGNED, a, ExprInt(0, 32) ), + a, b + ) + ), + + + + ( + ExprCond( + a8.signExtend(32) & ExprInt(0x80000000, 32), + a, b + ), + ExprCond( + ExprOp(TOK_INF_SIGNED, a8, ExprInt(0, 8) ), + a, b + ) + ), + + + ( + ExprCond( + ExprOp(TOK_INF_SIGNED, a8.signExtend(32), ExprInt(0x10, 32) ), + a, b + ), + ExprCond( + ExprOp(TOK_INF_SIGNED, a8, ExprInt(0x10, 8) ), + a, b + ) + ), + + ( + ExprCond( + ExprOp(TOK_INF_SIGNED, a8.signExtend(32), ExprInt(-0x10, 32) ), + a, b + ), + ExprCond( + ExprOp(TOK_INF_SIGNED, a8, ExprInt(-0x10, 8) ), + a, b + ) + ), + + + ( + ExprCond( + ExprOp(TOK_INF_UNSIGNED, a8.zeroExtend(32), ExprInt(0x10, 32) ), + a, b + ), + ExprCond( + ExprOp(TOK_INF_UNSIGNED, a8, ExprInt(0x10, 8) ), + a, b + ) + ), + + + + ( + ExprCond( + ExprOp(TOK_INF_SIGNED, a8.signExtend(32), ExprInt(0x200, 32) ), + a, b + ), + a + ), + + + ( + ExprCond( + ExprOp(TOK_INF_UNSIGNED, a8.zeroExtend(32), ExprInt(0x200, 32) ), + a, b + ), + a + ), + + + + ( + ExprCond( + ExprOp(TOK_INF_SIGNED, a8.zeroExtend(32), ExprInt(0x10, 32) ), + a, b + ), + ExprCond( + ExprOp(TOK_INF_UNSIGNED, a8, ExprInt(0x10, 8) ), + a, b + ) + ), + + ( + ExprCond( + ExprOp(TOK_INF_EQUAL_SIGNED, a8.zeroExtend(32), ExprInt(0x10, 32) ), + a, b + ), + ExprCond( + ExprOp(TOK_INF_EQUAL_UNSIGNED, a8, ExprInt(0x10, 8) ), + a, b + ) + ), + + + ( + ExprCond( + ExprOp(TOK_INF_SIGNED, a8.zeroExtend(32), ExprInt(-1, 32) ), + a, b + ), + b + ), + + ( + ExprCond( + ExprOp(TOK_INF_EQUAL_SIGNED, a8.zeroExtend(32), ExprInt(-1, 32) ), + a, b + ), + b + ), + + + (a8.zeroExtend(32)[2:5], a8[2:5]), + ] for e_input, e_check in to_test: diff --git a/test/test_all.py b/test/test_all.py index 4b97ffba..f3bcc477 100755 --- a/test/test_all.py +++ b/test/test_all.py @@ -21,6 +21,7 @@ TAGS = {"regression": "REGRESSION", # Regression tests "long": "LONG", # Very time consumming tests "llvm": "LLVM", # LLVM dependency is required "gcc": "GCC", # GCC based tests + "python": "PYTHON", # Python jitted tests "z3": "Z3", # Z3 dependency is needed "qemu": "QEMU", # QEMU tests (several tests) "cparser": "CPARSER", # pycparser is needed @@ -109,7 +110,7 @@ for script in ["x86/sem.py", continue testset += ArchUnitTest(script, jitter, base_dir="arch", tags=tags) -testset += ArchUnitTest("x86/unit/access_xmm.py", "python", base_dir="arch") +testset += ArchUnitTest("x86/unit/access_xmm.py", "python", base_dir="arch", tags=[TAGS["python"]]) ### QEMU regression tests class QEMUTest(RegressionTest): @@ -750,7 +751,7 @@ class ExampleJitterNoPython(ExampleJitter): for jitter in ExampleJitter.jitter_engines: # Take 5 min on a Core i5 - tags = {"python": [TAGS["long"]], + tags = {"python": [TAGS["long"], TAGS["python"]], "llvm": [TAGS["llvm"]], "gcc": [TAGS["gcc"]], } |