diff options
| -rw-r--r-- | miasm2/arch/aarch64/jit.py | 3 | ||||
| -rw-r--r-- | miasm2/arch/aarch64/sem.py | 3 | ||||
| -rw-r--r-- | miasm2/arch/arm/jit.py | 2 | ||||
| -rw-r--r-- | miasm2/arch/mips32/jit.py | 7 | ||||
| -rw-r--r-- | miasm2/arch/mips32/regs.py | 2 | ||||
| -rw-r--r-- | miasm2/arch/msp430/jit.py | 3 | ||||
| -rw-r--r-- | miasm2/arch/msp430/regs.py | 1 | ||||
| -rw-r--r-- | miasm2/arch/x86/jit.py | 3 | ||||
| -rw-r--r-- | miasm2/arch/x86/sem.py | 3 | ||||
| -rw-r--r-- | miasm2/ir/ir2C.py | 432 | ||||
| -rw-r--r-- | miasm2/jitter/JitCore.h | 2 | ||||
| -rw-r--r-- | miasm2/jitter/codegen.py | 567 | ||||
| -rw-r--r-- | miasm2/jitter/csts.py | 3 | ||||
| -rw-r--r-- | miasm2/jitter/jitcore.py | 9 | ||||
| -rw-r--r-- | miasm2/jitter/jitcore_gcc.py | 19 | ||||
| -rw-r--r-- | miasm2/jitter/jitcore_tcc.py | 19 | ||||
| -rw-r--r-- | miasm2/jitter/jitload.py | 8 | ||||
| -rw-r--r-- | test/test_all.py | 3 |
18 files changed, 615 insertions, 474 deletions
diff --git a/miasm2/arch/aarch64/jit.py b/miasm2/arch/aarch64/jit.py index 44b0609f..ca8d7b39 100644 --- a/miasm2/arch/aarch64/jit.py +++ b/miasm2/arch/aarch64/jit.py @@ -11,7 +11,6 @@ hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s")) log.addHandler(hnd) log.setLevel(logging.CRITICAL) - class jitter_aarch64l(jitter): max_reg_arg = 8 @@ -19,7 +18,6 @@ class jitter_aarch64l(jitter): sp = asmbloc.asm_symbol_pool() jitter.__init__(self, ir_aarch64l(sp), *args, **kwargs) self.vm.set_little_endian() - self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC def push_uint64_t(self, v): self.cpu.SP -= 8 @@ -70,4 +68,3 @@ class jitter_aarch64b(jitter_aarch64l): sp = asmbloc.asm_symbol_pool() jitter.__init__(self, ir_aarch64b(sp), *args, **kwargs) self.vm.set_big_endian() - self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC diff --git a/miasm2/arch/aarch64/sem.py b/miasm2/arch/aarch64/sem.py index b198bc43..02a93dd2 100644 --- a/miasm2/arch/aarch64/sem.py +++ b/miasm2/arch/aarch64/sem.py @@ -793,7 +793,8 @@ class ir_aarch64l(ir): dst = self.expr_fix_regs_for_mode(dst) src = self.expr_fix_regs_for_mode(src) assignblk[dst] = src - irbloc.dst = self.expr_fix_regs_for_mode(irbloc.dst) + if irbloc.dst is not None: + irbloc.dst = self.expr_fix_regs_for_mode(irbloc.dst) def mod_pc(self, instr, instr_ir, extra_ir): "Replace PC by the instruction's offset" diff --git a/miasm2/arch/arm/jit.py b/miasm2/arch/arm/jit.py index a9b93f6b..70d16176 100644 --- a/miasm2/arch/arm/jit.py +++ b/miasm2/arch/arm/jit.py @@ -17,7 +17,6 @@ class jitter_arml(jitter): sp = asmbloc.asm_symbol_pool() jitter.__init__(self, ir_arml(sp), *args, **kwargs) self.vm.set_little_endian() - self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC def push_uint32_t(self, v): self.cpu.SP -= 4 @@ -67,4 +66,3 @@ class jitter_armb(jitter_arml): sp = asmbloc.asm_symbol_pool() jitter.__init__(self, ir_armb(sp), *args, **kwargs) self.vm.set_big_endian() - self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC diff --git a/miasm2/arch/mips32/jit.py b/miasm2/arch/mips32/jit.py index 93223896..aca85de5 100644 --- a/miasm2/arch/mips32/jit.py +++ b/miasm2/arch/mips32/jit.py @@ -1,9 +1,10 @@ +import logging + from miasm2.jitter.jitload import jitter from miasm2.core import asmbloc from miasm2.core.utils import * from miasm2.arch.mips32.sem import ir_mips32l, ir_mips32b - -import logging +from miasm2.jitter.codegen import CGen log = logging.getLogger('jit_mips32') hnd = logging.StreamHandler() @@ -17,7 +18,6 @@ class jitter_mips32l(jitter): sp = asmbloc.asm_symbol_pool() jitter.__init__(self, ir_mips32l(sp), *args, **kwargs) self.vm.set_little_endian() - self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC def push_uint32_t(self, v): self.cpu.SP -= 4 @@ -42,4 +42,3 @@ class jitter_mips32b(jitter_mips32l): sp = asmbloc.asm_symbol_pool() jitter.__init__(self, ir_mips32b(sp), *args, **kwargs) self.vm.set_big_endian() - self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC diff --git a/miasm2/arch/mips32/regs.py b/miasm2/arch/mips32/regs.py index 6ddcf25b..b64b40d5 100644 --- a/miasm2/arch/mips32/regs.py +++ b/miasm2/arch/mips32/regs.py @@ -11,6 +11,8 @@ gen_reg('PC_FETCH', globals()) gen_reg('R_LO', globals()) gen_reg('R_HI', globals()) +exception_flags = ExprId('exception_flags', 32) + PC_init = ExprId("PC_init") PC_FETCH_init = ExprId("PC_FETCH_init") diff --git a/miasm2/arch/msp430/jit.py b/miasm2/arch/msp430/jit.py index 5a4ff58b..95d34f96 100644 --- a/miasm2/arch/msp430/jit.py +++ b/miasm2/arch/msp430/jit.py @@ -1,6 +1,7 @@ from miasm2.jitter.jitload import jitter from miasm2.core import asmbloc from miasm2.core.utils import * +from miasm2.arch.msp430.sem import ir_msp430 import logging @@ -13,11 +14,9 @@ log.setLevel(logging.CRITICAL) class jitter_msp430(jitter): def __init__(self, *args, **kwargs): - from miasm2.arch.msp430.sem import ir_msp430 sp = asmbloc.asm_symbol_pool() jitter.__init__(self, ir_msp430(sp), *args, **kwargs) self.vm.set_little_endian() - self.ir_arch.jit_pc = self.ir_arch.arch.regs.PC def push_uint16_t(self, v): regs = self.cpu.get_gpreg() diff --git a/miasm2/arch/msp430/regs.py b/miasm2/arch/msp430/regs.py index 60638f26..1e35029f 100644 --- a/miasm2/arch/msp430/regs.py +++ b/miasm2/arch/msp430/regs.py @@ -7,6 +7,7 @@ from miasm2.core.cpu import reg_info regs16_str = ["PC", "SP", "SR"] + ["R%d" % i for i in xrange(3, 16)] regs16_expr = [ExprId(x, 16) for x in regs16_str] +exception_flags = ExprId('exception_flags', 32) gpregs = reg_info(regs16_str, regs16_expr) diff --git a/miasm2/arch/x86/jit.py b/miasm2/arch/x86/jit.py index c4f6f128..771b651a 100644 --- a/miasm2/arch/x86/jit.py +++ b/miasm2/arch/x86/jit.py @@ -17,7 +17,6 @@ class jitter_x86_16(jitter): sp = asmbloc.asm_symbol_pool() jitter.__init__(self, ir_x86_16(sp), *args, **kwargs) self.vm.set_little_endian() - self.ir_arch.jit_pc = self.ir_arch.arch.regs.RIP self.ir_arch.do_stk_segm = False self.orig_irbloc_fix_regs_for_mode = self.ir_arch.irbloc_fix_regs_for_mode self.ir_arch.irbloc_fix_regs_for_mode = self.ir_archbloc_fix_regs_for_mode @@ -49,7 +48,6 @@ class jitter_x86_32(jitter): sp = asmbloc.asm_symbol_pool() jitter.__init__(self, ir_x86_32(sp), *args, **kwargs) self.vm.set_little_endian() - self.ir_arch.jit_pc = self.ir_arch.arch.regs.RIP self.ir_arch.do_stk_segm = False self.orig_irbloc_fix_regs_for_mode = self.ir_arch.irbloc_fix_regs_for_mode @@ -109,7 +107,6 @@ class jitter_x86_64(jitter): sp = asmbloc.asm_symbol_pool() jitter.__init__(self, ir_x86_64(sp), *args, **kwargs) self.vm.set_little_endian() - self.ir_arch.jit_pc = self.ir_arch.arch.regs.RIP self.ir_arch.do_stk_segm = False self.orig_irbloc_fix_regs_for_mode = self.ir_arch.irbloc_fix_regs_for_mode diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py index 11da1e8b..cdc98fba 100644 --- a/miasm2/arch/x86/sem.py +++ b/miasm2/arch/x86/sem.py @@ -4571,7 +4571,8 @@ class ir_x86_16(ir): dst = self.expr_fix_regs_for_mode(dst, mode) src = self.expr_fix_regs_for_mode(src, mode) assignblk[dst] = src - irbloc.dst = self.expr_fix_regs_for_mode(irbloc.dst, mode) + if irbloc.dst is not None: + irbloc.dst = self.expr_fix_regs_for_mode(irbloc.dst, mode) class ir_x86_32(ir_x86_16): diff --git a/miasm2/ir/ir2C.py b/miasm2/ir/ir2C.py deleted file mode 100644 index ebc61e27..00000000 --- a/miasm2/ir/ir2C.py +++ /dev/null @@ -1,432 +0,0 @@ -import miasm2.expression.expression as m2_expr -from miasm2.expression.simplifications import expr_simp -from miasm2.core import asmbloc -from miasm2.ir.translators import Translator -import logging - - -log_to_c_h = logging.getLogger("ir_helper") -console_handler = logging.StreamHandler() -console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s")) -log_to_c_h.addHandler(console_handler) -log_to_c_h.setLevel(logging.WARN) - -# Miasm to C translator -translator = Translator.to_language("C") - -prefetch_id = [] -prefetch_id_size = {} -for size in [8, 16, 32, 64]: - prefetch_id_size[size] = [] - for i in xrange(20): - name = 'pfmem%.2d_%d' % (size, i) - c = m2_expr.ExprId(name, size) - globals()[name] = c - prefetch_id.append(c) - prefetch_id_size[size].append(c) - -def init_arch_C(arch): - arch.id2Cid = {} - for x in arch.regs.all_regs_ids + prefetch_id: - arch.id2Cid[x] = m2_expr.ExprId('mycpu->' + str(x), x.size) - - arch.id2newCid = {} - - for x in arch.regs.all_regs_ids + prefetch_id: - arch.id2newCid[x] = m2_expr.ExprId('mycpu->%s_new' % x, x.size) - - -def patch_c_id(arch, e): - return e.replace_expr(arch.id2Cid) - - -def patch_c_new_id(arch, e): - return e.replace_expr(arch.id2newCid) - - -mask_int = 0xffffffffffffffff - - -pre_instr_test_exception = r""" -// pre instruction test exception -if (VM_exception_flag) { - %s; - return JIT_RET_EXCEPTION; -} -""" - - -code_exception_fetch_mem_at_instr = r""" -// except fetch mem at instr -if (VM_exception_flag & EXCEPT_DO_NOT_UPDATE_PC) { - %s; - return JIT_RET_EXCEPTION; -} -""" -code_exception_fetch_mem_post_instr = r""" -// except fetch mem post instr -if (VM_exception_flag) { - %s; - return JIT_RET_EXCEPTION; -} -""" - - -code_exception_fetch_mem_at_instr_noautomod = r""" -// except fetch mem at instr noauto -if ((VM_exception_flag & ~EXCEPT_CODE_AUTOMOD) & EXCEPT_DO_NOT_UPDATE_PC) { - %s; - return JIT_RET_EXCEPTION; -} -""" -code_exception_fetch_mem_post_instr_noautomod = r""" -// except post instr noauto -if (VM_exception_flag & ~EXCEPT_CODE_AUTOMOD) { - %s; - return JIT_RET_EXCEPTION; -} -""" - - -code_exception_at_instr = r""" -// except at instr -if (CPU_exception_flag && CPU_exception_flag > EXCEPT_NUM_UPDT_EIP) { - %s; - return JIT_RET_EXCEPTION; -} -""" - -code_exception_post_instr = r""" -// except post instr -if (CPU_exception_flag) { - if (CPU_exception_flag > EXCEPT_NUM_UPDT_EIP) { - %s; - } - else { - %s; - } - return JIT_RET_EXCEPTION; -} -""" - - -code_exception_at_instr_noautomod = r""" -if ((CPU_exception_flag & ~EXCEPT_CODE_AUTOMOD) && (CPU_exception_flag > EXCEPT_NUM_UPDT_EIP)) { - %s; - return JIT_RET_EXCEPTION; -} -""" - -code_exception_post_instr_noautomod = r""" -if (CPU_exception_flag & ~EXCEPT_CODE_AUTOMOD) { - if (CPU_exception_flag > EXCEPT_NUM_UPDT_EIP) { - %s; - } - else { - %s; - } - return JIT_RET_EXCEPTION; -} -""" - -goto_local_code = r""" -if (BlockDst->is_local) { - goto *local_labels[BlockDst->address]; -} -else { - return JIT_RET_NO_EXCEPTION; -} -""" - -my_size_mask = {1: 1, 2: 3, 3: 7, 7: 0x7f, - 8: 0xFF, - 16: 0xFFFF, - 32: 0xFFFFFFFF, - 64: 0xFFFFFFFFFFFFFFFFL} - -exception_flags = m2_expr.ExprId('exception_flags', 32) - - -def set_pc(ir_arch, src): - dst = ir_arch.jit_pc - if not isinstance(src, m2_expr.Expr): - src = m2_expr.ExprInt_from(dst, src) - e = m2_expr.ExprAff(dst, src.zeroExtend(dst.size)) - return e - - -def gen_resolve_int(ir_arch, e): - return 'Resolve_dst(BlockDst, 0x%X, 0)' % (e.arg) - -def gen_resolve_id_lbl(ir_arch, e): - if e.name.name.startswith("lbl_gen_"): - # TODO XXX CLEAN - return 'Resolve_dst(BlockDst, 0x%X, 1)'%(e.name.index) - else: - return 'Resolve_dst(BlockDst, 0x%X, 0)'%(e.name.offset) - -def gen_resolve_id(ir_arch, e): - return 'Resolve_dst(BlockDst, %s, 0)'%(translator.from_expr(patch_c_id(ir_arch.arch, e))) - -def gen_resolve_mem(ir_arch, e): - return 'Resolve_dst(BlockDst, %s, 0)'%(translator.from_expr(patch_c_id(ir_arch.arch, e))) - -def gen_resolve_other(ir_arch, e): - return 'Resolve_dst(BlockDst, %s, 0)'%(translator.from_expr(patch_c_id(ir_arch.arch, e))) - -def gen_resolve_dst_simple(ir_arch, e): - if isinstance(e, m2_expr.ExprInt): - return gen_resolve_int(ir_arch, e) - elif isinstance(e, m2_expr.ExprId) and isinstance(e.name, - asmbloc.asm_label): - return gen_resolve_id_lbl(ir_arch, e) - elif isinstance(e, m2_expr.ExprId): - return gen_resolve_id(ir_arch, e) - elif isinstance(e, m2_expr.ExprMem): - return gen_resolve_mem(ir_arch, e) - else: - return gen_resolve_other(ir_arch, e) - - -def gen_irdst(ir_arch, e): - out = [] - if isinstance(e, m2_expr.ExprCond): - dst_cond_c = translator.from_expr(patch_c_id(ir_arch.arch, e.cond)) - out.append("if (%s)"%dst_cond_c) - out.append(' %s;'%(gen_resolve_dst_simple(ir_arch, e.src1))) - out.append("else") - out.append(' %s;'%(gen_resolve_dst_simple(ir_arch, e.src2))) - else: - out.append('%s;'%(gen_resolve_dst_simple(ir_arch, e))) - return out - -def Expr2C(ir_arch, l, assignblk, gen_exception_code=False): - id_to_update = [] - out = ["// %s" % (l)] - out_pc = [] - - dst_dict = {} - src_mem = {} - - prefect_index = {8: 0, 16: 0, 32: 0, 64: 0} - new_expr = [] - - pc_is_dst = False - fetch_mem = False - set_exception_flags = False - for dst, src in assignblk.iteritems(): - assert not isinstance(dst, m2_expr.ExprOp) - if dst in dst_dict: - raise RuntimeError("warning: detected multi dst to same id") - new_expr.append((dst, src)) - # test exception flags - ops = m2_expr.get_expr_ops(src) - if set(['umod', 'udiv']).intersection(ops): - set_exception_flags = True - if dst == exception_flags: - set_exception_flags = True - # TODO XXX test function whose set exception_flags - - # search mem lookup for generate mem read prefetch - rs = src.get_r(mem_read=True) - for r in rs: - if (not isinstance(r, m2_expr.ExprMem)) or r in src_mem: - continue - fetch_mem = True - index = prefect_index[r.size] - prefect_index[r.size] += 1 - pfmem = prefetch_id_size[r.size][index] - src_mem[r] = pfmem - - out_mem = [] - - # first, generate mem prefetch - mem_k = src_mem.keys() - mem_k.sort() - for k in mem_k: - str_src = translator.from_expr(patch_c_id(ir_arch.arch, k)) - str_dst = translator.from_expr(patch_c_id(ir_arch.arch, src_mem[k])) - out.append('%s = %s;' % (str_dst, str_src)) - src_w_len = {} - for k, v in src_mem.items(): - src_w_len[k] = v - for dst, src in new_expr: - # reload src using prefetch - src = src.replace_expr(src_w_len) - if dst is ir_arch.IRDst: - out += gen_irdst(ir_arch, src) - continue - - - str_src = translator.from_expr(patch_c_id(ir_arch.arch, src)) - str_dst = translator.from_expr(patch_c_id(ir_arch.arch, dst)) - - - - if isinstance(dst, m2_expr.ExprId): - id_to_update.append(dst) - str_dst = patch_c_new_id(ir_arch.arch, dst) - if dst in ir_arch.arch.regs.regs_flt_expr: - # dont mask float affectation - out.append('%s = (%s);' % (str_dst, str_src)) - else: - out.append('%s = (%s)&0x%X;' % (str_dst, str_src, - my_size_mask[src.size])) - elif isinstance(dst, m2_expr.ExprMem): - fetch_mem = True - str_dst = str_dst.replace('MEM_LOOKUP', 'MEM_WRITE') - out_mem.append('%s, %s);' % (str_dst[:-1], str_src)) - - if dst == ir_arch.arch.pc[ir_arch.attrib]: - pc_is_dst = True - out_pc += ["return JIT_RET_NO_EXCEPTION;"] - - # if len(id_to_update) != len(set(id_to_update)): - # raise ValueError('Not implemented: multi dst to same id!', str([str(x) - # for x in exprs])) - out += out_mem - - if gen_exception_code: - if fetch_mem: - e = set_pc(ir_arch, l.offset & mask_int) - s1 = "%s" % translator.from_expr(patch_c_id(ir_arch.arch, e)) - s1 += ';\n Resolve_dst(BlockDst, 0x%X, 0)'%(l.offset & mask_int) - out.append(code_exception_fetch_mem_at_instr_noautomod % s1) - if set_exception_flags: - e = set_pc(ir_arch, l.offset & mask_int) - s1 = "%s" % translator.from_expr(patch_c_id(ir_arch.arch, e)) - s1 += ';\n Resolve_dst(BlockDst, 0x%X, 0)'%(l.offset & mask_int) - out.append(code_exception_at_instr_noautomod % s1) - - for i in id_to_update: - if i is ir_arch.IRDst: - continue - out.append('%s = %s;' % - (patch_c_id(ir_arch.arch, i), patch_c_new_id(ir_arch.arch, i))) - - post_instr = [] - # test stop exec #### - if gen_exception_code: - if set_exception_flags: - if pc_is_dst: - post_instr.append("if (VM_exception_flag) { " + - "/*pc = 0x%X; */return JIT_RET_EXCEPTION; }" % (l.offset)) - else: - e = set_pc(ir_arch, l.offset & mask_int) - s1 = "%s" % translator.from_expr(patch_c_id(ir_arch.arch, e)) - s1 += ';\n Resolve_dst(BlockDst, 0x%X, 0)'%(l.offset & mask_int) - e = set_pc(ir_arch, (l.offset + l.l) & mask_int) - s2 = "%s" % translator.from_expr(patch_c_id(ir_arch.arch, e)) - s2 += ';\n Resolve_dst(BlockDst, 0x%X, 0)'%((l.offset + l.l) & mask_int) - post_instr.append( - code_exception_post_instr_noautomod % (s1, s2)) - - if fetch_mem: - if l.additional_info.except_on_instr: - offset = l.offset - else: - offset = l.offset + l.l - - e = set_pc(ir_arch, offset & mask_int) - s1 = "%s" % translator.from_expr(patch_c_id(ir_arch.arch, e)) - s1 += ';\n Resolve_dst(BlockDst, 0x%X, 0)'%(offset & mask_int) - post_instr.append( - code_exception_fetch_mem_post_instr_noautomod % (s1)) - - # pc manip after all modifications - return out, post_instr, post_instr + out_pc - - -def label2offset(e): - if not isinstance(e, m2_expr.ExprId): - return e - if not isinstance(e.name, asmbloc.asm_label): - return e - return m2_expr.ExprInt_from(e, e.name.offset) - - -def expr2pyobj(arch, e): - if isinstance(e, m2_expr.ExprId): - if isinstance(e.name, asmbloc.asm_label): - src_c = 'PyString_FromStringAndSize("%s", %d)' % ( - e.name.name, len(e.name.name)) - else: - src_c = 'PyLong_FromUnsignedLongLong(%s)' % patch_c_id(arch, e) - else: - raise NotImplementedError('unknown type for e: %s' % type(e)) - return src_c - - -def ir2C(ir_arch, irbloc, lbl_done, - gen_exception_code=False, log_mn=False, log_regs=False): - out = [] - # print "TRANS" - # print irbloc - out.append(["%s:" % irbloc.label.name]) - #out.append(['printf("%s:\n");' % irbloc.label.name]) - assert len(irbloc.irs) == len(irbloc.lines) - for l, assignblk in zip(irbloc.lines, irbloc.irs): - if l.offset not in lbl_done: - e = set_pc(ir_arch, l.offset & mask_int) - s1 = "%s" % translator.from_expr(patch_c_id(ir_arch.arch, e)) - s1 += ';\n Resolve_dst(BlockDst, 0x%X, 0)'%(l.offset & mask_int) - out.append([pre_instr_test_exception % (s1)]) - lbl_done.add(l.offset) - - if log_regs: - out.append([r'dump_gpregs(jitcpu->cpu);']) - - if log_mn: - out.append(['printf("%.8X %s\\n");' % (l.offset, str(l))]) - # print l - # gen pc update - post_instr = "" - c_code, post_instr, _ = Expr2C(ir_arch, l, assignblk, gen_exception_code) - out.append(c_code + post_instr) - out.append([goto_local_code ] ) - return out - - -def irblocs2C(ir_arch, resolvers, label, irblocs, - gen_exception_code=False, log_mn=False, log_regs=False): - out = [] - - lbls = [b.label for b in irblocs] - lbls_local = [] - for l in lbls: - if l.name.startswith('lbl_gen_'): - l.index = int(l.name[8:], 16) - lbls_local.append(l) - lbl_index_min = 0 - lbls_index = [l.index for l in lbls if hasattr(l, 'index')] - lbls_local.sort(key=lambda x:x.index) - - if lbls_index: - lbl_index_min = min(lbls_index) - for l in lbls_local: - l.index -= lbl_index_min - - out.append("void* local_labels[] = {%s};"%(', '.join(["&&%s"%l.name for l in lbls_local]))) - out.append("vm_cpu_t* mycpu = (vm_cpu_t*)jitcpu->cpu;") - - - out.append("goto %s;" % label.name) - bloc_labels = [x.label for x in irblocs] - assert label in bloc_labels - - lbl_done = set([None]) - - for irbloc in irblocs: - # XXXX TEST - if irbloc.label.offset is None: - b_out = ir2C(ir_arch, irbloc, lbl_done, gen_exception_code) - else: - b_out = ir2C( - ir_arch, irbloc, lbl_done, gen_exception_code, log_mn, log_regs) - for exprs in b_out: - for l in exprs: - out.append(l) - out.append("") - - return out - diff --git a/miasm2/jitter/JitCore.h b/miasm2/jitter/JitCore.h index bae5a417..6add6f37 100644 --- a/miasm2/jitter/JitCore.h +++ b/miasm2/jitter/JitCore.h @@ -132,7 +132,7 @@ PyObject* vm_get_mem(JitCpu *self, PyObject* args); #define VM_exception_flag (((VmMngr*)jitcpu->pyvm)->vm_mngr.exception_flags) #define CPU_exception_flag (((vm_cpu_t*)jitcpu->cpu)->exception_flags) - +#define CPU_exception_flag_at_instr ((CPU_exception_flag) && ((CPU_exception_flag) > EXCEPT_NUM_UPDT_EIP)) #define JIT_RET_EXCEPTION 1 #define JIT_RET_NO_EXCEPTION 0 diff --git a/miasm2/jitter/codegen.py b/miasm2/jitter/codegen.py new file mode 100644 index 00000000..c1f1e392 --- /dev/null +++ b/miasm2/jitter/codegen.py @@ -0,0 +1,567 @@ +import miasm2.expression.expression as m2_expr +from miasm2.ir.ir import irbloc +from miasm2.ir.translators import Translator +from miasm2.core.asmbloc import expr_is_label, asm_block_bad, asm_label + +# Miasm to C translator +translator = Translator.to_language("C") + +PREFETCH_ID = [] +PREFETCH_ID_SIZE = {} +for size in [8, 16, 32, 64]: + PREFETCH_ID_SIZE[size] = [] + for i in xrange(20): + name = 'pfmem%.2d_%d' % (size, i) + c = m2_expr.ExprId(name, size) + # globals()[name] = c + PREFETCH_ID.append(c) + PREFETCH_ID_SIZE[size].append(c) + +SIZE_TO_MASK = {x: 2**x - 1 for x in (1, 2, 3, 7, 8, 16, 32, 64)} + +MASK_INT = 0xffffffffffffffff + + +class Attributes(object): + + """ + Store an irblock attributes + """ + + def __init__(self, log_mn=False, log_regs=False): + self.mem_read = False + self.mem_write = False + self.set_exception = False + self.op_set_exception = False + self.log_mn = log_mn + self.log_regs = log_regs + self.instr = None + + +class CGen(object): + + IMPLICIT_EXCEPTION_OP = set(['umod', 'udiv']) + + """ + Translate native assembly block to C + """ + + CODE_EXCEPTION_MEM_AT_INSTR = r""" + // except fetch mem at instr noauto + if ((VM_exception_flag & ~EXCEPT_CODE_AUTOMOD) & EXCEPT_DO_NOT_UPDATE_PC) { + %s = %s; + BlockDst->address = %s; + return JIT_RET_EXCEPTION; + } + """ + + CODE_EXCEPTION_MEM_POST_INSTR = r""" + // except fetch mem post instr + if (VM_exception_flag) { + %s = %s; + BlockDst->address = %s; + return JIT_RET_EXCEPTION; + } + """ + + CODE_EXCEPTION_AT_INSTR = r""" + if (CPU_exception_flag_at_instr) { + %s = %s; + BlockDst->address = %s; + return JIT_RET_EXCEPTION; + } + """ + + CODE_EXCEPTION_POST_INSTR = r""" + if (CPU_exception_flag) { + %s = %s; + BlockDst->address = %s; + return JIT_RET_EXCEPTION; + } + """ + + CODE_RETURN_EXCEPTION = r""" + return JIT_RET_EXCEPTION; + """ + + CODE_RETURN_NO_EXCEPTION = r""" + %s: + %s = %s; + BlockDst->address = %s; + return JIT_RET_NO_EXCEPTION; + """ + + CODE_CPU_EXCEPTION_POST_INSTR = r""" + if (CPU_exception_flag) { + %s = %s; + BlockDst->address = DST_value; + return JIT_RET_EXCEPTION; + } + """ + + CODE_VM_EXCEPTION_POST_INSTR = r""" + if (VM_exception_flag) { + %s = %s; + BlockDst->address = DST_value; + return JIT_RET_EXCEPTION; + } + """ + + CODE_INIT = r""" + int DST_case; + unsigned long long DST_value; + vm_cpu_t* mycpu = (vm_cpu_t*)jitcpu->cpu; + + goto %s; + """ + + CODE_BAD_BLOCK = r""" + // Unknown mnemonic + CPU_exception_flag = EXCEPT_UNK_MNEMO; + """ + CODE_RETURN_EXCEPTION + + def __init__(self, ir_arch): + self.ir_arch = ir_arch + self.PC = self.ir_arch.pc + self.init_arch_C() + + def init_arch_C(self): + self.id_to_c_id = {} + for reg in self.ir_arch.arch.regs.all_regs_ids + PREFETCH_ID: + self.id_to_c_id[reg] = m2_expr.ExprId('mycpu->%s' % reg, reg.size) + + self.id_to_new_c_id = {} + + for reg in self.ir_arch.arch.regs.all_regs_ids + PREFETCH_ID: + self.id_to_new_c_id[reg] = m2_expr.ExprId( + 'mycpu->%s_new' % reg, reg.size) + + self.C_PC = self.id_to_c(self.PC) + + def dst_to_c(self, src): + if not isinstance(src, m2_expr.Expr): + src = m2_expr.ExprInt(src, self.PC.size) + return self.id_to_c(src) + + def patch_c_id(self, expr): + return expr.replace_expr(self.id_to_c_id) + + def patch_c_new_id(self, expr): + return expr.replace_expr(self.id_to_new_c_id) + + def id_to_c(self, expr): + return translator.from_expr(self.patch_c_id(expr)) + + def id_to_cnew(self, expr): + return translator.from_expr(self.patch_c_new_id(expr)) + + def get_post_instr_label(self, offset): + return self.ir_arch.symbol_pool.getby_name_create("lbl_gen_post_instr_%.8X" % (offset)) + + def add_label_index(self, dst2index, lbl): + dst2index[lbl] = len(dst2index) + + def assignblk_to_irbloc(self, instr, assignblk): + """ + Ensure IRDst is always set in the head @assignblk of the @instr + @assignblk: Assignblk instance + @instr: an instruction instance + """ + if self.ir_arch.IRDst not in assignblk: + assignblk[self.ir_arch.IRDst] = m2_expr.ExprInt( + instr.offset + instr.l, + self.ir_arch.IRDst.size) + + return irbloc(self.ir_arch.get_instr_label(instr), [assignblk]) + + def block2assignblks(self, block): + irblocks_list = [] + for instr in block.lines: + assignblk_head, assignblks_extra = self.ir_arch.instr2ir(instr) + # Keep result in ordered list as first element is the assignblk head + # The remainings order is not really important + irblock_head = self.assignblk_to_irbloc(instr, assignblk_head) + irblocks = [irblock_head] + assignblks_extra + + for irblock in irblocks: + assert irblock.dst is not None + irblocks_list.append(irblocks) + return irblocks_list + + def gen_mem_prefetch(self, assignblk, mems_to_prefetch): + out = [] + for expr, prefetcher in sorted(mems_to_prefetch.iteritems()): + str_src = self.id_to_c(expr) + str_dst = self.id_to_c(prefetcher) + out.append('%s = %s;' % (str_dst, str_src)) + assignblk.C_prefetch = out + return out + + def gen_assignments(self, assignblk, prefetchers): + out_main = [] + out_mem = [] + out_updt = [] + id_to_update = set() + + for dst, src in sorted(assignblk.iteritems()): + src = src.replace_expr(prefetchers) + if dst is self.ir_arch.IRDst: + pass + elif isinstance(dst, m2_expr.ExprId): + id_to_update.add(dst) + str_dst = self.id_to_cnew(dst) + if dst in self.ir_arch.arch.regs.regs_flt_expr: + # Dont mask float affectation + out_main.append('%s = (%s);' % (str_dst, self.id_to_c(src))) + else: + out_main.append( + '%s = (%s)&0x%X;' % (str_dst, self.id_to_c(src), + SIZE_TO_MASK[src.size])) + elif isinstance(dst, m2_expr.ExprMem): + ptr = dst.arg.replace_expr(prefetchers) + new_dst = m2_expr.ExprMem(ptr, dst.size) + str_dst = self.id_to_c(new_dst).replace('MEM_LOOKUP', 'MEM_WRITE') + out_mem.append('%s, %s);' % (str_dst[:-1], self.id_to_c(src))) + else: + raise ValueError("Unknown dst") + + for dst, new_dst in dst_var.iteritems(): + if dst is self.ir_arch.IRDst: + continue + out_updt.append('%s = %s;' % (self.id_to_c(expr), self.id_to_cnew(expr))) + + assignblk.C_main = out_main + assignblk.C_mem = out_mem + assignblk.C_updt = out_updt + + def gen_c_assignblk(self, assignblk): + mem_read, mem_write = False, False + local_prefetch = {} + prefetch_index = {8: 0, 16: 0, 32: 0, 64: 0} + + # Prefetch memory read + for expr in assignblk.get_r(mem_read=True): + if not isinstance(expr, m2_expr.ExprMem): + continue + mem_read = True + index = prefetch_index[expr.size] + prefetch_index[expr.size] += 1 + local_prefetch[expr] = PREFETCH_ID_SIZE[expr.size][index] + + # Check if assignblk can write mem + mem_write = any(isinstance(expr, m2_expr.ExprMem) + for expr in assignblk.get_w()) + + assignblk.mem_write = mem_write + assignblk.mem_read = mem_read + + # Generate memory prefetch + return local_prefetch + + def gen_check_memory_exception(self, address): + dst = self.dst_to_c(address) + return (self.CODE_EXCEPTION_MEM_AT_INSTR % (self.C_PC, dst, dst)).split('\n') + + def gen_check_memory_exception_post(self, address): + dst = self.dst_to_c(address) + return (self.CODE_EXCEPTION_MEM_POST_INSTR % (self.C_PC, dst, dst)).split('\n') + + def gen_check_cpu_exception(self, address): + dst = self.dst_to_c(address) + return (self.CODE_EXCEPTION_AT_INSTR % (self.C_PC, dst, dst)).split('\n') + + def gen_check_cpu_exception_post(self, address): + dst = self.dst_to_c(address) + return (self.CODE_EXCEPTION_POST_INSTR % (self.C_PC, dst, dst)).split('\n') + + def traverse_expr_dst(self, expr, dst2index): + """ + Generate the index of the destination label for the @expr + @dst2index: dictionnary to link label to its index + """ + + if isinstance(expr, m2_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) + return ("((%s)?(%s):(%s))" % (cond, src1, src2), + "((%s)?(%s):(%s))" % (cond, src1b, src2b)) + elif isinstance(expr, m2_expr.ExprInt): + offset = int(expr.arg) + self.add_label_index(dst2index, offset) + return ("%s" % dst2index[offset], + hex(offset)) + elif expr_is_label(expr): + label = expr.name + if label.offset != None: + offset = label.offset + self.add_label_index(dst2index, offset) + return ("%s" % dst2index[offset], + hex(offset)) + else: + self.add_label_index(dst2index, label) + return ("%s" % dst2index[label], + "0") + + elif (isinstance(expr, m2_expr.ExprId) or + isinstance(expr, m2_expr.ExprMem) or + isinstance(expr, m2_expr.ExprSlice)): + dst2index[expr] = -1 + return ("-1", + self.id_to_c(expr)) + else: + raise RuntimeError("Unsupported IRDst type %s" % expr) + + def gen_assignblk_dst(self, dst): + dst2index = {} + (ret, retb) = self.traverse_expr_dst(dst, dst2index) + ret = "DST_case = %s;" % ret + retb = "DST_value = %s;" % retb + return ['// %s' % dst2index, + '%s' % ret, + '%s' % retb], dst2index + + def gen_post_instr_checks(self, attrib, dst): + out = [] + dst = self.dst_to_c(dst) + if attrib.mem_read | attrib.mem_write: + out += (self.CODE_VM_EXCEPTION_POST_INSTR % (self.C_PC, dst)).split('\n') + if attrib.set_exception or attrib.op_set_exception: + out += (self.CODE_CPU_EXCEPTION_POST_INSTR % (self.C_PC, dst)).split('\n') + + return out + + def gen_pre_code(self, attrib): + out = [] + + if attrib.log_mn: + out.append('printf("%.8X %s\\n");' % (attrib.instr.offset, + attrib.instr)) + return out + + def gen_post_code(self, attrib): + out = [] + if attrib.log_regs: + out.append('dump_gpregs(jitcpu->cpu);') + return out + + def gen_goto_code(self, attrib, instr_offsets, dst): + out = [] + if isinstance(dst, asm_label): + out.append('goto %s;' % dst.name) + elif dst in instr_offsets: + lbl = self.ir_arch.symbol_pool.getby_offset_create(dst) + out += self.gen_post_code(attrib) + out += self.gen_post_instr_checks(attrib, dst) + out.append('goto %s;' % lbl.name) + else: + out += self.gen_post_code(attrib) + out.append('BlockDst->address = DST_value;') + out += self.gen_post_instr_checks(attrib, dst) + out.append('\t\treturn JIT_RET_NO_EXCEPTION;') + return out + + def gen_dst_goto(self, attrib, instr_offsets, dst2index): + """ + Generate code for possible @dst2index. + + @attrib: an Attributs instance + @instr_offsets: list of instructions offsets + @dst2index: link from dstination to index + """ + + if not dst2index: + return [] + out = [] + out.append('switch(DST_case) {') + for dst, index in sorted(dst2index.iteritems(), key=lambda lblindex: lblindex[1]): + out.append('\tcase %d:' % index) + out += self.gen_goto_code(attrib, instr_offsets, dst) + out.append('\t\tbreak;') + out.append('};') + return out + + def gen_c_code(self, assignblk, c_dst): + """ + Generate the C code for @assignblk. + @assignblk: an Assignblk instance + @c_dst: irdst C code + """ + out = [] + + out.append("// Prefetch") + out += assignblk.C_prefetch + out.append("// Dst") + out += c_dst + out.append("// Main") + out += assignblk.C_main + + out.append("// Check op/mem exceptions") + + # Check memory access if assignblk has memory read + if assignblk.C_prefetch: + out += self.gen_check_memory_exception(assignblk.instr_addr) + + # Check if operator raised exception flags + if assignblk.op_set_exception: + out += self.gen_check_cpu_exception(assignblk.instr_addr) + + out.append("// Mem updt") + out += assignblk.C_mem + + out.append("// Check exception Mem write") + # Check memory write exceptions + if assignblk.mem_write: + out += self.gen_check_memory_exception(assignblk.instr_addr) + + out.append("// Updt") + out += assignblk.C_updt + + out.append("// Checks exception") + + # Check post assignblk exception flags + if assignblk.set_exception: + out += self.gen_check_cpu_exception(assignblk.instr_addr) + + return out + + def is_exception_operator(self, operator): + """Return True if the @op operator can raise a runtime exception""" + + return any(operator.startswith(except_op) + for except_op in self.IMPLICIT_EXCEPTION_OP) + + def get_caracteristics(self, irblock): + """ + Get the carateristics of each assignblk in the @irblock + @irblock: an irbloc instance + """ + + for assignblk in irblock.irs: + assignblk.mem_read, assignblk.mem_write = False, False + assignblk.op_set_exception = False + # Check explicit exception raising + assignblk.set_exception = self.ir_arch.arch.regs.exception_flags in assignblk + + element_read = assignblk.get_r(mem_read=True) + # Check implicit exception raising + assignblk.op_set_exception = any(self.is_exception_operator(operator) + for elem in assignblk.values() + for operator in m2_expr.get_expr_ops(elem)) + # Check mem read + assignblk.mem_read = any(isinstance(expr, m2_expr.ExprMem) + for expr in element_read) + # Check mem write + assignblk.mem_write = any(isinstance(dst, m2_expr.ExprMem) + for dst in assignblk) + + def get_attributes(self, instr, irblocks, log_mn=False, log_regs=False): + """ + Get the carateristics of each @irblocks. Returns the corresponding + attributes object. + @irblock: a list of irbloc instance + @log_mn: generate code to log instructions + @log_regs: generate code to log registers states + """ + + attrib = Attributes(log_mn, log_regs) + + for irblock in irblocks: + for assignblk in irblock.irs: + self.get_caracteristics(irblock) + attrib.mem_read |= assignblk.mem_read + attrib.mem_write |= assignblk.mem_write + attrib.set_exception |= assignblk.set_exception + attrib.op_set_exception |= assignblk.op_set_exception + attrib.instr = instr + return attrib + + def gen_bad_block(self): + """ + Generate the C code for a bad_block instance + """ + return self.CODE_BAD_BLOCK.split("\n") + + def get_block_post_label(self, block): + last_instr = block.lines[-1] + offset = last_instr.offset + last_instr.l + return self.ir_arch.symbol_pool.getby_offset_create(offset) + + def gen_init(self, block): + """ + Generate the init C code for a @block + @block: an asm_bloc instance + """ + + instr_offsets = [line.offset for line in block.lines] + instr_offsets.append(self.get_block_post_label(block).offset) + lbl_start = self.ir_arch.symbol_pool.getby_offset_create(instr_offsets[0]) + return (self.CODE_INIT % lbl_start.name).split("\n"), instr_offsets + + def gen_irblock(self, attrib, instr_offsets, instr, irblock): + """ + Generate the C code for an @irblock + @instr: the current instruction to translate + @irblock: an irbloc instance + @attrib: an Attributs instance + """ + + out = [] + dst2index = None + for index, assignblk in enumerate(irblock.irs): + if index == irblock.dst_linenb: + c_dst, dst2index = self.gen_assignblk_dst(irblock.dst) + else: + c_dst = [] + assignblk.instr_addr = instr.offset + prefetchers = self.gen_c_assignblk(assignblk) + self.gen_mem_prefetch(assignblk, prefetchers) + self.gen_assignments(assignblk, prefetchers) + + out += self.gen_c_code(assignblk, c_dst) + + if dst2index: + out.append("// Set irdst") + # Gen goto on irdst set + out += self.gen_dst_goto(attrib, instr_offsets, dst2index) + + return out + + def gen_finalize(self, block): + """ + Generate the C code for the final block instruction + """ + + lbl = self.get_block_post_label(block) + dst = self.dst_to_c(lbl.offset) + code = self.CODE_RETURN_NO_EXCEPTION % (lbl.name, self.C_PC, dst, dst) + return code.split('\n') + + def gen_c(self, block, log_mn=False, log_regs=False): + """ + Generate the C code for the @block and return it as a list of lines + @log_mn: log mnemonics + @log_regs: log registers + """ + + if isinstance(block, asm_block_bad): + return self.gen_bad_block() + irblocks_list = self.block2assignblks(block) + + out, instr_offsets = self.gen_init(block) + + for instr, irblocks in zip(block.lines, irblocks_list): + attrib = self.get_attributes(instr, irblocks, log_mn, log_regs) + + for index, irblock in enumerate(irblocks): + self.ir_arch.irbloc_fix_regs_for_mode( + irblock, self.ir_arch.attrib) + + out.append("%-40s // %.16X %s" % + (str(irblock.label.name) + ":", instr.offset, instr)) + if index == 0: + out += self.gen_pre_code(attrib) + out += self.gen_irblock(attrib, instr_offsets, instr, irblock) + + out += self.gen_finalize(block) + return ['\t' + line for line in out] diff --git a/miasm2/jitter/csts.py b/miasm2/jitter/csts.py index b71e9463..7af2435f 100644 --- a/miasm2/jitter/csts.py +++ b/miasm2/jitter/csts.py @@ -13,6 +13,9 @@ EXCEPT_BREAKPOINT_INTERN = (1 << 10) EXCEPT_ACCESS_VIOL = ((1 << 14) | EXCEPT_DO_NOT_UPDATE_PC) EXCEPT_DIV_BY_ZERO = ((1 << 16) | EXCEPT_DO_NOT_UPDATE_PC) EXCEPT_PRIV_INSN = ((1 << 17) | EXCEPT_DO_NOT_UPDATE_PC) +EXCEPT_ILLEGAL_INSN = ((1 << 18) | EXCEPT_DO_NOT_UPDATE_PC) +EXCEPT_UNK_MNEMO = ((1 << 19) | EXCEPT_DO_NOT_UPDATE_PC) + # VM Mngr constants PAGE_READ = 1 diff --git a/miasm2/jitter/jitcore.py b/miasm2/jitter/jitcore.py index 74c438a7..6048d62e 100644 --- a/miasm2/jitter/jitcore.py +++ b/miasm2/jitter/jitcore.py @@ -95,6 +95,11 @@ class JitCore(object): if cur_bloc.lines: cur_bloc.ad_min = cur_bloc.lines[0].offset cur_bloc.ad_max = cur_bloc.lines[-1].offset + cur_bloc.lines[-1].l + else: + # 1 byte block for unknown mnemonic + cur_bloc.ad_min = cur_bloc.label.offset + cur_bloc.ad_max = cur_bloc.label.offset+1 + def add_bloc_to_mem_interval(self, vm, bloc): "Update vm to include bloc addresses in its memory range" @@ -148,10 +153,6 @@ class JitCore(object): if self.log_newbloc: print cur_bloc - # Check for empty blocks - if not cur_bloc.lines: - raise ValueError("Cannot JIT a block without any assembly line") - # Update label -> bloc self.lbl2bloc[cur_bloc.label] = cur_bloc diff --git a/miasm2/jitter/jitcore_gcc.py b/miasm2/jitter/jitcore_gcc.py index a633f935..7f72d8e7 100644 --- a/miasm2/jitter/jitcore_gcc.py +++ b/miasm2/jitter/jitcore_gcc.py @@ -9,7 +9,6 @@ from distutils.sysconfig import get_python_inc from subprocess import check_call from hashlib import md5 -from miasm2.ir.ir2C import irblocs2C from miasm2.jitter import jitcore, Jitgcc from miasm2.core.utils import keydefaultdict @@ -97,6 +96,13 @@ class JitCore_Gcc(jitcore.JitCore): self.include_files = include_files self.libs = libs + def init_codegen(self, codegen): + """ + Get the code generator @codegen + @codegen: an CGen instance + """ + self.codegen = codegen + def label2fname(self, label): """ Generate function name from @label @@ -112,7 +118,8 @@ class JitCore_Gcc(jitcore.JitCore): self.lbl2jitbloc[label.offset] = addr self.gcc_states[label.offset] = lib - def gen_c_code(self, label, irblocks): + + def gen_c_code(self, label, block): """ Return the C code corresponding to the @irblocks @label: asm_label of the block to jit @@ -120,10 +127,7 @@ class JitCore_Gcc(jitcore.JitCore): """ f_name = self.label2fname(label) f_declaration = 'int %s(block_id * BlockDst, JitCpu* jitcpu)' % f_name - out = irblocs2C(self.ir_arch, self.resolver, label, irblocks, - gen_exception_code=True, - log_mn=self.log_mn, - log_regs=self.log_regs) + out = self.codegen.gen_c(block, log_mn=self.log_mn, log_regs=self.log_regs) out = [f_declaration + '{'] + out + ['}\n'] c_code = out @@ -141,8 +145,7 @@ class JitCore_Gcc(jitcore.JitCore): fname_out = os.path.join(self.tempdir, "%s.so" % block_hash) if not os.access(fname_out, os.R_OK | os.X_OK): - irblocks = self.ir_arch.add_bloc(block, gen_pc_updt=True) - func_code = self.gen_c_code(block.label, irblocks) + func_code = self.gen_c_code(block.label, block) # Create unique C file fdesc, fname_in = tempfile.mkstemp(suffix=".c") diff --git a/miasm2/jitter/jitcore_tcc.py b/miasm2/jitter/jitcore_tcc.py index 151fab7d..d3e90f85 100644 --- a/miasm2/jitter/jitcore_tcc.py +++ b/miasm2/jitter/jitcore_tcc.py @@ -7,7 +7,6 @@ from subprocess import Popen, PIPE from hashlib import md5 import tempfile -from miasm2.ir.ir2C import irblocs2C from miasm2.jitter import jitcore, Jittcc @@ -141,6 +140,13 @@ class JitCore_Tcc(jitcore.JitCore): include_files = ";".join(include_files) Jittcc.tcc_set_emul_lib_path(include_files, libs) + def init_codegen(self, codegen): + """ + Get the code generator @codegen + @codegen: an CGen instance + """ + self.codegen = codegen + def __del__(self): for tcc_state in self.tcc_states.values(): Jittcc.tcc_end(tcc_state) @@ -164,7 +170,7 @@ class JitCore_Tcc(jitcore.JitCore): self.lbl2jitbloc[label.offset] = mcode self.tcc_states[label.offset] = tcc_state - def gen_c_code(self, label, irblocks): + def gen_c_code(self, label, block): """ Return the C code corresponding to the @irblocks @label: asm_label of the block to jit @@ -172,10 +178,7 @@ class JitCore_Tcc(jitcore.JitCore): """ f_name = self.label2fname(label) f_declaration = 'int %s(block_id * BlockDst, JitCpu* jitcpu)' % f_name - out = irblocs2C(self.ir_arch, self.resolver, label, irblocks, - gen_exception_code=True, - log_mn=self.log_mn, - log_regs=self.log_regs) + out = self.codegen.gen_c(block, log_mn=self.log_mn, log_regs=self.log_regs) out = [f_declaration + '{'] + out + ['}\n'] c_code = out @@ -194,9 +197,7 @@ class JitCore_Tcc(jitcore.JitCore): if os.access(fname_out, os.R_OK): func_code = open(fname_out).read() else: - irblocks = self.ir_arch.add_bloc(block, gen_pc_updt=True) - block.irblocs = irblocks - func_code = self.gen_c_code(block.label, irblocks) + func_code = self.gen_c_code(block.label, block) # Create unique C file fdesc, fname_tmp = tempfile.mkstemp(suffix=".c") diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py index 2371067d..8943e2c7 100644 --- a/miasm2/jitter/jitload.py +++ b/miasm2/jitter/jitload.py @@ -7,9 +7,9 @@ from collections import Sequence, namedtuple, Iterator from miasm2.jitter.csts import * from miasm2.core.utils import * from miasm2.core.bin_stream import bin_stream_vm -from miasm2.ir.ir2C import init_arch_C from miasm2.core.interval import interval from miasm2.jitter.emulatedsymbexec import EmulatedSymbExec +from miasm2.jitter.codegen import CGen hnd = logging.StreamHandler() hnd.setFormatter(logging.Formatter("[%(levelname)s]: %(message)s")) @@ -161,11 +161,14 @@ class jitter: "Main class for JIT handling" + C_Gen = CGen + def __init__(self, ir_arch, jit_type="tcc"): """Init an instance of jitter. @ir_arch: ir instance for this architecture @jit_type: JiT backend to use. Available options are: - "tcc" + - "gcc" - "llvm" - "python" """ @@ -194,7 +197,6 @@ class jitter: self.cpu = jcore.JitCpu() self.ir_arch = ir_arch self.bs = bin_stream_vm(self.vm) - init_arch_C(self.arch) self.symbexec = EmulatedSymbExec(self.cpu, self.ir_arch, {}) self.symbexec.reset_regs() @@ -214,6 +216,8 @@ class jitter: raise RuntimeError('Unsupported jitter: %s' % jit_type) self.jit = JitCore(self.ir_arch, self.bs) + if jit_type in ['tcc', 'gcc']: + self.jit.init_codegen(self.C_Gen(self.ir_arch)) self.cpu.init_regs() self.vm.init_memory_page_pool() diff --git a/test/test_all.py b/test/test_all.py index 35f081de..a487900f 100644 --- a/test/test_all.py +++ b/test/test_all.py @@ -232,8 +232,7 @@ for script in ["modint.py", ]: testset += RegressionTest([script], base_dir="expression") ## IR -for script in ["ir2C.py", - "symbexec.py", +for script in ["symbexec.py", ]: testset += RegressionTest([script], base_dir="ir") testset += RegressionTest(["analysis.py"], base_dir="ir", |