diff options
Diffstat (limited to 'miasm2/jitter')
29 files changed, 614 insertions, 513 deletions
diff --git a/miasm2/jitter/JitCore.c b/miasm2/jitter/JitCore.c index 84f835f1..496ec8e1 100644 --- a/miasm2/jitter/JitCore.c +++ b/miasm2/jitter/JitCore.c @@ -74,6 +74,11 @@ 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) +{ + return vm_MEM_LOOKUP_128(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr); +} + void __attribute__((weak)) MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) { vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); @@ -94,8 +99,10 @@ 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) +{ + vm_MEM_WRITE_128(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); +} PyObject* __attribute__((weak)) vm_get_mem(JitCpu *self, PyObject* args) { diff --git a/miasm2/jitter/JitCore.h b/miasm2/jitter/JitCore.h index f599d6ea..c703178d 100644 --- a/miasm2/jitter/JitCore.h +++ b/miasm2/jitter/JitCore.h @@ -4,6 +4,7 @@ #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)){ \ @@ -30,6 +31,23 @@ } \ +#define getset_reg_u128(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); \ + } \ + 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; \ + return 0; \ + } #define getset_reg_u64(regname) \ static PyObject *JitCpu_get_ ## regname (JitCpu *self, void *closure) \ @@ -122,10 +140,12 @@ 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); 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); PyObject* vm_get_mem(JitCpu *self, PyObject* args); diff --git a/miasm2/jitter/Jitgcc.c b/miasm2/jitter/Jitgcc.c index 79274f24..329b7db4 100644 --- a/miasm2/jitter/Jitgcc.c +++ b/miasm2/jitter/Jitgcc.c @@ -10,13 +10,13 @@ typedef struct { typedef int (*jitted_func)(block_id*, PyObject*); -PyObject* gcc_exec_bloc(PyObject* self, PyObject* args) +PyObject* gcc_exec_block(PyObject* self, PyObject* args) { jitted_func func; PyObject* jitcpu; PyObject* func_py; PyObject* lbl2ptr; - PyObject* breakpoints; + PyObject* stop_offsets; PyObject* retaddr = NULL; int status; block_id BlockDst; @@ -26,7 +26,7 @@ PyObject* gcc_exec_bloc(PyObject* self, PyObject* args) if (!PyArg_ParseTuple(args, "OOOO|K", - &retaddr, &jitcpu, &lbl2ptr, &breakpoints, + &retaddr, &jitcpu, &lbl2ptr, &stop_offsets, &max_exec_per_call)) return NULL; @@ -73,8 +73,8 @@ PyObject* gcc_exec_bloc(PyObject* self, PyObject* args) if (status) return retaddr; - // Check breakpoint - if (PyDict_Contains(breakpoints, retaddr)) + // Check stop offsets + if (PySet_Contains(stop_offsets, retaddr)) return retaddr; } } @@ -85,8 +85,8 @@ static PyObject *GccError; static PyMethodDef GccMethods[] = { - {"gcc_exec_bloc", gcc_exec_bloc, METH_VARARGS, - "gcc exec bloc"}, + {"gcc_exec_block", gcc_exec_block, METH_VARARGS, + "gcc exec block"}, {NULL, NULL, 0, NULL} /* Sentinel */ }; diff --git a/miasm2/jitter/Jitllvm.c b/miasm2/jitter/Jitllvm.c index b46f88e3..6ecbd483 100644 --- a/miasm2/jitter/Jitllvm.c +++ b/miasm2/jitter/Jitllvm.c @@ -10,7 +10,7 @@ // Needed to get the JitCpu.cpu offset, arch independent #include "arch/JitCore_x86.h" -PyObject* llvm_exec_bloc(PyObject* self, PyObject* args) +PyObject* llvm_exec_block(PyObject* self, PyObject* args) { uint64_t (*func)(void*, void*, void*, uint8_t*); vm_cpu_t* cpu; @@ -20,14 +20,14 @@ PyObject* llvm_exec_bloc(PyObject* self, PyObject* args) uint8_t status; PyObject* func_py; PyObject* lbl2ptr; - PyObject* breakpoints; + PyObject* stop_offsets; PyObject* retaddr = NULL; uint64_t max_exec_per_call = 0; uint64_t cpt; int do_cpt; if (!PyArg_ParseTuple(args, "OOOO|K", - &retaddr, &jitcpu, &lbl2ptr, &breakpoints, + &retaddr, &jitcpu, &lbl2ptr, &stop_offsets, &max_exec_per_call)) return NULL; @@ -68,16 +68,16 @@ PyObject* llvm_exec_bloc(PyObject* self, PyObject* args) if (status) return retaddr; - // Check breakpoint - if (PyDict_Contains(breakpoints, retaddr)) + // Check stop offsets + if (PySet_Contains(stop_offsets, retaddr)) return retaddr; } } static PyMethodDef LLVMMethods[] = { - {"llvm_exec_bloc", llvm_exec_bloc, METH_VARARGS, - "llvm exec bloc"}, + {"llvm_exec_block", llvm_exec_block, METH_VARARGS, + "llvm exec block"}, {NULL, NULL, 0, NULL} /* Sentinel */ }; diff --git a/miasm2/jitter/arch/JitCore_aarch64.c b/miasm2/jitter/arch/JitCore_aarch64.c index 0224bfe2..a8502ef9 100644 --- a/miasm2/jitter/arch/JitCore_aarch64.c +++ b/miasm2/jitter/arch/JitCore_aarch64.c @@ -284,25 +284,6 @@ PyObject* vm_set_mem(JitCpu *self, PyObject* args) return Py_None; } - -UDIV(16) -UDIV(32) -UDIV(64) - -UMOD(16) -UMOD(32) -UMOD(64) - - -IDIV(16) -IDIV(32) -IDIV(64) - -IMOD(16) -IMOD(32) -IMOD(64) - - static PyMemberDef JitCpu_members[] = { {NULL} /* Sentinel */ }; diff --git a/miasm2/jitter/arch/JitCore_aarch64.h b/miasm2/jitter/arch/JitCore_aarch64.h index c7fc3cea..fa50513f 100644 --- a/miasm2/jitter/arch/JitCore_aarch64.h +++ b/miasm2/jitter/arch/JitCore_aarch64.h @@ -49,19 +49,4 @@ typedef struct { void dump_gpregs(vm_cpu_t* vmcpu); -uint64_t udiv64(vm_cpu_t* vmcpu, uint64_t a, uint64_t b); -uint64_t umod64(vm_cpu_t* vmcpu, uint64_t a, uint64_t b); -int64_t idiv64(vm_cpu_t* vmcpu, int64_t a, int64_t b); -int64_t imod64(vm_cpu_t* vmcpu, int64_t a, int64_t b); - -uint32_t udiv32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b); -uint32_t umod32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b); -int32_t idiv32(vm_cpu_t* vmcpu, int32_t a, int32_t b); -int32_t imod32(vm_cpu_t* vmcpu, int32_t a, int32_t b); - -uint16_t udiv16(vm_cpu_t* vmcpu, uint16_t a, uint16_t b); -uint16_t umod16(vm_cpu_t* vmcpu, uint16_t a, uint16_t b); -int16_t idiv16(vm_cpu_t* vmcpu, int16_t a, int16_t b); -int16_t imod16(vm_cpu_t* vmcpu, int16_t a, int16_t b); - #define RETURN_PC return BlockDst; diff --git a/miasm2/jitter/arch/JitCore_arm.c b/miasm2/jitter/arch/JitCore_arm.c index 60b8f95b..8a09ba6c 100644 --- a/miasm2/jitter/arch/JitCore_arm.c +++ b/miasm2/jitter/arch/JitCore_arm.c @@ -187,16 +187,6 @@ void check_automod(JitCpu* jitcpu, uint64_t addr, uint64_t size) } - -UDIV(32) - -UMOD(32) - -IDIV(32) - -IMOD(32) - - void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) { vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); @@ -221,22 +211,6 @@ void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src) check_automod(jitcpu, addr, 64); } - -uint32_t clz(uint32_t arg) -{ - - int i; - - for (i=0; i<32; i++) { - if (arg & (1ull << (31-i))) - break; - } - return i; -} - - - - PyObject* vm_set_mem(JitCpu *self, PyObject* args) { PyObject *py_addr; diff --git a/miasm2/jitter/arch/JitCore_arm.h b/miasm2/jitter/arch/JitCore_arm.h index 445ac44a..1f3ccaf2 100644 --- a/miasm2/jitter/arch/JitCore_arm.h +++ b/miasm2/jitter/arch/JitCore_arm.h @@ -38,13 +38,4 @@ typedef struct { void dump_gpregs(vm_cpu_t* vmcpu); - -uint32_t udiv32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b); -uint32_t umod32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b); -int32_t idiv32(vm_cpu_t* vmcpu, int32_t a, int32_t b); -int32_t imod32(vm_cpu_t* vmcpu, int32_t a, int32_t b); - - #define RETURN_PC return BlockDst; - -uint32_t clz(uint32_t arg); diff --git a/miasm2/jitter/arch/JitCore_mips32.c b/miasm2/jitter/arch/JitCore_mips32.c index 2142e8cc..4ebfbec8 100644 --- a/miasm2/jitter/arch/JitCore_mips32.c +++ b/miasm2/jitter/arch/JitCore_mips32.c @@ -222,25 +222,6 @@ void check_automod(JitCpu* jitcpu, uint64_t addr, uint64_t size) } -UDIV(16) -UDIV(32) -UDIV(64) - -UMOD(16) -UMOD(32) -UMOD(64) - - -IDIV(16) -IDIV(32) -IDIV(64) - -IMOD(16) -IMOD(32) -IMOD(64) - - - void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) { vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); diff --git a/miasm2/jitter/arch/JitCore_mips32.h b/miasm2/jitter/arch/JitCore_mips32.h index b45cac2b..ff2045d7 100644 --- a/miasm2/jitter/arch/JitCore_mips32.h +++ b/miasm2/jitter/arch/JitCore_mips32.h @@ -335,19 +335,4 @@ typedef struct { void dump_gpregs(vm_cpu_t* vmcpu); -uint64_t udiv64(vm_cpu_t* vmcpu, uint64_t a, uint64_t b); -uint64_t umod64(vm_cpu_t* vmcpu, uint64_t a, uint64_t b); -int64_t idiv64(vm_cpu_t* vmcpu, int64_t a, int64_t b); -int64_t imod64(vm_cpu_t* vmcpu, int64_t a, int64_t b); - -uint32_t udiv32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b); -uint32_t umod32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b); -int32_t idiv32(vm_cpu_t* vmcpu, int32_t a, int32_t b); -int32_t imod32(vm_cpu_t* vmcpu, int32_t a, int32_t b); - -uint16_t udiv16(vm_cpu_t* vmcpu, uint16_t a, uint16_t b); -uint16_t umod16(vm_cpu_t* vmcpu, uint16_t a, uint16_t b); -int16_t idiv16(vm_cpu_t* vmcpu, int16_t a, int16_t b); -int16_t imod16(vm_cpu_t* vmcpu, int16_t a, int16_t b); - #define RETURN_PC return BlockDst; diff --git a/miasm2/jitter/arch/JitCore_msp430.h b/miasm2/jitter/arch/JitCore_msp430.h index cad028a9..3934d37a 100644 --- a/miasm2/jitter/arch/JitCore_msp430.h +++ b/miasm2/jitter/arch/JitCore_msp430.h @@ -36,16 +36,4 @@ typedef struct { #define RETURN_PC return BlockDst; -uint16_t bcdadd_16(uint16_t a, uint16_t b); - -uint16_t bcdadd_cf_16(uint16_t a, uint16_t b); - -uint16_t hex2bcd_16(uint16_t a); - -uint8_t hex2bcd_8(uint8_t a); - -uint8_t bcd2hex_8(uint8_t a); - -uint16_t bcd2hex_16(uint16_t a); - void dump_gpregs(vm_cpu_t* vmcpu); diff --git a/miasm2/jitter/arch/JitCore_ppc32.c b/miasm2/jitter/arch/JitCore_ppc32.c index 7ea5e88f..616e7cfd 100644 --- a/miasm2/jitter/arch/JitCore_ppc32.c +++ b/miasm2/jitter/arch/JitCore_ppc32.c @@ -246,38 +246,6 @@ get_gpreg_offset_all(void) { return dict; } -int32_t -idiv32(struct vm_cpu *cpu, int32_t a, int32_t b) { - if (b == 0) - return 0; - - return a / b; -} - -uint32_t -udiv32(struct vm_cpu *cpu, uint32_t a, uint32_t b) { - if (b == 0) - return 0; - - return a / b; -} - -int32_t -imod32(struct vm_cpu *cpu, int32_t a, int32_t b) { - if (b == 0) - return 0; - - return a % b; -} - -uint32_t -umod32(struct vm_cpu *cpu, uint32_t a, uint32_t b) { - if (b == 0) - return 0; - - return a % b; -} - static PyGetSetDef JitCpu_getseters[] = { {"vmmngr", (getter)JitCpu_get_vmmngr, (setter)JitCpu_set_vmmngr, diff --git a/miasm2/jitter/arch/JitCore_ppc32.h b/miasm2/jitter/arch/JitCore_ppc32.h index 18cee358..5a048190 100644 --- a/miasm2/jitter/arch/JitCore_ppc32.h +++ b/miasm2/jitter/arch/JitCore_ppc32.h @@ -14,11 +14,6 @@ struct vm_cpu { uint32_t reserve_address; }; -int32_t idiv32(struct vm_cpu *, int32_t, int32_t); -uint32_t udiv32(struct vm_cpu *, uint32_t, uint32_t); -int32_t imod32(struct vm_cpu *, int32_t, int32_t); -uint32_t umod32(struct vm_cpu *, uint32_t, uint32_t); - void dump_gpregs(struct vm_cpu *); typedef struct vm_cpu vm_cpu_t; diff --git a/miasm2/jitter/arch/JitCore_x86.c b/miasm2/jitter/arch/JitCore_x86.c index e1e36989..eda6e6e5 100644 --- a/miasm2/jitter/arch/JitCore_x86.c +++ b/miasm2/jitter/arch/JitCore_x86.c @@ -55,6 +55,23 @@ reg_dict gpreg_dict[] = { {.name = "RAX", .offset = offsetof(vm_cpu_t, RAX)}, {.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)}, @@ -120,6 +137,23 @@ 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(tsc1); get_reg(tsc2); @@ -330,24 +364,6 @@ uint64_t segm2addr(JitCpu* jitcpu, uint64_t segm, uint64_t addr) return addr + ((vm_cpu_t*)jitcpu->cpu)->segm_base[segm]; } - -UDIV(16) -UDIV(32) -UDIV(64) - -UMOD(16) -UMOD(32) -UMOD(64) - - -IDIV(16) -IDIV(32) -IDIV(64) - -IMOD(16) -IMOD(32) -IMOD(64) - void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) { vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); @@ -544,6 +560,23 @@ 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_u32(tsc1); getset_reg_u32(tsc2); @@ -620,6 +653,23 @@ PyObject* get_gpreg_offset_all(void) get_reg_off(MM6); get_reg_off(MM7); + get_reg_off(XMM0); + get_reg_off(XMM1); + get_reg_off(XMM2); + get_reg_off(XMM3); + get_reg_off(XMM4); + get_reg_off(XMM5); + get_reg_off(XMM6); + get_reg_off(XMM7); + get_reg_off(XMM8); + get_reg_off(XMM9); + get_reg_off(XMM10); + get_reg_off(XMM11); + get_reg_off(XMM12); + get_reg_off(XMM13); + get_reg_off(XMM14); + get_reg_off(XMM15); + get_reg_off(tsc1); get_reg_off(tsc2); @@ -708,6 +758,23 @@ static PyGetSetDef JitCpu_getseters[] = { {"MM6", (getter)JitCpu_get_MM6, (setter)JitCpu_set_MM6, "MM6", NULL}, {"MM7", (getter)JitCpu_get_MM7, (setter)JitCpu_set_MM7, "MM7", NULL}, + {"XMM0", (getter)JitCpu_get_XMM0, (setter)JitCpu_set_XMM0, "XMM0", NULL}, + {"XMM1", (getter)JitCpu_get_XMM1, (setter)JitCpu_set_XMM1, "XMM1", NULL}, + {"XMM2", (getter)JitCpu_get_XMM2, (setter)JitCpu_set_XMM2, "XMM2", NULL}, + {"XMM3", (getter)JitCpu_get_XMM3, (setter)JitCpu_set_XMM3, "XMM3", NULL}, + {"XMM4", (getter)JitCpu_get_XMM4, (setter)JitCpu_set_XMM4, "XMM4", NULL}, + {"XMM5", (getter)JitCpu_get_XMM5, (setter)JitCpu_set_XMM5, "XMM5", NULL}, + {"XMM6", (getter)JitCpu_get_XMM6, (setter)JitCpu_set_XMM6, "XMM6", NULL}, + {"XMM7", (getter)JitCpu_get_XMM7, (setter)JitCpu_set_XMM7, "XMM7", NULL}, + {"XMM8", (getter)JitCpu_get_XMM8, (setter)JitCpu_set_XMM8, "XMM8", NULL}, + {"XMM9", (getter)JitCpu_get_XMM9, (setter)JitCpu_set_XMM9, "XMM9", NULL}, + {"XMM10", (getter)JitCpu_get_XMM10, (setter)JitCpu_set_XMM10, "XMM10", NULL}, + {"XMM11", (getter)JitCpu_get_XMM11, (setter)JitCpu_set_XMM11, "XMM11", NULL}, + {"XMM12", (getter)JitCpu_get_XMM12, (setter)JitCpu_set_XMM12, "XMM12", NULL}, + {"XMM13", (getter)JitCpu_get_XMM13, (setter)JitCpu_set_XMM13, "XMM13", NULL}, + {"XMM14", (getter)JitCpu_get_XMM14, (setter)JitCpu_set_XMM14, "XMM14", NULL}, + {"XMM15", (getter)JitCpu_get_XMM15, (setter)JitCpu_set_XMM15, "XMM15", NULL}, + {"tsc1", (getter)JitCpu_get_tsc1, (setter)JitCpu_set_tsc1, "tsc1", NULL}, {"tsc2", (getter)JitCpu_get_tsc2, (setter)JitCpu_set_tsc2, "tsc2", NULL}, diff --git a/miasm2/jitter/arch/JitCore_x86.h b/miasm2/jitter/arch/JitCore_x86.h index e55948e6..221ba5db 100644 --- a/miasm2/jitter/arch/JitCore_x86.h +++ b/miasm2/jitter/arch/JitCore_x86.h @@ -1,3 +1,4 @@ +#define uint128_t __uint128_t typedef struct { uint32_t exception_flags; @@ -96,31 +97,30 @@ typedef struct { uint64_t MM6; 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; + uint32_t segm_base[0x10000]; }vm_cpu_t; - - - void dump_gpregs_32(vm_cpu_t* vmcpu); void dump_gpregs_64(vm_cpu_t* vmcpu); uint64_t segm2addr(JitCpu* jitcpu, uint64_t segm, uint64_t addr); - -uint64_t udiv64(vm_cpu_t* vmcpu, uint64_t a, uint64_t b); -uint64_t umod64(vm_cpu_t* vmcpu, uint64_t a, uint64_t b); -int64_t idiv64(vm_cpu_t* vmcpu, int64_t a, int64_t b); -int64_t imod64(vm_cpu_t* vmcpu, int64_t a, int64_t b); - -uint32_t udiv32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b); -uint32_t umod32(vm_cpu_t* vmcpu, uint32_t a, uint32_t b); -int32_t idiv32(vm_cpu_t* vmcpu, int32_t a, int32_t b); -int32_t imod32(vm_cpu_t* vmcpu, int32_t a, int32_t b); - -uint16_t udiv16(vm_cpu_t* vmcpu, uint16_t a, uint16_t b); -uint16_t umod16(vm_cpu_t* vmcpu, uint16_t a, uint16_t b); -int16_t idiv16(vm_cpu_t* vmcpu, int16_t a, int16_t b); -int16_t imod16(vm_cpu_t* vmcpu, int16_t a, int16_t b); - #define RETURN_PC return BlockDst; diff --git a/miasm2/jitter/codegen.py b/miasm2/jitter/codegen.py index 2c546be8..10140fd2 100644 --- a/miasm2/jitter/codegen.py +++ b/miasm2/jitter/codegen.py @@ -2,17 +2,18 @@ Module to generate C code for a given native @block """ -import miasm2.expression.expression as m2_expr +from miasm2.expression.expression import Expr, ExprId, ExprLoc, ExprInt, \ + ExprMem, ExprCond, LocKey from miasm2.ir.ir import IRBlock, AssignBlock -from miasm2.ir.translators import Translator -from miasm2.core.asmblock import expr_is_label, AsmBlockBad, AsmLabel -# Miasm to C translator -TRANSLATOR = Translator.to_language("C") +from miasm2.ir.translators.C import TranslatorC +from miasm2.core.asmblock import AsmBlockBad -SIZE_TO_MASK = {x: 2**x - 1 for x in (1, 2, 3, 7, 8, 16, 32, 64)} +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)} -MASK_INT = 0xffffffffffffffff class Attributes(object): @@ -101,26 +102,21 @@ class CGen(object): def __init__(self, ir_arch): self.ir_arch = ir_arch self.PC = self.ir_arch.pc + self.translator = TranslatorC(self.ir_arch.loc_db) self.init_arch_C() def init_arch_C(self): """Iinitialize jitter internals""" self.id_to_c_id = {} for reg in self.ir_arch.arch.regs.all_regs_ids: - self.id_to_c_id[reg] = m2_expr.ExprId('mycpu->%s' % reg, reg.size) + self.id_to_c_id[reg] = ExprId('mycpu->%s' % reg, reg.size) self.C_PC = self.id_to_c(self.PC) - @staticmethod - def label_to_jitlabel(lbl): - """Convert AsmLabel to a jitter label name""" - assert lbl.offset is not None - return "jitblock_%X" % lbl.offset - def dst_to_c(self, src): """Translate Expr @src into C code""" - if not isinstance(src, m2_expr.Expr): - src = m2_expr.ExprInt(src, self.PC.size) + if not isinstance(src, Expr): + src = ExprInt(src, self.PC.size) return self.id_to_c(src) def patch_c_id(self, expr): @@ -129,14 +125,14 @@ class CGen(object): def id_to_c(self, expr): """Translate Expr @expr into corresponding C code""" - return TRANSLATOR.from_expr(self.patch_c_id(expr)) + return self.translator.from_expr(self.patch_c_id(expr)) - def add_label_index(self, dst2index, lbl): + def add_label_index(self, dst2index, loc_key): """Insert @lbl to the dictionnary @dst2index with a uniq value - @dst2index: AsmLabel -> uniq value - @lbl: AsmLabel istance""" + @dst2index: LocKey -> uniq value + @loc_key: LocKey istance""" - dst2index[lbl] = len(dst2index) + dst2index[loc_key] = len(dst2index) def assignblk_to_irbloc(self, instr, assignblk): """ @@ -147,10 +143,11 @@ class CGen(object): new_assignblk = dict(assignblk) if self.ir_arch.IRDst not in assignblk: offset = instr.offset + instr.l - dst = m2_expr.ExprInt(offset, self.ir_arch.IRDst.size) + loc_key = self.ir_arch.loc_db.get_or_create_offset_location(offset) + dst = ExprLoc(loc_key, self.ir_arch.IRDst.size) new_assignblk[self.ir_arch.IRDst] = dst irs = [AssignBlock(new_assignblk, instr)] - return IRBlock(self.ir_arch.get_instr_label(instr), irs) + return IRBlock(self.ir_arch.get_loc_key_for_instr(instr), irs) def block2assignblks(self, block): """ @@ -168,6 +165,7 @@ class CGen(object): for irblock in irblocks: assert irblock.dst is not None irblocks_list.append(irblocks) + return irblocks_list def add_local_var(self, dst_var, dst_index, expr): @@ -183,7 +181,7 @@ class CGen(object): if size not in dst_index: raise RuntimeError("Unsupported operand size %s", size) var_num = dst_index[size] - dst = m2_expr.ExprId("var_%.2d_%.2d" % (size, var_num), size) + dst = ExprId("var_%.2d_%.2d" % (size, var_num), size) dst_index[size] += 1 dst_var[expr] = dst return dst @@ -199,12 +197,13 @@ class CGen(object): # Prefetch memory read for expr in assignblk.get_r(mem_read=True): - if not isinstance(expr, m2_expr.ExprMem): + if not isinstance(expr, ExprMem): continue var_num = mem_index[expr.size] mem_index[expr.size] += 1 - var = m2_expr.ExprId( - "prefetch_%.2d_%.2d" % (expr.size, var_num), expr.size) + var = ExprId( + "prefetch_%.2d_%.2d" % (expr.size, var_num), expr.size + ) mem_var[expr] = var # Generate memory prefetch @@ -236,9 +235,9 @@ class CGen(object): for dst, src in sorted(assignblk.iteritems()): src = src.replace_expr(prefetchers) - if dst is self.ir_arch.IRDst: + if dst == self.ir_arch.IRDst: pass - elif isinstance(dst, m2_expr.ExprId): + elif isinstance(dst, ExprId): new_dst = self.add_local_var(dst_var, dst_index, dst) if dst in self.ir_arch.arch.regs.regs_flt_expr: # Dont mask float affectation @@ -246,19 +245,19 @@ class CGen(object): '%s = (%s);' % (self.id_to_c(new_dst), self.id_to_c(src))) else: c_main.append( - '%s = (%s)&0x%X;' % (self.id_to_c(new_dst), - self.id_to_c(src), - SIZE_TO_MASK[src.size])) - elif isinstance(dst, m2_expr.ExprMem): + '%s = (%s)&%s;' % (self.id_to_c(new_dst), + self.id_to_c(src), + SIZE_TO_MASK[src.size])) + elif isinstance(dst, ExprMem): ptr = dst.arg.replace_expr(prefetchers) - new_dst = m2_expr.ExprMem(ptr, dst.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: raise ValueError("Unknown dst") for dst, new_dst in dst_var.iteritems(): - if dst is self.ir_arch.IRDst: + 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)) @@ -283,25 +282,25 @@ class CGen(object): @dst2index: dictionnary to link label to its index """ - if isinstance(expr, m2_expr.ExprCond): + 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) return ("((%s)?(%s):(%s))" % (cond, src1, src2), "((%s)?(%s):(%s))" % (cond, src1b, src2b)) - if isinstance(expr, m2_expr.ExprInt): + if isinstance(expr, ExprInt): offset = int(expr) - self.add_label_index(dst2index, offset) - return ("%s" % dst2index[offset], hex(offset)) - if 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)) - self.add_label_index(dst2index, label) - return ("%s" % dst2index[label], "0") - + 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)) + 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)) + self.add_label_index(dst2index, loc_key) + return ("%s" % dst2index[loc_key], "0") dst2index[expr] = -1 return ("-1", self.id_to_c(expr)) @@ -337,8 +336,12 @@ class CGen(object): out = [] if instr_attrib.log_mn: - out.append('printf("%.8X %s\\n");' % (instr_attrib.instr.offset, - instr_attrib.instr)) + out.append( + 'printf("%.8X %s\\n");' % ( + instr_attrib.instr.offset, + instr_attrib.instr.to_string(self.ir_arch.loc_db) + ) + ) return out def gen_post_code(self, attrib): @@ -354,24 +357,27 @@ class CGen(object): @attrib: instruction Attributes @instr_offsets: instructions offsets list @dst: potential instruction destination""" - if isinstance(dst, AsmLabel) and dst.offset is None: - # Generate goto for local labels - return ['goto %s;' % dst.name] - offset = None - if isinstance(dst, AsmLabel) and dst.offset is not None: - offset = dst.offset - elif isinstance(dst, (int, long)): - offset = dst + out = [] - if (offset is not None and - offset > attrib.instr.offset and + if isinstance(dst, Expr): + out += self.gen_post_code(attrib) + out.append('BlockDst->address = DST_value;') + out += self.gen_post_instr_checks(attrib) + out.append('\t\treturn JIT_RET_NO_EXCEPTION;') + return out + + assert isinstance(dst, LocKey) + offset = self.ir_arch.loc_db.get_location_offset(dst) + if offset is None: + # Generate goto for local labels + return ['goto %s;' % dst] + if (offset > attrib.instr.offset and offset in instr_offsets): # Only generate goto for next instructions. # (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) - out.append('goto %s;' % self.label_to_jitlabel(lbl)) + out.append('goto %s;' % dst) else: out += self.gen_post_code(attrib) out.append('BlockDst->address = DST_value;') @@ -467,10 +473,10 @@ class CGen(object): element_read = assignblk.get_r(mem_read=True) # Check mem read - attrib.mem_read = any(isinstance(expr, m2_expr.ExprMem) + attrib.mem_read = any(isinstance(expr, ExprMem) for expr in element_read) # Check mem write - attrib.mem_write = any(isinstance(dst, m2_expr.ExprMem) + attrib.mem_write = any(isinstance(dst, ExprMem) for dst in assignblk) def get_attributes(self, instr, irblocks, log_mn=False, log_regs=False): @@ -512,7 +518,7 @@ class CGen(object): last_instr = block.lines[-1] offset = last_instr.offset + last_instr.l - return self.ir_arch.symbol_pool.getby_offset_create(offset) + return self.ir_arch.loc_db.get_or_create_offset_location(offset) def gen_init(self, block): """ @@ -521,9 +527,11 @@ 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 % self.label_to_jitlabel(lbl_start)).split("\n"), instr_offsets + post_label = self.get_block_post_label(block) + post_offset = self.ir_arch.loc_db.get_location_offset(post_label) + instr_offsets.append(post_offset) + lbl_start = block.loc_key + return (self.CODE_INIT % lbl_start).split("\n"), instr_offsets def gen_irblock(self, instr_attrib, attributes, instr_offsets, irblock): """ @@ -555,9 +563,10 @@ class CGen(object): 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 % (self.label_to_jitlabel(lbl), self.C_PC, dst, dst) + loc_key = self.get_block_post_label(block) + offset = self.ir_arch.loc_db.get_location_offset(loc_key) + dst = self.dst_to_c(offset) + code = self.CODE_RETURN_NO_EXCEPTION % (loc_key, self.C_PC, dst, dst) return code.split('\n') def gen_c(self, block, log_mn=False, log_regs=False): @@ -570,23 +579,19 @@ class CGen(object): if isinstance(block, AsmBlockBad): return self.gen_bad_block() irblocks_list = self.block2assignblks(block) - out, instr_offsets = self.gen_init(block) assert len(block.lines) == len(irblocks_list) for instr, irblocks in zip(block.lines, irblocks_list): instr_attrib, irblocks_attributes = self.get_attributes(instr, irblocks, log_mn, log_regs) - for index, irblock in enumerate(irblocks): new_irblock = self.ir_arch.irbloc_fix_regs_for_mode(irblock, self.ir_arch.attrib) - if new_irblock.label.offset is None: - out.append("%-40s // %.16X %s" % - (str(new_irblock.label.name) + ":", instr.offset, instr)) - else: - out.append("%-40s // %.16X %s" % - (self.label_to_jitlabel(new_irblock.label) + ":", instr.offset, instr)) + label = str(new_irblock.loc_key) + out.append("%-40s // %.16X %s" % + (label + ":", instr.offset, instr)) if index == 0: out += self.gen_pre_code(instr_attrib) out += self.gen_irblock(instr_attrib, irblocks_attributes[index], instr_offsets, new_irblock) out += self.gen_finalize(block) + return ['\t' + line for line in out] diff --git a/miasm2/jitter/jitcore.py b/miasm2/jitter/jitcore.py index f2b1375d..fc5cf35e 100644 --- a/miasm2/jitter/jitcore.py +++ b/miasm2/jitter/jitcore.py @@ -16,66 +16,69 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # from hashlib import md5 +import warnings -from miasm2.core import asmblock +from miasm2.core.asmblock import disasmEngine, AsmBlockBad from miasm2.core.interval import interval from miasm2.core.utils import BoundedDict +from miasm2.expression.expression import LocKey from miasm2.jitter.csts import * - class JitCore(object): "JiT management. This is an abstract class" + # Jitted function's name + FUNCNAME = "block_entry" + jitted_block_delete_cb = None jitted_block_max_size = 10000 - def __init__(self, ir_arch, bs=None): + def __init__(self, ir_arch, bin_stream): """Initialise a JitCore instance. @ir_arch: ir instance for current architecture - @bs: bitstream + @bin_stream: bin_stream instance """ - + # Arch related self.ir_arch = ir_arch + self.ircfg = self.ir_arch.new_ircfg() self.arch_name = "%s%s" % (self.ir_arch.arch.name, self.ir_arch.attrib) - self.bs = bs - self.known_blocs = {} - self.lbl2jitbloc = BoundedDict(self.jitted_block_max_size, + + # Structures for block tracking + self.offset_to_jitted_func = BoundedDict(self.jitted_block_max_size, delete_cb=self.jitted_block_delete_cb) - self.lbl2bloc = {} + self.loc_key_to_block = {} + self.blocks_mem_interval = interval() + + # Logging & options self.log_mn = False self.log_regs = False self.log_newbloc = False - self.segm_to_do = set() - self.jitcount = 0 - self.addr2obj = {} - self.addr2objref = {} - self.blocs_mem_interval = interval() - self.disasm_cb = None - self.split_dis = set() self.options = {"jit_maxline": 50, # Maximum number of line jitted "max_exec_per_call": 0 # 0 means no limit } - self.mdis = asmblock.disasmEngine(ir_arch.arch, ir_arch.attrib, bs, - lines_wd=self.options["jit_maxline"], - symbol_pool=ir_arch.symbol_pool, - follow_call=False, - dontdis_retcall=False, - split_dis=self.split_dis, - dis_block_callback=self.disasm_cb) + # Disassembly Engine + self.split_dis = set() + self.mdis = disasmEngine( + ir_arch.arch, ir_arch.attrib, bin_stream, + lines_wd=self.options["jit_maxline"], + loc_db=ir_arch.loc_db, + follow_call=False, + dontdis_retcall=False, + split_dis=self.split_dis, + ) def set_options(self, **kwargs): "Set options relative to the backend" - self.options.update(kwargs) def clear_jitted_blocks(self): "Reset all jitted blocks" - self.lbl2jitbloc.clear() - self.lbl2bloc.clear() - self.blocs_mem_interval = interval() + self.offset_to_jitted_func.clear() + self.loc_key_to_block.clear() + self.blocks_mem_interval = interval() def add_disassembly_splits(self, *args): """The disassembly engine will stop on address in args if they @@ -90,7 +93,7 @@ class JitCore(object): "Initialise the Jitter" raise NotImplementedError("Abstract class") - def get_bloc_min_max(self, cur_block): + def set_block_min_max(self, cur_block): "Update cur_block to set min/max address" if cur_block.lines: @@ -98,94 +101,107 @@ class JitCore(object): cur_block.ad_max = cur_block.lines[-1].offset + cur_block.lines[-1].l else: # 1 byte block for unknown mnemonic - cur_block.ad_min = cur_block.label.offset - cur_block.ad_max = cur_block.label.offset+1 + offset = ir_arch.loc_db.get_location_offset(cur_block.loc_key) + cur_block.ad_min = offset + cur_block.ad_max = offset+1 - def add_bloc_to_mem_interval(self, vm, block): + def add_block_to_mem_interval(self, vm, block): "Update vm to include block addresses in its memory range" - - self.blocs_mem_interval += interval([(block.ad_min, block.ad_max - 1)]) + self.blocks_mem_interval += interval([(block.ad_min, block.ad_max - 1)]) vm.reset_code_bloc_pool() - for a, b in self.blocs_mem_interval: + for a, b in self.blocks_mem_interval: vm.add_code_bloc(a, b + 1) - def jitirblocs(self, label, irblocks): + def jit_irblocks(self, label, irblocks): """JiT a group of irblocks. @label: the label of the irblocks - @irblocks: a gorup of irblocks + @irblocks: a group of irblocks """ raise NotImplementedError("Abstract class") - def add_bloc(self, block): + def add_block(self, block): """Add a block to JiT and JiT it. @block: asm_bloc to add """ - - irblocks = self.ir_arch.add_block(block, gen_pc_updt = True) + irblocks = self.ir_arch.add_asmblock_to_ircfg(block, self.ircfg, gen_pc_updt = True) block.blocks = irblocks - self.jitirblocs(block.label, irblocks) + self.jit_irblocks(block.loc_key, irblocks) - def disbloc(self, addr, vm): + def disasm_and_jit_block(self, addr, vm): """Disassemble a new block and JiT it - @addr: address of the block to disassemble (AsmLabel or int) + @addr: address of the block to disassemble (LocKey or int) @vm: VmMngr instance """ # Get the block - if isinstance(addr, asmblock.AsmLabel): - addr = addr.offset + if isinstance(addr, LocKey): + addr = self.ir_arch.loc_db.get_location_offset(addr) + if addr is None: + raise RuntimeError("Unknown offset for LocKey") # Prepare disassembler self.mdis.lines_wd = self.options["jit_maxline"] - self.mdis.dis_block_callback = self.disasm_cb # Disassemble it - try: - cur_block = self.mdis.dis_block(addr) - except IOError: - # vm_exception_flag is set - label = self.ir_arch.symbol_pool.getby_offset_create(addr) - cur_block = asmblock.AsmBlockBad(label) - + cur_block = self.mdis.dis_block(addr) + if isinstance(cur_block, AsmBlockBad): + return cur_block # Logging if self.log_newbloc: - print cur_block + print cur_block.to_string(self.mdis.loc_db) # Update label -> block - self.lbl2bloc[cur_block.label] = cur_block + self.loc_key_to_block[cur_block.loc_key] = cur_block # Store min/max block address needed in jit automod code - self.get_bloc_min_max(cur_block) + self.set_block_min_max(cur_block) # JiT it - self.add_bloc(cur_block) + self.add_block(cur_block) # Update jitcode mem range - self.add_bloc_to_mem_interval(vm, cur_block) - - def runbloc(self, cpu, lbl, breakpoints): - """Run the block starting at lbl. + self.add_block_to_mem_interval(vm, cur_block) + return cur_block + + def run_at(self, cpu, offset, stop_offsets): + """Run from the starting address @offset. + Execution will stop if: + - max_exec_per_call option is reached + - a new, yet unknown, block is reached after the execution of block at + address @offset + - an address in @stop_offsets is reached @cpu: JitCpu instance - @lbl: target label + @offset: starting address (int) + @stop_offsets: set of address on which the jitter must stop """ - if lbl is None: - lbl = getattr(cpu, self.ir_arch.pc.name) + if offset is None: + offset = getattr(cpu, self.ir_arch.pc.name) - if not lbl in self.lbl2jitbloc: + if offset not in self.offset_to_jitted_func: # Need to JiT the block - self.disbloc(lbl, cpu.vmmngr) + cur_block = self.disasm_and_jit_block(offset, cpu.vmmngr) + if isinstance(cur_block, AsmBlockBad): + errno = cur_block.errno + if errno == AsmBlockBad.ERROR_IO: + cpu.vmmngr.set_exception(EXCEPT_ACCESS_VIOL) + elif errno == AsmBlockBad.ERROR_CANNOT_DISASM: + cpu.set_exception(EXCEPT_UNK_MNEMO) + else: + raise RuntimeError("Unhandled disasm result %r" % errno) + return offset # Run the block and update cpu/vmmngr state - return self.exec_wrapper(lbl, cpu, self.lbl2jitbloc.data, breakpoints, + return self.exec_wrapper(offset, cpu, self.offset_to_jitted_func.data, + stop_offsets, self.options["max_exec_per_call"]) - def blocs2memrange(self, blocks): + def blocks_to_memrange(self, blocks): """Return an interval instance standing for blocks addresses - @blocks: list of asm_bloc instances + @blocks: list of AsmBlock instances """ mem_range = interval() @@ -204,10 +220,10 @@ class JitCore(object): vm.reset_code_bloc_pool() # Add blocks in the pool - for start, stop in self.blocs_mem_interval: + for start, stop in self.blocks_mem_interval: vm.add_code_bloc(start, stop + 1) - def del_bloc_in_range(self, ad1, ad2): + def del_block_in_range(self, ad1, ad2): """Find and remove jitted block in range [ad1, ad2]. Return the list of block removed. @ad1: First address @@ -216,7 +232,7 @@ class JitCore(object): # Find concerned blocks modified_blocks = set() - for block in self.lbl2bloc.values(): + for block in self.loc_key_to_block.values(): if not block.lines: continue if block.ad_max <= ad1 or block.ad_min >= ad2: @@ -227,26 +243,28 @@ class JitCore(object): modified_blocks.add(block) # Generate interval to delete - del_interval = self.blocs2memrange(modified_blocks) + del_interval = self.blocks_to_memrange(modified_blocks) # Remove interval from monitored interval list - self.blocs_mem_interval -= del_interval + self.blocks_mem_interval -= del_interval # Remove modified blocks for block in modified_blocks: try: for irblock in block.blocks: # Remove offset -> jitted block link - if irblock.label.offset in self.lbl2jitbloc: - del(self.lbl2jitbloc[irblock.label.offset]) + offset = self.ir_arch.loc_db.get_location_offset(irblock.loc_key) + if offset in self.offset_to_jitted_func: + del(self.offset_to_jitted_func[offset]) except AttributeError: # The block has never been translated in IR - if block.label.offset in self.lbl2jitbloc: - del(self.lbl2jitbloc[block.label.offset]) + offset = self.ir_arch.loc_db.get_location_offset(block.loc_key) + if offset in self.offset_to_jitted_func: + del(self.offset_to_jitted_func[offset]) # Remove label -> block link - del(self.lbl2bloc[block.label]) + del(self.loc_key_to_block[block.loc_key]) return modified_blocks @@ -256,7 +274,7 @@ class JitCore(object): @mem_range: list of start/stop addresses """ for addr_start, addr_stop in mem_range: - self.del_bloc_in_range(addr_start, addr_stop) + self.del_block_in_range(addr_start, addr_stop) self.__updt_jitcode_mem_range(vm) vm.reset_memory_access() @@ -275,9 +293,20 @@ class JitCore(object): @block: asmblock """ block_raw = "".join(line.b for line in block.lines) - block_hash = md5("%X_%s_%s_%s_%s" % (block.label.offset, + offset = self.ir_arch.loc_db.get_location_offset(block.loc_key) + block_hash = md5("%X_%s_%s_%s_%s" % (offset, self.arch_name, self.log_mn, self.log_regs, block_raw)).hexdigest() return block_hash + + @property + def disasm_cb(self): + warnings.warn("Deprecated API: use .mdis.dis_block_callback") + return self.mdis.dis_block_callback + + @disasm_cb.setter + def disasm_cb(self, value): + warnings.warn("Deprecated API: use .mdis.dis_block_callback") + self.mdis.dis_block_callback = value diff --git a/miasm2/jitter/jitcore_cc_base.py b/miasm2/jitter/jitcore_cc_base.py index 4dd8825a..bbf10a53 100644 --- a/miasm2/jitter/jitcore_cc_base.py +++ b/miasm2/jitter/jitcore_cc_base.py @@ -46,9 +46,9 @@ class resolver: class JitCore_Cc_Base(JitCore): "JiT management, abstract class using a C compiler as backend" - def __init__(self, ir_arch, bs=None): + def __init__(self, ir_arch, bin_stream): self.jitted_block_delete_cb = self.deleteCB - super(JitCore_Cc_Base, self).__init__(ir_arch, bs) + super(JitCore_Cc_Base, self).__init__(ir_arch, bin_stream) self.resolver = resolver() self.ir_arch = ir_arch self.states = {} @@ -85,21 +85,12 @@ class JitCore_Cc_Base(JitCore): """ self.codegen = codegen - def label2fname(self, label): - """ - Generate function name from @label - @label: AsmLabel instance - """ - return "block_%s" % self.codegen.label_to_jitlabel(label) - - def gen_c_code(self, label, block): + def gen_c_code(self, block): """ Return the C code corresponding to the @irblocks - @label: AsmLabel of the block to jit @irblocks: list of irblocks """ - f_name = self.label2fname(label) - f_declaration = 'int %s(block_id * BlockDst, JitCpu* jitcpu)' % f_name + f_declaration = 'int %s(block_id * BlockDst, JitCpu* jitcpu)' % self.FUNCNAME out = self.codegen.gen_c(block, log_mn=self.log_mn, log_regs=self.log_regs) out = [f_declaration + '{'] + out + ['}\n'] c_code = out diff --git a/miasm2/jitter/jitcore_gcc.py b/miasm2/jitter/jitcore_gcc.py index ccccc37a..dbaa2a08 100644 --- a/miasm2/jitter/jitcore_gcc.py +++ b/miasm2/jitter/jitcore_gcc.py @@ -13,9 +13,9 @@ from miasm2.jitter.jitcore_cc_base import JitCore_Cc_Base, gen_core class JitCore_Gcc(JitCore_Cc_Base): "JiT management, using a C compiler as backend" - def __init__(self, ir_arch, bs=None): - super(JitCore_Gcc, self).__init__(ir_arch, bs) - self.exec_wrapper = Jitgcc.gcc_exec_bloc + def __init__(self, ir_arch, bin_stream): + super(JitCore_Gcc, self).__init__(ir_arch, bin_stream) + self.exec_wrapper = Jitgcc.gcc_exec_block def deleteCB(self, offset): """Free the state associated to @offset and delete it @@ -25,14 +25,14 @@ class JitCore_Gcc(JitCore_Cc_Base): del self.states[offset] def load_code(self, label, fname_so): - f_name = self.label2fname(label) lib = ctypes.cdll.LoadLibrary(fname_so) - func = getattr(lib, f_name) + func = getattr(lib, self.FUNCNAME) addr = ctypes.cast(func, ctypes.c_void_p).value - self.lbl2jitbloc[label.offset] = addr - self.states[label.offset] = lib + offset = self.ir_arch.loc_db.get_location_offset(label) + self.offset_to_jitted_func[offset] = addr + self.states[offset] = lib - def add_bloc(self, block): + def add_block(self, block): """Add a bloc to JiT and JiT it. @block: block to jit """ @@ -40,7 +40,7 @@ class JitCore_Gcc(JitCore_Cc_Base): fname_out = os.path.join(self.tempdir, "%s.so" % block_hash) if not os.access(fname_out, os.R_OK | os.X_OK): - func_code = self.gen_c_code(block.label, block) + func_code = self.gen_c_code(block) # Create unique C file fdesc, fname_in = tempfile.mkstemp(suffix=".c") @@ -60,7 +60,7 @@ class JitCore_Gcc(JitCore_Cc_Base): os.rename(fname_tmp, fname_out) os.remove(fname_in) - self.load_code(block.label, fname_out) + self.load_code(block.loc_key, fname_out) @staticmethod def gen_C_source(ir_arch, func_code): diff --git a/miasm2/jitter/jitcore_llvm.py b/miasm2/jitter/jitcore_llvm.py index 452b6d84..ea4f20ec 100644 --- a/miasm2/jitter/jitcore_llvm.py +++ b/miasm2/jitter/jitcore_llvm.py @@ -8,7 +8,6 @@ import Jitllvm class JitCore_LLVM(jitcore.JitCore): - "JiT management, using LLVM as backend" # Architecture dependant libraries @@ -20,8 +19,8 @@ class JitCore_LLVM(jitcore.JitCore): "ppc32": "JitCore_ppc32.so", } - def __init__(self, ir_arch, bs=None): - super(JitCore_LLVM, self).__init__(ir_arch, bs) + def __init__(self, ir_arch, bin_stream): + super(JitCore_LLVM, self).__init__(ir_arch, bin_stream) self.options.update({"safe_mode": True, # Verify each function "optimise": True, # Optimise functions @@ -29,7 +28,7 @@ class JitCore_LLVM(jitcore.JitCore): "log_assembly": False, # Print assembly executed }) - self.exec_wrapper = Jitllvm.llvm_exec_bloc + self.exec_wrapper = Jitllvm.llvm_exec_block self.ir_arch = ir_arch # Cache temporary dir @@ -74,16 +73,17 @@ class JitCore_LLVM(jitcore.JitCore): # Enable caching self.context.enable_cache() - def add_bloc(self, block): + def add_block(self, block): """Add a block to JiT and JiT it. @block: the block to add """ + block_hash = self.hash_block(block) fname_out = os.path.join(self.tempdir, "%s.bc" % block_hash) if not os.access(fname_out, os.R_OK): # Build a function in the context - func = LLVMFunction(self.context, LLVMFunction.canonize_label_name(block.label)) + func = LLVMFunction(self.context, self.FUNCNAME) # Set log level func.log_regs = self.log_regs @@ -114,7 +114,9 @@ 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, LLVMFunction.canonize_label_name(block.label)) + ptr = self.context.get_ptr_from_cache(fname_out, self.FUNCNAME) # Store a pointer on the function jitted code - self.lbl2jitbloc[block.label.offset] = ptr + loc_key = block.loc_key + offset = self.ir_arch.loc_db.get_location_offset(loc_key) + self.offset_to_jitted_func[offset] = ptr diff --git a/miasm2/jitter/jitcore_python.py b/miasm2/jitter/jitcore_python.py index 799848ab..61bd98d0 100644 --- a/miasm2/jitter/jitcore_python.py +++ b/miasm2/jitter/jitcore_python.py @@ -4,7 +4,6 @@ import miasm2.jitter.csts as csts from miasm2.expression.simplifications import ExpressionSimplifier from miasm2.jitter.emulatedsymbexec import EmulatedSymbExec - ################################################################################ # Python jitter Core # ################################################################################ @@ -15,15 +14,19 @@ class JitCore_Python(jitcore.JitCore): SymbExecClass = EmulatedSymbExec - def __init__(self, ir_arch, bs=None): - super(JitCore_Python, self).__init__(ir_arch, bs) + def __init__(self, ir_arch, bin_stream): + super(JitCore_Python, self).__init__(ir_arch, bin_stream) self.ir_arch = ir_arch + self.ircfg = self.ir_arch.new_ircfg() # CPU & VM (None for now) will be set later expr_simp = ExpressionSimplifier() expr_simp.enable_passes(ExpressionSimplifier.PASS_COMMONS) - self.symbexec = self.SymbExecClass(None, None, self.ir_arch, {}, - sb_expr_simp=expr_simp) + self.symbexec = self.SymbExecClass( + None, None, + self.ir_arch, {}, + sb_expr_simp=expr_simp + ) self.symbexec.enable_emulated_simplifications() def set_cpu_vm(self, cpu, vm): @@ -34,10 +37,10 @@ class JitCore_Python(jitcore.JitCore): "Preload symbols according to current architecture" self.symbexec.reset_regs() - def jitirblocs(self, label, irblocks): + def jit_irblocks(self, loc_key, irblocks): """Create a python function corresponding to an irblocks' group. - @label: the label of the irblocks - @irblocks: a gorup of irblocks + @loc_key: the loc_key of the irblocks + @irblocks: a group of irblocks """ def myfunc(cpu): @@ -48,7 +51,7 @@ class JitCore_Python(jitcore.JitCore): vmmngr = cpu.vmmngr # Keep current location in irblocks - cur_label = label + cur_loc_key = loc_key # Required to detect new instructions offsets_jitted = set() @@ -57,13 +60,14 @@ class JitCore_Python(jitcore.JitCore): exec_engine = self.symbexec expr_simp = exec_engine.expr_simp + known_loc_keys = set(irb.loc_key for irb in irblocks) # For each irbloc inside irblocks while True: - # Get the current bloc for irb in irblocks: - if irb.label == cur_label: + if irb.loc_key == cur_loc_key: break + else: raise RuntimeError("Irblocks must end with returning an " "ExprInt instance") @@ -75,7 +79,7 @@ class JitCore_Python(jitcore.JitCore): for assignblk in irb: instr = assignblk.instr # For each new instruction (in assembly) - if instr.offset not in offsets_jitted: + if instr is not None and instr.offset not in offsets_jitted: # Test exceptions vmmngr.check_invalid_code_blocs() vmmngr.check_memory_breakpoint() @@ -120,23 +124,25 @@ class JitCore_Python(jitcore.JitCore): # Manage resulting address if isinstance(ad, m2_expr.ExprInt): return ad.arg.arg - elif isinstance(ad, m2_expr.ExprId): - cur_label = ad.name + elif isinstance(ad, m2_expr.ExprLoc): + cur_loc_key = ad.loc_key else: raise NotImplementedError("Type not handled: %s" % ad) - # Associate myfunc with current label - self.lbl2jitbloc[label.offset] = myfunc + # Associate myfunc with current loc_key + offset = self.ir_arch.loc_db.get_location_offset(loc_key) + assert offset is not None + self.offset_to_jitted_func[offset] = myfunc - def exec_wrapper(self, label, cpu, _lbl2jitbloc, _breakpoints, + def exec_wrapper(self, loc_key, cpu, _offset_to_jitted_func, _stop_offsets, _max_exec_per_call): - """Call the function @label with @cpu - @label: function's label + """Call the function @loc_key with @cpu + @loc_key: function's loc_key @cpu: JitCpu instance """ - # Get Python function corresponding to @label - fc_ptr = self.lbl2jitbloc[label] + # Get Python function corresponding to @loc_key + fc_ptr = self.offset_to_jitted_func[loc_key] # Execute the function return fc_ptr(cpu) diff --git a/miasm2/jitter/jitload.py b/miasm2/jitter/jitload.py index db486b4f..288e737a 100644 --- a/miasm2/jitter/jitload.py +++ b/miasm2/jitter/jitload.py @@ -1,5 +1,6 @@ import logging +import warnings from functools import wraps from collections import Sequence, namedtuple, Iterator @@ -160,7 +161,7 @@ class ExceptionHandle(): return not self.__eq__(to_cmp) -class jitter(object): +class Jitter(object): "Main class for JIT handling" @@ -204,8 +205,11 @@ class jitter(object): self.cpu = jcore.JitCpu() self.ir_arch = ir_arch self.bs = bin_stream_vm(self.vm) + self.ircfg = self.ir_arch.new_ircfg() - self.symbexec = EmulatedSymbExec(self.cpu, self.vm, self.ir_arch, {}) + self.symbexec = EmulatedSymbExec( + self.cpu, self.vm, self.ir_arch, {} + ) self.symbexec.reset_regs() try: @@ -302,18 +306,20 @@ class jitter(object): """ self.exceptions_handler.add_callback(flag, callback) - def runbloc(self, pc): + def run_at(self, pc): """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, pc, self.breakpoints_handler.callbacks) + return self.jit.run_at( + self.cpu, pc, + set(self.breakpoints_handler.callbacks.keys()) + ) def runiter_once(self, pc): """Iterator on callbacks results on code running from PC. Check exceptions before breakpoints.""" self.pc = pc - # Callback called before exec if self.exec_cb is not None: res = self.exec_cb(self) @@ -349,7 +355,7 @@ class jitter(object): assert(self.get_exception() == 0) # Run the bloc at PC - self.pc = self.runbloc(self.pc) + self.pc = self.run_at(self.pc) # Check exceptions (raised by the execution of the block) exception_flag = self.get_exception() @@ -485,3 +491,33 @@ class jitter(object): self.symbexec.update_cpu_from_engine() return ret + + def set_trace_log(self, + trace_instr=True, trace_regs=True, + trace_new_blocks=False): + """ + Activate/Deactivate trace log options + + @trace_instr: activate instructions tracing log + @trace_regs: activate registers tracing log + @trace_new_blocks: dump new code blocks log + """ + + # As trace state changes, clear already jitted blocks + self.jit.clear_jitted_blocks() + + self.jit.log_mn = trace_instr + self.jit.log_regs = trace_regs + self.jit.log_newbloc = trace_new_blocks + + +class jitter(Jitter): + """ + DEPRECATED object + Use Jitter instead of jitter + """ + + + def __init__(self, *args, **kwargs): + warnings.warn("Deprecated API: use Jitter") + super(jitter, self).__init__(*args, **kwargs) diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py index 97cd9f17..d63351cc 100644 --- a/miasm2/jitter/llvmconvert.py +++ b/miasm2/jitter/llvmconvert.py @@ -14,7 +14,8 @@ import os from llvmlite import binding as llvm from llvmlite import ir as llvm_ir -import miasm2.expression.expression as m2_expr +from miasm2.expression.expression import ExprId, ExprInt, ExprMem, ExprSlice, \ + ExprCond, ExprLoc, ExprOp, ExprCompose, LocKey import miasm2.jitter.csts as m2_csts import miasm2.core.asmblock as m2_asmblock from miasm2.jitter.codegen import CGen @@ -43,7 +44,7 @@ class LLVMType(llvm_ir.Type): @classmethod def generic(cls, e): "Generic value for execution" - if isinstance(e, m2_expr.ExprInt): + if isinstance(e, ExprInt): return llvm_e.GenericValue.int(LLVMType.IntType(e.size), int(e.arg)) elif isinstance(e, llvm_e.GenericValue): return e @@ -69,6 +70,16 @@ class LLVMContext(): self.target_machine = target.create_target_machine() self.init_exec_engine() + def canonize_label_name(self, label): + """Canonize @label names to a common form. + @label: str or asmlabel instance""" + if isinstance(label, str): + return label + elif isinstance(label, LocKey): + return str(label) + else: + raise ValueError("label must either be str or LocKey") + def optimise_level(self, level=2): """Set the optimisation level to @level from 0 to 2 0: non-optimized @@ -193,7 +204,7 @@ class LLVMContext_JIT(LLVMContext): fc = {} p8 = llvm_ir.PointerType(LLVMType.IntType(8)) - for i in [8, 16, 32, 64]: + for i in [8, 16, 32, 64, 128]: fc["MEM_LOOKUP_%02d" % i] = {"ret": LLVMType.IntType(i), "args": [p8, LLVMType.IntType(64)]} @@ -405,7 +416,7 @@ class LLVMFunction(): @label: str or asmlabel @overwrite: if False, do nothing if a bbl with the same name already exists Return the corresponding LLVM Basic Block""" - name = self.canonize_label_name(label) + name = self.llvm_context.canonize_label_name(label) bbl = self.name2bbl.get(name, None) if not overwrite and bbl is not None: return bbl @@ -483,25 +494,9 @@ class LLVMFunction(): var_casted = var self.builder.ret(var_casted) - @staticmethod - def canonize_label_name(label): - """Canonize @label names to a common form. - @label: str or asmlabel instance""" - if isinstance(label, str): - return label - 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") - - def get_basic_bloc_by_label(self, label): + def get_basic_block_by_loc_key(self, loc_key): "Return the bbl corresponding to label, None otherwise" - return self.name2bbl.get(self.canonize_label_name(label), None) + return self.name2bbl.get(self.llvm_context.canonize_label_name(loc_key), None) def global_constant(self, name, value): """ @@ -567,11 +562,11 @@ class LLVMFunction(): # Destination builder = self.builder - if isinstance(dst, m2_expr.ExprId): + if isinstance(dst, ExprId): ptr_casted = self.get_ptr_by_expr(dst) builder.store(src, ptr_casted) - elif isinstance(dst, m2_expr.ExprMem): + elif isinstance(dst, ExprMem): addr = self.add_ir(dst.arg) self.llvm_context.memory_write(self, addr, dst.size, src) else: @@ -624,20 +619,19 @@ class LLVMFunction(): builder = self.builder - if isinstance(expr, m2_expr.ExprInt): + if isinstance(expr, ExprInt): ret = llvm_ir.Constant(LLVMType.IntType(expr.size), int(expr.arg)) self.update_cache(expr, ret) return ret - if isinstance(expr, m2_expr.ExprId): - name = expr.name - if not isinstance(name, str): - # Resolve label - offset = name.offset - ret = llvm_ir.Constant(LLVMType.IntType(expr.size), offset) - self.update_cache(expr, ret) - return ret + if expr.is_loc(): + offset = self.llvm_context.ir_arch.loc_db.get_location_offset(expr.loc_key) + ret = llvm_ir.Constant(LLVMType.IntType(expr.size), offset) + self.update_cache(expr, ret) + return ret + if isinstance(expr, ExprId): + name = expr.name try: # If expr.name is already known (args) return self.local_vars[name] @@ -650,7 +644,7 @@ class LLVMFunction(): self.update_cache(expr, var) return var - if isinstance(expr, m2_expr.ExprOp): + if isinstance(expr, ExprOp): op = expr.op if (op in self.op_translate or @@ -857,12 +851,12 @@ class LLVMFunction(): raise NotImplementedError() - if isinstance(expr, m2_expr.ExprMem): + if isinstance(expr, ExprMem): addr = self.add_ir(expr.arg) return self.llvm_context.memory_lookup(self, addr, expr.size) - if isinstance(expr, m2_expr.ExprCond): + if isinstance(expr, ExprCond): # Compute cond cond = self.add_ir(expr.cond) zero_casted = LLVMType.IntType(expr.cond.size)(0) @@ -875,7 +869,7 @@ class LLVMFunction(): self.update_cache(expr, ret) return ret - if isinstance(expr, m2_expr.ExprSlice): + if isinstance(expr, ExprSlice): src = self.add_ir(expr.arg) @@ -901,7 +895,7 @@ class LLVMFunction(): self.update_cache(expr, ret) return ret - if isinstance(expr, m2_expr.ExprCompose): + if isinstance(expr, ExprCompose): args = [] @@ -982,9 +976,9 @@ class LLVMFunction(): builder.position_at_end(then_block) PC = self.llvm_context.PC if isinstance(offset, (int, long)): - offset = self.add_ir(m2_expr.ExprInt(offset, PC.size)) + offset = self.add_ir(ExprInt(offset, PC.size)) self.affect(offset, PC) - self.affect(self.add_ir(m2_expr.ExprInt(1, 8)), m2_expr.ExprId("status", 32)) + self.affect(self.add_ir(ExprInt(1, 8)), ExprId("status", 32)) self.set_ret(offset) builder.position_at_end(merge_block) @@ -1029,9 +1023,9 @@ class LLVMFunction(): builder.position_at_end(then_block) PC = self.llvm_context.PC if isinstance(offset, (int, long)): - offset = self.add_ir(m2_expr.ExprInt(offset, PC.size)) + offset = self.add_ir(ExprInt(offset, PC.size)) self.affect(offset, PC) - self.affect(self.add_ir(m2_expr.ExprInt(1, 8)), m2_expr.ExprId("status", 32)) + self.affect(self.add_ir(ExprInt(1, 8)), ExprId("status", 32)) self.set_ret(offset) builder.position_at_end(merge_block) @@ -1056,6 +1050,9 @@ class LLVMFunction(): self.builder.call(fc_ptr, [self.local_vars["vmmngr"]]) self.check_memory_exception(next_instr, restricted_exception=False) + if attrib.set_exception: + self.check_cpu_exception(next_instr, restricted_exception=False) + if attrib.mem_read | attrib.mem_write: fc_ptr = self.mod.get_global("reset_memory_access") self.builder.call(fc_ptr, [self.local_vars["vmmngr"]]) @@ -1073,9 +1070,9 @@ class LLVMFunction(): for i, solution in enumerate(possible_values(expr)): value = solution.value index = dst2case.get(value, i) - to_eval = to_eval.replace_expr({value: m2_expr.ExprInt(index, value.size)}) + to_eval = to_eval.replace_expr({value: ExprInt(index, value.size)}) dst2case[value] = index - if m2_asmblock.expr_is_int_or_label(value): + if value.is_int() or value.is_loc(): case2dst[i] = value else: case2dst[i] = self.add_ir(value) @@ -1101,13 +1098,14 @@ class LLVMFunction(): # We are no longer in the main stream, deactivate cache self.main_stream = False - if isinstance(dst, m2_expr.ExprInt): - dst = m2_expr.ExprId(self.llvm_context.ir_arch.symbol_pool.getby_offset_create(int(dst)), - dst.size) + if isinstance(dst, ExprInt): + loc_key = self.llvm_context.ir_arch.loc_db.get_or_create_offset_location(int(dst)) + dst = ExprLoc(loc_key, dst.size) - if m2_asmblock.expr_is_label(dst): - bbl = self.get_basic_bloc_by_label(dst) - offset = dst.name.offset + if isinstance(dst, ExprLoc): + loc_key = dst.loc_key + bbl = self.get_basic_block_by_loc_key(loc_key) + offset = self.llvm_context.ir_arch.loc_db.get_location_offset(loc_key) if bbl is not None: # "local" jump, inside this function if offset is None: @@ -1127,7 +1125,7 @@ class LLVMFunction(): # extern # "extern" jump on a defined offset, return to the caller - dst = self.add_ir(m2_expr.ExprInt(offset, PC.size)) + dst = self.add_ir(ExprInt(offset, PC.size)) # "extern" jump with a computed value, return to the caller assert isinstance(dst, (llvm_ir.Instruction, llvm_ir.Value)) @@ -1139,7 +1137,7 @@ class LLVMFunction(): self.gen_post_code(attrib) self.affect(dst, PC) self.gen_post_instr_checks(attrib, dst) - self.affect(self.add_ir(m2_expr.ExprInt(0, 8)), m2_expr.ExprId("status", 32)) + self.affect(self.add_ir(ExprInt(0, 8)), ExprId("status", 32)) self.set_ret(dst) @@ -1163,7 +1161,7 @@ class LLVMFunction(): # Prefetch memory for element in assignblk.get_r(mem_read=True): - if isinstance(element, m2_expr.ExprMem): + if isinstance(element, ExprMem): self.add_ir(element) # Evaluate expressions @@ -1181,7 +1179,7 @@ class LLVMFunction(): # Update the memory for dst, src in values.iteritems(): - if isinstance(dst, m2_expr.ExprMem): + if isinstance(dst, ExprMem): self.affect(src, dst) # Check memory write exception @@ -1191,7 +1189,7 @@ class LLVMFunction(): # Update registers values for dst, src in values.iteritems(): - if not isinstance(dst, m2_expr.ExprMem): + if not isinstance(dst, ExprMem): self.affect(src, dst) # Check post assignblk exception flags @@ -1232,11 +1230,12 @@ class LLVMFunction(): builder = self.builder m2_exception_flag = self.llvm_context.ir_arch.arch.regs.exception_flags t_size = LLVMType.IntType(m2_exception_flag.size) - self.affect(self.add_ir(m2_expr.ExprInt(1, 8)), - m2_expr.ExprId("status", 32)) + self.affect(self.add_ir(ExprInt(1, 8)), + ExprId("status", 32)) self.affect(t_size(m2_csts.EXCEPT_UNK_MNEMO), m2_exception_flag) - self.set_ret(LLVMType.IntType(64)(asmblock.label.offset)) + offset = self.llvm_context.ir_arch.loc_db.get_location_offset(asmblock.loc_key) + self.set_ret(LLVMType.IntType(64)(offset)) def gen_finalize(self, asmblock, codegen): """ @@ -1247,11 +1246,11 @@ class LLVMFunction(): next_label = codegen.get_block_post_label(asmblock) builder = self.builder - builder.position_at_end(self.get_basic_bloc_by_label(next_label)) + builder.position_at_end(self.get_basic_block_by_loc_key(next_label)) # Common code - self.affect(self.add_ir(m2_expr.ExprInt(0, 8)), - m2_expr.ExprId("status", 32)) + self.affect(self.add_ir(ExprInt(0, 8)), + ExprId("status", 32)) # Check if IRDst has been set zero_casted = LLVMType.IntType(codegen.delay_slot_set.size)(0) @@ -1274,14 +1273,15 @@ class LLVMFunction(): PC = self.llvm_context.PC to_ret = self.add_ir(codegen.delay_slot_dst) self.affect(to_ret, PC) - self.affect(self.add_ir(m2_expr.ExprInt(0, 8)), - m2_expr.ExprId("status", 32)) + self.affect(self.add_ir(ExprInt(0, 8)), + ExprId("status", 32)) self.set_ret(to_ret) # Else Block builder.position_at_end(else_block) PC = self.llvm_context.PC - to_ret = LLVMType.IntType(PC.size)(next_label.offset) + next_label_offset = self.llvm_context.ir_arch.loc_db.get_location_offset(next_label) + to_ret = LLVMType.IntType(PC.size)(next_label_offset) self.affect(to_ret, PC) self.set_ret(to_ret) @@ -1290,16 +1290,16 @@ class LLVMFunction(): Prototype : f(i8* jitcpu, i8* vmcpu, i8* vmmngr, i8* status)""" # Build function signature - self.my_args.append((m2_expr.ExprId("jitcpu", 32), + self.my_args.append((ExprId("jitcpu", 32), llvm_ir.PointerType(LLVMType.IntType(8)), "jitcpu")) - self.my_args.append((m2_expr.ExprId("vmcpu", 32), + self.my_args.append((ExprId("vmcpu", 32), llvm_ir.PointerType(LLVMType.IntType(8)), "vmcpu")) - self.my_args.append((m2_expr.ExprId("vmmngr", 32), + self.my_args.append((ExprId("vmmngr", 32), llvm_ir.PointerType(LLVMType.IntType(8)), "vmmngr")) - self.my_args.append((m2_expr.ExprId("status", 32), + self.my_args.append((ExprId("status", 32), llvm_ir.PointerType(LLVMType.IntType(8)), "status")) ret_size = 64 @@ -1317,7 +1317,7 @@ class LLVMFunction(): # Create basic blocks (for label branchs) entry_bbl, builder = self.entry_bbl, self.builder for instr in asmblock.lines: - lbl = self.llvm_context.ir_arch.symbol_pool.getby_offset_create(instr.offset) + lbl = self.llvm_context.ir_arch.loc_db.get_or_create_offset_location(instr.offset) self.append_basic_block(lbl) # TODO: merge duplicate code with CGen @@ -1332,9 +1332,10 @@ class LLVMFunction(): ptr = self.CreateEntryBlockAlloca(eltype, default_value=eltype(0)) self.local_vars_pointers[element.name] = ptr - lbl = codegen.get_block_post_label(asmblock) - instr_offsets.append(lbl.offset) - self.append_basic_block(lbl) + loc_key = codegen.get_block_post_label(asmblock) + offset = self.llvm_context.ir_arch.loc_db.get_location_offset(loc_key) + instr_offsets.append(offset) + self.append_basic_block(loc_key) # Add content builder.position_at_end(entry_bbl) @@ -1347,7 +1348,7 @@ class LLVMFunction(): # Pre-create basic blocks for irblock in irblocks: - self.append_basic_block(irblock.label, overwrite=False) + self.append_basic_block(irblock.loc_key, overwrite=False) # Generate the corresponding code for index, irblock in enumerate(irblocks): @@ -1355,8 +1356,7 @@ class LLVMFunction(): irblock, self.llvm_context.ir_arch.attrib) # Set the builder at the begining of the correct bbl - name = self.canonize_label_name(new_irblock.label) - self.builder.position_at_end(self.get_basic_bloc_by_label(name)) + self.builder.position_at_end(self.get_basic_block_by_loc_key(new_irblock.loc_key)) if index == 0: self.gen_pre_code(instr_attrib) @@ -1367,7 +1367,7 @@ class LLVMFunction(): # Branch entry_bbl on first label builder.position_at_end(entry_bbl) - first_label_bbl = self.get_basic_bloc_by_label(asmblock.label) + first_label_bbl = self.get_basic_block_by_loc_key(asmblock.loc_key) builder.branch(first_label_bbl) diff --git a/miasm2/jitter/loader/elf.py b/miasm2/jitter/loader/elf.py index deaebd09..01dea647 100644 --- a/miasm2/jitter/loader/elf.py +++ b/miasm2/jitter/loader/elf.py @@ -32,7 +32,6 @@ def preload_elf(vm, e, runtime_lib, patch_vm_imp=True): # XXX quick hack fa = get_import_address_elf(e) dyn_funcs = {} - # log.debug('imported funcs: %s' % fa) for (libname, libfunc), ads in fa.items(): for ad in ads: ad_base_lib = runtime_lib.lib_get_add_base(libname) @@ -77,7 +76,6 @@ def vm_load_elf(vm, fdata, name="", **kargs): # -2: Trick to avoid merging 2 consecutive pages i += [(a_addr, b_addr - 2)] for a, b in i.intervals: - # print hex(a), hex(b) vm.add_memory_page(a, PAGE_READ | PAGE_WRITE, "\x00" * (b + 2 - a), repr(name)) diff --git a/miasm2/jitter/loader/pe.py b/miasm2/jitter/loader/pe.py index 2fe4cd3f..9bc0ef8b 100644 --- a/miasm2/jitter/loader/pe.py +++ b/miasm2/jitter/loader/pe.py @@ -163,7 +163,8 @@ def vm_load_pe(vm, fdata, align_s=True, load_hdr=True, name="", **kargs): section.size = new_size section.rawsize = new_size section.data = strpatchwork.StrPatchwork( - section.data[:new_size]) + section.data[:new_size] + ) section.offset = section.addr # Last section alignement diff --git a/miasm2/jitter/op_semantics.c b/miasm2/jitter/op_semantics.c index 82f56422..0420532a 100644 --- a/miasm2/jitter/op_semantics.c +++ b/miasm2/jitter/op_semantics.c @@ -774,3 +774,23 @@ uint64_t double_to_mem_64(double d) #endif return m; } + +UDIV(16) +UDIV(32) +UDIV(64) +UDIV(128) + +UMOD(16) +UMOD(32) +UMOD(64) +UMOD(128) + +IDIV(16) +IDIV(32) +IDIV(64) +IDIV(128) + +IMOD(16) +IMOD(32) +IMOD(64) +IMOD(128) diff --git a/miasm2/jitter/op_semantics.h b/miasm2/jitter/op_semantics.h index a52afd42..3eb81cff 100644 --- a/miasm2/jitter/op_semantics.h +++ b/miasm2/jitter/op_semantics.h @@ -1,6 +1,9 @@ #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] @@ -27,7 +30,7 @@ unsigned int cntleadzeros(uint64_t size, uint64_t src); unsigned int cnttrailzeros(uint64_t size, uint64_t src); #define UDIV(sizeA) \ - uint ## sizeA ## _t udiv ## sizeA (vm_cpu_t* vmcpu, uint ## sizeA ## _t a, uint ## sizeA ## _t b) \ + uint ## sizeA ## _t udiv ## sizeA (uint ## sizeA ## _t a, uint ## sizeA ## _t b) \ { \ uint ## sizeA ## _t r; \ if (b == 0) { \ @@ -40,7 +43,7 @@ unsigned int cnttrailzeros(uint64_t size, uint64_t src); #define UMOD(sizeA) \ - uint ## sizeA ## _t umod ## sizeA (vm_cpu_t* vmcpu, uint ## sizeA ## _t a, uint ## sizeA ## _t b) \ + uint ## sizeA ## _t umod ## sizeA (uint ## sizeA ## _t a, uint ## sizeA ## _t b) \ { \ uint ## sizeA ## _t r; \ if (b == 0) { \ @@ -53,7 +56,7 @@ unsigned int cnttrailzeros(uint64_t size, uint64_t src); #define IDIV(sizeA) \ - int ## sizeA ## _t idiv ## sizeA (vm_cpu_t* vmcpu, int ## sizeA ## _t a, int ## sizeA ## _t b) \ + int ## sizeA ## _t idiv ## sizeA (int ## sizeA ## _t a, int ## sizeA ## _t b) \ { \ int ## sizeA ## _t r; \ if (b == 0) { \ @@ -66,7 +69,7 @@ unsigned int cnttrailzeros(uint64_t size, uint64_t src); #define IMOD(sizeA) \ - int ## sizeA ## _t imod ## sizeA (vm_cpu_t* vmcpu, int ## sizeA ## _t a, int ## sizeA ## _t b) \ + int ## sizeA ## _t imod ## sizeA (int ## sizeA ## _t a, int ## sizeA ## _t b) \ { \ int ## sizeA ## _t r; \ if (b == 0) { \ @@ -77,6 +80,21 @@ unsigned int cnttrailzeros(uint64_t size, uint64_t src); return r; \ } +uint64_t udiv64(uint64_t a, uint64_t b); +uint64_t umod64(uint64_t a, uint64_t b); +int64_t idiv64(int64_t a, int64_t b); +int64_t imod64(int64_t a, int64_t b); + +uint32_t udiv32(uint32_t a, uint32_t b); +uint32_t umod32(uint32_t a, uint32_t b); +int32_t idiv32(int32_t a, int32_t b); +int32_t imod32(int32_t a, int32_t b); + +uint16_t udiv16(uint16_t a, uint16_t b); +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); + unsigned int x86_cpuid(unsigned int a, unsigned int reg_num); double int2double(unsigned int m); diff --git a/miasm2/jitter/vm_mngr.c b/miasm2/jitter/vm_mngr.c index 6da7bfed..dd0f6cf2 100644 --- a/miasm2/jitter/vm_mngr.c +++ b/miasm2/jitter/vm_mngr.c @@ -101,6 +101,13 @@ 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) { @@ -108,7 +115,7 @@ void print_val(uint64_t base, uint64_t addr) fprintf(stderr, "addr 0x%"PRIX64" val 0x%"PRIX64"\n", addr-base, *ptr); } -inline int midpoint(int imin, int imax) +int midpoint(int imin, int imax) { return (imin + imax) / 2; } @@ -159,11 +166,11 @@ struct memory_page_node * get_memory_page_from_address(vm_mngr_t* vm_mngr, uint6 -static uint64_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t ad) +static uint128_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t ad) { struct memory_page_node * mpn; unsigned char * addr; - uint64_t ret = 0; + uint128_t ret = 0; struct memory_breakpoint_info * b; @@ -206,6 +213,10 @@ static uint64_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint6 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: exit(EXIT_FAILURE); break; @@ -238,6 +249,9 @@ static uint64_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint6 case 64: ret = set_endian64(vm_mngr, ret); break; + case 128: + ret = set_endian128(vm_mngr, ret); + break; default: exit(EXIT_FAILURE); break; @@ -247,7 +261,7 @@ static uint64_t memory_page_read(vm_mngr_t* vm_mngr, unsigned int my_size, uint6 } static void memory_page_write(vm_mngr_t* vm_mngr, unsigned int my_size, - uint64_t ad, uint64_t src) + uint64_t ad, uint128_t src) { struct memory_page_node * mpn; unsigned char * addr; @@ -291,6 +305,10 @@ 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: exit(EXIT_FAILURE); break; @@ -312,6 +330,9 @@ 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: exit(EXIT_FAILURE); break; @@ -480,6 +501,12 @@ 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; @@ -508,6 +535,13 @@ 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 eff5e0da..a50b52d0 100644 --- a/miasm2/jitter/vm_mngr.h +++ b/miasm2/jitter/vm_mngr.h @@ -26,6 +26,8 @@ #define __LITTLE_ENDIAN _LITTLE_ENDIAN #endif +#define uint128_t __uint128_t + #define Endian16_Swap(value) \ ((((uint16_t)((value) & 0x00FF)) << 8) | \ (((uint16_t)((value) & 0xFF00)) >> 8)) @@ -46,8 +48,25 @@ ((((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); @@ -174,13 +193,13 @@ 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); |