diff options
| -rw-r--r-- | miasm2/arch/arm/sem.py | 39 | ||||
| -rw-r--r-- | miasm2/arch/ppc/sem.py | 25 | ||||
| -rw-r--r-- | miasm2/ir/translators/C.py | 65 | ||||
| -rw-r--r-- | miasm2/jitter/bn.c | 86 | ||||
| -rw-r--r-- | miasm2/jitter/bn.h | 13 | ||||
| -rw-r--r-- | miasm2/jitter/llvmconvert.py | 37 |
6 files changed, 240 insertions, 25 deletions
diff --git a/miasm2/arch/arm/sem.py b/miasm2/arch/arm/sem.py index 64403206..3e017d1f 100644 --- a/miasm2/arch/arm/sem.py +++ b/miasm2/arch/arm/sem.py @@ -1754,15 +1754,52 @@ class ir_arml(IntermediateRepresentation): irblocks.append(irblock) + it_instr_irblocks = [] assignments = [] loc = loc_do + split = self.add_instr_to_current_state( instr, block, assignments, - irblocks, gen_pc_updt + it_instr_irblocks, gen_pc_updt ) if split: raise NotImplementedError("Unsupported instr in IT block (%s)" % instr) + if it_instr_irblocks: + assert len(it_instr_irblocks) == 1 + it_instr_irblocks = it_instr_irblocks.pop() + # Remove flags assignment if instr != [CMP, CMN, TST] + if instr.name not in ["CMP", "CMN", "TST"]: + # Fix assignments + out = [] + for assignment in assignments: + assignment = AssignBlock( + { + dst:src for (dst, src) in assignment.iteritems() + if dst not in [zf, nf, of, cf] + }, + assignment.instr + ) + out.append(assignment) + assignments = out + # Fix extra irblocksx + new_irblocks = [] + for irblock in it_instr_irblocks: + out = [] + for tmp_assignment in irblock: + assignment = AssignBlock( + { + dst:src for (dst, src) in assignment.iteritems() + if dst not in [zf, nf, of, cf] + }, + assignment.instr + ) + out.append(assignment) + new_irblock = IRBlock(irblock.loc_key, out) + new_irblocks.append(new_irblock) + it_instr_irblocks = new_irblocks + + irblocks += it_instr_irblocks dst = ExprAssign(self.IRDst, ExprLoc(loc_next, 32)) dst_blk = AssignBlock([dst], instr) assignments.append(dst_blk) diff --git a/miasm2/arch/ppc/sem.py b/miasm2/arch/ppc/sem.py index 44895624..558450b2 100644 --- a/miasm2/arch/ppc/sem.py +++ b/miasm2/arch/ppc/sem.py @@ -17,7 +17,12 @@ crf_dict = dict((ExprId("CR%d" % i, 4), for bit in ['LT', 'GT', 'EQ', 'SO' ] )) for i in xrange(8) ) -ctx = { 'crf_dict': crf_dict, 'spr_dict': spr_dict } +ctx = { + 'crf_dict': crf_dict, + 'spr_dict': spr_dict, + 'expr': expr, +} + ctx.update(all_regs_ids_byname) sbuild = SemBuilder(ctx) @@ -746,22 +751,16 @@ def mn_do_nop_warn(ir, instr, *args): @sbuild.parse def mn_cmp_signed(arg1, arg2, arg3): - crf_dict[arg1]['LT'] = ((arg2 - arg3) ^ - ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))).msb() - crf_dict[arg1]['GT'] = ((arg3 - arg2) ^ - ((arg3 ^ arg2) & ((arg3 - arg2) ^ arg3))).msb() - crf_dict[arg1]['EQ'] = i1(0) if arg2 - arg3 else i1(1) + crf_dict[arg1]['LT'] = expr.ExprOp(expr.TOK_INF_SIGNED, arg2, arg3) + crf_dict[arg1]['GT'] = expr.ExprOp(expr.TOK_INF_SIGNED, arg3, arg2) + crf_dict[arg1]['EQ'] = expr.ExprOp(expr.TOK_EQUAL, arg2, arg3) crf_dict[arg1]['SO'] = XER_SO @sbuild.parse def mn_cmp_unsigned(arg1, arg2, arg3): - crf_dict[arg1]['LT'] = (((arg2 - arg3) ^ - ((arg2 ^ arg3) & ((arg2 - arg3) ^ arg2))) ^ - arg2 ^ arg3).msb() - crf_dict[arg1]['GT'] = (((arg3 - arg2) ^ - ((arg3 ^ arg2) & ((arg3 - arg2) ^ arg3))) ^ - arg2 ^ arg3).msb() - crf_dict[arg1]['EQ'] = i1(0) if arg2 - arg3 else i1(1) + crf_dict[arg1]['LT'] = expr.ExprOp(expr.TOK_INF_UNSIGNED, arg2, arg3) + crf_dict[arg1]['GT'] = expr.ExprOp(expr.TOK_INF_UNSIGNED, arg3, arg2) + crf_dict[arg1]['EQ'] = expr.ExprOp(expr.TOK_EQUAL, arg2, arg3) crf_dict[arg1]['SO'] = XER_SO def mn_nop(ir, instr, *args): diff --git a/miasm2/ir/translators/C.py b/miasm2/ir/translators/C.py index a239383b..5a55237f 100644 --- a/miasm2/ir/translators/C.py +++ b/miasm2/ir/translators/C.py @@ -1,7 +1,9 @@ from miasm2.ir.translators.translator import Translator from miasm2.expression.modint import size2mask from miasm2.expression.expression import ExprInt, ExprCond, ExprCompose, \ - TOK_EQUAL + TOK_EQUAL, \ + TOK_INF_SIGNED, TOK_INF_UNSIGNED, \ + TOK_INF_EQUAL_SIGNED, TOK_INF_EQUAL_UNSIGNED def int_size_to_bn(value, size): if size < 32: @@ -17,6 +19,22 @@ def int_size_to_bn(value, size): return int_str, size_nibble +TOK_CMP_TO_NATIVE_C = { + TOK_EQUAL: "==", + TOK_INF_SIGNED: "<", + TOK_INF_UNSIGNED: "<", + TOK_INF_EQUAL_SIGNED: "<=", + TOK_INF_EQUAL_UNSIGNED: "<=", +} + +TOK_CMP_TO_BIGNUM_C = { + TOK_EQUAL: "equal", + TOK_INF_SIGNED: "inf_signed", + TOK_INF_UNSIGNED: "inf_unsigned", + TOK_INF_EQUAL_SIGNED: "inf_equal_signed", + TOK_INF_EQUAL_UNSIGNED: "inf_equal_unsigned", +} + class TranslatorC(Translator): "Translate a Miasm expression to an equivalent C code" @@ -238,14 +256,7 @@ class TranslatorC(Translator): raise NotImplementedError('Unknown op: %r' % expr.op) elif len(expr.args) == 2: - if expr.op == TOK_EQUAL: - return '(((%s&%s) == (%s&%s))?1:0)' % ( - self.from_expr(expr.args[0]), - self._size2mask(expr.args[0].size), - self.from_expr(expr.args[1]), - self._size2mask(expr.args[1].size), - ) - elif expr.op in self.dct_shift: + if expr.op in self.dct_shift: arg0 = self.from_expr(expr.args[0]) arg1 = self.from_expr(expr.args[1]) if expr.size <= self.NATIVE_INT_MAX_SIZE: @@ -399,6 +410,42 @@ class TranslatorC(Translator): self.from_expr(expr.args[0]), self.from_expr(expr.args[1]) ) + + + elif expr.op in [ + TOK_EQUAL, + TOK_INF_SIGNED, + TOK_INF_UNSIGNED, + TOK_INF_EQUAL_SIGNED, + TOK_INF_EQUAL_UNSIGNED, + ]: + arg0 = self.from_expr(expr.args[0]) + arg1 = self.from_expr(expr.args[1]) + + if expr.size <= self.NATIVE_INT_MAX_SIZE: + op = TOK_CMP_TO_NATIVE_C[expr.op] + if expr.op in [TOK_INF_SIGNED, TOK_INF_EQUAL_SIGNED]: + cast = "(int%d_t)" % expr.args[0].size + else: + cast = "(uint%d_t)" % expr.args[0].size + out = '((%s%s %s %s%s)?1:0)' % ( + cast, + arg0, + op, + cast, + arg1 + ) + else: + op = TOK_CMP_TO_BIGNUM_C[expr.op] + out = "bignum_is_%s(%s, %s)" % ( + op, + arg0, + arg1 + ) + out = "bignum_mask(%s, %d)"% (out, expr.size) + return out + + else: raise NotImplementedError('Unknown op: %r' % expr.op) diff --git a/miasm2/jitter/bn.c b/miasm2/jitter/bn.c index c621d102..dd4f34ef 100644 --- a/miasm2/jitter/bn.c +++ b/miasm2/jitter/bn.c @@ -579,6 +579,92 @@ int bignum_cmp(bn_t a, bn_t b) } +/* Signed compare bn */ +int bignum_cmp_signed(bn_t a, bn_t b) +{ + int i = BN_ARRAY_SIZE; + do { + i -= 1; /* Decrement first, to start with last array element */ + if ((DTYPE_SIGNED)a.array[i] > (DTYPE_SIGNED)b.array[i]) { + return LARGER; + } + else if ((DTYPE_SIGNED)a.array[i] < (DTYPE_SIGNED)b.array[i]) { + return SMALLER; + } + } + while (i != 0); + + return EQUAL; +} + + +/* Unsigned compare bn */ +int bignum_cmp_unsigned(bn_t a, bn_t b) +{ + return bignum_cmp(a, b); +} + + +/* Return 1 if a == b else 0 */ +int bignum_is_equal(bn_t a, bn_t b) +{ + int ret; + ret = bignum_cmp_unsigned(a, b); + if (ret == EQUAL) + return 1; + else + return 0; +} + + +/* Return 1 if a <u b else 0 */ +int bignum_is_inf_unsigned(bn_t a, bn_t b) +{ + int ret; + ret = bignum_cmp_unsigned(a, b); + if (ret == SMALLER) + return 1; + else + return 0; +} + + +/* Return 1 if a <=u b else 0 */ +int bignum_is_inf_equal_unsigned(bn_t a, bn_t b) +{ + int ret; + ret = bignum_cmp_unsigned(a, b); + if (ret == EQUAL || ret == SMALLER) + return 1; + else + return 0; +} + + +/* Return 1 if a <s b else 0 */ +int bignum_is_inf_signed(bn_t a, bn_t b) +{ + int ret; + ret = bignum_cmp_signed(a, b); + if (ret == SMALLER) + return 1; + else + return 0; +} + + +/* Return 1 if a <=s b else 0 */ +int bignum_is_inf_equal_signed(bn_t a, bn_t b) +{ + int ret; + ret = bignum_cmp_signed(a, b); + if (ret == EQUAL || ret == SMALLER) + return 1; + else + return 0; +} + + int bignum_is_zero(bn_t n) { //require(n, "n is null"); diff --git a/miasm2/jitter/bn.h b/miasm2/jitter/bn.h index f0a13b53..1aa6b432 100644 --- a/miasm2/jitter/bn.h +++ b/miasm2/jitter/bn.h @@ -56,6 +56,7 @@ Code slightly modified to support ast generation calculus style from Expr. #elif (WORD_SIZE == 1) /* Data type of array in structure */ #define DTYPE uint8_t + #define DTYPE_SIGNED int8_t /* bitmask for getting MSB */ #define DTYPE_MSB ((DTYPE_TMP)(0x80)) /* Data-type larger than DTYPE, for holding intermediate results of calculations */ @@ -67,6 +68,7 @@ Code slightly modified to support ast generation calculus style from Expr. #define MAX_VAL ((DTYPE_TMP)0xFF) #elif (WORD_SIZE == 2) #define DTYPE uint16_t + #define DTYPE_SIGNED int16_t #define DTYPE_TMP uint32_t #define DTYPE_MSB ((DTYPE_TMP)(0x8000)) #define SPRINTF_FORMAT_STR "%.04x" @@ -74,6 +76,7 @@ Code slightly modified to support ast generation calculus style from Expr. #define MAX_VAL ((DTYPE_TMP)0xFFFF) #elif (WORD_SIZE == 4) #define DTYPE uint32_t + #define DTYPE_SIGNED int32_t #define DTYPE_TMP uint64_t #define DTYPE_MSB ((DTYPE_TMP)(0x80000000)) #define SPRINTF_FORMAT_STR "%.08x" @@ -132,7 +135,15 @@ _MIASM_EXPORT bn_t bignum_a_rshift(bn_t a, int size, int nbits); /* b = a a>> nb _MIASM_EXPORT bn_t bignum_not(bn_t a); /* c = ~a */ /* Special operators and comparison */ -_MIASM_EXPORT int bignum_cmp(bn_t a, bn_t b); /* Compare: returns LARGER, EQUAL or SMALLER */ +_MIASM_EXPORT int bignum_cmp(bn_t a, bn_t b); /* Compare: returns LARGER, EQUAL or SMALLER */ +_MIASM_EXPORT int bignum_is_equal(bn_t a, bn_t b); /* Return 1 if a == b else 0 */ +_MIASM_EXPORT int bignum_is_inf_unsigned(bn_t a, bn_t b); /* Return 1 if a <u b else 0 */ +_MIASM_EXPORT int bignum_is_inf_equal_unsigned(bn_t a, bn_t b); /* Return 1 if a <=u b else 0 */ +_MIASM_EXPORT int bignum_is_inf_signed(bn_t a, bn_t b); /* Return 1 if a <s b else 0 */ +_MIASM_EXPORT int bignum_is_inf_equal_signed(bn_t a, bn_t b); /* Return 1 if a <=s b else 0 */ + + + _MIASM_EXPORT int bignum_is_zero(bn_t n); /* For comparison with zero */ _MIASM_EXPORT bn_t bignum_inc(bn_t n); /* Increment: add one to n */ _MIASM_EXPORT bn_t bignum_dec(bn_t n); /* Decrement: subtract one from n */ diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py index a31348cf..fd32001c 100644 --- a/miasm2/jitter/llvmconvert.py +++ b/miasm2/jitter/llvmconvert.py @@ -15,7 +15,11 @@ import os from llvmlite import binding as llvm from llvmlite import ir as llvm_ir from miasm2.expression.expression import ExprId, ExprInt, ExprMem, ExprSlice, \ - ExprCond, ExprLoc, ExprOp, ExprCompose, LocKey, Expr + ExprCond, ExprLoc, ExprOp, ExprCompose, LocKey, Expr, \ + TOK_EQUAL, \ + TOK_INF_SIGNED, TOK_INF_UNSIGNED, \ + TOK_INF_EQUAL_SIGNED, TOK_INF_EQUAL_UNSIGNED + import miasm2.jitter.csts as m2_csts import miasm2.core.asmblock as m2_asmblock from miasm2.jitter.codegen import CGen, Attributes @@ -1074,6 +1078,37 @@ class LLVMFunction(object): self.update_cache(expr, ret) return ret + if op in [ + TOK_EQUAL, + TOK_INF_SIGNED, + TOK_INF_EQUAL_SIGNED, + TOK_INF_UNSIGNED, + TOK_INF_EQUAL_UNSIGNED, + ]: + if op == TOK_EQUAL: + opname = "==" + callback = builder.icmp_unsigned + elif op == TOK_INF_SIGNED: + opname = "<" + callback = builder.icmp_signed + elif op == TOK_INF_UNSIGNED: + opname = "<" + callback = builder.icmp_unsigned + elif op == TOK_INF_EQUAL_SIGNED: + opname = "<=" + callback = builder.icmp_signed + elif op == TOK_INF_EQUAL_UNSIGNED: + opname = "<" + callback = builder.icmp_unsigned + + left = self.add_ir(expr.args[0]) + right = self.add_ir(expr.args[1]) + + ret = callback(opname, left, right) + self.update_cache(expr, ret) + + return ret + if len(expr.args) > 1: if op == "*": |