diff options
| -rw-r--r-- | miasm2/core/utils.py | 5 | ||||
| -rw-r--r-- | miasm2/ir/ir2C.py | 24 | ||||
| -rw-r--r-- | miasm2/jitter/JitCore.h | 3 | ||||
| -rw-r--r-- | miasm2/jitter/Jittcc.c | 50 | ||||
| -rw-r--r-- | miasm2/jitter/jitcore.py | 12 | ||||
| -rw-r--r-- | miasm2/jitter/jitcore_python.py | 2 | ||||
| -rw-r--r-- | miasm2/jitter/jitcore_tcc.py | 2 | ||||
| -rw-r--r-- | miasm2/jitter/jitload.py | 18 |
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: |