diff options
| -rw-r--r-- | miasm2/arch/aarch64/ira.py | 7 | ||||
| -rw-r--r-- | miasm2/arch/arm/ira.py | 7 | ||||
| -rw-r--r-- | miasm2/arch/mips32/jit.py | 2 | ||||
| -rw-r--r-- | miasm2/arch/msp430/ira.py | 14 | ||||
| -rw-r--r-- | miasm2/arch/x86/ira.py | 14 | ||||
| -rw-r--r-- | miasm2/jitter/codegen.py | 34 | ||||
| -rw-r--r-- | miasm2/jitter/jitcore_cc_base.py | 2 | ||||
| -rw-r--r-- | miasm2/jitter/jitcore_llvm.py | 4 | ||||
| -rw-r--r-- | miasm2/jitter/llvmconvert.py | 14 | ||||
| -rw-r--r-- | miasm2/jitter/vm_mngr_py.c | 8 | ||||
| -rw-r--r-- | test/jitter/test_post_instr.py | 46 | ||||
| -rwxr-xr-x | test/test_all.py | 1 |
12 files changed, 89 insertions, 64 deletions
diff --git a/miasm2/arch/aarch64/ira.py b/miasm2/arch/aarch64/ira.py index ada2e028..5a89e910 100644 --- a/miasm2/arch/aarch64/ira.py +++ b/miasm2/arch/aarch64/ira.py @@ -24,13 +24,6 @@ class ir_a_aarch64l(ir_a_aarch64l_base): ir_a_aarch64l_base.__init__(self, symbol_pool) self.ret_reg = self.arch.regs.X0 - # for test XXX TODO - def set_dead_regs(self, irblock): - irblock.rw[-1][1].add(self.arch.regs.zf) - irblock.rw[-1][1].add(self.arch.regs.nf) - irblock.rw[-1][1].add(self.arch.regs.of) - irblock.rw[-1][1].add(self.arch.regs.cf) - def get_out_regs(self, _): return set([self.ret_reg, self.sp]) diff --git a/miasm2/arch/arm/ira.py b/miasm2/arch/arm/ira.py index 760e6d90..bfa9bad2 100644 --- a/miasm2/arch/arm/ira.py +++ b/miasm2/arch/arm/ira.py @@ -21,13 +21,6 @@ class ir_a_arml(ir_a_arml_base): ir_a_arml_base.__init__(self, symbol_pool) self.ret_reg = self.arch.regs.R0 - # for test XXX TODO - def set_dead_regs(self, irblock): - irblock.rw[-1][1].add(self.arch.regs.zf) - irblock.rw[-1][1].add(self.arch.regs.nf) - irblock.rw[-1][1].add(self.arch.regs.of) - irblock.rw[-1][1].add(self.arch.regs.cf) - def get_out_regs(self, _): return set([self.ret_reg, self.sp]) diff --git a/miasm2/arch/mips32/jit.py b/miasm2/arch/mips32/jit.py index 0ba531f1..bfa9c5fd 100644 --- a/miasm2/arch/mips32/jit.py +++ b/miasm2/arch/mips32/jit.py @@ -63,7 +63,7 @@ class mipsCGen(CGen): """ lbl = self.get_block_post_label(block) - out = (self.CODE_RETURN_NO_EXCEPTION % (lbl.name, + out = (self.CODE_RETURN_NO_EXCEPTION % (self.label_to_jitlabel(lbl), self.C_PC, m2_expr.ExprId('branch_dst_irdst'), m2_expr.ExprId('branch_dst_irdst'), diff --git a/miasm2/arch/msp430/ira.py b/miasm2/arch/msp430/ira.py index 0dc63c61..0f88facc 100644 --- a/miasm2/arch/msp430/ira.py +++ b/miasm2/arch/msp430/ira.py @@ -16,20 +16,6 @@ class ir_a_msp430(ir_a_msp430_base): def __init__(self, symbol_pool=None): ir_a_msp430_base.__init__(self, symbol_pool) - # for test XXX TODO - def set_dead_regs(self, irblock): - irblock.rw[-1][1].add(self.arch.regs.zf) - irblock.rw[-1][1].add(self.arch.regs.nf) - irblock.rw[-1][1].add(self.arch.regs.of) - irblock.rw[-1][1].add(self.arch.regs.cf) - - irblock.rw[-1][1].add(self.arch.regs.res) - irblock.rw[-1][1].add(self.arch.regs.scg1) - irblock.rw[-1][1].add(self.arch.regs.scg0) - irblock.rw[-1][1].add(self.arch.regs.osc) - irblock.rw[-1][1].add(self.arch.regs.cpuoff) - irblock.rw[-1][1].add(self.arch.regs.gie) - def get_out_regs(self, _): return set([self.ret_reg, self.sp]) diff --git a/miasm2/arch/x86/ira.py b/miasm2/arch/x86/ira.py index 74aa0203..1fcaaa52 100644 --- a/miasm2/arch/x86/ira.py +++ b/miasm2/arch/x86/ira.py @@ -12,23 +12,9 @@ class ir_a_x86_16(ir_x86_16, ira): ir_x86_16.__init__(self, symbol_pool) self.ret_reg = self.arch.regs.AX - # for test XXX TODO - def set_dead_regs(self, irblock): - irblock.rw[-1][1].add(self.arch.regs.zf) - irblock.rw[-1][1].add(self.arch.regs.of) - irblock.rw[-1][1].add(self.arch.regs.pf) - irblock.rw[-1][1].add(self.arch.regs.cf) - irblock.rw[-1][1].add(self.arch.regs.nf) - irblock.rw[-1][1].add(self.arch.regs.af) - def get_out_regs(self, _): return set([self.ret_reg, self.sp]) - def add_unused_regs(self): - leaves = [self.blocks[label] for label in self.g.leafs()] - for irblock in leaves: - self.set_dead_regs(irblock) - class ir_a_x86_32(ir_x86_32, ir_a_x86_16): def __init__(self, symbol_pool=None): diff --git a/miasm2/jitter/codegen.py b/miasm2/jitter/codegen.py index 9d005451..09a6fecf 100644 --- a/miasm2/jitter/codegen.py +++ b/miasm2/jitter/codegen.py @@ -65,7 +65,7 @@ class CGen(object): CODE_CPU_EXCEPTION_POST_INSTR = r""" if (CPU_exception_flag) { - %s = %s; + %s = DST_value; BlockDst->address = DST_value; return JIT_RET_EXCEPTION; } @@ -75,7 +75,7 @@ class CGen(object): check_memory_breakpoint(&(jitcpu->pyvm->vm_mngr)); check_invalid_code_blocs(&(jitcpu->pyvm->vm_mngr)); if (VM_exception_flag) { - %s = %s; + %s = DST_value; BlockDst->address = DST_value; return JIT_RET_EXCEPTION; } @@ -106,6 +106,11 @@ class CGen(object): self.C_PC = self.id_to_c(self.PC) + @staticmethod + def label_to_jitlabel(lbl): + assert lbl.offset is not None + return "jitblock_%X" % lbl.offset + def dst_to_c(self, src): if not isinstance(src, m2_expr.Expr): src = m2_expr.ExprInt(src, self.PC.size) @@ -296,13 +301,12 @@ class CGen(object): '%s' % ret, '%s' % retb], dst2index - def gen_post_instr_checks(self, attrib, dst): + def gen_post_instr_checks(self, attrib): 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') + out += (self.CODE_VM_EXCEPTION_POST_INSTR % (self.C_PC)).split('\n') if attrib.set_exception or attrib.op_set_exception: - out += (self.CODE_CPU_EXCEPTION_POST_INSTR % (self.C_PC, dst)).split('\n') + out += (self.CODE_CPU_EXCEPTION_POST_INSTR % (self.C_PC)).split('\n') if attrib.mem_read | attrib.mem_write: out.append("reset_memory_access(&(jitcpu->pyvm->vm_mngr));") @@ -340,12 +344,12 @@ class CGen(object): # (consecutive instructions) 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) + out += self.gen_post_instr_checks(attrib) + out.append('goto %s;' % self.label_to_jitlabel(lbl)) else: out += self.gen_post_code(attrib) out.append('BlockDst->address = DST_value;') - out += self.gen_post_instr_checks(attrib, dst) + out += self.gen_post_instr_checks(attrib) out.append('\t\treturn JIT_RET_NO_EXCEPTION;') return out @@ -497,7 +501,7 @@ class CGen(object): 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 + return (self.CODE_INIT % self.label_to_jitlabel(lbl_start)).split("\n"), instr_offsets def gen_irblock(self, attrib, instr_offsets, instr, irblock): """ @@ -535,7 +539,7 @@ class CGen(object): 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) + code = self.CODE_RETURN_NO_EXCEPTION % (self.label_to_jitlabel(lbl), self.C_PC, dst, dst) return code.split('\n') def gen_c(self, block, log_mn=False, log_regs=False): @@ -558,8 +562,12 @@ class CGen(object): 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 irblock.label.offset is None: + out.append("%-40s // %.16X %s" % + (str(irblock.label.name) + ":", instr.offset, instr)) + else: + out.append("%-40s // %.16X %s" % + (self.label_to_jitlabel(irblock.label) + ":", instr.offset, instr)) if index == 0: out += self.gen_pre_code(attrib) out += self.gen_irblock(attrib, instr_offsets, instr, irblock) diff --git a/miasm2/jitter/jitcore_cc_base.py b/miasm2/jitter/jitcore_cc_base.py index ae8a5dc2..0ca2392d 100644 --- a/miasm2/jitter/jitcore_cc_base.py +++ b/miasm2/jitter/jitcore_cc_base.py @@ -90,7 +90,7 @@ class JitCore_Cc_Base(JitCore): Generate function name from @label @label: AsmLabel instance """ - return "block_%s" % label.name + return "block_%s" % self.codegen.label_to_jitlabel(label) def gen_c_code(self, label, block): """ diff --git a/miasm2/jitter/jitcore_llvm.py b/miasm2/jitter/jitcore_llvm.py index d082dd79..7765ad39 100644 --- a/miasm2/jitter/jitcore_llvm.py +++ b/miasm2/jitter/jitcore_llvm.py @@ -82,7 +82,7 @@ class JitCore_LLVM(jitcore.JitCore): if not os.access(fname_out, os.R_OK): # Build a function in the context - func = LLVMFunction(self.context, block.label.name) + func = LLVMFunction(self.context, LLVMFunction.canonize_label_name(block.label)) # Set log level func.log_regs = self.log_regs @@ -113,7 +113,7 @@ class JitCore_LLVM(jitcore.JitCore): else: # The cache file exists: function can be loaded from cache - ptr = self.context.get_ptr_from_cache(fname_out, block.label.name) + ptr = self.context.get_ptr_from_cache(fname_out, LLVMFunction.canonize_label_name(block.label)) # Store a pointer on the function jitted code self.lbl2jitbloc[block.label.offset] = ptr diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py index 85000935..b2e1e957 100644 --- a/miasm2/jitter/llvmconvert.py +++ b/miasm2/jitter/llvmconvert.py @@ -503,15 +503,19 @@ class LLVMFunction(): var_casted = var self.builder.ret(var_casted) - def canonize_label_name(self, label): + @staticmethod + def canonize_label_name(label): """Canonize @label names to a common form. @label: str or asmlabel instance""" if isinstance(label, str): return label - elif isinstance(label, m2_asmblock.AsmLabel): - return "label_%s" % label.name - elif m2_asmblock.expr_is_label(label): - return "label_%s" % label.name.name + if m2_asmblock.expr_is_label(label): + label = label.name + if isinstance(label, m2_asmblock.AsmLabel): + if label.offset is None: + return "label_%s" % label.name + else: + return "label_%X" % label.offset else: raise ValueError("label must either be str or asmlabel") diff --git a/miasm2/jitter/vm_mngr_py.c b/miasm2/jitter/vm_mngr_py.c index e8c8715e..b53e098a 100644 --- a/miasm2/jitter/vm_mngr_py.c +++ b/miasm2/jitter/vm_mngr_py.c @@ -262,6 +262,14 @@ PyObject* vm_add_memory_breakpoint(VmMngr* self, PyObject* args) PyGetInt(access, b_access); add_memory_breakpoint(&self->vm_mngr, b_ad, b_size, b_access); + + /* Raise exception in the following pattern: + - set_mem(XXX) + - add_memory_breakpoint(XXX) + -> Here, there is a pending breakpoint not raise + */ + check_memory_breakpoint(&self->vm_mngr); + Py_INCREF(Py_None); return Py_None; } diff --git a/test/jitter/test_post_instr.py b/test/jitter/test_post_instr.py new file mode 100644 index 00000000..ceba469d --- /dev/null +++ b/test/jitter/test_post_instr.py @@ -0,0 +1,46 @@ +from miasm2.analysis.machine import Machine +from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE, EXCEPT_BREAKPOINT_INTERN, EXCEPT_ACCESS_VIOL +import sys + +machine = Machine("x86_32") +jitter = machine.jitter(sys.argv[1]) + +# Prepare stack and reset memory accesses to avoid an exception +jitter.vm.add_memory_page(0x10000, PAGE_READ|PAGE_WRITE, "\x00"*0x1000, "stack") +print jitter.vm + +jitter.cpu.ESP = 0x10000 + 0x1000 +jitter.push_uint32_t(0x0) +jitter.push_uint32_t(0x1337beef) + +jitter.vm.reset_memory_access() +print hex(jitter.vm.get_exception()) + +# Add code, and keep memory write pending +jitter.vm.add_memory_page(0x1000, PAGE_READ|PAGE_WRITE, "\x00"*0x1000, "code page") + +# MOV EAX, 0x11223344 +# RET +jitter.vm.set_mem(0x1000, "B844332211C3".decode('hex')) + +jitter.jit.log_mn = True +jitter.jit.log_regs = True + +def do_not_raise_me(jitter): + raise ValueError("Should not be here") + +jitter.exceptions_handler.callbacks[EXCEPT_BREAKPOINT_INTERN] = [] +jitter.add_exception_handler(EXCEPT_BREAKPOINT_INTERN, + do_not_raise_me) +jitter.vm.add_memory_breakpoint(0x11000-4, 4, 7) + +# The memory write pending will raise automod execption +# The RET should not re evalueate PC @ [ESP+4] +jitter.init_run(0x1000) +try: + jitter.continue_run() +except AssertionError: + assert jitter.vm.get_exception() == EXCEPT_ACCESS_VIOL +except RuntimeError: + assert sys.argv[1] == 'python' + assert jitter.vm.get_exception() == EXCEPT_ACCESS_VIOL diff --git a/test/test_all.py b/test/test_all.py index dc17c19b..9b3f2dc1 100755 --- a/test/test_all.py +++ b/test/test_all.py @@ -341,6 +341,7 @@ for i, test_args in enumerate(test_args): for script in ["jitload.py", "vm_mngr.py", "jit_options.py", + "test_post_instr.py", ]: for engine in ArchUnitTest.jitter_engines: testset += RegressionTest([script, engine], base_dir="jitter", |