about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm2/core/utils.py5
-rw-r--r--miasm2/ir/ir2C.py24
-rw-r--r--miasm2/jitter/JitCore.h3
-rw-r--r--miasm2/jitter/Jittcc.c50
-rw-r--r--miasm2/jitter/jitcore.py12
-rw-r--r--miasm2/jitter/jitcore_python.py2
-rw-r--r--miasm2/jitter/jitcore_tcc.py2
-rw-r--r--miasm2/jitter/jitload.py18
8 files changed, 74 insertions, 42 deletions
diff --git a/miasm2/core/utils.py b/miasm2/core/utils.py
index 75eb3113..30aff7d2 100644
--- a/miasm2/core/utils.py
+++ b/miasm2/core/utils.py
@@ -119,6 +119,11 @@ class BoundedDict(UserDict.DictMixin):
         "Return the list of dict's keys"
         return self._data.keys()
 
+    @property
+    def data(self):
+        "Return the current instance as a dictionnary"
+        return self._data
+
     def __getitem__(self, key):
         # Retrieve data first to raise the proper exception on error
         data = self._data[key]
diff --git a/miasm2/ir/ir2C.py b/miasm2/ir/ir2C.py
index 6cf3b4e6..0161c391 100644
--- a/miasm2/ir/ir2C.py
+++ b/miasm2/ir/ir2C.py
@@ -51,7 +51,7 @@ pre_instr_test_exception = r"""
 // pre instruction test exception
 if (VM_exception_flag) {
     %s;
-    return;
+    return JIT_RET_EXCEPTION;
 }
 """
 
@@ -60,14 +60,14 @@ code_exception_fetch_mem_at_instr = r"""
 // except fetch mem at instr
 if (VM_exception_flag & EXCEPT_DO_NOT_UPDATE_PC) {
     %s;
-    return;
+    return JIT_RET_EXCEPTION;
 }
 """
 code_exception_fetch_mem_post_instr = r"""
 // except fetch mem post instr
 if (VM_exception_flag) {
     %s;
-    return;
+    return JIT_RET_EXCEPTION;
 }
 """
 
@@ -76,14 +76,14 @@ 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;
+    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;
+    return JIT_RET_EXCEPTION;
 }
 """
 
@@ -92,7 +92,7 @@ code_exception_at_instr = r"""
 // except at instr
 if (CPU_exception_flag && CPU_exception_flag > EXCEPT_NUM_UPDT_EIP) {
     %s;
-    return;
+    return JIT_RET_EXCEPTION;
 }
 """
 
@@ -105,7 +105,7 @@ if (CPU_exception_flag) {
     else {
       %s;
     }
-    return;
+    return JIT_RET_EXCEPTION;
 }
 """
 
@@ -113,7 +113,7 @@ if (CPU_exception_flag) {
 code_exception_at_instr_noautomod = r"""
 if ((CPU_exception_flag & ~EXCEPT_CODE_AUTOMOD) && (CPU_exception_flag > EXCEPT_NUM_UPDT_EIP)) {
     %s;
-    return;
+    return JIT_RET_EXCEPTION;
 }
 """
 
@@ -125,7 +125,7 @@ if (CPU_exception_flag & ~EXCEPT_CODE_AUTOMOD) {
     else {
       %s;
     }
-    return;
+    return JIT_RET_EXCEPTION;
 }
 """
 
@@ -134,7 +134,7 @@ if (BlockDst->is_local) {
     goto *local_labels[BlockDst->address];
 }
 else {
-    return;
+    return JIT_RET_NO_EXCEPTION;
 }
 """
 
@@ -296,7 +296,7 @@ def Expr2C(ir_arch, l, exprs, gen_exception_code=False):
 
         if e.dst == ir_arch.arch.pc[ir_arch.attrib]:
             pc_is_dst = True
-            out_pc += ["return;"]
+            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)
@@ -327,7 +327,7 @@ def Expr2C(ir_arch, l, exprs, gen_exception_code=False):
         if set_exception_flags:
             if pc_is_dst:
                 post_instr.append("if (VM_exception_flag) { " +
-                    "/*pc = 0x%X; */return; }" % (l.offset))
+                    "/*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))
diff --git a/miasm2/jitter/JitCore.h b/miasm2/jitter/JitCore.h
index af87a9cb..c8400701 100644
--- a/miasm2/jitter/JitCore.h
+++ b/miasm2/jitter/JitCore.h
@@ -131,4 +131,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 JIT_RET_EXCEPTION 1
+#define JIT_RET_NO_EXCEPTION 0
+
 #endif
