diff options
| -rw-r--r-- | miasm2/arch/x86/sem.py | 4 | ||||
| -rw-r--r-- | miasm2/ir/translators/C.py | 372 | ||||
| -rw-r--r-- | miasm2/jitter/JitCore.c | 152 | ||||
| -rw-r--r-- | miasm2/jitter/JitCore.h | 108 | ||||
| -rw-r--r-- | miasm2/jitter/Jitllvm.c | 1 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_aarch64.c | 1 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_arm.c | 7 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_mep.c | 1 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_mips32.c | 1 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_msp430.c | 1 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_ppc32.c | 1 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_x86.c | 286 | ||||
| -rw-r--r-- | miasm2/jitter/arch/JitCore_x86.h | 91 | ||||
| -rw-r--r-- | miasm2/jitter/bn.c | 848 | ||||
| -rw-r--r-- | miasm2/jitter/bn.h | 145 | ||||
| -rw-r--r-- | miasm2/jitter/codegen.py | 75 | ||||
| -rw-r--r-- | miasm2/jitter/jitcore_cc_base.py | 1 | ||||
| -rw-r--r-- | miasm2/jitter/llvmconvert.py | 103 | ||||
| -rw-r--r-- | miasm2/jitter/op_semantics.c | 8 | ||||
| -rw-r--r-- | miasm2/jitter/op_semantics.h | 8 | ||||
| -rw-r--r-- | miasm2/jitter/vm_mngr.c | 48 | ||||
| -rw-r--r-- | miasm2/jitter/vm_mngr.h | 22 | ||||
| -rwxr-xr-x | setup.py | 23 |
23 files changed, 1918 insertions, 389 deletions
diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index ef939144..00bdd6d7 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -2820,8 +2820,8 @@ def das(_, instr): def aam(_, instr, src): e = [] tempAL = mRAX[instr.mode][0:8] - newEAX = m2_expr.ExprCompose(tempAL % src, - tempAL / src, + newEAX = m2_expr.ExprCompose(m2_expr.ExprOp("umod", tempAL, src), + m2_expr.ExprOp("udiv", tempAL, src), mRAX[instr.mode][16:]) e += [m2_expr.ExprAff(mRAX[instr.mode], newEAX)] e += update_flag_arith(newEAX) 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 diff --git a/miasm2/jitter/JitCore.c b/miasm2/jitter/JitCore.c index 496ec8e1..1b9790d8 100644 --- a/miasm2/jitter/JitCore.c +++ b/miasm2/jitter/JitCore.c @@ -5,6 +5,7 @@ #include "queue.h" #include "vm_mngr.h" #include "vm_mngr_py.h" +#include "bn.h" #include "JitCore.h" @@ -74,9 +75,85 @@ uint64_t __attribute__((weak)) MEM_LOOKUP_64(JitCpu* jitcpu, uint64_t addr) return vm_MEM_LOOKUP_64(&(jitcpu->pyvm->vm_mngr), addr); } -uint128_t __attribute__((weak)) MEM_LOOKUP_128(JitCpu* jitcpu, uint64_t addr) + +bn_t MEM_LOOKUP_BN_BN(JitCpu* jitcpu, int size, bn_t addr) +{ + uint64_t ptr; + int i; + uint8_t tmp; + bn_t val = bignum_from_int(0); + + ptr = bignum_to_uint64(addr); + + + for (i=0; i < size; i += 8) { + tmp = vm_MEM_LOOKUP_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, ptr); + ptr += 1; + val = bignum_or(val, bignum_lshift(bignum_from_int(tmp), i)); + } + + return val; +} + + +uint64_t MEM_LOOKUP_BN_INT(JitCpu* jitcpu, int size, bn_t addr) +{ + uint64_t ptr; + uint64_t val = 0; + + ptr = bignum_to_uint64(addr); + + switch (size) { + case 8: + val = vm_MEM_LOOKUP_08(&(jitcpu->pyvm->vm_mngr), ptr); + break; + case 16: + val = vm_MEM_LOOKUP_16(&(jitcpu->pyvm->vm_mngr), ptr); + break; + case 32: + val = vm_MEM_LOOKUP_32(&(jitcpu->pyvm->vm_mngr), ptr); + break; + case 64: + val = vm_MEM_LOOKUP_64(&(jitcpu->pyvm->vm_mngr), ptr); + break; + default: + fprintf(stderr, "Error: bad READ size %d\n", size); + exit(-1); + break; + } + + return val; +} + + + +bn_t MEM_LOOKUP_INT_BN(JitCpu* jitcpu, int size, uint64_t addr) +{ + int i; + uint8_t tmp; + bn_t val = bignum_from_int(0); + + for (i=0; i < size; i += 8) { + tmp = vm_MEM_LOOKUP_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr); + addr += 1; + val = bignum_or(val, bignum_lshift(bignum_from_int(tmp), i)); + } + + return val; +} + + +void MEM_LOOKUP_INT_BN_TO_PTR(JitCpu* jitcpu, int size, uint64_t addr, char* ptr) { - return vm_MEM_LOOKUP_128(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr); + bn_t ret; + + if (size % 8) { + fprintf(stderr, "Bad size %d\n", size); + exit(-1); + } + + ret = MEM_LOOKUP_INT_BN(jitcpu, size, addr); + memcpy(ptr, (char*)&ret, size / 8); } void __attribute__((weak)) MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) @@ -99,11 +176,78 @@ void __attribute__((weak)) MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); } -void __attribute__((weak)) MEM_WRITE_128(JitCpu* jitcpu, uint64_t addr, uint128_t src) + +void MEM_WRITE_BN_BN(JitCpu* jitcpu, int size, bn_t addr, bn_t src) +{ + uint64_t ptr; + int val; + int i; + + ptr = bignum_to_uint64(addr); + for (i=0; i < size; i += 8) { + val = bignum_to_uint64(src) & 0xFF; + vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, ptr, val); + ptr += 1; + src = bignum_rshift(src, 8); + } +} + + +void MEM_WRITE_BN_INT(JitCpu* jitcpu, int size, bn_t addr, uint64_t src) +{ + uint64_t ptr; + ptr = bignum_to_uint64(addr); + + switch (size) { + case 8: + vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, ptr, src); + break; + case 16: + vm_MEM_WRITE_16(&((VmMngr*)jitcpu->pyvm)->vm_mngr, ptr, src); + break; + case 32: + vm_MEM_WRITE_32(&((VmMngr*)jitcpu->pyvm)->vm_mngr, ptr, src); + break; + case 64: + vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, ptr, src); + break; + default: + fprintf(stderr, "Error: bad write size %d\n", size); + exit(-1); + break; + } +} + +void MEM_WRITE_INT_BN(JitCpu* jitcpu, int size, uint64_t addr, bn_t src) { - vm_MEM_WRITE_128(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); + int val; + int i; + + for (i=0; i < size; i += 8) { + val = bignum_to_uint64(src) & 0xFF; + vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, val); + addr += 1; + src = bignum_rshift(src, 8); + } } + +void MEM_WRITE_INT_BN_FROM_PTR(JitCpu* jitcpu, int size, uint64_t addr, char* ptr) +{ + bn_t val; + + if (size % 8) { + fprintf(stderr, "Bad size %d\n", size); + exit(-1); + } + + val = bignum_from_int(0); + memcpy(&val, ptr, size / 8); + MEM_WRITE_INT_BN(jitcpu, size, addr, val); +} + + + PyObject* __attribute__((weak)) vm_get_mem(JitCpu *self, PyObject* args) { PyObject *py_addr; diff --git a/miasm2/jitter/JitCore.h b/miasm2/jitter/JitCore.h index c703178d..dfa67b6b 100644 --- a/miasm2/jitter/JitCore.h +++ b/miasm2/jitter/JitCore.h @@ -1,10 +1,11 @@ #ifndef JITCORE_H #define JITCORE_H + + #define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;} #define RAISE_ret0(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return 0;} -#define uint128_t __uint128_t #define PyGetInt(item, value) \ if (PyInt_Check(item)){ \ @@ -31,24 +32,66 @@ } \ -#define getset_reg_u128(regname) \ +#define getset_reg_bn(regname) \ static PyObject *JitCpu_get_ ## regname (JitCpu *self, void *closure) \ - { \ - return _PyLong_FromByteArray((const unsigned char*) &(((vm_cpu_t*)(self->cpu))-> regname ), sizeof(uint128_t), /*little_endian*/ 1, /*is_signed*/ 0); \ + { \ + bn_t bn; \ + PyObject* py_long; \ + PyObject* py_tmp; \ + PyObject* cst_32; \ + uint64_t tmp; \ + py_long = PyLong_FromLong(0); \ + cst_32 = PyLong_FromLong(32); \ + bn = ((vm_cpu_t*)(self->cpu))-> regname; \ + while (!bignum_is_zero(bn)) { \ + tmp = bignum_to_uint64(bignum_mask(bn, 32)) & 0xffffffff; \ + bn = bignum_rshift(bn, 32); \ + py_tmp = PyLong_FromLong(tmp); \ + py_long = PyObject_CallMethod(py_long, "__lshift__", "O", cst_32); \ + py_long = PyObject_CallMethod(py_long, "__add__", "O", py_tmp); \ + } \ + return py_long; \ } \ + \ static int JitCpu_set_ ## regname (JitCpu *self, PyObject *value, void *closure) \ { \ - uint128_t val = 0; \ - int i; \ - unsigned char bytes[sizeof(uint128_t)]; \ - _PyLong_AsByteArray((PyLongObject*)value, bytes, sizeof(uint128_t), /*little_endian*/ 1, /*is_signed*/ 0); \ - for (i = 0; i < sizeof(uint128_t); i++) { \ - val |= (uint128_t) bytes[i] << (8 * i); \ - } \ - ((vm_cpu_t*)(self->cpu))-> regname = val; \ + bn_t bn; \ + int j; \ + PyObject* py_long = value; \ + PyObject* py_tmp; \ + PyObject* cst_32; \ + PyObject* cst_ffffffff; \ + uint64_t tmp; \ + \ + /* Ensure py_long is a PyLong */ \ + if (PyInt_Check(py_long)){ \ + tmp = (uint64_t)PyInt_AsLong(py_long); \ + py_long = PyLong_FromLong(tmp); \ + } else if (PyLong_Check(py_long)){ \ + /* Already PyLong */ \ + } \ + else{ \ + PyErr_SetString(PyExc_TypeError, "Arg must be int"); \ + return -1; \ + } \ + \ + cst_ffffffff = PyLong_FromLong(0xffffffff); \ + cst_32 = PyLong_FromLong(32); \ + bn = bignum_from_int(0); \ + \ + for (j = 0; j < BN_BYTE_SIZE; j += 4) { \ + py_tmp = PyObject_CallMethod(py_long, "__and__", "O", cst_ffffffff); \ + tmp = PyLong_AsUnsignedLongMask(py_tmp); \ + bn = bignum_lshift(bn, 32); \ + bn = bignum_or(bn, bignum_from_uint64(tmp)); \ + py_long = PyObject_CallMethod(py_long, "__rshift__", "O", cst_32); \ + } \ + \ + ((vm_cpu_t*)(self->cpu))-> regname = bn; \ return 0; \ } + #define getset_reg_u64(regname) \ static PyObject *JitCpu_get_ ## regname (JitCpu *self, void *closure) \ { \ @@ -97,6 +140,27 @@ } while(0); +#define get_reg_bn(reg) do { \ + bn_t bn; \ + PyObject* py_long; \ + PyObject* py_tmp; \ + PyObject* cst_32; \ + uint64_t tmp; \ + py_long = PyLong_FromLong(0); \ + cst_32 = PyLong_FromLong(32); \ + bn = ((vm_cpu_t*)(self->cpu))-> reg; \ + while (!bignum_is_zero(bn)) { \ + tmp = bignum_to_uint64(bignum_mask(bn, 32)) & 0xffffffff; \ + bn = bignum_rshift(bn, 32); \ + py_tmp = PyLong_FromLong(tmp); \ + py_long = PyObject_CallMethod(py_long, "__lshift__", "O", cst_32); \ + py_long = PyObject_CallMethod(py_long, "__add__", "O", py_tmp); \ + } \ + PyDict_SetItemString(dict, #reg, py_long); \ + Py_DECREF(py_long); \ + } while(0); + + #define get_reg_off(reg) do { \ o = PyLong_FromUnsignedLongLong((uint64_t)offsetof(vm_cpu_t, reg)); \ PyDict_SetItemString(dict, #reg, o); \ @@ -104,6 +168,8 @@ } while(0); + + typedef struct { uint8_t is_local; uint64_t address; @@ -120,6 +186,7 @@ typedef struct { typedef struct _reg_dict{ char* name; size_t offset; + size_t size; } reg_dict; @@ -140,14 +207,27 @@ uint8_t MEM_LOOKUP_08(JitCpu* jitcpu, uint64_t addr); uint16_t MEM_LOOKUP_16(JitCpu* jitcpu, uint64_t addr); uint32_t MEM_LOOKUP_32(JitCpu* jitcpu, uint64_t addr); uint64_t MEM_LOOKUP_64(JitCpu* jitcpu, uint64_t addr); -uint128_t MEM_LOOKUP_128(JitCpu* jitcpu, uint64_t addr); + +bn_t MEM_LOOKUP_BN_BN(JitCpu* jitcpu, int size, bn_t addr); +bn_t MEM_LOOKUP_INT_BN(JitCpu* jitcpu, int size, uint64_t addr); + +uint64_t MEM_LOOKUP_BN_INT(JitCpu* jitcpu, int size, bn_t addr); + void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src); void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src); void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src); void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src); -void MEM_WRITE_128(JitCpu* jitcpu, uint64_t addr, uint128_t src); + +void MEM_WRITE_BN_BN(JitCpu* jitcpu, int size, bn_t addr, bn_t src); +void MEM_WRITE_BN_INT(JitCpu* jitcpu, int size, bn_t addr, uint64_t src); +void MEM_WRITE_INT_BN(JitCpu* jitcpu, int size, uint64_t addr, bn_t src); + + PyObject* vm_get_mem(JitCpu *self, PyObject* args); +void MEM_LOOKUP_INT_BN_TO_PTR(JitCpu* jitcpu, int size, uint64_t addr, char* ptr); +void MEM_WRITE_INT_BN_FROM_PTR(JitCpu* jitcpu, int size, uint64_t addr, char* ptr); + #define VM_exception_flag (jitcpu->pyvm->vm_mngr.exception_flags) diff --git a/miasm2/jitter/Jitllvm.c b/miasm2/jitter/Jitllvm.c index 6ecbd483..bb500d2e 100644 --- a/miasm2/jitter/Jitllvm.c +++ b/miasm2/jitter/Jitllvm.c @@ -6,6 +6,7 @@ #include "queue.h" #include "vm_mngr.h" #include "vm_mngr_py.h" +#include "bn.h" #include "JitCore.h" // Needed to get the JitCpu.cpu offset, arch independent #include "arch/JitCore_x86.h" diff --git a/miasm2/jitter/arch/JitCore_aarch64.c b/miasm2/jitter/arch/JitCore_aarch64.c index a8502ef9..f5977308 100644 --- a/miasm2/jitter/arch/JitCore_aarch64.c +++ b/miasm2/jitter/arch/JitCore_aarch64.c @@ -5,6 +5,7 @@ #include "../queue.h" #include "../vm_mngr.h" #include "../vm_mngr_py.h" +#include "../bn.h" #include "../JitCore.h" #include "../op_semantics.h" #include "JitCore_aarch64.h" diff --git a/miasm2/jitter/arch/JitCore_arm.c b/miasm2/jitter/arch/JitCore_arm.c index 8a09ba6c..c71db0c6 100644 --- a/miasm2/jitter/arch/JitCore_arm.c +++ b/miasm2/jitter/arch/JitCore_arm.c @@ -5,6 +5,7 @@ #include "../queue.h" #include "../vm_mngr.h" #include "../vm_mngr_py.h" +#include "../bn.h" #include "../JitCore.h" #include "../op_semantics.h" #include "JitCore_arm.h" @@ -380,9 +381,9 @@ static PyGetSetDef JitCpu_getseters[] = { {"cf", (getter)JitCpu_get_cf, (setter)JitCpu_set_cf, "cf", NULL}, {"ge0", (getter)JitCpu_get_ge0, (setter)JitCpu_set_ge0, "ge0", NULL}, - {"ge1", (getter)JitCpu_get_ge1, (setter)JitCpu_set_ge0, "ge1", NULL}, - {"ge2", (getter)JitCpu_get_ge2, (setter)JitCpu_set_ge0, "ge2", NULL}, - {"ge3", (getter)JitCpu_get_ge3, (setter)JitCpu_set_ge0, "ge3", NULL}, + {"ge1", (getter)JitCpu_get_ge1, (setter)JitCpu_set_ge1, "ge1", NULL}, + {"ge2", (getter)JitCpu_get_ge2, (setter)JitCpu_set_ge2, "ge2", NULL}, + {"ge3", (getter)JitCpu_get_ge3, (setter)JitCpu_set_ge3, "ge3", NULL}, {NULL} /* Sentinel */ }; diff --git a/miasm2/jitter/arch/JitCore_mep.c b/miasm2/jitter/arch/JitCore_mep.c index e63fa97b..dff65dd5 100644 --- a/miasm2/jitter/arch/JitCore_mep.c +++ b/miasm2/jitter/arch/JitCore_mep.c @@ -8,6 +8,7 @@ #include "../queue.h" #include "../vm_mngr.h" #include "../vm_mngr_py.h" +#include "../bn.h" #include "../JitCore.h" #include "JitCore_mep.h" diff --git a/miasm2/jitter/arch/JitCore_mips32.c b/miasm2/jitter/arch/JitCore_mips32.c index 4ebfbec8..a1bf44f5 100644 --- a/miasm2/jitter/arch/JitCore_mips32.c +++ b/miasm2/jitter/arch/JitCore_mips32.c @@ -5,6 +5,7 @@ #include "../queue.h" #include "../vm_mngr.h" #include "../vm_mngr_py.h" +#include "../bn.h" #include "../JitCore.h" #include "../op_semantics.h" #include "JitCore_mips32.h" diff --git a/miasm2/jitter/arch/JitCore_msp430.c b/miasm2/jitter/arch/JitCore_msp430.c index 7fe41413..7072a380 100644 --- a/miasm2/jitter/arch/JitCore_msp430.c +++ b/miasm2/jitter/arch/JitCore_msp430.c @@ -5,6 +5,7 @@ #include "../queue.h" #include "../vm_mngr.h" #include "../vm_mngr_py.h" +#include "../bn.h" #include "../JitCore.h" #include "JitCore_msp430.h" diff --git a/miasm2/jitter/arch/JitCore_ppc32.c b/miasm2/jitter/arch/JitCore_ppc32.c index 616e7cfd..3acf769a 100644 --- a/miasm2/jitter/arch/JitCore_ppc32.c +++ b/miasm2/jitter/arch/JitCore_ppc32.c @@ -5,6 +5,7 @@ #include "../queue.h" #include "../vm_mngr.h" #include "../vm_mngr_py.h" +#include "../bn.h" #include "../JitCore.h" #include "JitCore_ppc32.h" diff --git a/miasm2/jitter/arch/JitCore_x86.c b/miasm2/jitter/arch/JitCore_x86.c index eda6e6e5..cc3f8573 100644 --- a/miasm2/jitter/arch/JitCore_x86.c +++ b/miasm2/jitter/arch/JitCore_x86.c @@ -5,78 +5,79 @@ #include "../queue.h" #include "../vm_mngr.h" #include "../vm_mngr_py.h" +#include "../bn.h" #include "../JitCore.h" #include "../op_semantics.h" #include "JitCore_x86.h" - - -reg_dict gpreg_dict[] = { {.name = "RAX", .offset = offsetof(vm_cpu_t, RAX)}, - {.name = "RBX", .offset = offsetof(vm_cpu_t, RBX)}, - {.name = "RCX", .offset = offsetof(vm_cpu_t, RCX)}, - {.name = "RDX", .offset = offsetof(vm_cpu_t, RDX)}, - {.name = "RSI", .offset = offsetof(vm_cpu_t, RSI)}, - {.name = "RDI", .offset = offsetof(vm_cpu_t, RDI)}, - {.name = "RSP", .offset = offsetof(vm_cpu_t, RSP)}, - {.name = "RBP", .offset = offsetof(vm_cpu_t, RBP)}, - - {.name = "R8", .offset = offsetof(vm_cpu_t, R8)}, - {.name = "R9", .offset = offsetof(vm_cpu_t, R9)}, - {.name = "R10", .offset = offsetof(vm_cpu_t, R10)}, - {.name = "R11", .offset = offsetof(vm_cpu_t, R11)}, - {.name = "R12", .offset = offsetof(vm_cpu_t, R12)}, - {.name = "R13", .offset = offsetof(vm_cpu_t, R13)}, - {.name = "R14", .offset = offsetof(vm_cpu_t, R14)}, - {.name = "R15", .offset = offsetof(vm_cpu_t, R15)}, - - {.name = "RIP", .offset = offsetof(vm_cpu_t, RIP)}, - - {.name = "zf", .offset = offsetof(vm_cpu_t, zf)}, - {.name = "nf", .offset = offsetof(vm_cpu_t, nf)}, - {.name = "pf", .offset = offsetof(vm_cpu_t, pf)}, - {.name = "of", .offset = offsetof(vm_cpu_t, of)}, - {.name = "cf", .offset = offsetof(vm_cpu_t, cf)}, - {.name = "af", .offset = offsetof(vm_cpu_t, af)}, - {.name = "df", .offset = offsetof(vm_cpu_t, df)}, - - {.name = "ES", .offset = offsetof(vm_cpu_t, ES)}, - {.name = "CS", .offset = offsetof(vm_cpu_t, CS)}, - {.name = "SS", .offset = offsetof(vm_cpu_t, SS)}, - {.name = "DS", .offset = offsetof(vm_cpu_t, DS)}, - {.name = "FS", .offset = offsetof(vm_cpu_t, FS)}, - {.name = "GS", .offset = offsetof(vm_cpu_t, GS)}, - - {.name = "MM0", .offset = offsetof(vm_cpu_t, MM0)}, - {.name = "MM1", .offset = offsetof(vm_cpu_t, MM1)}, - {.name = "MM2", .offset = offsetof(vm_cpu_t, MM2)}, - {.name = "MM3", .offset = offsetof(vm_cpu_t, MM3)}, - {.name = "MM4", .offset = offsetof(vm_cpu_t, MM4)}, - {.name = "MM5", .offset = offsetof(vm_cpu_t, MM5)}, - {.name = "MM6", .offset = offsetof(vm_cpu_t, MM6)}, - {.name = "MM7", .offset = offsetof(vm_cpu_t, MM7)}, - - {.name = "XMM0", .offset = offsetof(vm_cpu_t, XMM0)}, - {.name = "XMM1", .offset = offsetof(vm_cpu_t, XMM1)}, - {.name = "XMM2", .offset = offsetof(vm_cpu_t, XMM2)}, - {.name = "XMM3", .offset = offsetof(vm_cpu_t, XMM3)}, - {.name = "XMM4", .offset = offsetof(vm_cpu_t, XMM4)}, - {.name = "XMM5", .offset = offsetof(vm_cpu_t, XMM5)}, - {.name = "XMM6", .offset = offsetof(vm_cpu_t, XMM6)}, - {.name = "XMM7", .offset = offsetof(vm_cpu_t, XMM7)}, - {.name = "XMM8", .offset = offsetof(vm_cpu_t, XMM8)}, - {.name = "XMM9", .offset = offsetof(vm_cpu_t, XMM9)}, - {.name = "XMM10", .offset = offsetof(vm_cpu_t, XMM10)}, - {.name = "XMM11", .offset = offsetof(vm_cpu_t, XMM11)}, - {.name = "XMM12", .offset = offsetof(vm_cpu_t, XMM12)}, - {.name = "XMM13", .offset = offsetof(vm_cpu_t, XMM13)}, - {.name = "XMM14", .offset = offsetof(vm_cpu_t, XMM14)}, - {.name = "XMM15", .offset = offsetof(vm_cpu_t, XMM15)}, - - {.name = "tsc1", .offset = offsetof(vm_cpu_t, tsc1)}, - {.name = "tsc2", .offset = offsetof(vm_cpu_t, tsc2)}, - - {.name = "exception_flags", .offset = offsetof(vm_cpu_t, exception_flags)}, - {.name = "interrupt_num", .offset = offsetof(vm_cpu_t, interrupt_num)}, +vm_cpu_t ref_arch_regs; + +reg_dict gpreg_dict[] = { {.name = "RAX", .offset = offsetof(vm_cpu_t, RAX), .size = 8*sizeof(ref_arch_regs.RAX)}, + {.name = "RBX", .offset = offsetof(vm_cpu_t, RBX), .size = 8*sizeof(ref_arch_regs.RBX)}, + {.name = "RCX", .offset = offsetof(vm_cpu_t, RCX), .size = 8*sizeof(ref_arch_regs.RCX)}, + {.name = "RDX", .offset = offsetof(vm_cpu_t, RDX), .size = 8*sizeof(ref_arch_regs.RDX)}, + {.name = "RSI", .offset = offsetof(vm_cpu_t, RSI), .size = 8*sizeof(ref_arch_regs.RSI)}, + {.name = "RDI", .offset = offsetof(vm_cpu_t, RDI), .size = 8*sizeof(ref_arch_regs.RDI)}, + {.name = "RSP", .offset = offsetof(vm_cpu_t, RSP), .size = 8*sizeof(ref_arch_regs.RSP)}, + {.name = "RBP", .offset = offsetof(vm_cpu_t, RBP), .size = 8*sizeof(ref_arch_regs.RBP)}, + + {.name = "R8", .offset = offsetof(vm_cpu_t, R8), .size = 8*sizeof(ref_arch_regs.R8)}, + {.name = "R9", .offset = offsetof(vm_cpu_t, R9), .size = 8*sizeof(ref_arch_regs.R9)}, + {.name = "R10", .offset = offsetof(vm_cpu_t, R10), .size = 8*sizeof(ref_arch_regs.R10)}, + {.name = "R11", .offset = offsetof(vm_cpu_t, R11), .size = 8*sizeof(ref_arch_regs.R11)}, + {.name = "R12", .offset = offsetof(vm_cpu_t, R12), .size = 8*sizeof(ref_arch_regs.R12)}, + {.name = "R13", .offset = offsetof(vm_cpu_t, R13), .size = 8*sizeof(ref_arch_regs.R13)}, + {.name = "R14", .offset = offsetof(vm_cpu_t, R14), .size = 8*sizeof(ref_arch_regs.R14)}, + {.name = "R15", .offset = offsetof(vm_cpu_t, R15), .size = 8*sizeof(ref_arch_regs.R15)}, + + {.name = "RIP", .offset = offsetof(vm_cpu_t, RIP), .size = 8*sizeof(ref_arch_regs.RIP)}, + + {.name = "zf", .offset = offsetof(vm_cpu_t, zf), .size = 8*sizeof(ref_arch_regs.zf)}, + {.name = "nf", .offset = offsetof(vm_cpu_t, nf), .size = 8*sizeof(ref_arch_regs.nf)}, + {.name = "pf", .offset = offsetof(vm_cpu_t, pf), .size = 8*sizeof(ref_arch_regs.pf)}, + {.name = "of", .offset = offsetof(vm_cpu_t, of), .size = 8*sizeof(ref_arch_regs.of)}, + {.name = "cf", .offset = offsetof(vm_cpu_t, cf), .size = 8*sizeof(ref_arch_regs.cf)}, + {.name = "af", .offset = offsetof(vm_cpu_t, af), .size = 8*sizeof(ref_arch_regs.af)}, + {.name = "df", .offset = offsetof(vm_cpu_t, df), .size = 8*sizeof(ref_arch_regs.df)}, + + {.name = "ES", .offset = offsetof(vm_cpu_t, ES), .size = 8*sizeof(ref_arch_regs.ES)}, + {.name = "CS", .offset = offsetof(vm_cpu_t, CS), .size = 8*sizeof(ref_arch_regs.CS)}, + {.name = "SS", .offset = offsetof(vm_cpu_t, SS), .size = 8*sizeof(ref_arch_regs.SS)}, + {.name = "DS", .offset = offsetof(vm_cpu_t, DS), .size = 8*sizeof(ref_arch_regs.DS)}, + {.name = "FS", .offset = offsetof(vm_cpu_t, FS), .size = 8*sizeof(ref_arch_regs.FS)}, + {.name = "GS", .offset = offsetof(vm_cpu_t, GS), .size = 8*sizeof(ref_arch_regs.GS)}, + + {.name = "MM0", .offset = offsetof(vm_cpu_t, MM0), .size = 8*sizeof(ref_arch_regs.MM0)}, + {.name = "MM1", .offset = offsetof(vm_cpu_t, MM1), .size = 8*sizeof(ref_arch_regs.MM1)}, + {.name = "MM2", .offset = offsetof(vm_cpu_t, MM2), .size = 8*sizeof(ref_arch_regs.MM2)}, + {.name = "MM3", .offset = offsetof(vm_cpu_t, MM3), .size = 8*sizeof(ref_arch_regs.MM3)}, + {.name = "MM4", .offset = offsetof(vm_cpu_t, MM4), .size = 8*sizeof(ref_arch_regs.MM4)}, + {.name = "MM5", .offset = offsetof(vm_cpu_t, MM5), .size = 8*sizeof(ref_arch_regs.MM5)}, + {.name = "MM6", .offset = offsetof(vm_cpu_t, MM6), .size = 8*sizeof(ref_arch_regs.MM6)}, + {.name = "MM7", .offset = offsetof(vm_cpu_t, MM7), .size = 8*sizeof(ref_arch_regs.MM7)}, + + {.name = "XMM0", .offset = offsetof(vm_cpu_t, XMM0), .size = 128}, + {.name = "XMM1", .offset = offsetof(vm_cpu_t, XMM1), .size = 128}, + {.name = "XMM2", .offset = offsetof(vm_cpu_t, XMM2), .size = 128}, + {.name = "XMM3", .offset = offsetof(vm_cpu_t, XMM3), .size = 128}, + {.name = "XMM4", .offset = offsetof(vm_cpu_t, XMM4), .size = 128}, + {.name = "XMM5", .offset = offsetof(vm_cpu_t, XMM5), .size = 128}, + {.name = "XMM6", .offset = offsetof(vm_cpu_t, XMM6), .size = 128}, + {.name = "XMM7", .offset = offsetof(vm_cpu_t, XMM7), .size = 128}, + {.name = "XMM8", .offset = offsetof(vm_cpu_t, XMM8), .size = 128}, + {.name = "XMM9", .offset = offsetof(vm_cpu_t, XMM9), .size = 128}, + {.name = "XMM10", .offset = offsetof(vm_cpu_t, XMM10), .size = 128}, + {.name = "XMM11", .offset = offsetof(vm_cpu_t, XMM11), .size = 128}, + {.name = "XMM12", .offset = offsetof(vm_cpu_t, XMM12), .size = 128}, + {.name = "XMM13", .offset = offsetof(vm_cpu_t, XMM13), .size = 128}, + {.name = "XMM14", .offset = offsetof(vm_cpu_t, XMM14), .size = 128}, + {.name = "XMM15", .offset = offsetof(vm_cpu_t, XMM15), .size = 128}, + + {.name = "tsc1", .offset = offsetof(vm_cpu_t, tsc1), .size = 8*sizeof(ref_arch_regs.tsc1)}, + {.name = "tsc2", .offset = offsetof(vm_cpu_t, tsc2), .size = 8*sizeof(ref_arch_regs.tsc2)}, + + {.name = "exception_flags", .offset = offsetof(vm_cpu_t, exception_flags), .size = 8*sizeof(ref_arch_regs.exception_flags)}, + {.name = "interrupt_num", .offset = offsetof(vm_cpu_t, interrupt_num), .size = 8*sizeof(ref_arch_regs.interrupt_num)}, }; @@ -137,22 +138,22 @@ PyObject* cpu_get_gpreg(JitCpu* self) get_reg(MM6); get_reg(MM7); - get_reg(XMM0); - get_reg(XMM1); - get_reg(XMM2); - get_reg(XMM3); - get_reg(XMM4); - get_reg(XMM5); - get_reg(XMM6); - get_reg(XMM7); - get_reg(XMM8); - get_reg(XMM9); - get_reg(XMM10); - get_reg(XMM11); - get_reg(XMM12); - get_reg(XMM13); - get_reg(XMM14); - get_reg(XMM15); + get_reg_bn(XMM0); + get_reg_bn(XMM1); + get_reg_bn(XMM2); + get_reg_bn(XMM3); + get_reg_bn(XMM4); + get_reg_bn(XMM5); + get_reg_bn(XMM6); + get_reg_bn(XMM7); + get_reg_bn(XMM8); + get_reg_bn(XMM9); + get_reg_bn(XMM10); + get_reg_bn(XMM11); + get_reg_bn(XMM12); + get_reg_bn(XMM13); + get_reg_bn(XMM14); + get_reg_bn(XMM15); get_reg(tsc1); get_reg(tsc2); @@ -180,14 +181,68 @@ PyObject* cpu_set_gpreg(JitCpu* self, PyObject *args) if(!PyString_Check(d_key)) RAISE(PyExc_TypeError, "key must be str"); - PyGetInt(d_value, val); - found = 0; for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){ if (strcmp(PyString_AsString(d_key), gpreg_dict[i].name)) continue; - *((uint64_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val; found = 1; + switch (gpreg_dict[i].size) { + case 8: + PyGetInt(d_value, val); + *((uint8_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val; + break; + case 16: + PyGetInt(d_value, val); + *((uint16_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val; + break; + case 32: + PyGetInt(d_value, val); + *((uint32_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val; + break; + case 64: + PyGetInt(d_value, val); + *((uint64_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val; + break; + case 128: + { + bn_t bn; + int j; + PyObject* py_long = d_value; + PyObject* py_tmp; + PyObject* cst_32; + PyObject* cst_ffffffff; + uint64_t tmp; + + /* Ensure py_long is a PyLong */ + if (PyInt_Check(py_long)){ + tmp = (uint64_t)PyInt_AsLong(py_long); + py_long = PyLong_FromLong(tmp); + } else if (PyLong_Check(py_long)){ + /* Already PyLong */ + } + else{ + RAISE(PyExc_TypeError,"arg must be int"); + } + + + + cst_ffffffff = PyLong_FromLong(0xffffffff); + cst_32 = PyLong_FromLong(32); + bn = bignum_from_int(0); + + for (j = 0; j < BN_BYTE_SIZE; j += 4) { + py_tmp = PyObject_CallMethod(py_long, "__and__", "O", cst_ffffffff); + tmp = PyLong_AsUnsignedLongMask(py_tmp); + bn = bignum_lshift(bn, 32); + bn = bignum_or(bn, bignum_from_uint64(tmp)); + py_long = PyObject_CallMethod(py_long, "__rshift__", "O", cst_32); + } + + + *(bn_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset) = bn; + } + break; + } break; } @@ -203,11 +258,9 @@ PyObject* cpu_set_gpreg(JitCpu* self, PyObject *args) PyObject * cpu_init_regs(JitCpu* self) { memset(self->cpu, 0, sizeof(vm_cpu_t)); - ((vm_cpu_t*)self->cpu)->tsc1 = 0x22222222; ((vm_cpu_t*)self->cpu)->tsc2 = 0x11111111; ((vm_cpu_t*)self->cpu)->i_f = 1; - Py_INCREF(Py_None); return Py_None; @@ -215,7 +268,6 @@ PyObject * cpu_init_regs(JitCpu* self) void dump_gpregs_16(vm_cpu_t* vmcpu) { - printf("EAX %.8"PRIX32" EBX %.8"PRIX32" ECX %.8"PRIX32" EDX %.8"PRIX32" ", (uint32_t)(vmcpu->RAX & 0xFFFFFFFF), (uint32_t)(vmcpu->RBX & 0xFFFFFFFF), @@ -228,12 +280,11 @@ void dump_gpregs_16(vm_cpu_t* vmcpu) (uint32_t)(vmcpu->RBP & 0xFFFFFFFF)); printf("EIP %.8"PRIX32" ", (uint32_t)(vmcpu->RIP & 0xFFFFFFFF)); - printf("zf %.1"PRIX32" nf %.1"PRIX32" of %.1"PRIX32" cf %.1"PRIX32"\n", + printf("zf %.1d nf %.1d of %.1d cf %.1d\n", (uint32_t)(vmcpu->zf & 0x1), (uint32_t)(vmcpu->nf & 0x1), (uint32_t)(vmcpu->of & 0x1), (uint32_t)(vmcpu->cf & 0x1)); - } void dump_gpregs_32(vm_cpu_t* vmcpu) @@ -251,7 +302,7 @@ void dump_gpregs_32(vm_cpu_t* vmcpu) (uint32_t)(vmcpu->RBP & 0xFFFFFFFF)); printf("EIP %.8"PRIX32" ", (uint32_t)(vmcpu->RIP & 0xFFFFFFFF)); - printf("zf %.1"PRIX32" nf %.1"PRIX32" of %.1"PRIX32" cf %.1"PRIX32"\n", + printf("zf %.1d nf %.1d of %.1d cf %.1d\n", (uint32_t)(vmcpu->zf & 0x1), (uint32_t)(vmcpu->nf & 0x1), (uint32_t)(vmcpu->of & 0x1), @@ -274,7 +325,7 @@ void dump_gpregs_64(vm_cpu_t* vmcpu) vmcpu->R12, vmcpu->R13, vmcpu->R14, vmcpu->R15); - printf("zf %.1"PRIX64" nf %.1"PRIX64" of %.1"PRIX64" cf %.1"PRIX64"\n", + printf("zf %.1d nf %.1d of %.1d cf %.1d\n", vmcpu->zf, vmcpu->nf, vmcpu->of, vmcpu->cf); } @@ -459,7 +510,6 @@ JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) return 0; } - #define getset_reg_E_u32(regname) \ static PyObject *JitCpu_get_E ## regname (JitCpu *self, void *closure) \ { \ @@ -522,13 +572,12 @@ getset_reg_u64(af); getset_reg_u64(df); -getset_reg_u64(ES); -getset_reg_u64(CS); -getset_reg_u64(SS); -getset_reg_u64(DS); -getset_reg_u64(FS); -getset_reg_u64(GS); - +getset_reg_u16(ES); +getset_reg_u16(CS); +getset_reg_u16(SS); +getset_reg_u16(DS); +getset_reg_u16(FS); +getset_reg_u16(GS); getset_reg_E_u32(AX); getset_reg_E_u32(BX); @@ -560,22 +609,22 @@ getset_reg_u64(MM5); getset_reg_u64(MM6); getset_reg_u64(MM7); -getset_reg_u128(XMM0); -getset_reg_u128(XMM1); -getset_reg_u128(XMM2); -getset_reg_u128(XMM3); -getset_reg_u128(XMM4); -getset_reg_u128(XMM5); -getset_reg_u128(XMM6); -getset_reg_u128(XMM7); -getset_reg_u128(XMM8); -getset_reg_u128(XMM9); -getset_reg_u128(XMM10); -getset_reg_u128(XMM11); -getset_reg_u128(XMM12); -getset_reg_u128(XMM13); -getset_reg_u128(XMM14); -getset_reg_u128(XMM15); +getset_reg_bn(XMM0); +getset_reg_bn(XMM1); +getset_reg_bn(XMM2); +getset_reg_bn(XMM3); +getset_reg_bn(XMM4); +getset_reg_bn(XMM5); +getset_reg_bn(XMM6); +getset_reg_bn(XMM7); +getset_reg_bn(XMM8); +getset_reg_bn(XMM9); +getset_reg_bn(XMM10); +getset_reg_bn(XMM11); +getset_reg_bn(XMM12); +getset_reg_bn(XMM13); +getset_reg_bn(XMM14); +getset_reg_bn(XMM15); getset_reg_u32(tsc1); getset_reg_u32(tsc2); @@ -588,7 +637,6 @@ PyObject* get_gpreg_offset_all(void) { PyObject *dict = PyDict_New(); PyObject *o; - get_reg_off(exception_flags); get_reg_off(RAX); diff --git a/miasm2/jitter/arch/JitCore_x86.h b/miasm2/jitter/arch/JitCore_x86.h index a5fc4bd4..cde113ab 100644 --- a/miasm2/jitter/arch/JitCore_x86.h +++ b/miasm2/jitter/arch/JitCore_x86.h @@ -1,4 +1,5 @@ -#define uint128_t __uint128_t +#include "../bn.h" + typedef struct { uint32_t exception_flags; @@ -26,28 +27,28 @@ typedef struct { uint64_t RIP; /* eflag */ - uint64_t zf; - uint64_t nf; - uint64_t pf; - uint64_t of; - uint64_t cf; - uint64_t af; - uint64_t df; - - uint64_t tf; - uint64_t i_f; - uint64_t iopl_f; - uint64_t nt; - uint64_t rf; - uint64_t vm; - uint64_t ac; - uint64_t vif; - uint64_t vip; - uint64_t i_d; - - uint64_t my_tick; - - uint64_t cond; + uint8_t zf; + uint8_t nf; + uint8_t pf; + uint8_t of; + uint8_t cf; + uint8_t af; + uint8_t df; + + uint8_t tf; + uint8_t i_f; + uint8_t iopl_f; + uint8_t nt; + uint8_t rf; + uint8_t vm; + uint8_t ac; + uint8_t vif; + uint8_t vip; + uint8_t i_d; + + bn_t my_tick; + + bn_t cond; uint64_t float_st0; uint64_t float_st1; @@ -78,12 +79,12 @@ typedef struct { uint64_t tsc2; - uint64_t ES; - uint64_t CS; - uint64_t SS; - uint64_t DS; - uint64_t FS; - uint64_t GS; + uint16_t ES; + uint16_t CS; + uint16_t SS; + uint16_t DS; + uint16_t FS; + uint16_t GS; unsigned int cr0; unsigned int cr3; @@ -98,22 +99,22 @@ typedef struct { uint64_t MM7; /* SSE */ - uint128_t XMM0; - uint128_t XMM1; - uint128_t XMM2; - uint128_t XMM3; - uint128_t XMM4; - uint128_t XMM5; - uint128_t XMM6; - uint128_t XMM7; - uint128_t XMM8; - uint128_t XMM9; - uint128_t XMM10; - uint128_t XMM11; - uint128_t XMM12; - uint128_t XMM13; - uint128_t XMM14; - uint128_t XMM15; + bn_t XMM0; + bn_t XMM1; + bn_t XMM2; + bn_t XMM3; + bn_t XMM4; + bn_t XMM5; + bn_t XMM6; + bn_t XMM7; + bn_t XMM8; + bn_t XMM9; + bn_t XMM10; + bn_t XMM11; + bn_t XMM12; + bn_t XMM13; + bn_t XMM14; + bn_t XMM15; uint32_t segm_base[0x10000]; diff --git a/miasm2/jitter/bn.c b/miasm2/jitter/bn.c new file mode 100644 index 00000000..9462de2c --- /dev/null +++ b/miasm2/jitter/bn.c @@ -0,0 +1,848 @@ +/* + +Big number library - arithmetic on multiple-precision unsigned integers. + +This library is an implementation of arithmetic on arbitrarily large integers. + +The difference between this and other implementations, is that the data structure +has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), +and all memory is allocated statically: no dynamic allocation for better or worse. + +Primary goals are correctness, clarity of code and clean, portable implementation. +Secondary goal is a memory footprint small enough to make it suitable for use in +embedded applications. + + +The current state is correct functionality and adequate performance. +There may well be room for performance-optimizations and improvements. + +Source: https://github.com/kokke/tiny-bignum-c + +Code slightly modified to support ast generation calculus style from Expr. + +*/ + +#include <stdio.h> +#include <stdbool.h> +#include <inttypes.h> +#include <assert.h> +#include "bn.h" + +/* Functions for shifting number in-place. */ +static bn_t _lshift_one_bit(bn_t a); +static bn_t _rshift_one_bit(bn_t a); +static bn_t _lshift_word(bn_t a, int nwords); +static bn_t _rshift_word(bn_t a, int nwords); + + + + +/* Public / Exported functions. */ +bn_t bignum_init(void) +{ + int i; + bn_t n; + + for (i = 0; i < BN_ARRAY_SIZE; ++i) { + n.array[i] = 0; + } + + return n; +} + + +bn_t bignum_from_int(DTYPE_TMP i) +{ + bn_t n; + + n = bignum_init(); + /* Endianness issue if machine is not little-endian? */ +#ifdef WORD_SIZE + #if (WORD_SIZE == 1) + n.array[0] = (i & 0x000000ff); + n.array[1] = (i & 0x0000ff00) >> 8; + n.array[2] = (i & 0x00ff0000) >> 16; + n.array[3] = (i & 0xff000000) >> 24; + #elif (WORD_SIZE == 2) + n.array[0] = (i & 0x0000ffff); + n.array[1] = (i & 0xffff0000) >> 16; + #elif (WORD_SIZE == 4) + n.array[0] = i; + DTYPE_TMP num_32 = 32; + DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */ + n.array[1] = tmp; + #endif +#endif + + return n; +} + + + +bn_t bignum_from_uint64(uint64_t i) +{ + bn_t n; + n = bignum_init(); + /* Endianness issue if machine is not little-endian? */ +#ifdef WORD_SIZE + #if (WORD_SIZE == 1) + n.array[0] = (i & 0x000000ff); + n.array[1] = (i & 0x0000ff00) >> 8; + n.array[2] = (i & 0x00ff0000) >> 16; + n.array[3] = (i & 0xff000000) >> 24; + #elif (WORD_SIZE == 2) + n.array[0] = (i & 0x0000ffff); + n.array[1] = (i & 0xffff0000) >> 16; + #elif (WORD_SIZE == 4) + n.array[0] = i; + DTYPE_TMP num_32 = 32; + DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */ + n.array[1] = tmp; + #endif +#endif + + return n; +} + + + + + +int bignum_to_int(bn_t n) +{ + + int ret = 0; + + /* Endianness issue if machine is not little-endian? */ +#if (WORD_SIZE == 1) + ret += n.array[0]; + ret += n.array[1] << 8; + ret += n.array[2] << 16; + ret += n.array[3] << 24; +#elif (WORD_SIZE == 2) + ret += n.array[0]; + ret += n.array[1] << 16; +#elif (WORD_SIZE == 4) + ret += n.array[0]; +#endif + + + return ret; +} + + +uint64_t bignum_to_uint64(bn_t n) +{ + + uint64_t ret = 0; + + /* Endianness issue if machine is not little-endian? */ +#if (WORD_SIZE == 1) + ret += (uint64_t)(n.array[0]); + ret += (uint64_t)(n.array[1]) << 8; + ret += (uint64_t)(n.array[2]) << 16; + ret += (uint64_t)(n.array[3]) << 24; + + ret += (uint64_t)(n.array[4]) << 32; + ret += (uint64_t)(n.array[5]) << 40; + ret += (uint64_t)(n.array[6]) << 48; + ret += (uint64_t)(n.array[7]) << 56; + + +#elif (WORD_SIZE == 2) + ret += (uint64_t)(n.array[0]); + ret += (uint64_t)(n.array[1]) << 16; + ret += (uint64_t)(n.array[2]) << 32; + ret += (uint64_t)(n.array[3]) << 48; +#elif (WORD_SIZE == 4) + ret += n.array[0]; + ret += (uint64_t)(n.array[1]) << 32; +#endif + + return ret; +} + + + + +bn_t bignum_from_string(char* str, int nbytes) +{ + + require(str, "str is null"); + require(nbytes > 0, "nbytes must be positive"); + require((nbytes & 1) == 0, "string format must be in hex -> equal number of bytes"); + + bn_t n; + + n = bignum_init(); + + DTYPE tmp; /* DTYPE is defined in bn.h - uint{8,16,32,64}_t */ + int i = nbytes - (2 * WORD_SIZE); /* index into string */ + int j = 0; /* index into array */ + + /* reading last hex-byte "MSB" from string first -> big endian */ + /* MSB ~= most significant byte / block ? :) */ + while (i >= 0) { + tmp = 0; + sscanf(&str[i], SSCANF_FORMAT_STR, &tmp); + n.array[j] = tmp; + i -= (2 * WORD_SIZE); /* step WORD_SIZE hex-byte(s) back in the string. */ + j += 1; /* step one element forward in the array. */ + } + + return n; +} + +void bignum_to_string(bn_t n, char* str, int nbytes) +{ + require(str, "str is null"); + require(nbytes > 0, "nbytes must be positive"); + require((nbytes & 1) == 0, "string format must be in hex -> equal number of bytes"); + + int j = BN_ARRAY_SIZE - 1; /* index into array - reading "MSB" first -> big-endian */ + int i = 0; /* index into string representation. */ + + /* reading last array-element "MSB" first -> big endian */ + while ((j >= 0) && (nbytes > (i + 1))) { + sprintf(&str[i], SPRINTF_FORMAT_STR, n.array[j]); + i += (2 * WORD_SIZE); /* step WORD_SIZE hex-byte(s) forward in the string. */ + j -= 1; /* step one element back in the array. */ + } + + /* Zero-terminate string */ + str[i] = 0; +} + + + +bn_t bignum_dec(bn_t n) +{ + //require(n, "n is null"); + + DTYPE tmp; /* copy of n */ + DTYPE res; + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) { + tmp = n.array[i]; + res = tmp - 1; + n.array[i] = res; + + if (!(res > tmp)) { + break; + } + } + + return n; +} + + +bn_t bignum_inc(bn_t n) +{ + //require(n, "n is null"); + + DTYPE res; + DTYPE_TMP tmp; /* copy of n */ + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) { + tmp = n.array[i]; + res = tmp + 1; + n.array[i] = res; + + if (res > tmp) { + break; + } + } + + return n; +} + + + +bn_t bignum_add(bn_t a, bn_t b) +{ + //require(a, "a is null"); + //require(b, "b is null"); + //require(c, "c is null"); + bn_t c; + + DTYPE_TMP tmp; + int carry = 0; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) { + tmp = (DTYPE_TMP)a.array[i] + b.array[i] + carry; + carry = (tmp > MAX_VAL); + c.array[i] = (tmp & MAX_VAL); + } + + return c; +} + + +bn_t bignum_sub(bn_t a, bn_t b) +{ + //require(a, "a is null"); + //require(b, "b is null"); + //require(c, "c is null"); + bn_t c; + + DTYPE_TMP res; + DTYPE_TMP tmp1; + DTYPE_TMP tmp2; + int borrow = 0; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) { + tmp1 = (DTYPE_TMP)a.array[i] + (MAX_VAL + 1); /* + number_base */ + tmp2 = (DTYPE_TMP)b.array[i] + borrow;; + res = (tmp1 - tmp2); + c.array[i] = (DTYPE)(res & MAX_VAL); /* "modulo number_base" == "% (number_base - 1)" if number_base is 2^N */ + borrow = (res <= MAX_VAL); + } + + return c; +} + + + + +bn_t bignum_mul(bn_t a, bn_t b) +{ + //require(a, "a is null"); + //require(b, "b is null"); + //require(c, "c is null"); + + bn_t c; + bn_t row; + bn_t tmp; + int i, j; + + c = bignum_init(); + + for (i = 0; i < BN_ARRAY_SIZE; ++i) { + row = bignum_init(); + + for (j = 0; j < BN_ARRAY_SIZE; ++j) { + if (i + j < BN_ARRAY_SIZE) { + tmp = bignum_init(); + DTYPE_TMP intermediate = ((DTYPE_TMP)a.array[i] * (DTYPE_TMP)b.array[j]); + tmp = bignum_from_int(intermediate); + tmp = _lshift_word(tmp, i + j); + row = bignum_add(tmp, row); + } + } + c = bignum_add(c, row); + } + + return c; +} + + +bn_t bignum_udiv(bn_t a, bn_t b) +{ + //require(a, "a is null"); + //require(b, "b is null"); + //require(c, "c is null"); + + bn_t c; + bn_t current; + bn_t denom; + bn_t tmp; + + current = bignum_from_int(1); // int current = 1; + denom = bignum_assign(b); // denom = b + tmp = bignum_assign(a); // tmp = a + + const DTYPE_TMP half_max = 1 + (DTYPE_TMP)(MAX_VAL / 2); + bool overflow = false; + + while (bignum_cmp(denom, a) != LARGER) { // while (denom <= a) { + if (denom.array[BN_ARRAY_SIZE - 1] >= half_max) { + overflow = true; + break; + } + current = _lshift_one_bit(current); // current <<= 1; + denom = _lshift_one_bit(denom); // denom <<= 1; + } + if (!overflow) { + denom = _rshift_one_bit(denom); // denom >>= 1; + current = _rshift_one_bit(current); // current >>= 1; + } + c = bignum_init(); // int answer = 0; + + while (!bignum_is_zero(current)) { // while (current != 0) + if (bignum_cmp(tmp, denom) != SMALLER) { // if (dividend >= denom) + tmp = bignum_sub(tmp, denom); // dividend -= denom; + c = bignum_or(c, current); // answer |= current; + } + current = _rshift_one_bit(current); // current >>= 1; + denom = _rshift_one_bit(denom); // denom >>= 1; + } // return answer; + + return c; +} + + + +bn_t bignum_lshift(bn_t a, int nbits) +{ + //require(a, "a is null"); + //require(b, "b is null"); + require(nbits >= 0, "no negative shifts"); + + bn_t b; + + b = bignum_assign(a); + /* Handle shift in multiples of word-size */ + const int nbits_pr_word = (WORD_SIZE * 8); + int nwords = nbits / nbits_pr_word; + if (nwords != 0) { + b = _lshift_word(b, nwords); + nbits -= (nwords * nbits_pr_word); + } + + if (nbits != 0) { + int i; + for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) { + b.array[i] = (b.array[i] << nbits) | (b.array[i - 1] >> ((8 * WORD_SIZE) - nbits)); + } + b.array[i] <<= nbits; + } + + return b; +} + + +bn_t bignum_rshift(bn_t a, int nbits) +{ + //require(a, "a is null"); + //require(b, "b is null"); + require(nbits >= 0, "no negative shifts"); + + bn_t b; + + b = bignum_assign(a); + /* Handle shift in multiples of word-size */ + const int nbits_pr_word = (WORD_SIZE * 8); + int nwords = nbits / nbits_pr_word; + + if (nwords != 0) { + b = _rshift_word(b, nwords); + nbits -= (nwords * nbits_pr_word); + } + if (nbits != 0) { + int i; + for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) { + b.array[i] = (b.array[i] >> nbits) | (b.array[i + 1] << ((8 * WORD_SIZE) - nbits)); + } + b.array[i] >>= nbits; + } + + return b; +} + + + +bn_t bignum_a_rshift(bn_t a, int size, int nbits) +{ + //require(a, "a is null"); + //require(b, "b is null"); + require(nbits >= 0, "no negative shifts"); + require(size > 0, "no negative shifts"); + + bn_t b; + bn_t tmp, mask; + + b = bignum_rshift(a, nbits); + + /* get sign bit */ + tmp = bignum_rshift(a, size - 1); + tmp = bignum_mask(tmp, 1); + + if (!bignum_is_zero(tmp)) { + /* generate sign propag */ + tmp = bignum_from_int(1); + tmp = bignum_lshift(tmp, size); + tmp = bignum_dec(tmp); + + mask = bignum_from_int(1); + mask = bignum_lshift(mask, size - nbits); + mask = bignum_dec(mask); + + tmp = bignum_xor(tmp, mask); + b = bignum_or(b, tmp); + } + + return b; +} + +bn_t bignum_not(bn_t a) +{ + int i; + bn_t b; + + for (i = 0; i < BN_ARRAY_SIZE; ++i) { + b.array[i] = ~a.array[i]; + } + + return b; +} + + + +bn_t bignum_umod(bn_t a, bn_t b) +{ + /* + Take divmod and throw away div part + */ + //require(a, "a is null"); + //require(b, "b is null"); + //require(c, "c is null"); + + bn_t c, d; + bn_t tmp; + + /* c = (a / b) */ + c = bignum_udiv(a, b); + /* tmp = (c * b) */ + tmp = bignum_mul(c, b); + /* c = a - tmp */ + d = bignum_sub(a, tmp); + return d; +} + + +bn_t bignum_and(bn_t a, bn_t b) +{ + //require(a, "a is null"); + //require(b, "b is null"); + //require(c, "c is null"); + bn_t c; + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) { + c.array[i] = (a.array[i] & b.array[i]); + } + + return c; +} + + +bn_t bignum_or(bn_t a, bn_t b) +{ + //require(a, "a is null"); + //require(b, "b is null"); + //require(c, "c is null"); + bn_t c; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) { + c.array[i] = (a.array[i] | b.array[i]); + } + + return c; +} + + +bn_t bignum_xor(bn_t a, bn_t b) +{ + //require(a, "a is null"); + //require(b, "b is null"); + //require(c, "c is null"); + + bn_t c; + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) { + c.array[i] = (a.array[i] ^ b.array[i]); + } + return c; +} + + +int bignum_cmp(bn_t a, bn_t b) +{ + //require(a, "a is null"); + //require(b, "b is null"); + + int i = BN_ARRAY_SIZE; + do { + i -= 1; /* Decrement first, to start with last array element */ + if (a.array[i] > b.array[i]) { + return LARGER; + } + else if (a.array[i] < b.array[i]) { + return SMALLER; + } + } + while (i != 0); + + return EQUAL; +} + + +int bignum_is_zero(bn_t n) +{ + //require(n, "n is null"); + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) { + if (n.array[i]) { + return 0; + } + } + + return 1; +} + + + +bn_t bignum_assign(bn_t src) +{ + //require(dst, "dst is null"); + //require(src, "src is null"); + bn_t dst; + + int i; + for (i = 0; i < BN_ARRAY_SIZE; ++i) { + dst.array[i] = src.array[i]; + } + + return dst; +} + + +bn_t bignum_mask(bn_t src, int bits) +{ + bn_t dst; + bn_t mask; + + mask = bignum_from_int(1); + mask = bignum_lshift(mask, bits); + mask = bignum_dec(mask); + + dst = bignum_and(src, mask); + return dst; +} + +/* Private / Static functions. */ +static bn_t _rshift_word(bn_t a, int nwords) +{ + /* Naive method: */ + //require(a, "a is null"); + int i; + + require(nwords >= 0, "no negative shifts"); + + if (nwords >= BN_ARRAY_SIZE) { + for (i = 0; i < BN_ARRAY_SIZE; ++i) { + a.array[i] = 0; + } + return a; + } + + for (i = 0; i < BN_ARRAY_SIZE - nwords; ++i) { + a.array[i] = a.array[i + nwords]; + } + + for (; i < BN_ARRAY_SIZE; ++i) { + a.array[i] = 0; + } + + return a; +} + + +static bn_t _lshift_word(bn_t a, int nwords) +{ + //require(a, "a is null"); + require(nwords >= 0, "no negative shifts"); + + int i; + + if (nwords >= BN_ARRAY_SIZE) { + for (i = 0; i < BN_ARRAY_SIZE; ++i) { + a.array[i] = 0; + } + return a; + } + + /* Shift whole words */ + for (i = (BN_ARRAY_SIZE - 1); i >= nwords; --i) { + a.array[i] = a.array[i - nwords]; + } + /* Zero pad shifted words. */ + for (; i >= 0; --i) { + a.array[i] = 0; + } + + return a; +} + + +static bn_t _lshift_one_bit(bn_t a) +{ + //require(a, "a is null"); + + int i; + for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) { + a.array[i] = (a.array[i] << 1) | (a.array[i - 1] >> ((8 * WORD_SIZE) - 1)); + } + a.array[0] <<= 1; + + return a; +} + + +static bn_t _rshift_one_bit(bn_t a) +{ + //require(a, "a is null"); + + int i; + for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) { + a.array[i] = (a.array[i] >> 1) | (a.array[i + 1] << ((8 * WORD_SIZE) - 1)); + } + a.array[BN_ARRAY_SIZE - 1] >>= 1; + + return a; +} + + +bn_t bignum_rol(bn_t a, int size, int nbits) +{ + bn_t c; + + c = bignum_or( + bignum_lshift(a, nbits), + bignum_rshift(a, size - nbits) + ); + c = bignum_mask(c, size); + return c; +} + + +bn_t bignum_ror(bn_t a, int size, int nbits) +{ + bn_t c; + + c = bignum_or( + bignum_rshift(a, nbits), + bignum_lshift(a, size - nbits) + ); + c = bignum_mask(c, size); + return c; +} + + +int bignum_getbit(bn_t a, int pos) +{ + int d_pos, bit_pos; + + require(pos < BN_BIT_SIZE, "size must be below bignum max size"); + + d_pos = pos / (sizeof(DTYPE) * 8); + bit_pos = pos % (sizeof(DTYPE) * 8); + return !!(a.array[d_pos] & (1 << bit_pos)); + +} + + + +/* + * Count leading zeros - count the number of zero starting at the most + * significant bit + * + * Example: + * - cntleadzeros(size=32, src=2): 30 + * - cntleadzeros(size=32, src=0): 32 + */ +int bignum_cntleadzeros(bn_t n, int size) +{ + int i; + + require(size, "size must be greater than 0"); + require(size <= BN_BIT_SIZE, "size must be below bignum max size"); + + for (i = 0; i < size; i++) { + if (bignum_getbit(n, size - i - 1)) + break; + } + + return i; +} + + + +/* + * Count trailing zeros - count the number of zero starting at the least + * significant bit + * + * Example: + * - cnttrailzeros(size=32, src=2): 1 + * - cnttrailzeros(size=32, src=0): 32 + */ +int bignum_cnttrailzeros(bn_t n, int size) +{ + int i; + + require(size, "size must be greater than 0"); + require(size <= BN_BIT_SIZE, "size must be below bignum max size"); + + for (i = 0; i < size; i++) { + if (bignum_getbit(n, i)) + break; + } + + return i; +} + + + + +bn_t bignum_idiv(bn_t a, bn_t b, int size) +{ + require(size, "size must be greater than 0"); + require(size <= BN_BIT_SIZE, "size must be below bignum max size"); + + int a_sign, b_sign; + bn_t c; + + a_sign = bignum_getbit(a, size - 1); + b_sign = bignum_getbit(b, size - 1); + + if (a_sign) { + /* neg a */ + printf("a neg\n"); + a = bignum_sub(bignum_from_int(0), a); + a = bignum_mask(a, size - 1); + } + + if (b_sign) { + /* neg b */ + printf("b neg\n"); + b = bignum_sub(bignum_from_int(0), b); + b = bignum_mask(b, size - 1); + } + + c = bignum_udiv(a, b); + if (a_sign ^ b_sign) { + c = bignum_sub(bignum_from_int(0), c); + } + + c = bignum_mask(c, size); + return c; +} + + + +bn_t bignum_imod(bn_t a, bn_t b, int size) +{ + require(size, "size must be greater than 0"); + require(size <= BN_BIT_SIZE, "size must be below bignum max size"); + + bn_t c; + + c = bignum_idiv(a, b, size); + c = bignum_mul(c, b); + c = bignum_sub(a, c); + c = bignum_mask(c, size); + return c; +} diff --git a/miasm2/jitter/bn.h b/miasm2/jitter/bn.h new file mode 100644 index 00000000..6f726eb3 --- /dev/null +++ b/miasm2/jitter/bn.h @@ -0,0 +1,145 @@ +#ifndef __BIGNUM_H__ +#define __BIGNUM_H__ +/* + +Big number library - arithmetic on multiple-precision unsigned integers. + +This library is an implementation of arithmetic on arbitrarily large integers. + +The difference between this and other implementations, is that the data structure +has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), +and all memory is allocated statically: no dynamic allocation for better or worse. + +Primary goals are correctness, clarity of code and clean, portable implementation. +Secondary goal is a memory footprint small enough to make it suitable for use in +embedded applications. + + +The current state is correct functionality and adequate performance. +There may well be room for performance-optimizations and improvements. + +Source: https://github.com/kokke/tiny-bignum-c + +Code slightly modified to support ast generation calculus style from Expr. + +*/ + +#include <stdint.h> +#include <assert.h> + + +/* This macro defines the word size in bytes of the array that constitues the big-number data structure. */ +#ifndef WORD_SIZE + #define WORD_SIZE 4 +#endif + +#define BN_BYTE_SIZE 32 + +#define BN_BIT_SIZE ((BN_BYTE_SIZE) * 8) + +/* Size of big-numbers in bytes */ +//#define BN_ARRAY_SIZE (128 / WORD_SIZE) +#define BN_ARRAY_SIZE (BN_BYTE_SIZE / WORD_SIZE) + + +/* Here comes the compile-time specialization for how large the underlying array size should be. */ +/* The choices are 1, 2 and 4 bytes in size with uint32, uint64 for WORD_SIZE==4, as temporary. */ +#ifndef WORD_SIZE + #error Must define WORD_SIZE to be 1, 2, 4 +#elif (WORD_SIZE == 1) + /* Data type of array in structure */ + #define DTYPE uint8_t + /* bitmask for getting MSB */ + #define DTYPE_MSB ((DTYPE_TMP)(0x80)) + /* Data-type larger than DTYPE, for holding intermediate results of calculations */ + #define DTYPE_TMP uint32_t + /* sprintf format string */ + #define SPRINTF_FORMAT_STR "%.02x" + #define SSCANF_FORMAT_STR "%2hhx" + /* Max value of integer type */ + #define MAX_VAL ((DTYPE_TMP)0xFF) +#elif (WORD_SIZE == 2) + #define DTYPE uint16_t + #define DTYPE_TMP uint32_t + #define DTYPE_MSB ((DTYPE_TMP)(0x8000)) + #define SPRINTF_FORMAT_STR "%.04x" + #define SSCANF_FORMAT_STR "%4hx" + #define MAX_VAL ((DTYPE_TMP)0xFFFF) +#elif (WORD_SIZE == 4) + #define DTYPE uint32_t + #define DTYPE_TMP uint64_t + #define DTYPE_MSB ((DTYPE_TMP)(0x80000000)) + #define SPRINTF_FORMAT_STR "%.08x" + #define SSCANF_FORMAT_STR "%8x" + #define MAX_VAL ((DTYPE_TMP)0xFFFFFFFF) +#endif +#ifndef DTYPE + #error DTYPE must be defined to uint8_t, uint16_t uint32_t or whatever +#endif + + +/* Custom assert macro - easy to disable */ +#define require(p, msg) assert(p && #msg) + + +/* Data-holding structure: array of DTYPEs */ +typedef struct bn +{ + DTYPE array[BN_ARRAY_SIZE]; +} bn_t; + + + +/* Tokens returned by bignum_cmp() for value comparison */ +enum { SMALLER = -1, EQUAL = 0, LARGER = 1 }; + +/* Initialization functions: */ +bn_t bignum_init(void); +bn_t bignum_from_int(DTYPE_TMP i); +bn_t bignum_from_uint64(uint64_t i); +int bignum_to_int(bn_t n); +uint64_t bignum_to_uint64(bn_t n); +bn_t bignum_from_string(char* str, int nbytes); +void bignum_to_string(bn_t n, char* str, int maxsize); + + +/* Basic arithmetic operations: */ +bn_t bignum_add(bn_t a, bn_t b); /* c = a + b */ +bn_t bignum_sub(bn_t a, bn_t b); /* c = a - b */ +bn_t bignum_mul(bn_t a, bn_t b); /* c = a * b */ +bn_t bignum_udiv(bn_t a, bn_t b); /* c = a / b */ +bn_t bignum_umod(bn_t a, bn_t b); /* c = a % b */ +bn_t bignum_idiv(bn_t a, bn_t b, int size); +bn_t bignum_imod(bn_t a, bn_t b, int size); +//void bignum_udivmod(struct bn* a, struct bn* b, struct bn* c, struct bn* d); /* c = a/b, d = a%b */ + + + +/* Bitwise operations: */ +bn_t bignum_and(bn_t a, bn_t b); /* c = a & b */ +bn_t bignum_or(bn_t a, bn_t b); /* c = a | b */ +bn_t bignum_xor(bn_t a, bn_t b); /* c = a ^ b */ +bn_t bignum_lshift(bn_t a, int nbits); /* b = a << nbits */ +bn_t bignum_rshift(bn_t a, int nbits); /* b = a >> nbits */ +bn_t bignum_a_rshift(bn_t a, int size, int nbits); /* b = a a>> nbits */ +bn_t bignum_not(bn_t a); /* c = ~a */ + +/* Special operators and comparison */ +int bignum_cmp(bn_t a, bn_t b); /* Compare: returns LARGER, EQUAL or SMALLER */ +int bignum_is_zero(bn_t n); /* For comparison with zero */ +bn_t bignum_inc(bn_t n); /* Increment: add one to n */ +bn_t bignum_dec(bn_t n); /* Decrement: subtract one from n */ +//bn_t bignum_pow(bn_t a, bn_t b, bn_t c); /* Calculate a^b -- e.g. 2^10 => 1024 */ +//bn_t bignum_isqrt(bn_t a, bn_t b); /* Integer square root -- e.g. isqrt(5) => 2*/ +int bignum_cntleadzeros(bn_t n, int size); +int bignum_cnttrailzeros(bn_t n, int size); +bn_t bignum_assign(bn_t src); /* Copy src into dst -- dst := src */ +bn_t bignum_mask(bn_t src, int bits); /* c = src & ((1<<bits) -1) */ + +bn_t bignum_rol(bn_t a, int size, int nbits); +bn_t bignum_ror(bn_t a, int size, int nbits); +int bignum_getbit(bn_t a, int pos); + +#endif /* #ifndef __BIGNUM_H__ */ + + diff --git a/miasm2/jitter/codegen.py b/miasm2/jitter/codegen.py index a709d5ec..abba9843 100644 --- a/miasm2/jitter/codegen.py +++ b/miasm2/jitter/codegen.py @@ -6,13 +6,16 @@ from miasm2.expression.expression import Expr, ExprId, ExprLoc, ExprInt, \ ExprMem, ExprCond, LocKey from miasm2.ir.ir import IRBlock, AssignBlock -from miasm2.ir.translators.C import TranslatorC +from miasm2.ir.translators.C import TranslatorC, int_size_to_bn from miasm2.core.asmblock import AsmBlockBad TRANSLATOR_NO_SYMBOL = TranslatorC(loc_db=None) SIZE_TO_MASK = {size: TRANSLATOR_NO_SYMBOL.from_expr(ExprInt(0, size).mask) - for size in (1, 2, 3, 7, 8, 16, 32, 64, 128)} + for size in (1, 2, 3, 7, 8, 16, 32, 64)} + + + @@ -88,7 +91,7 @@ class CGen(object): CODE_INIT = r""" int DST_case; - unsigned long long DST_value; + uint64_t DST_value; vm_cpu_t* mycpu = (vm_cpu_t*)jitcpu->cpu; goto %s; @@ -232,7 +235,10 @@ class CGen(object): c_prefetch.append('%s = %s;' % (str_dst, str_src)) for var in prefetchers.itervalues(): - c_var.append("uint%d_t %s;" % (var.size, var)) + if var.size <= self.translator.NATIVE_INT_MAX_SIZE: + c_var.append("uint%d_t %s;" % (var.size, var)) + else: + c_var.append("bn_t %s; // %d" % (var, var.size)) for dst, src in sorted(assignblk.iteritems()): src = src.replace_expr(prefetchers) @@ -244,24 +250,50 @@ class CGen(object): # Dont mask float affectation c_main.append( '%s = (%s);' % (self.id_to_c(new_dst), self.id_to_c(src))) - else: + elif new_dst.size <= self.translator.NATIVE_INT_MAX_SIZE: c_main.append( '%s = (%s)&%s;' % (self.id_to_c(new_dst), self.id_to_c(src), SIZE_TO_MASK[src.size])) + else: + c_main.append( + '%s = bignum_mask(%s, %d);' % ( + self.id_to_c(new_dst), + self.id_to_c(src), + src.size + ) + ) elif isinstance(dst, ExprMem): ptr = dst.arg.replace_expr(prefetchers) - new_dst = ExprMem(ptr, dst.size) - str_dst = self.id_to_c(new_dst).replace('MEM_LOOKUP', 'MEM_WRITE') - c_mem.append('%s, %s);' % (str_dst[:-1], self.id_to_c(src))) + if ptr.size <= self.translator.NATIVE_INT_MAX_SIZE: + new_dst = ExprMem(ptr, dst.size) + str_dst = self.id_to_c(new_dst).replace('MEM_LOOKUP', 'MEM_WRITE') + c_mem.append('%s, %s);' % (str_dst[:-1], self.id_to_c(src))) + else: + ptr_str = self.id_to_c(ptr) + if ptr.size <= self.translator.NATIVE_INT_MAX_SIZE: + c_mem.append('%s, %s);' % (str_dst[:-1], self.id_to_c(src))) + else: + if src.size <= self.translator.NATIVE_INT_MAX_SIZE: + c_mem.append('MEM_WRITE_BN_INT(jitcpu, %d, %s, %s);' % ( + src.size, ptr_str, self.id_to_c(src)) + ) + else: + c_mem.append('MEM_WRITE_BN_BN(jitcpu, %d, %s, %s);' % ( + src.size, ptr_str, self.id_to_c(src)) + ) else: raise ValueError("Unknown dst") for dst, new_dst in dst_var.iteritems(): if dst == self.ir_arch.IRDst: continue + c_updt.append('%s = %s;' % (self.id_to_c(dst), self.id_to_c(new_dst))) - c_var.append("uint%d_t %s;" % (new_dst.size, new_dst)) + if dst.size <= self.translator.NATIVE_INT_MAX_SIZE: + c_var.append("uint%d_t %s;" % (new_dst.size, new_dst)) + else: + c_var.append("bn_t %s; // %d" % (new_dst, new_dst.size)) return c_prefetch, c_var, c_main, c_mem, c_updt @@ -284,24 +316,39 @@ class CGen(object): """ if isinstance(expr, ExprCond): - cond = self.id_to_c(expr.cond) src1, src1b = self.traverse_expr_dst(expr.src1, dst2index) src2, src2b = self.traverse_expr_dst(expr.src2, dst2index) + cond = self.id_to_c(expr.cond) + if not expr.cond.size <= self.translator.NATIVE_INT_MAX_SIZE: + cond = "(!bignum_is_zero(%s))" % cond + return ("((%s)?(%s):(%s))" % (cond, src1, src2), "((%s)?(%s):(%s))" % (cond, src1b, src2b)) if isinstance(expr, ExprInt): offset = int(expr) loc_key = self.ir_arch.loc_db.get_or_create_offset_location(offset) self.add_label_index(dst2index, loc_key) - return ("%s" % dst2index[loc_key], hex(offset)) + + value, int_size = int_size_to_bn(offset, 64) + out = hex(offset) + + return ("%s" % dst2index[loc_key], out) if expr.is_loc(): loc_key = expr.loc_key offset = self.ir_arch.loc_db.get_location_offset(expr.loc_key) if offset is not None: self.add_label_index(dst2index, loc_key) - return ("%s" % dst2index[loc_key], hex(offset)) + + value, int_size = int_size_to_bn(offset, 64) + out = hex(offset) + + return ("%s" % dst2index[loc_key], out) self.add_label_index(dst2index, loc_key) - return ("%s" % dst2index[loc_key], "0") + + value, int_size = int_size_to_bn(0, 64) + out = hex(0) + + return ("%s" % dst2index[loc_key], out) dst2index[expr] = -1 return ("-1", self.id_to_c(expr)) @@ -311,7 +358,7 @@ class CGen(object): dst2index = {} (ret, retb) = self.traverse_expr_dst(dst, dst2index) ret = "DST_case = %s;" % ret - retb = "DST_value = %s;" % retb + retb = 'DST_value = %s;' % retb return ['// %s' % dst2index, '%s' % ret, '%s' % retb], dst2index diff --git a/miasm2/jitter/jitcore_cc_base.py b/miasm2/jitter/jitcore_cc_base.py index bbf10a53..81a5d009 100644 --- a/miasm2/jitter/jitcore_cc_base.py +++ b/miasm2/jitter/jitcore_cc_base.py @@ -16,6 +16,7 @@ def gen_core(arch, attrib): txt += '#include "%s/op_semantics.h"\n' % lib_dir txt += '#include "%s/vm_mngr.h"\n' % lib_dir txt += '#include "%s/vm_mngr_py.h"\n' % lib_dir + txt += '#include "%s/bn.h"\n' % lib_dir txt += '#include "%s/JitCore.h"\n' % lib_dir txt += '#include "%s/arch/JitCore_%s.h"\n' % (lib_dir, arch.name) diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py index c4e6709d..7c95688d 100644 --- a/miasm2/jitter/llvmconvert.py +++ b/miasm2/jitter/llvmconvert.py @@ -215,7 +215,7 @@ class LLVMContext_JIT(LLVMContext): fc = {} p8 = llvm_ir.PointerType(LLVMType.IntType(8)) - for i in [8, 16, 32, 64, 128]: + for i in [8, 16, 32, 64]: fc["MEM_LOOKUP_%02d" % i] = {"ret": LLVMType.IntType(i), "args": [p8, LLVMType.IntType(64)]} @@ -224,6 +224,22 @@ class LLVMContext_JIT(LLVMContext): "args": [p8, LLVMType.IntType(64), LLVMType.IntType(i)]} + + fc["MEM_LOOKUP_INT_BN_TO_PTR"] = {"ret": llvm_ir.VoidType(), + "args": [ + p8, + LLVMType.IntType(32), + LLVMType.IntType(64), + p8 + ]} + fc["MEM_WRITE_INT_BN_FROM_PTR"] = {"ret": llvm_ir.VoidType(), + "args": [ + p8, + LLVMType.IntType(32), + LLVMType.IntType(64), + p8, + ]} + fc["reset_memory_access"] = {"ret": llvm_ir.VoidType(), "args": [p8, ]} @@ -307,25 +323,86 @@ class LLVMContext_JIT(LLVMContext): def memory_lookup(self, func, addr, size): """Perform a memory lookup at @addr of size @size (in bit)""" builder = func.builder - fc_name = "MEM_LOOKUP_%02d" % size - fc_ptr = self.mod.get_global(fc_name) - addr_casted = builder.zext(addr, - LLVMType.IntType(64)) + if size <= 64: + fc_name = "MEM_LOOKUP_%02d" % size + fc_ptr = self.mod.get_global(fc_name) + addr_casted = builder.zext(addr, LLVMType.IntType(64)) + ret = builder.call( + fc_ptr, [func.local_vars["jitcpu"],addr_casted] + ) + else: + # Miasm uses a memory lookup function which returns a bn_t for its + # result. We cannot simply translate this into IntType. The trick + # here is to use the function MEM_LOOKUP_INT_BN_TO_PTR which has a + # different interface: the resulting bn_t is passed through a char* + # argument. + # + # WARNING: Here, we use the fact that the serialisation of LLVM + # IntType is the *same* as the bn_t structure. + + fc_name = "MEM_LOOKUP_INT_BN_TO_PTR" + fc_ptr = self.mod.get_global(fc_name) + addr_casted = builder.zext(addr, LLVMType.IntType(64)) + size_cst = llvm_ir.Constant(LLVMType.IntType(32), size) + + value_ptr = builder.alloca(llvm_ir.IntType(size)) + value_ptr_u8 = builder.bitcast( + value_ptr, + LLVMType.IntType(8).as_pointer() + ) + + + builder.call( + fc_ptr, + [ + func.local_vars["jitcpu"], + size_cst, + addr_casted, + value_ptr_u8 + ] + ) + ret = builder.load(value_ptr) - ret = builder.call(fc_ptr, [func.local_vars["jitcpu"], - addr_casted]) return ret def memory_write(self, func, addr, size, value): """Perform a memory write at @addr of size @size (in bit) with LLVM IR @value""" # Function call builder = func.builder - fc_name = "MEM_WRITE_%02d" % size - fc_ptr = self.mod.get_global(fc_name) - dst_casted = builder.zext(addr, LLVMType.IntType(64)) - builder.call(fc_ptr, [func.local_vars["jitcpu"], - dst_casted, - value]) + if size <= 64: + fc_name = "MEM_WRITE_%02d" % size + fc_ptr = self.mod.get_global(fc_name) + dst_casted = builder.zext(addr, LLVMType.IntType(64)) + builder.call( + fc_ptr, + [ + func.local_vars["jitcpu"], + dst_casted, + value + ] + ) + else: + # The same trick as described in MEM_LOOKUP_INT_BN_TO_PTR is used + # here. + + fc_name = "MEM_WRITE_INT_BN_FROM_PTR" + fc_ptr = self.mod.get_global(fc_name) + addr_casted = builder.zext(addr, LLVMType.IntType(64)) + size_cst = llvm_ir.Constant(LLVMType.IntType(32), size) + + ret = builder.alloca(value.type) + builder.store(value, ret) + value_ptr = builder.bitcast(ret, llvm_ir.IntType(8).as_pointer()) + + ret = builder.call( + fc_ptr, + [ + func.local_vars["jitcpu"], + size_cst, + addr_casted, + value_ptr, + ] + ) @staticmethod diff --git a/miasm2/jitter/op_semantics.c b/miasm2/jitter/op_semantics.c index 0bc3fcc5..061e7736 100644 --- a/miasm2/jitter/op_semantics.c +++ b/miasm2/jitter/op_semantics.c @@ -776,22 +776,22 @@ uint64_t fpround_towardszero_fp64(uint64_t a) } +UDIV(8) UDIV(16) UDIV(32) UDIV(64) -UDIV(128) +UMOD(8) UMOD(16) UMOD(32) UMOD(64) -UMOD(128) +IDIV(8) IDIV(16) IDIV(32) IDIV(64) -IDIV(128) +IMOD(8) IMOD(16) IMOD(32) IMOD(64) -IMOD(128) diff --git a/miasm2/jitter/op_semantics.h b/miasm2/jitter/op_semantics.h index f8042895..9ff2881e 100644 --- a/miasm2/jitter/op_semantics.h +++ b/miasm2/jitter/op_semantics.h @@ -1,9 +1,6 @@ #ifndef OP_SEMANTICS_H #define OP_SEMANTICS_H -#define uint128_t __uint128_t -#define int128_t __int128_t - #define CC_P 1 extern const uint8_t parity_table[256]; #define parity(a) parity_table[(a) & 0xFF] @@ -95,6 +92,11 @@ uint16_t umod16(uint16_t a, uint16_t b); int16_t idiv16(int16_t a, int16_t b); int16_t imod16(int16_t a, int16_t b); +uint8_t udiv8(uint8_t a, uint8_t b); +uint8_t umod8(uint8_t a, uint8_t b); +int8_t idiv8(int8_t a, int8_t b); +int8_t imod8(int8_t a, int8_t b); + unsigned int x86_cpuid(unsigned int a, unsigned int reg_num); uint32_t fpu_fadd32(uint32_t a, uint32_t b); diff --git a/miasm2/jitter/vm_mngr.c b/miasm2/jitter/vm_mngr.c index dd0f6cf2..9b7a4c98 100644 --- a/miasm2/jitter/vm_mngr.c +++ b/miasm2/jitter/vm_mngr.c @@ -101,14 +101,6 @@ uint64_t set_endian64(vm_mngr_t* vm_mngr, uint64_t val) return Endian64_Swap(val); } -uint128_t set_endian128(vm_mngr_t* vm_mngr, uint128_t val) -{ - if (vm_mngr->sex == __BYTE_ORDER) - return val; - else - return Endian128_Swap(val); -} - void print_val(uint64_t base, uint64_t addr) { uint64_t *ptr = (uint64_t *) (intptr_t) addr; @@ -163,14 +155,11 @@ struct memory_page_node * get_memory_page_from_address(vm_mngr_t* vm_mngr, uint6 return NULL; } - - - -static uint128_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t ad) +static uint64_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t ad) { struct memory_page_node * mpn; unsigned char * addr; - uint128_t ret = 0; + uint64_t ret = 0; struct memory_breakpoint_info * b; @@ -213,11 +202,8 @@ static uint128_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint ret = *((uint64_t*)addr)&0xFFFFFFFFFFFFFFFFULL; ret = set_endian64(vm_mngr, ret); break; - case 128: - ret = *((uint128_t*)addr)&MASK_128; - ret = set_endian128(vm_mngr, ret); - break; default: + fprintf(stderr, "Bad memory access size %d\n", my_size); exit(EXIT_FAILURE); break; } @@ -249,10 +235,8 @@ static uint128_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint case 64: ret = set_endian64(vm_mngr, ret); break; - case 128: - ret = set_endian128(vm_mngr, ret); - break; default: + fprintf(stderr, "Bad memory access size %d\n", my_size); exit(EXIT_FAILURE); break; } @@ -261,7 +245,7 @@ static uint128_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint } static void memory_page_write(vm_mngr_t* vm_mngr, unsigned int my_size, - uint64_t ad, uint128_t src) + uint64_t ad, uint64_t src) { struct memory_page_node * mpn; unsigned char * addr; @@ -305,11 +289,8 @@ static void memory_page_write(vm_mngr_t* vm_mngr, unsigned int my_size, src = set_endian64(vm_mngr, src); *((uint64_t*)addr) = src&0xFFFFFFFFFFFFFFFFULL; break; - case 128: - src = set_endian128(vm_mngr, src); - *((uint128_t*)addr) = src&MASK_128; - break; default: + fprintf(stderr, "Bad memory access size %d\n", my_size); exit(EXIT_FAILURE); break; } @@ -330,10 +311,8 @@ static void memory_page_write(vm_mngr_t* vm_mngr, unsigned int my_size, case 64: src = set_endian64(vm_mngr, src); break; - case 128: - src = set_endian128(vm_mngr, src); - break; default: + fprintf(stderr, "Bad memory access size %d\n", my_size); exit(EXIT_FAILURE); break; } @@ -501,12 +480,6 @@ void vm_MEM_WRITE_64(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t src) memory_page_write(vm_mngr, 64, addr, src); } -void vm_MEM_WRITE_128(vm_mngr_t* vm_mngr, uint64_t addr, uint128_t src) -{ - add_mem_write(vm_mngr, addr, 16); - memory_page_write(vm_mngr, 128, addr, src); -} - unsigned char vm_MEM_LOOKUP_08(vm_mngr_t* vm_mngr, uint64_t addr) { unsigned char ret; @@ -535,13 +508,6 @@ uint64_t vm_MEM_LOOKUP_64(vm_mngr_t* vm_mngr, uint64_t addr) ret = memory_page_read(vm_mngr, 64, addr); return ret; } -uint128_t vm_MEM_LOOKUP_128(vm_mngr_t* vm_mngr, uint128_t addr) -{ - uint128_t ret; - add_mem_read(vm_mngr, addr, 16); - ret = memory_page_read(vm_mngr, 128, addr); - return ret; -} int vm_read_mem(vm_mngr_t* vm_mngr, uint64_t addr, char** buffer_ptr, uint64_t size) diff --git a/miasm2/jitter/vm_mngr.h b/miasm2/jitter/vm_mngr.h index a50b52d0..d65a45e8 100644 --- a/miasm2/jitter/vm_mngr.h +++ b/miasm2/jitter/vm_mngr.h @@ -26,7 +26,6 @@ #define __LITTLE_ENDIAN _LITTLE_ENDIAN #endif -#define uint128_t __uint128_t #define Endian16_Swap(value) \ ((((uint16_t)((value) & 0x00FF)) << 8) | \ @@ -48,25 +47,6 @@ ((((uint64_t)value)>>40) & 0x000000000000FF00ULL) | \ ((((uint64_t)value)>>56) & 0x00000000000000FFULL)) -#define Endian128_Swap(value) \ - (((((uint128_t)value)>>120) & 0xFF) | \ - ((((uint128_t)value)>>112) & 0xFF) << 8 | \ - ((((uint128_t)value)>>104) & 0xFF) << 16 | \ - ((((uint128_t)value)>>96) & 0xFF) << 24 | \ - ((((uint128_t)value)>>88) & 0xFF) << 32 | \ - ((((uint128_t)value)>>80) & 0xFF) << 40 | \ - ((((uint128_t)value)>>72) & 0xFF) << 48 | \ - ((((uint128_t)value)>>64) & 0xFF) << 56 | \ - ((((uint128_t)value)>>56) & 0xFF) << 64 | \ - ((((uint128_t)value)>>48) & 0xFF) << 72 | \ - ((((uint128_t)value)>>40) & 0xFF) << 80 | \ - ((((uint128_t)value)>>32) & 0xFF) << 88 | \ - ((((uint128_t)value)>>24) & 0xFF) << 96 | \ - ((((uint128_t)value)>>16) & 0xFF) << 104 | \ - ((((uint128_t)value)>>8) & 0xFF) << 112 | \ - ((((uint128_t)value)) & 0xFF) << 120) - -#define MASK_128 ((uint128_t) 0xFFFFFFFFFFFFFFFFULL | (uint128_t) 0xFFFFFFFFFFFFFFFFULL << 64) LIST_HEAD(code_bloc_list_head, code_bloc_node); LIST_HEAD(memory_breakpoint_info_head, memory_breakpoint_info); @@ -193,13 +173,11 @@ void vm_MEM_WRITE_08(vm_mngr_t* vm_mngr, uint64_t addr, unsigned char src); void vm_MEM_WRITE_16(vm_mngr_t* vm_mngr, uint64_t addr, unsigned short src); void vm_MEM_WRITE_32(vm_mngr_t* vm_mngr, uint64_t addr, unsigned int src); void vm_MEM_WRITE_64(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t src); -void vm_MEM_WRITE_128(vm_mngr_t* vm_mngr, uint64_t addr, uint128_t src); unsigned char vm_MEM_LOOKUP_08(vm_mngr_t* vm_mngr, uint64_t addr); unsigned short vm_MEM_LOOKUP_16(vm_mngr_t* vm_mngr, uint64_t addr); unsigned int vm_MEM_LOOKUP_32(vm_mngr_t* vm_mngr, uint64_t addr); uint64_t vm_MEM_LOOKUP_64(vm_mngr_t* vm_mngr, uint64_t addr); -uint128_t vm_MEM_LOOKUP_128(vm_mngr_t* vm_mngr, uint128_t addr); void MEM_WRITE_08_PASSTHROUGH(uint64_t addr, unsigned char src); void MEM_WRITE_16_PASSTHROUGH(uint64_t addr, unsigned short src); diff --git a/setup.py b/setup.py index 1985a52e..209219b2 100755 --- a/setup.py +++ b/setup.py @@ -29,47 +29,62 @@ def buil_all(): ext_modules_all = [ Extension("miasm2.jitter.VmMngr", ["miasm2/jitter/vm_mngr.c", - "miasm2/jitter/vm_mngr_py.c"]), + "miasm2/jitter/vm_mngr_py.c", + "miasm2/jitter/bn.c", + ]), Extension("miasm2.jitter.arch.JitCore_x86", ["miasm2/jitter/JitCore.c", "miasm2/jitter/vm_mngr.c", "miasm2/jitter/op_semantics.c", + "miasm2/jitter/bn.c", "miasm2/jitter/arch/JitCore_x86.c"]), Extension("miasm2.jitter.arch.JitCore_arm", ["miasm2/jitter/JitCore.c", "miasm2/jitter/vm_mngr.c", "miasm2/jitter/op_semantics.c", + "miasm2/jitter/bn.c", "miasm2/jitter/arch/JitCore_arm.c"]), Extension("miasm2.jitter.arch.JitCore_aarch64", ["miasm2/jitter/JitCore.c", "miasm2/jitter/vm_mngr.c", "miasm2/jitter/op_semantics.c", + "miasm2/jitter/bn.c", "miasm2/jitter/arch/JitCore_aarch64.c"]), Extension("miasm2.jitter.arch.JitCore_msp430", ["miasm2/jitter/JitCore.c", "miasm2/jitter/vm_mngr.c", "miasm2/jitter/op_semantics.c", + "miasm2/jitter/bn.c", "miasm2/jitter/arch/JitCore_msp430.c"]), Extension("miasm2.jitter.arch.JitCore_mep", ["miasm2/jitter/JitCore.c", "miasm2/jitter/vm_mngr.c", + "miasm2/jitter/bn.c", "miasm2/jitter/arch/JitCore_mep.c"]), Extension("miasm2.jitter.arch.JitCore_mips32", ["miasm2/jitter/JitCore.c", "miasm2/jitter/vm_mngr.c", "miasm2/jitter/op_semantics.c", + "miasm2/jitter/bn.c", "miasm2/jitter/arch/JitCore_mips32.c"]), Extension("miasm2.jitter.arch.JitCore_ppc32", ["miasm2/jitter/JitCore.c", "miasm2/jitter/vm_mngr.c", "miasm2/jitter/op_semantics.c", + "miasm2/jitter/bn.c", "miasm2/jitter/arch/JitCore_ppc32.c"], depends=["miasm2/jitter/arch/JitCore_ppc32.h", - "miasm2/jitter/arch/JitCore_ppc32_regs.h"]), + "miasm2/jitter/arch/JitCore_ppc32_regs.h", + "miasm2/jitter/bn.h", + ]), Extension("miasm2.jitter.Jitllvm", - ["miasm2/jitter/Jitllvm.c"]), + ["miasm2/jitter/Jitllvm.c", + "miasm2/jitter/bn.c", + ]), Extension("miasm2.jitter.Jitgcc", - ["miasm2/jitter/Jitgcc.c"]), + ["miasm2/jitter/Jitgcc.c", + "miasm2/jitter/bn.c", + ]), ] print 'building' |