diff options
| author | Fabrice Desclaux <fabrice.desclaux@cea.fr> | 2019-01-27 17:07:41 +0100 |
|---|---|---|
| committer | Fabrice Desclaux <fabrice.desclaux@cea.fr> | 2019-01-27 17:09:54 +0100 |
| commit | 045792970f462e4d408fd01b419ccd851a1301a2 (patch) | |
| tree | d36dfd2d7452ceef5ebbb66a8a5288d5c7595ada | |
| parent | 98f54e1cff3b80d2c0c14ed0424b90bfe9112680 (diff) | |
| download | miasm-045792970f462e4d408fd01b419ccd851a1301a2.tar.gz miasm-045792970f462e4d408fd01b419ccd851a1301a2.zip | |
Jitter: support high level flags
| -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 |
4 files changed, 190 insertions, 11 deletions
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 == "*": |