diff --git a/miasm2/jitter/Jittcc.c b/miasm2/jitter/Jittcc.c
index d146aaf4..a2102609 100644
--- a/miasm2/jitter/Jittcc.c
+++ b/miasm2/jitter/Jittcc.c
@@ -124,23 +124,53 @@ typedef struct {
 	uint64_t address;
 } block_id;
 
+typedef int (*jitted_func)(block_id*, PyObject*);
+
 
 PyObject* tcc_exec_bloc(PyObject* self, PyObject* args)
 {
-	void (*func)(block_id*, PyObject*);
+	jitted_func func;
 	PyObject* jitcpu;
-	block_id BlockDst = {0, 0};
-
-	if (!PyArg_ParseTuple(args, "KO", &func, &jitcpu))
+	PyObject* func_py;
+	PyObject* lbl2ptr;
+	PyObject* breakpoints;
+	PyObject* retaddr = NULL;
+	int status;
+	block_id BlockDst;
+
+	if (!PyArg_ParseTuple(args, "OOOO", &retaddr, &jitcpu, &lbl2ptr, &breakpoints))
 		return NULL;
-	func(&BlockDst, jitcpu);
 
-	if (BlockDst.is_local == 1) {
-		fprintf(stderr, "return on local label!\n");
-		exit(1);
-	}
+	for (;;) {
+		// Init
+		BlockDst.is_local = 0;
+		BlockDst.address = 0;
+
+		// Get the expected jitted function address
+		func_py = PyDict_GetItem(lbl2ptr, retaddr);
+		if (func_py)
+			func = (jitted_func) PyInt_AsLong((PyObject*) func_py);
+		else {
+			if (BlockDst.is_local == 1) {
+				fprintf(stderr, "return on local label!\n");
+				exit(1);
+			}
+			// retaddr is not jitted yet
+			return retaddr;
+		}
+
+		// Execute it
+		status = func(&BlockDst, jitcpu);
+		retaddr = PyLong_FromUnsignedLongLong(BlockDst.address);
 
-	return PyLong_FromUnsignedLongLong(BlockDst.address);
+		// Check exception
+		if (status)
+			return retaddr;
+
+		// Check breakpoint
+		if (PyDict_Contains(breakpoints, retaddr))
+			return retaddr;
+	}
 }
 
 PyObject* tcc_compil(PyObject* self, PyObject* args)
diff --git a/miasm2/jitter/jitcore.py b/miasm2/jitter/jitcore.py
index a3a91d76..46451520 100644
--- a/miasm2/jitter/jitcore.py
+++ b/miasm2/jitter/jitcore.py
@@ -153,17 +153,15 @@ class JitCore(object):
         # Update jitcode mem range
         self.add_bloc_to_mem_interval(vm, cur_bloc)
 
-    def jit_call(self, label, cpu, vmmngr):
+    def jit_call(self, label, cpu, _vmmngr, breakpoints):
         """Call the function label with cpu and vmmngr states
         @label: function's label
         @cpu: JitCpu instance
-        @vm: VmMngr instance
+        @breakpoints: Dict instance of used breakpoints
         """
+        return self.exec_wrapper(label, cpu, self.lbl2jitbloc.data, breakpoints)
 
