about summary refs log tree commit diff stats
path: root/miasm2/ir/translators/C.py
diff options
context:
space:
mode:
Diffstat (limited to 'miasm2/ir/translators/C.py')
-rw-r--r--miasm2/ir/translators/C.py372
1 files changed, 271 insertions, 101 deletions
diff --git a/miasm2/ir/translators/C.py b/miasm2/ir/translators/C.py
index f8fd4d3b..066c0f32 100644
--- a/miasm2/ir/translators/C.py
+++ b/miasm2/ir/translators/C.py
@@ -3,6 +3,22 @@ from miasm2.core import asmblock
 from miasm2.expression.modint import size2mask
 
 
+def int_size_to_bn(value, size):
+    if size < 32:
+        size = 32
+        int_str = "%.8x" % value
+        size_nibble = 8
+    else:
+        # size must be multiple of 4
+        size = ((size + 31) / 32) * 32
+        size_nibble = size / 4
+        fmt_str = "%%.%dx" % size_nibble
+        int_str = fmt_str % value
+    assert len(int_str) == size_nibble
+    return int_str, size_nibble
+
+
+
 class TranslatorC(Translator):
     "Translate a Miasm expression to an equivalent C code"
 
@@ -18,6 +34,8 @@ class TranslatorC(Translator):
                '>>>': 'rot_right',
                }
 
+    NATIVE_INT_MAX_SIZE = 64
+
     def __init__(self, loc_db=None, **kwargs):
         """Instance a C translator
         @loc_db: LocationDB instance
@@ -28,38 +46,34 @@ class TranslatorC(Translator):
 
     def _size2mask(self, size):
         """Return a C string corresponding to the size2mask operation, with support for
-        @size <= 128"""
+        @size <= 64"""
+        assert size <= 64
         mask = size2mask(size)
-        if size > 64:
-            # Avoid "integer constant is too large for its type" error
-            return "(0x%x | ((uint128_t) 0x%x << 64))" % (
-                mask & 0xFFFFFFFFFFFFFFFF,
-                (mask >> 64) & 0xFFFFFFFFFFFFFFFF,
-            )
         return "0x%x" % mask
 
     def from_ExprId(self, expr):
         return str(expr)
 
     def from_ExprInt(self, expr):
-        if expr.size == 128:
-            # Avoid "integer constant is too large for its type" error
-            return "(0x%x | ((uint128_t) 0x%x << 64))" % (
-                int(expr) & 0xFFFFFFFFFFFFFFFF,
-                (int(expr) >> 64) & 0xFFFFFFFFFFFFFFFF,
-            )
-        return "0x%x" % expr.arg.arg
+        if expr.size <= self.NATIVE_INT_MAX_SIZE:
+            assert expr.size <= 64
+            return "0x%x" % expr.arg.arg
+        value, int_size = int_size_to_bn(int(expr), expr.size)
+        return 'bignum_from_string("%s", %d)' % (value, int_size)
 
     def from_ExprLoc(self, expr):
         loc_key = expr.loc_key
         if self.loc_db is None:
             return str(loc_key)
-
         offset = self.loc_db.get_location_offset(loc_key)
         if offset is None:
             return str(loc_key)
 
-        return "0x%x" % offset
+        if expr.size <= self.NATIVE_INT_MAX_SIZE:
+            return "0x%x" % offset
+
+        value, int_size = int_size_to_bn(offset, 64)
+        return 'bignum_from_string("%s", %d)' % (value, int_size)
 
     def from_ExprAff(self, expr):
         new_dst = self.from_expr(expr.dst)
@@ -67,33 +81,66 @@ class TranslatorC(Translator):
         return "%s = %s" % (new_dst, new_src)
 
     def from_ExprCond(self, expr):
-        new_cond = self.from_expr(expr.cond)
-        new_src1 = self.from_expr(expr.src1)
-        new_src2 = self.from_expr(expr.src2)
-        return "(%s?%s:%s)" % (new_cond, new_src1, new_src2)
+        cond = self.from_expr(expr.cond)
+        src1 = self.from_expr(expr.src1)
+        src2 = self.from_expr(expr.src2)
+        if not expr.cond.size <= self.NATIVE_INT_MAX_SIZE:
+            cond = "(!bignum_is_zero(%s))" % cond
+        out = "(%s?%s:%s)" % (cond, src1, src2)
+        return out
 
     def from_ExprMem(self, expr):
-        new_ptr = self.from_expr(expr.arg)
-        return "MEM_LOOKUP_%.2d(jitcpu, %s)" % (expr.size, new_ptr)
+        ptr = expr.arg
+        if ptr.size <= self.NATIVE_INT_MAX_SIZE:
+            new_ptr = self.from_expr(ptr)
+            if expr.size <= self.NATIVE_INT_MAX_SIZE:
+                # Native ptr, Native Mem
+                return "MEM_LOOKUP_%.2d(jitcpu, %s)" % (expr.size, new_ptr)
+            else:
+                # Native ptr, BN mem
+                return "MEM_LOOKUP_INT_BN(jitcpu, %d, %s)" % (expr.size, new_ptr)
+        # BN ptr
+        new_ptr = self.from_expr(ptr)
+
+        if expr.size <= self.NATIVE_INT_MAX_SIZE:
+            # BN ptr, Native Mem
+            return "MEM_LOOKUP_BN_INT(jitcpu, %d, %s)" % (expr.size, new_ptr)
+        else:
+            # BN ptr, BN mem
+            return "MEM_LOOKUP_BN_BN(jitcpu, %d, %s)" % (expr.size, new_ptr)
 
     def from_ExprOp(self, expr):
         if len(expr.args) == 1:
             if expr.op == 'parity':
-                return "parity(%s&%s)" % (
-                    self.from_expr(expr.args[0]),
-                    self._size2mask(expr.args[0].size),
-                )
+                arg = expr.args[0]
+                out = self.from_expr(arg)
+                if arg.size <= self.NATIVE_INT_MAX_SIZE:
+                    out = "(%s&%s)" % (out, self._size2mask(arg.size))
+                else:
+                    out = 'bignum_mask(%s, 8)' % (out, 8)
+                    out = 'bignum_to_uint64(%s)' % out
+                out = 'parity(%s)' % out
+                return out
+
             elif expr.op in ['cntleadzeros', 'cnttrailzeros']:
-                return "%s(0x%x, %s)" % (
-                    expr.op,
-                    expr.args[0].size,
-                    self.from_expr(expr.args[0])
-                )
+                arg = expr.args[0]
+                out = self.from_expr(arg)
+                if arg.size <= self.NATIVE_INT_MAX_SIZE:
+                    out = "%s(0x%x, %s)" % (expr.op, expr.args[0].size, out)
+                else:
+                    out = "bignum_%s(%s, %d)" % (expr.op, out, arg.size)
+                return out
+
             elif expr.op == '!':
-                return "(~ %s)&%s" % (
-                    self.from_expr(expr.args[0]),
-                    self._size2mask(expr.args[0].size),
-                )
+                arg = expr.args[0]
+                out = self.from_expr(arg)
+                if expr.size <= self.NATIVE_INT_MAX_SIZE:
+                    out = "(~ %s)&%s" % (out, self._size2mask(arg.size))
+                else:
+                    out = "bignum_not(%s)" % out
+                    out = "bignum_mask(%s, expr.size)" % out
+                return out
+
             elif expr.op in [
                     "ftan", "frndint", "f2xm1", "fsin", "fsqrt", "fabs", "fcos",
                     "fchs",
@@ -105,12 +152,23 @@ class TranslatorC(Translator):
                 )
             elif (expr.op.startswith("access_")    or
                   expr.op.startswith("load_")      or
-                  expr.op.startswith("fxam_c")     or
-                  expr.op in ["-"]):
-                return "%s(%s)" % (
-                    expr.op,
-                    self.from_expr(expr.args[0])
-                )
+                  expr.op.startswith("fxam_c")):
+                arg = expr.args[0]
+                out = self.from_expr(arg)
+                out = "%s(%s)" % (expr.op, out)
+                return out
+
+            elif expr.op == "-":
+                arg = expr.args[0]
+                out = self.from_expr(arg)
+                if arg.size <= self.NATIVE_INT_MAX_SIZE:
+                    out = "(%s(%s))" % (expr.op, out)
+                    out = "(%s&%s)" % (out, self._size2mask(arg.size))
+                else:
+                    out = "bignum_sub(bignum_from_uint64(0), %s)" % out
+                    out = "bignum_mask(%s, %d)"% (out, expr.size)
+                return out
+
             elif expr.op.startswith("fpround_"):
                 return "%s_fp%d(%s)" % (
                     expr.op,
@@ -170,20 +228,52 @@ class TranslatorC(Translator):
                     self._size2mask(expr.args[1].size),
                 )
             elif expr.op in self.dct_shift:
-                return 'SHIFT_%s(%d, %s, %s)' % (
-                    self.dct_shift[expr.op].upper(),
-                    expr.args[0].size,
-                    self.from_expr(expr.args[0]),
-                    self.from_expr(expr.args[1])
-                )
-            elif expr.is_associative() or expr.op in ["%", "/"]:
-                oper = ['(%s&%s)' % (
-                    self.from_expr(arg),
-                    self._size2mask(arg.size)
-                )
+                arg0 = self.from_expr(expr.args[0])
+                arg1 = self.from_expr(expr.args[1])
+                if expr.size <= self.NATIVE_INT_MAX_SIZE:
+                    out = 'SHIFT_%s(%d, %s, %s)' % (
+                        self.dct_shift[expr.op].upper(),
+                        expr.args[0].size,
+                        self.from_expr(expr.args[0]),
+                        self.from_expr(expr.args[1])
+                    )
+                else:
+                    op = {
+                        "<<": "lshift",
+                        ">>": "rshift",
+                        "a>>": "a_rshift"
+                    }
+                    out = "bignum_%s(%s, bignum_to_uint64(%s))" % (
+                        op[expr.op], arg0, arg1
+                    )
+                    out = "bignum_mask(%s, %d)"% (out, expr.size)
+                return out
+
+            elif expr.is_associative():
+                args = [self.from_expr(arg)
                         for arg in expr.args]
-                oper = str(expr.op).join(oper)
-                return "((%s)&%s)" % (oper, self._size2mask(expr.args[0].size))
+                if expr.size <= self.NATIVE_INT_MAX_SIZE:
+                    out = (" %s " % expr.op).join(args)
+                    out = "((%s)&%s)" % (out, self._size2mask(expr.size))
+                else:
+                    op_to_bn_func = {
+                    "+": "add",
+                    "*": "mul",
+                    "|": "or",
+                    "^": "xor",
+                    "&": "and",
+                    }
+                    args = list(expr.args)
+                    out = self.from_expr(args.pop())
+                    while args:
+                        out = 'bignum_mask(bignum_%s(%s, %s), %d)' % (
+                            op_to_bn_func[expr.op],
+                            out,
+                            self.from_expr(args.pop()),
+                            expr.size
+                    )
+                return out
+
             elif expr.op in ['-']:
                 return '(((%s&%s) %s (%s&%s))&%s)' % (
                     self.from_expr(expr.args[0]),
@@ -194,13 +284,27 @@ class TranslatorC(Translator):
                     self._size2mask(expr.args[0].size)
                 )
             elif expr.op in self.dct_rot:
-                return '(%s(%s, %s, %s) &%s)' % (
-                    self.dct_rot[expr.op],
-                    expr.args[0].size,
-                    self.from_expr(expr.args[0]),
-                    self.from_expr(expr.args[1]),
-                    self._size2mask(expr.args[0].size),
-                )
+                arg0 = self.from_expr(expr.args[0])
+                arg1 = self.from_expr(expr.args[1])
+                if expr.size <= self.NATIVE_INT_MAX_SIZE:
+                    out = '(%s(%s, %s, %s) &%s)' % (
+                        self.dct_rot[expr.op],
+                        expr.args[0].size,
+                        self.from_expr(expr.args[0]),
+                        self.from_expr(expr.args[1]),
+                        self._size2mask(expr.args[0].size),
+                    )
+                else:
+                    op = {
+                        ">>>": "ror",
+                        "<<<": "rol"
+                    }
+                    out = "bignum_%d(%s, %d, bignum_to_uint64(%s))" % (
+                        op[expr.op], arg0, expr.size, arg1
+                    )
+                    out = "bignum_mask(%s, %d)"% (out, expr.size)
+                return out
+
             elif expr.op == 'x86_cpuid':
                 return "%s(%s, %s)" % (expr.op,
                                        self.from_expr(expr.args[0]),
@@ -208,24 +312,62 @@ class TranslatorC(Translator):
             elif (expr.op.startswith("fcom")  or
                   expr.op in ["fadd", "fsub", "fdiv", 'fmul', "fscale",
                               "fprem", "fprem_lsb", "fyl2x", "fpatan"]):
-                return "fpu_%s%d(%s, %s)" % (
-                    expr.op,
-                    expr.size,
-                    self.from_expr(expr.args[0]),
-                    self.from_expr(expr.args[1]),
-                )
+                arg0 = self.from_expr(expr.args[0])
+                arg1 = self.from_expr(expr.args[1])
+                if not expr.args[0].size <= self.NATIVE_INT_MAX_SIZE:
+                    raise ValueError("Bad semantic: fpu do operations do not support such size")
+                out = "fpu_%s%d(%s, %s)" % (expr.op, expr.size, arg0, arg1)
+                return out
+
             elif expr.op == "segm":
                 return "segm2addr(jitcpu, %s, %s)" % (
                     self.from_expr(expr.args[0]),
                     self.from_expr(expr.args[1])
                 )
-            elif expr.op in ['udiv', 'umod', 'idiv', 'imod']:
-                return '%s%d(%s, %s)' % (
-                    expr.op,
-                    expr.args[0].size,
-                    self.from_expr(expr.args[0]),
-                    self.from_expr(expr.args[1])
-                )
+
+            elif expr.op in ['udiv', 'umod']:
+                arg0 = self.from_expr(expr.args[0])
+                arg1 = self.from_expr(expr.args[1])
+
+                if expr.size <= self.NATIVE_INT_MAX_SIZE:
+                    out = '%s%d(%s, %s)' % (
+                        expr.op,
+                        expr.args[0].size,
+                        self.from_expr(expr.args[0]),
+                        self.from_expr(expr.args[1])
+                    )
+                else:
+                    out = "bignum_%s(%s, %s)" % (
+                        expr.op,
+                        self.from_expr(expr.args[0]),
+                        self.from_expr(expr.args[1])
+                    )
+                    out = "bignum_mask(%s, %d)"% (out, expr.size)
+                return out
+
+
+
+            elif expr.op in ['idiv', 'imod']:
+                arg0 = self.from_expr(expr.args[0])
+                arg1 = self.from_expr(expr.args[1])
+
+                if expr.size <= self.NATIVE_INT_MAX_SIZE:
+                    out = '%s%d(%s, %s)' % (
+                        expr.op,
+                        expr.args[0].size,
+                        self.from_expr(expr.args[0]),
+                        self.from_expr(expr.args[1])
+                    )
+                else:
+                    out = "bignum_%s(%s, %s, %d)" % (
+                        expr.op,
+                        self.from_expr(expr.args[0]),
+                        self.from_expr(expr.args[1]),
+                        expr.size
+                    )
+                    out = "bignum_mask(%s, %d)"% (out, expr.size)
+                return out
+
             elif expr.op in ["bcdadd", "bcdadd_cf"]:
                 return "%s_%d(%s, %s)" % (
                     expr.op, expr.args[0].size,
@@ -250,36 +392,64 @@ class TranslatorC(Translator):
             raise NotImplementedError('Unknown op: %s' % expr.op)
 
     def from_ExprSlice(self, expr):
-        # XXX check mask for 64 bit & 32 bit compat
-        return "((%s>>%d) &%s)" % (
-            self.from_expr(expr.arg),
-            expr.start,
-            self._size2mask(expr.stop - expr.start)
-        )
+        out = self.from_expr(expr.arg)
+        if expr.arg.size <= self.NATIVE_INT_MAX_SIZE:
+            # XXX check mask for 64 bit & 32 bit compat
+            out = "((%s>>%d) &%s)" % (
+                out, expr.start,
+                self._size2mask(expr.stop - expr.start)
+            )
+        else:
+            out = "bignum_rshift(%s, %d)" % (out, expr.start)
+            out = "bignum_mask(%s, %d)" % (out, expr.stop - expr.start)
+
+            if expr.size <= self.NATIVE_INT_MAX_SIZE:
+                # Convert bignum to int
+                out = "bignum_to_uint64(%s)" % out
+        return out
 
     def from_ExprCompose(self, expr):
-        out = []
-        # XXX check mask for 64 bit & 32 bit compat
-        if expr.size in [8, 16, 32, 64, 128]:
-            size = expr.size
+        if expr.size <= self.NATIVE_INT_MAX_SIZE:
+
+            out = []
+            # XXX check mask for 64 bit & 32 bit compat
+            if expr.size in [8, 16, 32, 64, 128]:
+                size = expr.size
+            else:
+                # Uncommon expression size, use at least uint8
+                size = max(expr.size, 8)
+                next_power = 1
+                while next_power <= size:
+                    next_power <<= 1
+                size = next_power
+
+            dst_cast = "uint%d_t" % size
+            for index, arg in expr.iter_args():
+                out.append("(((%s)(%s & %s)) << %d)" % (
+                    dst_cast,
+                    self.from_expr(arg),
+                    self._size2mask(arg.size),
+                    index)
+                )
+            out = ' | '.join(out)
+            return '(' + out + ')'
         else:
-            # Uncommon expression size, use at least uint8
-            size = max(expr.size, 8)
-            next_power = 1
-            while next_power <= size:
-                next_power <<= 1
-            size = next_power
-
-        dst_cast = "uint%d_t" % size
-        for index, arg in expr.iter_args():
-            out.append("(((%s)(%s & %s)) << %d)" % (
-                dst_cast,
-                self.from_expr(arg),
-                self._size2mask(arg.size),
-                index)
-            )
-        out = ' | '.join(out)
-        return '(' + out + ')'
+            # Convert all parts to bignum
+            args = []
+            for index, arg in expr.iter_args():
+                arg_str = self.from_expr(arg)
+                if arg.size <= self.NATIVE_INT_MAX_SIZE:
+                    arg_str = '((%s) & %s)' % (arg_str, self._size2mask(arg.size))
+                    arg_str = 'bignum_from_uint64(%s)' % arg_str
+                else:
+                    arg_str = 'bignum_mask(%s, %d)' % (arg_str, arg.size)
+                arg_str = 'bignum_lshift(%s, %d)' % (arg_str, index)
+                args.append(arg_str)
+            out = args.pop()
+            while args:
+                arg = args.pop()
+                out = "bignum_or(%s, %s)" % (out, arg)
+            return out
 
 
 # Register the class