-        fc_ptr = self.lbl2jitbloc[label]
-        return self.exec_wrapper(fc_ptr, cpu)
-
-    def runbloc(self, cpu, vm, lbl):
+    def runbloc(self, cpu, vm, lbl, breakpoints):
         """Run the bloc starting at lbl.
         @cpu: JitCpu instance
         @vm: VmMngr instance
@@ -178,7 +176,7 @@ class JitCore(object):
             self.disbloc(lbl, cpu, vm)
 
         # Run the bloc and update cpu/vmmngr state
-        ret = self.jit_call(lbl, cpu, vm)
+        ret = self.jit_call(lbl, cpu, vm, breakpoints)
 
         return ret
 
diff --git a/miasm2/jitter/jitcore_python.py b/miasm2/jitter/jitcore_python.py
index 150e3906..bc284825 100644
--- a/miasm2/jitter/jitcore_python.py
+++ b/miasm2/jitter/jitcore_python.py
@@ -183,7 +183,7 @@ class JitCore_Python(jitcore.JitCore):
         # Associate myfunc with current label
         self.lbl2jitbloc[label.offset] = myfunc
 
-    def jit_call(self, label, cpu, vmmngr):
+    def jit_call(self, label, cpu, vmmngr, _breakpoints):
         """Call the function label with cpu and vmmngr states
         @label: function's label
         @cpu: JitCpu instance
diff --git a/miasm2/jitter/jitcore_tcc.py b/miasm2/jitter/jitcore_tcc.py
index 20f10339..304a5bca 100644
--- a/miasm2/jitter/jitcore_tcc.py
+++ b/miasm2/jitter/jitcore_tcc.py
@@ -138,7 +138,7 @@ class JitCore_Tcc(jitcore.JitCore):
 
     def jitirblocs(self, label, irblocs):
         f_name = "bloc_%s" % label.name
-        f_declaration = 'void %s(block_id * BlockDst, JitCpu* jitcpu)' % f_name
+        f_declaration = 'int %s(block_id * BlockDst, JitCpu* jitcpu)' % f_name
         out = irblocs2C(self.ir_arch, self.resolver, label, irblocs,
                         gen_exception_code=True,
                         log_mn=self.log_mn,
diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py
index 112920a1..7213d73c 100644
--- a/miasm2/jitter/jitload.py
+++ b/miasm2/jitter/jitload.py
@@ -137,11 +137,7 @@ class CallbackHandlerBitflag(CallbackHandler):
 
     "Handle a list of callback with conditions on bitflag"
 
-    # Overrides CallbackHandler's implem, but do not serve for optimization
-    def has_callbacks(self, bitflag):
-        return any(cb_mask & bitflag != 0 for cb_mask in self.callbacks)
-
-    def __call__(self, bitflag, *args):
+    def call_callbacks(self, bitflag, *args):
         """Call each callbacks associated with bit set in bitflag. While
         callbacks return True, continue with next callback.
         Iterator on other results"""
@@ -151,7 +147,8 @@ class CallbackHandlerBitflag(CallbackHandler):
 
             if b & bitflag != 0:
                 # If the flag matched
-                for res in self.call_callbacks(b, *args):
+                for res in super(CallbackHandlerBitflag,
+                                 self).call_callbacks(b, *args):
                     if res is not True:
                         yield res
 
@@ -292,7 +289,7 @@ class jitter:
         """Wrapper on JiT backend. Run the code at PC and return the next PC.
         @pc: address of code to run"""
 
-        return self.jit.runbloc(self.cpu, self.vm, pc)
+        return self.jit.runbloc(self.cpu, self.vm, pc, self.breakpoints_handler.callbacks)
 
     def runiter_once(self, pc):
         """Iterator on callbacks results on code running from PC.
@@ -308,10 +305,9 @@ class jitter:
 
         # Check breakpoints
         old_pc = self.pc
-        if self.breakpoints_handler.has_callbacks(self.pc):
-            for res in self.breakpoints_handler(self.pc, self):
-                if res is not True:
-                    yield res
+        for res in self.breakpoints_handler.call_callbacks(self.pc, self):
+            if res is not True:
+                yield res
 
         # If a callback changed pc, re call every callback
         if old_pc != self.pc: