diff options
Diffstat (limited to 'miasm/jitter')
47 files changed, 0 insertions, 16738 deletions
diff --git a/miasm/jitter/JitCore.c b/miasm/jitter/JitCore.c deleted file mode 100644 index dfead5a8..00000000 --- a/miasm/jitter/JitCore.c +++ /dev/null @@ -1,247 +0,0 @@ -#include <Python.h> -#include "structmember.h" -#include <stdint.h> -#include <limits.h> -#include <inttypes.h> -#include "compat_py23.h" -#include "queue.h" -#include "vm_mngr.h" -#include "bn.h" -#include "vm_mngr_py.h" -#include "JitCore.h" - - -void JitCpu_dealloc(JitCpu* self) -{ - Py_TYPE(self)->tp_free((PyObject*)self); -} - - -PyObject * JitCpu_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - JitCpu *self; - - self = (JitCpu *)type->tp_alloc(type, 0); - return (PyObject *)self; -} - -PyObject * JitCpu_get_vmmngr(JitCpu *self, void *closure) -{ - if (self->pyvm) { - Py_INCREF(self->pyvm); - return (PyObject*)self->pyvm; - } - Py_INCREF(Py_None); - return Py_None; -} - -PyObject * JitCpu_set_vmmngr(JitCpu *self, PyObject *value, void *closure) -{ - self->pyvm = (VmMngr*)value; - return 0; -} - - - -PyObject * JitCpu_get_vmcpu(JitCpu *self, void *closure) -{ - PyObject * ret; - uint64_t addr; - addr = (uint64_t) self->cpu; - ret = PyLong_FromUnsignedLongLong(addr); - return ret; -} - -PyObject * JitCpu_set_vmcpu(JitCpu *self, PyObject *value, void *closure) -{ - fprintf(stderr, "Set vmcpu not supported yet\n"); - exit(-1); -} - - - -PyObject * JitCpu_get_jitter(JitCpu *self, void *closure) -{ - if (self->jitter) { - Py_INCREF(self->jitter); - return self->jitter; - } - Py_INCREF(Py_None); - return Py_None; -} - -PyObject * JitCpu_set_jitter(JitCpu *self, PyObject *value, void *closure) -{ - self->jitter = value; - return 0; -} - -uint8_t MEM_LOOKUP_08(JitCpu* jitcpu, uint64_t addr) -{ - return vm_MEM_LOOKUP_08(&(jitcpu->pyvm->vm_mngr), addr); -} - -uint16_t MEM_LOOKUP_16(JitCpu* jitcpu, uint64_t addr) -{ - return vm_MEM_LOOKUP_16(&(jitcpu->pyvm->vm_mngr), addr); -} - -uint32_t MEM_LOOKUP_32(JitCpu* jitcpu, uint64_t addr) -{ - return vm_MEM_LOOKUP_32(&(jitcpu->pyvm->vm_mngr), addr); -} - -uint64_t MEM_LOOKUP_64(JitCpu* jitcpu, uint64_t addr) -{ - return vm_MEM_LOOKUP_64(&(jitcpu->pyvm->vm_mngr), addr); -} - -bn_t MEM_LOOKUP_BN_BN(JitCpu* jitcpu, int size, bn_t addr) -{ - uint64_t ptr; - int i; - uint8_t tmp; - bn_t val = bignum_from_int(0); - - ptr = bignum_to_uint64(addr); - - - for (i=0; i < size; i += 8) { - tmp = vm_MEM_LOOKUP_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, ptr); - ptr += 1; - val = bignum_or(val, bignum_lshift(bignum_from_int(tmp), i)); - } - - return val; -} - - -uint64_t MEM_LOOKUP_BN_INT(JitCpu* jitcpu, int size, bn_t addr) -{ - uint64_t ptr; - uint64_t val = 0; - - ptr = bignum_to_uint64(addr); - - switch (size) { - case 8: - val = vm_MEM_LOOKUP_08(&(jitcpu->pyvm->vm_mngr), ptr); - break; - case 16: - val = vm_MEM_LOOKUP_16(&(jitcpu->pyvm->vm_mngr), ptr); - break; - case 32: - val = vm_MEM_LOOKUP_32(&(jitcpu->pyvm->vm_mngr), ptr); - break; - case 64: - val = vm_MEM_LOOKUP_64(&(jitcpu->pyvm->vm_mngr), ptr); - break; - default: - fprintf(stderr, "Error: bad READ size %d\n", size); - exit(-1); - break; - } - - return val; -} - - - -bn_t MEM_LOOKUP_INT_BN(JitCpu* jitcpu, int size, uint64_t addr) -{ - int i; - uint8_t tmp; - bn_t val = bignum_from_int(0); - - for (i=0; i < size; i += 8) { - tmp = vm_MEM_LOOKUP_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr); - addr += 1; - val = bignum_or(val, bignum_lshift(bignum_from_int(tmp), i)); - } - - return val; -} - - -void MEM_LOOKUP_INT_BN_TO_PTR(JitCpu* jitcpu, int size, uint64_t addr, char* ptr) -{ - bn_t ret; - - if (size % 8) { - fprintf(stderr, "Bad size %d\n", size); - exit(-1); - } - - ret = MEM_LOOKUP_INT_BN(jitcpu, size, addr); - memcpy(ptr, (char*)&ret, size / 8); -} - - -void MEM_WRITE_BN_BN(JitCpu* jitcpu, int size, bn_t addr, bn_t src) -{ - uint64_t ptr; - int val; - int i; - - ptr = bignum_to_uint64(addr); - for (i=0; i < size; i += 8) { - val = bignum_to_uint64(src) & 0xFF; - vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, ptr, val); - ptr += 1; - src = bignum_rshift(src, 8); - } -} - - -void MEM_WRITE_BN_INT(JitCpu* jitcpu, int size, bn_t addr, uint64_t src) -{ - uint64_t ptr; - ptr = bignum_to_uint64(addr); - - switch (size) { - case 8: - vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, ptr, (unsigned char)src); - break; - case 16: - vm_MEM_WRITE_16(&((VmMngr*)jitcpu->pyvm)->vm_mngr, ptr, (unsigned short)src); - break; - case 32: - vm_MEM_WRITE_32(&((VmMngr*)jitcpu->pyvm)->vm_mngr, ptr, (unsigned int)src); - break; - case 64: - vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, ptr, src); - break; - default: - fprintf(stderr, "Error: bad write size %d\n", size); - exit(-1); - break; - } -} - -void MEM_WRITE_INT_BN(JitCpu* jitcpu, int size, uint64_t addr, bn_t src) -{ - int val; - int i; - - for (i=0; i < size; i += 8) { - val = bignum_to_uint64(src) & 0xFF; - vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, val); - addr += 1; - src = bignum_rshift(src, 8); - } -} - - -void MEM_WRITE_INT_BN_FROM_PTR(JitCpu* jitcpu, int size, uint64_t addr, char* ptr) -{ - bn_t val; - - if (size % 8) { - fprintf(stderr, "Bad size %d\n", size); - exit(-1); - } - - val = bignum_from_int(0); - memcpy(&val, ptr, size / 8); - MEM_WRITE_INT_BN(jitcpu, size, addr, val); -} diff --git a/miasm/jitter/JitCore.h b/miasm/jitter/JitCore.h deleted file mode 100644 index ff6ff159..00000000 --- a/miasm/jitter/JitCore.h +++ /dev/null @@ -1,242 +0,0 @@ -#ifndef JITCORE_H -#define JITCORE_H - -#if _WIN32 -#define _MIASM_EXPORT __declspec(dllexport) - -#ifndef SSIZE_MAX -#ifdef _WIN64 -#define SSIZE_MAX _I64_MAX -#else -#define SSIZE_MAX INT_MAX -#endif -#endif - -#else -#define _MIASM_EXPORT -#endif - -#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;} - - -#if PY_MAJOR_VERSION >= 3 -#define getset_reg_bn(regname, size) \ - static PyObject *JitCpu_get_ ## regname (JitCpu *self, void *closure) \ - { \ - bn_t bn; \ - PyObject* py_long; \ - bn = (self->cpu)->regname; \ - bn = bignum_mask(bn, (size)); \ - py_long = bn_to_PyLong(bn); \ - return py_long; \ - } \ - \ - static PyObject *JitCpu_set_ ## regname (JitCpu *self, PyObject *value, void *closure) \ - { \ - bn_t bn; \ - PyObject* py_long = value; \ - if (PyLong_Check(py_long)){ \ - Py_INCREF(py_long); \ - } else { \ - RAISE(PyExc_TypeError,"arg must be int"); \ - } \ - \ - bn = PyLong_to_bn(py_long); \ - \ - (self->cpu)->regname = bignum_mask(bn, (size)); \ - return 0; \ - } - - -#else -#define getset_reg_bn(regname, size) \ - static PyObject *JitCpu_get_ ## regname (JitCpu *self, void *closure) \ - { \ - bn_t bn; \ - PyObject* py_long; \ - bn = (self->cpu)->regname; \ - bn = bignum_mask(bn, (size)); \ - py_long = bn_to_PyLong(bn); \ - return py_long; \ - } \ - \ - static PyObject *JitCpu_set_ ## regname (JitCpu *self, PyObject *value, void *closure) \ - { \ - bn_t bn; \ - PyObject* py_long = value; \ - uint64_t tmp; \ - \ - if (PyInt_Check(py_long)){ \ - tmp = (uint64_t)PyInt_AsLong(py_long); \ - py_long = PyLong_FromLong((long)tmp); \ - } else if (PyLong_Check(py_long)){ \ - Py_INCREF(py_long); \ - } \ - else{ \ - RAISE(PyExc_TypeError,"arg must be int"); \ - } \ - \ - bn = PyLong_to_bn(py_long); \ - \ - self->cpu->regname = bignum_mask(bn, (size)); \ - return 0; \ - } -#endif - - - - - - - - - - - -#define getset_reg_u64(regname) \ - static PyObject *JitCpu_get_ ## regname (JitCpu *self, void *closure) \ - { \ - return PyLong_FromUnsignedLongLong(self->cpu->regname); \ - } \ - static int JitCpu_set_ ## regname (JitCpu *self, PyObject *value, void *closure) \ - { \ - uint64_t val; \ - PyGetInt_uint64_t_retneg(value, val); \ - self->cpu->regname = val; \ - return 0; \ - } - -#define getset_reg_u32(regname) \ - static PyObject *JitCpu_get_ ## regname (JitCpu *self, void *closure) \ - { \ - return PyLong_FromUnsignedLongLong(self->cpu->regname); \ - } \ - static int JitCpu_set_ ## regname (JitCpu *self, PyObject *value, void *closure) \ - { \ - uint32_t val; \ - PyGetInt_uint32_t_retneg(value, val); \ - self->cpu->regname = val; \ - return 0; \ - } - - -#define getset_reg_u16(regname) \ - static PyObject *JitCpu_get_ ## regname (JitCpu *self, void *closure) \ - { \ - return PyLong_FromUnsignedLongLong(self->cpu->regname); \ - } \ - static int JitCpu_set_ ## regname (JitCpu *self, PyObject *value, void *closure) \ - { \ - uint16_t val; \ - PyGetInt_uint16_t_retneg(value, val); \ - self->cpu->regname = val; \ - return 0; \ - } - - -#define getset_reg_u8(regname) \ - static PyObject *JitCpu_get_ ## regname (JitCpu *self, void *closure) \ - { \ - return PyLong_FromUnsignedLongLong(self->cpu->regname); \ - } \ - static int JitCpu_set_ ## regname (JitCpu *self, PyObject *value, void *closure) \ - { \ - uint8_t val; \ - PyGetInt_uint8_t_retneg(value, val); \ - self->cpu->regname = val; \ - return 0; \ - } - - -#define get_reg(reg) do { \ - o = PyLong_FromUnsignedLongLong((uint64_t)self->cpu->reg); \ - PyDict_SetItemString(dict, #reg, o); \ - Py_DECREF(o); \ - } while(0); - - -#define get_reg_bn(reg, size) do { \ - bn_t bn; \ - PyObject* py_long; \ - bn = self->cpu->reg; \ - bn = bignum_mask(bn, size); \ - py_long = bn_to_PyLong(bn); \ - PyDict_SetItemString(dict, #reg, py_long); \ - Py_DECREF(py_long); \ - } while(0); - - -#define get_reg_off(reg) do { \ - o = PyLong_FromUnsignedLongLong((uint64_t)offsetof(struct vm_cpu, reg)); \ - PyDict_SetItemString(dict, #reg, o); \ - Py_DECREF(o); \ - } while(0); - - - - -typedef struct { - uint8_t is_local; - uint64_t address; -} block_id; - -struct vm_cpu; - -typedef struct { - PyObject_HEAD - VmMngr *pyvm; - PyObject *jitter; - struct vm_cpu *cpu; -} JitCpu; - - -typedef struct _reg_dict{ - char* name; - size_t offset; - size_t size; -} reg_dict; - - - -void JitCpu_dealloc(JitCpu* self); -PyObject * JitCpu_new(PyTypeObject *type, PyObject *args, PyObject *kwds); -PyObject * JitCpu_get_vmmngr(JitCpu *self, void *closure); -PyObject * JitCpu_set_vmmngr(JitCpu *self, PyObject *value, void *closure); -PyObject * JitCpu_get_vmcpu(JitCpu *self, void *closure); -PyObject * JitCpu_set_vmcpu(JitCpu *self, PyObject *value, void *closure); -PyObject * JitCpu_get_jitter(JitCpu *self, void *closure); -PyObject * JitCpu_set_jitter(JitCpu *self, PyObject *value, void *closure); -void Resolve_dst(block_id* BlockDst, uint64_t addr, uint64_t is_local); - -#define Resolve_dst(b, arg_addr, arg_is_local) do {(b)->address = (arg_addr); (b)->is_local = (arg_is_local);} while(0) - - - -_MIASM_EXPORT uint8_t MEM_LOOKUP_08(JitCpu* jitcpu, uint64_t addr); -_MIASM_EXPORT uint16_t MEM_LOOKUP_16(JitCpu* jitcpu, uint64_t addr); -_MIASM_EXPORT uint32_t MEM_LOOKUP_32(JitCpu* jitcpu, uint64_t addr); -_MIASM_EXPORT uint64_t MEM_LOOKUP_64(JitCpu* jitcpu, uint64_t addr); - -_MIASM_EXPORT bn_t MEM_LOOKUP_BN_BN(JitCpu* jitcpu, int size, bn_t addr); -_MIASM_EXPORT bn_t MEM_LOOKUP_INT_BN(JitCpu* jitcpu, int size, uint64_t addr); - -_MIASM_EXPORT uint64_t MEM_LOOKUP_BN_INT(JitCpu* jitcpu, int size, bn_t addr); - -_MIASM_EXPORT void MEM_WRITE_BN_BN(JitCpu* jitcpu, int size, bn_t addr, bn_t src); -_MIASM_EXPORT void MEM_WRITE_BN_INT(JitCpu* jitcpu, int size, bn_t addr, uint64_t src); -_MIASM_EXPORT void MEM_WRITE_INT_BN(JitCpu* jitcpu, int size, uint64_t addr, bn_t src); - - -_MIASM_EXPORT void MEM_LOOKUP_INT_BN_TO_PTR(JitCpu* jitcpu, int size, uint64_t addr, char* ptr); -_MIASM_EXPORT void MEM_WRITE_INT_BN_FROM_PTR(JitCpu* jitcpu, int size, uint64_t addr, char* ptr); - - - -#define VM_exception_flag (jitcpu->pyvm->vm_mngr.exception_flags) -#define CPU_exception_flag (((struct vm_cpu*)jitcpu->cpu)->exception_flags) -#define CPU_exception_flag_at_instr ((CPU_exception_flag) && ((CPU_exception_flag) > EXCEPT_NUM_UPDT_EIP)) -#define JIT_RET_EXCEPTION 1 -#define JIT_RET_NO_EXCEPTION 0 - -#endif diff --git a/miasm/jitter/Jitgcc.c b/miasm/jitter/Jitgcc.c deleted file mode 100644 index 9dc7b2fd..00000000 --- a/miasm/jitter/Jitgcc.c +++ /dev/null @@ -1,100 +0,0 @@ -#include <Python.h> -#include <inttypes.h> -#include <stdint.h> -#include "compat_py23.h" - -typedef struct { - uint8_t is_local; - uint64_t address; -} block_id; - -typedef int (*jitted_func)(block_id*, PyObject*); - - -PyObject* gcc_exec_block(PyObject* self, PyObject* args) -{ - jitted_func func; - PyObject* jitcpu; - PyObject* func_py; - PyObject* lbl2ptr; - PyObject* stop_offsets; - PyObject* retaddr = NULL; - int status; - block_id BlockDst; - uint64_t max_exec_per_call = 0; - uint64_t cpt; - int do_cpt; - - - if (!PyArg_ParseTuple(args, "OOOO|K", - &retaddr, &jitcpu, &lbl2ptr, &stop_offsets, - &max_exec_per_call)) - return NULL; - - /* The loop will decref retaddr always once */ - Py_INCREF(retaddr); - - if (max_exec_per_call == 0) { - do_cpt = 0; - cpt = 1; - } else { - do_cpt = 1; - cpt = max_exec_per_call; - } - - - - for (;;) { - if (cpt == 0) - return retaddr; - if (do_cpt) - cpt --; - // 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) PyLong_AsVoidPtr((PyObject*) func_py); - else { - if (BlockDst.is_local == 1) { - fprintf(stderr, "return on local label!\n"); - exit(EXIT_FAILURE); - } - // retaddr is not jitted yet - return retaddr; - } - // Execute it - status = func(&BlockDst, jitcpu); - Py_DECREF(retaddr); - retaddr = PyLong_FromUnsignedLongLong(BlockDst.address); - - // Check exception - if (status) - return retaddr; - - // Check stop offsets - if (PySet_Contains(stop_offsets, retaddr)) - return retaddr; - } -} - - - -static PyMethodDef GccMethods[] = { - {"gcc_exec_block", gcc_exec_block, METH_VARARGS, - "gcc exec block"}, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; - - - -MOD_INIT(Jitgcc) -{ - PyObject *module = NULL; - - MOD_DEF(module, "Jitgcc", "gcc module", GccMethods); - - RET_MODULE; -} diff --git a/miasm/jitter/Jitllvm.c b/miasm/jitter/Jitllvm.c deleted file mode 100644 index 3420c254..00000000 --- a/miasm/jitter/Jitllvm.c +++ /dev/null @@ -1,96 +0,0 @@ -#include <Python.h> - -#include <inttypes.h> - -#include <stdint.h> -#include "compat_py23.h" -#include "queue.h" -#include "vm_mngr.h" -#include "bn.h" -#include "vm_mngr_py.h" -#include "JitCore.h" -// Needed to get the JitCpu.cpu offset, arch independent -#include "arch/JitCore_x86.h" - -PyObject* llvm_exec_block(PyObject* self, PyObject* args) -{ - uint64_t (*func)(void*, void*, void*, uint8_t*); - struct vm_cpu* cpu; - vm_mngr_t* vm; - uint64_t ret; - JitCpu* jitcpu; - uint8_t status; - PyObject* func_py; - PyObject* lbl2ptr; - 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, &stop_offsets, - &max_exec_per_call)) - return NULL; - - cpu = jitcpu->cpu; - vm = &(jitcpu->pyvm->vm_mngr); - /* The loop will decref retaddr always once */ - Py_INCREF(retaddr); - - if (max_exec_per_call == 0) { - do_cpt = 0; - cpt = 1; - } else { - do_cpt = 1; - cpt = max_exec_per_call; - } - - for (;;) { - // Handle cpt - if (cpt == 0) - return retaddr; - if (do_cpt) - cpt --; - - // Get the expected jitted function address - func_py = PyDict_GetItem(lbl2ptr, retaddr); - if (func_py) - func = PyLong_AsVoidPtr((PyObject*) func_py); - else - // retaddr is not jitted yet - return retaddr; - - // Execute it - ret = func((void*) jitcpu, (void*)(intptr_t) cpu, (void*)(intptr_t) vm, &status); - Py_DECREF(retaddr); - retaddr = PyLong_FromUnsignedLongLong(ret); - - // Check exception - if (status) - return retaddr; - - // Check stop offsets - if (PySet_Contains(stop_offsets, retaddr)) - return retaddr; - } -} - - -static PyMethodDef LLVMMethods[] = { - {"llvm_exec_block", llvm_exec_block, METH_VARARGS, - "llvm exec block"}, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; - - - - -MOD_INIT(Jitllvm) -{ - PyObject *module = NULL; - - MOD_DEF(module, "Jitllvm", "llvm module", LLVMMethods); - - RET_MODULE; -} diff --git a/miasm/jitter/__init__.py b/miasm/jitter/__init__.py deleted file mode 100644 index 460e327d..00000000 --- a/miasm/jitter/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"JustInTime compilation feature" diff --git a/miasm/jitter/arch/JitCore_aarch64.c b/miasm/jitter/arch/JitCore_aarch64.c deleted file mode 100644 index 7961f3cc..00000000 --- a/miasm/jitter/arch/JitCore_aarch64.c +++ /dev/null @@ -1,519 +0,0 @@ -#include <Python.h> -#include "structmember.h" -#include <stdint.h> -#include <inttypes.h> -#include "../compat_py23.h" -#include "../queue.h" -#include "../vm_mngr.h" -#include "../bn.h" -#include "../vm_mngr_py.h" -#include "../JitCore.h" -#include "../op_semantics.h" -#include "JitCore_aarch64.h" - - - -reg_dict gpreg_dict[] = { - {.name = "X0", .offset = offsetof(struct vm_cpu, X0), .size = 64}, - {.name = "X1", .offset = offsetof(struct vm_cpu, X1), .size = 64}, - {.name = "X2", .offset = offsetof(struct vm_cpu, X2), .size = 64}, - {.name = "X3", .offset = offsetof(struct vm_cpu, X3), .size = 64}, - {.name = "X4", .offset = offsetof(struct vm_cpu, X4), .size = 64}, - {.name = "X5", .offset = offsetof(struct vm_cpu, X5), .size = 64}, - {.name = "X6", .offset = offsetof(struct vm_cpu, X6), .size = 64}, - {.name = "X7", .offset = offsetof(struct vm_cpu, X7), .size = 64}, - {.name = "X8", .offset = offsetof(struct vm_cpu, X8), .size = 64}, - {.name = "X9", .offset = offsetof(struct vm_cpu, X9), .size = 64}, - {.name = "X10", .offset = offsetof(struct vm_cpu, X10), .size = 64}, - {.name = "X11", .offset = offsetof(struct vm_cpu, X11), .size = 64}, - {.name = "X12", .offset = offsetof(struct vm_cpu, X12), .size = 64}, - {.name = "X13", .offset = offsetof(struct vm_cpu, X13), .size = 64}, - {.name = "X14", .offset = offsetof(struct vm_cpu, X14), .size = 64}, - {.name = "X15", .offset = offsetof(struct vm_cpu, X15), .size = 64}, - {.name = "X16", .offset = offsetof(struct vm_cpu, X16), .size = 64}, - {.name = "X17", .offset = offsetof(struct vm_cpu, X17), .size = 64}, - {.name = "X18", .offset = offsetof(struct vm_cpu, X18), .size = 64}, - {.name = "X19", .offset = offsetof(struct vm_cpu, X19), .size = 64}, - {.name = "X20", .offset = offsetof(struct vm_cpu, X20), .size = 64}, - {.name = "X21", .offset = offsetof(struct vm_cpu, X21), .size = 64}, - {.name = "X22", .offset = offsetof(struct vm_cpu, X22), .size = 64}, - {.name = "X23", .offset = offsetof(struct vm_cpu, X23), .size = 64}, - {.name = "X24", .offset = offsetof(struct vm_cpu, X24), .size = 64}, - {.name = "X25", .offset = offsetof(struct vm_cpu, X25), .size = 64}, - {.name = "X26", .offset = offsetof(struct vm_cpu, X26), .size = 64}, - {.name = "X27", .offset = offsetof(struct vm_cpu, X27), .size = 64}, - {.name = "X28", .offset = offsetof(struct vm_cpu, X28), .size = 64}, - {.name = "X29", .offset = offsetof(struct vm_cpu, X29), .size = 64}, - {.name = "LR", .offset = offsetof(struct vm_cpu, LR), .size = 64}, - - {.name = "SP", .offset = offsetof(struct vm_cpu, SP), .size = 64}, - {.name = "PC", .offset = offsetof(struct vm_cpu, PC), .size = 64}, - - {.name = "zf", .offset = offsetof(struct vm_cpu, zf), .size = 8}, - {.name = "nf", .offset = offsetof(struct vm_cpu, nf), .size = 8}, - {.name = "of", .offset = offsetof(struct vm_cpu, of), .size = 8}, - {.name = "cf", .offset = offsetof(struct vm_cpu, cf), .size = 8}, - - {.name = "exception_flags", .offset = offsetof(struct vm_cpu, exception_flags), .size = 32}, - {.name = "interrupt_num", .offset = offsetof(struct vm_cpu, interrupt_num), .size = 32}, - -}; - -/************************** JitCpu object **************************/ - - - - -PyObject* cpu_get_gpreg(JitCpu* self) -{ - PyObject *dict = PyDict_New(); - PyObject *o; - - get_reg(X0); - get_reg(X1); - get_reg(X2); - get_reg(X3); - get_reg(X4); - get_reg(X5); - get_reg(X6); - get_reg(X7); - get_reg(X8); - get_reg(X9); - get_reg(X10); - get_reg(X11); - get_reg(X12); - get_reg(X13); - get_reg(X14); - get_reg(X15); - get_reg(X16); - get_reg(X17); - get_reg(X18); - get_reg(X19); - get_reg(X20); - get_reg(X21); - get_reg(X22); - get_reg(X23); - get_reg(X24); - get_reg(X25); - get_reg(X26); - get_reg(X27); - get_reg(X28); - get_reg(X29); - get_reg(LR); - get_reg(SP); - get_reg(PC); - - get_reg(zf); - get_reg(nf); - get_reg(of); - get_reg(cf); - - return dict; -} - - - -PyObject* cpu_set_gpreg(JitCpu* self, PyObject *args) -{ - PyObject* dict; - PyObject *d_key, *d_value = NULL; - Py_ssize_t pos = 0; - const char *d_key_name; - uint32_t val32; - uint64_t val64; - unsigned int i, found; - - if (!PyArg_ParseTuple(args, "O", &dict)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - if(!PyDict_Check(dict)) - RAISE(PyExc_TypeError, "arg must be dict"); - while(PyDict_Next(dict, &pos, &d_key, &d_value)){ - PyGetStr(d_key_name, d_key); - found = 0; - for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){ - if (strcmp(d_key_name, gpreg_dict[i].name)) - continue; - found = 1; - switch (gpreg_dict[i].size) { - default: - RAISE(PyExc_TypeError, "Unsupported size"); - break; - case 32: - PyGetInt_uint32_t(d_value, val32); - *((uint32_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val32; - break; - case 64: - PyGetInt_uint64_t(d_value, val64); - *((uint64_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val64; - break; - } - } - - if (found) - continue; - fprintf(stderr, "unknown key: %s\n", d_key_name); - RAISE(PyExc_ValueError, "unknown reg"); - } - Py_INCREF(Py_None); - return Py_None; -} - - -PyObject * cpu_init_regs(JitCpu* self) -{ - memset(self->cpu, 0, sizeof(struct vm_cpu)); - - Py_INCREF(Py_None); - return Py_None; -} - -void dump_gpregs(struct vm_cpu* vmcpu) -{ - printf("X0 %.16"PRIX64" X1 %.16"PRIX64" X2 %.16"PRIX64" X3 %.16"PRIX64" "\ - "X4 %.16"PRIX64" X5 %.16"PRIX64" X6 %.16"PRIX64" X7 %.16"PRIX64"\n", - vmcpu->X0, vmcpu->X1, vmcpu->X2, vmcpu->X3, vmcpu->X4, vmcpu->X5, vmcpu->X6, vmcpu->X7); - printf("X8 %.16"PRIX64" X9 %.16"PRIX64" X10 %.16"PRIX64" X11 %.16"PRIX64" "\ - "X12 %.16"PRIX64" X13 %.16"PRIX64" X14 %.16"PRIX64" X15 %.16"PRIX64"\n", - vmcpu->X8, vmcpu->X9, vmcpu->X10, vmcpu->X11, - vmcpu->X12, vmcpu->X13, vmcpu->X14, vmcpu->X15); - printf("X16 %.16"PRIX64" X17 %.16"PRIX64" X18 %.16"PRIX64" X19 %.16"PRIX64" "\ - "X20 %.16"PRIX64" X21 %.16"PRIX64" X22 %.16"PRIX64" X23 %.16"PRIX64"\n", - vmcpu->X16, vmcpu->X17, vmcpu->X18, vmcpu->X19, - vmcpu->X20, vmcpu->X21, vmcpu->X22, vmcpu->X23); - printf("X24 %.16"PRIX64" X25 %.16"PRIX64" X26 %.16"PRIX64" X27 %.16"PRIX64" "\ - "X28 %.16"PRIX64" X29 %.16"PRIX64" LR %.16"PRIX64"\n", - vmcpu->X24, vmcpu->X25, vmcpu->X26, vmcpu->X27, - vmcpu->X28, vmcpu->X29, vmcpu->LR); - - - printf("SP %.16"PRIX64" PC %.16"PRIX64" "\ - "zf %"PRIX32" nf %"PRIX32" of %"PRIX32" cf %"PRIX32"\n", - vmcpu->SP, vmcpu->PC, - vmcpu->zf, vmcpu->nf, vmcpu->of, vmcpu->cf); -} - - -PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args) -{ - struct vm_cpu* vmcpu; - - vmcpu = self->cpu; - dump_gpregs(vmcpu); - Py_INCREF(Py_None); - return Py_None; -} - - -PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args) -{ - return cpu_dump_gpregs(self, args); -} - - -PyObject* cpu_set_exception(JitCpu* self, PyObject* args) -{ - PyObject *item1; - uint32_t exception_flags; - - if (!PyArg_ParseTuple(args, "O", &item1)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint32_t(item1, exception_flags); - - ((struct vm_cpu*)self->cpu)->exception_flags = exception_flags; - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* cpu_get_exception(JitCpu* self, PyObject* args) -{ - return PyLong_FromUnsignedLongLong((uint64_t)(((struct vm_cpu*)self->cpu)->exception_flags)); -} - - -void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) -{ - vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src) -{ - vm_MEM_WRITE_16(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src) -{ - vm_MEM_WRITE_32(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src) -{ - vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - - -static PyMemberDef JitCpu_members[] = { - {NULL} /* Sentinel */ -}; - -static PyMethodDef JitCpu_methods[] = { - {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, - "X"}, - {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, - "X"}, - {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, - "X"}, - {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, - "X"}, - {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, - "X"}, - {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, - "X"}, - {"set_exception", (PyCFunction)cpu_set_exception, METH_VARARGS, - "X"}, - {NULL} /* Sentinel */ -}; - -static int -JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) -{ - self->cpu = malloc(sizeof(struct vm_cpu)); - if (self->cpu == NULL) { - fprintf(stderr, "cannot alloc struct vm_cpu\n"); - exit(EXIT_FAILURE); - } - return 0; -} - - - -getset_reg_u64(X0); -getset_reg_u64(X1); -getset_reg_u64(X2); -getset_reg_u64(X3); -getset_reg_u64(X4); -getset_reg_u64(X5); -getset_reg_u64(X6); -getset_reg_u64(X7); -getset_reg_u64(X8); -getset_reg_u64(X9); -getset_reg_u64(X10); -getset_reg_u64(X11); -getset_reg_u64(X12); -getset_reg_u64(X13); -getset_reg_u64(X14); -getset_reg_u64(X15); -getset_reg_u64(X16); -getset_reg_u64(X17); -getset_reg_u64(X18); -getset_reg_u64(X19); -getset_reg_u64(X20); -getset_reg_u64(X21); -getset_reg_u64(X22); -getset_reg_u64(X23); -getset_reg_u64(X24); -getset_reg_u64(X25); -getset_reg_u64(X26); -getset_reg_u64(X27); -getset_reg_u64(X28); -getset_reg_u64(X29); -getset_reg_u64(LR); -getset_reg_u64(SP); -getset_reg_u64(PC); - -getset_reg_u32(zf); -getset_reg_u32(nf); -getset_reg_u32(of); -getset_reg_u32(cf); - - -getset_reg_u32(exception_flags); -getset_reg_u32(interrupt_num); - - -PyObject* get_gpreg_offset_all(void) -{ - PyObject *dict = PyDict_New(); - PyObject *o; - - get_reg_off(exception_flags); - - get_reg_off(X0); - get_reg_off(X1); - get_reg_off(X2); - get_reg_off(X3); - get_reg_off(X4); - get_reg_off(X5); - get_reg_off(X6); - get_reg_off(X7); - get_reg_off(X8); - get_reg_off(X9); - get_reg_off(X10); - get_reg_off(X11); - get_reg_off(X12); - get_reg_off(X13); - get_reg_off(X14); - get_reg_off(X15); - get_reg_off(X16); - get_reg_off(X17); - get_reg_off(X18); - get_reg_off(X19); - get_reg_off(X20); - get_reg_off(X21); - get_reg_off(X22); - get_reg_off(X23); - get_reg_off(X24); - get_reg_off(X25); - get_reg_off(X26); - get_reg_off(X27); - get_reg_off(X28); - get_reg_off(X29); - get_reg_off(LR); - get_reg_off(SP); - get_reg_off(PC); - - /* eflag */ - get_reg_off(zf); - get_reg_off(nf); - get_reg_off(of); - get_reg_off(cf); - - return dict; -} - - -static PyGetSetDef JitCpu_getseters[] = { - {"vmmngr", - (getter)JitCpu_get_vmmngr, (setter)JitCpu_set_vmmngr, - "vmmngr", - NULL}, - - {"jitter", - (getter)JitCpu_get_jitter, (setter)JitCpu_set_jitter, - "jitter", - NULL}, - - - - {"X0" , (getter)JitCpu_get_X0 , (setter)JitCpu_set_X0 , "X0" , NULL}, - {"X1" , (getter)JitCpu_get_X1 , (setter)JitCpu_set_X1 , "X1" , NULL}, - {"X2" , (getter)JitCpu_get_X2 , (setter)JitCpu_set_X2 , "X2" , NULL}, - {"X3" , (getter)JitCpu_get_X3 , (setter)JitCpu_set_X3 , "X3" , NULL}, - {"X4" , (getter)JitCpu_get_X4 , (setter)JitCpu_set_X4 , "X4" , NULL}, - {"X5" , (getter)JitCpu_get_X5 , (setter)JitCpu_set_X5 , "X5" , NULL}, - {"X6" , (getter)JitCpu_get_X6 , (setter)JitCpu_set_X6 , "X6" , NULL}, - {"X7" , (getter)JitCpu_get_X7 , (setter)JitCpu_set_X7 , "X7" , NULL}, - {"X8" , (getter)JitCpu_get_X8 , (setter)JitCpu_set_X8 , "X8" , NULL}, - {"X9" , (getter)JitCpu_get_X9 , (setter)JitCpu_set_X9 , "X9" , NULL}, - - {"X10" , (getter)JitCpu_get_X10 , (setter)JitCpu_set_X10 , "X10" , NULL}, - {"X11" , (getter)JitCpu_get_X11 , (setter)JitCpu_set_X11 , "X11" , NULL}, - {"X12" , (getter)JitCpu_get_X12 , (setter)JitCpu_set_X12 , "X12" , NULL}, - {"X13" , (getter)JitCpu_get_X13 , (setter)JitCpu_set_X13 , "X13" , NULL}, - {"X14" , (getter)JitCpu_get_X14 , (setter)JitCpu_set_X14 , "X14" , NULL}, - {"X15" , (getter)JitCpu_get_X15 , (setter)JitCpu_set_X15 , "X15" , NULL}, - {"X16" , (getter)JitCpu_get_X16 , (setter)JitCpu_set_X16 , "X16" , NULL}, - {"X17" , (getter)JitCpu_get_X17 , (setter)JitCpu_set_X17 , "X17" , NULL}, - {"X18" , (getter)JitCpu_get_X18 , (setter)JitCpu_set_X18 , "X18" , NULL}, - {"X19" , (getter)JitCpu_get_X19 , (setter)JitCpu_set_X19 , "X19" , NULL}, - - {"X20" , (getter)JitCpu_get_X20 , (setter)JitCpu_set_X20 , "X20" , NULL}, - {"X21" , (getter)JitCpu_get_X21 , (setter)JitCpu_set_X21 , "X21" , NULL}, - {"X22" , (getter)JitCpu_get_X22 , (setter)JitCpu_set_X22 , "X22" , NULL}, - {"X23" , (getter)JitCpu_get_X23 , (setter)JitCpu_set_X23 , "X23" , NULL}, - {"X24" , (getter)JitCpu_get_X24 , (setter)JitCpu_set_X24 , "X24" , NULL}, - {"X25" , (getter)JitCpu_get_X25 , (setter)JitCpu_set_X25 , "X25" , NULL}, - {"X26" , (getter)JitCpu_get_X26 , (setter)JitCpu_set_X26 , "X26" , NULL}, - {"X27" , (getter)JitCpu_get_X27 , (setter)JitCpu_set_X27 , "X27" , NULL}, - {"X28" , (getter)JitCpu_get_X28 , (setter)JitCpu_set_X28 , "X28" , NULL}, - {"X29" , (getter)JitCpu_get_X29 , (setter)JitCpu_set_X29 , "X29" , NULL}, - - {"LR" , (getter)JitCpu_get_LR , (setter)JitCpu_set_LR , "LR" , NULL}, - - - - {"SP" , (getter)JitCpu_get_SP , (setter)JitCpu_set_SP , "SP" , NULL}, - {"PC" , (getter)JitCpu_get_PC , (setter)JitCpu_set_PC , "PC" , NULL}, - - {"zf", (getter)JitCpu_get_zf, (setter)JitCpu_set_zf, "zf", NULL}, - {"nf", (getter)JitCpu_get_nf, (setter)JitCpu_set_nf, "nf", NULL}, - {"of", (getter)JitCpu_get_of, (setter)JitCpu_set_of, "of", NULL}, - {"cf", (getter)JitCpu_get_cf, (setter)JitCpu_set_cf, "cf", NULL}, - - {"exception_flags", (getter)JitCpu_get_exception_flags, (setter)JitCpu_set_exception_flags, "exception_flags", NULL}, - {"interrupt_num", (getter)JitCpu_get_interrupt_num, (setter)JitCpu_set_interrupt_num, "interrupt_num", NULL}, - - {NULL} /* Sentinel */ -}; - - -static PyTypeObject JitCpuType = { - PyVarObject_HEAD_INIT(NULL, 0) - "JitCore_aarch64.JitCpu", /*tp_name*/ - sizeof(JitCpu), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)JitCpu_dealloc,/*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "JitCpu objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - JitCpu_methods, /* tp_methods */ - JitCpu_members, /* tp_members */ - JitCpu_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)JitCpu_init, /* tp_init */ - 0, /* tp_alloc */ - JitCpu_new, /* tp_new */ -}; - - - -static PyMethodDef JitCore_aarch64_Methods[] = { - {"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS}, - {NULL, NULL, 0, NULL} /* Sentinel */ - -}; - - - -MOD_INIT(JitCore_aarch64) -{ - PyObject *module = NULL; - - MOD_DEF(module, "JitCore_aarch64", "JitCore_aarch64 module", JitCore_aarch64_Methods); - - if (module == NULL) - RET_MODULE; - - if (PyType_Ready(&JitCpuType) < 0) - RET_MODULE; - - Py_INCREF(&JitCpuType); - if (PyModule_AddObject(module, "JitCpu", (PyObject *)&JitCpuType) < 0) - RET_MODULE; - - RET_MODULE; -} - diff --git a/miasm/jitter/arch/JitCore_aarch64.h b/miasm/jitter/arch/JitCore_aarch64.h deleted file mode 100644 index 975a93ec..00000000 --- a/miasm/jitter/arch/JitCore_aarch64.h +++ /dev/null @@ -1,57 +0,0 @@ - -struct vm_cpu { - uint32_t exception_flags; - uint32_t interrupt_num; - - /* gpregs */ - - uint64_t X0; - uint64_t X1; - uint64_t X2; - uint64_t X3; - uint64_t X4; - uint64_t X5; - uint64_t X6; - uint64_t X7; - uint64_t X8; - uint64_t X9; - uint64_t X10; - uint64_t X11; - uint64_t X12; - uint64_t X13; - uint64_t X14; - uint64_t X15; - uint64_t X16; - uint64_t X17; - uint64_t X18; - uint64_t X19; - uint64_t X20; - uint64_t X21; - uint64_t X22; - uint64_t X23; - uint64_t X24; - uint64_t X25; - uint64_t X26; - uint64_t X27; - uint64_t X28; - uint64_t X29; - uint64_t LR; - uint64_t SP; - - uint64_t PC; - - /* eflag */ - uint32_t zf; - uint32_t nf; - uint32_t of; - uint32_t cf; -}; - -_MIASM_EXPORT void dump_gpregs(struct vm_cpu* vmcpu); - -_MIASM_EXPORT void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src); -_MIASM_EXPORT void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src); -_MIASM_EXPORT void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src); -_MIASM_EXPORT void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src); - -#define RETURN_PC return BlockDst; diff --git a/miasm/jitter/arch/JitCore_arm.c b/miasm/jitter/arch/JitCore_arm.c deleted file mode 100644 index b39ae4d2..00000000 --- a/miasm/jitter/arch/JitCore_arm.c +++ /dev/null @@ -1,453 +0,0 @@ -#include <Python.h> -#include "structmember.h" -#include <stdint.h> -#include <inttypes.h> -#include "../compat_py23.h" -#include "../queue.h" -#include "../vm_mngr.h" -#include "../bn.h" -#include "../vm_mngr_py.h" -#include "../JitCore.h" -#include "../op_semantics.h" -#include "JitCore_arm.h" - - - -reg_dict gpreg_dict[] = { - {.name = "R0", .offset = offsetof(struct vm_cpu, R0), .size = 32}, - {.name = "R1", .offset = offsetof(struct vm_cpu, R1), .size = 32}, - {.name = "R2", .offset = offsetof(struct vm_cpu, R2), .size = 32}, - {.name = "R3", .offset = offsetof(struct vm_cpu, R3), .size = 32}, - {.name = "R4", .offset = offsetof(struct vm_cpu, R4), .size = 32}, - {.name = "R5", .offset = offsetof(struct vm_cpu, R5), .size = 32}, - {.name = "R6", .offset = offsetof(struct vm_cpu, R6), .size = 32}, - {.name = "R7", .offset = offsetof(struct vm_cpu, R7), .size = 32}, - {.name = "R8", .offset = offsetof(struct vm_cpu, R8), .size = 32}, - {.name = "R9", .offset = offsetof(struct vm_cpu, R9), .size = 32}, - {.name = "R10", .offset = offsetof(struct vm_cpu, R10), .size = 32}, - {.name = "R11", .offset = offsetof(struct vm_cpu, R11), .size = 32}, - {.name = "R12", .offset = offsetof(struct vm_cpu, R12), .size = 32}, - {.name = "SP", .offset = offsetof(struct vm_cpu, SP), .size = 32}, - {.name = "LR", .offset = offsetof(struct vm_cpu, LR), .size = 32}, - {.name = "PC", .offset = offsetof(struct vm_cpu, PC), .size = 32}, - - {.name = "zf", .offset = offsetof(struct vm_cpu, zf), .size = 8}, - {.name = "nf", .offset = offsetof(struct vm_cpu, nf), .size = 8}, - {.name = "of", .offset = offsetof(struct vm_cpu, of), .size = 8}, - {.name = "cf", .offset = offsetof(struct vm_cpu, cf), .size = 8}, - - {.name = "ge0", .offset = offsetof(struct vm_cpu, ge0), .size = 8}, - {.name = "ge1", .offset = offsetof(struct vm_cpu, ge1), .size = 8}, - {.name = "ge2", .offset = offsetof(struct vm_cpu, ge2), .size = 8}, - {.name = "ge3", .offset = offsetof(struct vm_cpu, ge3), .size = 8}, - - {.name = "exception_flags", .offset = offsetof(struct vm_cpu, exception_flags), .size = 32}, - {.name = "interrupt_num", .offset = offsetof(struct vm_cpu, interrupt_num), .size = 32}, -}; - -/************************** JitCpu object **************************/ - - - - -PyObject* cpu_get_gpreg(JitCpu* self) -{ - PyObject *dict = PyDict_New(); - PyObject *o; - - get_reg(R0); - get_reg(R1); - get_reg(R2); - get_reg(R3); - get_reg(R4); - get_reg(R5); - get_reg(R6); - get_reg(R7); - get_reg(R8); - get_reg(R9); - get_reg(R10); - get_reg(R11); - get_reg(R12); - get_reg(SP); - get_reg(LR); - get_reg(PC); - - get_reg(zf); - get_reg(nf); - get_reg(of); - get_reg(cf); - - get_reg(ge0); - get_reg(ge1); - get_reg(ge2); - get_reg(ge3); - - return dict; -} - - - -PyObject* cpu_set_gpreg(JitCpu* self, PyObject *args) -{ - PyObject* dict; - PyObject *d_key, *d_value = NULL; - Py_ssize_t pos = 0; - const char *d_key_name; - uint32_t val; - unsigned int i, found; - - if (!PyArg_ParseTuple(args, "O", &dict)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - if(!PyDict_Check(dict)) - RAISE(PyExc_TypeError, "arg must be dict"); - while(PyDict_Next(dict, &pos, &d_key, &d_value)){ - PyGetStr(d_key_name, d_key); - PyGetInt_uint32_t(d_value, val); - - found = 0; - for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){ - if (strcmp(d_key_name, gpreg_dict[i].name)) - continue; - *((uint32_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val; - found = 1; - break; - } - - if (found) - continue; - fprintf(stderr, "unknown key: %s\n", d_key_name); - RAISE(PyExc_ValueError, "unknown reg"); - } - Py_INCREF(Py_None); - return Py_None; -} - - -PyObject * cpu_init_regs(JitCpu* self) -{ - memset(self->cpu, 0, sizeof(struct vm_cpu)); - - Py_INCREF(Py_None); - return Py_None; -} - -void dump_gpregs(struct vm_cpu* vmcpu) -{ - printf("R0 %.8"PRIX32" R1 %.8"PRIX32" R2 %.8"PRIX32" R3 %.8"PRIX32" ", - vmcpu->R0, vmcpu->R1, vmcpu->R2, vmcpu->R3); - printf("R4 %.8"PRIX32" R5 %.8"PRIX32" R6 %.8"PRIX32" R7 %.8"PRIX32"\n", - vmcpu->R4, vmcpu->R5, vmcpu->R6, vmcpu->R7); - printf("R8 %.8"PRIX32" R9 %.8"PRIX32" R10 %.8"PRIX32" R11 %.8"PRIX32" ", - vmcpu->R8, vmcpu->R9, vmcpu->R10, vmcpu->R11); - printf("R12 %.8"PRIX32" SP %.8"PRIX32" LR %.8"PRIX32" PC %.8"PRIX32" ", - vmcpu->R12, vmcpu->SP, vmcpu->LR, vmcpu->PC); - printf("zf %"PRIX32" nf %"PRIX32" of %"PRIX32" cf %"PRIX32"\n", - vmcpu->zf, vmcpu->nf, vmcpu->of, vmcpu->cf); -} - - -PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args) -{ - struct vm_cpu* vmcpu; - - vmcpu = self->cpu; - dump_gpregs(vmcpu); - Py_INCREF(Py_None); - return Py_None; -} - - -PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args) -{ - return cpu_dump_gpregs(self, args); -} - - - -PyObject* cpu_set_exception(JitCpu* self, PyObject* args) -{ - PyObject *item1; - uint32_t exception_flags; - - if (!PyArg_ParseTuple(args, "O", &item1)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint32_t(item1, exception_flags); - - ((struct vm_cpu*)self->cpu)->exception_flags = exception_flags; - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* cpu_get_exception(JitCpu* self, PyObject* args) -{ - return PyLong_FromUnsignedLongLong((uint64_t)(((struct vm_cpu*)self->cpu)->exception_flags)); -} - -void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) -{ - vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src) -{ - vm_MEM_WRITE_16(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src) -{ - vm_MEM_WRITE_32(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src) -{ - vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -PyObject* cpu_set_interrupt_num(JitCpu* self, PyObject* args) -{ - PyObject *item1; - uint32_t exception_flags; - - if (!PyArg_ParseTuple(args, "O", &item1)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint32_t(item1, exception_flags); - - ((struct vm_cpu*)self->cpu)->interrupt_num = exception_flags; - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* cpu_get_interrupt_num(JitCpu* self, PyObject* args) -{ - return PyLong_FromUnsignedLongLong((uint64_t)(((struct vm_cpu*)self->cpu)->interrupt_num)); -} - -static PyMemberDef JitCpu_members[] = { - {NULL} /* Sentinel */ -}; - -static PyMethodDef JitCpu_methods[] = { - {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, - "X"}, - {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, - "X"}, - {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, - "X"}, - {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, - "X"}, - {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, - "X"}, - {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, - "X"}, - {"set_exception", (PyCFunction)cpu_set_exception, METH_VARARGS, - "X"}, - {"get_interrupt_num", (PyCFunction)cpu_get_interrupt_num, METH_VARARGS, - "X"}, - {"set_interrupt_num", (PyCFunction)cpu_set_interrupt_num, METH_VARARGS, - "X"}, - {NULL} /* Sentinel */ -}; - -static int -JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) -{ - self->cpu = malloc(sizeof(struct vm_cpu)); - if (self->cpu == NULL) { - fprintf(stderr, "cannot alloc struct vm_cpu\n"); - exit(EXIT_FAILURE); - } - return 0; -} - -getset_reg_u32(R0); -getset_reg_u32(R1); -getset_reg_u32(R2); -getset_reg_u32(R3); -getset_reg_u32(R4); -getset_reg_u32(R5); -getset_reg_u32(R6); -getset_reg_u32(R7); -getset_reg_u32(R8); -getset_reg_u32(R9); -getset_reg_u32(R10); -getset_reg_u32(R11); -getset_reg_u32(R12); -getset_reg_u32(SP); -getset_reg_u32(LR); -getset_reg_u32(PC); - -getset_reg_u32(zf); -getset_reg_u32(nf); -getset_reg_u32(of); -getset_reg_u32(cf); - -getset_reg_u32(ge0); -getset_reg_u32(ge1); -getset_reg_u32(ge2); -getset_reg_u32(ge3); - -getset_reg_u32(exception_flags); -getset_reg_u32(interrupt_num); - -PyObject* get_gpreg_offset_all(void) -{ - PyObject *dict = PyDict_New(); - PyObject *o; - - get_reg_off(exception_flags); - get_reg_off(interrupt_num); - - get_reg_off(R0); - get_reg_off(R1); - get_reg_off(R2); - get_reg_off(R3); - get_reg_off(R4); - get_reg_off(R5); - get_reg_off(R6); - get_reg_off(R7); - get_reg_off(R8); - get_reg_off(R9); - get_reg_off(R10); - get_reg_off(R11); - get_reg_off(R12); - get_reg_off(SP); - get_reg_off(LR); - get_reg_off(PC); - - /* eflag */ - get_reg_off(zf); - get_reg_off(nf); - get_reg_off(of); - get_reg_off(cf); - - get_reg_off(ge0); - get_reg_off(ge1); - get_reg_off(ge2); - get_reg_off(ge3); - - return dict; -} - -static PyGetSetDef JitCpu_getseters[] = { - {"vmmngr", - (getter)JitCpu_get_vmmngr, (setter)JitCpu_set_vmmngr, - "vmmngr", - NULL}, - - {"jitter", - (getter)JitCpu_get_jitter, (setter)JitCpu_set_jitter, - "jitter", - NULL}, - - - - {"R0" , (getter)JitCpu_get_R0 , (setter)JitCpu_set_R0 , "R0" , NULL}, - {"R1" , (getter)JitCpu_get_R1 , (setter)JitCpu_set_R1 , "R1" , NULL}, - {"R2" , (getter)JitCpu_get_R2 , (setter)JitCpu_set_R2 , "R2" , NULL}, - {"R3" , (getter)JitCpu_get_R3 , (setter)JitCpu_set_R3 , "R3" , NULL}, - {"R4" , (getter)JitCpu_get_R4 , (setter)JitCpu_set_R4 , "R4" , NULL}, - {"R5" , (getter)JitCpu_get_R5 , (setter)JitCpu_set_R5 , "R5" , NULL}, - {"R6" , (getter)JitCpu_get_R6 , (setter)JitCpu_set_R6 , "R6" , NULL}, - {"R7" , (getter)JitCpu_get_R7 , (setter)JitCpu_set_R7 , "R7" , NULL}, - {"R8" , (getter)JitCpu_get_R8 , (setter)JitCpu_set_R8 , "R8" , NULL}, - {"R9" , (getter)JitCpu_get_R9 , (setter)JitCpu_set_R9 , "R9" , NULL}, - {"R10", (getter)JitCpu_get_R10, (setter)JitCpu_set_R10, "R10", NULL}, - {"R11", (getter)JitCpu_get_R11, (setter)JitCpu_set_R11, "R11", NULL}, - {"R12", (getter)JitCpu_get_R12, (setter)JitCpu_set_R12, "R12", NULL}, - {"SP" , (getter)JitCpu_get_SP , (setter)JitCpu_set_SP , "SP" , NULL}, - {"LR" , (getter)JitCpu_get_LR , (setter)JitCpu_set_LR , "LR" , NULL}, - {"PC" , (getter)JitCpu_get_PC , (setter)JitCpu_set_PC , "PC" , NULL}, - - {"zf", (getter)JitCpu_get_zf, (setter)JitCpu_set_zf, "zf", NULL}, - {"nf", (getter)JitCpu_get_nf, (setter)JitCpu_set_nf, "nf", NULL}, - {"of", (getter)JitCpu_get_of, (setter)JitCpu_set_of, "of", NULL}, - {"cf", (getter)JitCpu_get_cf, (setter)JitCpu_set_cf, "cf", NULL}, - - {"ge0", (getter)JitCpu_get_ge0, (setter)JitCpu_set_ge0, "ge0", NULL}, - {"ge1", (getter)JitCpu_get_ge1, (setter)JitCpu_set_ge1, "ge1", NULL}, - {"ge2", (getter)JitCpu_get_ge2, (setter)JitCpu_set_ge2, "ge2", NULL}, - {"ge3", (getter)JitCpu_get_ge3, (setter)JitCpu_set_ge3, "ge3", NULL}, - - {"exception_flags", (getter)JitCpu_get_exception_flags, (setter)JitCpu_set_exception_flags, "exception_flags", NULL}, - {"interrupt_num", (getter)JitCpu_get_interrupt_num, (setter)JitCpu_set_interrupt_num, "interrupt_num", NULL}, - - {NULL} /* Sentinel */ -}; - - -static PyTypeObject JitCpuType = { - PyVarObject_HEAD_INIT(NULL, 0) - "JitCore_arm.JitCpu", /*tp_name*/ - sizeof(JitCpu), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)JitCpu_dealloc,/*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "JitCpu objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - JitCpu_methods, /* tp_methods */ - JitCpu_members, /* tp_members */ - JitCpu_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)JitCpu_init, /* tp_init */ - 0, /* tp_alloc */ - JitCpu_new, /* tp_new */ -}; - - - -static PyMethodDef JitCore_arm_Methods[] = { - - /* - - */ - {"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS}, - {NULL, NULL, 0, NULL} /* Sentinel */ - -}; - - - -MOD_INIT(JitCore_arm) -{ - PyObject *module = NULL; - - MOD_DEF(module, "JitCore_arm", "JitCore_arm module", JitCore_arm_Methods); - - if (module == NULL) - RET_MODULE; - - if (PyType_Ready(&JitCpuType) < 0) - RET_MODULE; - - Py_INCREF(&JitCpuType); - if (PyModule_AddObject(module, "JitCpu", (PyObject *)&JitCpuType) < 0) - RET_MODULE; - - RET_MODULE; -} - diff --git a/miasm/jitter/arch/JitCore_arm.h b/miasm/jitter/arch/JitCore_arm.h deleted file mode 100644 index 30a38344..00000000 --- a/miasm/jitter/arch/JitCore_arm.h +++ /dev/null @@ -1,47 +0,0 @@ - -struct vm_cpu { - uint32_t exception_flags; - uint32_t interrupt_num; - - /* gpregs */ - uint32_t R0; - uint32_t R1; - uint32_t R2; - uint32_t R3; - uint32_t R4; - uint32_t R5; - uint32_t R6; - uint32_t R7; - uint32_t R8; - uint32_t R9; - uint32_t R10; - uint32_t R11; - uint32_t R12; - uint32_t SP; - uint32_t LR; - uint32_t PC; - - /* eflag */ - uint32_t zf; - uint32_t nf; - uint32_t of; - uint32_t cf; - - /* ge */ - uint32_t ge0; - uint32_t ge1; - uint32_t ge2; - uint32_t ge3; - - uint32_t bp_num; -}; - - -_MIASM_EXPORT void dump_gpregs(struct vm_cpu* vmcpu); - -_MIASM_EXPORT void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src); -_MIASM_EXPORT void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src); -_MIASM_EXPORT void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src); -_MIASM_EXPORT void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src); - -#define RETURN_PC return BlockDst; diff --git a/miasm/jitter/arch/JitCore_m68k.c b/miasm/jitter/arch/JitCore_m68k.c deleted file mode 100644 index 0989fde1..00000000 --- a/miasm/jitter/arch/JitCore_m68k.c +++ /dev/null @@ -1,467 +0,0 @@ -#include <Python.h> -#include "structmember.h" -#include <stdint.h> -#include <inttypes.h> -#include "../compat_py23.h" -#include "../queue.h" -#include "../vm_mngr.h" -#include "../bn.h" -#include "../vm_mngr_py.h" -#include "../JitCore.h" -#include "../op_semantics.h" -#include "JitCore_m68k.h" - - - -reg_dict gpreg_dict[] = { - {.name = "A0", .offset = offsetof(struct vm_cpu, A0), .size = 32}, - {.name = "A1", .offset = offsetof(struct vm_cpu, A1), .size = 32}, - {.name = "A2", .offset = offsetof(struct vm_cpu, A2), .size = 32}, - {.name = "A3", .offset = offsetof(struct vm_cpu, A3), .size = 32}, - {.name = "A4", .offset = offsetof(struct vm_cpu, A4), .size = 32}, - {.name = "A5", .offset = offsetof(struct vm_cpu, A5), .size = 32}, - {.name = "A6", .offset = offsetof(struct vm_cpu, A6), .size = 32}, - {.name = "SP", .offset = offsetof(struct vm_cpu, SP), .size = 32}, - - {.name = "D0", .offset = offsetof(struct vm_cpu, D0), .size = 32}, - {.name = "D1", .offset = offsetof(struct vm_cpu, D1), .size = 32}, - {.name = "D2", .offset = offsetof(struct vm_cpu, D2), .size = 32}, - {.name = "D3", .offset = offsetof(struct vm_cpu, D3), .size = 32}, - {.name = "D4", .offset = offsetof(struct vm_cpu, D4), .size = 32}, - {.name = "D5", .offset = offsetof(struct vm_cpu, D5), .size = 32}, - {.name = "D6", .offset = offsetof(struct vm_cpu, D6), .size = 32}, - {.name = "D7", .offset = offsetof(struct vm_cpu, D7), .size = 32}, - - {.name = "PC", .offset = offsetof(struct vm_cpu, PC), .size = 32}, - - {.name = "zf", .offset = offsetof(struct vm_cpu, zf), .size = 8}, - {.name = "nf", .offset = offsetof(struct vm_cpu, nf), .size = 8}, - {.name = "vf", .offset = offsetof(struct vm_cpu, vf), .size = 8}, - {.name = "cf", .offset = offsetof(struct vm_cpu, cf), .size = 8}, - {.name = "xf", .offset = offsetof(struct vm_cpu, xf), .size = 8}, - - {.name = "exception_flags", .offset = offsetof(struct vm_cpu, exception_flags), .size = 32}, - {.name = "interrupt_num", .offset = offsetof(struct vm_cpu, interrupt_num), .size = 32}, -}; - -/************************** JitCpu object **************************/ - - - - -PyObject* cpu_get_gpreg(JitCpu* self) -{ - PyObject *dict = PyDict_New(); - PyObject *o; - - get_reg(A0); - get_reg(A1); - get_reg(A2); - get_reg(A3); - get_reg(A4); - get_reg(A5); - get_reg(A6); - get_reg(SP); - - get_reg(D0); - get_reg(D1); - get_reg(D2); - get_reg(D3); - get_reg(D4); - get_reg(D5); - get_reg(D6); - get_reg(D7); - - get_reg(PC); - - get_reg(zf); - get_reg(nf); - get_reg(vf); - get_reg(cf); - get_reg(xf); - - return dict; -} - - - -PyObject* cpu_set_gpreg(JitCpu* self, PyObject *args) -{ - PyObject* dict; - PyObject *d_key, *d_value = NULL; - Py_ssize_t pos = 0; - const char *d_key_name; - uint32_t val; - unsigned int i, found; - - if (!PyArg_ParseTuple(args, "O", &dict)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - if(!PyDict_Check(dict)) - RAISE(PyExc_TypeError, "arg must be dict"); - while(PyDict_Next(dict, &pos, &d_key, &d_value)){ - PyGetStr(d_key_name, d_key); - PyGetInt_uint32_t(d_value, val); - - found = 0; - for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){ - if (strcmp(d_key_name, gpreg_dict[i].name)) - continue; - *((uint32_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val; - found = 1; - break; - } - - if (found) - continue; - fprintf(stderr, "unknown key: %s\n", d_key_name); - RAISE(PyExc_ValueError, "unknown reg"); - } - Py_INCREF(Py_None); - return Py_None; -} - - -PyObject * cpu_init_regs(JitCpu* self) -{ - memset(self->cpu, 0, sizeof(struct vm_cpu)); - - Py_INCREF(Py_None); - return Py_None; -} - - -uint64_t segm2addr(JitCpu* jitcpu, uint64_t segm, uint64_t addr) -{ - return addr; -} - -void dump_gpregs(struct vm_cpu* vmcpu) -{ - printf("A0 %.8"PRIX32" A1 %.8"PRIX32" A2 %.8"PRIX32" A3 %.8"PRIX32" ", - vmcpu->A0, vmcpu->A1, vmcpu->A2, vmcpu->A3); - printf("R4 %.8"PRIX32" A5 %.8"PRIX32" A6 %.8"PRIX32" SP %.8"PRIX32"\n", - vmcpu->A4, vmcpu->A5, vmcpu->A6, vmcpu->SP); - - printf("D0 %.8"PRIX32" D1 %.8"PRIX32" D2 %.8"PRIX32" D3 %.8"PRIX32" ", - vmcpu->D0, vmcpu->D1, vmcpu->D2, vmcpu->D3); - printf("R4 %.8"PRIX32" D5 %.8"PRIX32" D6 %.8"PRIX32" D7 %.8"PRIX32"\n", - vmcpu->D4, vmcpu->D5, vmcpu->D6, vmcpu->D7); - - - printf("PC %.8"PRIX32" ", - vmcpu->PC); - printf("zf %"PRIX32" nf %"PRIX32" vf %"PRIX32" cf %"PRIX32" xf %"PRIX32"\n", - vmcpu->zf, vmcpu->nf, vmcpu->vf, vmcpu->cf, vmcpu->xf); -} - -void dump_gpregs_32(struct vm_cpu* vmcpu) -{ - dump_gpregs(vmcpu); -} - -PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args) -{ - struct vm_cpu* vmcpu; - - vmcpu = self->cpu; - dump_gpregs(vmcpu); - Py_INCREF(Py_None); - return Py_None; -} - - -PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args) -{ - return cpu_dump_gpregs(self, args); -} - - - -PyObject* cpu_set_exception(JitCpu* self, PyObject* args) -{ - PyObject *item1; - uint32_t exception_flags; - - if (!PyArg_ParseTuple(args, "O", &item1)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint32_t(item1, exception_flags); - - ((struct vm_cpu*)self->cpu)->exception_flags = exception_flags; - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* cpu_get_exception(JitCpu* self, PyObject* args) -{ - return PyLong_FromUnsignedLongLong((uint64_t)(((struct vm_cpu*)self->cpu)->exception_flags)); -} - -void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) -{ - vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src) -{ - vm_MEM_WRITE_16(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src) -{ - vm_MEM_WRITE_32(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src) -{ - vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -PyObject* cpu_set_interrupt_num(JitCpu* self, PyObject* args) -{ - PyObject *item1; - uint32_t exception_flags; - - if (!PyArg_ParseTuple(args, "O", &item1)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint32_t(item1, exception_flags); - - ((struct vm_cpu*)self->cpu)->interrupt_num = exception_flags; - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* cpu_get_interrupt_num(JitCpu* self, PyObject* args) -{ - return PyLong_FromUnsignedLongLong((uint64_t)(((struct vm_cpu*)self->cpu)->interrupt_num)); -} - -static PyMemberDef JitCpu_members[] = { - {NULL} /* Sentinel */ -}; - -static PyMethodDef JitCpu_methods[] = { - {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, - "X"}, - {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, - "X"}, - {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, - "X"}, - {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, - "X"}, - {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, - "X"}, - {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, - "X"}, - {"set_exception", (PyCFunction)cpu_set_exception, METH_VARARGS, - "X"}, - {"get_interrupt_num", (PyCFunction)cpu_get_interrupt_num, METH_VARARGS, - "X"}, - {"set_interrupt_num", (PyCFunction)cpu_set_interrupt_num, METH_VARARGS, - "X"}, - {NULL} /* Sentinel */ -}; - -static int -JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) -{ - self->cpu = malloc(sizeof(struct vm_cpu)); - if (self->cpu == NULL) { - fprintf(stderr, "cannot alloc struct vm_cpu\n"); - exit(EXIT_FAILURE); - } - return 0; -} - -getset_reg_u32(A0); -getset_reg_u32(A1); -getset_reg_u32(A2); -getset_reg_u32(A3); -getset_reg_u32(A4); -getset_reg_u32(A5); -getset_reg_u32(A6); -getset_reg_u32(SP); - -getset_reg_u32(D0); -getset_reg_u32(D1); -getset_reg_u32(D2); -getset_reg_u32(D3); -getset_reg_u32(D4); -getset_reg_u32(D5); -getset_reg_u32(D6); -getset_reg_u32(D7); -getset_reg_u32(PC); - -getset_reg_u32(zf); -getset_reg_u32(nf); -getset_reg_u32(vf); -getset_reg_u32(cf); -getset_reg_u32(xf); - -getset_reg_u32(exception_flags); -getset_reg_u32(interrupt_num); - -PyObject* get_gpreg_offset_all(void) -{ - PyObject *dict = PyDict_New(); - PyObject *o; - - get_reg_off(exception_flags); - get_reg_off(interrupt_num); - - get_reg_off(A0); - get_reg_off(A1); - get_reg_off(A2); - get_reg_off(A3); - get_reg_off(A4); - get_reg_off(A5); - get_reg_off(A6); - get_reg_off(SP); - - get_reg_off(D0); - get_reg_off(D1); - get_reg_off(D2); - get_reg_off(D3); - get_reg_off(D4); - get_reg_off(D5); - get_reg_off(D6); - get_reg_off(D7); - - get_reg_off(PC); - - /* eflag */ - get_reg_off(zf); - get_reg_off(nf); - get_reg_off(vf); - get_reg_off(cf); - get_reg_off(xf); - - return dict; -} - -static PyGetSetDef JitCpu_getseters[] = { - {"vmmngr", - (getter)JitCpu_get_vmmngr, (setter)JitCpu_set_vmmngr, - "vmmngr", - NULL}, - - {"vmcpu", - (getter)JitCpu_get_vmcpu, (setter)JitCpu_set_vmcpu, - "vmcpu", - NULL}, - - {"jitter", - (getter)JitCpu_get_jitter, (setter)JitCpu_set_jitter, - "jitter", - NULL}, - - - - {"A0" , (getter)JitCpu_get_A0 , (setter)JitCpu_set_A0 , "A0" , NULL}, - {"A1" , (getter)JitCpu_get_A1 , (setter)JitCpu_set_A1 , "A1" , NULL}, - {"A2" , (getter)JitCpu_get_A2 , (setter)JitCpu_set_A2 , "A2" , NULL}, - {"A3" , (getter)JitCpu_get_A3 , (setter)JitCpu_set_A3 , "A3" , NULL}, - {"A4" , (getter)JitCpu_get_A4 , (setter)JitCpu_set_A4 , "A4" , NULL}, - {"A5" , (getter)JitCpu_get_A5 , (setter)JitCpu_set_A5 , "A5" , NULL}, - {"A6" , (getter)JitCpu_get_A6 , (setter)JitCpu_set_A6 , "A6" , NULL}, - {"SP" , (getter)JitCpu_get_SP , (setter)JitCpu_set_SP , "SP" , NULL}, - - {"D0" , (getter)JitCpu_get_D0 , (setter)JitCpu_set_D0 , "D0" , NULL}, - {"D1" , (getter)JitCpu_get_D1 , (setter)JitCpu_set_D1 , "D1" , NULL}, - {"D2" , (getter)JitCpu_get_D2 , (setter)JitCpu_set_D2 , "D2" , NULL}, - {"D3" , (getter)JitCpu_get_D3 , (setter)JitCpu_set_D3 , "D3" , NULL}, - {"D4" , (getter)JitCpu_get_D4 , (setter)JitCpu_set_D4 , "D4" , NULL}, - {"D5" , (getter)JitCpu_get_D5 , (setter)JitCpu_set_D5 , "D5" , NULL}, - {"D6" , (getter)JitCpu_get_D6 , (setter)JitCpu_set_D6 , "D6" , NULL}, - {"D7" , (getter)JitCpu_get_D7 , (setter)JitCpu_set_D7 , "D7" , NULL}, - - {"PC" , (getter)JitCpu_get_PC , (setter)JitCpu_set_PC , "PC" , NULL}, - - {"zf", (getter)JitCpu_get_zf, (setter)JitCpu_set_zf, "zf", NULL}, - {"nf", (getter)JitCpu_get_nf, (setter)JitCpu_set_nf, "nf", NULL}, - {"vf", (getter)JitCpu_get_vf, (setter)JitCpu_set_vf, "vf", NULL}, - {"cf", (getter)JitCpu_get_cf, (setter)JitCpu_set_cf, "cf", NULL}, - {"xf", (getter)JitCpu_get_xf, (setter)JitCpu_set_xf, "xf", NULL}, - - {"exception_flags", (getter)JitCpu_get_exception_flags, (setter)JitCpu_set_exception_flags, "exception_flags", NULL}, - {"interrupt_num", (getter)JitCpu_get_interrupt_num, (setter)JitCpu_set_interrupt_num, "interrupt_num", NULL}, - - {NULL} /* Sentinel */ -}; - - -static PyTypeObject JitCpuType = { - PyVarObject_HEAD_INIT(NULL, 0) - "JitCore_m68k.JitCpu", /*tp_name*/ - sizeof(JitCpu), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)JitCpu_dealloc,/*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "JitCpu objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - JitCpu_methods, /* tp_methods */ - JitCpu_members, /* tp_members */ - JitCpu_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)JitCpu_init, /* tp_init */ - 0, /* tp_alloc */ - JitCpu_new, /* tp_new */ -}; - - - -static PyMethodDef JitCore_m68k_Methods[] = { - - /* - - */ - {"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS}, - {NULL, NULL, 0, NULL} /* Sentinel */ - -}; - - - -MOD_INIT(JitCore_m68k) -{ - PyObject *module = NULL; - - MOD_DEF(module, "JitCore_m68k", "JitCore_m68k module", JitCore_m68k_Methods); - - if (module == NULL) - RET_MODULE; - - if (PyType_Ready(&JitCpuType) < 0) - RET_MODULE; - - Py_INCREF(&JitCpuType); - if (PyModule_AddObject(module, "JitCpu", (PyObject *)&JitCpuType) < 0) - RET_MODULE; - - RET_MODULE; -} - diff --git a/miasm/jitter/arch/JitCore_m68k.h b/miasm/jitter/arch/JitCore_m68k.h deleted file mode 100644 index 6ff6b326..00000000 --- a/miasm/jitter/arch/JitCore_m68k.h +++ /dev/null @@ -1,55 +0,0 @@ - -struct vm_cpu { - uint32_t exception_flags; - uint32_t interrupt_num; - - /* gpregs */ - uint32_t A0; - uint32_t A1; - uint32_t A2; - uint32_t A3; - uint32_t A4; - uint32_t A5; - uint32_t A6; - uint32_t SP; - - uint32_t D0; - uint32_t D1; - uint32_t D2; - uint32_t D3; - uint32_t D4; - uint32_t D5; - uint32_t D6; - uint32_t D7; - - - uint32_t PC; - - /* eflag */ - uint32_t zf; - uint32_t nf; - uint32_t vf; - uint32_t cf; - uint32_t xf; - - uint64_t float_st0; - uint64_t float_st1; - uint64_t float_st2; - uint64_t float_st3; - uint64_t float_st4; - uint64_t float_st5; - uint64_t float_st6; - uint64_t float_st7; - - uint32_t bp_num; -}; - - -_MIASM_EXPORT void dump_gpregs(struct vm_cpu* vmcpu); - -_MIASM_EXPORT void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src); -_MIASM_EXPORT void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src); -_MIASM_EXPORT void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src); -_MIASM_EXPORT void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src); - -#define RETURN_PC return BlockDst; diff --git a/miasm/jitter/arch/JitCore_mep.c b/miasm/jitter/arch/JitCore_mep.c deleted file mode 100644 index 286a12ac..00000000 --- a/miasm/jitter/arch/JitCore_mep.c +++ /dev/null @@ -1,569 +0,0 @@ -// Inspired from JitCore_mep.c - -#include <Python.h> -#include "structmember.h" -#include <stdint.h> - -#include <inttypes.h> -#include "../compat_py23.h" -#include "../queue.h" -#include "../vm_mngr.h" -#include "../bn.h" -#include "../vm_mngr_py.h" -#include "../JitCore.h" -#include "JitCore_mep.h" - - -reg_dict gpreg_dict[] = { - {.name = "R0", .offset = offsetof(struct vm_cpu, R0), .size = 32}, - {.name = "R1", .offset = offsetof(struct vm_cpu, R1), .size = 32}, - {.name = "R2", .offset = offsetof(struct vm_cpu, R2), .size = 32}, - {.name = "R3", .offset = offsetof(struct vm_cpu, R3), .size = 32}, - {.name = "R4", .offset = offsetof(struct vm_cpu, R4), .size = 32}, - {.name = "R5", .offset = offsetof(struct vm_cpu, R5), .size = 32}, - {.name = "R6", .offset = offsetof(struct vm_cpu, R6), .size = 32}, - {.name = "R7", .offset = offsetof(struct vm_cpu, R7), .size = 32}, - {.name = "R8", .offset = offsetof(struct vm_cpu, R8), .size = 32}, - {.name = "R9", .offset = offsetof(struct vm_cpu, R9), .size = 32}, - {.name = "R10", .offset = offsetof(struct vm_cpu, R10), .size = 32}, - {.name = "R11", .offset = offsetof(struct vm_cpu, R11), .size = 32}, - {.name = "R12", .offset = offsetof(struct vm_cpu, R12), .size = 32}, - {.name = "TP", .offset = offsetof(struct vm_cpu, TP), .size = 32}, - {.name = "GP", .offset = offsetof(struct vm_cpu, GP), .size = 32}, - {.name = "SP", .offset = offsetof(struct vm_cpu, SP), .size = 32}, - - {.name = "PC", .offset = offsetof(struct vm_cpu, PC), .size = 32}, - {.name = "LP", .offset = offsetof(struct vm_cpu, LP), .size = 32}, - {.name = "SAR", .offset = offsetof(struct vm_cpu, SAR), .size = 32}, - {.name = "S3", .offset = offsetof(struct vm_cpu, S3), .size = 32}, - {.name = "RPB", .offset = offsetof(struct vm_cpu, RPB), .size = 32}, - {.name = "RPE", .offset = offsetof(struct vm_cpu, RPE), .size = 32}, - {.name = "RPC", .offset = offsetof(struct vm_cpu, RPC), .size = 32}, - {.name = "HI", .offset = offsetof(struct vm_cpu, HI), .size = 32}, - {.name = "LO", .offset = offsetof(struct vm_cpu, LO), .size = 32}, - {.name = "S9", .offset = offsetof(struct vm_cpu, S9), .size = 32}, - {.name = "S10", .offset = offsetof(struct vm_cpu, S10), .size = 32}, - {.name = "S11", .offset = offsetof(struct vm_cpu, S11), .size = 32}, - {.name = "MB0", .offset = offsetof(struct vm_cpu, MB0), .size = 32}, - {.name = "ME0", .offset = offsetof(struct vm_cpu, ME0), .size = 32}, - {.name = "MB1", .offset = offsetof(struct vm_cpu, MB1), .size = 32}, - {.name = "ME1", .offset = offsetof(struct vm_cpu, ME1), .size = 32}, - {.name = "PSW", .offset = offsetof(struct vm_cpu, PSW), .size = 32}, - {.name = "ID", .offset = offsetof(struct vm_cpu, ID), .size = 32}, - {.name = "TMP", .offset = offsetof(struct vm_cpu, TMP), .size = 32}, - {.name = "EPC", .offset = offsetof(struct vm_cpu, EPC), .size = 32}, - {.name = "EXC", .offset = offsetof(struct vm_cpu, EXC), .size = 32}, - {.name = "CFG", .offset = offsetof(struct vm_cpu, CFG), .size = 32}, - {.name = "S22", .offset = offsetof(struct vm_cpu, S22), .size = 32}, - {.name = "NPC", .offset = offsetof(struct vm_cpu, NPC), .size = 32}, - {.name = "DBG", .offset = offsetof(struct vm_cpu, DBG), .size = 32}, - {.name = "DEPC", .offset = offsetof(struct vm_cpu, DEPC), .size = 32}, - {.name = "OPT", .offset = offsetof(struct vm_cpu, OPT), .size = 32}, - {.name = "RCFG", .offset = offsetof(struct vm_cpu, RCFG), .size = 32}, - {.name = "CCFG", .offset = offsetof(struct vm_cpu, CCFG), .size = 32}, - {.name = "S29", .offset = offsetof(struct vm_cpu, S29), .size = 32}, - {.name = "S30", .offset = offsetof(struct vm_cpu, S30), .size = 32}, - {.name = "S31", .offset = offsetof(struct vm_cpu, S31), .size = 32}, - {.name = "S32", .offset = offsetof(struct vm_cpu, S32), .size = 32}, - {.name = "take_jmp", .offset = offsetof(struct vm_cpu, take_jmp), .size = 32}, - {.name = "last_addr", .offset = offsetof(struct vm_cpu, last_addr), .size = 32}, - {.name = "is_repeat_end", .offset = offsetof(struct vm_cpu, is_repeat_end), .size = 32}, - - {.name = "PC_end", .offset = offsetof(struct vm_cpu, PC_end), .size = 32}, - {.name = "RPE_instr_count", .offset = offsetof(struct vm_cpu, RPE_instr_count), .size = 32}, - {.name = "RPC_current", .offset = offsetof(struct vm_cpu, RPC_current), .size = 32}, - -}; - -/************************** JitCpu object **************************/ - - - -PyObject* cpu_get_gpreg(JitCpu* self) -{ - PyObject *dict = PyDict_New(); - PyObject *o; - - get_reg(R0); - get_reg(R1); - get_reg(R2); - get_reg(R3); - get_reg(R4); - get_reg(R5); - get_reg(R6); - get_reg(R7); - get_reg(R8); - get_reg(R9); - get_reg(R10); - get_reg(R11); - get_reg(R12); - get_reg(TP); - get_reg(GP); - get_reg(SP); - - get_reg(PC); - get_reg(LP); - get_reg(SAR); - get_reg(S3); - get_reg(RPB); - get_reg(RPE); - get_reg(RPC); - get_reg(HI); - get_reg(LO); - get_reg(S9); - get_reg(S10); - get_reg(S11); - get_reg(MB0); - get_reg(ME0); - get_reg(MB1); - get_reg(ME1); - get_reg(PSW); - get_reg(ID); - get_reg(TMP); - get_reg(EPC); - get_reg(EXC); - get_reg(CFG); - get_reg(S22); - get_reg(NPC); - get_reg(DBG); - get_reg(DEPC); - get_reg(OPT); - get_reg(RCFG); - get_reg(CCFG); - get_reg(S29); - get_reg(S30); - get_reg(S31); - get_reg(S32); - - get_reg(PC_end); - get_reg(RPE_instr_count); - get_reg(RPC_current); - - - return dict; -} - - -PyObject* cpu_set_gpreg(JitCpu* self, PyObject *args) -{ - PyObject* dict; - PyObject *d_key, *d_value = NULL; - Py_ssize_t pos = 0; - const char *d_key_name; - uint32_t val; - unsigned int i, found; - - if (!PyArg_ParseTuple(args, "O", &dict)) - return NULL; - if(!PyDict_Check(dict)) - RAISE(PyExc_TypeError, "arg must be dict"); - while(PyDict_Next(dict, &pos, &d_key, &d_value)){ - PyGetStr(d_key_name, d_key); - PyGetInt_uint32_t(d_value, val); - - found = 0; - for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){ - if (strcmp(d_key_name, gpreg_dict[i].name)) - continue; - *((uint32_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val; - found = 1; - break; - } - - if (found) - continue; - fprintf(stderr, "unknown key: %s\n", d_key_name); - RAISE(PyExc_ValueError, "unknown reg"); - } - Py_INCREF(Py_None); - return Py_None; -} - - - - -PyObject * cpu_init_regs(JitCpu* self) -{ - memset(self->cpu, 0, sizeof(struct vm_cpu)); - - Py_INCREF(Py_None); - return Py_None; - -} - -void dump_gpregs(struct vm_cpu* vmcpu) -{ - printf("R0 %.4"PRIX32" ", vmcpu->R0); - printf("R1 %.4"PRIX32" ", vmcpu->R1); - printf("R2 %.4"PRIX32" ", vmcpu->R2); - printf("R3 %.4"PRIX32" ", vmcpu->R3); - printf("R4 %.4"PRIX32" ", vmcpu->R4); - printf("R5 %.4"PRIX32" ", vmcpu->R5); - printf("R6 %.4"PRIX32" ", vmcpu->R6); - printf("R7 %.4"PRIX32" ", vmcpu->R7); - printf("R8 %.4"PRIX32" ", vmcpu->R8); - printf("R9 %.4"PRIX32" ", vmcpu->R9); - printf("R10 %.4"PRIX32" ", vmcpu->R10); - printf("R11 %.4"PRIX32" ", vmcpu->R11); - printf("R12 %.4"PRIX32" ", vmcpu->R12); - printf("TP %.4"PRIX32" ", vmcpu->TP); - printf("GP %.4"PRIX32" ", vmcpu->GP); - printf("SP %.4"PRIX32" ", vmcpu->SP); - printf("\n"); -} - - -PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args) -{ - struct vm_cpu* vmcpu; - - vmcpu = self->cpu; - dump_gpregs(vmcpu); - Py_INCREF(Py_None); - return Py_None; -} - -PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args) -{ - return cpu_dump_gpregs(self, args); -} - -PyObject* cpu_set_exception(JitCpu* self, PyObject* args) -{ - PyObject *item1; - uint32_t exception_flags; - - if (!PyArg_ParseTuple(args, "O", &item1)) - return NULL; - - PyGetInt_uint32_t(item1, exception_flags); - - ((struct vm_cpu*)self->cpu)->exception_flags = exception_flags; - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* cpu_get_exception(JitCpu* self, PyObject* args) -{ - return PyLong_FromUnsignedLongLong((uint64_t)(((struct vm_cpu*)self->cpu)->exception_flags)); -} - -void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) -{ - vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src) -{ - vm_MEM_WRITE_16(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src) -{ - vm_MEM_WRITE_32(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src) -{ - vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - - -static PyMemberDef JitCpu_members[] = { - {NULL} /* Sentinel */ -}; - -static PyMethodDef JitCpu_methods[] = { - {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, "X"}, - {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, "X"}, - {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, "X"}, - {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, "X"}, - {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, "X"}, - {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, "X"}, - {"set_exception", (PyCFunction)cpu_set_exception, METH_VARARGS, "X"}, - {NULL} /* Sentinel */ -}; - -static int -JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) -{ - self->cpu = malloc(sizeof(struct vm_cpu)); - if (self->cpu == NULL) { - fprintf(stderr, "cannot alloc struct vm_cpu\n"); - exit(0); - } - return 0; -} - -getset_reg_u32(R0); -getset_reg_u32(R1); -getset_reg_u32(R2); -getset_reg_u32(R3); -getset_reg_u32(R4); -getset_reg_u32(R5); -getset_reg_u32(R6); -getset_reg_u32(R7); -getset_reg_u32(R8); -getset_reg_u32(R9); -getset_reg_u32(R10); -getset_reg_u32(R11); -getset_reg_u32(R12); -getset_reg_u32(TP); -getset_reg_u32(GP); -getset_reg_u32(SP); - -getset_reg_u32(PC); -getset_reg_u32(LP); -getset_reg_u32(SAR); -getset_reg_u32(S3); -getset_reg_u32(RPB); -getset_reg_u32(RPE); -getset_reg_u32(RPC); -getset_reg_u32(HI); -getset_reg_u32(LO); -getset_reg_u32(S9); -getset_reg_u32(S10); -getset_reg_u32(S11); -getset_reg_u32(MB0); -getset_reg_u32(ME0); -getset_reg_u32(MB1); -getset_reg_u32(ME1); -getset_reg_u32(PSW); -getset_reg_u32(ID); -getset_reg_u32(TMP); -getset_reg_u32(EPC); -getset_reg_u32(EXC); -getset_reg_u32(CFG); -getset_reg_u32(S22); -getset_reg_u32(NPC); -getset_reg_u32(DBG); -getset_reg_u32(DEPC); -getset_reg_u32(OPT); -getset_reg_u32(RCFG); -getset_reg_u32(CCFG); -getset_reg_u32(S29); -getset_reg_u32(S30); -getset_reg_u32(S31); -getset_reg_u32(S32); - -getset_reg_u32(PC_end); -getset_reg_u32(RPE_instr_count); -getset_reg_u32(RPC_current); - - - -PyObject* get_gpreg_offset_all(void) -{ - PyObject *dict = PyDict_New(); - PyObject *o; - get_reg_off(exception_flags); - - get_reg_off(R0); - get_reg_off(R1); - get_reg_off(R2); - get_reg_off(R3); - get_reg_off(R4); - get_reg_off(R5); - get_reg_off(R6); - get_reg_off(R7); - get_reg_off(R8); - get_reg_off(R9); - get_reg_off(R10); - get_reg_off(R11); - get_reg_off(R12); - get_reg_off(TP); - get_reg_off(GP); - get_reg_off(SP); - - get_reg_off(PC); - get_reg_off(LP); - get_reg_off(SAR); - get_reg_off(S3); - get_reg_off(RPB); - get_reg_off(RPE); - get_reg_off(RPC); - get_reg_off(HI); - get_reg_off(LO); - get_reg_off(S9); - get_reg_off(S10); - get_reg_off(S11); - get_reg_off(MB0); - get_reg_off(ME0); - get_reg_off(MB1); - get_reg_off(ME1); - get_reg_off(PSW); - get_reg_off(ID); - get_reg_off(TMP); - get_reg_off(EPC); - get_reg_off(EXC); - get_reg_off(CFG); - get_reg_off(S22); - get_reg_off(NPC); - get_reg_off(DBG); - get_reg_off(DEPC); - get_reg_off(OPT); - get_reg_off(RCFG); - get_reg_off(CCFG); - get_reg_off(S29); - get_reg_off(S30); - get_reg_off(S31); - get_reg_off(S32); - - get_reg_off(PC_end); - get_reg_off(RPE_instr_count); - get_reg_off(RPC_current); - - - return dict; -} - - - - -static PyGetSetDef JitCpu_getseters[] = { - {"vmmngr", - (getter)JitCpu_get_vmmngr, (setter)JitCpu_set_vmmngr, - "vmmngr", - NULL}, - - {"jitter", - (getter)JitCpu_get_jitter, (setter)JitCpu_set_jitter, - "jitter", - NULL}, - - - {"R0" , (getter)JitCpu_get_R0 , (setter)JitCpu_set_R0 , "R0" , NULL}, - {"R1" , (getter)JitCpu_get_R1 , (setter)JitCpu_set_R1 , "R1" , NULL}, - {"R2" , (getter)JitCpu_get_R2 , (setter)JitCpu_set_R2 , "R2" , NULL}, - {"R3" , (getter)JitCpu_get_R3 , (setter)JitCpu_set_R3 , "R3" , NULL}, - {"R4" , (getter)JitCpu_get_R4 , (setter)JitCpu_set_R4 , "R4" , NULL}, - {"R5" , (getter)JitCpu_get_R5 , (setter)JitCpu_set_R5 , "R5" , NULL}, - {"R6" , (getter)JitCpu_get_R6 , (setter)JitCpu_set_R6 , "R6" , NULL}, - {"R7" , (getter)JitCpu_get_R7 , (setter)JitCpu_set_R7 , "R7" , NULL}, - {"R8" , (getter)JitCpu_get_R8 , (setter)JitCpu_set_R8 , "R8" , NULL}, - {"R9" , (getter)JitCpu_get_R9 , (setter)JitCpu_set_R9 , "R9" , NULL}, - {"R10" , (getter)JitCpu_get_R10 , (setter)JitCpu_set_R10 , "R10" , NULL}, - {"R11" , (getter)JitCpu_get_R11 , (setter)JitCpu_set_R11 , "R11" , NULL}, - {"R12" , (getter)JitCpu_get_R12 , (setter)JitCpu_set_R12 , "R12" , NULL}, - {"TP" , (getter)JitCpu_get_TP , (setter)JitCpu_set_TP , "TP" , NULL}, - {"GP" , (getter)JitCpu_get_GP , (setter)JitCpu_set_GP , "GP" , NULL}, - {"SP" , (getter)JitCpu_get_SP , (setter)JitCpu_set_SP , "SP" , NULL}, - - {"PC" , (getter)JitCpu_get_PC , (setter)JitCpu_set_PC , "PC" , NULL}, - {"LP" , (getter)JitCpu_get_LP , (setter)JitCpu_set_LP , "LP" , NULL}, - {"SAR" , (getter)JitCpu_get_SAR , (setter)JitCpu_set_SAR , "SAR" , NULL}, - {"S3" , (getter)JitCpu_get_S3 , (setter)JitCpu_set_S3 , "S3" , NULL}, - {"RPB" , (getter)JitCpu_get_RPB , (setter)JitCpu_set_RPB , "RPB" , NULL}, - {"RPE" , (getter)JitCpu_get_RPE , (setter)JitCpu_set_RPE , "RPE" , NULL}, - {"RPC" , (getter)JitCpu_get_RPC , (setter)JitCpu_set_RPC , "RPC" , NULL}, - {"HI" , (getter)JitCpu_get_HI , (setter)JitCpu_set_HI , "HI" , NULL}, - {"LO" , (getter)JitCpu_get_LO , (setter)JitCpu_set_LO , "LO" , NULL}, - {"S9" , (getter)JitCpu_get_S9 , (setter)JitCpu_set_S9 , "S9" , NULL}, - {"S10" , (getter)JitCpu_get_S10 , (setter)JitCpu_set_S10 , "S10" , NULL}, - {"S11" , (getter)JitCpu_get_S11 , (setter)JitCpu_set_S11 , "S11" , NULL}, - {"MB0" , (getter)JitCpu_get_MB0 , (setter)JitCpu_set_MB0 , "MB0" , NULL}, - {"ME0" , (getter)JitCpu_get_ME0 , (setter)JitCpu_set_ME0 , "ME0" , NULL}, - {"MB1" , (getter)JitCpu_get_MB1 , (setter)JitCpu_set_MB1 , "MB1" , NULL}, - {"ME1" , (getter)JitCpu_get_ME1 , (setter)JitCpu_set_ME1 , "ME1" , NULL}, - {"PSW" , (getter)JitCpu_get_PSW , (setter)JitCpu_set_PSW , "PSW" , NULL}, - {"ID" , (getter)JitCpu_get_ID , (setter)JitCpu_set_ID , "ID" , NULL}, - {"TMP" , (getter)JitCpu_get_TMP , (setter)JitCpu_set_TMP , "TMP" , NULL}, - {"EPC" , (getter)JitCpu_get_EPC , (setter)JitCpu_set_EPC , "EPC" , NULL}, - {"EXC" , (getter)JitCpu_get_EXC , (setter)JitCpu_set_EXC , "EXC" , NULL}, - {"CFG" , (getter)JitCpu_get_CFG , (setter)JitCpu_set_CFG , "CFG" , NULL}, - {"S22" , (getter)JitCpu_get_S22 , (setter)JitCpu_set_S22 , "S22" , NULL}, - {"NPC" , (getter)JitCpu_get_NPC , (setter)JitCpu_set_NPC , "NPC" , NULL}, - {"DBG" , (getter)JitCpu_get_DBG , (setter)JitCpu_set_DBG , "DBG" , NULL}, - {"DEPC" , (getter)JitCpu_get_DEPC , (setter)JitCpu_set_DEPC , "DEPC" , NULL}, - {"OPT" , (getter)JitCpu_get_OPT , (setter)JitCpu_set_OPT , "OPT" , NULL}, - {"RCFG" , (getter)JitCpu_get_RCFG , (setter)JitCpu_set_RCFG , "RCFG" , NULL}, - {"CCFG" , (getter)JitCpu_get_CCFG , (setter)JitCpu_set_CCFG , "CCFG" , NULL}, - {"S29" , (getter)JitCpu_get_S29 , (setter)JitCpu_set_S29 , "S29" , NULL}, - {"S30" , (getter)JitCpu_get_S30 , (setter)JitCpu_set_S30 , "S30" , NULL}, - {"S31" , (getter)JitCpu_get_S31 , (setter)JitCpu_set_S31 , "S31" , NULL}, - {"S32" , (getter)JitCpu_get_S32 , (setter)JitCpu_set_S32 , "S32" , NULL}, - - {"PC_end" , (getter)JitCpu_get_PC_end , (setter)JitCpu_set_PC_end , "PC_end" , NULL}, - {"RPE_instr_count" , (getter)JitCpu_get_RPE_instr_count , (setter)JitCpu_set_RPE_instr_count , "RPE_instr_count" , NULL}, - {"RPC_current" , (getter)JitCpu_get_RPC_current , (setter)JitCpu_set_RPC_current , "RPC_current" , NULL}, - - - - {NULL} /* Sentinel */ -}; - - - -static PyTypeObject JitCpuType = { - PyVarObject_HEAD_INIT(NULL, 0) - "JitCore_mep.JitCpu", /*tp_name*/ - sizeof(JitCpu), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)JitCpu_dealloc,/*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "JitCpu objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - JitCpu_methods, /* tp_methods */ - JitCpu_members, /* tp_members */ - JitCpu_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)JitCpu_init, /* tp_init */ - 0, /* tp_alloc */ - JitCpu_new, /* tp_new */ -}; - - - -static PyMethodDef JitCore_mep_Methods[] = { - - /* - - */ - {"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS}, - {NULL, NULL, 0, NULL} /* Sentinel */ - -}; - - - -MOD_INIT(JitCore_mep) -{ - PyObject *module = NULL; - - MOD_DEF(module, "JitCore_mep", "JitCore_mep module", JitCore_mep_Methods); - - if (module == NULL) - RET_MODULE; - - if (PyType_Ready(&JitCpuType) < 0) - RET_MODULE; - - Py_INCREF(&JitCpuType); - if (PyModule_AddObject(module, "JitCpu", (PyObject *)&JitCpuType) < 0) - RET_MODULE; - - RET_MODULE; -} diff --git a/miasm/jitter/arch/JitCore_mep.h b/miasm/jitter/arch/JitCore_mep.h deleted file mode 100644 index f656b3a0..00000000 --- a/miasm/jitter/arch/JitCore_mep.h +++ /dev/null @@ -1,82 +0,0 @@ -// Inspired from JitCore_msp430.h - -struct vm_cpu { - /* miasm flags */ - uint32_t exception_flags; - - /* gpregs */ - uint32_t R0; - uint32_t R1; - uint32_t R2; - uint32_t R3; - uint32_t R4; - uint32_t R5; - uint32_t R6; - uint32_t R7; - uint32_t R8; - uint32_t R9; - uint32_t R10; - uint32_t R11; - uint32_t R12; - uint32_t TP; - uint32_t GP; - uint32_t SP; - - /* csregs */ - uint32_t PC; - uint32_t LP; - uint32_t SAR; - uint32_t S3; - uint32_t RPB; - uint32_t RPE; - uint32_t RPC; - uint32_t HI; - uint32_t LO; - uint32_t S9; - uint32_t S10; - uint32_t S11; - uint32_t MB0; - uint32_t ME0; - uint32_t MB1; - uint32_t ME1; - uint32_t PSW; - uint32_t ID; - uint32_t TMP; - uint32_t EPC; - uint32_t EXC; - uint32_t CFG; - uint32_t S22; - uint32_t NPC; - uint32_t DBG; - uint32_t DEPC; - uint32_t OPT; - uint32_t RCFG; - uint32_t CCFG; - uint32_t S29; - uint32_t S30; - uint32_t S31; - uint32_t S32; - - /* miasm specific regs */ - uint32_t PC_end; - uint32_t RPE_instr_count; - uint32_t RPC_current; - - - uint32_t take_jmp; - uint32_t last_addr; - uint32_t is_repeat_end; - uint32_t in_erepeat; - - /* flags */ - -}; - -_MIASM_EXPORT void dump_gpregs(struct vm_cpu* vmcpu); - -_MIASM_EXPORT void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src); -_MIASM_EXPORT void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src); -_MIASM_EXPORT void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src); -_MIASM_EXPORT void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src); - -#define RETURN_PC return BlockDst; diff --git a/miasm/jitter/arch/JitCore_mips32.c b/miasm/jitter/arch/JitCore_mips32.c deleted file mode 100644 index 1d7a762c..00000000 --- a/miasm/jitter/arch/JitCore_mips32.c +++ /dev/null @@ -1,484 +0,0 @@ -#include <Python.h> -#include "structmember.h" -#include <stdint.h> -#include <inttypes.h> -#include "../compat_py23.h" -#include "../queue.h" -#include "../vm_mngr.h" -#include "../bn.h" -#include "../vm_mngr_py.h" -#include "../JitCore.h" -#include "../op_semantics.h" -#include "JitCore_mips32.h" - - - -reg_dict gpreg_dict[] = { {.name = "ZERO", .offset = offsetof(struct vm_cpu, ZERO), .size = 32}, - {.name = "AT", .offset = offsetof(struct vm_cpu, AT), .size = 32}, - {.name = "V0", .offset = offsetof(struct vm_cpu, V0), .size = 32}, - {.name = "V1", .offset = offsetof(struct vm_cpu, V1), .size = 32}, - {.name = "A0", .offset = offsetof(struct vm_cpu, A0), .size = 32}, - {.name = "A1", .offset = offsetof(struct vm_cpu, A1), .size = 32}, - {.name = "A2", .offset = offsetof(struct vm_cpu, A2), .size = 32}, - {.name = "A3", .offset = offsetof(struct vm_cpu, A3), .size = 32}, - {.name = "T0", .offset = offsetof(struct vm_cpu, T0), .size = 32}, - {.name = "T1", .offset = offsetof(struct vm_cpu, T1), .size = 32}, - {.name = "T2", .offset = offsetof(struct vm_cpu, T2), .size = 32}, - {.name = "T3", .offset = offsetof(struct vm_cpu, T3), .size = 32}, - {.name = "T4", .offset = offsetof(struct vm_cpu, T4), .size = 32}, - {.name = "T5", .offset = offsetof(struct vm_cpu, T5), .size = 32}, - {.name = "T6", .offset = offsetof(struct vm_cpu, T6), .size = 32}, - {.name = "T7", .offset = offsetof(struct vm_cpu, T7), .size = 32}, - {.name = "S0", .offset = offsetof(struct vm_cpu, S0), .size = 32}, - {.name = "S1", .offset = offsetof(struct vm_cpu, S1), .size = 32}, - {.name = "S2", .offset = offsetof(struct vm_cpu, S2), .size = 32}, - {.name = "S3", .offset = offsetof(struct vm_cpu, S3), .size = 32}, - {.name = "S4", .offset = offsetof(struct vm_cpu, S4), .size = 32}, - {.name = "S5", .offset = offsetof(struct vm_cpu, S5), .size = 32}, - {.name = "S6", .offset = offsetof(struct vm_cpu, S6), .size = 32}, - {.name = "S7", .offset = offsetof(struct vm_cpu, S7), .size = 32}, - {.name = "T8", .offset = offsetof(struct vm_cpu, T8), .size = 32}, - {.name = "T9", .offset = offsetof(struct vm_cpu, T9), .size = 32}, - {.name = "K0", .offset = offsetof(struct vm_cpu, K0), .size = 32}, - {.name = "K1", .offset = offsetof(struct vm_cpu, K1), .size = 32}, - {.name = "GP", .offset = offsetof(struct vm_cpu, GP), .size = 32}, - {.name = "SP", .offset = offsetof(struct vm_cpu, SP), .size = 32}, - {.name = "FP", .offset = offsetof(struct vm_cpu, FP), .size = 32}, - {.name = "RA", .offset = offsetof(struct vm_cpu, RA), .size = 32}, - {.name = "PC", .offset = offsetof(struct vm_cpu, PC), .size = 32}, - {.name = "PC_FETCH", .offset = offsetof(struct vm_cpu, PC_FETCH), .size = 32}, - {.name = "R_LO", .offset = offsetof(struct vm_cpu, R_LO), .size = 32}, - {.name = "R_HI", .offset = offsetof(struct vm_cpu, R_HI), .size = 32}, -}; - -/************************** JitCpu object **************************/ - - - -PyObject* cpu_get_gpreg(JitCpu* self) -{ - PyObject *dict = PyDict_New(); - PyObject *o; - - get_reg(ZERO); - get_reg(AT); - get_reg(V0); - get_reg(V1); - get_reg(A0); - get_reg(A1); - get_reg(A2); - get_reg(A3); - get_reg(T0); - get_reg(T1); - get_reg(T2); - get_reg(T3); - get_reg(T4); - get_reg(T5); - get_reg(T6); - get_reg(T7); - get_reg(S0); - get_reg(S1); - get_reg(S2); - get_reg(S3); - get_reg(S4); - get_reg(S5); - get_reg(S6); - get_reg(S7); - get_reg(T8); - get_reg(T9); - get_reg(K0); - get_reg(K1); - get_reg(GP); - get_reg(SP); - get_reg(FP); - get_reg(RA); - get_reg(PC); - get_reg(PC_FETCH); - get_reg(R_LO); - get_reg(R_HI); - - return dict; -} - - - - -PyObject* cpu_set_gpreg(JitCpu* self, PyObject *args) -{ - PyObject* dict; - PyObject *d_key, *d_value = NULL; - Py_ssize_t pos = 0; - const char *d_key_name; - uint32_t val; - unsigned int i, found; - - if (!PyArg_ParseTuple(args, "O", &dict)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - if(!PyDict_Check(dict)) - RAISE(PyExc_TypeError, "arg must be dict"); - while(PyDict_Next(dict, &pos, &d_key, &d_value)){ - PyGetStr(d_key_name, d_key); - PyGetInt_uint32_t(d_value, val); - - found = 0; - for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){ - if (strcmp(d_key_name, gpreg_dict[i].name)) - continue; - *((uint32_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val; - found = 1; - break; - } - - if (found) - continue; - fprintf(stderr, "unknown key: %s\n", d_key_name); - RAISE(PyExc_ValueError, "unknown reg"); - } - Py_INCREF(Py_None); - return Py_None; -} - - - - -PyObject * cpu_init_regs(JitCpu* self) -{ - memset(self->cpu, 0, sizeof(struct vm_cpu)); - - Py_INCREF(Py_None); - return Py_None; - -} - - -void dump_gpregs(struct vm_cpu* vmcpu) -{ - - printf("ZR %.8"PRIX32" AT %.8"PRIX32" V0 %.8"PRIX32" V1 %.8"PRIX32" ", - vmcpu->ZERO, vmcpu->AT, vmcpu->V0, vmcpu->V1); - printf("A0 %.8"PRIX32" A1 %.8"PRIX32" A2 %.8"PRIX32" A3 %.8"PRIX32" ", - vmcpu->A0, vmcpu->A1, vmcpu->A2, vmcpu->A3); - printf("T0 %.8"PRIX32" T1 %.8"PRIX32" T2 %.8"PRIX32" T3 %.8"PRIX32" ", - vmcpu->T0, vmcpu->T1, vmcpu->T2, vmcpu->T3); - printf("T4 %.8"PRIX32" T5 %.8"PRIX32" T6 %.8"PRIX32" T7 %.8"PRIX32"\n", - vmcpu->T4, vmcpu->T5, vmcpu->T6, vmcpu->T7); - printf("S0 %.8"PRIX32" S1 %.8"PRIX32" S2 %.8"PRIX32" S3 %.8"PRIX32" ", - vmcpu->S0, vmcpu->S1, vmcpu->S2, vmcpu->S3); - printf("S4 %.8"PRIX32" S5 %.8"PRIX32" S6 %.8"PRIX32" S7 %.8"PRIX32" ", - vmcpu->S4, vmcpu->S5, vmcpu->S6, vmcpu->S7); - printf("T8 %.8"PRIX32" T9 %.8"PRIX32" K0 %.8"PRIX32" K1 %.8"PRIX32" ", - vmcpu->T8, vmcpu->T9, vmcpu->K0, vmcpu->K1); - printf("GP %.8"PRIX32" SP %.8"PRIX32" FP %.8"PRIX32" RA %.8"PRIX32"\n", - vmcpu->GP, vmcpu->SP, vmcpu->FP, vmcpu->RA); - printf("PC %.8"PRIX32"\n", - vmcpu->PC); -} - - -PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args) -{ - struct vm_cpu* vmcpu; - - vmcpu = self->cpu; - dump_gpregs(vmcpu); - Py_INCREF(Py_None); - return Py_None; -} - -PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args) -{ - return cpu_dump_gpregs(self, args); -} - - -PyObject* cpu_set_exception(JitCpu* self, PyObject* args) -{ - PyObject *item1; - uint32_t exception_flags; - - if (!PyArg_ParseTuple(args, "O", &item1)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint32_t(item1, exception_flags); - - ((struct vm_cpu*)self->cpu)->exception_flags = exception_flags; - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* cpu_get_exception(JitCpu* self, PyObject* args) -{ - return PyLong_FromUnsignedLongLong((uint64_t)(((struct vm_cpu*)self->cpu)->exception_flags)); -} - - -void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) -{ - vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src) -{ - vm_MEM_WRITE_16(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src) -{ - vm_MEM_WRITE_32(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src) -{ - vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - - - -static PyMemberDef JitCpu_members[] = { - {NULL} /* Sentinel */ -}; - -static PyMethodDef JitCpu_methods[] = { - {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, - "X"}, - {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, - "X"}, - {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, - "X"}, - {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, - "X"}, - {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, - "X"}, - {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, - "X"}, - {"set_exception", (PyCFunction)cpu_set_exception, METH_VARARGS, - "X"}, - {NULL} /* Sentinel */ -}; - - -static int -JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) -{ - self->cpu = malloc(sizeof(struct vm_cpu)); - if (self->cpu == NULL) { - fprintf(stderr, "cannot alloc struct vm_cpu\n"); - exit(EXIT_FAILURE); - } - return 0; -} - -getset_reg_u32(ZERO); -getset_reg_u32(AT); -getset_reg_u32(V0); -getset_reg_u32(V1); -getset_reg_u32(A0); -getset_reg_u32(A1); -getset_reg_u32(A2); -getset_reg_u32(A3); -getset_reg_u32(T0); -getset_reg_u32(T1); -getset_reg_u32(T2); -getset_reg_u32(T3); -getset_reg_u32(T4); -getset_reg_u32(T5); -getset_reg_u32(T6); -getset_reg_u32(T7); -getset_reg_u32(S0); -getset_reg_u32(S1); -getset_reg_u32(S2); -getset_reg_u32(S3); -getset_reg_u32(S4); -getset_reg_u32(S5); -getset_reg_u32(S6); -getset_reg_u32(S7); -getset_reg_u32(T8); -getset_reg_u32(T9); -getset_reg_u32(K0); -getset_reg_u32(K1); -getset_reg_u32(GP); -getset_reg_u32(SP); -getset_reg_u32(FP); -getset_reg_u32(RA); -getset_reg_u32(PC); -getset_reg_u32(PC_FETCH); -getset_reg_u32(R_LO); -getset_reg_u32(R_HI); - - -PyObject* get_gpreg_offset_all(void) -{ - PyObject *dict = PyDict_New(); - PyObject *o; - - get_reg_off(exception_flags); - - - get_reg_off(ZERO); - get_reg_off(AT); - get_reg_off(V0); - get_reg_off(V1); - get_reg_off(A0); - get_reg_off(A1); - get_reg_off(A2); - get_reg_off(A3); - get_reg_off(T0); - get_reg_off(T1); - get_reg_off(T2); - get_reg_off(T3); - get_reg_off(T4); - get_reg_off(T5); - get_reg_off(T6); - get_reg_off(T7); - get_reg_off(S0); - get_reg_off(S1); - get_reg_off(S2); - get_reg_off(S3); - get_reg_off(S4); - get_reg_off(S5); - get_reg_off(S6); - get_reg_off(S7); - get_reg_off(T8); - get_reg_off(T9); - get_reg_off(K0); - get_reg_off(K1); - get_reg_off(GP); - get_reg_off(SP); - get_reg_off(FP); - get_reg_off(RA); - get_reg_off(PC); - get_reg_off(PC_FETCH); - get_reg_off(R_LO); - get_reg_off(R_HI); - - return dict; -} - - -static PyGetSetDef JitCpu_getseters[] = { - {"vmmngr", - (getter)JitCpu_get_vmmngr, (setter)JitCpu_set_vmmngr, - "vmmngr", - NULL}, - - {"jitter", - (getter)JitCpu_get_jitter, (setter)JitCpu_set_jitter, - "jitter", - NULL}, - - {"ZERO" , (getter)JitCpu_get_ZERO , (setter)JitCpu_set_ZERO , "ZERO" , NULL}, - {"AT" , (getter)JitCpu_get_AT , (setter)JitCpu_set_AT , "AT" , NULL}, - {"V0" , (getter)JitCpu_get_V0 , (setter)JitCpu_set_V0 , "V0" , NULL}, - {"V1" , (getter)JitCpu_get_V1 , (setter)JitCpu_set_V1 , "V1" , NULL}, - {"A0" , (getter)JitCpu_get_A0 , (setter)JitCpu_set_A0 , "A0" , NULL}, - {"A1" , (getter)JitCpu_get_A1 , (setter)JitCpu_set_A1 , "A1" , NULL}, - {"A2" , (getter)JitCpu_get_A2 , (setter)JitCpu_set_A2 , "A2" , NULL}, - {"A3" , (getter)JitCpu_get_A3 , (setter)JitCpu_set_A3 , "A3" , NULL}, - {"T0" , (getter)JitCpu_get_T0 , (setter)JitCpu_set_T0 , "T0" , NULL}, - {"T1" , (getter)JitCpu_get_T1 , (setter)JitCpu_set_T1 , "T1" , NULL}, - {"T2" , (getter)JitCpu_get_T2 , (setter)JitCpu_set_T2 , "T2" , NULL}, - {"T3" , (getter)JitCpu_get_T3 , (setter)JitCpu_set_T3 , "T3" , NULL}, - {"T4" , (getter)JitCpu_get_T4 , (setter)JitCpu_set_T4 , "T4" , NULL}, - {"T5" , (getter)JitCpu_get_T5 , (setter)JitCpu_set_T5 , "T5" , NULL}, - {"T6" , (getter)JitCpu_get_T6 , (setter)JitCpu_set_T6 , "T6" , NULL}, - {"T7" , (getter)JitCpu_get_T7 , (setter)JitCpu_set_T7 , "T7" , NULL}, - {"S0" , (getter)JitCpu_get_S0 , (setter)JitCpu_set_S0 , "S0" , NULL}, - {"S1" , (getter)JitCpu_get_S1 , (setter)JitCpu_set_S1 , "S1" , NULL}, - {"S2" , (getter)JitCpu_get_S2 , (setter)JitCpu_set_S2 , "S2" , NULL}, - {"S3" , (getter)JitCpu_get_S3 , (setter)JitCpu_set_S3 , "S3" , NULL}, - {"S4" , (getter)JitCpu_get_S4 , (setter)JitCpu_set_S4 , "S4" , NULL}, - {"S5" , (getter)JitCpu_get_S5 , (setter)JitCpu_set_S5 , "S5" , NULL}, - {"S6" , (getter)JitCpu_get_S6 , (setter)JitCpu_set_S6 , "S6" , NULL}, - {"S7" , (getter)JitCpu_get_S7 , (setter)JitCpu_set_S7 , "S7" , NULL}, - {"T8" , (getter)JitCpu_get_T8 , (setter)JitCpu_set_T8 , "T8" , NULL}, - {"T9" , (getter)JitCpu_get_T9 , (setter)JitCpu_set_T9 , "T9" , NULL}, - {"K0" , (getter)JitCpu_get_K0 , (setter)JitCpu_set_K0 , "K0" , NULL}, - {"K1" , (getter)JitCpu_get_K1 , (setter)JitCpu_set_K1 , "K1" , NULL}, - {"GP" , (getter)JitCpu_get_GP , (setter)JitCpu_set_GP , "GP" , NULL}, - {"SP" , (getter)JitCpu_get_SP , (setter)JitCpu_set_SP , "SP" , NULL}, - {"FP" , (getter)JitCpu_get_FP , (setter)JitCpu_set_FP , "FP" , NULL}, - {"RA" , (getter)JitCpu_get_RA , (setter)JitCpu_set_RA , "RA" , NULL}, - {"PC" , (getter)JitCpu_get_PC , (setter)JitCpu_set_PC , "PC" , NULL}, - {"PC_FETCH" , (getter)JitCpu_get_PC_FETCH , (setter)JitCpu_set_PC_FETCH , "PC_FETCH" , NULL}, - {"R_LO" , (getter)JitCpu_get_R_LO , (setter)JitCpu_set_R_LO , "R_LO" , NULL}, - {"R_HI" , (getter)JitCpu_get_R_HI , (setter)JitCpu_set_R_HI , "R_HI" , NULL}, - - {NULL} /* Sentinel */ -}; - - -static PyTypeObject JitCpuType = { - PyVarObject_HEAD_INIT(NULL, 0) - "JitCore_mips32.JitCpu", /*tp_name*/ - sizeof(JitCpu), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)JitCpu_dealloc,/*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "JitCpu objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - JitCpu_methods, /* tp_methods */ - JitCpu_members, /* tp_members */ - JitCpu_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)JitCpu_init, /* tp_init */ - 0, /* tp_alloc */ - JitCpu_new, /* tp_new */ -}; - - - -static PyMethodDef JitCore_mips32_Methods[] = { - - /* - - */ - {"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS}, - {NULL, NULL, 0, NULL} /* Sentinel */ - -}; - - - - - -MOD_INIT(JitCore_mips32) -{ - PyObject *module = NULL; - - MOD_DEF(module, "JitCore_mips32", "JitCore_mips32 module", JitCore_mips32_Methods); - - if (module == NULL) - RET_MODULE; - - if (PyType_Ready(&JitCpuType) < 0) - RET_MODULE; - - Py_INCREF(&JitCpuType); - if (PyModule_AddObject(module, "JitCpu", (PyObject *)&JitCpuType) < 0) - RET_MODULE; - - RET_MODULE; -} diff --git a/miasm/jitter/arch/JitCore_mips32.h b/miasm/jitter/arch/JitCore_mips32.h deleted file mode 100644 index 8478fb53..00000000 --- a/miasm/jitter/arch/JitCore_mips32.h +++ /dev/null @@ -1,343 +0,0 @@ - -struct vm_cpu { - uint32_t exception_flags; - - /* gpregs */ - - uint32_t ZERO; - uint32_t AT; - uint32_t V0; - uint32_t V1; - uint32_t A0; - uint32_t A1; - uint32_t A2; - uint32_t A3; - uint32_t T0; - uint32_t T1; - uint32_t T2; - uint32_t T3; - uint32_t T4; - uint32_t T5; - uint32_t T6; - uint32_t T7; - uint32_t S0; - uint32_t S1; - uint32_t S2; - uint32_t S3; - uint32_t S4; - uint32_t S5; - uint32_t S6; - uint32_t S7; - uint32_t T8; - uint32_t T9; - uint32_t K0; - uint32_t K1; - uint32_t GP; - uint32_t SP; - uint32_t FP; - uint32_t RA; - uint32_t PC; - uint32_t PC_FETCH; - uint32_t R_LO; - uint32_t R_HI; - - - double F0; - double F1; - double F2; - double F3; - double F4; - double F5; - double F6; - double F7; - double F8; - double F9; - double F10; - double F11; - double F12; - double F13; - double F14; - double F15; - double F16; - double F17; - double F18; - double F19; - double F20; - double F21; - double F22; - double F23; - double F24; - double F25; - double F26; - double F27; - double F28; - double F29; - double F30; - double F31; - - uint32_t INDEX; - uint32_t CPR0_1; - uint32_t CPR0_2; - uint32_t CPR0_3; - uint32_t CPR0_4; - uint32_t CPR0_5; - uint32_t CPR0_6; - uint32_t CPR0_7; - uint32_t RANDOM; - uint32_t CPR0_9; - uint32_t CPR0_10; - uint32_t CPR0_11; - uint32_t CPR0_12; - uint32_t CPR0_13; - uint32_t CPR0_14; - uint32_t CPR0_15; - uint32_t ENTRYLO0; - uint32_t CPR0_17; - uint32_t CPR0_18; - uint32_t CPR0_19; - uint32_t CPR0_20; - uint32_t CPR0_21; - uint32_t CPR0_22; - uint32_t CPR0_23; - uint32_t ENTRYLO1; - uint32_t CPR0_25; - uint32_t CPR0_26; - uint32_t CPR0_27; - uint32_t CPR0_28; - uint32_t CPR0_29; - uint32_t CPR0_30; - uint32_t CPR0_31; - uint32_t CONTEXT; - uint32_t CONTEXTCONFIG; - uint32_t CPR0_34; - uint32_t CPR0_35; - uint32_t CPR0_36; - uint32_t CPR0_37; - uint32_t CPR0_38; - uint32_t CPR0_39; - uint32_t PAGEMASK; - uint32_t PAGEGRAIN; - uint32_t SEGCTL0; - uint32_t SEGCTL1; - uint32_t SEGCTL2; - uint32_t PWBASE; - uint32_t PWFIELD; - uint32_t PWSIZE; - uint32_t WIRED; - uint32_t CPR0_49; - uint32_t CPR0_50; - uint32_t CPR0_51; - uint32_t CPR0_52; - uint32_t CPR0_53; - uint32_t PWCTL; - uint32_t CPR0_55; - uint32_t CPR0_56; - uint32_t CPR0_57; - uint32_t CPR0_58; - uint32_t CPR0_59; - uint32_t CPR0_60; - uint32_t CPR0_61; - uint32_t CPR0_62; - uint32_t CPR0_63; - uint32_t BADVADDR; - uint32_t BADINSTR; - uint32_t BADINSTRP; - uint32_t CPR0_67; - uint32_t CPR0_68; - uint32_t CPR0_69; - uint32_t CPR0_70; - uint32_t CPR0_71; - uint32_t COUNT; - uint32_t CPR0_73; - uint32_t CPR0_74; - uint32_t CPR0_75; - uint32_t CPR0_76; - uint32_t CPR0_77; - uint32_t CPR0_78; - uint32_t CPR0_79; - uint32_t ENTRYHI; - uint32_t CPR0_81; - uint32_t CPR0_82; - uint32_t CPR0_83; - uint32_t CPR0_84; - uint32_t CPR0_85; - uint32_t CPR0_86; - uint32_t CPR0_87; - uint32_t CPR0_88; - uint32_t CPR0_89; - uint32_t CPR0_90; - uint32_t CPR0_91; - uint32_t CPR0_92; - uint32_t CPR0_93; - uint32_t CPR0_94; - uint32_t CPR0_95; - uint32_t CPR0_96; - uint32_t CPR0_97; - uint32_t CPR0_98; - uint32_t CPR0_99; - uint32_t CPR0_100; - uint32_t CPR0_101; - uint32_t CPR0_102; - uint32_t CPR0_103; - uint32_t CAUSE; - uint32_t CPR0_105; - uint32_t CPR0_106; - uint32_t CPR0_107; - uint32_t CPR0_108; - uint32_t CPR0_109; - uint32_t CPR0_110; - uint32_t CPR0_111; - uint32_t EPC; - uint32_t CPR0_113; - uint32_t CPR0_114; - uint32_t CPR0_115; - uint32_t CPR0_116; - uint32_t CPR0_117; - uint32_t CPR0_118; - uint32_t CPR0_119; - uint32_t PRID; - uint32_t EBASE; - uint32_t CPR0_122; - uint32_t CPR0_123; - uint32_t CPR0_124; - uint32_t CPR0_125; - uint32_t CPR0_126; - uint32_t CPR0_127; - uint32_t CONFIG; - uint32_t CONFIG1; - uint32_t CONFIG2; - uint32_t CONFIG3; - uint32_t CONFIG4; - uint32_t CONFIG5; - uint32_t CPR0_134; - uint32_t CPR0_135; - uint32_t CPR0_136; - uint32_t CPR0_137; - uint32_t CPR0_138; - uint32_t CPR0_139; - uint32_t CPR0_140; - uint32_t CPR0_141; - uint32_t CPR0_142; - uint32_t CPR0_143; - uint32_t CPR0_144; - uint32_t CPR0_145; - uint32_t CPR0_146; - uint32_t CPR0_147; - uint32_t CPR0_148; - uint32_t CPR0_149; - uint32_t CPR0_150; - uint32_t CPR0_151; - uint32_t WATCHHI; - uint32_t CPR0_153; - uint32_t CPR0_154; - uint32_t CPR0_155; - uint32_t CPR0_156; - uint32_t CPR0_157; - uint32_t CPR0_158; - uint32_t CPR0_159; - uint32_t CPR0_160; - uint32_t CPR0_161; - uint32_t CPR0_162; - uint32_t CPR0_163; - uint32_t CPR0_164; - uint32_t CPR0_165; - uint32_t CPR0_166; - uint32_t CPR0_167; - uint32_t CPR0_168; - uint32_t CPR0_169; - uint32_t CPR0_170; - uint32_t CPR0_171; - uint32_t CPR0_172; - uint32_t CPR0_173; - uint32_t CPR0_174; - uint32_t CPR0_175; - uint32_t CPR0_176; - uint32_t CPR0_177; - uint32_t CPR0_178; - uint32_t CPR0_179; - uint32_t CPR0_180; - uint32_t CPR0_181; - uint32_t CPR0_182; - uint32_t CPR0_183; - uint32_t CPR0_184; - uint32_t CPR0_185; - uint32_t CPR0_186; - uint32_t CPR0_187; - uint32_t CPR0_188; - uint32_t CPR0_189; - uint32_t CPR0_190; - uint32_t CPR0_191; - uint32_t CPR0_192; - uint32_t CPR0_193; - uint32_t CPR0_194; - uint32_t CPR0_195; - uint32_t CPR0_196; - uint32_t CPR0_197; - uint32_t CPR0_198; - uint32_t CPR0_199; - uint32_t CPR0_200; - uint32_t CPR0_201; - uint32_t CPR0_202; - uint32_t CPR0_203; - uint32_t CPR0_204; - uint32_t CPR0_205; - uint32_t CPR0_206; - uint32_t CPR0_207; - uint32_t CPR0_208; - uint32_t CPR0_209; - uint32_t CPR0_210; - uint32_t CPR0_211; - uint32_t CPR0_212; - uint32_t CPR0_213; - uint32_t CPR0_214; - uint32_t CPR0_215; - uint32_t CPR0_216; - uint32_t CPR0_217; - uint32_t CPR0_218; - uint32_t CPR0_219; - uint32_t CPR0_220; - uint32_t CPR0_221; - uint32_t CPR0_222; - uint32_t CPR0_223; - uint32_t CPR0_224; - uint32_t CPR0_225; - uint32_t CPR0_226; - uint32_t CPR0_227; - uint32_t CPR0_228; - uint32_t CPR0_229; - uint32_t CPR0_230; - uint32_t CPR0_231; - uint32_t CPR0_232; - uint32_t CPR0_233; - uint32_t CPR0_234; - uint32_t CPR0_235; - uint32_t CPR0_236; - uint32_t CPR0_237; - uint32_t CPR0_238; - uint32_t CPR0_239; - uint32_t CPR0_240; - uint32_t CPR0_241; - uint32_t CPR0_242; - uint32_t CPR0_243; - uint32_t CPR0_244; - uint32_t CPR0_245; - uint32_t CPR0_246; - uint32_t CPR0_247; - uint32_t CPR0_248; - uint32_t CPR0_249; - uint32_t KSCRATCH0; - uint32_t KSCRATCH1; - uint32_t KSCRATCH2; - uint32_t KSCRATCH3; - uint32_t KSCRATCH4; - uint32_t KSCRATCH5; -}; - -_MIASM_EXPORT void dump_gpregs(struct vm_cpu* vmcpu); - -_MIASM_EXPORT void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src); -_MIASM_EXPORT void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src); -_MIASM_EXPORT void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src); -_MIASM_EXPORT void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src); - -#define RETURN_PC return BlockDst; diff --git a/miasm/jitter/arch/JitCore_msp430.c b/miasm/jitter/arch/JitCore_msp430.c deleted file mode 100644 index 86e082ad..00000000 --- a/miasm/jitter/arch/JitCore_msp430.c +++ /dev/null @@ -1,423 +0,0 @@ -#include <Python.h> -#include "structmember.h" -#include <stdint.h> -#include <inttypes.h> -#include "../compat_py23.h" -#include "../queue.h" -#include "../vm_mngr.h" -#include "../bn.h" -#include "../vm_mngr_py.h" -#include "../JitCore.h" -#include "JitCore_msp430.h" - - -reg_dict gpreg_dict[] = { {.name = "PC", .offset = offsetof(struct vm_cpu, PC)}, - {.name = "SP", .offset = offsetof(struct vm_cpu, SP)}, - //{.name = "SR", .offset = offsetof(struct vm_cpu, SR)}, - {.name = "R3", .offset = offsetof(struct vm_cpu, R3)}, - {.name = "R4", .offset = offsetof(struct vm_cpu, R4)}, - {.name = "R5", .offset = offsetof(struct vm_cpu, R5)}, - {.name = "R6", .offset = offsetof(struct vm_cpu, R6)}, - {.name = "R7", .offset = offsetof(struct vm_cpu, R7)}, - {.name = "R8", .offset = offsetof(struct vm_cpu, R8)}, - {.name = "R9", .offset = offsetof(struct vm_cpu, R9)}, - {.name = "R10", .offset = offsetof(struct vm_cpu, R10)}, - {.name = "R11", .offset = offsetof(struct vm_cpu, R11)}, - {.name = "R12", .offset = offsetof(struct vm_cpu, R12)}, - {.name = "R13", .offset = offsetof(struct vm_cpu, R13)}, - {.name = "R14", .offset = offsetof(struct vm_cpu, R14)}, - {.name = "R15", .offset = offsetof(struct vm_cpu, R15)}, - - {.name = "zf", .offset = offsetof(struct vm_cpu, zf)}, - {.name = "nf", .offset = offsetof(struct vm_cpu, nf)}, - {.name = "of", .offset = offsetof(struct vm_cpu, of)}, - {.name = "cf", .offset = offsetof(struct vm_cpu, cf)}, - - {.name = "cpuoff", .offset = offsetof(struct vm_cpu, cpuoff)}, - {.name = "gie", .offset = offsetof(struct vm_cpu, gie)}, - {.name = "osc", .offset = offsetof(struct vm_cpu, osc)}, - {.name = "scg0", .offset = offsetof(struct vm_cpu, scg0)}, - {.name = "scg1", .offset = offsetof(struct vm_cpu, scg1)}, - {.name = "res", .offset = offsetof(struct vm_cpu, res)}, - -}; - -/************************** JitCpu object **************************/ - - - -PyObject* cpu_get_gpreg(JitCpu* self) -{ - PyObject *dict = PyDict_New(); - PyObject *o; - - get_reg(PC); - get_reg(SP); - //get_reg(SR); - get_reg(R3); - get_reg(R4); - get_reg(R5); - get_reg(R6); - get_reg(R7); - get_reg(R8); - get_reg(R9); - get_reg(R10); - get_reg(R11); - get_reg(R12); - get_reg(R13); - get_reg(R14); - get_reg(R15); - - get_reg(zf); - get_reg(nf); - get_reg(of); - get_reg(cf); - - get_reg(cpuoff); - get_reg(gie); - get_reg(osc); - get_reg(scg0); - get_reg(scg1); - get_reg(res); - - - return dict; -} - - -PyObject* cpu_set_gpreg(JitCpu* self, PyObject *args) -{ - PyObject* dict; - PyObject *d_key, *d_value = NULL; - Py_ssize_t pos = 0; - const char *d_key_name; - uint32_t val; - unsigned int i, found; - - if (!PyArg_ParseTuple(args, "O", &dict)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - if(!PyDict_Check(dict)) - RAISE(PyExc_TypeError, "arg must be dict"); - while(PyDict_Next(dict, &pos, &d_key, &d_value)){ - PyGetStr(d_key_name, d_key); - PyGetInt_uint32_t(d_value, val); - found = 0; - for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){ - if (strcmp(d_key_name, gpreg_dict[i].name)) - continue; - *((uint32_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val; - found = 1; - break; - } - - if (found) - continue; - fprintf(stderr, "unknown key: %s\n", d_key_name); - RAISE(PyExc_ValueError, "unknown reg"); - } - Py_INCREF(Py_None); - return Py_None; -} - - - - -PyObject * cpu_init_regs(JitCpu* self) -{ - memset(self->cpu, 0, sizeof(struct vm_cpu)); - - Py_INCREF(Py_None); - return Py_None; - -} - -void dump_gpregs(struct vm_cpu* vmcpu) -{ - - printf("PC %.4"PRIX32" SP %.4"PRIX32" R3 %.4"PRIX32" ", - vmcpu->PC, vmcpu->SP, vmcpu->R3); - printf("R4 %.4"PRIX32" R5 %.4"PRIX32" R6 %.4"PRIX32" R7 %.4"PRIX32"\n", - vmcpu->R4, vmcpu->R5, vmcpu->R6, vmcpu->R7); - printf("R8 %.4"PRIX32" R9 %.4"PRIX32" R10 %.4"PRIX32" R11 %.4"PRIX32" ", - vmcpu->R8, vmcpu->R9, vmcpu->R10, vmcpu->R11); - printf("R12 %.4"PRIX32" R13 %.4"PRIX32" R14 %.4"PRIX32" R15 %.4"PRIX32"\n", - vmcpu->R12, vmcpu->R13, vmcpu->R14, vmcpu->R15); - printf("zf %"PRIX32" nf %"PRIX32" of %"PRIX32" cf %"PRIX32"\n", - vmcpu->zf, vmcpu->nf, vmcpu->of, vmcpu->cf); -} - - -PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args) -{ - struct vm_cpu* vmcpu; - - vmcpu = self->cpu; - dump_gpregs(vmcpu); - Py_INCREF(Py_None); - return Py_None; -} - -PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args) -{ - return cpu_dump_gpregs(self, args); -} - - -PyObject* cpu_set_exception(JitCpu* self, PyObject* args) -{ - PyObject *item1; - uint32_t exception_flags; - - if (!PyArg_ParseTuple(args, "O", &item1)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint32_t(item1, exception_flags); - - ((struct vm_cpu*)self->cpu)->exception_flags = exception_flags; - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* cpu_get_exception(JitCpu* self, PyObject* args) -{ - return PyLong_FromUnsignedLongLong((uint64_t)(((struct vm_cpu*)self->cpu)->exception_flags)); -} - -void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) -{ - vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src) -{ - vm_MEM_WRITE_16(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src) -{ - vm_MEM_WRITE_32(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src) -{ - vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - - -static PyMemberDef JitCpu_members[] = { - {NULL} /* Sentinel */ -}; - -static PyMethodDef JitCpu_methods[] = { - {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, - "X"}, - {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, - "X"}, - {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, - "X"}, - {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, - "X"}, - {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, - "X"}, - {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, - "X"}, - {"set_exception", (PyCFunction)cpu_set_exception, METH_VARARGS, - "X"}, - {NULL} /* Sentinel */ -}; - -static int -JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) -{ - self->cpu = malloc(sizeof(struct vm_cpu)); - if (self->cpu == NULL) { - fprintf(stderr, "cannot alloc struct vm_cpu\n"); - exit(EXIT_FAILURE); - } - return 0; -} - -getset_reg_u16(PC); -getset_reg_u16(SP); -getset_reg_u16(R3); -getset_reg_u16(R4); -getset_reg_u16(R5); -getset_reg_u16(R6); -getset_reg_u16(R7); -getset_reg_u16(R8); -getset_reg_u16(R9); -getset_reg_u16(R10); -getset_reg_u16(R11); -getset_reg_u16(R12); -getset_reg_u16(R13); -getset_reg_u16(R14); -getset_reg_u16(R15); -getset_reg_u16(zf); -getset_reg_u16(nf); -getset_reg_u16(of); -getset_reg_u16(cf); -getset_reg_u16(cpuoff); -getset_reg_u16(gie); -getset_reg_u16(osc); -getset_reg_u16(scg0); -getset_reg_u16(scg1); -getset_reg_u16(res); - - - -PyObject* get_gpreg_offset_all(void) -{ - PyObject *dict = PyDict_New(); - PyObject *o; - get_reg_off(exception_flags); - - get_reg_off(PC); - get_reg_off(SP); - get_reg_off(R3); - get_reg_off(R4); - get_reg_off(R5); - get_reg_off(R6); - get_reg_off(R7); - get_reg_off(R8); - get_reg_off(R9); - get_reg_off(R10); - get_reg_off(R11); - get_reg_off(R12); - get_reg_off(R13); - get_reg_off(R14); - get_reg_off(R15); - - get_reg_off(zf); - get_reg_off(nf); - get_reg_off(of); - get_reg_off(cf); - get_reg_off(cpuoff); - get_reg_off(gie); - get_reg_off(osc); - get_reg_off(scg0); - get_reg_off(scg1); - get_reg_off(res); - - return dict; -} - - - - -static PyGetSetDef JitCpu_getseters[] = { - {"vmmngr", - (getter)JitCpu_get_vmmngr, (setter)JitCpu_set_vmmngr, - "vmmngr", - NULL}, - - {"jitter", - (getter)JitCpu_get_jitter, (setter)JitCpu_set_jitter, - "jitter", - NULL}, - - - {"PC" , (getter)JitCpu_get_PC , (setter)JitCpu_set_PC , "PC" , NULL}, - {"SP" , (getter)JitCpu_get_SP , (setter)JitCpu_set_SP , "SP" , NULL}, - {"R3" , (getter)JitCpu_get_R3 , (setter)JitCpu_set_R3 , "R3" , NULL}, - {"R4" , (getter)JitCpu_get_R4 , (setter)JitCpu_set_R4 , "R4" , NULL}, - {"R5" , (getter)JitCpu_get_R5 , (setter)JitCpu_set_R5 , "R5" , NULL}, - {"R6" , (getter)JitCpu_get_R6 , (setter)JitCpu_set_R6 , "R6" , NULL}, - {"R7" , (getter)JitCpu_get_R7 , (setter)JitCpu_set_R7 , "R7" , NULL}, - {"R8" , (getter)JitCpu_get_R8 , (setter)JitCpu_set_R8 , "R8" , NULL}, - {"R9" , (getter)JitCpu_get_R9 , (setter)JitCpu_set_R9 , "R9" , NULL}, - {"R10" , (getter)JitCpu_get_R10 , (setter)JitCpu_set_R10 , "R10" , NULL}, - {"R11" , (getter)JitCpu_get_R11 , (setter)JitCpu_set_R11 , "R11" , NULL}, - {"R12" , (getter)JitCpu_get_R12 , (setter)JitCpu_set_R12 , "R12" , NULL}, - {"R13" , (getter)JitCpu_get_R13 , (setter)JitCpu_set_R13 , "R13" , NULL}, - {"R14" , (getter)JitCpu_get_R14 , (setter)JitCpu_set_R14 , "R14" , NULL}, - {"R15" , (getter)JitCpu_get_R15 , (setter)JitCpu_set_R15 , "R15" , NULL}, - {"zf" , (getter)JitCpu_get_zf , (setter)JitCpu_set_zf , "zf" , NULL}, - {"nf" , (getter)JitCpu_get_nf , (setter)JitCpu_set_nf , "nf" , NULL}, - {"of" , (getter)JitCpu_get_of , (setter)JitCpu_set_of , "of" , NULL}, - {"cf" , (getter)JitCpu_get_cf , (setter)JitCpu_set_cf , "cf" , NULL}, - {"cpuoff" , (getter)JitCpu_get_cpuoff , (setter)JitCpu_set_cpuoff , "cpuoff" , NULL}, - {"gie" , (getter)JitCpu_get_gie , (setter)JitCpu_set_gie , "gie" , NULL}, - {"osc" , (getter)JitCpu_get_osc , (setter)JitCpu_set_osc , "osc" , NULL}, - {"scg0" , (getter)JitCpu_get_scg0 , (setter)JitCpu_set_scg0 , "scg0" , NULL}, - {"scg1" , (getter)JitCpu_get_scg1 , (setter)JitCpu_set_scg1 , "scg1" , NULL}, - {"res" , (getter)JitCpu_get_res , (setter)JitCpu_set_res , "res" , NULL}, - - {NULL} /* Sentinel */ -}; - - - -static PyTypeObject JitCpuType = { - PyVarObject_HEAD_INIT(NULL, 0) - "JitCore_msp430.JitCpu", /*tp_name*/ - sizeof(JitCpu), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)JitCpu_dealloc,/*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "JitCpu objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - JitCpu_methods, /* tp_methods */ - JitCpu_members, /* tp_members */ - JitCpu_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)JitCpu_init, /* tp_init */ - 0, /* tp_alloc */ - JitCpu_new, /* tp_new */ -}; - - - -static PyMethodDef JitCore_msp430_Methods[] = { - - /* - - */ - {"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS}, - {NULL, NULL, 0, NULL} /* Sentinel */ - -}; - - - - -MOD_INIT(JitCore_msp430) -{ - PyObject *module = NULL; - - MOD_DEF(module, "JitCore_msp430", "JitCore_msp430 module", JitCore_msp430_Methods); - - if (module == NULL) - RET_MODULE; - - if (PyType_Ready(&JitCpuType) < 0) - RET_MODULE; - - Py_INCREF(&JitCpuType); - if (PyModule_AddObject(module, "JitCpu", (PyObject *)&JitCpuType) < 0) - RET_MODULE; - - RET_MODULE; -} diff --git a/miasm/jitter/arch/JitCore_msp430.h b/miasm/jitter/arch/JitCore_msp430.h deleted file mode 100644 index d7b6a7b9..00000000 --- a/miasm/jitter/arch/JitCore_msp430.h +++ /dev/null @@ -1,44 +0,0 @@ - -struct vm_cpu { - uint32_t exception_flags; - - /* gpregs */ - uint32_t PC; - uint32_t SP; - uint32_t R3; - uint32_t R4; - uint32_t R5; - uint32_t R6; - uint32_t R7; - uint32_t R8; - uint32_t R9; - uint32_t R10; - uint32_t R11; - uint32_t R12; - uint32_t R13; - uint32_t R14; - uint32_t R15; - - /* eflag */ - uint32_t zf; - uint32_t nf; - uint32_t of; - uint32_t cf; - - uint32_t cpuoff; - uint32_t gie; - uint32_t osc; - uint32_t scg0; - uint32_t scg1; - uint32_t res; - -}; - -#define RETURN_PC return BlockDst; - -_MIASM_EXPORT void dump_gpregs(struct vm_cpu* vmcpu); - -_MIASM_EXPORT void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src); -_MIASM_EXPORT void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src); -_MIASM_EXPORT void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src); -_MIASM_EXPORT void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src); diff --git a/miasm/jitter/arch/JitCore_ppc32.c b/miasm/jitter/arch/JitCore_ppc32.c deleted file mode 100644 index 086b140f..00000000 --- a/miasm/jitter/arch/JitCore_ppc32.c +++ /dev/null @@ -1,297 +0,0 @@ -#include <Python.h> -#include "structmember.h" -#include <stdint.h> -#include <inttypes.h> -#include "../compat_py23.h" -#include "../queue.h" -#include "../vm_mngr.h" -#include "../bn.h" -#include "../vm_mngr_py.h" -#include "../JitCore.h" -#include "JitCore_ppc32.h" - -reg_dict gpreg_dict[] = { -#define JITCORE_PPC_REG_EXPAND(_name, _size) \ - { .name = #_name, .offset = offsetof(struct vm_cpu, _name), .size = _size }, -#include "JitCore_ppc32_regs.h" -#undef JITCORE_PPC_REG_EXPAND -}; - -PyObject* cpu_get_gpreg(JitCpu* self) -{ - PyObject *dict = PyDict_New(); - PyObject *o; - -#define JITCORE_PPC_REG_EXPAND(_name, _size) \ - get_reg(_name); -#include "JitCore_ppc32_regs.h" -#undef JITCORE_PPC_REG_EXPAND - - return dict; -} - - - -PyObject * -cpu_set_gpreg(JitCpu *self, PyObject *args) { - PyObject *dict; - PyObject *d_key, *d_value = NULL; - Py_ssize_t pos = 0; - const char *d_key_name; - uint32_t val; - unsigned int i; - - if (!PyArg_ParseTuple(args, "O", &dict)) - return NULL; - if(!PyDict_Check(dict)) - RAISE(PyExc_TypeError, "arg must be dict"); - - while(PyDict_Next(dict, &pos, &d_key, &d_value)) { - int found = 0; - PyGetStr(d_key_name, d_key); - PyGetInt_uint32_t(d_value, val); - - for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){ - if (strcmp(d_key_name, gpreg_dict[i].name)) - continue; - *((uint32_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val; - found = 1; - break; - } - - if (found) - continue; - fprintf(stderr, "unknown key: %s\n", d_key_name); - RAISE(PyExc_ValueError, "unknown reg"); - } - - Py_INCREF(Py_None); - return Py_None; -} - - -PyObject * -cpu_init_regs(JitCpu *self) { - memset(self->cpu, 0, sizeof(struct vm_cpu)); - - Py_INCREF(Py_None); - return Py_None; -} - -static void -dump_gpreg(const char *name, uint32_t val, int *n) { - printf("%6s %.8" PRIX32"%c", name, val, (*n + 1) % 4 == 0? '\n':' '); - *n = (*n + 1) % 4; -} - -void -dump_gpregs(struct vm_cpu *vmcpu) { - int reg_num = 0; - -#define JITCORE_PPC_REG_EXPAND(_name, _size) \ - dump_gpreg(#_name, vmcpu->_name, ®_num); -#include "JitCore_ppc32_regs.h" -#undef JITCORE_PPC_REG_EXPAND - - if ((reg_num % 4) != 0) - putchar('\n'); -} - - -PyObject * -cpu_dump_gpregs(JitCpu *self, PyObject *args) { - - dump_gpregs(self->cpu); - - Py_INCREF(Py_None); - return Py_None; -} - -PyObject * -cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args) -{ - return cpu_dump_gpregs(self, args); -} - -PyObject * -cpu_set_exception(JitCpu *self, PyObject *args) { - PyObject *item1; - uint64_t exception_flags; - - if (!PyArg_ParseTuple(args, "O", &item1)) - return NULL; - - PyGetInt_uint64_t(item1, exception_flags); - - ((struct vm_cpu *)self->cpu)->exception_flags = exception_flags; - - Py_INCREF(Py_None); - return Py_None; -} - -PyObject * -cpu_get_exception(JitCpu *self, PyObject *args) { - return PyLong_FromUnsignedLongLong(((struct vm_cpu *)self->cpu)->exception_flags); -} - -static PyObject * -cpu_get_spr_access(JitCpu *self, PyObject *args) { - return PyLong_FromUnsignedLongLong(((struct vm_cpu *) self->cpu)->spr_access); -} - -void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) -{ - vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src) -{ - vm_MEM_WRITE_16(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src) -{ - vm_MEM_WRITE_32(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src) -{ - vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - - - -static PyMemberDef JitCpu_members[] = { - {NULL} /* Sentinel */ -}; - -static PyMethodDef JitCpu_methods[] = { - {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, "X"}, - {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, "X"}, - {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, "X"}, - {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, "X"}, - {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, "X"}, - {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, "X"}, - {"set_exception", (PyCFunction)cpu_set_exception, METH_VARARGS, "X"}, - {"get_spr_access", (PyCFunction)cpu_get_spr_access, METH_VARARGS, "X"}, - {NULL} /* Sentinel */ -}; - -static int -JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) { - self->cpu = malloc(sizeof(struct vm_cpu)); - if (self->cpu == NULL) { - fprintf(stderr, "cannot alloc struct vm_cpu\n"); - exit(1); - } - return 0; -} - - -#define JITCORE_PPC_REG_EXPAND(_name, _size) \ -getset_reg_u32(_name); -#include "JitCore_ppc32_regs.h" -#undef JITCORE_PPC_REG_EXPAND - -PyObject * -get_gpreg_offset_all(void) { - PyObject *dict = PyDict_New(); - PyObject *o; - -#define JITCORE_PPC_REG_EXPAND(_name, _size) \ - get_reg_off(_name); -#include "JitCore_ppc32_regs.h" -#undef JITCORE_PPC_REG_EXPAND - - return dict; -} - -static PyGetSetDef JitCpu_getseters[] = { - {"vmmngr", - (getter)JitCpu_get_vmmngr, (setter)JitCpu_set_vmmngr, - "vmmngr", - NULL}, - - {"jitter", - (getter)JitCpu_get_jitter, (setter)JitCpu_set_jitter, - "jitter", - NULL}, - -#define JITCORE_PPC_REG_EXPAND(_name, _size) \ - { #_name, (getter) JitCpu_get_ ## _name , \ - (setter) JitCpu_set_ ## _name , #_name , NULL}, -#include "JitCore_ppc32_regs.h" -#undef JITCORE_PPC_REG_EXPAND - - {NULL} /* Sentinel */ -}; - - -static PyTypeObject JitCpuType = { - PyVarObject_HEAD_INIT(NULL, 0) - "JitCore_ppc.JitCpu", /*tp_name*/ - sizeof(JitCpu), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)JitCpu_dealloc,/*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "JitCpu objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - JitCpu_methods, /* tp_methods */ - JitCpu_members, /* tp_members */ - JitCpu_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)JitCpu_init, /* tp_init */ - 0, /* tp_alloc */ - JitCpu_new, /* tp_new */ -}; - - - -static PyMethodDef JitCore_ppc32_Methods[] = { - {"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS}, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; - - - -MOD_INIT(JitCore_ppc32) -{ - PyObject *module = NULL; - - MOD_DEF(module, "JitCore_ppc32", "JitCore_ppc32 module", JitCore_ppc32_Methods); - - if (module == NULL) - RET_MODULE; - - if (PyType_Ready(&JitCpuType) < 0) - RET_MODULE; - - Py_INCREF(&JitCpuType); - if (PyModule_AddObject(module, "JitCpu", (PyObject *)&JitCpuType) < 0) - RET_MODULE; - - RET_MODULE; -} diff --git a/miasm/jitter/arch/JitCore_ppc32.h b/miasm/jitter/arch/JitCore_ppc32.h deleted file mode 100644 index abb04941..00000000 --- a/miasm/jitter/arch/JitCore_ppc32.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * _size can't be used yet because all register accesses are homogeneously - * 32-bit - */ -struct vm_cpu { -#define JITCORE_PPC_REG_EXPAND(_name, _size) \ - uint32_t _name; -#include "JitCore_ppc32_regs.h" -#undef JITCORE_PPC_REG_EXPAND - - uint64_t exception_flags; - uint32_t spr_access; - uint32_t reserve; - uint32_t reserve_address; -}; - -_MIASM_EXPORT void dump_gpregs(struct vm_cpu *); - -_MIASM_EXPORT void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src); -_MIASM_EXPORT void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src); -_MIASM_EXPORT void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src); -_MIASM_EXPORT void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src); diff --git a/miasm/jitter/arch/JitCore_ppc32_regs.h b/miasm/jitter/arch/JitCore_ppc32_regs.h deleted file mode 100644 index 79191d32..00000000 --- a/miasm/jitter/arch/JitCore_ppc32_regs.h +++ /dev/null @@ -1,192 +0,0 @@ -JITCORE_PPC_REG_EXPAND(R0, 32) -JITCORE_PPC_REG_EXPAND(R1, 32) -JITCORE_PPC_REG_EXPAND(R2, 32) -JITCORE_PPC_REG_EXPAND(R3, 32) -JITCORE_PPC_REG_EXPAND(R4, 32) -JITCORE_PPC_REG_EXPAND(R5, 32) -JITCORE_PPC_REG_EXPAND(R6, 32) -JITCORE_PPC_REG_EXPAND(R7, 32) -JITCORE_PPC_REG_EXPAND(R8, 32) -JITCORE_PPC_REG_EXPAND(R9, 32) -JITCORE_PPC_REG_EXPAND(R10, 32) -JITCORE_PPC_REG_EXPAND(R11, 32) -JITCORE_PPC_REG_EXPAND(R12, 32) -JITCORE_PPC_REG_EXPAND(R13, 32) -JITCORE_PPC_REG_EXPAND(R14, 32) -JITCORE_PPC_REG_EXPAND(R15, 32) -JITCORE_PPC_REG_EXPAND(R16, 32) -JITCORE_PPC_REG_EXPAND(R17, 32) -JITCORE_PPC_REG_EXPAND(R18, 32) -JITCORE_PPC_REG_EXPAND(R19, 32) -JITCORE_PPC_REG_EXPAND(R20, 32) -JITCORE_PPC_REG_EXPAND(R21, 32) -JITCORE_PPC_REG_EXPAND(R22, 32) -JITCORE_PPC_REG_EXPAND(R23, 32) -JITCORE_PPC_REG_EXPAND(R24, 32) -JITCORE_PPC_REG_EXPAND(R25, 32) -JITCORE_PPC_REG_EXPAND(R26, 32) -JITCORE_PPC_REG_EXPAND(R27, 32) -JITCORE_PPC_REG_EXPAND(R28, 32) -JITCORE_PPC_REG_EXPAND(R29, 32) -JITCORE_PPC_REG_EXPAND(R30, 32) -JITCORE_PPC_REG_EXPAND(R31, 32) - -JITCORE_PPC_REG_EXPAND(PC, 32) -JITCORE_PPC_REG_EXPAND(LR, 32) -JITCORE_PPC_REG_EXPAND(CTR, 32) -JITCORE_PPC_REG_EXPAND(MSR, 32) - -JITCORE_PPC_REG_EXPAND(XER_SO, 32) -JITCORE_PPC_REG_EXPAND(XER_OV, 32) -JITCORE_PPC_REG_EXPAND(XER_CA, 32) -JITCORE_PPC_REG_EXPAND(XER_BC, 32) - -JITCORE_PPC_REG_EXPAND(CR0_LT, 8) -JITCORE_PPC_REG_EXPAND(CR0_GT, 8) -JITCORE_PPC_REG_EXPAND(CR0_EQ, 8) -JITCORE_PPC_REG_EXPAND(CR0_SO, 8) -JITCORE_PPC_REG_EXPAND(CR1_LT, 8) -JITCORE_PPC_REG_EXPAND(CR1_GT, 8) -JITCORE_PPC_REG_EXPAND(CR1_EQ, 8) -JITCORE_PPC_REG_EXPAND(CR1_SO, 8) -JITCORE_PPC_REG_EXPAND(CR2_LT, 8) -JITCORE_PPC_REG_EXPAND(CR2_GT, 8) -JITCORE_PPC_REG_EXPAND(CR2_EQ, 8) -JITCORE_PPC_REG_EXPAND(CR2_SO, 8) -JITCORE_PPC_REG_EXPAND(CR3_LT, 8) -JITCORE_PPC_REG_EXPAND(CR3_GT, 8) -JITCORE_PPC_REG_EXPAND(CR3_EQ, 8) -JITCORE_PPC_REG_EXPAND(CR3_SO, 8) -JITCORE_PPC_REG_EXPAND(CR4_LT, 8) -JITCORE_PPC_REG_EXPAND(CR4_GT, 8) -JITCORE_PPC_REG_EXPAND(CR4_EQ, 8) -JITCORE_PPC_REG_EXPAND(CR4_SO, 8) -JITCORE_PPC_REG_EXPAND(CR5_LT, 8) -JITCORE_PPC_REG_EXPAND(CR5_GT, 8) -JITCORE_PPC_REG_EXPAND(CR5_EQ, 8) -JITCORE_PPC_REG_EXPAND(CR5_SO, 8) -JITCORE_PPC_REG_EXPAND(CR6_LT, 8) -JITCORE_PPC_REG_EXPAND(CR6_GT, 8) -JITCORE_PPC_REG_EXPAND(CR6_EQ, 8) -JITCORE_PPC_REG_EXPAND(CR6_SO, 8) -JITCORE_PPC_REG_EXPAND(CR7_LT, 8) -JITCORE_PPC_REG_EXPAND(CR7_GT, 8) -JITCORE_PPC_REG_EXPAND(CR7_EQ, 8) -JITCORE_PPC_REG_EXPAND(CR7_SO, 8) - -JITCORE_PPC_REG_EXPAND(SPRG0, 32) -JITCORE_PPC_REG_EXPAND(SPRG1, 32) -JITCORE_PPC_REG_EXPAND(SPRG2, 32) -JITCORE_PPC_REG_EXPAND(SPRG3, 32) -JITCORE_PPC_REG_EXPAND(SRR0, 32) -JITCORE_PPC_REG_EXPAND(SRR1, 32) -JITCORE_PPC_REG_EXPAND(DAR, 32) -JITCORE_PPC_REG_EXPAND(DSISR, 32) -JITCORE_PPC_REG_EXPAND(PIR, 32) -JITCORE_PPC_REG_EXPAND(PVR, 32) -JITCORE_PPC_REG_EXPAND(DEC, 32) -JITCORE_PPC_REG_EXPAND(TBL, 32) -JITCORE_PPC_REG_EXPAND(TBU, 32) - -JITCORE_PPC_REG_EXPAND(SR0, 32) -JITCORE_PPC_REG_EXPAND(SR1, 32) -JITCORE_PPC_REG_EXPAND(SR2, 32) -JITCORE_PPC_REG_EXPAND(SR3, 32) -JITCORE_PPC_REG_EXPAND(SR4, 32) -JITCORE_PPC_REG_EXPAND(SR5, 32) -JITCORE_PPC_REG_EXPAND(SR6, 32) -JITCORE_PPC_REG_EXPAND(SR7, 32) -JITCORE_PPC_REG_EXPAND(SR8, 32) -JITCORE_PPC_REG_EXPAND(SR9, 32) -JITCORE_PPC_REG_EXPAND(SR10, 32) -JITCORE_PPC_REG_EXPAND(SR11, 32) -JITCORE_PPC_REG_EXPAND(SR12, 32) -JITCORE_PPC_REG_EXPAND(SR13, 32) -JITCORE_PPC_REG_EXPAND(SR14, 32) -JITCORE_PPC_REG_EXPAND(SR15, 32) -JITCORE_PPC_REG_EXPAND(IBAT0U, 32) -JITCORE_PPC_REG_EXPAND(IBAT0L, 32) -JITCORE_PPC_REG_EXPAND(IBAT1U, 32) -JITCORE_PPC_REG_EXPAND(IBAT1L, 32) -JITCORE_PPC_REG_EXPAND(IBAT2U, 32) -JITCORE_PPC_REG_EXPAND(IBAT2L, 32) -JITCORE_PPC_REG_EXPAND(IBAT3U, 32) -JITCORE_PPC_REG_EXPAND(IBAT3L, 32) -JITCORE_PPC_REG_EXPAND(DBAT0U, 32) -JITCORE_PPC_REG_EXPAND(DBAT0L, 32) -JITCORE_PPC_REG_EXPAND(DBAT1U, 32) -JITCORE_PPC_REG_EXPAND(DBAT1L, 32) -JITCORE_PPC_REG_EXPAND(DBAT2U, 32) -JITCORE_PPC_REG_EXPAND(DBAT2L, 32) -JITCORE_PPC_REG_EXPAND(DBAT3U, 32) -JITCORE_PPC_REG_EXPAND(DBAT3L, 32) -JITCORE_PPC_REG_EXPAND(SDR1, 32) - -JITCORE_PPC_REG_EXPAND(FPR0, 64) -JITCORE_PPC_REG_EXPAND(FPR1, 64) -JITCORE_PPC_REG_EXPAND(FPR2, 64) -JITCORE_PPC_REG_EXPAND(FPR3, 64) -JITCORE_PPC_REG_EXPAND(FPR4, 64) -JITCORE_PPC_REG_EXPAND(FPR5, 64) -JITCORE_PPC_REG_EXPAND(FPR6, 64) -JITCORE_PPC_REG_EXPAND(FPR7, 64) -JITCORE_PPC_REG_EXPAND(FPR8, 64) -JITCORE_PPC_REG_EXPAND(FPR9, 64) -JITCORE_PPC_REG_EXPAND(FPR10, 64) -JITCORE_PPC_REG_EXPAND(FPR11, 64) -JITCORE_PPC_REG_EXPAND(FPR12, 64) -JITCORE_PPC_REG_EXPAND(FPR13, 64) -JITCORE_PPC_REG_EXPAND(FPR14, 64) -JITCORE_PPC_REG_EXPAND(FPR15, 64) -JITCORE_PPC_REG_EXPAND(FPR16, 64) -JITCORE_PPC_REG_EXPAND(FPR17, 64) -JITCORE_PPC_REG_EXPAND(FPR18, 64) -JITCORE_PPC_REG_EXPAND(FPR19, 64) -JITCORE_PPC_REG_EXPAND(FPR20, 64) -JITCORE_PPC_REG_EXPAND(FPR21, 64) -JITCORE_PPC_REG_EXPAND(FPR22, 64) -JITCORE_PPC_REG_EXPAND(FPR23, 64) -JITCORE_PPC_REG_EXPAND(FPR24, 64) -JITCORE_PPC_REG_EXPAND(FPR25, 64) -JITCORE_PPC_REG_EXPAND(FPR26, 64) -JITCORE_PPC_REG_EXPAND(FPR27, 64) -JITCORE_PPC_REG_EXPAND(FPR28, 64) -JITCORE_PPC_REG_EXPAND(FPR29, 64) -JITCORE_PPC_REG_EXPAND(FPR30, 64) -JITCORE_PPC_REG_EXPAND(FPR31, 64) -JITCORE_PPC_REG_EXPAND(FPSCR, 32) - -JITCORE_PPC_REG_EXPAND(VR0, 128) -JITCORE_PPC_REG_EXPAND(VR1, 128) -JITCORE_PPC_REG_EXPAND(VR2, 128) -JITCORE_PPC_REG_EXPAND(VR3, 128) -JITCORE_PPC_REG_EXPAND(VR4, 128) -JITCORE_PPC_REG_EXPAND(VR5, 128) -JITCORE_PPC_REG_EXPAND(VR6, 128) -JITCORE_PPC_REG_EXPAND(VR7, 128) -JITCORE_PPC_REG_EXPAND(VR8, 128) -JITCORE_PPC_REG_EXPAND(VR9, 128) -JITCORE_PPC_REG_EXPAND(VR10, 128) -JITCORE_PPC_REG_EXPAND(VR11, 128) -JITCORE_PPC_REG_EXPAND(VR12, 128) -JITCORE_PPC_REG_EXPAND(VR13, 128) -JITCORE_PPC_REG_EXPAND(VR14, 128) -JITCORE_PPC_REG_EXPAND(VR15, 128) -JITCORE_PPC_REG_EXPAND(VR16, 128) -JITCORE_PPC_REG_EXPAND(VR17, 128) -JITCORE_PPC_REG_EXPAND(VR18, 128) -JITCORE_PPC_REG_EXPAND(VR19, 128) -JITCORE_PPC_REG_EXPAND(VR20, 128) -JITCORE_PPC_REG_EXPAND(VR21, 128) -JITCORE_PPC_REG_EXPAND(VR22, 128) -JITCORE_PPC_REG_EXPAND(VR23, 128) -JITCORE_PPC_REG_EXPAND(VR24, 128) -JITCORE_PPC_REG_EXPAND(VR25, 128) -JITCORE_PPC_REG_EXPAND(VR26, 128) -JITCORE_PPC_REG_EXPAND(VR27, 128) -JITCORE_PPC_REG_EXPAND(VR28, 128) -JITCORE_PPC_REG_EXPAND(VR29, 128) -JITCORE_PPC_REG_EXPAND(VR30, 128) -JITCORE_PPC_REG_EXPAND(VR31, 128) -JITCORE_PPC_REG_EXPAND(VRSAVE, 32) -JITCORE_PPC_REG_EXPAND(VSCR, 32) diff --git a/miasm/jitter/arch/JitCore_x86.c b/miasm/jitter/arch/JitCore_x86.c deleted file mode 100644 index 9081f3d8..00000000 --- a/miasm/jitter/arch/JitCore_x86.c +++ /dev/null @@ -1,903 +0,0 @@ -#include <Python.h> -#include "structmember.h" -#include <stdint.h> -#include <inttypes.h> -#include "../compat_py23.h" -#include "../queue.h" -#include "../vm_mngr.h" -#include "../bn.h" -#include "../vm_mngr_py.h" -#include "../JitCore.h" -#include "../op_semantics.h" -#include "JitCore_x86.h" - - -struct vm_cpu ref_arch_regs; - -reg_dict gpreg_dict[] = { - {.name = "RAX", .offset = offsetof(struct vm_cpu, RAX), .size = 64}, - {.name = "RBX", .offset = offsetof(struct vm_cpu, RBX), .size = 64}, - {.name = "RCX", .offset = offsetof(struct vm_cpu, RCX), .size = 64}, - {.name = "RDX", .offset = offsetof(struct vm_cpu, RDX), .size = 64}, - {.name = "RSI", .offset = offsetof(struct vm_cpu, RSI), .size = 64}, - {.name = "RDI", .offset = offsetof(struct vm_cpu, RDI), .size = 64}, - {.name = "RSP", .offset = offsetof(struct vm_cpu, RSP), .size = 64}, - {.name = "RBP", .offset = offsetof(struct vm_cpu, RBP), .size = 64}, - - {.name = "R8", .offset = offsetof(struct vm_cpu, R8), .size = 64}, - {.name = "R9", .offset = offsetof(struct vm_cpu, R9), .size = 64}, - {.name = "R10", .offset = offsetof(struct vm_cpu, R10), .size = 64}, - {.name = "R11", .offset = offsetof(struct vm_cpu, R11), .size = 64}, - {.name = "R12", .offset = offsetof(struct vm_cpu, R12), .size = 64}, - {.name = "R13", .offset = offsetof(struct vm_cpu, R13), .size = 64}, - {.name = "R14", .offset = offsetof(struct vm_cpu, R14), .size = 64}, - {.name = "R15", .offset = offsetof(struct vm_cpu, R15), .size = 64}, - - {.name = "RIP", .offset = offsetof(struct vm_cpu, RIP), .size = 64}, - - {.name = "zf", .offset = offsetof(struct vm_cpu, zf), .size = 8}, - {.name = "nf", .offset = offsetof(struct vm_cpu, nf), .size = 8}, - {.name = "pf", .offset = offsetof(struct vm_cpu, pf), .size = 8}, - {.name = "of", .offset = offsetof(struct vm_cpu, of), .size = 8}, - {.name = "cf", .offset = offsetof(struct vm_cpu, cf), .size = 8}, - {.name = "af", .offset = offsetof(struct vm_cpu, af), .size = 8}, - {.name = "df", .offset = offsetof(struct vm_cpu, df), .size = 8}, - - {.name = "ES", .offset = offsetof(struct vm_cpu, ES), .size = 16}, - {.name = "CS", .offset = offsetof(struct vm_cpu, CS), .size = 16}, - {.name = "SS", .offset = offsetof(struct vm_cpu, SS), .size = 16}, - {.name = "DS", .offset = offsetof(struct vm_cpu, DS), .size = 16}, - {.name = "FS", .offset = offsetof(struct vm_cpu, FS), .size = 16}, - {.name = "GS", .offset = offsetof(struct vm_cpu, GS), .size = 16}, - - {.name = "MM0", .offset = offsetof(struct vm_cpu, MM0), .size = 64}, - {.name = "MM1", .offset = offsetof(struct vm_cpu, MM1), .size = 64}, - {.name = "MM2", .offset = offsetof(struct vm_cpu, MM2), .size = 64}, - {.name = "MM3", .offset = offsetof(struct vm_cpu, MM3), .size = 64}, - {.name = "MM4", .offset = offsetof(struct vm_cpu, MM4), .size = 64}, - {.name = "MM5", .offset = offsetof(struct vm_cpu, MM5), .size = 64}, - {.name = "MM6", .offset = offsetof(struct vm_cpu, MM6), .size = 64}, - {.name = "MM7", .offset = offsetof(struct vm_cpu, MM7), .size = 64}, - - {.name = "XMM0", .offset = offsetof(struct vm_cpu, XMM0), .size = 128}, - {.name = "XMM1", .offset = offsetof(struct vm_cpu, XMM1), .size = 128}, - {.name = "XMM2", .offset = offsetof(struct vm_cpu, XMM2), .size = 128}, - {.name = "XMM3", .offset = offsetof(struct vm_cpu, XMM3), .size = 128}, - {.name = "XMM4", .offset = offsetof(struct vm_cpu, XMM4), .size = 128}, - {.name = "XMM5", .offset = offsetof(struct vm_cpu, XMM5), .size = 128}, - {.name = "XMM6", .offset = offsetof(struct vm_cpu, XMM6), .size = 128}, - {.name = "XMM7", .offset = offsetof(struct vm_cpu, XMM7), .size = 128}, - {.name = "XMM8", .offset = offsetof(struct vm_cpu, XMM8), .size = 128}, - {.name = "XMM9", .offset = offsetof(struct vm_cpu, XMM9), .size = 128}, - {.name = "XMM10", .offset = offsetof(struct vm_cpu, XMM10), .size = 128}, - {.name = "XMM11", .offset = offsetof(struct vm_cpu, XMM11), .size = 128}, - {.name = "XMM12", .offset = offsetof(struct vm_cpu, XMM12), .size = 128}, - {.name = "XMM13", .offset = offsetof(struct vm_cpu, XMM13), .size = 128}, - {.name = "XMM14", .offset = offsetof(struct vm_cpu, XMM14), .size = 128}, - {.name = "XMM15", .offset = offsetof(struct vm_cpu, XMM15), .size = 128}, - - {.name = "tsc", .offset = offsetof(struct vm_cpu, tsc), .size = 64}, - - {.name = "exception_flags", .offset = offsetof(struct vm_cpu, exception_flags), .size = 32}, - {.name = "interrupt_num", .offset = offsetof(struct vm_cpu, interrupt_num), .size = 32}, -}; - - - -/************************** JitCpu object **************************/ - - - - - -PyObject* cpu_get_gpreg(JitCpu* self) -{ - PyObject *dict = PyDict_New(); - PyObject *o; - - get_reg(RAX); - get_reg(RBX); - get_reg(RCX); - get_reg(RDX); - get_reg(RSI); - get_reg(RDI); - get_reg(RSP); - get_reg(RBP); - - get_reg(R8); - get_reg(R9); - get_reg(R10); - get_reg(R11); - get_reg(R12); - get_reg(R13); - get_reg(R14); - get_reg(R15); - - get_reg(RIP); - - get_reg(zf); - get_reg(nf); - get_reg(pf); - get_reg(of); - get_reg(cf); - get_reg(af); - get_reg(df); - - - get_reg(ES); - get_reg(CS); - get_reg(SS); - get_reg(DS); - get_reg(FS); - get_reg(GS); - - get_reg(MM0); - get_reg(MM1); - get_reg(MM2); - get_reg(MM3); - get_reg(MM4); - get_reg(MM5); - get_reg(MM6); - get_reg(MM7); - - get_reg_bn(XMM0, 128); - get_reg_bn(XMM1, 128); - get_reg_bn(XMM2, 128); - get_reg_bn(XMM3, 128); - get_reg_bn(XMM4, 128); - get_reg_bn(XMM5, 128); - get_reg_bn(XMM6, 128); - get_reg_bn(XMM7, 128); - get_reg_bn(XMM8, 128); - get_reg_bn(XMM9, 128); - get_reg_bn(XMM10, 128); - get_reg_bn(XMM11, 128); - get_reg_bn(XMM12, 128); - get_reg_bn(XMM13, 128); - get_reg_bn(XMM14, 128); - get_reg_bn(XMM15, 128); - - get_reg(tsc); - - return dict; -} - - -PyObject* cpu_set_gpreg(JitCpu* self, PyObject *args) -{ - PyObject* dict; - PyObject *d_key, *d_value = NULL; - const char *d_key_name; - Py_ssize_t pos = 0; - uint8_t val08; - uint16_t val16; - uint32_t val32; - uint64_t val64; - unsigned int i, found; - - if (!PyArg_ParseTuple(args, "O", &dict)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - if(!PyDict_Check(dict)) - RAISE(PyExc_TypeError, "arg must be dict"); - while(PyDict_Next(dict, &pos, &d_key, &d_value)){ - PyGetStr(d_key_name, d_key); - found = 0; - for (i=0; i < sizeof(gpreg_dict)/sizeof(reg_dict); i++){ - if (strcmp(d_key_name, gpreg_dict[i].name)) - continue; - found = 1; - switch (gpreg_dict[i].size) { - default: - RAISE(PyExc_TypeError, "Unsupported size"); - break; - case 8: - PyGetInt_uint8_t(d_value, val08); - *((uint8_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val08; - break; - case 16: - PyGetInt_uint16_t(d_value, val16); - *((uint16_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val16; - break; - case 32: - PyGetInt_uint32_t(d_value, val32); - *((uint32_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val32; - break; - case 64: - PyGetInt_uint64_t(d_value, val64); - *((uint64_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset)) = val64; - break; - case 128: - { - bn_t bn; - PyObject* py_long = d_value; - - -#if PY_MAJOR_VERSION >= 3 - if (PyLong_Check(py_long)){ - /* Already PyLong */ - /* Increment ref as we will decement it next */ - Py_INCREF(py_long); - } else { - RAISE(PyExc_TypeError,"arg must be int"); - } -#else - uint64_t tmp; - - if (PyInt_Check(py_long)){ - tmp = (uint64_t)PyInt_AsLong(py_long); - py_long = PyLong_FromLong((long)tmp); - } else if (PyLong_Check(py_long)){ - /* Already PyLong */ - /* Increment ref as we will decement it next */ - Py_INCREF(py_long); - } - else{ - RAISE(PyExc_TypeError,"arg must be int"); - } -#endif - - bn = PyLong_to_bn(py_long); - *(bn_t*)(((char*)(self->cpu)) + gpreg_dict[i].offset) = bignum_mask(bn, 128); - } - break; - } - break; - } - - if (found) - continue; - fprintf(stderr, "unknown key: %s\n", d_key_name); - RAISE(PyExc_ValueError, "unknown reg"); - } - Py_INCREF(Py_None); - return Py_None; -} - -PyObject * cpu_init_regs(JitCpu* self) -{ - memset(self->cpu, 0, sizeof(struct vm_cpu)); - ((struct vm_cpu*)self->cpu)->tsc = 0x1122334455667788ULL; - ((struct vm_cpu*)self->cpu)->i_f = 1; - Py_INCREF(Py_None); - return Py_None; - -} - -void dump_gpregs_16(struct vm_cpu* vmcpu) -{ - printf("EAX %.8"PRIX32" EBX %.8"PRIX32" ECX %.8"PRIX32" EDX %.8"PRIX32" ", - (uint32_t)(vmcpu->RAX & 0xFFFFFFFF), - (uint32_t)(vmcpu->RBX & 0xFFFFFFFF), - (uint32_t)(vmcpu->RCX & 0xFFFFFFFF), - (uint32_t)(vmcpu->RDX & 0xFFFFFFFF)); - printf("ESI %.8"PRIX32" EDI %.8"PRIX32" ESP %.8"PRIX32" EBP %.8"PRIX32" ", - (uint32_t)(vmcpu->RSI & 0xFFFFFFFF), - (uint32_t)(vmcpu->RDI & 0xFFFFFFFF), - (uint32_t)(vmcpu->RSP & 0xFFFFFFFF), - (uint32_t)(vmcpu->RBP & 0xFFFFFFFF)); - printf("EIP %.8"PRIX32" ", - (uint32_t)(vmcpu->RIP & 0xFFFFFFFF)); - printf("zf %.1d nf %.1d of %.1d cf %.1d\n", - (uint32_t)(vmcpu->zf & 0x1), - (uint32_t)(vmcpu->nf & 0x1), - (uint32_t)(vmcpu->of & 0x1), - (uint32_t)(vmcpu->cf & 0x1)); -} - -void dump_gpregs_32(struct vm_cpu* vmcpu) -{ - - printf("EAX %.8"PRIX32" EBX %.8"PRIX32" ECX %.8"PRIX32" EDX %.8"PRIX32" ", - (uint32_t)(vmcpu->RAX & 0xFFFFFFFF), - (uint32_t)(vmcpu->RBX & 0xFFFFFFFF), - (uint32_t)(vmcpu->RCX & 0xFFFFFFFF), - (uint32_t)(vmcpu->RDX & 0xFFFFFFFF)); - printf("ESI %.8"PRIX32" EDI %.8"PRIX32" ESP %.8"PRIX32" EBP %.8"PRIX32" ", - (uint32_t)(vmcpu->RSI & 0xFFFFFFFF), - (uint32_t)(vmcpu->RDI & 0xFFFFFFFF), - (uint32_t)(vmcpu->RSP & 0xFFFFFFFF), - (uint32_t)(vmcpu->RBP & 0xFFFFFFFF)); - printf("EIP %.8"PRIX32" ", - (uint32_t)(vmcpu->RIP & 0xFFFFFFFF)); - printf("zf %.1d nf %.1d of %.1d cf %.1d\n", - (uint32_t)(vmcpu->zf & 0x1), - (uint32_t)(vmcpu->nf & 0x1), - (uint32_t)(vmcpu->of & 0x1), - (uint32_t)(vmcpu->cf & 0x1)); - -} - -void dump_gpregs_64(struct vm_cpu* vmcpu) -{ - - printf("RAX %.16"PRIX64" RBX %.16"PRIX64" RCX %.16"PRIX64" RDX %.16"PRIX64" ", - vmcpu->RAX, vmcpu->RBX, vmcpu->RCX, vmcpu->RDX); - printf("RSI %.16"PRIX64" RDI %.16"PRIX64" RSP %.16"PRIX64" RBP %.16"PRIX64" ", - vmcpu->RSI, vmcpu->RDI, vmcpu->RSP, vmcpu->RBP); - printf("RIP %.16"PRIX64"\n", - vmcpu->RIP); - printf("R8 %.16"PRIX64" R9 %.16"PRIX64" R10 %.16"PRIX64" R11 %.16"PRIX64" ", - vmcpu->R8, vmcpu->R9, vmcpu->R10, vmcpu->R11); - printf("R12 %.16"PRIX64" R13 %.16"PRIX64" R14 %.16"PRIX64" R15 %.16"PRIX64" ", - vmcpu->R12, vmcpu->R13, vmcpu->R14, vmcpu->R15); - - - printf("zf %.1d nf %.1d of %.1d cf %.1d\n", - vmcpu->zf, vmcpu->nf, vmcpu->of, vmcpu->cf); - -} - -PyObject * cpu_dump_gpregs(JitCpu* self, PyObject* args) -{ - struct vm_cpu* vmcpu; - - vmcpu = self->cpu; - dump_gpregs_64(vmcpu); - Py_INCREF(Py_None); - return Py_None; -} - - -PyObject * cpu_dump_gpregs_with_attrib(JitCpu* self, PyObject* args) -{ - struct vm_cpu* vmcpu; - PyObject *item1; - uint64_t attrib; - - if (!PyArg_ParseTuple(args, "O", &item1)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(item1, attrib); - - vmcpu = self->cpu; - if (attrib == 16 || attrib == 32) - dump_gpregs_32(vmcpu); - else if (attrib == 64) - dump_gpregs_64(vmcpu); - else { - RAISE(PyExc_TypeError,"Bad attrib"); - } - - Py_INCREF(Py_None); - return Py_None; -} - - - -PyObject* cpu_set_exception(JitCpu* self, PyObject* args) -{ - PyObject *item1; - uint32_t exception_flags; - - if (!PyArg_ParseTuple(args, "O", &item1)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint32_t(item1, exception_flags); - - ((struct vm_cpu*)self->cpu)->exception_flags = exception_flags; - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* cpu_get_exception(JitCpu* self, PyObject* args) -{ - return PyLong_FromUnsignedLongLong((uint64_t)(((struct vm_cpu*)self->cpu)->exception_flags)); -} - -PyObject* cpu_set_interrupt_num(JitCpu* self, PyObject* args) -{ - PyObject *item1; - uint32_t exception_flags; - - if (!PyArg_ParseTuple(args, "O", &item1)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint32_t(item1, exception_flags); - - ((struct vm_cpu*)self->cpu)->interrupt_num = exception_flags; - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* cpu_get_interrupt_num(JitCpu* self, PyObject* args) -{ - return PyLong_FromUnsignedLongLong((uint64_t)(((struct vm_cpu*)self->cpu)->interrupt_num)); -} - -PyObject* cpu_set_segm_base(JitCpu* self, PyObject* args) -{ - PyObject *item1, *item2; - uint64_t segm_num, segm_base; - - if (!PyArg_ParseTuple(args, "OO", &item1, &item2)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(item1, segm_num); - PyGetInt_uint64_t(item2, segm_base); - ((struct vm_cpu*)self->cpu)->segm_base[segm_num & 0xFFFF] = segm_base; - - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* cpu_get_segm_base(JitCpu* self, PyObject* args) -{ - PyObject *item1; - uint64_t segm_num; - PyObject* v; - - if (!PyArg_ParseTuple(args, "O", &item1)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - PyGetInt_uint64_t(item1, segm_num); - v = PyLong_FromLong((long)(((struct vm_cpu*)self->cpu)->segm_base[segm_num & 0xFFFF])); - return v; -} - -uint64_t segm2addr(JitCpu* jitcpu, uint64_t segm, uint64_t addr) -{ - return addr + ((struct vm_cpu*)jitcpu->cpu)->segm_base[segm & 0xFFFF]; -} - -void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src) -{ - vm_MEM_WRITE_08(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src) -{ - vm_MEM_WRITE_16(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src) -{ - vm_MEM_WRITE_32(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - -void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src) -{ - vm_MEM_WRITE_64(&((VmMngr*)jitcpu->pyvm)->vm_mngr, addr, src); -} - - - -static PyMemberDef JitCpu_members[] = { - {NULL} /* Sentinel */ -}; - -static PyMethodDef JitCpu_methods[] = { - {"init_regs", (PyCFunction)cpu_init_regs, METH_NOARGS, - "X"}, - {"dump_gpregs", (PyCFunction)cpu_dump_gpregs, METH_NOARGS, - "X"}, - {"dump_gpregs_with_attrib", (PyCFunction)cpu_dump_gpregs_with_attrib, METH_VARARGS, - "X"}, - {"get_gpreg", (PyCFunction)cpu_get_gpreg, METH_NOARGS, - "X"}, - {"set_gpreg", (PyCFunction)cpu_set_gpreg, METH_VARARGS, - "X"}, - {"get_segm_base", (PyCFunction)cpu_get_segm_base, METH_VARARGS, - "X"}, - {"set_segm_base", (PyCFunction)cpu_set_segm_base, METH_VARARGS, - "X"}, - {"get_exception", (PyCFunction)cpu_get_exception, METH_VARARGS, - "X"}, - {"set_exception", (PyCFunction)cpu_set_exception, METH_VARARGS, - "X"}, - {"get_interrupt_num", (PyCFunction)cpu_get_interrupt_num, METH_VARARGS, - "X"}, - {"set_interrupt_num", (PyCFunction)cpu_set_interrupt_num, METH_VARARGS, - "X"}, - {NULL} /* Sentinel */ -}; - -static int -JitCpu_init(JitCpu *self, PyObject *args, PyObject *kwds) -{ - self->cpu = malloc(sizeof(struct vm_cpu)); - if (self->cpu == NULL) { - fprintf(stderr, "cannot alloc struct vm_cpu\n"); - exit(EXIT_FAILURE); - } - return 0; -} - -#define getset_reg_E_u32(regname) \ - static PyObject *JitCpu_get_E ## regname (JitCpu *self, void *closure) \ - { \ - return PyLong_FromUnsignedLongLong((uint32_t)(self->cpu->R ## regname & 0xFFFFFFFF )); \ - } \ - static int JitCpu_set_E ## regname (JitCpu *self, PyObject *value, void *closure) \ - { \ - uint32_t val32; \ - uint64_t val64; \ - PyGetInt_uint32_t_retneg(value, val32); \ - val64 = val32; \ - val64 |= self->cpu->R ##regname & 0xFFFFFFFF00000000ULL; \ - self->cpu->R ## regname = val64; \ - return 0; \ - } - - - -#define getset_reg_R_u16(regname) \ - static PyObject *JitCpu_get_ ## regname (JitCpu *self, void *closure) \ - { \ - return PyLong_FromUnsignedLongLong((uint16_t)(self->cpu->R ## regname & 0xFFFF )); \ - } \ - static int JitCpu_set_ ## regname (JitCpu *self, PyObject *value, void *closure) \ - { \ - uint16_t val16; \ - uint64_t val64; \ - PyGetInt_uint16_t_retneg(value, val16); \ - val64 = val16; \ - val64 |= self->cpu->R ##regname & 0xFFFFFFFFFFFF0000ULL; \ - self->cpu->R ## regname = val64; \ - return 0; \ - } - - -getset_reg_u64(RAX); -getset_reg_u64(RBX); -getset_reg_u64(RCX); -getset_reg_u64(RDX); -getset_reg_u64(RSI); -getset_reg_u64(RDI); -getset_reg_u64(RSP); -getset_reg_u64(RBP); - -getset_reg_u64(R8); -getset_reg_u64(R9); -getset_reg_u64(R10); -getset_reg_u64(R11); -getset_reg_u64(R12); -getset_reg_u64(R13); -getset_reg_u64(R14); -getset_reg_u64(R15); - -getset_reg_u64(RIP); - -getset_reg_u8(zf); -getset_reg_u8(nf); -getset_reg_u8(pf); -getset_reg_u8(of); -getset_reg_u8(cf); -getset_reg_u8(af); -getset_reg_u8(df); - - -getset_reg_u16(ES); -getset_reg_u16(CS); -getset_reg_u16(SS); -getset_reg_u16(DS); -getset_reg_u16(FS); -getset_reg_u16(GS); - -getset_reg_E_u32(AX); -getset_reg_E_u32(BX); -getset_reg_E_u32(CX); -getset_reg_E_u32(DX); -getset_reg_E_u32(SI); -getset_reg_E_u32(DI); -getset_reg_E_u32(SP); -getset_reg_E_u32(BP); -getset_reg_E_u32(IP); - -getset_reg_R_u16(AX); -getset_reg_R_u16(BX); -getset_reg_R_u16(CX); -getset_reg_R_u16(DX); -getset_reg_R_u16(SI); -getset_reg_R_u16(DI); -getset_reg_R_u16(SP); -getset_reg_R_u16(BP); - -getset_reg_R_u16(IP); - -getset_reg_u64(MM0); -getset_reg_u64(MM1); -getset_reg_u64(MM2); -getset_reg_u64(MM3); -getset_reg_u64(MM4); -getset_reg_u64(MM5); -getset_reg_u64(MM6); -getset_reg_u64(MM7); - -getset_reg_bn(XMM0, 128); -getset_reg_bn(XMM1, 128); -getset_reg_bn(XMM2, 128); -getset_reg_bn(XMM3, 128); -getset_reg_bn(XMM4, 128); -getset_reg_bn(XMM5, 128); -getset_reg_bn(XMM6, 128); -getset_reg_bn(XMM7, 128); -getset_reg_bn(XMM8, 128); -getset_reg_bn(XMM9, 128); -getset_reg_bn(XMM10, 128); -getset_reg_bn(XMM11, 128); -getset_reg_bn(XMM12, 128); -getset_reg_bn(XMM13, 128); -getset_reg_bn(XMM14, 128); -getset_reg_bn(XMM15, 128); - -getset_reg_u64(tsc); - -getset_reg_u32(exception_flags); -getset_reg_u32(interrupt_num); - - -PyObject* get_gpreg_offset_all(void) -{ - PyObject *dict = PyDict_New(); - PyObject *o; - get_reg_off(exception_flags); - - get_reg_off(RAX); - get_reg_off(RBX); - get_reg_off(RCX); - get_reg_off(RDX); - get_reg_off(RSI); - get_reg_off(RDI); - get_reg_off(RSP); - get_reg_off(RBP); - get_reg_off(R8); - get_reg_off(R9); - get_reg_off(R10); - get_reg_off(R11); - get_reg_off(R12); - get_reg_off(R13); - get_reg_off(R14); - get_reg_off(R15); - get_reg_off(RIP); - get_reg_off(zf); - get_reg_off(nf); - get_reg_off(pf); - get_reg_off(of); - get_reg_off(cf); - get_reg_off(af); - get_reg_off(df); - get_reg_off(tf); - get_reg_off(i_f); - get_reg_off(iopl_f); - get_reg_off(nt); - get_reg_off(rf); - get_reg_off(vm); - get_reg_off(ac); - get_reg_off(vif); - get_reg_off(vip); - get_reg_off(i_d); - get_reg_off(my_tick); - get_reg_off(cond); - - get_reg_off(float_st0); - get_reg_off(float_st1); - get_reg_off(float_st2); - get_reg_off(float_st3); - get_reg_off(float_st4); - get_reg_off(float_st5); - get_reg_off(float_st6); - get_reg_off(float_st7); - - get_reg_off(ES); - get_reg_off(CS); - get_reg_off(SS); - get_reg_off(DS); - get_reg_off(FS); - get_reg_off(GS); - - get_reg_off(MM0); - get_reg_off(MM1); - get_reg_off(MM2); - get_reg_off(MM3); - get_reg_off(MM4); - get_reg_off(MM5); - 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(tsc); - - get_reg_off(interrupt_num); - get_reg_off(exception_flags); - - get_reg_off(float_stack_ptr); - get_reg_off(reg_float_cs); - get_reg_off(reg_float_eip); - get_reg_off(reg_float_control); - - return dict; -} - - -static PyGetSetDef JitCpu_getseters[] = { - {"vmmngr", - (getter)JitCpu_get_vmmngr, (setter)JitCpu_set_vmmngr, - "vmmngr", - NULL}, - - {"vmcpu", - (getter)JitCpu_get_vmcpu, (setter)JitCpu_set_vmcpu, - "vmcpu", - NULL}, - - {"jitter", - (getter)JitCpu_get_jitter, (setter)JitCpu_set_jitter, - "jitter", - NULL}, - - - {"RAX", (getter)JitCpu_get_RAX, (setter)JitCpu_set_RAX, "RAX", NULL}, - {"RBX", (getter)JitCpu_get_RBX, (setter)JitCpu_set_RBX, "RBX", NULL}, - {"RCX", (getter)JitCpu_get_RCX, (setter)JitCpu_set_RCX, "RCX", NULL}, - {"RDX", (getter)JitCpu_get_RDX, (setter)JitCpu_set_RDX, "RDX", NULL}, - {"RSI", (getter)JitCpu_get_RSI, (setter)JitCpu_set_RSI, "RSI", NULL}, - {"RDI", (getter)JitCpu_get_RDI, (setter)JitCpu_set_RDI, "RDI", NULL}, - {"RSP", (getter)JitCpu_get_RSP, (setter)JitCpu_set_RSP, "RSP", NULL}, - {"RBP", (getter)JitCpu_get_RBP, (setter)JitCpu_set_RBP, "RBP", NULL}, - {"R8", (getter)JitCpu_get_R8, (setter)JitCpu_set_R8, "R8", NULL}, - {"R9", (getter)JitCpu_get_R9, (setter)JitCpu_set_R9, "R9", NULL}, - {"R10", (getter)JitCpu_get_R10, (setter)JitCpu_set_R10, "R10", NULL}, - {"R11", (getter)JitCpu_get_R11, (setter)JitCpu_set_R11, "R11", NULL}, - {"R12", (getter)JitCpu_get_R12, (setter)JitCpu_set_R12, "R12", NULL}, - {"R13", (getter)JitCpu_get_R13, (setter)JitCpu_set_R13, "R13", NULL}, - {"R14", (getter)JitCpu_get_R14, (setter)JitCpu_set_R14, "R14", NULL}, - {"R15", (getter)JitCpu_get_R15, (setter)JitCpu_set_R15, "R15", NULL}, - {"RIP", (getter)JitCpu_get_RIP, (setter)JitCpu_set_RIP, "RIP", NULL}, - {"zf", (getter)JitCpu_get_zf, (setter)JitCpu_set_zf, "zf", NULL}, - {"nf", (getter)JitCpu_get_nf, (setter)JitCpu_set_nf, "nf", NULL}, - {"pf", (getter)JitCpu_get_pf, (setter)JitCpu_set_pf, "pf", NULL}, - {"of", (getter)JitCpu_get_of, (setter)JitCpu_set_of, "of", NULL}, - {"cf", (getter)JitCpu_get_cf, (setter)JitCpu_set_cf, "cf", NULL}, - {"af", (getter)JitCpu_get_af, (setter)JitCpu_set_af, "af", NULL}, - {"df", (getter)JitCpu_get_df, (setter)JitCpu_set_df, "df", NULL}, - {"ES", (getter)JitCpu_get_ES, (setter)JitCpu_set_ES, "ES", NULL}, - {"CS", (getter)JitCpu_get_CS, (setter)JitCpu_set_CS, "CS", NULL}, - {"SS", (getter)JitCpu_get_SS, (setter)JitCpu_set_SS, "SS", NULL}, - {"DS", (getter)JitCpu_get_DS, (setter)JitCpu_set_DS, "DS", NULL}, - {"FS", (getter)JitCpu_get_FS, (setter)JitCpu_set_FS, "FS", NULL}, - {"GS", (getter)JitCpu_get_GS, (setter)JitCpu_set_GS, "GS", NULL}, - - {"EAX", (getter)JitCpu_get_EAX, (setter)JitCpu_set_EAX, "EAX", NULL}, - {"EBX", (getter)JitCpu_get_EBX, (setter)JitCpu_set_EBX, "EBX", NULL}, - {"ECX", (getter)JitCpu_get_ECX, (setter)JitCpu_set_ECX, "ECX", NULL}, - {"EDX", (getter)JitCpu_get_EDX, (setter)JitCpu_set_EDX, "EDX", NULL}, - {"ESI", (getter)JitCpu_get_ESI, (setter)JitCpu_set_ESI, "ESI", NULL}, - {"EDI", (getter)JitCpu_get_EDI, (setter)JitCpu_set_EDI, "EDI", NULL}, - {"ESP", (getter)JitCpu_get_ESP, (setter)JitCpu_set_ESP, "ESP", NULL}, - {"EBP", (getter)JitCpu_get_EBP, (setter)JitCpu_set_EBP, "EBP", NULL}, - {"EIP", (getter)JitCpu_get_EIP, (setter)JitCpu_set_EIP, "EIP", NULL}, - - {"AX", (getter)JitCpu_get_AX, (setter)JitCpu_set_AX, "AX", NULL}, - {"BX", (getter)JitCpu_get_BX, (setter)JitCpu_set_BX, "BX", NULL}, - {"CX", (getter)JitCpu_get_CX, (setter)JitCpu_set_CX, "CX", NULL}, - {"DX", (getter)JitCpu_get_DX, (setter)JitCpu_set_DX, "DX", NULL}, - {"SI", (getter)JitCpu_get_SI, (setter)JitCpu_set_SI, "SI", NULL}, - {"DI", (getter)JitCpu_get_DI, (setter)JitCpu_set_DI, "DI", NULL}, - {"SP", (getter)JitCpu_get_SP, (setter)JitCpu_set_SP, "SP", NULL}, - {"BP", (getter)JitCpu_get_BP, (setter)JitCpu_set_BP, "BP", NULL}, - - {"IP", (getter)JitCpu_get_IP, (setter)JitCpu_set_IP, "IP", NULL}, - - {"MM0", (getter)JitCpu_get_MM0, (setter)JitCpu_set_MM0, "MM0", NULL}, - {"MM1", (getter)JitCpu_get_MM1, (setter)JitCpu_set_MM1, "MM1", NULL}, - {"MM2", (getter)JitCpu_get_MM2, (setter)JitCpu_set_MM2, "MM2", NULL}, - {"MM3", (getter)JitCpu_get_MM3, (setter)JitCpu_set_MM3, "MM3", NULL}, - {"MM4", (getter)JitCpu_get_MM4, (setter)JitCpu_set_MM4, "MM4", NULL}, - {"MM5", (getter)JitCpu_get_MM5, (setter)JitCpu_set_MM5, "MM5", NULL}, - {"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}, - - {"tsc", (getter)JitCpu_get_tsc, (setter)JitCpu_set_tsc, "tsc", NULL}, - - {"exception_flags", (getter)JitCpu_get_exception_flags, (setter)JitCpu_set_exception_flags, "exception_flags", NULL}, - {"interrupt_num", (getter)JitCpu_get_interrupt_num, (setter)JitCpu_set_interrupt_num, "interrupt_num", NULL}, - - - {NULL} /* Sentinel */ -}; - - -static PyTypeObject JitCpuType = { - PyVarObject_HEAD_INIT(NULL, 0) - "JitCore_x86.JitCpu", /*tp_name*/ - sizeof(JitCpu), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)JitCpu_dealloc,/*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "JitCpu objects", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - JitCpu_methods, /* tp_methods */ - JitCpu_members, /* tp_members */ - JitCpu_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)JitCpu_init, /* tp_init */ - 0, /* tp_alloc */ - JitCpu_new, /* tp_new */ -}; - - - -static PyMethodDef JitCore_x86_Methods[] = { - - /* - - */ - {"get_gpreg_offset_all", (PyCFunction)get_gpreg_offset_all, METH_NOARGS}, - {NULL, NULL, 0, NULL} /* Sentinel */ - -}; - - -MOD_INIT(JitCore_x86) -{ - PyObject *module = NULL; - - MOD_DEF(module, "JitCore_x86", "JitCore_x86 module", JitCore_x86_Methods); - - if (module == NULL) - RET_MODULE; - - if (PyType_Ready(&JitCpuType) < 0) - RET_MODULE; - - Py_INCREF(&JitCpuType); - if (PyModule_AddObject(module, "JitCpu", (PyObject *)&JitCpuType) < 0) - RET_MODULE; - - RET_MODULE; -} diff --git a/miasm/jitter/arch/JitCore_x86.h b/miasm/jitter/arch/JitCore_x86.h deleted file mode 100644 index 5c005e86..00000000 --- a/miasm/jitter/arch/JitCore_x86.h +++ /dev/null @@ -1,136 +0,0 @@ -#include "../bn.h" - -#if _WIN32 -#define _MIASM_EXPORT __declspec(dllexport) -#else -#define _MIASM_EXPORT -#endif - -struct vm_cpu { - uint32_t exception_flags; - uint32_t interrupt_num; - - - /* gpregs */ - uint64_t RAX; - uint64_t RBX; - uint64_t RCX; - uint64_t RDX; - uint64_t RSI; - uint64_t RDI; - uint64_t RSP; - uint64_t RBP; - uint64_t R8; - uint64_t R9; - uint64_t R10; - uint64_t R11; - uint64_t R12; - uint64_t R13; - uint64_t R14; - uint64_t R15; - - uint64_t RIP; - - /* eflag */ - uint8_t zf; - uint8_t nf; - uint8_t pf; - uint8_t of; - uint8_t cf; - uint8_t af; - uint8_t df; - - uint8_t tf; - uint8_t i_f; - uint8_t iopl_f; - uint8_t nt; - uint8_t rf; - uint8_t vm; - uint8_t ac; - uint8_t vif; - uint8_t vip; - uint8_t i_d; - - bn_t my_tick; - - bn_t cond; - - uint64_t float_st0; - uint64_t float_st1; - uint64_t float_st2; - uint64_t float_st3; - uint64_t float_st4; - uint64_t float_st5; - uint64_t float_st6; - uint64_t float_st7; - - unsigned int float_c0; - unsigned int float_c1; - unsigned int float_c2; - unsigned int float_c3; - - - unsigned int float_stack_ptr; - - unsigned int reg_float_control; - - unsigned int reg_float_eip; - unsigned int reg_float_cs; - unsigned int reg_float_address; - unsigned int reg_float_ds; - - - uint64_t tsc; - - - uint16_t ES; - uint16_t CS; - uint16_t SS; - uint16_t DS; - uint16_t FS; - uint16_t GS; - - unsigned int cr0; - unsigned int cr3; - - uint64_t MM0; - uint64_t MM1; - uint64_t MM2; - uint64_t MM3; - uint64_t MM4; - uint64_t MM5; - uint64_t MM6; - uint64_t MM7; - - /* SSE */ - bn_t XMM0; - bn_t XMM1; - bn_t XMM2; - bn_t XMM3; - bn_t XMM4; - bn_t XMM5; - bn_t XMM6; - bn_t XMM7; - bn_t XMM8; - bn_t XMM9; - bn_t XMM10; - bn_t XMM11; - bn_t XMM12; - bn_t XMM13; - bn_t XMM14; - bn_t XMM15; - - uint64_t segm_base[0x10000]; - -}; - -_MIASM_EXPORT void dump_gpregs_32(struct vm_cpu* vmcpu); -_MIASM_EXPORT void dump_gpregs_64(struct vm_cpu* vmcpu); -_MIASM_EXPORT uint64_t segm2addr(JitCpu* jitcpu, uint64_t segm, uint64_t addr); - -_MIASM_EXPORT void MEM_WRITE_08(JitCpu* jitcpu, uint64_t addr, uint8_t src); -_MIASM_EXPORT void MEM_WRITE_16(JitCpu* jitcpu, uint64_t addr, uint16_t src); -_MIASM_EXPORT void MEM_WRITE_32(JitCpu* jitcpu, uint64_t addr, uint32_t src); -_MIASM_EXPORT void MEM_WRITE_64(JitCpu* jitcpu, uint64_t addr, uint64_t src); - -#define RETURN_PC return BlockDst; diff --git a/miasm/jitter/arch/__init__.py b/miasm/jitter/arch/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/miasm/jitter/arch/__init__.py +++ /dev/null diff --git a/miasm/jitter/bn.c b/miasm/jitter/bn.c deleted file mode 100644 index 43e552a4..00000000 --- a/miasm/jitter/bn.c +++ /dev/null @@ -1,933 +0,0 @@ -/* - -Big number library - arithmetic on multiple-precision unsigned integers. - -This library is an implementation of arithmetic on arbitrarily large integers. - -The difference between this and other implementations, is that the data structure -has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), -and all memory is allocated statically: no dynamic allocation for better or worse. - -Primary goals are correctness, clarity of code and clean, portable implementation. -Secondary goal is a memory footprint small enough to make it suitable for use in -embedded applications. - - -The current state is correct functionality and adequate performance. -There may well be room for performance-optimizations and improvements. - -Source: https://github.com/kokke/tiny-bignum-c - -Code slightly modified to support ast generation calculus style from Expr. - -*/ - -#include <stdio.h> -#include <stdbool.h> -#include <inttypes.h> -#include <assert.h> -#include "bn.h" - -/* Functions for shifting number in-place. */ -static bn_t _lshift_one_bit(bn_t a); -static bn_t _rshift_one_bit(bn_t a); -static bn_t _lshift_word(bn_t a, int nwords); -static bn_t _rshift_word(bn_t a, int nwords); - - - - -/* Public / Exported functions. */ -bn_t bignum_init(void) -{ - int i; - bn_t n; - - for (i = 0; i < BN_ARRAY_SIZE; ++i) { - n.array[i] = 0; - } - - return n; -} - - -bn_t bignum_from_int(DTYPE_TMP i) -{ - bn_t n; - - n = bignum_init(); - /* Endianness issue if machine is not little-endian? */ -#ifdef WORD_SIZE - #if (WORD_SIZE == 1) - n.array[0] = (i & 0x000000ff); - n.array[1] = (i & 0x0000ff00) >> 8; - n.array[2] = (i & 0x00ff0000) >> 16; - n.array[3] = (i & 0xff000000) >> 24; - #elif (WORD_SIZE == 2) - n.array[0] = (i & 0x0000ffff); - n.array[1] = (i & 0xffff0000) >> 16; - #elif (WORD_SIZE == 4) - n.array[0] = (DTYPE)i; - DTYPE_TMP num_32 = 32; - DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */ - n.array[1] = (DTYPE)tmp; - #endif -#endif - - return n; -} - - - -bn_t bignum_from_uint64(uint64_t i) -{ - bn_t n; - n = bignum_init(); - /* Endianness issue if machine is not little-endian? */ -#ifdef WORD_SIZE - #if (WORD_SIZE == 1) - n.array[0] = (i & 0x000000ff); - n.array[1] = (i & 0x0000ff00) >> 8; - n.array[2] = (i & 0x00ff0000) >> 16; - n.array[3] = (i & 0xff000000) >> 24; - #elif (WORD_SIZE == 2) - n.array[0] = (i & 0x0000ffff); - n.array[1] = (i & 0xffff0000) >> 16; - #elif (WORD_SIZE == 4) - n.array[0] = (DTYPE)i; - DTYPE_TMP num_32 = 32; - DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */ - n.array[1] = (DTYPE)tmp; - #endif -#endif - - return n; -} - - - - - -int bignum_to_int(bn_t n) -{ - - int ret = 0; - - /* Endianness issue if machine is not little-endian? */ -#if (WORD_SIZE == 1) - ret += n.array[0]; - ret += n.array[1] << 8; - ret += n.array[2] << 16; - ret += n.array[3] << 24; -#elif (WORD_SIZE == 2) - ret += n.array[0]; - ret += n.array[1] << 16; -#elif (WORD_SIZE == 4) - ret += n.array[0]; -#endif - - - return ret; -} - - -uint64_t bignum_to_uint64(bn_t n) -{ - - uint64_t ret = 0; - - /* Endianness issue if machine is not little-endian? */ -#if (WORD_SIZE == 1) - ret += (uint64_t)(n.array[0]); - ret += (uint64_t)(n.array[1]) << 8; - ret += (uint64_t)(n.array[2]) << 16; - ret += (uint64_t)(n.array[3]) << 24; - - ret += (uint64_t)(n.array[4]) << 32; - ret += (uint64_t)(n.array[5]) << 40; - ret += (uint64_t)(n.array[6]) << 48; - ret += (uint64_t)(n.array[7]) << 56; - - -#elif (WORD_SIZE == 2) - ret += (uint64_t)(n.array[0]); - ret += (uint64_t)(n.array[1]) << 16; - ret += (uint64_t)(n.array[2]) << 32; - ret += (uint64_t)(n.array[3]) << 48; -#elif (WORD_SIZE == 4) - ret += n.array[0]; - ret += (uint64_t)(n.array[1]) << 32; -#endif - - return ret; -} - - - - -bn_t bignum_from_string(char* str, int nbytes) -{ - - require(str, "str is null"); - require(nbytes > 0, "nbytes must be positive"); - require((nbytes & 1) == 0, "string format must be in hex -> equal number of bytes"); - - bn_t n; - - n = bignum_init(); - - DTYPE tmp; /* DTYPE is defined in bn.h - uint{8,16,32,64}_t */ - int i = nbytes - (2 * WORD_SIZE); /* index into string */ - int j = 0; /* index into array */ - - /* reading last hex-byte "MSB" from string first -> big endian */ - /* MSB ~= most significant byte / block ? :) */ - while (i >= 0) { - tmp = 0; - sscanf(&str[i], SSCANF_FORMAT_STR, &tmp); - n.array[j] = tmp; - i -= (2 * WORD_SIZE); /* step WORD_SIZE hex-byte(s) back in the string. */ - j += 1; /* step one element forward in the array. */ - } - - return n; -} - -void bignum_to_string(bn_t n, char* str, int nbytes) -{ - require(str, "str is null"); - require(nbytes > 0, "nbytes must be positive"); - require((nbytes & 1) == 0, "string format must be in hex -> equal number of bytes"); - - int j = BN_ARRAY_SIZE - 1; /* index into array - reading "MSB" first -> big-endian */ - int i = 0; /* index into string representation. */ - - /* reading last array-element "MSB" first -> big endian */ - while ((j >= 0) && (nbytes > (i + 1))) { - sprintf(&str[i], SPRINTF_FORMAT_STR, n.array[j]); - i += (2 * WORD_SIZE); /* step WORD_SIZE hex-byte(s) forward in the string. */ - j -= 1; /* step one element back in the array. */ - } - - /* Zero-terminate string */ - str[i] = 0; -} - - - -bn_t bignum_dec(bn_t n) -{ - //require(n, "n is null"); - - DTYPE tmp; /* copy of n */ - DTYPE res; - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) { - tmp = n.array[i]; - res = tmp - 1; - n.array[i] = res; - - if (!(res > tmp)) { - break; - } - } - - return n; -} - - -bn_t bignum_inc(bn_t n) -{ - //require(n, "n is null"); - - DTYPE res; - DTYPE tmp; /* copy of n */ - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) { - tmp = n.array[i]; - res = tmp + 1; - n.array[i] = res; - - if (res > tmp) { - break; - } - } - - return n; -} - - - -bn_t bignum_add(bn_t a, bn_t b) -{ - //require(a, "a is null"); - //require(b, "b is null"); - //require(c, "c is null"); - bn_t c; - - DTYPE_TMP tmp; - int carry = 0; - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) { - tmp = (DTYPE_TMP)a.array[i] + b.array[i] + carry; - carry = (tmp > MAX_VAL); - c.array[i] = (tmp & MAX_VAL); - } - - return c; -} - - -bn_t bignum_sub(bn_t a, bn_t b) -{ - //require(a, "a is null"); - //require(b, "b is null"); - //require(c, "c is null"); - bn_t c; - - DTYPE_TMP res; - DTYPE_TMP tmp1; - DTYPE_TMP tmp2; - int borrow = 0; - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) { - tmp1 = (DTYPE_TMP)a.array[i] + (MAX_VAL + 1); /* + number_base */ - tmp2 = (DTYPE_TMP)b.array[i] + borrow;; - res = (tmp1 - tmp2); - c.array[i] = (DTYPE)(res & MAX_VAL); /* "modulo number_base" == "% (number_base - 1)" if number_base is 2^N */ - borrow = (res <= MAX_VAL); - } - - return c; -} - - - - -bn_t bignum_mul(bn_t a, bn_t b) -{ - //require(a, "a is null"); - //require(b, "b is null"); - //require(c, "c is null"); - - bn_t c; - bn_t row; - bn_t tmp; - int i, j; - - c = bignum_init(); - - for (i = 0; i < BN_ARRAY_SIZE; ++i) { - row = bignum_init(); - - for (j = 0; j < BN_ARRAY_SIZE; ++j) { - if (i + j < BN_ARRAY_SIZE) { - tmp = bignum_init(); - DTYPE_TMP intermediate = ((DTYPE_TMP)a.array[i] * (DTYPE_TMP)b.array[j]); - tmp = bignum_from_int(intermediate); - tmp = _lshift_word(tmp, i + j); - row = bignum_add(tmp, row); - } - } - c = bignum_add(c, row); - } - - return c; -} - - -bn_t bignum_udiv(bn_t a, bn_t b) -{ - //require(a, "a is null"); - //require(b, "b is null"); - //require(c, "c is null"); - - bn_t c; - bn_t current; - bn_t denom; - bn_t tmp; - - current = bignum_from_int(1); // int current = 1; - denom = bignum_assign(b); // denom = b - tmp = bignum_assign(a); // tmp = a - - const DTYPE_TMP half_max = 1 + (DTYPE_TMP)(MAX_VAL / 2); - bool overflow = false; - - while (bignum_cmp(denom, a) != LARGER) { // while (denom <= a) { - if (denom.array[BN_ARRAY_SIZE - 1] >= half_max) { - overflow = true; - break; - } - current = _lshift_one_bit(current); // current <<= 1; - denom = _lshift_one_bit(denom); // denom <<= 1; - } - if (!overflow) { - denom = _rshift_one_bit(denom); // denom >>= 1; - current = _rshift_one_bit(current); // current >>= 1; - } - c = bignum_init(); // int answer = 0; - - while (!bignum_is_zero(current)) { // while (current != 0) - if (bignum_cmp(tmp, denom) != SMALLER) { // if (dividend >= denom) - tmp = bignum_sub(tmp, denom); // dividend -= denom; - c = bignum_or(c, current); // answer |= current; - } - current = _rshift_one_bit(current); // current >>= 1; - denom = _rshift_one_bit(denom); // denom >>= 1; - } // return answer; - - return c; -} - - - -bn_t bignum_lshift(bn_t a, int nbits) -{ - //require(a, "a is null"); - //require(b, "b is null"); - require(nbits >= 0, "no negative shifts"); - - bn_t b; - - b = bignum_assign(a); - /* Handle shift in multiples of word-size */ - const int nbits_pr_word = (WORD_SIZE * 8); - int nwords = nbits / nbits_pr_word; - if (nwords != 0) { - b = _lshift_word(b, nwords); - nbits -= (nwords * nbits_pr_word); - } - - if (nbits != 0) { - int i; - for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) { - b.array[i] = (b.array[i] << nbits) | (b.array[i - 1] >> ((8 * WORD_SIZE) - nbits)); - } - b.array[i] <<= nbits; - } - - return b; -} - - -bn_t bignum_rshift(bn_t a, int nbits) -{ - //require(a, "a is null"); - //require(b, "b is null"); - require(nbits >= 0, "no negative shifts"); - - bn_t b; - - b = bignum_assign(a); - /* Handle shift in multiples of word-size */ - const int nbits_pr_word = (WORD_SIZE * 8); - int nwords = nbits / nbits_pr_word; - - if (nwords != 0) { - b = _rshift_word(b, nwords); - nbits -= (nwords * nbits_pr_word); - } - if (nbits != 0) { - int i; - for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) { - b.array[i] = (b.array[i] >> nbits) | (b.array[i + 1] << ((8 * WORD_SIZE) - nbits)); - } - b.array[i] >>= nbits; - } - - return b; -} - - - -bn_t bignum_a_rshift(bn_t a, int size, int nbits) -{ - //require(a, "a is null"); - //require(b, "b is null"); - require(nbits >= 0, "no negative shifts"); - require(size > 0, "no negative shifts"); - - bn_t b; - bn_t tmp, mask; - - b = bignum_rshift(a, nbits); - - /* get sign bit */ - tmp = bignum_rshift(a, size - 1); - tmp = bignum_mask(tmp, 1); - - if (!bignum_is_zero(tmp)) { - /* generate sign propag */ - tmp = bignum_from_int(1); - tmp = bignum_lshift(tmp, size); - tmp = bignum_dec(tmp); - - mask = bignum_from_int(1); - mask = bignum_lshift(mask, size - nbits); - mask = bignum_dec(mask); - - tmp = bignum_xor(tmp, mask); - b = bignum_or(b, tmp); - } - - return b; -} - -bn_t bignum_not(bn_t a) -{ - int i; - bn_t b; - - for (i = 0; i < BN_ARRAY_SIZE; ++i) { - b.array[i] = ~a.array[i]; - } - - return b; -} - - - -bn_t bignum_umod(bn_t a, bn_t b) -{ - /* - Take divmod and throw away div part - */ - //require(a, "a is null"); - //require(b, "b is null"); - //require(c, "c is null"); - - bn_t c, d; - bn_t tmp; - - /* c = (a / b) */ - c = bignum_udiv(a, b); - /* tmp = (c * b) */ - tmp = bignum_mul(c, b); - /* c = a - tmp */ - d = bignum_sub(a, tmp); - return d; -} - - -bn_t bignum_and(bn_t a, bn_t b) -{ - //require(a, "a is null"); - //require(b, "b is null"); - //require(c, "c is null"); - bn_t c; - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) { - c.array[i] = (a.array[i] & b.array[i]); - } - - return c; -} - - -bn_t bignum_or(bn_t a, bn_t b) -{ - //require(a, "a is null"); - //require(b, "b is null"); - //require(c, "c is null"); - bn_t c; - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) { - c.array[i] = (a.array[i] | b.array[i]); - } - - return c; -} - - -bn_t bignum_xor(bn_t a, bn_t b) -{ - //require(a, "a is null"); - //require(b, "b is null"); - //require(c, "c is null"); - - bn_t c; - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) { - c.array[i] = (a.array[i] ^ b.array[i]); - } - return c; -} - - -int bignum_cmp(bn_t a, bn_t b) -{ - //require(a, "a is null"); - //require(b, "b is null"); - - int i = BN_ARRAY_SIZE; - do { - i -= 1; /* Decrement first, to start with last array element */ - if (a.array[i] > b.array[i]) { - return LARGER; - } - else if (a.array[i] < b.array[i]) { - return SMALLER; - } - } - while (i != 0); - - return EQUAL; -} - - -/* Signed compare bn */ -int bignum_cmp_signed(bn_t a, bn_t b) -{ - int i = BN_ARRAY_SIZE; - do { - i -= 1; /* Decrement first, to start with last array element */ - if ((DTYPE_SIGNED)a.array[i] > (DTYPE_SIGNED)b.array[i]) { - return LARGER; - } - else if ((DTYPE_SIGNED)a.array[i] < (DTYPE_SIGNED)b.array[i]) { - return SMALLER; - } - } - while (i != 0); - - return EQUAL; -} - - -/* Unsigned compare bn */ -int bignum_cmp_unsigned(bn_t a, bn_t b) -{ - return bignum_cmp(a, b); -} - - -/* Return 1 if a == b else 0 */ -int bignum_is_equal(bn_t a, bn_t b) -{ - int ret; - ret = bignum_cmp_unsigned(a, b); - if (ret == EQUAL) - return 1; - else - return 0; -} - - -/* Return 1 if a <u b else 0 */ -int bignum_is_inf_unsigned(bn_t a, bn_t b) -{ - int ret; - ret = bignum_cmp_unsigned(a, b); - if (ret == SMALLER) - return 1; - else - return 0; -} - - -/* Return 1 if a <=u b else 0 */ -int bignum_is_inf_equal_unsigned(bn_t a, bn_t b) -{ - int ret; - ret = bignum_cmp_unsigned(a, b); - if (ret == EQUAL || ret == SMALLER) - return 1; - else - return 0; -} - - -/* Return 1 if a <s b else 0 */ -int bignum_is_inf_signed(bn_t a, bn_t b) -{ - int ret; - ret = bignum_cmp_signed(a, b); - if (ret == SMALLER) - return 1; - else - return 0; -} - - -/* Return 1 if a <=s b else 0 */ -int bignum_is_inf_equal_signed(bn_t a, bn_t b) -{ - int ret; - ret = bignum_cmp_signed(a, b); - if (ret == EQUAL || ret == SMALLER) - return 1; - else - return 0; -} - - -int bignum_is_zero(bn_t n) -{ - //require(n, "n is null"); - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) { - if (n.array[i]) { - return 0; - } - } - - return 1; -} - - - -bn_t bignum_assign(bn_t src) -{ - //require(dst, "dst is null"); - //require(src, "src is null"); - bn_t dst; - - int i; - for (i = 0; i < BN_ARRAY_SIZE; ++i) { - dst.array[i] = src.array[i]; - } - - return dst; -} - - -bn_t bignum_mask(bn_t src, int bits) -{ - bn_t dst; - bn_t mask; - - mask = bignum_from_int(0); - mask = bignum_dec(mask); - mask = bignum_rshift(mask, BN_BIT_SIZE - bits); - dst = bignum_and(src, mask); - return dst; -} - -/* Private / Static functions. */ -static bn_t _rshift_word(bn_t a, int nwords) -{ - /* Naive method: */ - //require(a, "a is null"); - int i; - - require(nwords >= 0, "no negative shifts"); - - if (nwords >= BN_ARRAY_SIZE) { - for (i = 0; i < BN_ARRAY_SIZE; ++i) { - a.array[i] = 0; - } - return a; - } - - for (i = 0; i < BN_ARRAY_SIZE - nwords; ++i) { - a.array[i] = a.array[i + nwords]; - } - - for (; i < BN_ARRAY_SIZE; ++i) { - a.array[i] = 0; - } - - return a; -} - - -static bn_t _lshift_word(bn_t a, int nwords) -{ - //require(a, "a is null"); - require(nwords >= 0, "no negative shifts"); - - int i; - - if (nwords >= BN_ARRAY_SIZE) { - for (i = 0; i < BN_ARRAY_SIZE; ++i) { - a.array[i] = 0; - } - return a; - } - - /* Shift whole words */ - for (i = (BN_ARRAY_SIZE - 1); i >= nwords; --i) { - a.array[i] = a.array[i - nwords]; - } - /* Zero pad shifted words. */ - for (; i >= 0; --i) { - a.array[i] = 0; - } - - return a; -} - - -static bn_t _lshift_one_bit(bn_t a) -{ - //require(a, "a is null"); - - int i; - for (i = (BN_ARRAY_SIZE - 1); i > 0; --i) { - a.array[i] = (a.array[i] << 1) | (a.array[i - 1] >> ((8 * WORD_SIZE) - 1)); - } - a.array[0] <<= 1; - - return a; -} - - -static bn_t _rshift_one_bit(bn_t a) -{ - //require(a, "a is null"); - - int i; - for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i) { - a.array[i] = (a.array[i] >> 1) | (a.array[i + 1] << ((8 * WORD_SIZE) - 1)); - } - a.array[BN_ARRAY_SIZE - 1] >>= 1; - - return a; -} - - -bn_t bignum_rol(bn_t a, int size, int nbits) -{ - bn_t c; - - c = bignum_or( - bignum_lshift(a, nbits), - bignum_rshift(a, size - nbits) - ); - c = bignum_mask(c, size); - return c; -} - - -bn_t bignum_ror(bn_t a, int size, int nbits) -{ - bn_t c; - - c = bignum_or( - bignum_rshift(a, nbits), - bignum_lshift(a, size - nbits) - ); - c = bignum_mask(c, size); - return c; -} - - -int bignum_getbit(bn_t a, int pos) -{ - int d_pos, bit_pos; - - require(pos < BN_BIT_SIZE, "size must be below bignum max size"); - - d_pos = pos / (sizeof(DTYPE) * 8); - bit_pos = pos % (sizeof(DTYPE) * 8); - return !!(a.array[d_pos] & (1 << bit_pos)); - -} - - - -/* - * Count leading zeros - count the number of zero starting at the most - * significant bit - * - * Example: - * - cntleadzeros(size=32, src=2): 30 - * - cntleadzeros(size=32, src=0): 32 - */ -int bignum_cntleadzeros(bn_t n, int size) -{ - int i; - - require(size, "size must be greater than 0"); - require(size <= BN_BIT_SIZE, "size must be below bignum max size"); - - for (i = 0; i < size; i++) { - if (bignum_getbit(n, size - i - 1)) - break; - } - - return i; -} - - - -/* - * Count trailing zeros - count the number of zero starting at the least - * significant bit - * - * Example: - * - cnttrailzeros(size=32, src=2): 1 - * - cnttrailzeros(size=32, src=0): 32 - */ -int bignum_cnttrailzeros(bn_t n, int size) -{ - int i; - - require(size, "size must be greater than 0"); - require(size <= BN_BIT_SIZE, "size must be below bignum max size"); - - for (i = 0; i < size; i++) { - if (bignum_getbit(n, i)) - break; - } - - return i; -} - - - - -bn_t bignum_sdiv(bn_t a, bn_t b, int size) -{ - require(size, "size must be greater than 0"); - require(size <= BN_BIT_SIZE, "size must be below bignum max size"); - - int a_sign, b_sign; - bn_t c; - - a_sign = bignum_getbit(a, size - 1); - b_sign = bignum_getbit(b, size - 1); - - if (a_sign) { - /* neg a */ - printf("a neg\n"); - a = bignum_sub(bignum_from_int(0), a); - a = bignum_mask(a, size - 1); - } - - if (b_sign) { - /* neg b */ - printf("b neg\n"); - b = bignum_sub(bignum_from_int(0), b); - b = bignum_mask(b, size - 1); - } - - c = bignum_udiv(a, b); - if (a_sign ^ b_sign) { - c = bignum_sub(bignum_from_int(0), c); - } - - c = bignum_mask(c, size); - return c; -} - - - -bn_t bignum_smod(bn_t a, bn_t b, int size) -{ - require(size, "size must be greater than 0"); - require(size <= BN_BIT_SIZE, "size must be below bignum max size"); - - bn_t c; - - c = bignum_sdiv(a, b, size); - c = bignum_mul(c, b); - c = bignum_sub(a, c); - c = bignum_mask(c, size); - return c; -} diff --git a/miasm/jitter/bn.h b/miasm/jitter/bn.h deleted file mode 100644 index 8c4a8ba1..00000000 --- a/miasm/jitter/bn.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef __BIGNUM_H__ -#define __BIGNUM_H__ - -#if _WIN32 -#define _MIASM_EXPORT __declspec(dllexport) -#else -#define _MIASM_EXPORT -#endif - -/* - -Big number library - arithmetic on multiple-precision unsigned integers. - -This library is an implementation of arithmetic on arbitrarily large integers. - -The difference between this and other implementations, is that the data structure -has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM), -and all memory is allocated statically: no dynamic allocation for better or worse. - -Primary goals are correctness, clarity of code and clean, portable implementation. -Secondary goal is a memory footprint small enough to make it suitable for use in -embedded applications. - - -The current state is correct functionality and adequate performance. -There may well be room for performance-optimizations and improvements. - -Source: https://github.com/kokke/tiny-bignum-c - -Code slightly modified to support ast generation calculus style from Expr. - -*/ - -#include <stdint.h> -#include <assert.h> - - -/* This macro defines the word size in bytes of the array that constitutes the big-number data structure. */ -#ifndef WORD_SIZE - #define WORD_SIZE 4 -#endif - -#define BN_BYTE_SIZE 32 - -#define BN_BIT_SIZE ((BN_BYTE_SIZE) * 8) - -/* Size of big-numbers in bytes */ -//#define BN_ARRAY_SIZE (128 / WORD_SIZE) -#define BN_ARRAY_SIZE (BN_BYTE_SIZE / WORD_SIZE) - - -/* Here comes the compile-time specialization for how large the underlying array size should be. */ -/* The choices are 1, 2 and 4 bytes in size with uint32, uint64 for WORD_SIZE==4, as temporary. */ -#ifndef WORD_SIZE - #error Must define WORD_SIZE to be 1, 2, 4 -#elif (WORD_SIZE == 1) - /* Data type of array in structure */ - #define DTYPE uint8_t - #define DTYPE_SIGNED int8_t - /* bitmask for getting MSB */ - #define DTYPE_MSB ((DTYPE_TMP)(0x80)) - /* Data-type larger than DTYPE, for holding intermediate results of calculations */ - #define DTYPE_TMP uint32_t - /* sprintf format string */ - #define SPRINTF_FORMAT_STR "%.02x" - #define SSCANF_FORMAT_STR "%2hhx" - /* Max value of integer type */ - #define MAX_VAL ((DTYPE_TMP)0xFF) -#elif (WORD_SIZE == 2) - #define DTYPE uint16_t - #define DTYPE_SIGNED int16_t - #define DTYPE_TMP uint32_t - #define DTYPE_MSB ((DTYPE_TMP)(0x8000)) - #define SPRINTF_FORMAT_STR "%.04x" - #define SSCANF_FORMAT_STR "%4hx" - #define MAX_VAL ((DTYPE_TMP)0xFFFF) -#elif (WORD_SIZE == 4) - #define DTYPE uint32_t - #define DTYPE_SIGNED int32_t - #define DTYPE_TMP uint64_t - #define DTYPE_MSB ((DTYPE_TMP)(0x80000000)) - #define SPRINTF_FORMAT_STR "%.08x" - #define SSCANF_FORMAT_STR "%8x" - #define MAX_VAL ((DTYPE_TMP)0xFFFFFFFF) -#endif -#ifndef DTYPE - #error DTYPE must be defined to uint8_t, uint16_t uint32_t or whatever -#endif - - -/* Custom assert macro - easy to disable */ -#define require(p, msg) assert(p && #msg) - - -/* Data-holding structure: array of DTYPEs */ -typedef struct bn -{ - DTYPE array[BN_ARRAY_SIZE]; -} bn_t; - - - -/* Tokens returned by bignum_cmp() for value comparison */ -enum { SMALLER = -1, EQUAL = 0, LARGER = 1 }; - -/* Initialization functions: */ -_MIASM_EXPORT bn_t bignum_init(void); -_MIASM_EXPORT bn_t bignum_from_int(DTYPE_TMP i); -_MIASM_EXPORT bn_t bignum_from_uint64(uint64_t i); -_MIASM_EXPORT int bignum_to_int(bn_t n); -_MIASM_EXPORT uint64_t bignum_to_uint64(bn_t n); -_MIASM_EXPORT bn_t bignum_from_string(char* str, int nbytes); -_MIASM_EXPORT void bignum_to_string(bn_t n, char* str, int maxsize); - - -/* Basic arithmetic operations: */ -_MIASM_EXPORT bn_t bignum_add(bn_t a, bn_t b); /* c = a + b */ -_MIASM_EXPORT bn_t bignum_sub(bn_t a, bn_t b); /* c = a - b */ -_MIASM_EXPORT bn_t bignum_mul(bn_t a, bn_t b); /* c = a * b */ -_MIASM_EXPORT bn_t bignum_udiv(bn_t a, bn_t b); /* c = a / b */ -_MIASM_EXPORT bn_t bignum_umod(bn_t a, bn_t b); /* c = a % b */ -_MIASM_EXPORT bn_t bignum_sdiv(bn_t a, bn_t b, int size); -_MIASM_EXPORT bn_t bignum_smod(bn_t a, bn_t b, int size); -//void bignum_udivmod(struct bn* a, struct bn* b, struct bn* c, struct bn* d); /* c = a/b, d = a%b */ - - - -/* Bitwise operations: */ -_MIASM_EXPORT bn_t bignum_and(bn_t a, bn_t b); /* c = a & b */ -_MIASM_EXPORT bn_t bignum_or(bn_t a, bn_t b); /* c = a | b */ -_MIASM_EXPORT bn_t bignum_xor(bn_t a, bn_t b); /* c = a ^ b */ -_MIASM_EXPORT bn_t bignum_lshift(bn_t a, int nbits); /* b = a << nbits */ -_MIASM_EXPORT bn_t bignum_rshift(bn_t a, int nbits); /* b = a >> nbits */ -_MIASM_EXPORT bn_t bignum_a_rshift(bn_t a, int size, int nbits); /* b = a a>> nbits */ -_MIASM_EXPORT bn_t bignum_not(bn_t a); /* c = ~a */ - -/* Special operators and comparison */ -_MIASM_EXPORT int bignum_cmp(bn_t a, bn_t b); /* Compare: returns LARGER, EQUAL or SMALLER */ -_MIASM_EXPORT int bignum_is_equal(bn_t a, bn_t b); /* Return 1 if a == b else 0 */ -_MIASM_EXPORT int bignum_is_inf_unsigned(bn_t a, bn_t b); /* Return 1 if a <u b else 0 */ -_MIASM_EXPORT int bignum_is_inf_equal_unsigned(bn_t a, bn_t b); /* Return 1 if a <=u b else 0 */ -_MIASM_EXPORT int bignum_is_inf_signed(bn_t a, bn_t b); /* Return 1 if a <s b else 0 */ -_MIASM_EXPORT int bignum_is_inf_equal_signed(bn_t a, bn_t b); /* Return 1 if a <=s b else 0 */ - - - -_MIASM_EXPORT int bignum_is_zero(bn_t n); /* For comparison with zero */ -_MIASM_EXPORT bn_t bignum_inc(bn_t n); /* Increment: add one to n */ -_MIASM_EXPORT bn_t bignum_dec(bn_t n); /* Decrement: subtract one from n */ -//bn_t bignum_pow(bn_t a, bn_t b, bn_t c); /* Calculate a^b -- e.g. 2^10 => 1024 */ -//bn_t bignum_isqrt(bn_t a, bn_t b); /* Integer square root -- e.g. isqrt(5) => 2*/ -_MIASM_EXPORT int bignum_cntleadzeros(bn_t n, int size); -_MIASM_EXPORT int bignum_cnttrailzeros(bn_t n, int size); -_MIASM_EXPORT bn_t bignum_assign(bn_t src); /* Copy src into dst -- dst := src */ -_MIASM_EXPORT bn_t bignum_mask(bn_t src, int bits); /* c = src & ((1<<bits) -1) */ - -_MIASM_EXPORT bn_t bignum_rol(bn_t a, int size, int nbits); -_MIASM_EXPORT bn_t bignum_ror(bn_t a, int size, int nbits); -_MIASM_EXPORT int bignum_getbit(bn_t a, int pos); - -#endif /* #ifndef __BIGNUM_H__ */ - - diff --git a/miasm/jitter/codegen.py b/miasm/jitter/codegen.py deleted file mode 100644 index 305d6c36..00000000 --- a/miasm/jitter/codegen.py +++ /dev/null @@ -1,656 +0,0 @@ -""" -Module to generate C code for a given native @block -""" - -from builtins import zip -import warnings - -from future.utils import viewitems, viewvalues - -from miasm.expression.expression import ExprId, ExprLoc, ExprInt, \ - ExprMem, ExprCond, LocKey, is_expr -from miasm.ir.ir import IRBlock, AssignBlock - -from miasm.ir.translators.C import TranslatorC -from miasm.core.asmblock import AsmBlockBad -from miasm.expression.simplifications import expr_simp_high_to_explicit - -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)} - - - - - - -class Attributes(object): - - """ - Store an irblock attributes - """ - - def __init__(self, log_mn=False, log_regs=False): - self.mem_read = False - self.mem_write = False - self.set_exception = False - self.log_mn = log_mn - self.log_regs = log_regs - self.instr = None - - -class CGen(object): - """ - Helper to generate C code for a given AsmBlock - """ - - """ - Translate native assembly block to C - """ - - CODE_EXCEPTION_MEM_AT_INSTR = r""" - // except fetch mem at instr noauto - if ((VM_exception_flag & ~EXCEPT_CODE_AUTOMOD) & EXCEPT_DO_NOT_UPDATE_PC) { - %s = %s; - BlockDst->address = %s; - return JIT_RET_EXCEPTION; - } - """ - - CODE_EXCEPTION_AT_INSTR = r""" - if (CPU_exception_flag_at_instr) { - %s = %s; - BlockDst->address = %s; - return JIT_RET_EXCEPTION; - } - """ - - CODE_RETURN_EXCEPTION = r""" - return JIT_RET_EXCEPTION; - """ - - CODE_RETURN_NO_EXCEPTION = r""" - %s: - %s = %s; - BlockDst->address = %s; - return JIT_RET_NO_EXCEPTION; - """ - - CODE_CPU_EXCEPTION_POST_INSTR = r""" - if (CPU_exception_flag) { - %s = DST_value; - BlockDst->address = DST_value; - return JIT_RET_EXCEPTION; - } - """ - - CODE_VM_EXCEPTION_POST_INSTR = r""" - check_memory_breakpoint(&(jitcpu->pyvm->vm_mngr)); - check_invalid_code_blocs(&(jitcpu->pyvm->vm_mngr)); - if (VM_exception_flag) { - %s = DST_value; - BlockDst->address = DST_value; - return JIT_RET_EXCEPTION; - } - """ - - CODE_INIT = r""" - int DST_case; - uint64_t DST_value; - struct vm_cpu *mycpu = jitcpu->cpu; - - goto %s; - """ - - CODE_BAD_BLOCK = r""" - // Unknown mnemonic - CPU_exception_flag = EXCEPT_UNK_MNEMO; - """ + CODE_RETURN_EXCEPTION - - def __init__(self, lifter): - self.lifter = lifter - self.PC = self.lifter.pc - self.translator = TranslatorC(self.lifter.loc_db) - self.init_arch_C() - - @property - def ir_arch(self): - warnings.warn('DEPRECATION WARNING: use ".lifter" instead of ".ir_arch"') - return self.lifter - - def init_arch_C(self): - """Iinitialize jitter internals""" - self.id_to_c_id = {} - for reg in self.lifter.arch.regs.all_regs_ids: - self.id_to_c_id[reg] = ExprId('mycpu->%s' % reg, reg.size) - - self.C_PC = self.id_to_c(self.PC) - - def dst_to_c(self, src): - """Translate Expr @src into C code""" - if not is_expr(src): - src = ExprInt(src, self.PC.size) - return self.id_to_c(src) - - def patch_c_id(self, expr): - """Replace ExprId in @expr with corresponding C variables""" - return expr.replace_expr(self.id_to_c_id) - - def id_to_c(self, expr): - """Translate Expr @expr into corresponding C code""" - return self.translator.from_expr(self.patch_c_id(expr)) - - def add_label_index(self, dst2index, loc_key): - """Insert @lbl to the dictionary @dst2index with a uniq value - @dst2index: LocKey -> uniq value - @loc_key: LocKey instance""" - - if loc_key not in dst2index: - dst2index[loc_key] = len(dst2index) - - def assignblk_to_irbloc(self, instr, assignblk): - """ - Ensure IRDst is always set in the head @assignblk of the @instr - @instr: an instruction instance - @assignblk: Assignblk instance - """ - new_assignblk = dict(assignblk) - if self.lifter.IRDst not in assignblk: - offset = instr.offset + instr.l - loc_key = self.lifter.loc_db.get_or_create_offset_location(offset) - dst = ExprLoc(loc_key, self.lifter.IRDst.size) - new_assignblk[self.lifter.IRDst] = dst - irs = [AssignBlock(new_assignblk, instr)] - return IRBlock(self.lifter.loc_db, self.lifter.get_loc_key_for_instr(instr), irs) - - def block2assignblks(self, block): - """ - Return the list of irblocks for a native @block - @block: AsmBlock - """ - irblocks_list = [] - for instr in block.lines: - assignblk_head, assignblks_extra = self.lifter.instr2ir(instr) - # Keep result in ordered list as first element is the assignblk head - # The remainings order is not really important - irblock_head = self.assignblk_to_irbloc(instr, assignblk_head) - irblocks = [irblock_head] + assignblks_extra - - # Simplify high level operators - out = [] - for irblock in irblocks: - new_irblock = self.lifter.irbloc_fix_regs_for_mode(irblock, self.lifter.attrib) - new_irblock = new_irblock.simplify(expr_simp_high_to_explicit)[1] - out.append(new_irblock) - irblocks = out - - 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): - """ - Add local variable used to store temporary result - @dst_var: dictionary of Expr -> local_var_expr - @dst_index : dictionary of size -> local var count - @expr: Expression source - """ - size = expr.size - if size < 8: - size = 8 - if size not in dst_index: - raise RuntimeError("Unsupported operand size %s", size) - var_num = dst_index[size] - dst = ExprId("var_%.2d_%.2d" % (size, var_num), size) - dst_index[size] += 1 - dst_var[expr] = dst - return dst - - def get_mem_prefetch(self, assignblk): - """ - Generate temporary variables used to fetch memory used in the @assignblk - Return a dictionary: ExprMem -> temporary variable - @assignblk: AssignBlock instance - """ - mem_index = {8: 0, 16: 0, 32: 0, 64: 0, 128:0} - mem_var = {} - - # Prefetch memory read - for expr in assignblk.get_r(mem_read=True): - if not isinstance(expr, ExprMem): - continue - var_num = mem_index[expr.size] - mem_index[expr.size] += 1 - var = ExprId( - "prefetch_%.2d_%.2d" % (expr.size, var_num), expr.size - ) - mem_var[expr] = var - - # Generate memory prefetch - return mem_var - - def gen_c_assignments(self, assignblk): - """ - Return C information used to generate the C code of the @assignblk - @assignblk: an AssignBlock instance - """ - c_var = [] - c_main = [] - c_mem = [] - c_updt = [] - c_prefetch = [] - - dst_index = {8: 0, 16: 0, 32: 0, 64: 0, 128:0} - dst_var = {} - - prefetchers = self.get_mem_prefetch(assignblk) - - for expr, prefetcher in viewitems(prefetchers): - str_src = self.id_to_c(expr) - str_dst = self.id_to_c(prefetcher) - c_prefetch.append('%s = %s;' % (str_dst, str_src)) - - for var in viewvalues(prefetchers): - if var.size <= self.translator.NATIVE_INT_MAX_SIZE: - c_var.append("uint%d_t %s;" % (var.size, var)) - else: - c_var.append("bn_t %s; // %d" % (var, var.size)) - - for dst, src in viewitems(assignblk): - src = src.replace_expr(prefetchers) - if dst == self.lifter.IRDst: - pass - elif isinstance(dst, ExprId): - new_dst = self.add_local_var(dst_var, dst_index, dst) - if dst in self.lifter.arch.regs.regs_flt_expr: - # Don't mask float assignment - c_main.append( - '%s = (%s);' % (self.id_to_c(new_dst), self.id_to_c(src))) - elif new_dst.size <= self.translator.NATIVE_INT_MAX_SIZE: - c_main.append( - '%s = (%s)&%s;' % (self.id_to_c(new_dst), - self.id_to_c(src), - SIZE_TO_MASK[src.size])) - else: - c_main.append( - '%s = bignum_mask(%s, %d);' % ( - self.id_to_c(new_dst), - self.id_to_c(src), - src.size - ) - ) - elif isinstance(dst, ExprMem): - ptr = dst.ptr.replace_expr(prefetchers) - if ptr.size <= self.translator.NATIVE_INT_MAX_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: - ptr_str = self.id_to_c(ptr) - if ptr.size <= self.translator.NATIVE_INT_MAX_SIZE: - c_mem.append('%s, %s);' % (str_dst[:-1], self.id_to_c(src))) - else: - if src.size <= self.translator.NATIVE_INT_MAX_SIZE: - c_mem.append('MEM_WRITE_BN_INT(jitcpu, %d, %s, %s);' % ( - src.size, ptr_str, self.id_to_c(src)) - ) - else: - c_mem.append('MEM_WRITE_BN_BN(jitcpu, %d, %s, %s);' % ( - src.size, ptr_str, self.id_to_c(src)) - ) - else: - raise ValueError("Unknown dst") - - for dst, new_dst in viewitems(dst_var): - if dst == self.lifter.IRDst: - continue - - c_updt.append('%s = %s;' % (self.id_to_c(dst), self.id_to_c(new_dst))) - if dst.size <= self.translator.NATIVE_INT_MAX_SIZE: - c_var.append("uint%d_t %s;" % (new_dst.size, new_dst)) - else: - c_var.append("bn_t %s; // %d" % (new_dst, new_dst.size)) - - return c_prefetch, c_var, c_main, c_mem, c_updt - - def gen_check_memory_exception(self, address): - """Generate C code to check memory exceptions - @address: address of the faulty instruction""" - dst = self.dst_to_c(address) - return (self.CODE_EXCEPTION_MEM_AT_INSTR % (self.C_PC, dst, dst)).split('\n') - - def gen_check_cpu_exception(self, address): - """Generate C code to check cpu exceptions - @address: address of the faulty instruction""" - dst = self.dst_to_c(address) - return (self.CODE_EXCEPTION_AT_INSTR % (self.C_PC, dst, dst)).split('\n') - - def traverse_expr_dst(self, expr, dst2index): - """ - Generate the index of the destination label for the @expr - @dst2index: dictionary to link label to its index - """ - - if isinstance(expr, ExprCond): - src1, src1b = self.traverse_expr_dst(expr.src1, dst2index) - src2, src2b = self.traverse_expr_dst(expr.src2, dst2index) - cond = self.id_to_c(expr.cond) - if not expr.cond.size <= self.translator.NATIVE_INT_MAX_SIZE: - cond = "(!bignum_is_zero(%s))" % cond - - return ("((%s)?(%s):(%s))" % (cond, src1, src2), - "((%s)?(%s):(%s))" % (cond, src1b, src2b)) - if isinstance(expr, ExprInt): - offset = int(expr) - loc_key = self.lifter.loc_db.get_or_create_offset_location(offset) - self.add_label_index(dst2index, loc_key) - out = hex(offset) - return ("%s" % dst2index[loc_key], out) - if expr.is_loc(): - loc_key = expr.loc_key - offset = self.lifter.loc_db.get_location_offset(expr.loc_key) - if offset is not None: - self.add_label_index(dst2index, loc_key) - out = hex(offset) - return ("%s" % dst2index[loc_key], out) - self.add_label_index(dst2index, loc_key) - out = hex(0) - return ("%s" % dst2index[loc_key], out) - dst2index[expr] = -1 - return ("-1", self.id_to_c(expr)) - - def gen_assignblk_dst(self, dst): - """Generate C code to handle instruction destination - @dst: instruction destination Expr""" - dst2index = {} - (ret, retb) = self.traverse_expr_dst(dst, dst2index) - ret = "DST_case = %s;" % ret - retb = 'DST_value = %s;' % retb - return ['// %s' % dst2index, - '%s' % ret, - '%s' % retb], dst2index - - def gen_post_instr_checks(self, attrib): - """Generate C code for handling potential exceptions - @attrib: Attributes instance""" - out = [] - if attrib.mem_read | attrib.mem_write: - out += (self.CODE_VM_EXCEPTION_POST_INSTR % (self.C_PC)).split('\n') - if attrib.set_exception: - out += (self.CODE_CPU_EXCEPTION_POST_INSTR % (self.C_PC)).split('\n') - - if attrib.mem_read | attrib.mem_write: - out.append("reset_memory_access(&(jitcpu->pyvm->vm_mngr));") - - return out - - def gen_pre_code(self, instr_attrib): - """Callback to generate code BEFORE the instruction execution - @instr_attrib: Attributes instance""" - - out = [] - - if instr_attrib.log_mn: - out.append( - 'printf("%.8X %s\\n");' % ( - instr_attrib.instr.offset, - instr_attrib.instr.to_string(self.lifter.loc_db) - ) - ) - return out - - def gen_post_code(self, attrib, pc_value): - """Callback to generate code AFTER the instruction execution - @attrib: Attributes instance""" - out = [] - if attrib.log_regs: - # Update PC for dump_gpregs - out.append("%s = %s;" % (self.C_PC, pc_value)) - out.append('dump_gpregs(jitcpu->cpu);') - return out - - def gen_goto_code(self, attrib, instr_offsets, dst): - """Generate C code for a potential destination @dst - @attrib: instruction Attributes - @instr_offsets: instructions offsets list - @dst: potential instruction destination""" - - out = [] - if is_expr(dst): - out += self.gen_post_code(attrib, "DST_value") - 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.lifter.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) - out += self.gen_post_code(attrib, "0x%x" % offset) - out += self.gen_post_instr_checks(attrib) - out.append('goto %s;' % dst) - else: - out += self.gen_post_code(attrib, "0x%x" % offset) - out.append('BlockDst->address = DST_value;') - out += self.gen_post_instr_checks(attrib) - out.append('\t\treturn JIT_RET_NO_EXCEPTION;') - return out - - def gen_dst_goto(self, attrib, instr_offsets, dst2index): - """ - Generate code for possible @dst2index. - - @attrib: an Attributes instance - @instr_offsets: list of instructions offsets - @dst2index: link from destination to index - """ - - if not dst2index: - return [] - out = [] - out.append('switch(DST_case) {') - - stopcase = False - for dst, index in sorted(viewitems(dst2index), key=lambda lblindex: lblindex[1]): - if index == -1: - # Handle '-1' case only once - if not stopcase: - stopcase = True - else: - continue - - out.append('\tcase %d:' % index) - - out += self.gen_goto_code(attrib, instr_offsets, dst) - out.append('\t\tbreak;') - out.append('};') - return out - - def gen_c_code(self, attrib, c_dst, c_assignmnts): - """ - Generate the C code for assignblk. - @attrib: Attributes instance - @c_dst: irdst C code - """ - - c_prefetch, c_var, c_main, c_mem, c_updt = c_assignmnts - out = [] - out.append("{") - out.append("// var") - out += c_var - out.append("// Prefetch") - out += c_prefetch - out.append("// Dst") - out += c_dst - out.append("// Main") - out += c_main - - out.append("// Check op/mem exceptions") - - # Check memory access if assignblk has memory read - if c_prefetch: - out += self.gen_check_memory_exception(attrib.instr.offset) - - out.append("// Mem updt") - out += c_mem - - out.append("// Check exception Mem write") - # Check memory write exceptions - if attrib.mem_write: - out += self.gen_check_memory_exception(attrib.instr.offset) - - out.append("// Updt") - out += c_updt - - out.append("// Checks exception") - - # Check post assignblk exception flags - if attrib.set_exception: - out += self.gen_check_cpu_exception(attrib.instr.offset) - - out.append("}") - - return out - - def get_caracteristics(self, assignblk, attrib): - """ - Set the carateristics in @attrib according to the @assignblk - @assignblk: an AssignBlock instance - @attrib: an Attributes instance - """ - - # Check explicit exception raising - attrib.set_exception = self.lifter.arch.regs.exception_flags in assignblk - - element_read = assignblk.get_r(mem_read=True) - # Check mem read - attrib.mem_read = any(isinstance(expr, ExprMem) - for expr in element_read) - # Check mem write - attrib.mem_write = any(isinstance(dst, ExprMem) - for dst in assignblk) - - def get_attributes(self, instr, irblocks, log_mn=False, log_regs=False): - """ - Get the carateristics of each @irblocks. Returns the corresponding - attributes object. - @irblock: a list of irbloc instance - @log_mn: generate code to log instructions - @log_regs: generate code to log registers states - """ - - instr_attrib = Attributes(log_mn, log_regs) - instr_attrib.instr = instr - irblocks_attributes = [] - - for irblock in irblocks: - attributes = [] - irblocks_attributes.append(attributes) - for assignblk in irblock: - attrib = Attributes(log_mn, log_regs) - attributes.append(attrib) - self.get_caracteristics(assignblk, attrib) - attrib.instr = instr - instr_attrib.mem_read |= attrib.mem_read - instr_attrib.mem_write |= attrib.mem_write - instr_attrib.set_exception |= attrib.set_exception - - return instr_attrib, irblocks_attributes - - def gen_bad_block(self): - """ - Generate the C code for a bad_block instance - """ - return self.CODE_BAD_BLOCK.split("\n") - - def get_block_post_label(self, block): - """Get label next to the @block - @block: AsmBlock instance""" - - last_instr = block.lines[-1] - offset = last_instr.offset + last_instr.l - return self.lifter.loc_db.get_or_create_offset_location(offset) - - def gen_init(self, block): - """ - Generate the init C code for a @block - @block: an asm_bloc instance - """ - - instr_offsets = [line.offset for line in block.lines] - post_label = self.get_block_post_label(block) - post_offset = self.lifter.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): - """ - Generate the C code for an @irblock - @irblock: an irbloc instance - @attributes: an Attributes instance list - """ - - out = [] - dst2index = None - for index, assignblk in enumerate(irblock): - if index == irblock.dst_linenb: - c_dst, dst2index = self.gen_assignblk_dst(irblock.dst) - else: - c_dst = [] - - c_assignmnts = self.gen_c_assignments(assignblk) - out += self.gen_c_code(attributes[index], c_dst, c_assignmnts) - - if dst2index: - out.append("// Set irdst") - # Gen goto on irdst set - out += self.gen_dst_goto(instr_attrib, instr_offsets, dst2index) - - return out - - def gen_finalize(self, block): - """ - Generate the C code for the final block instruction - """ - - loc_key = self.get_block_post_label(block) - offset = self.lifter.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): - """ - Generate the C code for the @block and return it as a list of lines - @log_mn: log mnemonics - @log_regs: log registers - """ - - if isinstance(block, 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): - label = str(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, irblock) - - out += self.gen_finalize(block) - - return ['\t' + line for line in out] diff --git a/miasm/jitter/compat_py23.h b/miasm/jitter/compat_py23.h deleted file mode 100644 index 6dce7818..00000000 --- a/miasm/jitter/compat_py23.h +++ /dev/null @@ -1,228 +0,0 @@ -#ifndef __COMPAT_PY23_H__ -#define __COMPAT_PY23_H__ - - -#include "bn.h" - -#if PY_MAJOR_VERSION >= 3 -#define PyGetInt_uint_t(size_type, item, value) \ - if (PyLong_Check(item)) { \ - Py_INCREF(item); \ - PyObject* py_long = item; \ - PyObject* py_long_new; \ - bn_t bn; \ - uint64_t tmp; \ - int neg = 0; \ - \ - if (Py_SIZE(py_long) < 0) { \ - neg = 1; \ - py_long_new = PyObject_CallMethod(py_long, "__neg__", NULL); \ - Py_DECREF(py_long); \ - py_long = py_long_new; \ - } \ - \ - bn = PyLong_to_bn(py_long); \ - \ - bn_t mask_bn = bignum_lshift(bignum_from_int(1), sizeof(size_type)*8); \ - if (bignum_is_inf_equal_unsigned(mask_bn, bn)) { \ - RAISE(PyExc_TypeError, "Arg too big for " #size_type ""); \ - } \ - if (neg) { \ - bn = bignum_sub(mask_bn, bn); \ - } \ - tmp = bignum_to_uint64(bn); \ - value = (size_type) tmp; \ - } \ - else{ \ - RAISE(PyExc_TypeError, "Arg must be int"); \ - } - - -#define PyGetInt_uint_t_retneg(size_type, item, value) \ - if (PyLong_Check(item)) { \ - Py_INCREF(item); \ - PyObject* py_long = item; \ - PyObject* py_long_new; \ - bn_t bn; \ - uint64_t tmp; \ - int neg = 0; \ - \ - if (Py_SIZE(py_long) < 0) { \ - neg = 1; \ - py_long_new = PyObject_CallMethod(py_long, "__neg__", NULL); \ - Py_DECREF(py_long); \ - py_long = py_long_new; \ - } \ - \ - bn = PyLong_to_bn(py_long); \ - \ - bn_t mask_bn = bignum_lshift(bignum_from_int(1), sizeof(size_type)*8); \ - if (bignum_is_inf_equal_unsigned(mask_bn, bn)) { \ - PyErr_SetString(PyExc_TypeError, "Arg too big for " #size_type ""); \ - return -1; \ - } \ - if (neg) { \ - bn = bignum_sub(mask_bn, bn); \ - } \ - tmp = bignum_to_uint64(bn); \ - value = (size_type) tmp; \ - } \ - else{ \ - PyErr_SetString(PyExc_TypeError, "Arg must be int"); \ - return -1; \ - } - -#define PyGetStr(dest, name) \ - if (!PyUnicode_Check((name))) \ - RAISE(PyExc_TypeError,"Page name must be bytes"); \ - (dest) = PyUnicode_AsUTF8((name)) - - - -#else -#define PyGetInt_uint_t(size_type, item, value) \ - if (PyInt_Check(item)) { \ - long tmp; \ - tmp = PyInt_AsLong(item); \ - \ - if (Py_SIZE(item) < 0) { \ - if (-tmp > ((size_type) -1)) { \ - RAISE(PyExc_TypeError, "Arg too big for " #size_type ""); \ - } \ - } \ - else if (tmp > (size_type) -1) { \ - RAISE(PyExc_TypeError, "Arg too big for " #size_type ""); \ - } \ - value = (size_type) tmp; \ - } \ - else if (PyLong_Check(item)){ \ - Py_INCREF(item); \ - PyObject* py_long = item; \ - PyObject* py_long_new; \ - bn_t bn; \ - uint64_t tmp; \ - int neg = 0; \ - \ - if (Py_SIZE(py_long) < 0) { \ - neg = 1; \ - py_long_new = PyObject_CallMethod(py_long, "__neg__", NULL); \ - Py_DECREF(py_long); \ - py_long = py_long_new; \ - } \ - \ - bn = PyLong_to_bn(py_long); \ - \ - bn_t mask_bn = bignum_lshift(bignum_from_int(1), sizeof(size_type)*8); \ - if (bignum_is_inf_equal_unsigned(mask_bn, bn)) { \ - RAISE(PyExc_TypeError, "Arg too big for " #size_type ""); \ - } \ - if (neg) { \ - bn = bignum_sub(mask_bn, bn); \ - } \ - tmp = bignum_to_uint64(bn); \ - value = (size_type) tmp; \ - } \ - else{ \ - RAISE(PyExc_TypeError, "Arg must be int"); \ - } - - -#define PyGetInt_uint_t_retneg(size_type, item, value) \ - if (PyInt_Check(item)) { \ - long tmp; \ - tmp = PyInt_AsLong(item); \ - \ - if (Py_SIZE(item) < 0) { \ - if (-tmp > ((size_type) -1)) { \ - PyErr_SetString(PyExc_TypeError, "Arg too big for " #size_type ""); \ - return -1; \ - } \ - } \ - else if (tmp > (size_type) -1) { \ - PyErr_SetString(PyExc_TypeError, "Arg too big for " #size_type ""); \ - return -1; \ - } \ - value = (size_type) tmp; \ - } \ - else if (PyLong_Check(item)){ \ - Py_INCREF(item); \ - PyObject* py_long = item; \ - PyObject* py_long_new; \ - bn_t bn; \ - uint64_t tmp; \ - int neg = 0; \ - \ - if (Py_SIZE(py_long) < 0) { \ - neg = 1; \ - py_long_new = PyObject_CallMethod(py_long, "__neg__", NULL); \ - Py_DECREF(py_long); \ - py_long = py_long_new; \ - } \ - \ - bn = PyLong_to_bn(py_long); \ - \ - bn_t mask_bn = bignum_lshift(bignum_from_int(1), sizeof(size_type)*8); \ - if (bignum_is_inf_equal_unsigned(mask_bn, bn)) { \ - PyErr_SetString(PyExc_TypeError, "Arg too big for " #size_type ""); \ - return -1; \ - } \ - if (neg) { \ - bn = bignum_sub(mask_bn, bn); \ - } \ - tmp = bignum_to_uint64(bn); \ - value = (size_type) tmp; \ - } \ - else{ \ - PyErr_SetString(PyExc_TypeError, "Arg must be int"); \ - return -1; \ - } \ - - -#define PyGetStr(dest, name) \ - if (!PyString_Check((name))) \ - RAISE(PyExc_TypeError,"Page name must be bytes"); \ - (dest) = PyString_AsString((name)) - -#endif - - - -#define PyGetInt_size_t(item, value) PyGetInt_uint_t(size_t, item, value) - -#define PyGetInt_uint8_t(item, value) PyGetInt_uint_t(uint8_t, item, value) -#define PyGetInt_uint16_t(item, value) PyGetInt_uint_t(uint16_t, item, value) -#define PyGetInt_uint32_t(item, value) PyGetInt_uint_t(uint32_t, item, value) -#define PyGetInt_uint64_t(item, value) PyGetInt_uint_t(uint64_t, item, value) - -#define PyGetInt_uint8_t_retneg(item, value) PyGetInt_uint_t_retneg(uint8_t, item, value) -#define PyGetInt_uint16_t_retneg(item, value) PyGetInt_uint_t_retneg(uint16_t, item, value) -#define PyGetInt_uint32_t_retneg(item, value) PyGetInt_uint_t_retneg(uint32_t, item, value) -#define PyGetInt_uint64_t_retneg(item, value) PyGetInt_uint_t_retneg(uint64_t, item, value) - - - -#if PY_MAJOR_VERSION >= 3 - -#define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void) - -#define MOD_DEF(ob, name, doc, methods) \ - static struct PyModuleDef moduledef = { \ - PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \ - ob = PyModule_Create(&moduledef); -#define RET_MODULE return module - -#else - -#define MOD_INIT(name) PyMODINIT_FUNC init##name(void) - -#define MOD_DEF(ob, name, doc, methods) \ - ob = Py_InitModule3(name, methods, doc); - -#define RET_MODULE return -#endif - - - - - -#endif diff --git a/miasm/jitter/csts.py b/miasm/jitter/csts.py deleted file mode 100644 index f40cbe74..00000000 --- a/miasm/jitter/csts.py +++ /dev/null @@ -1,50 +0,0 @@ -#-*- coding:utf-8 -*- - - -# VM Mngr Exceptions -EXCEPT_DO_NOT_UPDATE_PC = 1 << 25 -EXCEPT_NUM_UPDT_EIP = (1<<11) - -EXCEPT_CODE_AUTOMOD = (1 << 0) -EXCEPT_SOFT_BP = (1 << 1) -EXCEPT_INT_XX = (1 << 2) -EXCEPT_SPR_ACCESS = (1 << 3) -EXCEPT_SYSCALL = (1 << 4) -EXCEPT_BREAKPOINT_MEMORY = (1 << 10) -# Deprecated -EXCEPT_BREAKPOINT_INTERN = EXCEPT_BREAKPOINT_MEMORY - -EXCEPT_ACCESS_VIOL = ((1 << 14) | EXCEPT_DO_NOT_UPDATE_PC) -EXCEPT_DIV_BY_ZERO = ((1 << 16) | EXCEPT_DO_NOT_UPDATE_PC) -EXCEPT_PRIV_INSN = ((1 << 17) | EXCEPT_DO_NOT_UPDATE_PC) -EXCEPT_ILLEGAL_INSN = ((1 << 18) | EXCEPT_DO_NOT_UPDATE_PC) -EXCEPT_UNK_MNEMO = ((1 << 19) | EXCEPT_DO_NOT_UPDATE_PC) -EXCEPT_INT_1 = ((1 << 20) | EXCEPT_DO_NOT_UPDATE_PC) - -JitterExceptions = { - "DO_NOT_UPDATE_PC": EXCEPT_DO_NOT_UPDATE_PC, - "NUM_UPDT_EIP": EXCEPT_NUM_UPDT_EIP, - "CODE_AUTOMOD": EXCEPT_CODE_AUTOMOD, - "SOFT_BP": EXCEPT_SOFT_BP, - "INT_XX": EXCEPT_INT_XX, - "SPR_ACCESS": EXCEPT_SPR_ACCESS, - "SYSCALL": EXCEPT_SYSCALL, - "BREAKPOINT_MEMORY": EXCEPT_BREAKPOINT_MEMORY, - "BREAKPOINT_INTERN": EXCEPT_BREAKPOINT_INTERN, - "ACCESS_VIOL": EXCEPT_ACCESS_VIOL, - "DIV_BY_ZERO": EXCEPT_DIV_BY_ZERO, - "PRIV_INSN": EXCEPT_PRIV_INSN, - "ILLEGAL_INSN": EXCEPT_ILLEGAL_INSN, - "UNK_MNEMO": EXCEPT_UNK_MNEMO, - "INT_1": EXCEPT_INT_1, -} - -# VM Mngr constants - -PAGE_READ = 1 -PAGE_WRITE = 2 -PAGE_EXEC = 4 - -BREAKPOINT_READ = 1 -BREAKPOINT_WRITE = 2 - diff --git a/miasm/jitter/emulatedsymbexec.py b/miasm/jitter/emulatedsymbexec.py deleted file mode 100644 index 1c3100ae..00000000 --- a/miasm/jitter/emulatedsymbexec.py +++ /dev/null @@ -1,170 +0,0 @@ -from miasm.core.utils import decode_hex, encode_hex -import miasm.expression.expression as m2_expr -from miasm.ir.symbexec import SymbolicExecutionEngine -from miasm.arch.x86.arch import is_op_segm - - -class EmulatedSymbExec(SymbolicExecutionEngine): - """Symbolic exec instance linked with a jitter""" - - x86_cpuid = { - 0: { - 0: 0xa, - 1: 0x756E6547, - 2: 0x6C65746E, - 3: 0x49656E69, - }, - 1: { - 0: 0x00020652, - 1: 0x00000800, - 2: 0x00000209, - 3: 0x078bf9ff - }, - 2: { - 0: 0, - 1: 0, - 2: 0, - 3: 0 - }, - 4: { - 0: 0, - 1: 0, - 2: 0, - 3: 0 - }, - 7: { - 0: 0, - 1: (1 << 0) | (1 << 3), - 2: 0, - 3: 0 - }, - 0x80000000: { - 0: 0x80000008, - 1: 0, - 2: 0, - 3: 0 - }, - 0x80000001: { - 0: 0, - 1: 0, - 2: (1 << 0) | (1 << 8), - 3: (1 << 11) | (1 << 29), - }, - } - - def __init__(self, cpu, vm, *args, **kwargs): - """Instantiate an EmulatedSymbExec, associated to CPU @cpu and bind - memory accesses. - @cpu: JitCpu instance - """ - super(EmulatedSymbExec, self).__init__(*args, **kwargs) - self.cpu = cpu - self.vm = vm - - def reset_regs(self): - """Set registers value to 0. Ignore register aliases""" - for reg in self.lifter.arch.regs.all_regs_ids_no_alias: - self.symbols.symbols_id[reg] = m2_expr.ExprInt(0, size=reg.size) - - # Memory management - def mem_read(self, expr_mem): - """Memory read wrapper for symbolic execution - @expr_mem: ExprMem""" - - addr = expr_mem.ptr - if not addr.is_int(): - return super(EmulatedSymbExec, self).mem_read(expr_mem) - addr = int(addr) - size = expr_mem.size // 8 - value = self.vm.get_mem(addr, size) - if self.vm.is_little_endian(): - value = value[::-1] - self.vm.add_mem_read(addr, size) - - return m2_expr.ExprInt( - int(encode_hex(value), 16), - expr_mem.size - ) - - def mem_write(self, dest, data): - """Memory read wrapper for symbolic execution - @dest: ExprMem instance - @data: Expr instance""" - - # Get the content to write - data = self.expr_simp(data) - if not isinstance(data, m2_expr.ExprInt): - raise RuntimeError("A simplification is missing: %s" % data) - to_write = int(data) - - # Format information - addr = int(dest.ptr) - size = data.size // 8 - content = hex(to_write).replace("0x", "").replace("L", "") - content = "0" * (size * 2 - len(content)) + content - content = decode_hex(content) - - if self.vm.is_little_endian(): - content = content[::-1] - - # Write in VmMngr context - self.vm.set_mem(addr, content) - - # Interaction symbexec <-> jitter - def update_cpu_from_engine(self): - """Updates @cpu instance according to new CPU values""" - - for symbol in self.symbols: - if isinstance(symbol, m2_expr.ExprId): - if hasattr(self.cpu, symbol.name): - value = self.symbols.symbols_id[symbol] - if not isinstance(value, m2_expr.ExprInt): - raise ValueError("A simplification is missing: %s" % value) - - setattr(self.cpu, symbol.name, int(value)) - else: - raise NotImplementedError("Type not handled: %s" % symbol) - - - def update_engine_from_cpu(self): - """Updates CPU values according to @cpu instance""" - - for symbol in self.symbols: - if isinstance(symbol, m2_expr.ExprId): - if hasattr(self.cpu, symbol.name): - value = m2_expr.ExprInt(getattr(self.cpu, symbol.name), - symbol.size) - self.symbols.symbols_id[symbol] = value - else: - raise NotImplementedError("Type not handled: %s" % symbol) - - # CPU specific simplifications - def _simp_handle_segm(self, e_s, expr): - """Handle 'segm' operation""" - if not is_op_segm(expr): - return expr - if not expr.args[0].is_int(): - return expr - segm_nb = int(expr.args[0]) - segmaddr = self.cpu.get_segm_base(segm_nb) - return e_s(m2_expr.ExprInt(segmaddr, expr.size) + expr.args[1]) - - def _simp_handle_x86_cpuid(self, e_s, expr): - """From miasm/jitter/op_semantics.h: x86_cpuid""" - if expr.op != "x86_cpuid": - return expr - - if any(not arg.is_int() for arg in expr.args): - return expr - a, reg_num = (int(arg) for arg in expr.args) - - # Not found error is keeped on purpose - return m2_expr.ExprInt(self.x86_cpuid[a][reg_num], expr.size) - - def enable_emulated_simplifications(self): - """Enable simplifications needing a CPU instance on associated - ExpressionSimplifier - """ - self.expr_simp.enable_passes({ - m2_expr.ExprOp: [self._simp_handle_segm, self._simp_handle_x86_cpuid], - }) diff --git a/miasm/jitter/jitcore.py b/miasm/jitter/jitcore.py deleted file mode 100644 index 434854ca..00000000 --- a/miasm/jitter/jitcore.py +++ /dev/null @@ -1,308 +0,0 @@ -from __future__ import print_function -# -# Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -from hashlib import md5 -import warnings - -from future.utils import viewvalues - -from miasm.core.asmblock import disasmEngine, AsmBlockBad -from miasm.core.interval import interval -from miasm.core.utils import BoundedDict -from miasm.expression.expression import LocKey -from miasm.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, lifter, bin_stream): - """Initialise a JitCore instance. - @lifter: Lifter instance for current architecture - @bin_stream: bin_stream instance - """ - # Arch related - self.lifter = lifter - self.ircfg = self.lifter.new_ircfg() - self.arch_name = "%s%s" % (self.lifter.arch.name, self.lifter.attrib) - - # Structures for block tracking - self.offset_to_jitted_func = BoundedDict(self.jitted_block_max_size, - delete_cb=self.jitted_block_delete_cb) - 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.options = {"jit_maxline": 50, # Maximum number of line jitted - "max_exec_per_call": 0 # 0 means no limit - } - - # Disassembly Engine - self.split_dis = set() - self.mdis = disasmEngine( - lifter.arch, lifter.attrib, bin_stream, - lines_wd=self.options["jit_maxline"], - loc_db=lifter.loc_db, - follow_call=False, - dontdis_retcall=False, - split_dis=self.split_dis, - ) - - @property - def ir_arch(self): - warnings.warn('DEPRECATION WARNING: use ".lifter" instead of ".ir_arch"') - return self.lifter - - - 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.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 - are not at the block beginning""" - self.split_dis.update(set(args)) - - def remove_disassembly_splits(self, *args): - """The disassembly engine will no longer stop on address in args""" - self.split_dis.difference_update(set(args)) - - def load(self): - "Initialise the Jitter" - raise NotImplementedError("Abstract class") - - def set_block_min_max(self, cur_block): - "Update cur_block to set min/max address" - - if cur_block.lines: - cur_block.ad_min = cur_block.lines[0].offset - cur_block.ad_max = cur_block.lines[-1].offset + cur_block.lines[-1].l - else: - # 1 byte block for unknown mnemonic - offset = self.lifter.loc_db.get_location_offset(cur_block.loc_key) - cur_block.ad_min = offset - cur_block.ad_max = offset+1 - - - def add_block_to_mem_interval(self, vm, block): - "Update vm to include block addresses in its memory range" - self.blocks_mem_interval += interval([(block.ad_min, block.ad_max - 1)]) - - vm.reset_code_bloc_pool() - for a, b in self.blocks_mem_interval: - vm.add_code_bloc(a, b + 1) - - def add_block(self, block): - """Add a block to JiT and JiT it. - @block: asm_bloc to add - """ - raise NotImplementedError("Abstract class") - - def disasm_and_jit_block(self, addr, vm): - """Disassemble a new block and JiT it - @addr: address of the block to disassemble (LocKey or int) - @vm: VmMngr instance - """ - - # Get the block - if isinstance(addr, LocKey): - addr = self.lifter.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"] - - # Disassemble it - cur_block = self.mdis.dis_block(addr) - if isinstance(cur_block, AsmBlockBad): - return cur_block - # Logging - if self.log_newbloc: - print(cur_block) - - # Update label -> block - self.loc_key_to_block[cur_block.loc_key] = cur_block - - # Store min/max block address needed in jit automod code - self.set_block_min_max(cur_block) - - # JiT it - self.add_block(cur_block) - - # Update jitcode mem range - 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 - @offset: starting address (int) - @stop_offsets: set of address on which the jitter must stop - """ - - if offset is None: - offset = getattr(cpu, self.lifter.pc.name) - - if offset not in self.offset_to_jitted_func: - # Need to JiT the block - 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(offset, cpu, self.offset_to_jitted_func.data, - stop_offsets, - self.options["max_exec_per_call"]) - - def blocks_to_memrange(self, blocks): - """Return an interval instance standing for blocks addresses - @blocks: list of AsmBlock instances - """ - - mem_range = interval() - mem_range = interval([(block.ad_min, block.ad_max - 1) for block in blocks]) - return mem_range - - def __updt_jitcode_mem_range(self, vm): - """Rebuild the VM blocks address memory range - @vm: VmMngr instance - """ - - # Reset the current pool - vm.reset_code_bloc_pool() - - # Add blocks in the pool - for start, stop in self.blocks_mem_interval: - vm.add_code_bloc(start, stop + 1) - - 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 - @ad2: Last address - """ - - # Find concerned blocks - modified_blocks = set() - for block in viewvalues(self.loc_key_to_block): - if not block.lines: - continue - if block.ad_max <= ad1 or block.ad_min >= ad2: - # Block not modified - pass - else: - # Modified blocks - modified_blocks.add(block) - - # Remove modified blocks - for block in modified_blocks: - try: - for irblock in block.blocks: - # Remove offset -> jitted block link - offset = self.lifter.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 - offset = self.lifter.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.loc_key_to_block[block.loc_key]) - - # Re generate blocks intervals - self.blocks_mem_interval = self.blocks_to_memrange(self.loc_key_to_block.values()) - - return modified_blocks - - def updt_automod_code_range(self, vm, mem_range): - """Remove jitted code in range @mem_range - @vm: VmMngr instance - @mem_range: list of start/stop addresses - """ - for addr_start, addr_stop in mem_range: - self.del_block_in_range(addr_start, addr_stop) - self.__updt_jitcode_mem_range(vm) - vm.reset_memory_access() - - def updt_automod_code(self, vm): - """Remove jitted code updated by memory write - @vm: VmMngr instance - """ - mem_range = [] - for addr_start, addr_stop in vm.get_memory_write(): - mem_range.append((addr_start, addr_stop)) - self.updt_automod_code_range(vm, mem_range) - - def hash_block(self, block): - """ - Build a hash of the block @block - @block: asmblock - """ - block_raw = b"".join(line.b for line in block.lines) - offset = self.lifter.loc_db.get_location_offset(block.loc_key) - block_hash = md5( - b"%X_%s_%s_%s_%s" % ( - offset, - self.arch_name.encode(), - b'\x01' if self.log_mn else b'\x00', - b'\x01' if self.log_regs else b'\x00', - 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/miasm/jitter/jitcore_cc_base.py b/miasm/jitter/jitcore_cc_base.py deleted file mode 100644 index c5819d1f..00000000 --- a/miasm/jitter/jitcore_cc_base.py +++ /dev/null @@ -1,127 +0,0 @@ -#-*- coding:utf-8 -*- - -import glob -import os -import tempfile -import platform -import sysconfig - -from miasm.jitter.jitcore import JitCore -from miasm.core.utils import keydefaultdict - -is_win = platform.system() == "Windows" - -def gen_core(arch, attrib): - lib_dir = os.path.dirname(os.path.realpath(__file__)) - - txt = "" - txt += '#include "%s/queue.h"\n' % lib_dir - txt += '#include "%s/op_semantics.h"\n' % lib_dir - txt += '#include "%s/vm_mngr.h"\n' % lib_dir - txt += '#include "%s/bn.h"\n' % lib_dir - txt += '#include "%s/vm_mngr_py.h"\n' % lib_dir - txt += '#include "%s/JitCore.h"\n' % lib_dir - txt += '#include "%s/arch/JitCore_%s.h"\n' % (lib_dir, arch.name) - - txt += r''' -#define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;} -''' - return txt - - -class myresolver(object): - - def __init__(self, offset): - self.offset = offset - - def ret(self): - return "return PyLong_FromUnsignedLongLong(0x%X);" % self.offset - - -class resolver(object): - - def __init__(self): - self.resolvers = keydefaultdict(myresolver) - - def get_resolver(self, offset): - return self.resolvers[offset] - - -class JitCore_Cc_Base(JitCore): - "JiT management, abstract class using a C compiler as backend" - - def __init__(self, lifter, bin_stream): - self.jitted_block_delete_cb = self.deleteCB - super(JitCore_Cc_Base, self).__init__(lifter, bin_stream) - self.resolver = resolver() - self.lifter = lifter - self.states = {} - self.tempdir = os.path.join(tempfile.gettempdir(), "miasm_cache") - try: - os.mkdir(self.tempdir, 0o755) - except OSError: - pass - if not os.access(self.tempdir, os.R_OK | os.W_OK): - raise RuntimeError( - 'Cannot access cache directory %s ' % self.tempdir) - self.exec_wrapper = None - self.libs = None - self.include_files = None - - def deleteCB(self, offset): - raise NotImplementedError() - - def load(self): - lib_dir = os.path.dirname(os.path.realpath(__file__)) - ext = sysconfig.get_config_var('EXT_SUFFIX') - if ext is None: - ext = ".so" if not is_win else ".lib" - if is_win: - # sysconfig.get_config_var('EXT_SUFFIX') is .pyd on Windows and need to be forced to .lib - # Additionally windows built libraries may have a name like VmMngr.cp38-win_amd64.lib - ext_files = glob.glob(os.path.join(lib_dir, "VmMngr.*lib")) - if len(ext_files) == 1: - ext = os.path.basename(ext_files[0]).replace("VmMngr", "") - - libs = [ - os.path.join(lib_dir, "VmMngr" + ext), - os.path.join( - lib_dir, - "arch", - "JitCore_%s%s" % (self.lifter.arch.name, ext) - ) - ] - - include_files = [ - os.path.dirname(__file__), - sysconfig.get_paths()['include'], - ] - self.include_files = include_files - self.libs = libs - - def init_codegen(self, codegen): - """ - Get the code generator @codegen - @codegen: an CGen instance - """ - self.codegen = codegen - - def gen_c_code(self, block): - """ - Return the C code corresponding to the @irblocks - @irblocks: list of irblocks - """ - f_declaration = '_MIASM_EXPORT 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 - - return self.gen_C_source(self.lifter, c_code) - - @staticmethod - def gen_C_source(lifter, func_code): - raise NotImplementedError() diff --git a/miasm/jitter/jitcore_gcc.py b/miasm/jitter/jitcore_gcc.py deleted file mode 100644 index 958c9d13..00000000 --- a/miasm/jitter/jitcore_gcc.py +++ /dev/null @@ -1,141 +0,0 @@ -#-*- coding:utf-8 -*- - -import sys -import os -import tempfile -import ctypes -import _ctypes -import platform -import sysconfig -from subprocess import check_call -from miasm.jitter import Jitgcc -from miasm.jitter.jitcore_cc_base import JitCore_Cc_Base, gen_core - -is_win = platform.system() == "Windows" - -class JitCore_Gcc(JitCore_Cc_Base): - "JiT management, using a C compiler as backend" - - def __init__(self, lifter, bin_stream): - super(JitCore_Gcc, self).__init__(lifter, bin_stream) - self.exec_wrapper = Jitgcc.gcc_exec_block - - def deleteCB(self, offset): - """Free the state associated to @offset and delete it - @offset: gcc state offset - """ - flib = None - if is_win: - flib = _ctypes.FreeLibrary - else: - flib = _ctypes.dlclose - flib(self.states[offset]._handle) - del self.states[offset] - - def load_code(self, label, fname_so): - lib = ctypes.cdll.LoadLibrary(fname_so) - func = getattr(lib, self.FUNCNAME) - addr = ctypes.cast(func, ctypes.c_void_p).value - offset = self.lifter.loc_db.get_location_offset(label) - self.offset_to_jitted_func[offset] = addr - self.states[offset] = lib - - def add_block(self, block): - """Add a block to JiT and JiT it. - @block: block to jit - """ - block_hash = self.hash_block(block) - ext = sysconfig.get_config_var('EXT_SUFFIX') - if ext is None: - ext = ".so" if not is_win else ".pyd" - fname_out = os.path.join(self.tempdir, "%s%s" % (block_hash, ext)) - - if not os.access(fname_out, os.R_OK | os.X_OK): - func_code = self.gen_c_code(block) - - # Create unique C file - fdesc, fname_in = tempfile.mkstemp(suffix=".c") - os.write(fdesc, func_code.encode()) - os.close(fdesc) - - # Create unique SO file - fdesc, fname_tmp = tempfile.mkstemp(suffix=ext) - os.close(fdesc) - - inc_dir = ["-I%s" % inc for inc in self.include_files] - libs = ["%s" % lib for lib in self.libs] - if is_win: - libs.append( - os.path.join( - sysconfig.get_paths()['include'], - "..", - "libs", - "python%d%d.lib" % (sys.version_info.major, sys.version_info.minor) - ) - ) - cl = [ - "cl", "/nologo", "/W3", "/MP", - "/Od", "/DNDEBUG", "/D_WINDOWS", "/Gm-", "/EHsc", - "/RTC1", "/MD", "/GS", - fname_in - ] + inc_dir + libs - cl += ["/link", "/DLL", "/OUT:" + fname_tmp] - out_dir, _ = os.path.split(fname_tmp) - check_call(cl, cwd = out_dir) - basename_out, _ = os.path.splitext(fname_tmp) - basename_in, _ = os.path.splitext(os.path.basename(fname_in)) - for ext in ('.obj', '.exp', '.lib'): - artifact_out_path = os.path.join( - out_dir, - basename_out + ext - ) - if os.path.isfile(artifact_out_path): - os.remove(artifact_out_path) - artifact_in_path = os.path.join( - out_dir, - basename_in + ext - ) - if os.path.isfile(artifact_in_path): - os.remove(artifact_in_path) - else: - args = [ - "cc", - "-O3", - "-shared", - "-fPIC", - fname_in, - "-o", - fname_tmp - ] + inc_dir + libs - check_call(args) - - # Move temporary file to final file - try: - os.rename(fname_tmp, fname_out) - except WindowsError as e: - # On Windows, os.rename works slightly differently than on - # Linux; quoting the documentation: - # "On Unix, if dst exists and is a file, it will be replaced - # silently if the user has permission. The operation may fail - # on some Unix flavors if src and dst are on different - # filesystems. If successful, the renaming will be an atomic - # operation (this is a POSIX requirement). On Windows, if dst - # already exists, OSError will be raised even if it is a file; - # there may be no way to implement an atomic rename when dst - # names an existing file." - # [Error 183] Cannot create a file when that file already exists - if e.winerror != 183: - raise - os.remove(fname_tmp) - os.remove(fname_in) - - self.load_code(block.loc_key, fname_out) - - @staticmethod - def gen_C_source(lifter, func_code): - c_source = "" - c_source += "\n".join(func_code) - - c_source = gen_core(lifter.arch, lifter.attrib) + c_source - c_source = "#define PARITY_IMPORT\n#include <Python.h>\n" + c_source - return c_source diff --git a/miasm/jitter/jitcore_llvm.py b/miasm/jitter/jitcore_llvm.py deleted file mode 100644 index 4f1871b2..00000000 --- a/miasm/jitter/jitcore_llvm.py +++ /dev/null @@ -1,144 +0,0 @@ -from __future__ import print_function -import os -import glob -import importlib -import tempfile -import sysconfig - -from miasm.jitter.llvmconvert import * -import miasm.jitter.jitcore as jitcore -from miasm.jitter import Jitllvm -import platform - -import llvmlite -llvmlite.binding.load_library_permanently(Jitllvm.__file__) - -is_win = platform.system() == "Windows" - -class JitCore_LLVM(jitcore.JitCore): - "JiT management, using LLVM as backend" - - # Architecture dependent libraries - arch_dependent_libs = { - "x86": "JitCore_x86", - "arm": "JitCore_arm", - "msp430": "JitCore_msp430", - "mips32": "JitCore_mips32", - "aarch64": "JitCore_aarch64", - "ppc32": "JitCore_ppc32", - } - - def __init__(self, lifter, bin_stream): - super(JitCore_LLVM, self).__init__(lifter, bin_stream) - - self.options.update( - { - "safe_mode": True, # Verify each function - "optimise": True, # Optimise functions - "log_func": False, # Print LLVM functions - "log_assembly": False, # Print assembly executed - } - ) - - self.exec_wrapper = Jitllvm.llvm_exec_block - self.lifter = lifter - - # Cache temporary dir - self.tempdir = os.path.join(tempfile.gettempdir(), "miasm_cache") - try: - os.mkdir(self.tempdir, 0o755) - except OSError: - pass - if not os.access(self.tempdir, os.R_OK | os.W_OK): - raise RuntimeError( - 'Cannot access cache directory %s ' % self.tempdir) - - def load(self): - - # Library to load within Jit context - libs_to_load = [] - - # Get architecture dependent Jitcore library (if any) - lib_dir = os.path.dirname(os.path.realpath(__file__)) - ext = sysconfig.get_config_var('EXT_SUFFIX') - if ext is None: - ext = ".so" if not is_win else ".pyd" - if is_win: - # sysconfig.get_config_var('EXT_SUFFIX') is .pyd on Windows and need to be forced to .lib - # Additionally windows built libraries may have a name like VmMngr.cp38-win_amd64.lib - ext_files = glob.glob(os.path.join(lib_dir, "VmMngr.*pyd")) - if len(ext_files) == 1: - ext = os.path.basename(ext_files[0]).replace("VmMngr", "") - lib_dir = os.path.join(lib_dir, 'arch') - try: - jit_lib = os.path.join( - lib_dir, self.arch_dependent_libs[self.lifter.arch.name] + ext - ) - libs_to_load.append(jit_lib) - except KeyError: - pass - - # Create a context - self.context = LLVMContext_JIT(libs_to_load, self.lifter) - - # Set the optimisation level - self.context.optimise_level() - - # Save the current architecture parameters - self.arch = self.lifter.arch - - # Get the correspondence between registers and vmcpu struct - mod_name = "miasm.jitter.arch.JitCore_%s" % (self.lifter.arch.name) - mod = importlib.import_module(mod_name) - self.context.set_vmcpu(mod.get_gpreg_offset_all()) - - # Enable caching - self.context.enable_cache() - - 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, self.FUNCNAME) - - # Set log level - func.log_regs = self.log_regs - func.log_mn = self.log_mn - - # Import asm block - func.from_asmblock(block) - - # Verify - if self.options["safe_mode"] is True: - func.verify() - - # Optimise - if self.options["optimise"] is True: - func.optimise() - - # Log - if self.options["log_func"] is True: - print(func) - if self.options["log_assembly"] is True: - print(func.get_assembly()) - - # Use propagate the cache filename - self.context.set_cache_filename(func, fname_out) - - # Get a pointer on the function for JiT - ptr = func.get_function_pointer() - - else: - # The cache file exists: function can be loaded from cache - ptr = self.context.get_ptr_from_cache(fname_out, self.FUNCNAME) - - # Store a pointer on the function jitted code - loc_key = block.loc_key - offset = self.lifter.loc_db.get_location_offset(loc_key) - self.offset_to_jitted_func[offset] = ptr diff --git a/miasm/jitter/jitcore_python.py b/miasm/jitter/jitcore_python.py deleted file mode 100644 index 269df973..00000000 --- a/miasm/jitter/jitcore_python.py +++ /dev/null @@ -1,219 +0,0 @@ -from __future__ import print_function -from builtins import zip -import miasm.jitter.jitcore as jitcore -from miasm.expression.expression import ExprInt, ExprLoc -import miasm.jitter.csts as csts -from miasm.expression.simplifications import expr_simp_explicit -from miasm.jitter.emulatedsymbexec import EmulatedSymbExec - -################################################################################ -# Python jitter Core # -################################################################################ - - -class JitCore_Python(jitcore.JitCore): - "JiT management, using Miasm2 Symbol Execution engine as backend" - - SymbExecClass = EmulatedSymbExec - - def __init__(self, lifter, bin_stream): - super(JitCore_Python, self).__init__(lifter, bin_stream) - self.lifter = lifter - self.ircfg = self.lifter.new_ircfg() - - # CPU & VM (None for now) will be set later - - self.symbexec = self.SymbExecClass( - None, None, - self.lifter, {}, - sb_expr_simp=expr_simp_explicit - ) - self.symbexec.enable_emulated_simplifications() - - def set_cpu_vm(self, cpu, vm): - self.symbexec.cpu = cpu - self.symbexec.vm = vm - - def load(self): - "Preload symbols according to current architecture" - self.symbexec.reset_regs() - - def arch_specific(self): - """Return arch specific information for the current architecture""" - arch = self.lifter.arch - has_delayslot = False - if arch.name == "mips32": - from miasm.arch.mips32.jit import mipsCGen - cgen_class = mipsCGen - has_delayslot = True - elif arch.name == "arm": - from miasm.arch.arm.jit import arm_CGen - cgen_class = arm_CGen - else: - from miasm.jitter.codegen import CGen - cgen_class = CGen - return cgen_class(self.lifter), has_delayslot - - def add_block(self, asmblock): - """Create a python function corresponding to an AsmBlock - @asmblock: AsmBlock - """ - - # TODO: merge duplicate code with CGen, llvmconvert - codegen, has_delayslot = self.arch_specific() - irblocks_list = codegen.block2assignblks(asmblock) - instr_offsets = [line.offset for line in asmblock.lines] - - loc_db = self.lifter.loc_db - local_loc_keys = [] - for irblocks in irblocks_list: - for irblock in irblocks: - local_loc_keys.append(irblock.loc_key) - - def myfunc(cpu): - """Execute the function according to cpu and vmmngr states - @cpu: JitCpu instance - """ - # Get virtual memory handler - vmmngr = cpu.vmmngr - - # Get execution engine (EmulatedSymbExec instance) - exec_engine = self.symbexec - - # Refresh CPU values according to @cpu instance - exec_engine.update_engine_from_cpu() - - # Get initial loc_key - cur_loc_key = asmblock.loc_key - - # Update PC helper - update_pc = lambda value: setattr(cpu, self.lifter.pc.name, value) - - while True: - # Retrieve the expected irblock - for instr, irblocks in zip(asmblock.lines, irblocks_list): - for index, irblock in enumerate(irblocks): - if irblock.loc_key == cur_loc_key: - break - else: - continue - break - else: - raise RuntimeError("Unable to find the block for %r" % cur_loc_key) - - instr_attrib, irblocks_attributes = codegen.get_attributes( - instr, irblocks, self.log_mn, self.log_regs - ) - irblock_attributes = irblocks_attributes[index] - - # Do IRBlock - new_irblock = self.lifter.irbloc_fix_regs_for_mode( - irblock, self.lifter.attrib - ) - if index == 0: - # Pre code - if instr_attrib.log_mn: - print("%.8X %s" % ( - instr_attrib.instr.offset, - instr_attrib.instr.to_string(loc_db) - )) - - # Exec IRBlock - instr = instr_attrib.instr - - for index, assignblk in enumerate(irblock): - attributes = irblock_attributes[index] - - # Eval current instruction (in IR) - exec_engine.eval_updt_assignblk(assignblk) - - # Check memory access / write exception - # TODO: insert a check between memory reads and writes - if attributes.mem_read or attributes.mem_write: - # Restricted exception - flag = ~csts.EXCEPT_CODE_AUTOMOD & csts.EXCEPT_DO_NOT_UPDATE_PC - if (vmmngr.get_exception() & flag != 0): - # Do not update registers - update_pc(instr.offset) - return instr.offset - - # Update registers values - exec_engine.update_cpu_from_engine() - - # Check post assignblk exception flags - if attributes.set_exception: - # Restricted exception - if cpu.get_exception() > csts.EXCEPT_NUM_UPDT_EIP: - # Update PC - update_pc(instr.offset) - return instr.offset - - dst = exec_engine.eval_expr(self.lifter.IRDst) - if dst.is_int(): - loc_key = loc_db.get_or_create_offset_location(int(dst)) - dst = ExprLoc(loc_key, dst.size) - - assert dst.is_loc() - loc_key = dst.loc_key - offset = loc_db.get_location_offset(loc_key) - if offset is None: - # Avoid checks on generated label - cur_loc_key = loc_key - continue - - if instr_attrib.log_regs: - update_pc(offset) - cpu.dump_gpregs_with_attrib(self.lifter.attrib) - - # Post-instr checks - if instr_attrib.mem_read | instr_attrib.mem_write: - vmmngr.check_memory_breakpoint() - vmmngr.check_invalid_code_blocs() - if vmmngr.get_exception(): - update_pc(offset) - return offset - - if instr_attrib.set_exception: - if cpu.get_exception(): - update_pc(offset) - return offset - - if instr_attrib.mem_read | instr_attrib.mem_write: - vmmngr.reset_memory_access() - - # Manage resulting address - if (loc_key in local_loc_keys and - offset > instr.offset): - # Forward local jump - # Note: a backward local jump has to be promoted to extern, - # for max_exec_per_call support - cur_loc_key = loc_key - continue - - # Delay slot - if has_delayslot: - delay_slot_set = exec_engine.eval_expr(codegen.delay_slot_set) - if delay_slot_set.is_int() and int(delay_slot_set) != 0: - return int(exec_engine.eval_expr(codegen.delay_slot_dst)) - - # Extern of asmblock, must have an offset - assert offset is not None - return offset - - # Associate myfunc with current loc_key - offset = loc_db.get_location_offset(asmblock.loc_key) - assert offset is not None - self.offset_to_jitted_func[offset] = myfunc - - def exec_wrapper(self, loc_key, cpu, _offset_to_jitted_func, _stop_offsets, - _max_exec_per_call): - """Call the function @loc_key with @cpu - @loc_key: function's loc_key - @cpu: JitCpu instance - """ - - # 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/miasm/jitter/jitload.py b/miasm/jitter/jitload.py deleted file mode 100644 index 99e4429d..00000000 --- a/miasm/jitter/jitload.py +++ /dev/null @@ -1,585 +0,0 @@ -import logging -import warnings -from functools import wraps -from collections import namedtuple -try: - from collections.abc import Sequence, Iterator -except ImportError: - from collections import Sequence, Iterator - -from future.utils import viewitems - -from miasm.jitter.csts import * -from miasm.core.utils import * -from miasm.core.bin_stream import bin_stream_vm -from miasm.jitter.emulatedsymbexec import EmulatedSymbExec -from miasm.jitter.codegen import CGen -from miasm.jitter.jitcore_cc_base import JitCore_Cc_Base - -hnd = logging.StreamHandler() -hnd.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s")) -log = logging.getLogger('jitload.py') -log.addHandler(hnd) -log.setLevel(logging.CRITICAL) -log_func = logging.getLogger('jit function call') -log_func.addHandler(hnd) -log_func.setLevel(logging.CRITICAL) - -try: - from miasm.jitter import VmMngr -except ImportError: - log.error('cannot import VmMngr') - - -def named_arguments(func): - """Function decorator to allow the use of .func_args_*() methods - with either the number of arguments or the list of the argument - names. - - The wrapper is also used to log the argument values. - - @func: function - - """ - @wraps(func) - def newfunc(self, args): - if isinstance(args, Sequence): - ret_ad, arg_vals = func(self, len(args)) - arg_vals = namedtuple("args", args)(*arg_vals) - # func_name(arguments) return address - log_func.info( - '%s(%s) ret addr: %s', - get_caller_name(1), - ', '.join( - "%s=0x%x" % (field, value) - for field, value in viewitems(arg_vals._asdict()) - ), - hex(ret_ad) - ) - return ret_ad, namedtuple("args", args)(*arg_vals) - else: - ret_ad, arg_vals = func(self, args) - # func_name(arguments) return address - log_func.info('%s(%s) ret addr: %s', - get_caller_name(1), - ', '.join(hex(arg) for arg in arg_vals), - hex(ret_ad)) - return ret_ad, arg_vals - return newfunc - - -class CallbackHandler(object): - - "Handle a list of callback" - - def __init__(self): - self.callbacks = {} # Key -> [callback list] - - def add_callback(self, key, callback): - """Add a callback to the key @key, iff the @callback isn't already - assigned to it""" - if callback not in self.callbacks.get(key, []): - self.callbacks[key] = self.callbacks.get(key, []) + [callback] - - def set_callback(self, key, *args): - "Set the list of callback for key 'key'" - self.callbacks[key] = list(args) - - def get_callbacks(self, key): - "Return the list of callbacks associated to key 'key'" - return self.callbacks.get(key, []) - - def remove_callback(self, callback): - """Remove the callback from the list. - Return the list of empty keys (removed)""" - - to_check = set() - for key, cb_list in viewitems(self.callbacks): - try: - cb_list.remove(callback) - to_check.add(key) - except ValueError: - pass - - empty_keys = [] - for key in to_check: - if len(self.callbacks[key]) == 0: - empty_keys.append(key) - del(self.callbacks[key]) - - return empty_keys - - def has_callbacks(self, key): - return key in self.callbacks - - def remove_key(self, key): - """Remove and return all callbacks associated to @key""" - callbacks = self.callbacks.get(key, []) - del self.callbacks[key] - return callbacks - - def call_callbacks(self, key, *args): - """Call callbacks associated to key 'key' with arguments args. While - callbacks return True, continue with next callback. - Iterator on other results.""" - - res = True - - for c in self.get_callbacks(key): - res = c(*args) - if res is not True: - yield res - - def __call__(self, key, *args): - "Wrapper for call_callbacks" - return self.call_callbacks(key, *args) - - -class CallbackHandlerBitflag(CallbackHandler): - - "Handle a list of callback with conditions on bitflag" - - 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""" - - for bitflag_expected in self.callbacks: - if bitflag_expected & bitflag == bitflag_expected: - # If the flag matched - for res in super(CallbackHandlerBitflag, - self).call_callbacks(bitflag_expected, *args): - if res is not True: - yield res - - -class ExceptionHandle(object): - - "Return type for exception handler" - - def __init__(self, except_flag): - self.except_flag = except_flag - - @classmethod - def memoryBreakpoint(cls): - return cls(EXCEPT_BREAKPOINT_MEMORY) - - def __eq__(self, to_cmp): - if not isinstance(to_cmp, ExceptionHandle): - return False - return (self.except_flag == to_cmp.except_flag) - - def __ne__(self, to_cmp): - return not self.__eq__(to_cmp) - - -class JitterException(Exception): - - "Raised when any unhandled exception occurs (in jitter.vm or jitter.cpu)" - - def __init__(self, exception_flag): - super(JitterException, self).__init__() - self.exception_flag = exception_flag - - def __str__(self): - return "A jitter exception occurred: %s (0x%x)" % ( - self.exception_flag_to_str(), self.exception_flag - ) - - def exception_flag_to_str(self): - exception_flag_list = [] - for name, value in JitterExceptions.items(): - if value & self.exception_flag == value: - exception_flag_list.append(name) - return ' & '.join(exception_flag_list) - - -class Jitter(object): - - "Main class for JIT handling" - - C_Gen = CGen - - def __init__(self, lifter, jit_type="gcc"): - """Init an instance of jitter. - @lifter: Lifter instance for this architecture - @jit_type: JiT backend to use. Available options are: - - "gcc" - - "llvm" - - "python" - """ - - self.arch = lifter.arch - self.attrib = lifter.attrib - arch_name = lifter.arch.name # (lifter.arch.name, lifter.attrib) - self.running = False - - try: - if arch_name == "x86": - from miasm.jitter.arch import JitCore_x86 as jcore - elif arch_name == "arm": - from miasm.jitter.arch import JitCore_arm as jcore - elif arch_name == "armt": - from miasm.jitter.arch import JitCore_arm as jcore - lifter.arch.name = 'arm' - elif arch_name == "aarch64": - from miasm.jitter.arch import JitCore_aarch64 as jcore - elif arch_name == "msp430": - from miasm.jitter.arch import JitCore_msp430 as jcore - elif arch_name == "mips32": - from miasm.jitter.arch import JitCore_mips32 as jcore - elif arch_name == "ppc32": - from miasm.jitter.arch import JitCore_ppc32 as jcore - elif arch_name == "mep": - from miasm.jitter.arch import JitCore_mep as jcore - else: - raise ValueError("unknown jit arch: %s" % arch_name) - except ImportError: - raise RuntimeError('Unsupported jit arch: %s' % arch_name) - - self.vm = VmMngr.Vm() - self.cpu = jcore.JitCpu() - self.lifter = lifter - self.bs = bin_stream_vm(self.vm) - self.ircfg = self.lifter.new_ircfg() - - self.symbexec = EmulatedSymbExec( - self.cpu, self.vm, self.lifter, {} - ) - self.symbexec.reset_regs() - - try: - if jit_type == "llvm": - from miasm.jitter.jitcore_llvm import JitCore_LLVM as JitCore - elif jit_type == "python": - from miasm.jitter.jitcore_python import JitCore_Python as JitCore - elif jit_type == "gcc": - from miasm.jitter.jitcore_gcc import JitCore_Gcc as JitCore - else: - raise ValueError("Unknown jitter %s" % jit_type) - except ImportError: - raise RuntimeError('Unsupported jitter: %s' % jit_type) - - self.jit = JitCore(self.lifter, self.bs) - if isinstance(self.jit, JitCore_Cc_Base): - self.jit.init_codegen(self.C_Gen(self.lifter)) - elif jit_type == "python": - self.jit.set_cpu_vm(self.cpu, self.vm) - - self.cpu.init_regs() - self.vm.init_memory_page_pool() - self.vm.init_code_bloc_pool() - self.vm.init_memory_breakpoint() - - self.jit.load() - self.cpu.vmmngr = self.vm - self.cpu.jitter = self.jit - self.stack_size = 0x10000 - self.stack_base = 0x1230000 - - # Init callback handler - self.breakpoints_handler = CallbackHandler() - self.exceptions_handler = CallbackHandlerBitflag() - self.init_exceptions_handler() - self.exec_cb = None - - def init_exceptions_handler(self): - "Add common exceptions handlers" - - def exception_automod(jitter): - "Tell the JiT backend to update blocks modified" - - self.jit.updt_automod_code(jitter.vm) - self.vm.set_exception(0) - - return True - - self.add_exception_handler(EXCEPT_CODE_AUTOMOD, exception_automod) - - def add_breakpoint(self, addr, callback): - """Add a callback associated with addr. - @addr: breakpoint address - @callback: function with definition (jitter instance) - """ - self.breakpoints_handler.add_callback(addr, callback) - self.jit.add_disassembly_splits(addr) - # De-jit previously jitted blocks - self.jit.updt_automod_code_range(self.vm, [(addr, addr)]) - - def set_breakpoint(self, addr, *args): - """Set callbacks associated with addr. - @addr: breakpoint address - @args: functions with definition (jitter instance) - """ - self.breakpoints_handler.set_callback(addr, *args) - self.jit.add_disassembly_splits(addr) - - def get_breakpoint(self, addr): - """ - Return breakpoints handlers for address @addr - @addr: integer - """ - return self.breakpoints_handler.get_callbacks(addr) - - def remove_breakpoints_by_callback(self, callback): - """Remove callbacks associated with breakpoint. - @callback: callback to remove - """ - empty_keys = self.breakpoints_handler.remove_callback(callback) - for key in empty_keys: - self.jit.remove_disassembly_splits(key) - - def remove_breakpoints_by_address(self, address): - """Remove all breakpoints associated with @address. - @address: address of breakpoints to remove - """ - callbacks = self.breakpoints_handler.remove_key(address) - if callbacks: - self.jit.remove_disassembly_splits(address) - - def add_exception_handler(self, flag, callback): - """Add a callback associated with an exception flag. - @flag: bitflag - @callback: function with definition (jitter instance) - """ - self.exceptions_handler.add_callback(flag, callback) - - 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.run_at( - self.cpu, pc, - set(self.breakpoints_handler.callbacks) - ) - - 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) - if res is not True: - yield res - - # Check breakpoints - old_pc = self.pc - for res in self.breakpoints_handler.call_callbacks(self.pc, self): - if res is not True: - if isinstance(res, Iterator): - # If the breakpoint is a generator, yield it step by step - for tmp in res: - yield tmp - else: - yield res - - # Check exceptions (raised by breakpoints) - exception_flag = self.get_exception() - for res in self.exceptions_handler(exception_flag, self): - if res is not True: - if isinstance(res, Iterator): - for tmp in res: - yield tmp - else: - yield res - - # If a callback changed pc, re call every callback - if old_pc != self.pc: - return - - # Exceptions should never be activated before run - exception_flag = self.get_exception() - if exception_flag: - raise JitterException(exception_flag) - - # Run the block at PC - self.pc = self.run_at(self.pc) - - # Check exceptions (raised by the execution of the block) - exception_flag = self.get_exception() - for res in self.exceptions_handler(exception_flag, self): - if res is not True: - if isinstance(res, Iterator): - for tmp in res: - yield tmp - else: - yield res - - def init_run(self, pc): - """Create an iterator on pc with runiter. - @pc: address of code to run - """ - self.run_iterator = self.runiter_once(pc) - self.pc = pc - self.running = True - - def continue_run(self, step=False, trace=False): - """PRE: init_run. - Continue the run of the current session until iterator returns or run is - set to False. - If step is True, run only one time. - If trace is True, activate trace log option until execution stops - Return the iterator value""" - - if trace: - self.set_trace_log() - while self.running: - try: - return next(self.run_iterator) - except StopIteration: - pass - - self.run_iterator = self.runiter_once(self.pc) - - if step is True: - break - if trace: - self.set_trace_log(False, False, False) - return None - - - def run(self, addr): - """ - Launch emulation - @addr: (int) start address - """ - self.init_run(addr) - return self.continue_run() - - def run_until(self, addr, trace=False): - """PRE: init_run. - Continue the run of the current session until iterator returns, run is - set to False or addr is reached. - If trace is True, activate trace log option until execution stops - Return the iterator value""" - - def stop_exec(jitter): - jitter.remove_breakpoints_by_callback(stop_exec) - return False - self.add_breakpoint(addr, stop_exec) - return self.continue_run(trace=trace) - - def init_stack(self): - self.vm.add_memory_page( - self.stack_base, - PAGE_READ | PAGE_WRITE, - b"\x00" * self.stack_size, - "Stack") - sp = self.arch.getsp(self.attrib) - setattr(self.cpu, sp.name, self.stack_base + self.stack_size) - # regs = self.cpu.get_gpreg() - # regs[sp.name] = self.stack_base+self.stack_size - # self.cpu.set_gpreg(regs) - - def get_exception(self): - return self.cpu.get_exception() | self.vm.get_exception() - - # common functions - def get_c_str(self, addr, max_char=None): - """Get C str from vm. - @addr: address in memory - @max_char: maximum len""" - l = 0 - tmp = addr - while ((max_char is None or l < max_char) and - self.vm.get_mem(tmp, 1) != b"\x00"): - tmp += 1 - l += 1 - value = self.vm.get_mem(addr, l) - value = force_str(value) - return value - - def set_c_str(self, addr, value): - """Set C str str from vm. - @addr: address in memory - @value: str""" - value = force_bytes(value) - self.vm.set_mem(addr, value + b'\x00') - - def get_str_ansi(self, addr, max_char=None): - raise NotImplementedError("Deprecated: use os_dep.win_api_x86_32.get_win_str_a") - - def get_str_unic(self, addr, max_char=None): - raise NotImplementedError("Deprecated: use os_dep.win_api_x86_32.get_win_str_a") - - @staticmethod - def handle_lib(jitter): - """Resolve the name of the function which cause the handler call. Then - call the corresponding handler from users callback. - """ - fname = jitter.libs.fad2cname[jitter.pc] - if fname in jitter.user_globals: - func = jitter.user_globals[fname] - else: - log.debug('%r', fname) - raise ValueError('unknown api', hex(jitter.pc), repr(fname)) - ret = func(jitter) - jitter.pc = getattr(jitter.cpu, jitter.lifter.pc.name) - - # Don't break on a None return - if ret is None: - return True - else: - return ret - - def handle_function(self, f_addr): - """Add a breakpoint which will trigger the function handler""" - self.add_breakpoint(f_addr, self.handle_lib) - - def add_lib_handler(self, libs, user_globals=None): - """Add a function to handle libs call with breakpoints - @libs: libimp instance - @user_globals: dictionary for defined user function - """ - if user_globals is None: - user_globals = {} - - self.libs = libs - out = {} - for name, func in viewitems(user_globals): - out[name] = func - self.user_globals = out - - for f_addr in libs.fad2cname: - self.handle_function(f_addr) - - def eval_expr(self, expr): - """Eval expression @expr in the context of the current instance. Side - effects are passed on it""" - self.symbexec.update_engine_from_cpu() - ret = self.symbexec.eval_updt_expr(expr) - 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/miasm/jitter/llvmconvert.py b/miasm/jitter/llvmconvert.py deleted file mode 100644 index 2430d884..00000000 --- a/miasm/jitter/llvmconvert.py +++ /dev/null @@ -1,1935 +0,0 @@ -# -# -# Miasm2 Extension: # -# - Miasm2 IR to LLVM IR # -# - JiT # -# -# Requires: # -# - llvmlite (tested on v0.15) # -# -# Authors : Fabrice DESCLAUX (CEA/DAM), Camille MOUGEY (CEA/DAM) # -# -# - -from builtins import zip -from builtins import range -import os -from llvmlite import binding as llvm -from llvmlite import ir as llvm_ir -from builtins import int as int_types -import warnings - -from future.utils import viewitems, viewvalues - -from miasm.expression.expression import ExprId, ExprInt, ExprMem, ExprSlice, \ - ExprCond, ExprLoc, ExprOp, ExprCompose, LocKey, Expr, \ - TOK_EQUAL, \ - TOK_INF_SIGNED, TOK_INF_UNSIGNED, \ - TOK_INF_EQUAL_SIGNED, TOK_INF_EQUAL_UNSIGNED - -import miasm.jitter.csts as m2_csts -import miasm.core.asmblock as m2_asmblock -from miasm.core.utils import size2mask -from miasm.jitter.codegen import CGen, Attributes -from miasm.expression.expression_helper import possible_values - - -class LLVMType(llvm_ir.Type): - - "Handle LLVM Type" - - int_cache = {} - - @classmethod - def IntType(cls, size=32): - try: - return cls.int_cache[size] - except KeyError: - cls.int_cache[size] = llvm_ir.IntType(size) - return cls.int_cache[size] - - @classmethod - def pointer(cls, addr): - "Generic pointer for execution" - return llvm_e.GenericValue.pointer(addr) - - @classmethod - def generic(cls, e): - "Generic value for execution" - if isinstance(e, ExprInt): - return llvm_e.GenericValue.int(LLVMType.IntType(e.size), int(e.arg)) - elif isinstance(e, llvm_e.GenericValue): - return e - else: - raise ValueError() - - @classmethod - def fptype(cls, size): - """Return the floating type corresponding to precision @size""" - if size == 32: - precision = llvm_ir.FloatType() - elif size == 64: - precision = llvm_ir.DoubleType() - else: - raise RuntimeError("Unsupported precision: %x", size) - return precision - - -class LLVMContext(object): - - "Context for llvm binding. Stand for a LLVM Module" - - known_fc = {} - - def __init__(self, name="mod"): - "Initialize a context with a module named 'name'" - # Initialize llvm - llvm.initialize() - llvm.initialize_native_target() - llvm.initialize_native_asmprinter() - - # Initialize target for compilation - target = llvm.Target.from_default_triple() - 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 - 2: optimized - """ - - # Set up the optimiser pipeline - pmb = llvm.create_pass_manager_builder() - pmb.opt_level = level - pm = llvm.create_module_pass_manager() - pmb.populate(pm) - self.pass_manager = pm - - def init_exec_engine(self): - mod = llvm.parse_assembly("") - engine = llvm.create_mcjit_compiler(mod, - self.target_machine) - self.exec_engine = engine - - def new_module(self, name="mod"): - """Create a module, with needed functions""" - self.mod = llvm_ir.Module(name=name) - self.add_fc(self.known_fc) - self.add_op() - - def get_execengine(self): - "Return the Execution Engine associated with this context" - return self.exec_engine - - def get_passmanager(self): - "Return the Pass Manager associated with this context" - return self.pass_manager - - def get_module(self): - "Return the module associated with this context" - return self.mod - - def add_shared_library(self, filename): - "Load the shared library 'filename'" - return llvm.load_library_permanently(filename) - - def add_fc(self, fc, readonly=False): - "Add function into known_fc" - - for name, detail in viewitems(fc): - fnty = llvm_ir.FunctionType(detail["ret"], detail["args"]) - fn = llvm_ir.Function(self.mod, fnty, name=name) - if readonly: - fn.attributes.add("readonly") - - def add_op(self): - "Add operations functions" - - i8 = LLVMType.IntType(8) - p8 = llvm_ir.PointerType(i8) - itype = LLVMType.IntType(64) - ftype = llvm_ir.FloatType() - dtype = llvm_ir.DoubleType() - fc = {"llvm.ctpop.i8": {"ret": i8, - "args": [i8]}, - "llvm.nearbyint.f32": {"ret": ftype, - "args": [ftype]}, - "llvm.nearbyint.f64": {"ret": dtype, - "args": [dtype]}, - "llvm.trunc.f32": {"ret": ftype, - "args": [ftype]}, - "segm2addr": {"ret": itype, - "args": [p8, - itype, - itype]}, - "x86_cpuid": {"ret": itype, - "args": [itype, - itype]}, - "fpu_fcom_c0": {"ret": itype, - "args": [dtype, - dtype]}, - "fpu_fcom_c1": {"ret": itype, - "args": [dtype, - dtype]}, - "fpu_fcom_c2": {"ret": itype, - "args": [dtype, - dtype]}, - "fpu_fcom_c3": {"ret": itype, - "args": [dtype, - dtype]}, - "llvm.sqrt.f32": {"ret": ftype, - "args": [ftype]}, - "llvm.sqrt.f64": {"ret": dtype, - "args": [dtype]}, - "llvm.fabs.f32": {"ret": ftype, - "args": [ftype]}, - "llvm.fabs.f64": {"ret": dtype, - "args": [dtype]}, - } - - for k in [8, 16]: - fc["bcdadd_%s" % k] = {"ret": LLVMType.IntType(k), - "args": [LLVMType.IntType(k), - LLVMType.IntType(k)]} - fc["bcdadd_cf_%s" % k] = {"ret": LLVMType.IntType(k), - "args": [LLVMType.IntType(k), - LLVMType.IntType(k)]} - self.add_fc(fc, readonly=True) - - - def memory_lookup(self, func, addr, size): - """Perform a memory lookup at @addr of size @size (in bit)""" - raise NotImplementedError("Abstract method") - - def memory_write(self, func, addr, size, value): - """Perform a memory write at @addr of size @size (in bit) with LLVM IR @value""" - raise NotImplementedError("Abstract method") - - -class LLVMContext_JIT(LLVMContext): - - """Extend LLVMContext_JIT in order to handle memory management and custom - operations""" - - def __init__(self, library_filenames, lifter, name="mod"): - "Init a LLVMContext object, and load the mem management shared library" - self.library_filenames = library_filenames - self.lifter = lifter - self.arch_specific() - self.load_libraries() - LLVMContext.__init__(self, name) - self.vmcpu = {} - - @property - def ir_arch(self): - warnings.warn('DEPRECATION WARNING: use ".lifter" instead of ".ir_arch"') - return self.lifter - - def load_libraries(self): - # Get LLVM specific functions - name = "libLLVM-%d.%d" % (llvm.llvm_version_info[0], - llvm.llvm_version_info[1], - ) - try: - # On Windows, no need to add ".dll" - self.add_shared_library(name) - except RuntimeError: - try: - # On Linux, ".so" is needed - self.add_shared_library("%s.so" % name) - except RuntimeError: - pass - - # Load additional libraries - for lib_fname in self.library_filenames: - self.add_shared_library(lib_fname) - - def new_module(self, name="mod"): - LLVMContext.new_module(self, name) - self.add_memlookups() - self.add_get_exceptionflag() - self.add_log_functions() - - def arch_specific(self): - arch = self.lifter.arch - if arch.name == "x86": - self.PC = arch.regs.RIP - self.logging_func = "dump_gpregs_%d" % self.lifter.attrib - else: - self.PC = self.lifter.pc - self.logging_func = "dump_gpregs" - if arch.name == "mips32": - from miasm.arch.mips32.jit import mipsCGen - self.cgen_class = mipsCGen - self.has_delayslot = True - elif arch.name == "arm": - from miasm.arch.arm.jit import arm_CGen - self.cgen_class = arm_CGen - self.has_delayslot = False - else: - self.cgen_class = CGen - self.has_delayslot = False - - def add_memlookups(self): - "Add MEM_LOOKUP functions" - - fc = {} - p8 = llvm_ir.PointerType(LLVMType.IntType(8)) - for i in [8, 16, 32, 64]: - fc["MEM_LOOKUP_%02d" % i] = {"ret": LLVMType.IntType(i), - "args": [p8, - LLVMType.IntType(64)]} - - fc["MEM_WRITE_%02d" % i] = {"ret": llvm_ir.VoidType(), - "args": [p8, - LLVMType.IntType(64), - LLVMType.IntType(i)]} - - fc["MEM_LOOKUP_INT_BN_TO_PTR"] = {"ret": llvm_ir.VoidType(), - "args": [ - p8, - LLVMType.IntType(32), - LLVMType.IntType(64), - p8 - ]} - fc["MEM_WRITE_INT_BN_FROM_PTR"] = {"ret": llvm_ir.VoidType(), - "args": [ - p8, - LLVMType.IntType(32), - LLVMType.IntType(64), - p8, - ]} - - fc["reset_memory_access"] = {"ret": llvm_ir.VoidType(), - "args": [p8, - ]} - fc["check_memory_breakpoint"] = {"ret": llvm_ir.VoidType(), - "args": [p8, - ]} - fc["check_invalid_code_blocs"] = {"ret": llvm_ir.VoidType(), - "args": [p8, - ]} - self.add_fc(fc) - - def add_get_exceptionflag(self): - "Add 'get_exception_flag' function" - p8 = llvm_ir.PointerType(LLVMType.IntType(8)) - self.add_fc({"get_exception_flag": {"ret": LLVMType.IntType(64), - "args": [p8]}}, readonly=True) - - def add_log_functions(self): - "Add functions for state logging" - - p8 = llvm_ir.PointerType(LLVMType.IntType(8)) - self.add_fc({self.logging_func: {"ret": llvm_ir.VoidType(), - "args": [p8]}}, - readonly=True) - - def set_vmcpu(self, lookup_table): - "Set the correspondence between register name and vmcpu offset" - - self.vmcpu = lookup_table - - def memory_lookup(self, func, addr, size): - """Perform a memory lookup at @addr of size @size (in bit)""" - builder = func.builder - if size <= 64: - fc_name = "MEM_LOOKUP_%02d" % size - fc_ptr = self.mod.get_global(fc_name) - addr_casted = builder.zext(addr, LLVMType.IntType(64)) - ret = builder.call( - fc_ptr, [func.local_vars["jitcpu"],addr_casted] - ) - else: - # Miasm uses a memory lookup function which returns a bn_t for its - # result. We cannot simply translate this into IntType. The trick - # here is to use the function MEM_LOOKUP_INT_BN_TO_PTR which has a - # different interface: the resulting bn_t is passed through a char* - # argument. - # - # WARNING: Here, we use the fact that the serialisation of LLVM - # IntType is the *same* as the bn_t structure. - - fc_name = "MEM_LOOKUP_INT_BN_TO_PTR" - fc_ptr = self.mod.get_global(fc_name) - addr_casted = builder.zext(addr, LLVMType.IntType(64)) - size_cst = llvm_ir.Constant(LLVMType.IntType(32), size) - - value_ptr = builder.alloca(llvm_ir.IntType(size)) - value_ptr_u8 = builder.bitcast( - value_ptr, - LLVMType.IntType(8).as_pointer() - ) - - - builder.call( - fc_ptr, - [ - func.local_vars["jitcpu"], - size_cst, - addr_casted, - value_ptr_u8 - ] - ) - ret = builder.load(value_ptr) - - return ret - - def memory_write(self, func, addr, size, value): - """Perform a memory write at @addr of size @size (in bit) with LLVM IR @value""" - # Function call - builder = func.builder - if size <= 64: - fc_name = "MEM_WRITE_%02d" % size - fc_ptr = self.mod.get_global(fc_name) - dst_casted = builder.zext(addr, LLVMType.IntType(64)) - builder.call( - fc_ptr, - [ - func.local_vars["jitcpu"], - dst_casted, - value - ] - ) - else: - # The same trick as described in MEM_LOOKUP_INT_BN_TO_PTR is used - # here. - - fc_name = "MEM_WRITE_INT_BN_FROM_PTR" - fc_ptr = self.mod.get_global(fc_name) - addr_casted = builder.zext(addr, LLVMType.IntType(64)) - size_cst = llvm_ir.Constant(LLVMType.IntType(32), size) - - ret = builder.alloca(value.type) - builder.store(value, ret) - value_ptr = builder.bitcast(ret, llvm_ir.IntType(8).as_pointer()) - - builder.call( - fc_ptr, - [ - func.local_vars["jitcpu"], - size_cst, - addr_casted, - value_ptr, - ] - ) - - - @staticmethod - def cache_notify(module, buffer): - """Called when @module has been compiled to @buffer""" - if not hasattr(module, "fname_out"): - return - fname_out = module.fname_out - - if os.access(fname_out, os.R_OK): - # No need to overwrite - return - - open(fname_out, "wb").write(buffer) - - @staticmethod - def cache_getbuffer(module): - """Return a compiled buffer for @module if available""" - if not hasattr(module, "fname_out"): - return None - - fname_out = module.fname_out - if os.access(fname_out, os.R_OK): - return open(fname_out, "rb").read() - return None - - def enable_cache(self): - "Enable cache of compiled object" - # Load shared libraries - for lib_fname in self.library_filenames: - self.add_shared_library(lib_fname) - - # Activate cache - self.exec_engine.set_object_cache( - self.cache_notify, - self.cache_getbuffer - ) - - def set_cache_filename(self, func, fname_out): - "Set the filename @fname_out to use for cache for @func" - # Use a custom attribute to propagate the cache filename - func.as_llvm_mod().fname_out = fname_out - - def get_ptr_from_cache(self, file_name, func_name): - "Load @file_name and return a pointer on the jitter @func_name" - # We use an empty module to avoid losing time on function building - empty_module = llvm.parse_assembly("") - empty_module.fname_out = file_name - - engine = self.exec_engine - engine.add_module(empty_module) - engine.finalize_object() - return engine.get_function_address(func_name) - - -class LLVMContext_IRCompilation(LLVMContext): - - """Extend LLVMContext in order to handle memory management and custom - operations for Miasm IR compilation""" - - def memory_lookup(self, func, addr, size): - """Perform a memory lookup at @addr of size @size (in bit)""" - builder = func.builder - int_size = LLVMType.IntType(size) - ptr_casted = builder.inttoptr( - addr, - llvm_ir.PointerType(int_size) - ) - return builder.load(ptr_casted) - - def memory_write(self, func, addr, size, value): - """Perform a memory write at @addr of size @size (in bit) with LLVM IR @value""" - builder = func.builder - int_size = LLVMType.IntType(size) - ptr_casted = builder.inttoptr( - addr, - llvm_ir.PointerType(int_size) - ) - return builder.store(value, ptr_casted) - - -class LLVMFunction(object): - """Represent a LLVM function - - Implementation note: - A new module is created each time to avoid cumulative lag (if @new_module) - """ - - # Default logging values - log_mn = False - log_regs = True - - # Operation translation - ## Basics - op_translate = {'x86_cpuid': 'x86_cpuid', - } - ## Add the size as first argument - op_translate_with_size = {} - ## Add the size as suffix - op_translate_with_suffix_size = { - 'bcdadd': 'bcdadd', - 'bcdadd_cf': 'bcdadd_cf', - } - - def __init__(self, llvm_context, name="fc", new_module=True): - "Create a new function with name @name" - self.llvm_context = llvm_context - if new_module: - self.llvm_context.new_module() - self.mod = self.llvm_context.get_module() - - self.my_args = [] # (Expr, LLVMType, Name) - self.ret_type = None - self.builder = None - self.entry_bbl = None - - self.branch_counter = 0 - self.name = name - self._llvm_mod = None - - # Constructor utils - - def new_branch_name(self): - "Return a new branch name" - self.branch_counter += 1 - return str(self.branch_counter) - - def append_basic_block(self, label, overwrite=True): - """Add a new basic block to the current function. - @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.llvm_context.canonize_label_name(label) - bbl = self.name2bbl.get(name, None) - if not overwrite and bbl is not None: - return bbl - bbl = self.fc.append_basic_block(name) - self.name2bbl[name] = bbl - - return bbl - - def CreateEntryBlockAlloca(self, var_type, default_value=None): - """Create an alloca instruction at the beginning of the current fc - @default_value: if set, store the default_value just after the allocation - """ - builder = self.builder - current_bbl = builder.basic_block - builder.position_at_start(self.entry_bbl) - - ret = builder.alloca(var_type) - if default_value is not None: - builder.store(default_value, ret) - builder.position_at_end(current_bbl) - return ret - - def get_ptr_by_expr(self, expr): - """"Return a pointer casted corresponding to ExprId expr. If it is not - already computed, compute it at the end of entry_bloc""" - - name = expr.name - - ptr_casted = self.local_vars_pointers.get(name, None) - if ptr_casted is not None: - # If the pointer has already been computed - return ptr_casted - - # Get current objects - builder = self.builder - current_bbl = builder.basic_block - - # Go at the right position - entry_bloc_bbl = self.entry_bbl - builder.position_at_end(entry_bloc_bbl) - - # Compute the pointer address - offset = self.llvm_context.vmcpu[name] - - # Pointer cast - ptr = builder.gep( - self.local_vars["vmcpu"], - [ - llvm_ir.Constant( - LLVMType.IntType(), - offset - ) - ] - ) - pointee_type = LLVMType.IntType(expr.size) - ptr_casted = builder.bitcast( - ptr, - llvm_ir.PointerType(pointee_type) - ) - # Store in cache - self.local_vars_pointers[name] = ptr_casted - - # Reset builder - builder.position_at_end(current_bbl) - - return ptr_casted - - def update_cache(self, name, value): - "Add 'name' = 'value' to the cache iff main_stream = True" - - if self.main_stream is True: - self.expr_cache[name] = value - - def set_ret(self, var): - "Cast @var and return it at the end of current bbl" - if var.type.width < 64: - var_casted = self.builder.zext(var, LLVMType.IntType(64)) - else: - var_casted = var - self.builder.ret(var_casted) - - def get_basic_block_by_loc_key(self, loc_key): - "Return the bbl corresponding to label, None otherwise" - return self.name2bbl.get( - self.llvm_context.canonize_label_name(loc_key), - None - ) - - def global_constant(self, name, value): - """ - Inspired from numba/cgutils.py - - Get or create a (LLVM module-)global constant with *name* or *value*. - """ - if name in self.mod.globals: - return self.mod.globals[name] - data = llvm_ir.GlobalVariable(self.mod, value.type, name=name) - data.global_constant = True - data.initializer = value - return data - - def make_bytearray(self, buf): - """ - Inspired from numba/cgutils.py - - Make a byte array constant from *buf*. - """ - b = bytearray(buf) - n = len(b) - return llvm_ir.Constant(llvm_ir.ArrayType(llvm_ir.IntType(8), n), b) - - def printf(self, format, *args): - """ - Inspired from numba/cgutils.py - - Calls printf(). - Argument `format` is expected to be a Python string. - Values to be printed are listed in `args`. - - Note: There is no checking to ensure there is correct number of values - in `args` and there type matches the declaration in the format string. - """ - assert isinstance(format, str) - mod = self.mod - # Make global constant for format string - cstring = llvm_ir.IntType(8).as_pointer() - fmt_bytes = self.make_bytearray((format + '\00').encode('ascii')) - - base_name = "printf_format" - count = 0 - while "%s_%d" % (base_name, count) in self.mod.globals: - count += 1 - global_fmt = self.global_constant( - "%s_%d" % (base_name, count), - fmt_bytes - ) - fnty = llvm_ir.FunctionType( - llvm_ir.IntType(32), - [cstring], - var_arg=True - ) - # Insert printf() - fn = mod.globals.get('printf', None) - if fn is None: - fn = llvm_ir.Function(mod, fnty, name="printf") - # Call - ptr_fmt = self.builder.bitcast(global_fmt, cstring) - return self.builder.call(fn, [ptr_fmt] + list(args)) - - # Effective constructors - - def assign(self, src, dst): - "Assign from LLVM src to M2 dst" - - # Destination - builder = self.builder - - if isinstance(dst, ExprId): - ptr_casted = self.get_ptr_by_expr(dst) - builder.store(src, ptr_casted) - - elif isinstance(dst, ExprMem): - addr = self.add_ir(dst.ptr) - self.llvm_context.memory_write(self, addr, dst.size, src) - else: - raise Exception("UnknownAssignmentType") - - def init_fc(self): - "Init the function" - - # Build type for fc signature - fc_type = llvm_ir.FunctionType( - self.ret_type, - [k[1] for k in self.my_args] - ) - - # Add fc in module - try: - fc = llvm_ir.Function(self.mod, fc_type, name=self.name) - except llvm.LLVMException: - # Overwrite the previous function - previous_fc = self.mod.get_global(self.name) - previous_fc.delete() - fc = self.mod.add_function(fc_type, self.name) - - # Name args - for i, a in enumerate(self.my_args): - fc.args[i].name = a[2] - - # Initialize local variable pool - self.local_vars = {} - self.local_vars_pointers = {} - for i, a in enumerate(self.my_args): - self.local_vars[a[2]] = fc.args[i] - - # Init cache - self.expr_cache = {} - self.main_stream = True - self.name2bbl = {} - - # Function link - self.fc = fc - - # Add a first BasicBlock - self.entry_bbl = self.append_basic_block("entry") - - # Instruction builder - self.builder = llvm_ir.IRBuilder(self.entry_bbl) - - def add_ir(self, expr): - "Add a Miasm2 IR to the last bbl. Return the var created" - - if self.main_stream is True and expr in self.expr_cache: - return self.expr_cache[expr] - - builder = self.builder - - if isinstance(expr, ExprInt): - ret = llvm_ir.Constant(LLVMType.IntType(expr.size), int(expr)) - self.update_cache(expr, ret) - return ret - - if expr.is_loc(): - offset = self.llvm_context.lifter.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] - except KeyError: - pass - - ptr_casted = self.get_ptr_by_expr(expr) - - var = builder.load(ptr_casted, name) - self.update_cache(expr, var) - return var - - if isinstance(expr, ExprOp): - op = expr.op - - if (op in self.op_translate or - op in self.op_translate_with_size or - op in self.op_translate_with_suffix_size): - args = [self.add_ir(arg) for arg in expr.args] - arg_size = expr.args[0].size - - if op in self.op_translate_with_size: - fc_name = self.op_translate_with_size[op] - arg_size_cst = llvm_ir.Constant(LLVMType.IntType(64), - arg_size) - args = [arg_size_cst] + args - elif op in self.op_translate: - fc_name = self.op_translate[op] - elif op in self.op_translate_with_suffix_size: - fc_name = "%s_%s" % (self.op_translate[op], arg_size) - - fc_ptr = self.mod.get_global(fc_name) - - # Cast args if needed - casted_args = [] - for i, arg in enumerate(args): - if arg.type.width < fc_ptr.args[i].type.width: - casted_args.append( - builder.zext( - arg, - fc_ptr.args[i].type - ) - ) - else: - casted_args.append(arg) - ret = builder.call(fc_ptr, casted_args) - - # Cast ret if needed - ret_size = fc_ptr.return_value.type.width - if ret_size > expr.size: - ret = builder.trunc(ret, LLVMType.IntType(expr.size)) - - self.update_cache(expr, ret) - return ret - - if op == "-": - # Unsupported op '-' with more than 1 arg - assert len(expr.args) == 1 - zero = LLVMType.IntType(expr.size)(0) - ret = builder.sub(zero, self.add_ir(expr.args[0])) - self.update_cache(expr, ret) - return ret - - if op == "parity": - assert len(expr.args) == 1 - arg = self.add_ir(expr.args[0]) - truncated = builder.trunc(arg, LLVMType.IntType(8)) - bitcount = builder.call( - self.mod.get_global("llvm.ctpop.i8"), - [truncated] - ) - ret = builder.not_(builder.trunc(bitcount, LLVMType.IntType(1))) - self.update_cache(expr, ret) - return ret - - if op in ["cntleadzeros", "cnttrailzeros"]: - assert len(expr.args) == 1 - arg = self.add_ir(expr.args[0]) - func_name = { - "cntleadzeros": "ctlz", - "cnttrailzeros": "cttz", - }[op] - func_llvm_name = "llvm.%s.i%d" % (func_name, expr.size) - func_sig = { - func_llvm_name: { - "ret": LLVMType.IntType(expr.size), - "args": [LLVMType.IntType(expr.args[0].size)] - } - } - try: - self.mod.get_global(func_llvm_name) - except KeyError: - self.llvm_context.add_fc(func_sig, readonly=True) - ret = builder.call( - self.mod.get_global(func_llvm_name), - [arg] - ) - self.update_cache(expr, ret) - return ret - - - if op.startswith('zeroExt_'): - arg = expr.args[0] - if expr.size == arg.size: - return arg - new_expr = ExprCompose(arg, ExprInt(0, expr.size - arg.size)) - return self.add_ir(new_expr) - - if op.startswith("signExt_"): - arg = expr.args[0] - add_size = expr.size - arg.size - new_expr = ExprCompose( - arg, - ExprCond( - arg.msb(), - ExprInt(size2mask(add_size), add_size), - ExprInt(0, add_size) - ) - ) - return self.add_ir(new_expr) - - - if op == "segm": - fc_ptr = self.mod.get_global("segm2addr") - - # Cast args if needed - args = [self.add_ir(arg) for arg in expr.args] - casted_args = [] - for i, arg in enumerate(args, 1): - if arg.type.width < fc_ptr.args[i].type.width: - casted_args.append( - builder.zext( - arg, - fc_ptr.args[i].type - ) - ) - else: - casted_args.append(arg) - - ret = builder.call( - fc_ptr, - [self.local_vars["jitcpu"]] + casted_args - ) - if ret.type.width > expr.size: - ret = builder.trunc(ret, LLVMType.IntType(expr.size)) - self.update_cache(expr, ret) - return ret - - if op in ["smod", "sdiv", "umod", "udiv"]: - assert len(expr.args) == 2 - - arg_b = self.add_ir(expr.args[1]) - arg_a = self.add_ir(expr.args[0]) - - if op == "smod": - callback = builder.srem - elif op == "sdiv": - callback = builder.sdiv - elif op == "umod": - callback = builder.urem - elif op == "udiv": - callback = builder.udiv - - ret = callback(arg_a, arg_b) - self.update_cache(expr, ret) - return ret - - unsigned_cmps = { - "==": "==", - "<u": "<", - "<=u": "<=" - } - if op in unsigned_cmps: - op = unsigned_cmps[op] - args = [self.add_ir(arg) for arg in expr.args] - ret = builder.select( - builder.icmp_unsigned(op, - args[0], - args[1] - ), - llvm_ir.IntType(expr.size)(1), - llvm_ir.IntType(expr.size)(0) - ) - self.update_cache(expr, ret) - return ret - - if op in [">>", "<<", "a>>"]: - assert len(expr.args) == 2 - # Undefined behavior must be enforced to 0 - count = self.add_ir(expr.args[1]) - value = self.add_ir(expr.args[0]) - itype = LLVMType.IntType(expr.size) - cond_ok = self.builder.icmp_unsigned( - "<", - count, - itype(expr.size) - ) - zero = itype(0) - if op == ">>": - callback = builder.lshr - elif op == "<<": - callback = builder.shl - elif op == "a>>": - callback = builder.ashr - # x a>> size is 0 or -1, depending on x sign - cond_neg = self.builder.icmp_signed("<", value, zero) - zero = self.builder.select(cond_neg, itype(-1), zero) - - ret = self.builder.select( - cond_ok, - callback(value, count), - zero - ) - self.update_cache(expr, ret) - return ret - - - if op in ['<<<', '>>>']: - assert len(expr.args) == 2 - # First compute rotation modulus size - count = self.add_ir(expr.args[1]) - value = self.add_ir(expr.args[0]) - itype = LLVMType.IntType(expr.size) - expr_size = itype(expr.size) - - # As shift of expr_size is undefined, we urem the shifters - shift = builder.urem(count, expr_size) - shift_inv = builder.urem( - builder.sub(expr_size, shift), - expr_size - ) - - if op == '<<<': - part_a = builder.shl(value, shift) - part_b = builder.lshr(value, shift_inv) - else: - part_a = builder.lshr(value, shift) - part_b = builder.shl(value, shift_inv) - ret = builder.or_(part_a, part_b) - self.update_cache(expr, ret) - return ret - - if op == "sint_to_fp": - fptype = LLVMType.fptype(expr.size) - arg = self.add_ir(expr.args[0]) - ret = builder.sitofp(arg, fptype) - ret = builder.bitcast(ret, llvm_ir.IntType(expr.size)) - self.update_cache(expr, ret) - return ret - - if op.startswith("fp_to_sint"): - size_arg = expr.args[0].size - fptype_orig = LLVMType.fptype(size_arg) - arg = self.add_ir(expr.args[0]) - arg = builder.bitcast(arg, fptype_orig) - # Enforce IEEE-754 behavior. This could be enhanced with - # 'llvm.experimental.constrained.nearbyint' - if size_arg == 32: - func = self.mod.get_global("llvm.nearbyint.f32") - elif size_arg == 64: - func = self.mod.get_global("llvm.nearbyint.f64") - else: - raise RuntimeError("Unsupported size") - rounded = builder.call(func, [arg]) - ret = builder.fptoui(rounded, llvm_ir.IntType(expr.size)) - self.update_cache(expr, ret) - return ret - - if op.startswith("fpconvert_fp"): - assert len(expr.args) == 1 - size_arg = expr.args[0].size - fptype = LLVMType.fptype(expr.size) - fptype_orig = LLVMType.fptype(size_arg) - arg = self.add_ir(expr.args[0]) - arg = builder.bitcast(arg, fptype_orig) - if expr.size > size_arg: - fc = builder.fpext - elif expr.size < size_arg: - fc = builder.fptrunc - else: - raise RuntimeError("Not supported, same size") - ret = fc(arg, fptype) - ret = builder.bitcast(ret, llvm_ir.IntType(expr.size)) - self.update_cache(expr, ret) - return ret - - if op.startswith("fpround_"): - assert len(expr.args) == 1 - fptype = LLVMType.fptype(expr.size) - arg = self.add_ir(expr.args[0]) - arg = builder.bitcast(arg, fptype) - if op == "fpround_towardszero" and expr.size == 32: - fc = self.mod.get_global("llvm.trunc.f32") - else: - raise RuntimeError("Not supported, same size") - rounded = builder.call(fc, [arg]) - ret = builder.bitcast(rounded, llvm_ir.IntType(expr.size)) - self.update_cache(expr, ret) - return ret - - if op in ["fcom_c0", "fcom_c1", "fcom_c2", "fcom_c3"]: - arg1 = self.add_ir(expr.args[0]) - arg2 = self.add_ir(expr.args[0]) - fc_name = "fpu_%s" % op - fc_ptr = self.mod.get_global(fc_name) - casted_args = [ - builder.bitcast(arg1, llvm_ir.DoubleType()), - builder.bitcast(arg2, llvm_ir.DoubleType()), - ] - ret = builder.call(fc_ptr, casted_args) - - # Cast ret if needed - ret_size = fc_ptr.return_value.type.width - if ret_size > expr.size: - ret = builder.trunc(ret, LLVMType.IntType(expr.size)) - self.update_cache(expr, ret) - return ret - - if op in ["fsqrt", "fabs"]: - arg = self.add_ir(expr.args[0]) - if op == "fsqrt": - op = "sqrt" - - # Apply the correct func - if expr.size == 32: - arg = builder.bitcast(arg, llvm_ir.FloatType()) - ret = builder.call( - self.mod.get_global("llvm.%s.f32" % op), - [arg] - ) - elif expr.size == 64: - arg = builder.bitcast(arg, llvm_ir.DoubleType()) - ret = builder.call( - self.mod.get_global("llvm.%s.f64" % op), - [arg] - ) - else: - raise RuntimeError("Unsupported precision: %x", expr.size) - - ret = builder.bitcast(ret, llvm_ir.IntType(expr.size)) - self.update_cache(expr, ret) - return ret - - if op in ["fadd", "fmul", "fsub", "fdiv"]: - # More than 2 args not yet supported - assert len(expr.args) == 2 - arg1 = self.add_ir(expr.args[0]) - arg2 = self.add_ir(expr.args[1]) - precision = LLVMType.fptype(expr.size) - arg1 = builder.bitcast(arg1, precision) - arg2 = builder.bitcast(arg2, precision) - if op == "fadd": - ret = builder.fadd(arg1, arg2) - elif op == "fmul": - ret = builder.fmul(arg1, arg2) - elif op == "fsub": - ret = builder.fsub(arg1, arg2) - elif op == "fdiv": - ret = builder.fdiv(arg1, arg2) - ret = builder.bitcast(ret, llvm_ir.IntType(expr.size)) - self.update_cache(expr, ret) - return ret - - if op in [ - TOK_EQUAL, - TOK_INF_SIGNED, - TOK_INF_EQUAL_SIGNED, - TOK_INF_UNSIGNED, - TOK_INF_EQUAL_UNSIGNED, - ]: - if op == TOK_EQUAL: - opname = "==" - callback = builder.icmp_unsigned - elif op == TOK_INF_SIGNED: - opname = "<" - callback = builder.icmp_signed - elif op == TOK_INF_UNSIGNED: - opname = "<" - callback = builder.icmp_unsigned - elif op == TOK_INF_EQUAL_SIGNED: - opname = "<=" - callback = builder.icmp_signed - elif op == TOK_INF_EQUAL_UNSIGNED: - opname = "<" - callback = builder.icmp_unsigned - - left = self.add_ir(expr.args[0]) - right = self.add_ir(expr.args[1]) - - ret = callback(opname, left, right) - self.update_cache(expr, ret) - - return ret - - if len(expr.args) > 1: - - if op == "*": - callback = builder.mul - elif op == "+": - callback = builder.add - elif op == "&": - callback = builder.and_ - elif op == "^": - callback = builder.xor - elif op == "|": - callback = builder.or_ - elif op == "%": - callback = builder.urem - elif op == "/": - callback = builder.udiv - else: - raise NotImplementedError('Unknown op: %s' % op) - - last = self.add_ir(expr.args[0]) - - for i in range(1, len(expr.args)): - last = callback(last, - self.add_ir(expr.args[i])) - - self.update_cache(expr, last) - - return last - - raise NotImplementedError() - - if isinstance(expr, ExprMem): - - addr = self.add_ir(expr.ptr) - ret = self.llvm_context.memory_lookup(self, addr, expr.size) - self.update_cache(expr, ret) - return ret - - if isinstance(expr, ExprCond): - # Compute cond - cond = self.add_ir(expr.cond) - zero_casted = LLVMType.IntType(expr.cond.size)(0) - condition_bool = builder.icmp_unsigned("!=", cond, - zero_casted) - then_value = self.add_ir(expr.src1) - else_value = self.add_ir(expr.src2) - ret = builder.select(condition_bool, then_value, else_value) - - self.update_cache(expr, ret) - return ret - - if isinstance(expr, ExprSlice): - - src = self.add_ir(expr.arg) - - # Remove trailing bits - if expr.start != 0: - to_shr = llvm_ir.Constant( - LLVMType.IntType(expr.arg.size), - expr.start - ) - shred = builder.lshr(src, to_shr) - else: - shred = src - - # Remove leading bits - to_and = llvm_ir.Constant( - LLVMType.IntType(expr.arg.size), - (1 << (expr.stop - expr.start)) - 1 - ) - anded = builder.and_(shred, - to_and) - - # Cast into e.size - ret = builder.trunc( - anded, - LLVMType.IntType(expr.size) - ) - - self.update_cache(expr, ret) - return ret - - if isinstance(expr, ExprCompose): - - args = [] - - # Build each part - for start, src in expr.iter_args(): - # src & size - src = self.add_ir(src) - src_casted = builder.zext( - src, - LLVMType.IntType(expr.size) - ) - to_and = llvm_ir.Constant( - LLVMType.IntType(expr.size), - (1 << src.type.width) - 1 - ) - anded = builder.and_(src_casted, - to_and) - - if (start != 0): - # result << start - to_shl = llvm_ir.Constant( - LLVMType.IntType(expr.size), - start - ) - shled = builder.shl(anded, to_shl) - final = shled - else: - # Optimisation - final = anded - - args.append(final) - - # result = part1 | part2 | ... - last = args[0] - for i in range(1, len(expr.args)): - last = builder.or_(last, args[i]) - - self.update_cache(expr, last) - return last - - raise Exception("UnkownExpression", expr.__class__.__name__) - - # JiT specifics - - def check_memory_exception(self, offset, restricted_exception=False): - """Add a check for memory errors. - @offset: offset of the current exception (int or Instruction) - If restricted_exception, check only for exception which do not - require a pc update, and do not consider automod exception""" - - # VmMngr "get_exception_flag" return's size - size = 64 - t_size = LLVMType.IntType(size) - - # Get exception flag value - # TODO: avoid costly call using a structure deref - builder = self.builder - fc_ptr = self.mod.get_global("get_exception_flag") - exceptionflag = builder.call(fc_ptr, [self.local_vars["vmmngr"]]) - - if restricted_exception is True: - flag = ~m2_csts.EXCEPT_CODE_AUTOMOD & m2_csts.EXCEPT_DO_NOT_UPDATE_PC - m2_flag = llvm_ir.Constant(t_size, flag) - exceptionflag = builder.and_(exceptionflag, m2_flag) - - # Compute cond - zero_casted = llvm_ir.Constant(t_size, 0) - condition_bool = builder.icmp_unsigned( - "!=", - exceptionflag, - zero_casted - ) - - # Create bbls - branch_id = self.new_branch_name() - then_block = self.append_basic_block('then%s' % branch_id) - merge_block = self.append_basic_block('ifcond%s' % branch_id) - - builder.cbranch(condition_bool, then_block, merge_block) - - # Deactivate object caching - current_main_stream = self.main_stream - self.main_stream = False - - # Then Block - builder.position_at_end(then_block) - PC = self.llvm_context.PC - if isinstance(offset, int_types): - offset = self.add_ir(ExprInt(offset, PC.size)) - self.assign(offset, PC) - self.assign(self.add_ir(ExprInt(1, 8)), ExprId("status", 32)) - self.set_ret(offset) - - builder.position_at_end(merge_block) - # Reactivate object caching - self.main_stream = current_main_stream - - def check_cpu_exception(self, offset, restricted_exception=False): - """Add a check for CPU errors. - @offset: offset of the current exception (int or Instruction) - If restricted_exception, check only for exception which do not - require a pc update""" - - # Get exception flag value - builder = self.builder - m2_exception_flag = self.llvm_context.lifter.arch.regs.exception_flags - t_size = LLVMType.IntType(m2_exception_flag.size) - exceptionflag = self.add_ir(m2_exception_flag) - - # Compute cond - if restricted_exception is True: - flag = m2_csts.EXCEPT_NUM_UPDT_EIP - condition_bool = builder.icmp_unsigned( - ">", - exceptionflag, - llvm_ir.Constant(t_size, flag) - ) - else: - zero_casted = llvm_ir.Constant(t_size, 0) - condition_bool = builder.icmp_unsigned( - "!=", - exceptionflag, - zero_casted - ) - - # Create bbls - branch_id = self.new_branch_name() - then_block = self.append_basic_block('then%s' % branch_id) - merge_block = self.append_basic_block('ifcond%s' % branch_id) - - builder.cbranch(condition_bool, then_block, merge_block) - - # Deactivate object caching - current_main_stream = self.main_stream - self.main_stream = False - - # Then Block - builder.position_at_end(then_block) - PC = self.llvm_context.PC - if isinstance(offset, int_types): - offset = self.add_ir(ExprInt(offset, PC.size)) - self.assign(offset, PC) - self.assign(self.add_ir(ExprInt(1, 8)), ExprId("status", 32)) - self.set_ret(offset) - - builder.position_at_end(merge_block) - # Reactivate object caching - self.main_stream = current_main_stream - - def gen_pre_code(self, instr_attrib): - if instr_attrib.log_mn: - loc_db = self.llvm_context.lifter.loc_db - self.printf( - "%.8X %s\n" % ( - instr_attrib.instr.offset, - instr_attrib.instr.to_string(loc_db) - ) - ) - - def gen_post_code(self, attributes, pc_value): - if attributes.log_regs: - # Update PC for dump_gpregs - PC = self.llvm_context.PC - t_size = LLVMType.IntType(PC.size) - dst = self.builder.zext(t_size(pc_value), t_size) - self.assign(dst, PC) - - fc_ptr = self.mod.get_global(self.llvm_context.logging_func) - self.builder.call(fc_ptr, [self.local_vars["vmcpu"]]) - - def gen_post_instr_checks(self, attrib, next_instr): - if attrib.mem_read | attrib.mem_write: - fc_ptr = self.mod.get_global("check_memory_breakpoint") - self.builder.call(fc_ptr, [self.local_vars["vmmngr"]]) - fc_ptr = self.mod.get_global("check_invalid_code_blocs") - 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"]]) - - def expr2cases(self, expr): - """ - Evaluate @expr and return: - - switch value -> dst - - evaluation of the switch value (if any) - """ - - to_eval = expr - dst2case = {} - case2dst = {} - for i, solution in enumerate(possible_values(expr)): - value = solution.value - index = dst2case.get(value, i) - to_eval = to_eval.replace_expr({value: ExprInt(index, value.size)}) - dst2case[value] = index - if value.is_int() or value.is_loc(): - case2dst[i] = value - else: - case2dst[i] = self.add_ir(value) - - - evaluated = self.add_ir(to_eval) - return case2dst, evaluated - - def gen_jump2dst(self, attrib, instr_offsets, dst): - """Generate the code for a jump to @dst with final check for error - - Several cases have to be considered: - - jump to an offset out of the current ASM BBL (JMP 0x11223344) - - jump to an offset inside the current ASM BBL (Go to next instruction) - - jump to an offset back in the current ASM BBL (For max_exec jit - option on self loops) - - jump to a generated IR label, which must be jitted in this same - function (REP MOVSB) - - jump to a computed offset (CALL @32[0x11223344]) - - """ - PC = self.llvm_context.PC - # We are no longer in the main stream, deactivate cache - self.main_stream = False - - offset = None - if isinstance(dst, ExprInt): - offset = int(dst) - loc_key = self.llvm_context.lifter.loc_db.get_or_create_offset_location(offset) - dst = ExprLoc(loc_key, dst.size) - - if isinstance(dst, ExprLoc): - loc_key = dst.loc_key - bbl = self.get_basic_block_by_loc_key(loc_key) - offset = self.llvm_context.lifter.loc_db.get_location_offset(loc_key) - if bbl is not None: - # "local" jump, inside this function - if offset is None: - # Avoid checks on generated label - self.builder.branch(bbl) - return - - if (offset in instr_offsets and - offset > attrib.instr.offset): - # forward local jump (ie. next instruction) - self.gen_post_code(attrib, offset) - self.gen_post_instr_checks(attrib, offset) - self.builder.branch(bbl) - return - - # reaching this point means a backward local jump, promote it to - # extern - - # "extern" jump on a defined offset, return to the caller - 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)) - # Cast @dst, if needed - # for instance, x86_32: IRDst is 32 bits, so is @dst; PC is 64 bits - if dst.type.width != PC.size: - dst = self.builder.zext(dst, LLVMType.IntType(PC.size)) - - self.gen_post_code(attrib, offset) - self.assign(dst, PC) - self.gen_post_instr_checks(attrib, dst) - self.assign(self.add_ir(ExprInt(0, 8)), ExprId("status", 32)) - self.set_ret(dst) - - - def gen_irblock(self, instr_attrib, attributes, instr_offsets, irblock): - """ - Generate the code for an @irblock - @instr_attrib: an Attributes instance or the instruction to translate - @attributes: list of Attributes corresponding to irblock assignments - @instr_offsets: offset of all asmblock's instructions - @irblock: an irblock instance - """ - - case2dst = None - case_value = None - instr = instr_attrib.instr - - for index, assignblk in enumerate(irblock): - # Enable cache - self.main_stream = True - self.expr_cache = {} - - # Prefetch memory - for element in assignblk.get_r(mem_read=True): - if isinstance(element, ExprMem): - self.add_ir(element) - - # Evaluate expressions - values = {} - for dst, src in viewitems(assignblk): - if dst == self.llvm_context.lifter.IRDst: - case2dst, case_value = self.expr2cases(src) - else: - values[dst] = self.add_ir(src) - - # Check memory access exception - if attributes[index].mem_read: - self.check_memory_exception( - instr.offset, - restricted_exception=True - ) - - # Update the memory - for dst, src in viewitems(values): - if isinstance(dst, ExprMem): - self.assign(src, dst) - - # Check memory write exception - if attributes[index].mem_write: - self.check_memory_exception( - instr.offset, - restricted_exception=True - ) - - # Update registers values - for dst, src in viewitems(values): - if not isinstance(dst, ExprMem): - self.assign(src, dst) - - # Check post assignblk exception flags - if attributes[index].set_exception: - self.check_cpu_exception( - instr.offset, - restricted_exception=True - ) - - # Destination - assert case2dst is not None - if len(case2dst) == 1: - # Avoid switch in this common case - self.gen_jump2dst( - instr_attrib, - instr_offsets, - next(iter(viewvalues(case2dst))) - ) - else: - current_bbl = self.builder.basic_block - - # Gen the out cases - branch_id = self.new_branch_name() - case2bbl = {} - for case, dst in list(viewitems(case2dst)): - name = "switch_%s_%d" % (branch_id, case) - bbl = self.append_basic_block(name) - case2bbl[case] = bbl - self.builder.position_at_start(bbl) - self.gen_jump2dst(instr_attrib, instr_offsets, dst) - - # Jump on the correct output - self.builder.position_at_end(current_bbl) - switch = self.builder.switch(case_value, case2bbl[0]) - for i, bbl in viewitems(case2bbl): - if i == 0: - # Default case is case 0, arbitrary - continue - switch.add_case(i, bbl) - - def gen_bad_block(self, asmblock): - """ - Translate an asm_bad_block into a CPU exception - """ - builder = self.builder - m2_exception_flag = self.llvm_context.lifter.arch.regs.exception_flags - t_size = LLVMType.IntType(m2_exception_flag.size) - self.assign( - self.add_ir(ExprInt(1, 8)), - ExprId("status", 32) - ) - self.assign( - t_size(m2_csts.EXCEPT_UNK_MNEMO), - m2_exception_flag - ) - offset = self.llvm_context.lifter.loc_db.get_location_offset( - asmblock.loc_key - ) - self.set_ret(LLVMType.IntType(64)(offset)) - - def gen_finalize(self, asmblock, codegen): - """ - In case of delayslot, generate a dummy BBL which return on the computed - IRDst or on next_label - """ - if self.llvm_context.has_delayslot: - next_label = codegen.get_block_post_label(asmblock) - builder = self.builder - - builder.position_at_end(self.get_basic_block_by_loc_key(next_label)) - - # Common code - self.assign(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) - condition_bool = builder.icmp_unsigned( - "!=", - self.add_ir(codegen.delay_slot_set), - zero_casted - ) - - # Create bbls - branch_id = self.new_branch_name() - then_block = self.append_basic_block('then%s' % branch_id) - else_block = self.append_basic_block('else%s' % branch_id) - - builder.cbranch(condition_bool, then_block, else_block) - - # Deactivate object caching - self.main_stream = False - - # Then Block - builder.position_at_end(then_block) - PC = self.llvm_context.PC - to_ret = self.add_ir(codegen.delay_slot_dst) - self.assign(to_ret, PC) - self.assign(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 - next_label_offset = self.llvm_context.lifter.loc_db.get_location_offset(next_label) - to_ret = LLVMType.IntType(PC.size)(next_label_offset) - self.assign(to_ret, PC) - self.set_ret(to_ret) - - def from_asmblock(self, asmblock): - """Build the function from an asmblock (asm_block instance). - Prototype : f(i8* jitcpu, i8* vmcpu, i8* vmmngr, i8* status)""" - - # Build function signature - self.my_args.append((ExprId("jitcpu", 32), - llvm_ir.PointerType(LLVMType.IntType(8)), - "jitcpu")) - self.my_args.append((ExprId("vmcpu", 32), - llvm_ir.PointerType(LLVMType.IntType(8)), - "vmcpu")) - self.my_args.append((ExprId("vmmngr", 32), - llvm_ir.PointerType(LLVMType.IntType(8)), - "vmmngr")) - self.my_args.append((ExprId("status", 32), - llvm_ir.PointerType(LLVMType.IntType(8)), - "status")) - ret_size = 64 - - self.ret_type = LLVMType.IntType(ret_size) - - # Initialise the function - self.init_fc() - self.local_vars_pointers["status"] = self.local_vars["status"] - - if isinstance(asmblock, m2_asmblock.AsmBlockBad): - self.gen_bad_block(asmblock) - return - - # Create basic blocks (for label branches) - entry_bbl, builder = self.entry_bbl, self.builder - for instr in asmblock.lines: - lbl = self.llvm_context.lifter.loc_db.get_or_create_offset_location(instr.offset) - self.append_basic_block(lbl) - - # TODO: merge duplicate code with CGen - codegen = self.llvm_context.cgen_class(self.llvm_context.lifter) - irblocks_list = codegen.block2assignblks(asmblock) - instr_offsets = [line.offset for line in asmblock.lines] - - # Prepare for delayslot - if self.llvm_context.has_delayslot: - for element in (codegen.delay_slot_dst, codegen.delay_slot_set): - eltype = LLVMType.IntType(element.size) - ptr = self.CreateEntryBlockAlloca( - eltype, - default_value=eltype(0) - ) - self.local_vars_pointers[element.name] = ptr - loc_key = codegen.get_block_post_label(asmblock) - offset = self.llvm_context.lifter.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) - - - for instr, irblocks in zip(asmblock.lines, irblocks_list): - instr_attrib, irblocks_attributes = codegen.get_attributes( - instr, - irblocks, - self.log_mn, - self.log_regs - ) - - # Pre-create basic blocks - for irblock in irblocks: - self.append_basic_block(irblock.loc_key, overwrite=False) - - # Generate the corresponding code - for index, irblock in enumerate(irblocks): - new_irblock = self.llvm_context.lifter.irbloc_fix_regs_for_mode( - irblock, self.llvm_context.lifter.attrib) - - # Set the builder at the beginning of the correct bbl - 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) - self.gen_irblock(instr_attrib, irblocks_attributes[index], instr_offsets, new_irblock) - - # Gen finalize (see codegen::CGen) is unrecheable, except with delayslot - self.gen_finalize(asmblock, codegen) - - # Branch entry_bbl on first label - builder.position_at_end(entry_bbl) - first_label_bbl = self.get_basic_block_by_loc_key(asmblock.loc_key) - builder.branch(first_label_bbl) - - - # LLVMFunction manipulation - - def __str__(self): - "Print the llvm IR corresponding to the current module" - return str(self.mod) - - def dot(self): - "Return the CFG of the current function" - return llvm.get_function_cfg(self.fc) - - def as_llvm_mod(self): - """Return a ModuleRef standing for the current function""" - if self._llvm_mod is None: - self._llvm_mod = llvm.parse_assembly(str(self.mod)) - return self._llvm_mod - - def verify(self): - "Verify the module syntax" - return self.as_llvm_mod().verify() - - def get_bytecode(self): - "Return LLVM bitcode corresponding to the current module" - return self.as_llvm_mod().as_bitcode() - - def get_assembly(self): - "Return native assembly corresponding to the current module" - return self.llvm_context.target_machine.emit_assembly(self.as_llvm_mod()) - - def optimise(self): - "Optimise the function in place" - return self.llvm_context.pass_manager.run(self.as_llvm_mod()) - - def __call__(self, *args): - "Eval the function with arguments args" - - e = self.llvm_context.get_execengine() - - genargs = [LLVMType.generic(a) for a in args] - ret = e.run_function(self.fc, genargs) - - return ret.as_int() - - def get_function_pointer(self): - "Return a pointer on the Jitted function" - engine = self.llvm_context.get_execengine() - - # Add the module and make sure it is ready for execution - engine.add_module(self.as_llvm_mod()) - engine.finalize_object() - - return engine.get_function_address(self.fc.name) - - -class LLVMFunction_IRCompilation(LLVMFunction): - """LLVMFunction made for IR export, in conjunction with - LLVMContext_IRCompilation. - - This class offers only the basics, and decision must be made by the class - user on how actual registers, ABI, etc. are reflected - - - Example of use: - >>> context = LLVMContext_IRCompilation() - >>> context.lifter = lifter - >>> - >>> func = LLVMFunction_IRCompilation(context, name="test") - >>> func.ret_type = llvm_ir.VoidType() - >>> func.init_fc() - >>> - >>> # Insert here function additional inits - >>> XX = func.builder.alloca(...) - >>> func.local_vars_pointers["EAX"] = XX - >>> # - >>> - >>> func.from_ircfg(ircfg) - """ - - def init_fc(self): - super(LLVMFunction_IRCompilation, self).init_fc() - - # Create a global IRDst if not any - IRDst = self.llvm_context.lifter.IRDst - if str(IRDst) not in self.mod.globals: - llvm_ir.GlobalVariable(self.mod, LLVMType.IntType(IRDst.size), - name=str(IRDst)) - - # Create an 'exit' basic block, the final leave - self.exit_bbl = self.append_basic_block("exit") - - def gen_jump2dst(self, _attrib, _instr_offsets, dst): - self.main_stream = False - - if isinstance(dst, Expr): - if dst.is_int(): - loc = self.llvm_context.lifter.loc_db.getby_offset_create(int(dst)) - dst = ExprLoc(loc, dst.size) - assert dst.is_loc() - bbl = self.get_basic_block_by_loc_key(dst.loc_key) - if bbl is not None: - # "local" jump, inside this function - self.builder.branch(bbl) - return - - # extern jump - dst = self.add_ir(dst) - - # Emulate indirect jump with: - # @IRDst = dst - # goto exit - self.builder.store(dst, self.mod.get_global("IRDst")) - self.builder.branch(self.exit_bbl) - - def gen_irblock(self, irblock): - instr_attrib = Attributes() - attributes = [Attributes() for _ in range(len(irblock.assignblks))] - instr_offsets = None - return super(LLVMFunction_IRCompilation, self).gen_irblock( - instr_attrib, attributes, instr_offsets, irblock - ) - - def from_ircfg(self, ircfg, append_ret=True): - # Create basic blocks - for loc_key, irblock in viewitems(ircfg.blocks): - self.append_basic_block(loc_key) - - # Add IRBlocks - for label, irblock in viewitems(ircfg.blocks): - self.builder.position_at_end(self.get_basic_block_by_loc_key(label)) - self.gen_irblock(irblock) - - # Branch the entry BBL on the IRCFG head - self.builder.position_at_end(self.entry_bbl) - heads = ircfg.heads() - assert len(heads) == 1 - starting_label = list(heads).pop() - self.builder.branch(self.get_basic_block_by_loc_key(starting_label)) - - # Returns with the builder on the exit block - self.builder.position_at_end(self.exit_bbl) - - if append_ret: - self.builder.ret_void() diff --git a/miasm/jitter/loader/__init__.py b/miasm/jitter/loader/__init__.py deleted file mode 100644 index e69de29b..00000000 --- a/miasm/jitter/loader/__init__.py +++ /dev/null diff --git a/miasm/jitter/loader/elf.py b/miasm/jitter/loader/elf.py deleted file mode 100644 index 91d1c18b..00000000 --- a/miasm/jitter/loader/elf.py +++ /dev/null @@ -1,339 +0,0 @@ -import struct -from collections import defaultdict - -from future.utils import viewitems - -from miasm.loader import cstruct -from miasm.loader import * -import miasm.loader.elf as elf_csts - -from miasm.jitter.csts import * -from miasm.jitter.loader.utils import canon_libname_libfunc, libimp -from miasm.core.utils import force_str -from miasm.core.interval import interval - -import logging - -log = logging.getLogger('loader_elf') -hnd = logging.StreamHandler() -hnd.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s")) -log.addHandler(hnd) -log.setLevel(logging.CRITICAL) - - -def get_import_address_elf(e): - import2addr = defaultdict(set) - for sh in e.sh: - if not hasattr(sh, 'rel'): - continue - for k, v in viewitems(sh.rel): - k = force_str(k) - import2addr[('xxx', k)].add(v.offset) - return import2addr - - -def preload_elf(vm, e, runtime_lib, patch_vm_imp=True, loc_db=None): - # XXX quick hack - fa = get_import_address_elf(e) - dyn_funcs = {} - for (libname, libfunc), ads in viewitems(fa): - # Quick hack - if a symbol is already known, do not stub it - if loc_db and loc_db.get_name_location(libfunc) is not None: - continue - for ad in ads: - ad_base_lib = runtime_lib.lib_get_add_base(libname) - ad_libfunc = runtime_lib.lib_get_add_func(ad_base_lib, libfunc, ad) - - libname_s = canon_libname_libfunc(libname, libfunc) - dyn_funcs[libname_s] = ad_libfunc - if patch_vm_imp: - log.debug('patch 0x%x 0x%x %s', ad, ad_libfunc, libfunc) - set_endianness = { elf_csts.ELFDATA2MSB: ">", - elf_csts.ELFDATA2LSB: "<", - elf_csts.ELFDATANONE: "" }[e.sex] - vm.set_mem(ad, - struct.pack(set_endianness + - cstruct.size2type[e.size], - ad_libfunc)) - return runtime_lib, dyn_funcs - -def fill_loc_db_with_symbols(elf, loc_db, base_addr=0): - """Parse the miasm.loader's ELF @elf to extract symbols, and fill the LocationDB - instance @loc_db with parsed symbols. - - The ELF is considered mapped at @base_addr - @elf: miasm.loader's ELF instance - @loc_db: LocationDB used to retrieve symbols'offset - @base_addr: addr to reloc to (if any) - """ - # Get symbol sections - symbol_sections = [] - for section_header in elf.sh: - if hasattr(section_header, 'symbols'): - for name, sym in viewitems(section_header.symbols): - if not name or sym.value == 0: - continue - name = loc_db.find_free_name(force_str(name)) - loc_db.add_location(name, sym.value, strict=False) - - if hasattr(section_header, 'reltab'): - for rel in section_header.reltab: - if not rel.sym or rel.offset == 0: - continue - name = loc_db.find_free_name(force_str(rel.sym)) - loc_db.add_location(name, rel.offset, strict=False) - - if hasattr(section_header, 'symtab'): - log.debug("Find %d symbols in %r", len(section_header.symtab), - section_header) - symbol_sections.append(section_header) - elif isinstance(section_header, ( - elf_init.GNUVerDef, elf_init.GNUVerSym, elf_init.GNUVerNeed - )): - log.debug("Find GNU version related section, unsupported for now") - - for section in symbol_sections: - for symbol_entry in section.symtab: - # Here, the computation of vaddr assumes 'elf' is an executable or a - # shared object file - - # For relocatable file, symbol_entry.value is an offset from the section - # base -> not handled here - st_bind = symbol_entry.info >> 4 - st_type = symbol_entry.info & 0xF - - if st_type not in [ - elf_csts.STT_NOTYPE, - elf_csts.STT_OBJECT, - elf_csts.STT_FUNC, - elf_csts.STT_COMMON, - elf_csts.STT_GNU_IFUNC, - ]: - # Ignore symbols useless in linking - continue - - if st_bind == elf_csts.STB_GLOBAL: - # Global symbol - weak = False - elif st_bind == elf_csts.STB_WEAK: - # Weak symbol - weak = True - else: - # Ignore local & others symbols - continue - - absolute = False - if symbol_entry.shndx == 0: - # SHN_UNDEF - continue - elif symbol_entry.shndx == 0xfff1: - # SHN_ABS - absolute = True - log.debug("Absolute symbol %r - %x", symbol_entry.name, - symbol_entry.value) - elif 0xff00 <= symbol_entry.shndx <= 0xffff: - # Reserved index (between SHN_LORESERV and SHN_HIRESERVE) - raise RuntimeError("Unsupported reserved index: %r" % symbol_entry) - - name = force_str(symbol_entry.name) - if name == "": - # Ignore empty symbol - log.debug("Empty symbol %r", symbol_entry) - continue - - if absolute: - vaddr = symbol_entry.value - else: - vaddr = symbol_entry.value + base_addr - - # 'weak' information is only used to force global symbols for now - already_existing_loc = loc_db.get_name_location(name) - if already_existing_loc is not None: - if weak: - # Weak symbol, this is ok to already exists, skip it - continue - else: - # Global symbol, force it - loc_db.remove_location_name(already_existing_loc, - name) - already_existing_off = loc_db.get_offset_location(vaddr) - if already_existing_off is not None: - loc_db.add_location_name(already_existing_off, name) - else: - loc_db.add_location(name=name, offset=vaddr) - - -def apply_reloc_x86(elf, vm, section, base_addr, loc_db): - """Apply relocation for x86 ELF contained in the section @section - @elf: miasm.loader's ELF instance - @vm: VmMngr instance - @section: elf's section containing relocation to perform - @base_addr: addr to reloc to - @loc_db: LocationDB used to retrieve symbols'offset - """ - if elf.size == 64: - addr_writer = lambda vaddr, addr: vm.set_mem(vaddr, - struct.pack("<Q", addr)) - elif elf.size == 32: - addr_writer = lambda vaddr, addr: vm.set_mem(vaddr, - struct.pack("<I", addr)) - else: - raise ValueError("Unsupported elf size %d" % elf.size) - - symb_section = section.linksection - for reloc in section.reltab: - - # Parse relocation info - r_info = reloc.info - if elf.size == 64: - r_info_sym = (r_info >> 32) & 0xFFFFFFFF - r_info_type = r_info & 0xFFFFFFFF - elif elf.size == 32: - r_info_sym = (r_info >> 8) & 0xFFFFFF - r_info_type = r_info & 0xFF - - is_ifunc = False - symbol_entry = None - if r_info_sym > 0: - symbol_entry = symb_section.symtab[r_info_sym] - - r_offset = reloc.offset - r_addend = reloc.cstr.sym - - if (elf.size, reloc.type) in [ - (64, elf_csts.R_X86_64_RELATIVE), - (64, elf_csts.R_X86_64_IRELATIVE), - (32, elf_csts.R_386_RELATIVE), - (32, elf_csts.R_386_IRELATIVE), - ]: - # B + A - addr = base_addr + r_addend - where = base_addr + r_offset - elif reloc.type == elf_csts.R_X86_64_64: - # S + A - addr_symb = loc_db.get_name_offset(symbol_entry.name) - if addr_symb is None: - log.warning("Unable to find symbol %r" % symbol_entry.name) - continue - addr = addr_symb + r_addend - where = base_addr + r_offset - elif (elf.size, reloc.type) in [ - (64, elf_csts.R_X86_64_TPOFF64), - (64, elf_csts.R_X86_64_DTPMOD64), - (32, elf_csts.R_386_TLS_TPOFF), - ]: - # Thread dependent, ignore for now - log.debug("Skip relocation TPOFF64 %r", reloc) - continue - elif (elf.size, reloc.type) in [ - (64, elf_csts.R_X86_64_GLOB_DAT), - (64, elf_csts.R_X86_64_JUMP_SLOT), - (32, elf_csts.R_386_JMP_SLOT), - (32, elf_csts.R_386_GLOB_DAT), - ]: - # S - addr = loc_db.get_name_offset(symbol_entry.name) - if addr is None: - log.warning("Unable to find symbol %r" % symbol_entry.name) - continue - is_ifunc = symbol_entry.info & 0xF == elf_csts.STT_GNU_IFUNC - where = base_addr + r_offset - else: - raise ValueError( - "Unknown relocation type: %d (%r)" % (reloc.type, - reloc) - ) - if is_ifunc: - # Resolve at runtime - not implemented for now - log.warning("Relocation for %r (at %x, currently pointing on %x) " - "has to be resolved at runtime", - name, where, sym_addr) - continue - - log.debug("Write %x at %x", addr, where) - addr_writer(where, addr) - - -def vm_load_elf(vm, fdata, name="", base_addr=0, loc_db=None, apply_reloc=False, - **kargs): - """ - Very dirty elf loader - TODO XXX: implement real loader - """ - elf = elf_init.ELF(fdata, **kargs) - i = interval() - all_data = {} - - for p in elf.ph.phlist: - if p.ph.type != elf_csts.PT_LOAD: - continue - log.debug( - '0x%x 0x%x 0x%x 0x%x 0x%x', p.ph.vaddr, p.ph.memsz, p.ph.offset, - p.ph.filesz, p.ph.type) - data_o = elf._content[p.ph.offset:p.ph.offset + p.ph.filesz] - addr_o = p.ph.vaddr + base_addr - a_addr = addr_o & ~0xFFF - b_addr = addr_o + max(p.ph.memsz, p.ph.filesz) - b_addr = (b_addr + 0xFFF) & ~0xFFF - all_data[addr_o] = data_o - # -2: Trick to avoid merging 2 consecutive pages - i += [(a_addr, b_addr - 2)] - for a, b in i.intervals: - vm.add_memory_page( - a, - PAGE_READ | PAGE_WRITE, - b"\x00" * (b + 2 - a), - repr(name) - ) - - for r_vaddr, data in viewitems(all_data): - vm.set_mem(r_vaddr, data) - - if loc_db is not None: - fill_loc_db_with_symbols(elf, loc_db, base_addr) - - if apply_reloc: - arch = guess_arch(elf) - sections = [] - for section in elf.sh: - if not hasattr(section, 'reltab'): - continue - if isinstance(section, elf_init.RelATable): - pass - elif isinstance(section, elf_init.RelTable): - if arch == "x86_64": - log.warning("REL section should not happen in x86_64") - else: - raise RuntimeError("Unknown relocation section type: %r" % section) - sections.append(section) - for section in sections: - if arch in ["x86_64", "x86_32"]: - apply_reloc_x86(elf, vm, section, base_addr, loc_db) - else: - log.debug("Unsupported relocation for arch %r" % arch) - - return elf - - -class libimp_elf(libimp): - pass - - -# machine, size, sex -> arch_name -ELF_machine = {(elf_csts.EM_ARM, 32, elf_csts.ELFDATA2LSB): "arml", - (elf_csts.EM_ARM, 32, elf_csts.ELFDATA2MSB): "armb", - (elf_csts.EM_AARCH64, 64, elf_csts.ELFDATA2LSB): "aarch64l", - (elf_csts.EM_AARCH64, 64, elf_csts.ELFDATA2MSB): "aarch64b", - (elf_csts.EM_MIPS, 32, elf_csts.ELFDATA2MSB): "mips32b", - (elf_csts.EM_MIPS, 32, elf_csts.ELFDATA2LSB): "mips32l", - (elf_csts.EM_386, 32, elf_csts.ELFDATA2LSB): "x86_32", - (elf_csts.EM_X86_64, 64, elf_csts.ELFDATA2LSB): "x86_64", - (elf_csts.EM_SH, 32, elf_csts.ELFDATA2LSB): "sh4", - (elf_csts.EM_PPC, 32, elf_csts.ELFDATA2MSB): "ppc32b", - } - - -def guess_arch(elf): - """Return the architecture specified by the ELF container @elf. - If unknown, return None""" - return ELF_machine.get((elf.Ehdr.machine, elf.size, elf.sex), None) diff --git a/miasm/jitter/loader/pe.py b/miasm/jitter/loader/pe.py deleted file mode 100644 index 9af068e4..00000000 --- a/miasm/jitter/loader/pe.py +++ /dev/null @@ -1,834 +0,0 @@ -from builtins import map -import os -import struct -import logging -from collections import defaultdict - -from future.utils import viewitems, viewvalues - -from miasm.loader import pe -from miasm.loader import cstruct -from miasm.loader import * - -from miasm.jitter.csts import * -from miasm.jitter.loader.utils import canon_libname_libfunc, libimp -from miasm.core.utils import force_str - -log = logging.getLogger('loader_pe') -hnd = logging.StreamHandler() -hnd.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s")) -log.addHandler(hnd) -log.setLevel(logging.INFO) - - -def get_pe_dependencies(pe_obj): - """Collect the shared libraries upon which this PE depends. - - @pe_obj: pe object - Returns a set of strings of DLL names. - - Example: - - pe = miasm.analysis.binary.Container.from_string(buf) - deps = miasm.jitter.loader.pe.get_pe_dependencies(pe.executable) - assert sorted(deps)[0] == 'api-ms-win-core-appcompat-l1-1-0.dll' - """ - - if pe_obj.DirImport.impdesc is None: - return set() - out = set() - for dependency in pe_obj.DirImport.impdesc: - libname = dependency.dlldescname.name.lower() - # transform bytes to str - libname = force_str(libname) - out.add(libname) - - # If binary has redirected export, add dependencies - if pe_obj.DirExport.expdesc != None: - addrs = get_export_name_addr_list(pe_obj) - for imp_ord_or_name, ad in addrs: - # if export is a redirection, search redirected dll - # and get function real addr - ret = is_redirected_export(pe_obj, ad) - if ret is False: - continue - dllname, func_info = ret - dllname = dllname + '.dll' - out.add(dllname) - - return out - - -def get_import_address_pe(e): - """Compute the addresses of imported symbols. - @e: pe object - Returns a dict mapping from tuple (dll name string, symbol name string) to set of virtual addresses. - - Example: - - pe = miasm.analysis.binary.Container.from_string(buf) - imports = miasm.jitter.loader.pe.get_import_address_pe(pe.executable) - assert imports[('api-ms-win-core-rtlsupport-l1-1-0.dll', 'RtlCaptureStackBackTrace')] == {0x6b88a6d0} - """ - import2addr = defaultdict(set) - if e.DirImport.impdesc is None: - return import2addr - for s in e.DirImport.impdesc: - # fthunk = e.rva2virt(s.firstthunk) - # l = "%2d %-25s %s" % (i, repr(s.dlldescname), repr(s)) - libname = force_str(s.dlldescname.name.lower()) - - for ii, imp in enumerate(s.impbynames): - if isinstance(imp, pe.ImportByName): - funcname = force_str(imp.name) - else: - funcname = imp - # l = " %2d %-16s" % (ii, repr(funcname)) - import2addr[(libname, funcname)].add( - e.rva2virt(s.firstthunk + (e._wsize * ii) // 8) - ) - return import2addr - - -def preload_pe(vm, e, runtime_lib, patch_vm_imp=True): - fa = get_import_address_pe(e) - dyn_funcs = {} - # log.debug('imported funcs: %s' % fa) - for (libname, libfunc), ads in viewitems(fa): - for ad in ads: - libname = force_str(libname) - ad_base_lib = runtime_lib.lib_get_add_base(libname) - ad_libfunc = runtime_lib.lib_get_add_func(ad_base_lib, libfunc, ad) - - libname_s = canon_libname_libfunc(libname, libfunc) - dyn_funcs[libname_s] = ad_libfunc - if patch_vm_imp: - vm.set_mem( - ad, struct.pack(cstruct.size2type[e._wsize], ad_libfunc)) - return dyn_funcs - - -def is_redirected_export(pe_obj, addr): - """Test if the @addr is a forwarded export address. If so, return - dllname/function name couple. If not, return False. - - An export address is a forwarded export if the rva is in the export - directory of the pe. - - @pe_obj: PE instance - @addr: virtual address of the function to test - """ - - export_dir = pe_obj.NThdr.optentries[pe.DIRECTORY_ENTRY_EXPORT] - addr_rva = pe_obj.virt2rva(addr) - if not (export_dir.rva <= addr_rva < export_dir.rva + export_dir.size): - return False - addr_end = pe_obj.virt.find(b'\x00', addr) - data = pe_obj.virt.get(addr, addr_end) - - data = force_str(data) - dllname, func_info = data.split('.', 1) - dllname = dllname.lower() - - # Test if function is forwarded using ordinal - if func_info.startswith('#'): - func_info = int(func_info[1:]) - return dllname, func_info - - -def get_export_name_addr_list(e): - """Collect names/ordinals and addresses of symbols exported by the given PE. - @e: PE instance - Returns a list of tuples: - (symbol name string, virtual address) - (ordinal number, virtual address) - - Example: - - pe = miasm.analysis.binary.Container.from_string(buf) - exports = miasm.jitter.loader.pe.get_export_name_addr_list(pe.executable) - assert exports[0] == ('AcquireSRWLockExclusive', 0x6b89b22a) - """ - out = [] - if e.DirExport.expdesc is None: - return out - - # add func name - for i, n in enumerate(e.DirExport.f_names): - addr = e.DirExport.f_address[e.DirExport.f_nameordinals[i].ordinal] - f_name = force_str(n.name.name) - # log.debug('%s %s' % (f_name, hex(e.rva2virt(addr.rva)))) - out.append((f_name, e.rva2virt(addr.rva))) - - # add func ordinal - for i, s in enumerate(e.DirExport.f_address): - if not s.rva: - continue - out.append((i + e.DirExport.expdesc.base, e.rva2virt(s.rva))) - - return out - - -def vm_load_pe(vm, fdata, align_s=True, load_hdr=True, name="", winobjs=None, **kargs): - """Load a PE in memory (@vm) from a data buffer @fdata - @vm: VmMngr instance - @fdata: data buffer to parse - @align_s: (optional) If False, keep gaps between section - @load_hdr: (optional) If False, do not load the NThdr in memory - Return the corresponding PE instance. - - Extra arguments are passed to PE instantiation. - If all sections are aligned, they will be mapped on several different pages - Otherwise, a big page is created, containing all sections - """ - - # Parse and build a PE instance - pe = pe_init.PE(fdata, **kargs) - - # Check if all section are aligned - aligned = True - for section in pe.SHList: - if section.addr & 0xFFF: - aligned = False - break - - if aligned: - # Loader NT header - if load_hdr: - # Header length - hdr_len = max(0x200, pe.NThdr.sizeofheaders) - # Page minimum size - min_len = min(pe.SHList[0].addr, 0x1000) - - # Get and pad the pe_hdr - pe_hdr = ( - pe.content[:hdr_len] + - max(0, (min_len - hdr_len)) * b"\x00" - ) - - if winobjs: - winobjs.allocated_pages[pe.NThdr.ImageBase] = (pe.NThdr.ImageBase, len(pe_hdr)) - vm.add_memory_page( - pe.NThdr.ImageBase, - PAGE_READ | PAGE_WRITE, - pe_hdr, - "%r: PE Header" % name - ) - - # Align sections size - if align_s: - # Use the next section address to compute the new size - for i, section in enumerate(pe.SHList[:-1]): - new_size = pe.SHList[i + 1].addr - section.addr - section.size = new_size - section.rawsize = new_size - section.data = strpatchwork.StrPatchwork( - section.data[:new_size] - ) - section.offset = section.addr - - # Last section alignment - last_section = pe.SHList[-1] - last_section.size = (last_section.size + 0xfff) & 0xfffff000 - - # Pad sections with null bytes and map them - for section in pe.SHList: - data = bytes(section.data) - data += b"\x00" * (section.size - len(data)) - attrib = PAGE_READ - if section.flags & 0x80000000: - attrib |= PAGE_WRITE - - section_addr = pe.rva2virt(section.addr) - if winobjs: - winobjs.allocated_pages[section_addr] = (section_addr, len(data)) - vm.add_memory_page( - section_addr, - attrib, - data, - "%r: %r" % (name, section.name) - ) - - return pe - - # At least one section is not aligned - log.warning('PE is not aligned, creating big section') - min_addr = 0 if load_hdr else None - max_addr = None - data = "" - - for i, section in enumerate(pe.SHList): - if i < len(pe.SHList) - 1: - # If it is not the last section, use next section address - section.size = pe.SHList[i + 1].addr - section.addr - section.rawsize = section.size - section.offset = section.addr - - # Update min and max addresses - if min_addr is None or section.addr < min_addr: - min_addr = section.addr - max_section_len = max(section.size, len(section.data)) - if max_addr is None or section.addr + max_section_len > max_addr: - max_addr = section.addr + max_section_len - - min_addr = pe.rva2virt(min_addr) - max_addr = pe.rva2virt(max_addr) - log.debug('Min: 0x%x, Max: 0x%x, Size: 0x%x', min_addr, max_addr, - (max_addr - min_addr)) - - # Create only one big section containing the whole PE - vm.add_memory_page( - min_addr, - PAGE_READ | PAGE_WRITE, - (max_addr - min_addr) * b"\x00" - ) - - # Copy each sections content in memory - for section in pe.SHList: - log.debug('Map 0x%x bytes to 0x%x', len(section.data), - pe.rva2virt(section.addr)) - vm.set_mem(pe.rva2virt(section.addr), bytes(section.data)) - - return pe - - -def vm_load_pe_lib(vm, fname_in, libs, lib_path_base, **kargs): - """Call vm_load_pe on @fname_in and update @libs accordingly - @vm: VmMngr instance - @fname_in: library name - @libs: libimp_pe instance - @lib_path_base: DLLs relative path - Return the corresponding PE instance - Extra arguments are passed to vm_load_pe - """ - - log.info('Loading module %r', fname_in) - - fname = os.path.join(lib_path_base, fname_in) - with open(fname, "rb") as fstream: - pe = vm_load_pe(vm, fstream.read(), name=fname_in, **kargs) - libs.add_export_lib(pe, fname_in) - return pe - - -def vm_load_pe_libs(vm, libs_name, libs, lib_path_base, **kargs): - """Call vm_load_pe_lib on each @libs_name filename - @vm: VmMngr instance - @libs_name: list of str - @libs: libimp_pe instance - @lib_path_base: (optional) DLLs relative path - Return a dictionary Filename -> PE instances - Extra arguments are passed to vm_load_pe_lib - """ - out = {} - for fname in libs_name: - assert isinstance(fname, str) - out[fname] = vm_load_pe_lib(vm, fname, libs, lib_path_base, **kargs) - return out - - -def vm_fix_imports_pe_libs(lib_imgs, libs, lib_path_base, - patch_vm_imp=True, **kargs): - for e in viewvalues(lib_imgs): - preload_pe(e, libs, patch_vm_imp) - - -def vm2pe(myjit, fname, libs=None, e_orig=None, - min_addr=None, max_addr=None, - min_section_offset=0x1000, img_base=None, - added_funcs=None, **kwargs): - if e_orig: - size = e_orig._wsize - else: - size = 32 - mye = pe_init.PE(wsize=size) - - if min_addr is None and e_orig is not None: - min_addr = min([e_orig.rva2virt(s.addr) for s in e_orig.SHList]) - if max_addr is None and e_orig is not None: - max_addr = max([e_orig.rva2virt(s.addr + s.size) - for s in e_orig.SHList]) - - if img_base is None: - img_base = e_orig.NThdr.ImageBase - - mye.NThdr.ImageBase = img_base - all_mem = myjit.vm.get_all_memory() - addrs = list(all_mem) - addrs.sort() - entry_point = mye.virt2rva(myjit.pc) - if entry_point is None or not 0 < entry_point < 0xFFFFFFFF: - raise ValueError( - "Current pc (0x%x) used as entry point seems to be out of the binary" % - myjit.pc - ) - - mye.Opthdr.AddressOfEntryPoint = entry_point - first = True - for ad in addrs: - if not min_addr <= ad < max_addr: - continue - log.debug("0x%x", ad) - if first: - mye.SHList.add_section( - "%.8X" % ad, - addr=ad - mye.NThdr.ImageBase, - data=all_mem[ad]['data'], - offset=min_section_offset) - else: - mye.SHList.add_section( - "%.8X" % ad, - addr=ad - mye.NThdr.ImageBase, - data=all_mem[ad]['data']) - first = False - if libs: - if added_funcs is not None: - for addr, funcaddr in added_funcs: - libbase, dllname = libs.fad2info[funcaddr] - libs.lib_get_add_func(libbase, dllname, addr) - - filter_import = kwargs.get( - 'filter_import', lambda _, ad: mye.virt.is_addr_in(ad)) - new_dll = libs.gen_new_lib(mye, filter_import) - else: - new_dll = {} - - log.debug('%s', new_dll) - - mye.DirImport.add_dlldesc(new_dll) - s_imp = mye.SHList.add_section("import", rawsize=len(mye.DirImport)) - mye.DirImport.set_rva(s_imp.addr) - log.debug('%r', mye.SHList) - if e_orig: - # resource - xx = bytes(mye) - mye.content = xx - ad = e_orig.NThdr.optentries[pe.DIRECTORY_ENTRY_RESOURCE].rva - size = e_orig.NThdr.optentries[pe.DIRECTORY_ENTRY_RESOURCE].size - log.debug('dirres 0x%x', ad) - if ad != 0: - mye.NThdr.optentries[pe.DIRECTORY_ENTRY_RESOURCE].rva = ad - mye.NThdr.optentries[pe.DIRECTORY_ENTRY_RESOURCE].size = size - mye.DirRes = pe.DirRes.unpack(mye.img_rva, ad, mye) - log.debug('%r', mye.DirRes) - s_res = mye.SHList.add_section( - name="myres", - rawsize=len(mye.DirRes) - ) - mye.DirRes.set_rva(s_res.addr) - # generation - open(fname, 'wb').write(bytes(mye)) - return mye - - -class libimp_pe(libimp): - - def __init__(self, *args, **kwargs): - super(libimp_pe, self).__init__(*args, **kwargs) - # dependency -> redirector - self.created_redirected_imports = {} - - - def add_function(self, dllname, imp_ord_or_name, addr): - assert isinstance(dllname, str) - assert isinstance(imp_ord_or_name, (int, str)) - libad = self.name2off[dllname] - c_name = canon_libname_libfunc( - dllname, imp_ord_or_name - ) - update_entry = True - if addr in self.fad2info: - known_libad, known_imp_ord_or_name = self.fad2info[addr] - if isinstance(imp_ord_or_name, int): - update_entry = False - self.cname2addr[c_name] = addr - log.debug("Add func %s %s", hex(addr), c_name) - if update_entry: - log.debug("Real Add func %s %s", hex(addr), c_name) - self.fad2cname[addr] = c_name - self.fad2info[addr] = libad, imp_ord_or_name - - - def add_export_lib(self, e, name): - if name in self.created_redirected_imports: - log.error("%r has previously been created due to redirect\ - imports due to %r. Change the loading order.", - name, self.created_redirected_imports[name]) - raise RuntimeError('Bad import: loading previously created import') - - self.all_exported_lib.append(e) - # will add real lib addresses to database - if name in self.name2off: - ad = self.name2off[name] - if e is not None and name in self.fake_libs: - log.error( - "You are trying to load %r but it has been faked previously. Try loading this module earlier.", name) - raise RuntimeError("Bad import") - else: - log.debug('new lib %s', name) - ad = e.NThdr.ImageBase - libad = ad - self.name2off[name] = ad - self.libbase2lastad[ad] = ad + 0x1 - self.lib_imp2ad[ad] = {} - self.lib_imp2dstad[ad] = {} - self.libbase_ad += 0x1000 - - ads = get_export_name_addr_list(e) - todo = list(ads) - # done = [] - while todo: - # for imp_ord_or_name, ad in ads: - imp_ord_or_name, ad = todo.pop() - - # if export is a redirection, search redirected dll - # and get function real addr - ret = is_redirected_export(e, ad) - if ret: - exp_dname, exp_fname = ret - exp_dname = exp_dname + '.dll' - exp_dname = exp_dname.lower() - # if dll auto refes in redirection - if exp_dname == name: - libad_tmp = self.name2off[exp_dname] - if isinstance(exp_fname, str): - exp_fname = bytes(ord(c) for c in exp_fname) - found = None - for tmp_func, tmp_addr in ads: - if tmp_func == exp_fname: - found = tmp_addr - assert found is not None - ad = found - else: - # import redirected lib from non loaded dll - if not exp_dname in self.name2off: - self.created_redirected_imports.setdefault( - exp_dname, set()).add(name) - - # Ensure import entry is created - new_lib_base = self.lib_get_add_base(exp_dname) - # Ensure function entry is created - _ = self.lib_get_add_func(new_lib_base, exp_fname) - - libad_tmp = self.name2off[exp_dname] - ad = self.lib_imp2ad[libad_tmp][exp_fname] - - self.lib_imp2ad[libad][imp_ord_or_name] = ad - name_inv = dict( - (value, key) for key, value in viewitems(self.name2off) - ) - c_name = canon_libname_libfunc( - name_inv[libad], imp_ord_or_name) - self.fad2cname[ad] = c_name - self.cname2addr[c_name] = ad - log.debug("Add func %s %s", hex(ad), c_name) - self.fad2info[ad] = libad, imp_ord_or_name - - def gen_new_lib(self, target_pe, filter_import=lambda peobj, ad: True, **kwargs): - """Gen a new DirImport description - @target_pe: PE instance - @filter_import: (boolean f(pe, address)) restrict addresses to keep - """ - - new_lib = [] - for lib_name, ad in viewitems(self.name2off): - # Build an IMAGE_IMPORT_DESCRIPTOR - - # Get fixed addresses - out_ads = dict() # addr -> func_name - for func_name, dst_addresses in viewitems(self.lib_imp2dstad[ad]): - out_ads.update({addr: func_name for addr in dst_addresses}) - - # Filter available addresses according to @filter_import - all_ads = [ - addr for addr in list(out_ads) if filter_import(target_pe, addr) - ] - - if not all_ads: - continue - - # Keep non-NULL elements - all_ads.sort(key=str) - for i, x in enumerate(all_ads): - if x not in [0, None]: - break - all_ads = all_ads[i:] - log.debug('ads: %s', list(map(hex, all_ads))) - - while all_ads: - # Find libname's Import Address Table - othunk = all_ads[0] - i = 0 - while (i + 1 < len(all_ads) and - all_ads[i] + target_pe._wsize // 8 == all_ads[i + 1]): - i += 1 - # 'i + 1' is IAT's length - - # Effectively build an IMAGE_IMPORT_DESCRIPTOR - funcs = [out_ads[addr] for addr in all_ads[:i + 1]] - try: - rva = target_pe.virt2rva(othunk) - except pe.InvalidOffset: - pass - else: - new_lib.append(({"name": lib_name, - "firstthunk": rva}, - funcs) - ) - - # Update elements to handle - all_ads = all_ads[i + 1:] - - return new_lib - - -def vm_load_pe_and_dependencies(vm, fname, name2module, runtime_lib, - lib_path_base, **kwargs): - """Load a binary and all its dependencies. Returns a dictionary containing - the association between binaries names and it's pe object - - @vm: virtual memory manager instance - @fname: full path of the binary - @name2module: dict containing association between name and pe - object. Updated. - @runtime_lib: libimp instance - @lib_path_base: directory of the libraries containing dependencies - - """ - - todo = [(fname, fname, 0)] - weight2name = {} - done = set() - - # Walk dependencies recursively - while todo: - name, fname, weight = todo.pop() - if name in done: - continue - done.add(name) - weight2name.setdefault(weight, set()).add(name) - if name in name2module: - pe_obj = name2module[name] - else: - try: - with open(fname, "rb") as fstream: - log.info('Loading module name %r', fname) - pe_obj = vm_load_pe( - vm, fstream.read(), name=fname, **kwargs) - except IOError: - log.error('Cannot open %s' % fname) - name2module[name] = None - continue - name2module[name] = pe_obj - - new_dependencies = get_pe_dependencies(pe_obj) - todo += [(name, os.path.join(lib_path_base, name), weight - 1) - for name in new_dependencies] - - known_export_addresses = {} - to_resolve = {} - for name, pe_obj in name2module.items(): - print(name) - if pe_obj is None: - continue - if pe_obj.DirExport.expdesc == None: - continue - addrs = get_export_name_addr_list(pe_obj) - for imp_ord_or_name, ad in addrs: - # if export is a redirection, search redirected dll - # and get function real addr - ret = is_redirected_export(pe_obj, ad) - if ret is False: - known_export_addresses[(name, imp_ord_or_name)] = ad - else: - dllname, func_info = ret - dllname = dllname + '.dll' - to_resolve[(name, imp_ord_or_name)] = (dllname, func_info) - - modified = True - while modified: - modified = False - out = {} - for target, dependency in to_resolve.items(): - dllname, funcname = dependency - if dependency in known_export_addresses: - known_export_addresses[target] = known_export_addresses[dependency] - modified = True - else: - log.error("Cannot resolve redirection %r %r", dllname, dependency) - raise RuntimeError('Cannot resolve redirection') - to_resolve = out - - for dllname, pe_obj in name2module.items(): - if pe_obj is None: - continue - ad = pe_obj.NThdr.ImageBase - libad = ad - runtime_lib.name2off[dllname] = ad - runtime_lib.libbase2lastad[ad] = ad + 0x1 - runtime_lib.lib_imp2ad[ad] = {} - runtime_lib.lib_imp2dstad[ad] = {} - runtime_lib.libbase_ad += 0x1000 - - for (dllname, imp_ord_or_name), addr in known_export_addresses.items(): - runtime_lib.add_function(dllname, imp_ord_or_name, addr) - libad = runtime_lib.name2off[dllname] - runtime_lib.lib_imp2ad[libad][imp_ord_or_name] = addr - - assert not to_resolve - - for dllname, pe_obj in name2module.items(): - if pe_obj is None: - continue - preload_pe(vm, pe_obj, runtime_lib, patch_vm_imp=True) - - return name2module - -# machine -> arch -PE_machine = { - 0x14c: "x86_32", - 0x8664: "x86_64", -} - - -def guess_arch(pe): - """Return the architecture specified by the PE container @pe. - If unknown, return None""" - return PE_machine.get(pe.Coffhdr.machine, None) - - -class ImpRecStateMachine(object): - """ - Finite State Machine used for internal purpose only. - See `ImpRecStrategy` for more details. - """ - - # Looking for a function pointer - STATE_SEARCH = 0 - # Candidate function list - STATE_FUNC_FOUND = 1 - # Function list found, terminated by a NULL entry - STATE_END_FUNC_LIST = 2 - - def __init__(self, libs, ptrtype): - self.ptrtype = ptrtype - self.libs = libs - self.func_addrs = set(struct.pack(self.ptrtype, address) for address in self.libs.cname2addr.values()) - self.off2name = {v:k for k,v in self.libs.name2off.items()} - self.state = self.STATE_SEARCH - - # STATE_FUNC_FOUND - self.cur_list = [] - self.cur_list_lib = None - - # STATE_END_FUNC_LIST - self.seen = [] - - def format_func_info(self, func_info, func_addr): - return { - "lib_addr": func_info[0], - "lib_name": self.off2name[func_info[0]], - "entry_name": func_info[1], - "entry_module_addr": func_addr, - "entry_memory_addr": self.cur_address, - } - - def transition(self, data): - if self.state == self.STATE_SEARCH: - if data in self.func_addrs: - self.state = self.STATE_FUNC_FOUND - func_addr = struct.unpack(self.ptrtype, data)[0] - func_info = self.libs.fad2info[func_addr] - self.cur_list = [self.format_func_info(func_info, func_addr)] - self.cur_list_lib = func_info[0] - elif self.state == self.STATE_FUNC_FOUND: - if data == (b"\x00" * len(data)): - self.state = self.STATE_END_FUNC_LIST - elif data in self.func_addrs: - func_addr = struct.unpack(self.ptrtype, data)[0] - func_info = self.libs.fad2info[func_addr] - if func_info[0] != self.cur_list_lib: - # The list must belong to the same library - self.state = self.STATE_SEARCH - return - self.cur_list.append(self.format_func_info(func_info, func_addr)) - else: - self.state == self.STATE_SEARCH - elif self.state == self.STATE_END_FUNC_LIST: - self.seen.append(self.cur_list) - self.state = self.STATE_SEARCH - self.transition(data) - else: - raise ValueError() - - def run(self): - while True: - data, address = yield - self.cur_address = address - self.transition(data) - - -class ImpRecStrategy(object): - """ - Naive import reconstruction, similar to ImpRec - - It looks for a continuation of module export addresses, ended by a NULL entry, ie: - [...] - &Kernel32::LoadLibraryA - &Kernel32::HeapCreate - 00 00 00 00 - [...] - - Usage: - >>> sb = Sandbox[...] - >>> sb.run() - >>> imprec = ImpRecStrategy(sb.jitter, sb.libs, size=32) - >>> imprec.recover_import() - List<List<Recovered functions>> - - -> sb.libs has also been updated, ready to be passed to `vm2pe` - """ - def __init__(self, jitter, libs, size): - self._jitter = jitter - self._libs = libs - if size == 32: - self._ptrtype = "<I" - elif size == 64: - self._ptrtype = "<Q" - else: - ValueError("Unsupported size: %d" % size) - - def recover_import(self, update_libs=True, align_hypothesis=False): - """ - Launch the import recovery routine. - @update_libs: if set (default), update `libs` object with founded addresses - @align_hypothesis: if not set (default), do not consider import - addresses are written on aligned addresses - - Return the list of candidates - """ - candidates = [] - - alignments = [0] - if not align_hypothesis: - alignments = list(range(0, struct.calcsize(self._ptrtype))) - - for starting_offset in alignments: - # Search for several addresses from `func_addrs` ending with a `\x00` - fsm_obj = ImpRecStateMachine(self._libs, self._ptrtype) - fsm = fsm_obj.run() - fsm.send(None) - for addr_start, page_info in self._jitter.vm.get_all_memory().items(): - data = page_info["data"] - for i in range(starting_offset, page_info["size"], struct.calcsize(self._ptrtype)): - fsm.send((data[i:i+4], addr_start + i)) - - candidates.extend(fsm_obj.seen) - - # Apply to libs - if update_libs: - for entry_list in candidates: - for func_info in entry_list: - self._libs.lib_imp2dstad[func_info["lib_addr"]][func_info["entry_name"]].add(func_info["entry_memory_addr"]) - - return candidates diff --git a/miasm/jitter/loader/utils.py b/miasm/jitter/loader/utils.py deleted file mode 100644 index 7f913d76..00000000 --- a/miasm/jitter/loader/utils.py +++ /dev/null @@ -1,100 +0,0 @@ -from builtins import int as int_types -import logging - -from future.utils import viewitems, viewvalues -from past.builtins import basestring - -log = logging.getLogger('loader_common') -hnd = logging.StreamHandler() -hnd.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s")) -log.addHandler(hnd) -log.setLevel(logging.INFO) - - -def canon_libname_libfunc(libname, libfunc): - assert isinstance(libname, basestring) - assert isinstance(libfunc, basestring) or isinstance(libfunc, int_types) - dn = libname.split('.')[0] - if isinstance(libfunc, int_types): - return str(dn), libfunc - else: - return "%s_%s" % (dn, libfunc) - - -class libimp(object): - - def __init__(self, lib_base_ad=0x71111000, **kargs): - self.name2off = {} - self.libbase2lastad = {} - self.libbase_ad = lib_base_ad - self.lib_imp2ad = {} - self.lib_imp2dstad = {} - self.fad2cname = {} - self.cname2addr = {} - self.fad2info = {} - self.all_exported_lib = [] - self.fake_libs = set() - - def lib_get_add_base(self, name): - assert isinstance(name, basestring) - name = name.lower().strip(' ') - if not "." in name: - log.warning('warning adding .dll to modulename') - name += '.dll' - log.warning(name) - - if name in self.name2off: - ad = self.name2off[name] - else: - ad = self.libbase_ad - log.warning("Create dummy entry for %r", name) - self.fake_libs.add(name) - self.name2off[name] = ad - self.libbase2lastad[ad] = ad + 0x4 - self.lib_imp2ad[ad] = {} - self.lib_imp2dstad[ad] = {} - self.libbase_ad += 0x1000 - return ad - - def lib_get_add_func(self, libad, imp_ord_or_name, dst_ad=None): - if not libad in viewvalues(self.name2off): - raise ValueError('unknown lib base!', hex(libad)) - - # test if not ordinatl - # if imp_ord_or_name >0x10000: - # imp_ord_or_name = vm_get_str(imp_ord_or_name, 0x100) - # imp_ord_or_name = imp_ord_or_name[:imp_ord_or_name.find('\x00')] - - #[!] can have multiple dst ad - if not imp_ord_or_name in self.lib_imp2dstad[libad]: - self.lib_imp2dstad[libad][imp_ord_or_name] = set() - if dst_ad is not None: - self.lib_imp2dstad[libad][imp_ord_or_name].add(dst_ad) - - if imp_ord_or_name in self.lib_imp2ad[libad]: - return self.lib_imp2ad[libad][imp_ord_or_name] - log.debug('new imp %s %s' % (imp_ord_or_name, dst_ad)) - ad = self.libbase2lastad[libad] - self.libbase2lastad[libad] += 0x10 # arbitrary - self.lib_imp2ad[libad][imp_ord_or_name] = ad - - name_inv = dict( - (value, key) for key, value in viewitems(self.name2off) - ) - c_name = canon_libname_libfunc(name_inv[libad], imp_ord_or_name) - self.fad2cname[ad] = c_name - self.cname2addr[c_name] = ad - self.fad2info[ad] = libad, imp_ord_or_name - return ad - - def check_dst_ad(self): - for ad in self.lib_imp2dstad: - all_ads = sorted(viewvalues(self.lib_imp2dstad[ad])) - for i, x in enumerate(all_ads[:-1]): - if x is None or all_ads[i + 1] is None: - return False - if x + 4 != all_ads[i + 1]: - return False - return True - - diff --git a/miasm/jitter/op_semantics.c b/miasm/jitter/op_semantics.c deleted file mode 100644 index 6725ae64..00000000 --- a/miasm/jitter/op_semantics.c +++ /dev/null @@ -1,853 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <inttypes.h> -#include <math.h> -#include "op_semantics.h" - -const uint8_t parity_table[256] = { - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, - 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, -}; - -uint16_t bcdadd_16(uint16_t a, uint16_t b) -{ - int carry = 0; - int i,j = 0; - uint16_t res = 0; - int nib_a, nib_b; - for (i = 0; i < 16; i += 4) { - nib_a = (a >> i) & (0xF); - nib_b = (b >> i) & (0xF); - - j = (carry + nib_a + nib_b); - if (j >= 10) { - carry = 1; - j -= 10; - j &=0xf; - } - else { - carry = 0; - } - res += j << i; - } - return res; -} - -uint16_t bcdadd_cf_16(uint16_t a, uint16_t b) -{ - int carry = 0; - int i,j = 0; - int nib_a, nib_b; - for (i = 0; i < 16; i += 4) { - nib_a = (a >> i) & (0xF); - nib_b = (b >> i) & (0xF); - - j = (carry + nib_a + nib_b); - if (j >= 10) { - carry = 1; - j -= 10; - j &=0xf; - } - else { - carry = 0; - } - } - return carry; -} - -unsigned int mul_lo_op(unsigned int size, unsigned int a, unsigned int b) -{ - unsigned int mask; - - switch (size) { - case 8: mask = 0xff; break; - case 16: mask = 0xffff; break; - case 32: mask = 0xffffffff; break; - default: fprintf(stderr, "inv size in mul %d\n", size); exit(EXIT_FAILURE); - } - - a &= mask; - b &= mask; - return ((int64_t)a * (int64_t) b) & mask; -} - -unsigned int mul_hi_op(unsigned int size, unsigned int a, unsigned int b) -{ - uint64_t res = 0; - unsigned int mask; - - switch (size) { - case 8: mask = 0xff; break; - case 16: mask = 0xffff; break; - case 32: mask = 0xffffffff; break; - default: fprintf(stderr, "inv size in mul %d\n", size); exit(EXIT_FAILURE); - } - - a &= mask; - b &= mask; - res = ((uint64_t)a * (uint64_t)b); - return (res >> 32) & mask; -} - - -unsigned int imul_lo_op_08(char a, char b) -{ - return a*b; -} - -unsigned int imul_lo_op_16(short a, short b) -{ - return a*b; -} - -unsigned int imul_lo_op_32(int a, int b) -{ - return a*b; -} - -int imul_hi_op_08(char a, char b) -{ - int64_t res = 0; - res = a*b; - return (int)(res>>8); -} - -int imul_hi_op_16(short a, short b) -{ - int64_t res = 0; - res = a*b; - return (int)(res>>16); -} - -int imul_hi_op_32(int a, int b) -{ - int64_t res = 0; - res = (int64_t)a*(int64_t)b; - return (int)(res>>32ULL); -} - -unsigned int umul16_lo(unsigned short a, unsigned short b) -{ - return (a*b) & 0xffff; -} - -unsigned int umul16_hi(unsigned short a, unsigned short b) -{ - uint32_t c; - c = a*b; - return (c>>16) & 0xffff; -} - -uint64_t rot_left(uint64_t size, uint64_t a, uint64_t b) -{ - uint64_t tmp; - - b = b & 0x3F; - b %= size; - switch(size){ - case 8: - tmp = (a << b) | ((a & 0xFF) >> (size - b)); - return tmp & 0xFF; - case 16: - tmp = (a << b) | ((a & 0xFFFF) >> (size - b)); - return tmp & 0xFFFF; - case 32: - tmp = (a << b) | ((a & 0xFFFFFFFF) >> (size - b)); - return tmp & 0xFFFFFFFF; - case 64: - tmp = (a << b) | ((a&0xFFFFFFFFFFFFFFFF) >> (size - b)); - return tmp & 0xFFFFFFFFFFFFFFFF; - - /* Support cases for rcl */ - case 9: - tmp = (a << b) | ((a & 0x1FF) >> (size - b)); - return tmp & 0x1FF; - case 17: - tmp = (a << b) | ((a & 0x1FFFF) >> (size - b)); - return tmp & 0x1FFFF; - case 33: - tmp = (a << b) | ((a & 0x1FFFFFFFF) >> (size - b)); - return tmp & 0x1FFFFFFFF; - /* TODO XXX: support rcl in 64 bit mode */ - - default: - fprintf(stderr, "inv size in rotleft %"PRIX64"\n", size); - exit(EXIT_FAILURE); - } -} - -uint64_t rot_right(uint64_t size, uint64_t a, uint64_t b) -{ - uint64_t tmp; - - b = b & 0x3F; - b %= size; - switch(size){ - case 8: - tmp = ((a & 0xFF) >> b) | (a << (size - b)); - return tmp & 0xff; - case 16: - tmp = ((a & 0xFFFF) >> b) | (a << (size - b)); - return tmp & 0xFFFF; - case 32: - tmp = ((a & 0xFFFFFFFF) >> b) | (a << (size - b)); - return tmp & 0xFFFFFFFF; - case 64: - tmp = ((a & 0xFFFFFFFFFFFFFFFF) >> b) | (a << (size - b)); - return tmp & 0xFFFFFFFFFFFFFFFF; - - /* Support cases for rcr */ - case 9: - tmp = ((a & 0x1FF) >> b) | (a << (size - b)); - return tmp & 0x1FF; - case 17: - tmp = ((a & 0x1FFFF) >> b) | (a << (size - b)); - return tmp & 0x1FFFF; - case 33: - tmp = ((a & 0x1FFFFFFFF) >> b) | (a << (size - b)); - return tmp & 0x1FFFFFFFF; - /* TODO XXX: support rcr in 64 bit mode */ - - default: - fprintf(stderr, "inv size in rotright %"PRIX64"\n", size); - exit(EXIT_FAILURE); - } -} - -/* - * Count leading zeros - count the number of zero starting at the most - * significant bit - * - * Example: - * - cntleadzeros(size=32, src=2): 30 - * - cntleadzeros(size=32, src=0): 32 - */ -uint64_t cntleadzeros(uint64_t size, uint64_t src) -{ - int64_t i; - - for (i=(int64_t)size-1; i>=0; i--){ - if (src & (1ull << i)) - return (uint64_t)(size - (i + 1)); - } - return (uint64_t)size; -} - -/* - * Count trailing zeros - count the number of zero starting at the least - * significant bit - * - * Example: - * - cnttrailzeros(size=32, src=2): 1 - * - cnttrailzeros(size=32, src=0): 32 - */ -unsigned int cnttrailzeros(uint64_t size, uint64_t src) -{ - uint64_t i; - for (i=0; i<size; i++){ - if (src & (1ull << i)) - return (unsigned int)i; - } - return (unsigned int)size; -} - - -unsigned int my_imul08(unsigned int a, unsigned int b) -{ - char a08, b08; - short a16; - - a08 = a&0xFF; - b08 = b&0xFF; - a16 = a08*b08; - return (int)a16; -} - - - -unsigned int x86_cpuid(unsigned int a, unsigned int reg_num) -{ - if (reg_num >3){ - fprintf(stderr, "not implemented x86_cpuid reg %x\n", reg_num); - exit(EXIT_FAILURE); - } - // cases are output: EAX: 0; EBX: 1; ECX: 2; EDX: 3 - if (a == 0){ - switch(reg_num){ - case 0: - return 0xa; - // "GenuineIntel" - case 1: - return 0x756E6547; - case 2: - return 0x6C65746E; - case 3: - return 0x49656E69; - } - } - - else if (a == 1){ - switch(reg_num){ - case 0: - // Using a version too high will enable recent - // instruction set - return 0x000006FB; - //return 0x00020652; - case 1: - //return 0x02040800; - return 0x00000800; - case 2: - //return 0x0004E3BD; - return 0x00000209; - case 3: - return (/* fpu */ 1 << 0) | - (/* tsc */ 1 << 4) | - (/* cx8 */ 1 << 8) | - (/* cmov */ 1 << 15) | - (/* mmx */ 1 << 23) | - (/* sse */ 1 << 25) | - (/* sse2 */ 1 << 26) | - (/* ia64 */ 1 << 30); - } - } - // Cache and TLB - else if (a == 2){ - switch(reg_num){ - case 0: - return 0x00000000; - case 1: - return 0x00000000; - case 2: - return 0x00000000; - case 3: - return 0x00000000; - } - } - // Intel thread/core and cache topology - else if (a == 4){ - switch(reg_num){ - case 0: - return 0x00000000; - case 1: - return 0x00000000; - case 2: - return 0x00000000; - case 3: - return 0x00000000; - } - } - // Extended features - else if (a == 7){ - switch(reg_num){ - case 0: - return 0x00000000; - case 1: - return (/* fsgsbase */ 1 << 0) | (/* bmi1 */ 1 << 3); - case 2: - return 0x00000000; - case 3: - return 0x00000000; - } - } - // Extended Function CPUID Information - else if (a == 0x80000000){ - switch(reg_num){ - case 0: - // Pentium 4 Processor supporting Hyper-Threading - // Technology to Intel Xeon Processor 5100 Series - return 0x80000008; - case 1: - return 0x00000000; - case 2: - return 0x00000000; - case 3: - return 0x00000000; - } - } - else if (a == 0x80000001){ - switch(reg_num){ - case 0: - // Extended Processor Signature and Extended Feature - // Bits - return 0x00000000; - case 1: - return 0x00000000; - case 2: - return (/* LAHF-SAHF */ 1 << 0) - | (/* LZCNT */ 0 << 5) - | (/* PREFETCHW */ 1 << 8); - case 3: - return (/* SYSCALL/SYSRET */ 1 << 11) - | (/* Execute Disable Bit available */ 0 << 20) - | (/* 1-GByte pages available */ 0 << 26) - | (/* RDTSCP and IA32_TSC_AUX available */ 0 << 27) - | (/* Intel ® 64 Architecture available */ 1 << 29); - } - } - else{ - fprintf(stderr, "WARNING not implemented x86_cpuid index %X!\n", a); - exit(EXIT_FAILURE); - } - return 0; -} - -//#define DEBUG_MIASM_DOUBLE - -void dump_float(void) -{ - /* - printf("%e\n", vmmngr.float_st0); - printf("%e\n", vmmngr.float_st1); - printf("%e\n", vmmngr.float_st2); - printf("%e\n", vmmngr.float_st3); - printf("%e\n", vmmngr.float_st4); - printf("%e\n", vmmngr.float_st5); - printf("%e\n", vmmngr.float_st6); - printf("%e\n", vmmngr.float_st7); - */ -} - -typedef union { - uint32_t u32; - float flt; -} float_uint32_t; - - -typedef union { - uint64_t u64; - double dbl; -} double_uint64_t; - - -uint32_t fpu_fadd32(uint32_t a, uint32_t b) -{ - float_uint32_t a_cast, b_cast, c_cast; - - a_cast.u32 = a; - b_cast.u32 = b; - - c_cast.flt = a_cast.flt + b_cast.flt; -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e + %e -> %e\n", a, b, c_cast.flt); -#endif - return c_cast.u32; -} - -uint64_t fpu_fadd64(uint64_t a, uint64_t b) -{ - double_uint64_t a_cast, b_cast, c_cast; - - a_cast.u64 = a; - b_cast.u64 = b; - - c_cast.dbl = a_cast.dbl + b_cast.dbl; -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e + %e -> %e\n", a, b, c_cast.dbl); -#endif - return c_cast.u64; -} - -uint32_t fpu_fsub32(uint32_t a, uint32_t b) -{ - float_uint32_t a_cast, b_cast, c_cast; - - a_cast.u32 = a; - b_cast.u32 = b; - - c_cast.flt = a_cast.flt - b_cast.flt; -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e + %e -> %e\n", a, b, c_cast.flt); -#endif - return c_cast.u32; -} - -uint64_t fpu_fsub64(uint64_t a, uint64_t b) -{ - double_uint64_t a_cast, b_cast, c_cast; - - a_cast.u64 = a; - b_cast.u64 = b; - - c_cast.dbl = a_cast.dbl - b_cast.dbl; -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e + %e -> %e\n", a, b, c_cast.dbl); -#endif - return c_cast.u64; -} - -uint32_t fpu_fmul32(uint32_t a, uint32_t b) -{ - float_uint32_t a_cast, b_cast, c_cast; - - a_cast.u32 = a; - b_cast.u32 = b; - - c_cast.flt = a_cast.flt * b_cast.flt; -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e * %e -> %e\n", a, b, c_cast.flt); -#endif - return c_cast.u32; -} - -uint64_t fpu_fmul64(uint64_t a, uint64_t b) -{ - double_uint64_t a_cast, b_cast, c_cast; - - a_cast.u64 = a; - b_cast.u64 = b; - - c_cast.dbl = a_cast.dbl * b_cast.dbl; -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e * %e -> %e\n", a, b, c_cast.dbl); -#endif - return c_cast.u64; -} - -uint32_t fpu_fdiv32(uint32_t a, uint32_t b) -{ - float_uint32_t a_cast, b_cast, c_cast; - - a_cast.u32 = a; - b_cast.u32 = b; - - c_cast.flt = a_cast.flt / b_cast.flt; -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e * %e -> %e\n", a, b, c_cast.flt); -#endif - return c_cast.u32; -} - -uint64_t fpu_fdiv64(uint64_t a, uint64_t b) -{ - double_uint64_t a_cast, b_cast, c_cast; - - a_cast.u64 = a; - b_cast.u64 = b; - - c_cast.dbl = a_cast.dbl / b_cast.dbl; -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e * %e -> %e\n", a, b, c_cast.dbl); -#endif - return c_cast.u64; -} - -double fpu_ftan(double a) -{ - double b; - b = tan(a); -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e tan %e\n", a, b); -#endif - return b; -} - -double fpu_frndint(double a) -{ - int64_t b; - double c; - b = (int64_t)a; - c = (double)b; -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e double %e\n", a, c); -#endif - return c; -} - -double fpu_fsin(double a) -{ - double b; - b = sin(a); -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e sin %e\n", a, b); -#endif - return b; -} - -double fpu_fcos(double a) -{ - double b; - b = cos(a); -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e cos %e\n", a, b); -#endif - return b; -} - - -double fpu_fscale(double a, double b) -{ - double c; - c = a * exp2(trunc(b)); -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e *exp2 %e -> %e\n", a, b, c); -#endif - return c; -} - -double fpu_f2xm1(double a) -{ - double b; - b = exp2(a)-1; -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e exp2 -1 %e\n", a, b); -#endif - return b; -} - -uint32_t fpu_fsqrt32(uint32_t a) -{ - float_uint32_t a_cast; - a_cast.u32 = a; - a_cast.flt = sqrtf(a_cast.flt); -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e sqrt %e\n", a, a_cast.flt); -#endif - return a_cast.u32; -} - -uint64_t fpu_fsqrt64(uint64_t a) -{ - double_uint64_t a_cast; - - a_cast.u64 = a; - a_cast.dbl = sqrt(a_cast.dbl); -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e sqrt %e\n", a, a_cast.dbl); -#endif - return a_cast.u64; -} - -uint64_t fpu_fabs64(uint64_t a) -{ - double_uint64_t a_cast; - - a_cast.u64 = a; - a_cast.dbl = fabs(a_cast.dbl); -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e abs %e\n", a, a_cast.dbl); -#endif - return a_cast.u64; -} - -uint64_t fpu_fprem64(uint64_t a, uint64_t b) -{ - double_uint64_t a_cast, b_cast, c_cast; - - a_cast.u64 = a; - b_cast.u64 = b; - - c_cast.dbl = fmod(a_cast.dbl, b_cast.dbl); -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e %% %e -> %e\n", a, b, c); -#endif - return c_cast.u64; -} - -double fpu_fchs(double a) -{ - double b; - b = -a; -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf(" - %e -> %e\n", a, b); -#endif - return b; -} - -double fpu_fyl2x(double a, double b) -{ - double c; - c = b * (log(a) / log(2)); -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("%e * log(%e) -> %e\n", b, a, c); -#endif - return c; -} - -double fpu_fpatan(double a, double b) -{ - double c; - c = atan2(b, a); -#ifdef DEBUG_MIASM_DOUBLE - dump_float(); - printf("arctan(%e / %e) -> %e\n", b, a, c); -#endif - return c; -} - -unsigned int fpu_fcom_c0(double a, double b) -{ - if (isnan(a) || isnan(b)) - return 1; - if (a>=b) - return 0; - return 1; -} -unsigned int fpu_fcom_c1(double a, double b) -{ - //XXX - return 0; -} -unsigned int fpu_fcom_c2(double a, double b) -{ - if (isnan(a) || isnan(b)) - return 1; - return 0; -} -unsigned int fpu_fcom_c3(double a, double b) -{ - if (isnan(a) || isnan(b)) - return 1; - if (a==b) - return 1; - return 0; -} - -uint64_t sint_to_fp_64(int64_t a) -{ - double_uint64_t a_cast; - a_cast.dbl = (double) a; - return a_cast.u64; -} - -uint32_t sint_to_fp_32(int32_t a) -{ - float_uint32_t a_cast; - a_cast.flt = (float) a; - return a_cast.u32; -} - -int32_t fp32_to_sint32(uint32_t a) -{ - // Enforce nearbyint (IEEE-754 behavior) - float rounded; - float_uint32_t a_cast; - a_cast.u32 = a; - rounded = nearbyintf(a_cast.flt); - return (int32_t) rounded; -} - -int64_t fp64_to_sint64(uint64_t a) -{ - // Enforce nearbyint (IEEE-754 behavior) - double rounded; - double_uint64_t a_cast; - a_cast.u64 = a; - rounded = nearbyint(a_cast.dbl); - return (int64_t) rounded; -} - -int32_t fp64_to_sint32(uint64_t a) -{ - // Enforce nearbyint (IEEE-754 behavior) - double rounded; - double_uint64_t a_cast; - a_cast.u64 = a; - rounded = nearbyint(a_cast.dbl); - return (int32_t) rounded; -} - -uint32_t fp64_to_fp32(uint64_t a) -{ - float_uint32_t a_cast32; - double_uint64_t a_cast64; - a_cast64.u64 = a; - a_cast32.flt = (float)a_cast64.dbl; - return a_cast32.u32; -} - -uint64_t fp32_to_fp64(uint32_t a) -{ - float_uint32_t a_cast32; - double_uint64_t a_cast64; - a_cast32.u32 = a; - a_cast64.dbl = (double)a_cast32.flt; - return a_cast64.u64; -} - -uint32_t fpround_towardszero_fp32(uint32_t a) -{ - float_uint32_t a_cast; - a_cast.u32 = a; - a_cast.flt = truncf(a_cast.flt); - return a_cast.u32; -} - -uint64_t fpround_towardszero_fp64(uint64_t a) -{ - double_uint64_t a_cast; - a_cast.u64 = a; - a_cast.dbl = trunc(a_cast.dbl); - return a_cast.u64; -} - - -UDIV(8) -UDIV(16) -UDIV(32) -UDIV(64) - -UMOD(8) -UMOD(16) -UMOD(32) -UMOD(64) - -SDIV(8) -SDIV(16) -SDIV(32) -SDIV(64) - -SMOD(8) -SMOD(16) -SMOD(32) -SMOD(64) diff --git a/miasm/jitter/op_semantics.h b/miasm/jitter/op_semantics.h deleted file mode 100644 index b76a350c..00000000 --- a/miasm/jitter/op_semantics.h +++ /dev/null @@ -1,172 +0,0 @@ -#ifndef OP_SEMANTICS_H -#define OP_SEMANTICS_H - -#include <stdint.h> - -#if _WIN32 -#define _MIASM_EXPORT __declspec(dllexport) -#define _MIASM_IMPORT __declspec(dllimport) -#else -#define _MIASM_EXPORT -#define _MIASM_IMPORT -#endif - -#define CC_P 1 -#ifdef PARITY_IMPORT -_MIASM_IMPORT extern const uint8_t parity_table[256]; -#else -_MIASM_EXPORT extern const uint8_t parity_table[256]; -#endif -#define parity(a) parity_table[(a) & 0xFF] - - -_MIASM_EXPORT uint16_t bcdadd_16(uint16_t a, uint16_t b); -_MIASM_EXPORT uint16_t bcdadd_cf_16(uint16_t a, uint16_t b); - - -_MIASM_EXPORT unsigned int my_imul08(unsigned int a, unsigned int b); -_MIASM_EXPORT unsigned int mul_lo_op(unsigned int size, unsigned int a, unsigned int b); -_MIASM_EXPORT unsigned int mul_hi_op(unsigned int size, unsigned int a, unsigned int b); -_MIASM_EXPORT unsigned int imul_lo_op_08(char a, char b); -_MIASM_EXPORT unsigned int imul_lo_op_16(short a, short b); -_MIASM_EXPORT unsigned int imul_lo_op_32(int a, int b); -_MIASM_EXPORT int imul_hi_op_08(char a, char b); -_MIASM_EXPORT int imul_hi_op_16(short a, short b); -_MIASM_EXPORT int imul_hi_op_32(int a, int b); - - -_MIASM_EXPORT unsigned int umul16_lo(unsigned short a, unsigned short b); -_MIASM_EXPORT unsigned int umul16_hi(unsigned short a, unsigned short b); - - -_MIASM_EXPORT uint64_t rot_left(uint64_t size, uint64_t a, uint64_t b); -_MIASM_EXPORT uint64_t rot_right(uint64_t size, uint64_t a, uint64_t b); - -_MIASM_EXPORT uint64_t cntleadzeros(uint64_t size, uint64_t src); -_MIASM_EXPORT unsigned int cnttrailzeros(uint64_t size, uint64_t src); - -#define UDIV(sizeA) \ - uint ## sizeA ## _t udiv ## sizeA (uint ## sizeA ## _t a, uint ## sizeA ## _t b) \ - { \ - uint ## sizeA ## _t r; \ - if (b == 0) { \ - fprintf(stderr, "Should not happen\n"); \ - exit(EXIT_FAILURE); \ - } \ - r = a/b; \ - return r; \ - } - - -#define UMOD(sizeA) \ - uint ## sizeA ## _t umod ## sizeA (uint ## sizeA ## _t a, uint ## sizeA ## _t b) \ - { \ - uint ## sizeA ## _t r; \ - if (b == 0) { \ - fprintf(stderr, "Should not happen\n"); \ - exit(EXIT_FAILURE); \ - } \ - r = a%b; \ - return r; \ - } - - -#define SDIV(sizeA) \ - int ## sizeA ## _t sdiv ## sizeA (int ## sizeA ## _t a, int ## sizeA ## _t b) \ - { \ - int ## sizeA ## _t r; \ - if (b == 0) { \ - fprintf(stderr, "Should not happen\n"); \ - exit(EXIT_FAILURE); \ - } \ - r = a/b; \ - return r; \ - } - - -#define SMOD(sizeA) \ - int ## sizeA ## _t smod ## sizeA (int ## sizeA ## _t a, int ## sizeA ## _t b) \ - { \ - int ## sizeA ## _t r; \ - if (b == 0) { \ - fprintf(stderr, "Should not happen\n"); \ - exit(EXIT_FAILURE); \ - } \ - r = a%b; \ - return r; \ - } - -_MIASM_EXPORT uint64_t udiv64(uint64_t a, uint64_t b); -_MIASM_EXPORT uint64_t umod64(uint64_t a, uint64_t b); -_MIASM_EXPORT int64_t sdiv64(int64_t a, int64_t b); -_MIASM_EXPORT int64_t smod64(int64_t a, int64_t b); - -_MIASM_EXPORT uint32_t udiv32(uint32_t a, uint32_t b); -_MIASM_EXPORT uint32_t umod32(uint32_t a, uint32_t b); -_MIASM_EXPORT int32_t sdiv32(int32_t a, int32_t b); -_MIASM_EXPORT int32_t smod32(int32_t a, int32_t b); - -_MIASM_EXPORT uint16_t udiv16(uint16_t a, uint16_t b); -_MIASM_EXPORT uint16_t umod16(uint16_t a, uint16_t b); -_MIASM_EXPORT int16_t sdiv16(int16_t a, int16_t b); -_MIASM_EXPORT int16_t smod16(int16_t a, int16_t b); - -_MIASM_EXPORT uint8_t udiv8(uint8_t a, uint8_t b); -_MIASM_EXPORT uint8_t umod8(uint8_t a, uint8_t b); -_MIASM_EXPORT int8_t sdiv8(int8_t a, int8_t b); -_MIASM_EXPORT int8_t smod8(int8_t a, int8_t b); - -_MIASM_EXPORT unsigned int x86_cpuid(unsigned int a, unsigned int reg_num); - -_MIASM_EXPORT uint32_t fpu_fadd32(uint32_t a, uint32_t b); -_MIASM_EXPORT uint64_t fpu_fadd64(uint64_t a, uint64_t b); -_MIASM_EXPORT uint32_t fpu_fsub32(uint32_t a, uint32_t b); -_MIASM_EXPORT uint64_t fpu_fsub64(uint64_t a, uint64_t b); -_MIASM_EXPORT uint32_t fpu_fmul32(uint32_t a, uint32_t b); -_MIASM_EXPORT uint64_t fpu_fmul64(uint64_t a, uint64_t b); -_MIASM_EXPORT uint32_t fpu_fdiv32(uint32_t a, uint32_t b); -_MIASM_EXPORT uint64_t fpu_fdiv64(uint64_t a, uint64_t b); -_MIASM_EXPORT double fpu_ftan(double a); -_MIASM_EXPORT double fpu_frndint(double a); -_MIASM_EXPORT double fpu_fsin(double a); -_MIASM_EXPORT double fpu_fcos(double a); -_MIASM_EXPORT double fpu_fscale(double a, double b); -_MIASM_EXPORT double fpu_f2xm1(double a); -_MIASM_EXPORT uint32_t fpu_fsqrt32(uint32_t a); -_MIASM_EXPORT uint64_t fpu_fsqrt64(uint64_t a); -_MIASM_EXPORT uint64_t fpu_fabs64(uint64_t a); -_MIASM_EXPORT uint64_t fpu_fprem64(uint64_t a, uint64_t b); -_MIASM_EXPORT double fpu_fchs(double a); -_MIASM_EXPORT double fpu_fyl2x(double a, double b); -_MIASM_EXPORT double fpu_fpatan(double a, double b); -_MIASM_EXPORT unsigned int fpu_fcom_c0(double a, double b); -_MIASM_EXPORT unsigned int fpu_fcom_c1(double a, double b); -_MIASM_EXPORT unsigned int fpu_fcom_c2(double a, double b); -_MIASM_EXPORT unsigned int fpu_fcom_c3(double a, double b); - -_MIASM_EXPORT uint64_t sint_to_fp_64(int64_t a); -_MIASM_EXPORT uint32_t sint_to_fp_32(int32_t a); -_MIASM_EXPORT int32_t fp32_to_sint32(uint32_t a); -_MIASM_EXPORT int64_t fp64_to_sint64(uint64_t a); -_MIASM_EXPORT int32_t fp64_to_sint32(uint64_t a); -_MIASM_EXPORT uint32_t fp64_to_fp32(uint64_t a); -_MIASM_EXPORT uint64_t fp32_to_fp64(uint32_t a); -_MIASM_EXPORT uint32_t fpround_towardszero_fp32(uint32_t a); -_MIASM_EXPORT uint64_t fpround_towardszero_fp64(uint64_t a); - -#define SHIFT_RIGHT_ARITH(size, value, shift) \ - ((uint ## size ## _t)((((uint64_t) (shift)) > ((size) - 1))? \ - (((int ## size ## _t) (value)) < 0 ? -1 : 0) : \ - (((int ## size ## _t) (value)) >> (shift)))) - -#define SHIFT_RIGHT_LOGIC(size, value, shift) \ - ((uint ## size ## _t)((((uint64_t) (shift)) > ((size) - 1))? \ - 0 : \ - (((uint ## size ## _t) (value)) >> (shift)))) - -#define SHIFT_LEFT_LOGIC(size, value, shift) \ - ((uint ## size ## _t)((((uint64_t) (shift)) > ((size) - 1))? \ - 0 : \ - (((uint ## size ## _t) (value)) << (shift)))) - -#endif diff --git a/miasm/jitter/queue.h b/miasm/jitter/queue.h deleted file mode 100644 index 0caf72fb..00000000 --- a/miasm/jitter/queue.h +++ /dev/null @@ -1,553 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - * $FreeBSD$ - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -//#include <sys/cdefs.h> - -/* - * This file defines four types of data structures: singly-linked lists, - * singly-linked tail queues, lists and tail queues. - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A singly-linked tail queue is headed by a pair of pointers, one to the - * head of the list and the other to the tail of the list. The elements are - * singly linked for minimum space and pointer manipulation overhead at the - * expense of O(n) removal for arbitrary elements. New elements can be added - * to the list after an existing element, at the head of the list, or at the - * end of the list. Elements being removed from the head of the tail queue - * should use the explicit macro for this purpose for optimum efficiency. - * A singly-linked tail queue may only be traversed in the forward direction. - * Singly-linked tail queues are ideal for applications with large datasets - * and few or no removals or for implementing a FIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * For details on the use of these macros, see the queue(3) manual page. - * - * - * SLIST LIST STAILQ TAILQ - * _HEAD + + + + - * _HEAD_INITIALIZER + + + + - * _ENTRY + + + + - * _INIT + + + + - * _EMPTY + + + + - * _FIRST + + + + - * _NEXT + + + + - * _PREV - - - + - * _LAST - - + + - * _FOREACH + + + + - * _FOREACH_SAFE + + + + - * _FOREACH_REVERSE - - - + - * _FOREACH_REVERSE_SAFE - - - + - * _INSERT_HEAD + + + + - * _INSERT_BEFORE - + - + - * _INSERT_AFTER + + + + - * _INSERT_TAIL - - + + - * _CONCAT - - + + - * _REMOVE_HEAD + - + - - * _REMOVE + + + + - * - */ -#define QUEUE_MACRO_DEBUG 0 -#if QUEUE_MACRO_DEBUG -/* Store the last 2 places the queue element or head was altered */ -struct qm_trace { - char * lastfile; - int lastline; - char * prevfile; - int prevline; -}; - -#define TRACEBUF struct qm_trace trace; -#define TRASHIT(x) do {(x) = (void *)-1;} while (0) - -#define QMD_TRACE_HEAD(head) do { \ - (head)->trace.prevline = (head)->trace.lastline; \ - (head)->trace.prevfile = (head)->trace.lastfile; \ - (head)->trace.lastline = __LINE__; \ - (head)->trace.lastfile = __FILE__; \ -} while (0) - -#define QMD_TRACE_ELEM(elem) do { \ - (elem)->trace.prevline = (elem)->trace.lastline; \ - (elem)->trace.prevfile = (elem)->trace.lastfile; \ - (elem)->trace.lastline = __LINE__; \ - (elem)->trace.lastfile = __FILE__; \ -} while (0) - -#else -#define QMD_TRACE_ELEM(elem) -#define QMD_TRACE_HEAD(head) -#define TRACEBUF -#define TRASHIT(x) -#endif /* QUEUE_MACRO_DEBUG */ - -/* - * Singly-linked List declarations. - */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List functions. - */ -#define SLIST_EMPTY(head) ((head)->slh_first == NULL) - -#define SLIST_FIRST(head) ((head)->slh_first) - -#define SLIST_FOREACH(var, head, field) \ - for ((var) = SLIST_FIRST((head)); \ - (var); \ - (var) = SLIST_NEXT((var), field)) - -#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SLIST_FIRST((head)); \ - (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ - for ((varp) = &SLIST_FIRST((head)); \ - ((var) = *(varp)) != NULL; \ - (varp) = &SLIST_NEXT((var), field)) - -#define SLIST_INIT(head) do { \ - SLIST_FIRST((head)) = NULL; \ -} while (0) - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ - SLIST_NEXT((slistelm), field) = (elm); \ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ - SLIST_FIRST((head)) = (elm); \ -} while (0) - -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_REMOVE(head, elm, type, field) do { \ - if (SLIST_FIRST((head)) == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } \ - else { \ - struct type *curelm = SLIST_FIRST((head)); \ - while (SLIST_NEXT(curelm, field) != (elm)) \ - curelm = SLIST_NEXT(curelm, field); \ - SLIST_NEXT(curelm, field) = \ - SLIST_NEXT(SLIST_NEXT(curelm, field), field); \ - } \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ -} while (0) - -/* - * Singly-linked Tail queue declarations. - */ -#define STAILQ_HEAD(name, type) \ -struct name { \ - struct type *stqh_first;/* first element */ \ - struct type **stqh_last;/* addr of last next element */ \ -} - -#define STAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).stqh_first } - -#define STAILQ_ENTRY(type) \ -struct { \ - struct type *stqe_next; /* next element */ \ -} - -/* - * Singly-linked Tail queue functions. - */ -#define STAILQ_CONCAT(head1, head2) do { \ - if (!STAILQ_EMPTY((head2))) { \ - *(head1)->stqh_last = (head2)->stqh_first; \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_INIT((head2)); \ - } \ -} while (0) - -#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) - -#define STAILQ_FIRST(head) ((head)->stqh_first) - -#define STAILQ_FOREACH(var, head, field) \ - for((var) = STAILQ_FIRST((head)); \ - (var); \ - (var) = STAILQ_NEXT((var), field)) - - -#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = STAILQ_FIRST((head)); \ - (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define STAILQ_INIT(head) do { \ - STAILQ_FIRST((head)) = NULL; \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_NEXT((tqelm), field) = (elm); \ -} while (0) - -#define STAILQ_INSERT_HEAD(head, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_FIRST((head)) = (elm); \ -} while (0) - -#define STAILQ_INSERT_TAIL(head, elm, field) do { \ - STAILQ_NEXT((elm), field) = NULL; \ - *(head)->stqh_last = (elm); \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -#define STAILQ_LAST(head, type, field) \ - (STAILQ_EMPTY((head)) ? \ - NULL : \ - ((struct type *) \ - ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) - -#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) - -#define STAILQ_REMOVE(head, elm, type, field) do { \ - if (STAILQ_FIRST((head)) == (elm)) { \ - STAILQ_REMOVE_HEAD((head), field); \ - } \ - else { \ - struct type *curelm = STAILQ_FIRST((head)); \ - while (STAILQ_NEXT(curelm, field) != (elm)) \ - curelm = STAILQ_NEXT(curelm, field); \ - if ((STAILQ_NEXT(curelm, field) = \ - STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\ - (head)->stqh_last = &STAILQ_NEXT((curelm), field);\ - } \ -} while (0) - -#define STAILQ_REMOVE_HEAD(head, field) do { \ - if ((STAILQ_FIRST((head)) = \ - STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \ - if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -/* - * List declarations. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List functions. - */ - -#define LIST_EMPTY(head) ((head)->lh_first == NULL) - -#define LIST_FIRST(head) ((head)->lh_first) - -#define LIST_FOREACH(var, head, field) \ - for ((var) = LIST_FIRST((head)); \ - (var); \ - (var) = LIST_NEXT((var), field)) - -#define LIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = LIST_FIRST((head)); \ - (var) && ((tvar) = LIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define LIST_INIT(head) do { \ - LIST_FIRST((head)) = NULL; \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ - LIST_NEXT((listelm), field)->field.le_prev = \ - &LIST_NEXT((elm), field); \ - LIST_NEXT((listelm), field) = (elm); \ - (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - LIST_NEXT((elm), field) = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ - LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ - LIST_FIRST((head)) = (elm); \ - (elm)->field.le_prev = &LIST_FIRST((head)); \ -} while (0) - -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_REMOVE(elm, field) do { \ - if (LIST_NEXT((elm), field) != NULL) \ - LIST_NEXT((elm), field)->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = LIST_NEXT((elm), field); \ -} while (0) - -/* - * Tail queue declarations. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ - TRACEBUF \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ - TRACEBUF \ -} - -/* - * Tail queue functions. - */ -#define TAILQ_CONCAT(head1, head2, field) do { \ - if (!TAILQ_EMPTY(head2)) { \ - *(head1)->tqh_last = (head2)->tqh_first; \ - (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ - (head1)->tqh_last = (head2)->tqh_last; \ - TAILQ_INIT((head2)); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_HEAD(head2); \ - } \ -} while (0) - -#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) - -#define TAILQ_FIRST(head) ((head)->tqh_first) - -#define TAILQ_FOREACH(var, head, field) \ - for ((var) = TAILQ_FIRST((head)); \ - (var); \ - (var) = TAILQ_NEXT((var), field)) - -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = TAILQ_FIRST((head)); \ - (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var); \ - (var) = TAILQ_PREV((var), headname, field)) - -#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ - (var) = (tvar)) - -#define TAILQ_INIT(head) do { \ - TAILQ_FIRST((head)) = NULL; \ - (head)->tqh_last = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else { \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - } \ - TAILQ_NEXT((listelm), field) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&listelm->field); \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - TAILQ_NEXT((elm), field) = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&listelm->field); \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ - TAILQ_FIRST((head))->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - TAILQ_FIRST((head)) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - TAILQ_NEXT((elm), field) = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) - -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) - -#define TAILQ_REMOVE(head, elm, field) do { \ - if ((TAILQ_NEXT((elm), field)) != NULL) \ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else { \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - QMD_TRACE_HEAD(head); \ - } \ - *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ - TRASHIT((elm)->field.tqe_next); \ - TRASHIT((elm)->field.tqe_prev); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - - -#ifdef _KERNEL - -/* - * XXX insque() and remque() are an old way of handling certain queues. - * They bogusly assumes that all queue heads look alike. - */ - -struct quehead { - struct quehead *qh_link; - struct quehead *qh_rlink; -}; - -#if defined(__GNUC__) || defined(__INTEL_COMPILER) - -static __inline void -insque(void *a, void *b) -{ - struct quehead *element = (struct quehead *)a, - *head = (struct quehead *)b; - - element->qh_link = head->qh_link; - element->qh_rlink = head; - head->qh_link = element; - element->qh_link->qh_rlink = element; -} - -static __inline void -remque(void *a) -{ - struct quehead *element = (struct quehead *)a; - - element->qh_link->qh_rlink = element->qh_rlink; - element->qh_rlink->qh_link = element->qh_link; - element->qh_rlink = 0; -} - -#else /* !(__GNUC__ || __INTEL_COMPILER) */ - -void insque(void *a, void *b); -void remque(void *a); - -#endif /* __GNUC__ || __INTEL_COMPILER */ - -#endif /* _KERNEL */ - -#endif /* !_SYS_QUEUE_H_ */ diff --git a/miasm/jitter/vm_mngr.c b/miasm/jitter/vm_mngr.c deleted file mode 100644 index 9fe8ab65..00000000 --- a/miasm/jitter/vm_mngr.c +++ /dev/null @@ -1,1032 +0,0 @@ -/* -** Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net> -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License along -** with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include "vm_mngr.h" - -#include <inttypes.h> - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> - -#include "queue.h" - - - -/****************memory manager**************/ - - - - -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define MAX(a,b) (((a)>(b))?(a):(b)) - -// #define DEBUG_MIASM_AUTOMOD_CODE -#define MEMORY_ACCESS_LIST_INITIAL_COUNT 100 - -/* - To avoid alloc/free for each instruction access, the buffer is allocated here, - and is increased depending of program needs. - */ -void memory_access_list_init(struct memory_access_list * access) -{ - access->array = malloc(MEMORY_ACCESS_LIST_INITIAL_COUNT * sizeof(struct memory_access)); - if (access->array == NULL) { - fprintf(stderr, "cannot realloc struct memory_access access->array\n"); - exit(EXIT_FAILURE); - } - access->allocated = MEMORY_ACCESS_LIST_INITIAL_COUNT; - access->num = 0; -} - -void memory_access_list_reset(struct memory_access_list * access) -{ - access->num = 0; -} - -void memory_access_list_add(struct memory_access_list * access, uint64_t start, uint64_t stop) -{ - if (access->num >= access->allocated) { - if (access->allocated == 0) - access->allocated = 1; - else { - if (access->allocated >= SIZE_MAX / 2) { - fprintf(stderr, "Cannot alloc more pages\n"); - exit(EXIT_FAILURE); - } - access->allocated *= 2; - } - access->array = realloc(access->array, access->allocated * sizeof(struct memory_access)); - if (access->array == NULL) { - fprintf(stderr, "cannot realloc struct memory_access access->array\n"); - exit(EXIT_FAILURE); - } - } - access->array[access->num].start = start; - access->array[access->num].stop = stop; - access->num += 1; -} - - - -uint16_t set_endian16(vm_mngr_t* vm_mngr, uint16_t val) -{ - if (vm_mngr->sex == __BYTE_ORDER) - return val; - else - return Endian16_Swap(val); -} - -uint32_t set_endian32(vm_mngr_t* vm_mngr, uint32_t val) -{ - if (vm_mngr->sex == __BYTE_ORDER) - return val; - else - return Endian32_Swap(val); -} - -uint64_t set_endian64(vm_mngr_t* vm_mngr, uint64_t val) -{ - if (vm_mngr->sex == __BYTE_ORDER) - return val; - else - return Endian64_Swap(val); -} - -void print_val(uint64_t base, uint64_t addr) -{ - uint64_t *ptr = (uint64_t *) (intptr_t) addr; - fprintf(stderr, "addr 0x%"PRIX64" val 0x%"PRIX64"\n", addr-base, *ptr); -} - -int midpoint(int imin, int imax) -{ - return (imin + imax) / 2; -} - - -int find_page_node(struct memory_page_node * array, uint64_t key, int imin, int imax) -{ - // continue searching while [imin,imax] is not empty - while (imin <= imax) { - // calculate the midpoint for roughly equal partition - int imid = midpoint(imin, imax); - if(array[imid].ad <= key && key < array[imid].ad + array[imid].size) - // key found at index imid - return imid; - // determine which subarray to search - else if (array[imid].ad < key) - // change min index to search upper subarray - imin = imid + 1; - else - // change max index to search lower subarray - imax = imid - 1; - } - // key was not found - return -1; -} - -struct memory_page_node * get_memory_page_from_address(vm_mngr_t* vm_mngr, uint64_t ad, int raise_exception) -{ - struct memory_page_node * mpn; - int i; - - i = find_page_node(vm_mngr->memory_pages_array, - ad, - 0, - vm_mngr->memory_pages_number - 1); - if (i >= 0) { - mpn = &vm_mngr->memory_pages_array[i]; - if ((mpn->ad <= ad) && (ad < mpn->ad + mpn->size)) - return mpn; - } - if (raise_exception) { - fprintf(stderr, "WARNING: address 0x%"PRIX64" is not mapped in virtual memory:\n", ad); - vm_mngr->exception_flags |= EXCEPT_ACCESS_VIOL; - } - return NULL; -} - -static uint64_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; - struct memory_breakpoint_info * b; - - - mpn = get_memory_page_from_address(vm_mngr, ad, 1); - if (!mpn) - return 0; - - if ((mpn->access & PAGE_READ) == 0){ - fprintf(stderr, "access to non readable page!! %"PRIX64"\n", ad); - vm_mngr->exception_flags |= EXCEPT_ACCESS_VIOL; - return 0; - } - - /* check read breakpoint */ - LIST_FOREACH(b, &vm_mngr->memory_breakpoint_pool, next){ - if ((b->access & BREAKPOINT_READ) == 0) - continue; - if ((b->ad <= ad) && (ad < b->ad + b->size)) - vm_mngr->exception_flags |= EXCEPT_BREAKPOINT_MEMORY; - } - - - addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad]; - - /* read fits in a page */ - if (ad - mpn->ad + my_size/8 <= mpn->size){ - switch(my_size){ - case 8: - ret = *((unsigned char*)addr)&0xFF; - break; - case 16: - ret = *((unsigned short*)addr)&0xFFFF; - ret = set_endian16(vm_mngr, (uint16_t)ret); - break; - case 32: - ret = *((unsigned int*)addr)&0xFFFFFFFF; - ret = set_endian32(vm_mngr, (uint32_t)ret); - break; - case 64: - ret = *((uint64_t*)addr)&0xFFFFFFFFFFFFFFFFULL; - ret = set_endian64(vm_mngr, ret); - break; - default: - fprintf(stderr, "Bad memory access size %d\n", my_size); - exit(EXIT_FAILURE); - break; - } - } - /* read is multiple page wide */ - else{ - unsigned int new_size = my_size; - int index = 0; - while (new_size){ - mpn = get_memory_page_from_address(vm_mngr, ad, 1); - if (!mpn) - return 0; - addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad]; - ret |= ((uint64_t)(*((unsigned char*)addr)&0xFF))<<(index); - index +=8; - new_size -= 8; - ad ++; - } - switch(my_size){ - case 8: - break; - case 16: - ret = set_endian16(vm_mngr, (uint16_t)ret); - break; - case 32: - ret = set_endian32(vm_mngr, (uint32_t)ret); - break; - case 64: - ret = set_endian64(vm_mngr, ret); - break; - default: - fprintf(stderr, "Bad memory access size %d\n", my_size); - exit(EXIT_FAILURE); - break; - } - } - return ret; -} - -static void memory_page_write(vm_mngr_t* vm_mngr, unsigned int my_size, - uint64_t ad, uint64_t src) -{ - struct memory_page_node * mpn; - unsigned char * addr; - struct memory_breakpoint_info * b; - - mpn = get_memory_page_from_address(vm_mngr, ad, 1); - if (!mpn) - return; - - if ((mpn->access & PAGE_WRITE) == 0){ - fprintf(stderr, "access to non writable page!! %"PRIX64"\n", ad); - vm_mngr->exception_flags |= EXCEPT_ACCESS_VIOL; - return ; - } - - /* check read breakpoint*/ - LIST_FOREACH(b, &vm_mngr->memory_breakpoint_pool, next){ - if ((b->access & BREAKPOINT_WRITE) == 0) - continue; - if ((b->ad <= ad) && (ad < b->ad + b->size)) - vm_mngr->exception_flags |= EXCEPT_BREAKPOINT_MEMORY; - } - - addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad]; - - /* write fits in a page */ - if (ad - mpn->ad + my_size/8 <= mpn->size){ - switch(my_size){ - case 8: - *((unsigned char*)addr) = src&0xFF; - break; - case 16: - src = set_endian16(vm_mngr, (uint16_t)src); - *((unsigned short*)addr) = src&0xFFFF; - break; - case 32: - src = set_endian32(vm_mngr, (uint32_t)src); - *((unsigned int*)addr) = src&0xFFFFFFFF; - break; - case 64: - src = set_endian64(vm_mngr, src); - *((uint64_t*)addr) = src&0xFFFFFFFFFFFFFFFFULL; - break; - default: - fprintf(stderr, "Bad memory access size %d\n", my_size); - exit(EXIT_FAILURE); - break; - } - } - /* write is multiple page wide */ - else{ - switch(my_size){ - - case 8: - break; - case 16: - src = set_endian16(vm_mngr, (uint16_t)src); - break; - case 32: - src = set_endian32(vm_mngr, (uint32_t)src); - break; - case 64: - src = set_endian64(vm_mngr, src); - break; - default: - fprintf(stderr, "Bad memory access size %d\n", my_size); - exit(EXIT_FAILURE); - break; - } - while (my_size){ - mpn = get_memory_page_from_address(vm_mngr, ad, 1); - if (!mpn) - return; - - addr = &((unsigned char*)mpn->ad_hp)[ad - mpn->ad]; - *((unsigned char*)addr) = src&0xFF; - my_size -= 8; - src >>=8; - ad ++; - } - } -} - -// ################## - -void dump_code_bloc(vm_mngr_t* vm_mngr) -{ - struct code_bloc_node * cbp; - LIST_FOREACH(cbp, &vm_mngr->code_bloc_pool, next){ - fprintf(stderr, "%"PRIX64"%"PRIX64"\n", cbp->ad_start, cbp->ad_stop); - } - -} - -void add_range_to_list(struct memory_access_list * access, uint64_t addr1, uint64_t addr2) -{ - if (access->num > 0) { - /* Check match on upper bound */ - if (access->array[access->num-1].stop == addr1) { - access->array[access->num-1].stop = addr2; - return; - } - - /* Check match on lower bound */ - if (access->array[0].start == addr2) { - access->array[0].start = addr1; - return; - } - } - - /* No merge, add to the list */ - memory_access_list_add(access, addr1, addr2); -} - - -void add_mem_read(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t size) -{ - add_range_to_list(&(vm_mngr->memory_r), addr, addr + size); -} - -void add_mem_write(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t size) -{ - add_range_to_list(&(vm_mngr->memory_w), addr, addr + size); -} - -void check_invalid_code_blocs(vm_mngr_t* vm_mngr) -{ - size_t i; - struct code_bloc_node * cbp; - for (i=0;i<vm_mngr->memory_w.num; i++) { - if (vm_mngr->exception_flags & EXCEPT_CODE_AUTOMOD) - break; - if (vm_mngr->memory_w.array[i].stop <= vm_mngr->code_bloc_pool_ad_min || - vm_mngr->memory_w.array[i].start >=vm_mngr->code_bloc_pool_ad_max) - continue; - - LIST_FOREACH(cbp, &vm_mngr->code_bloc_pool, next){ - if ((cbp->ad_start < vm_mngr->memory_w.array[i].stop) && - (vm_mngr->memory_w.array[i].start < cbp->ad_stop)){ -#ifdef DEBUG_MIASM_AUTOMOD_CODE - fprintf(stderr, "**********************************\n"); - fprintf(stderr, "self modifying code %"PRIX64" %"PRIX64"\n", - vm_mngr->memory_w.array[i].start, - vm_mngr->memory_w.array[i].stop); - fprintf(stderr, "**********************************\n"); -#endif - vm_mngr->exception_flags |= EXCEPT_CODE_AUTOMOD; - break; - } - } - } -} - - -void check_memory_breakpoint(vm_mngr_t* vm_mngr) -{ - size_t i; - struct memory_breakpoint_info * memory_bp; - - /* Check memory breakpoints */ - LIST_FOREACH(memory_bp, &vm_mngr->memory_breakpoint_pool, next) { - if (vm_mngr->exception_flags & EXCEPT_BREAKPOINT_MEMORY) - break; - if (memory_bp->access & BREAKPOINT_READ) { - for (i=0;i<vm_mngr->memory_r.num; i++) { - if ((memory_bp->ad < vm_mngr->memory_r.array[i].stop) && - (vm_mngr->memory_r.array[i].start < memory_bp->ad + memory_bp->size)) { - vm_mngr->exception_flags |= EXCEPT_BREAKPOINT_MEMORY; - break; - } - } - } - if (memory_bp->access & BREAKPOINT_WRITE) { - for (i=0;i<vm_mngr->memory_w.num; i++) { - if ((memory_bp->ad < vm_mngr->memory_w.array[i].stop) && - (vm_mngr->memory_w.array[i].start < memory_bp->ad + memory_bp->size)) { - vm_mngr->exception_flags |= EXCEPT_BREAKPOINT_MEMORY; - break; - } - } - } - } -} - - -PyObject* get_memory_pylist(vm_mngr_t* vm_mngr, struct memory_access_list* memory_list) -{ - size_t i; - PyObject *pylist; - PyObject *range; - - pylist = PyList_New(memory_list->num); - for (i=0;i<memory_list->num;i++) { - range = PyTuple_New(2); - PyTuple_SetItem(range, 0, PyLong_FromUnsignedLongLong((uint64_t)memory_list->array[i].start)); - PyTuple_SetItem(range, 1, PyLong_FromUnsignedLongLong((uint64_t)memory_list->array[i].stop)); - PyList_SetItem(pylist, i, range); - } - return pylist; - -} - -PyObject* get_memory_read(vm_mngr_t* vm_mngr) -{ - return get_memory_pylist(vm_mngr, &vm_mngr->memory_r); -} - -PyObject* get_memory_write(vm_mngr_t* vm_mngr) -{ - return get_memory_pylist(vm_mngr, &vm_mngr->memory_w); -} - -void vm_MEM_WRITE_08(vm_mngr_t* vm_mngr, uint64_t addr, unsigned char src) -{ - add_mem_write(vm_mngr, addr, 1); - memory_page_write(vm_mngr, 8, addr, src); -} - -void vm_MEM_WRITE_16(vm_mngr_t* vm_mngr, uint64_t addr, unsigned short src) -{ - add_mem_write(vm_mngr, addr, 2); - memory_page_write(vm_mngr, 16, addr, src); -} -void vm_MEM_WRITE_32(vm_mngr_t* vm_mngr, uint64_t addr, unsigned int src) -{ - add_mem_write(vm_mngr, addr, 4); - memory_page_write(vm_mngr, 32, addr, src); -} -void vm_MEM_WRITE_64(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t src) -{ - add_mem_write(vm_mngr, addr, 8); - memory_page_write(vm_mngr, 64, addr, src); -} - -unsigned char vm_MEM_LOOKUP_08(vm_mngr_t* vm_mngr, uint64_t addr) -{ - unsigned char ret; - add_mem_read(vm_mngr, addr, 1); - ret = (unsigned char)memory_page_read(vm_mngr, 8, addr); - return ret; -} -unsigned short vm_MEM_LOOKUP_16(vm_mngr_t* vm_mngr, uint64_t addr) -{ - unsigned short ret; - add_mem_read(vm_mngr, addr, 2); - ret = (unsigned short)memory_page_read(vm_mngr, 16, addr); - return ret; -} -unsigned int vm_MEM_LOOKUP_32(vm_mngr_t* vm_mngr, uint64_t addr) -{ - unsigned int ret; - add_mem_read(vm_mngr, addr, 4); - ret = (unsigned int)memory_page_read(vm_mngr, 32, addr); - return ret; -} -uint64_t vm_MEM_LOOKUP_64(vm_mngr_t* vm_mngr, uint64_t addr) -{ - uint64_t ret; - add_mem_read(vm_mngr, addr, 8); - ret = memory_page_read(vm_mngr, 64, addr); - return ret; -} - - -int vm_read_mem(vm_mngr_t* vm_mngr, uint64_t addr, char** buffer_ptr, size_t size) -{ - char* buffer; - size_t len; - uint64_t addr_diff; - size_t addr_diff_st; - struct memory_page_node * mpn; - - buffer = malloc(size); - *buffer_ptr = buffer; - if (!buffer){ - fprintf(stderr, "Error: cannot alloc read\n"); - exit(EXIT_FAILURE); - } - - /* read is multiple page wide */ - while (size){ - mpn = get_memory_page_from_address(vm_mngr, addr, 1); - if (!mpn){ - free(*buffer_ptr); - PyErr_SetString(PyExc_RuntimeError, "Error: cannot find address"); - return -1; - } - - addr_diff = addr - mpn->ad; - if (addr_diff > SIZE_MAX) { - fprintf(stderr, "Size too big\n"); - exit(EXIT_FAILURE); - } - addr_diff_st = (size_t) addr_diff; - len = MIN(size, mpn->size - addr_diff_st); - memcpy(buffer, (char*)mpn->ad_hp + (addr_diff_st), len); - buffer += len; - addr += len; - size -= len; - } - - return 0; -} - - -/* - Try to read @size bytes from vm mmemory - Return the number of bytes consecutively read -*/ -uint64_t vm_read_mem_ret_buf(vm_mngr_t* vm_mngr, uint64_t addr, size_t size, char *buffer) -{ - size_t len; - uint64_t addr_diff; - uint64_t size_out; - size_t addr_diff_st; - - struct memory_page_node * mpn; - - size_out = 0; - /* read is multiple page wide */ - while (size){ - mpn = get_memory_page_from_address(vm_mngr, addr, 0); - if (!mpn){ - return size_out; - } - - addr_diff = addr - mpn->ad; - if (addr_diff > SIZE_MAX) { - fprintf(stderr, "Size too big\n"); - exit(EXIT_FAILURE); - } - addr_diff_st = (size_t) addr_diff; - len = MIN(size, mpn->size - addr_diff_st); - memcpy(buffer, (char*)mpn->ad_hp + (addr_diff_st), len); - buffer += len; - size_out += len; - addr += len; - size -= len; - } - - return size_out; -} - - -int vm_write_mem(vm_mngr_t* vm_mngr, uint64_t addr, char *buffer, size_t size) -{ - size_t len; - uint64_t addr_diff; - size_t addr_diff_st; - struct memory_page_node * mpn; - - if (size > SIZE_MAX) { - fprintf(stderr, "Write size wider than supported system\n"); - exit(EXIT_FAILURE); - } - - /* write is multiple page wide */ - while (size){ - mpn = get_memory_page_from_address(vm_mngr, addr, 1); - if (!mpn){ - PyErr_SetString(PyExc_RuntimeError, "Error: cannot find address"); - return -1; - } - - addr_diff = addr - mpn->ad; - if (addr_diff > SIZE_MAX) { - fprintf(stderr, "Size too big\n"); - exit(EXIT_FAILURE); - } - addr_diff_st = (size_t) addr_diff; - len = MIN(size, mpn->size - addr_diff_st); - memcpy((char*)mpn->ad_hp + addr_diff_st, buffer, len); - buffer += len; - addr += len; - size -= len; - } - - return 0; -} - - - -int is_mapped(vm_mngr_t* vm_mngr, uint64_t addr, size_t size) -{ - size_t len; - uint64_t addr_diff; - size_t addr_diff_st; - struct memory_page_node * mpn; - - if (size > SIZE_MAX) { - fprintf(stderr, "Test size wider than supported system\n"); - exit(EXIT_FAILURE); - } - - /* test multiple page wide */ - while (size){ - mpn = get_memory_page_from_address(vm_mngr, addr, 0); - if (!mpn) - return 0; - - addr_diff = addr - mpn->ad; - if (addr_diff > SIZE_MAX) { - fprintf(stderr, "Size too big\n"); - exit(EXIT_FAILURE); - } - addr_diff_st = (size_t) addr_diff; - len = MIN(size, mpn->size - addr_diff_st); - addr += len; - size -= len; - } - - return 1; -} - -struct memory_page_node * create_memory_page_node(uint64_t ad, size_t size, unsigned int access, const char *name) -{ - struct memory_page_node * mpn; - void* ad_hp; - - mpn = malloc(sizeof(*mpn)); - if (!mpn){ - fprintf(stderr, "Error: cannot alloc mpn\n"); - return NULL; - } - ad_hp = malloc(size); - if (!ad_hp){ - free(mpn); - fprintf(stderr, "Error: cannot alloc %zu\n", size); - return NULL; - } - mpn->name = malloc(strlen(name) + 1); - if (!mpn->name){ - free(mpn); - free(ad_hp); - fprintf(stderr, "Error: cannot alloc\n"); - return NULL; - } - - mpn->ad = ad; - mpn->size = size; - mpn->access = access; - mpn->ad_hp = ad_hp; - strcpy(mpn->name, name); - - return mpn; -} - - -struct code_bloc_node * create_code_bloc_node(uint64_t ad_start, uint64_t ad_stop) -{ - struct code_bloc_node * cbp; - - cbp = malloc(sizeof(*cbp)); - if (!cbp){ - fprintf(stderr, "Error: cannot alloc cbp\n"); - exit(EXIT_FAILURE); - } - - cbp->ad_start = ad_start; - cbp->ad_stop = ad_stop; - - return cbp; -} - - -void add_code_bloc(vm_mngr_t* vm_mngr, struct code_bloc_node* cbp) -{ - LIST_INSERT_HEAD(&vm_mngr->code_bloc_pool, cbp, next); - if (vm_mngr->code_bloc_pool_ad_min> cbp->ad_start) - vm_mngr->code_bloc_pool_ad_min = cbp->ad_start; - if (vm_mngr->code_bloc_pool_ad_max< cbp->ad_stop) - vm_mngr->code_bloc_pool_ad_max = cbp->ad_stop; -} - -void dump_code_bloc_pool(vm_mngr_t* vm_mngr) -{ - struct code_bloc_node * cbp; - - LIST_FOREACH(cbp, &vm_mngr->code_bloc_pool, next){ - printf("ad start %"PRIX64" ad_stop %"PRIX64"\n", - cbp->ad_start, - cbp->ad_stop); - } -} - - -void init_memory_page_pool(vm_mngr_t* vm_mngr) -{ - - vm_mngr->memory_pages_number = 0; - vm_mngr->memory_pages_array = NULL; -} - -void init_code_bloc_pool(vm_mngr_t* vm_mngr) -{ - LIST_INIT(&vm_mngr->code_bloc_pool); - vm_mngr->code_bloc_pool_ad_min = 0xffffffffffffffffULL; - vm_mngr->code_bloc_pool_ad_max = 0; - - memory_access_list_init(&(vm_mngr->memory_r)); - memory_access_list_init(&(vm_mngr->memory_w)); - - -} - -void init_memory_breakpoint(vm_mngr_t* vm_mngr) -{ - LIST_INIT(&vm_mngr->memory_breakpoint_pool); -} - - -void reset_memory_page_pool(vm_mngr_t* vm_mngr) -{ - struct memory_page_node * mpn; - int i; - for (i=0;i<vm_mngr->memory_pages_number; i++) { - mpn = &vm_mngr->memory_pages_array[i]; - free(mpn->ad_hp); - free(mpn->name); - } - free(vm_mngr->memory_pages_array); - vm_mngr->memory_pages_array = NULL; - vm_mngr->memory_pages_number = 0; -} - - -void reset_code_bloc_pool(vm_mngr_t* vm_mngr) -{ - struct code_bloc_node * cbp; - - - while (!LIST_EMPTY(&vm_mngr->code_bloc_pool)) { - cbp = LIST_FIRST(&vm_mngr->code_bloc_pool); - LIST_REMOVE(cbp, next); - free(cbp); - } - vm_mngr->code_bloc_pool_ad_min = 0xffffffffffffffffULL; - vm_mngr->code_bloc_pool_ad_max = 0; -} - -void reset_memory_access(vm_mngr_t* vm_mngr) -{ - memory_access_list_reset(&(vm_mngr->memory_r)); - memory_access_list_reset(&(vm_mngr->memory_w)); -} - -void reset_memory_breakpoint(vm_mngr_t* vm_mngr) -{ - struct memory_breakpoint_info * mpn; - - while (!LIST_EMPTY(&vm_mngr->memory_breakpoint_pool)) { - mpn = LIST_FIRST(&vm_mngr->memory_breakpoint_pool); - LIST_REMOVE(mpn, next); - free(mpn); - } - -} - - - -/* We don't use dichotomy here for the insertion */ -int is_mpn_in_tab(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a) -{ - struct memory_page_node * mpn; - int i; - - for (i=0;i<vm_mngr->memory_pages_number; i++) { - mpn = &vm_mngr->memory_pages_array[i]; - if (mpn->ad >= mpn_a->ad + mpn_a->size) - continue; - if (mpn->ad + mpn->size <= mpn_a->ad) - continue; - fprintf(stderr, - "Error: attempt to add page (0x%"PRIX64" 0x%"PRIX64") " - "overlapping page (0x%"PRIX64" 0x%"PRIX64")\n", - mpn_a->ad, mpn_a->ad + mpn_a->size, - mpn->ad, mpn->ad + mpn->size); - - return 1; - } - - return 0; -} - - -/* We don't use dichotomy here for the insertion */ -void add_memory_page(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a) -{ - struct memory_page_node * mpn; - int i; - - for (i=0; i < vm_mngr->memory_pages_number; i++) { - mpn = &vm_mngr->memory_pages_array[i]; - if (mpn->ad < mpn_a->ad) - continue; - break; - } - vm_mngr->memory_pages_array = realloc(vm_mngr->memory_pages_array, - sizeof(struct memory_page_node) * - (vm_mngr->memory_pages_number+1)); - if (vm_mngr->memory_pages_array == NULL) { - fprintf(stderr, "cannot realloc struct memory_page_node vm_mngr->memory_pages_array\n"); - exit(EXIT_FAILURE); - } - - - memmove(&vm_mngr->memory_pages_array[i+1], - &vm_mngr->memory_pages_array[i], - sizeof(struct memory_page_node) * (vm_mngr->memory_pages_number - i) - ); - - vm_mngr->memory_pages_array[i] = *mpn_a; - vm_mngr->memory_pages_number ++; -} - -void remove_memory_page(vm_mngr_t* vm_mngr, uint64_t ad) -{ - struct memory_page_node * mpn; - int i; - - i = find_page_node(vm_mngr->memory_pages_array, - ad, - 0, - vm_mngr->memory_pages_number - 1); - if (i < 0) { - return; - } - - mpn = &vm_mngr->memory_pages_array[i]; - free(mpn->name); - free(mpn->ad_hp); - memmove(&vm_mngr->memory_pages_array[i], - &vm_mngr->memory_pages_array[i+1], - sizeof(struct memory_page_node) * (vm_mngr->memory_pages_number - i - 1) - ); - vm_mngr->memory_pages_number --; - vm_mngr->memory_pages_array = realloc(vm_mngr->memory_pages_array, - sizeof(struct memory_page_node) * - (vm_mngr->memory_pages_number)); -} - -/* Return a char* representing the repr of vm_mngr_t object */ -char* dump(vm_mngr_t* vm_mngr) -{ - char buf[0x100]; - int length; - char *buf_final; - int i; - char buf_addr[0x20]; - char buf_size[0x20]; - struct memory_page_node * mpn; - /* 0x1234567812345678 0x1234567812345678 */ - char* intro = "Addr Size Access Comment\n"; - size_t total_len = strlen(intro) + 1; - - buf_final = malloc(total_len); - if (buf_final == NULL) { - fprintf(stderr, "Error: cannot alloc char* buf_final\n"); - exit(EXIT_FAILURE); - } - strcpy(buf_final, intro); - for (i=0; i< vm_mngr->memory_pages_number; i++) { - mpn = &vm_mngr->memory_pages_array[i]; - snprintf(buf_addr, sizeof(buf_addr), - "0x%"PRIX64, (uint64_t)mpn->ad); - snprintf(buf_size, sizeof(buf_size), - "0x%"PRIX64, (uint64_t)mpn->size); - - length = snprintf(buf, sizeof(buf) - 1, - "%-18s %-18s %c%c%c %s", - buf_addr, - buf_size, - mpn->access & PAGE_READ? 'R':'_', - mpn->access & PAGE_WRITE? 'W':'_', - mpn->access & PAGE_EXEC? 'X':'_', - mpn->name - ); - strcat(buf, "\n"); - total_len += length + 1 + 1; - buf_final = realloc(buf_final, total_len); - if (buf_final == NULL) { - fprintf(stderr, "cannot realloc char* buf_final\n"); - exit(EXIT_FAILURE); - } - strcat(buf_final, buf); - } - - return buf_final; -} - -void dump_memory_breakpoint_pool(vm_mngr_t* vm_mngr) -{ - struct memory_breakpoint_info * mpn; - - LIST_FOREACH(mpn, &vm_mngr->memory_breakpoint_pool, next){ - printf("ad %"PRIX64" size %"PRIX64" access %"PRIX64"\n", - mpn->ad, - mpn->size, - mpn->access - ); - } -} - - -void add_memory_breakpoint(vm_mngr_t* vm_mngr, uint64_t ad, uint64_t size, unsigned int access) -{ - struct memory_breakpoint_info * mpn_a; - mpn_a = malloc(sizeof(*mpn_a)); - if (!mpn_a) { - fprintf(stderr, "Error: cannot alloc\n"); - exit(EXIT_FAILURE); - } - mpn_a->ad = ad; - mpn_a->size = size; - mpn_a->access = access; - - LIST_INSERT_HEAD(&vm_mngr->memory_breakpoint_pool, mpn_a, next); - -} - -void remove_memory_breakpoint(vm_mngr_t* vm_mngr, uint64_t ad, unsigned int access) -{ - struct memory_breakpoint_info * mpn; - - LIST_FOREACH(mpn, &vm_mngr->memory_breakpoint_pool, next){ - if (mpn->ad == ad && mpn->access == access) - LIST_REMOVE(mpn, next); - } - -} - - -/********************************************/ - -void hexdump(char* m, unsigned int l) -{ - unsigned int i, j, last; - last = 0; - for (i=0;i<l;i++){ - if (!(i%0x10) && i){ - last = i; - printf(" "); - for (j=-0x10;j<0;j++){ - if (isprint(m[i+j])){ - printf("%c", m[i+j]); - } - else{ - printf("."); - } - } - printf("\n"); - } - printf("%.2X ", m[i]&0xFF); - } - l-=last; - if (l){ - for (j=i;j<last+0x10;j++) - printf(" "); - printf(" "); - for (j = 0;l;j++){ - if (isprint(m[last+j])){ - printf("%c", m[last+j]); - } - else{ - printf("."); - } - l--; - } - } - printf("\n"); - -} - - -// Return vm_mngr's exception flag value -_MIASM_EXPORT uint64_t get_exception_flag(vm_mngr_t* vm_mngr) -{ - return vm_mngr->exception_flags; -} diff --git a/miasm/jitter/vm_mngr.h b/miasm/jitter/vm_mngr.h deleted file mode 100644 index f7aea5b8..00000000 --- a/miasm/jitter/vm_mngr.h +++ /dev/null @@ -1,311 +0,0 @@ -/* -** Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net> -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License along -** with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#ifndef CODENAT_H -#define CODENAT_H - -#if defined(_WIN32) || defined(_WIN64) -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif -#endif - -#if _WIN32 -#define _MIASM_EXPORT __declspec(dllexport) -#else -#define _MIASM_EXPORT -#endif - -#include <Python.h> -#include <stdint.h> - -#include "queue.h" - -#ifdef __APPLE__ -#define __BYTE_ORDER __BYTE_ORDER__ -#define __BIG_ENDIAN BIG_ENDIAN -#define __LITTLE_ENDIAN LITTLE_ENDIAN -#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) -#define __BYTE_ORDER _BYTE_ORDER -#define __BIG_ENDIAN _BIG_ENDIAN -#define __LITTLE_ENDIAN _LITTLE_ENDIAN -#elif defined(_WIN32) || defined(_WIN64) -#define __BYTE_ORDER __LITTLE_ENDIAN -#define __BIG_ENDIAN '>' -#define __LITTLE_ENDIAN '<' -#elif defined(__ANDROID__) -#define __BYTE_ORDER __BYTE_ORDER__ -#define __LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ -#define __BIG_ENDIAN __ORDER_BIG_ENDIAN__ -#endif - - -#define Endian16_Swap(value) \ - ((((uint16_t)((value) & 0x00FF)) << 8) | \ - (((uint16_t)((value) & 0xFF00)) >> 8)) - -#define Endian32_Swap(value) \ - ((((uint32_t)((value) & 0x000000FF)) << 24) | \ - (((uint32_t)((value) & 0x0000FF00)) << 8) | \ - (((uint32_t)((value) & 0x00FF0000)) >> 8) | \ - (((uint32_t)((value) & 0xFF000000)) >> 24)) - -#define Endian64_Swap(value) \ - (((((uint64_t)value)<<56) & 0xFF00000000000000ULL) | \ - ((((uint64_t)value)<<40) & 0x00FF000000000000ULL) | \ - ((((uint64_t)value)<<24) & 0x0000FF0000000000ULL) | \ - ((((uint64_t)value)<< 8) & 0x000000FF00000000ULL) | \ - ((((uint64_t)value)>> 8) & 0x00000000FF000000ULL) | \ - ((((uint64_t)value)>>24) & 0x0000000000FF0000ULL) | \ - ((((uint64_t)value)>>40) & 0x000000000000FF00ULL) | \ - ((((uint64_t)value)>>56) & 0x00000000000000FFULL)) - - -LIST_HEAD(code_bloc_list_head, code_bloc_node); -LIST_HEAD(memory_breakpoint_info_head, memory_breakpoint_info); - - -#define BREAKPOINT_READ 1 -#define BREAKPOINT_WRITE 2 - -#define BREAK_SIGALARM 1<<5 - -#define MAX_MEMORY_PAGE_POOL_TAB 0x100000 -#define MEMORY_PAGE_POOL_MASK_BIT 12 -#define VM_BIG_ENDIAN 1 -#define VM_LITTLE_ENDIAN 2 - - -struct memory_page_node { - uint64_t ad; - size_t size; - uint64_t access; - void* ad_hp; - char* name; -}; - -struct memory_access { - uint64_t start; - uint64_t stop; -}; - -struct memory_access_list { - struct memory_access *array; - size_t allocated; - size_t num; -}; - -typedef struct { - int sex; - struct code_bloc_list_head code_bloc_pool; - struct memory_breakpoint_info_head memory_breakpoint_pool; - - int memory_pages_number; - struct memory_page_node* memory_pages_array; - - uint64_t code_bloc_pool_ad_min; - uint64_t code_bloc_pool_ad_max; - - uint64_t exception_flags; - uint64_t exception_flags_new; - PyObject *addr2obj; - - - struct memory_access_list memory_r; - struct memory_access_list memory_w; - - - int write_num; - -}vm_mngr_t; - - - -typedef struct { - PyObject *func; -}func_resolver; - - - - -//extern vm_mngr_t vmmngr; - -struct code_bloc_node { - uint64_t ad_start; - uint64_t ad_stop; - uint64_t ad_code; - LIST_ENTRY(code_bloc_node) next; -}; - - -struct memory_breakpoint_info { - uint64_t ad; - uint64_t size; - uint64_t access; - LIST_ENTRY(memory_breakpoint_info) next; -}; - - - -#define PAGE_READ 1 -#define PAGE_WRITE 2 -#define PAGE_EXEC 4 - -#define EXCEPT_DO_NOT_UPDATE_PC (1<<25) - -// interrupt with eip update after instr -#define EXCEPT_CODE_AUTOMOD (1<<0) -#define EXCEPT_SOFT_BP (1<<1) -#define EXCEPT_INT_XX (1<<2) - -#define EXCEPT_BREAKPOINT_MEMORY (1<<10) -// Deprecated -#define EXCEPT_BREAKPOINT_INTERN (EXCEPT_BREAKPOINT_MEMORY) - -#define EXCEPT_NUM_UPDT_EIP (1<<11) -// interrupt with eip at instr -#define EXCEPT_UNK_MEM_AD ((1<<12) | EXCEPT_DO_NOT_UPDATE_PC) -#define EXCEPT_THROW_SEH ((1<<13) | EXCEPT_DO_NOT_UPDATE_PC) -#define EXCEPT_UNK_EIP ((1<<14) | EXCEPT_DO_NOT_UPDATE_PC) -#define EXCEPT_ACCESS_VIOL ((1<<14) | EXCEPT_DO_NOT_UPDATE_PC) -#define EXCEPT_INT_DIV_BY_ZERO ((1<<16) | EXCEPT_DO_NOT_UPDATE_PC) -#define EXCEPT_PRIV_INSN ((1<<17) | EXCEPT_DO_NOT_UPDATE_PC) -#define EXCEPT_ILLEGAL_INSN ((1<<18) | EXCEPT_DO_NOT_UPDATE_PC) -#define EXCEPT_UNK_MNEMO ((1<<19) | EXCEPT_DO_NOT_UPDATE_PC) -#define EXCEPT_INT_1 ((1<<20) | EXCEPT_DO_NOT_UPDATE_PC) - - -int is_mem_mapped(vm_mngr_t* vm_mngr, uint64_t ad); -uint64_t get_mem_base_addr(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t *addr_base); -unsigned int MEM_LOOKUP(vm_mngr_t* vm_mngr, unsigned int my_size, uint64_t addr); - -int is_mapped(vm_mngr_t* vm_mngr, uint64_t addr, size_t size); -void vm_throw(vm_mngr_t* vm_mngr, unsigned long flags); - -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); - -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); - -void MEM_WRITE_08_PASSTHROUGH(uint64_t addr, unsigned char src); -void MEM_WRITE_16_PASSTHROUGH(uint64_t addr, unsigned short src); -void MEM_WRITE_32_PASSTHROUGH(uint64_t addr, unsigned int src); -void MEM_WRITE_64_PASSTHROUGH(uint64_t addr, uint64_t src); -unsigned char MEM_LOOKUP_08_PASSTHROUGH(uint64_t addr); -unsigned short MEM_LOOKUP_16_PASSTHROUGH(uint64_t addr); -unsigned int MEM_LOOKUP_32_PASSTHROUGH(uint64_t addr); -uint64_t MEM_LOOKUP_64_PASSTHROUGH(uint64_t addr); - -int vm_read_mem(vm_mngr_t* vm_mngr, uint64_t addr, char** buffer_ptr, size_t size); -int vm_write_mem(vm_mngr_t* vm_mngr, uint64_t addr, char *buffer, size_t size); - -void memory_access_list_init(struct memory_access_list * access); -void memory_access_list_reset(struct memory_access_list * access); -void memory_access_list_add(struct memory_access_list * access, uint64_t start, uint64_t stop); - -uint16_t set_endian16(vm_mngr_t* vm_mngr, uint16_t val); -uint32_t set_endian32(vm_mngr_t* vm_mngr, uint32_t val); -uint64_t set_endian64(vm_mngr_t* vm_mngr, uint64_t val); - - -void hexdump(char* m, unsigned int l); - -struct code_bloc_node * create_code_bloc_node(uint64_t ad_start, uint64_t ad_stop); -void add_code_bloc(vm_mngr_t* vm_mngr, struct code_bloc_node* cbp); - -struct memory_page_node * create_memory_page_node(uint64_t ad, size_t size, unsigned int access, const char *name);//memory_page* mp); -void init_memory_page_pool(vm_mngr_t* vm_mngr); -void init_code_bloc_pool(vm_mngr_t* vm_mngr); -void reset_memory_page_pool(vm_mngr_t* vm_mngr); -void reset_code_bloc_pool(vm_mngr_t* vm_mngr); -void dump_code_bloc_pool(vm_mngr_t* vm_mngr); -void add_memory_page(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a); -void remove_memory_page(vm_mngr_t* vm_mngr, uint64_t ad); - - -void init_memory_breakpoint(vm_mngr_t* vm_mngr); -void reset_memory_breakpoint(vm_mngr_t* vm_mngr); -void add_memory_breakpoint(vm_mngr_t* vm_mngr, uint64_t ad, uint64_t size, unsigned int access); -void remove_memory_breakpoint(vm_mngr_t* vm_mngr, uint64_t ad, unsigned int access); - -void add_memory_page(vm_mngr_t* vm_mngr, struct memory_page_node* mpn); - -void add_mem_read(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t size); -void add_mem_write(vm_mngr_t* vm_mngr, uint64_t addr, uint64_t size); -_MIASM_EXPORT void check_invalid_code_blocs(vm_mngr_t* vm_mngr); -_MIASM_EXPORT void check_memory_breakpoint(vm_mngr_t* vm_mngr); -_MIASM_EXPORT void reset_memory_access(vm_mngr_t* vm_mngr); -PyObject* get_memory_read(vm_mngr_t* vm_mngr); -PyObject* get_memory_write(vm_mngr_t* vm_mngr); - - -char* dump(vm_mngr_t* vm_mngr); -void dump_memory_breakpoint_pool(vm_mngr_t* vm_mngr); -PyObject* addr2BlocObj(vm_mngr_t* vm_mngr, uint64_t addr); - - - - -/********************************************/ -unsigned int get_memory_page_max_address(void); -unsigned int get_memory_page_max_user_address(void); - - -int is_mpn_in_tab(vm_mngr_t* vm_mngr, struct memory_page_node* mpn_a); - - -void _func_free(void); -void _func_alloc(void); -unsigned int _get_memory_page_max_address_py(void); -unsigned int _get_memory_page_max_user_address_py(void); -unsigned int _get_memory_page_from_min_ad_py(unsigned int size); - -void _func_malloc_memory_page(void); -void _func_free_memory_page(void); -void _func_virtualalloc_memory_page(void); -void _func_virtualfree_memory_page(void); -void _func_loadlib_fake(void); -void _func_getproc_fake(void); - - -void func_free(void); -void func_alloc(void); -unsigned int get_memory_page_max_address_py(void); -unsigned int get_memory_page_max_user_address_py(void); -unsigned int get_memory_page_from_min_ad_py(unsigned int size); -struct memory_page_node * get_memory_page_from_address(vm_mngr_t*, uint64_t ad, int raise_exception); -void func_malloc_memory_page(void); -void func_free_memory_page(void); -void func_virtualalloc_memory_page(void); -void func_virtualfree_memory_page(void); -void func_loadlib_fake(void); -void func_getproc_fake(void); - -unsigned int access_segment(unsigned int d); -unsigned int access_segment_ok(unsigned int d); - -unsigned int load_segment_limit(unsigned int d); -unsigned int load_segment_limit_ok(unsigned int d); - -unsigned int load_tr_segment_selector(unsigned int d); - -#endif diff --git a/miasm/jitter/vm_mngr_py.c b/miasm/jitter/vm_mngr_py.c deleted file mode 100644 index dd1bd9b1..00000000 --- a/miasm/jitter/vm_mngr_py.c +++ /dev/null @@ -1,1089 +0,0 @@ -/* -** Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net> -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License along -** with this program; if not, write to the Free Software Foundation, Inc., -** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include <Python.h> -#include "structmember.h" -#include <stdint.h> -#include <inttypes.h> -#include <signal.h> -#include "compat_py23.h" -#include "queue.h" -#include "vm_mngr.h" -#include "bn.h" -#include "vm_mngr_py.h" - -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define MAX(a,b) (((a)>(b))?(a):(b)) - -extern struct memory_page_list_head memory_page_pool; -extern struct code_bloc_list_head code_bloc_pool; - -#define RAISE(errtype, msg) {PyObject* p; p = PyErr_Format( errtype, msg ); return p;} - - - -/* XXX POC signals */ -VmMngr* global_vmmngr; - -PyObject* _vm_get_exception(unsigned int xcpt) -{ - PyObject*p; - - if (!xcpt) - p = NULL; - else if (xcpt & EXCEPT_CODE_AUTOMOD) - p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_CODE_AUTOMOD" ); - else if (xcpt & EXCEPT_UNK_EIP) - p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_UNK_EIP" ); - else if (xcpt & EXCEPT_UNK_MEM_AD) - p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_UNK_MEM_AD" ); - - else p = PyErr_Format( PyExc_RuntimeError, "EXCEPT_UNKNOWN" ); - return p; -} - -static void sig_alarm(int signo) -{ - global_vmmngr->vm_mngr.exception_flags |= BREAK_SIGALARM; - return; -} - -PyObject* set_alarm(VmMngr* self) -{ - global_vmmngr = self; - signal(SIGALRM, sig_alarm); - - Py_INCREF(Py_None); - return Py_None; -} - - - -PyObject* vm_add_memory_page(VmMngr* self, PyObject* args) -{ - PyObject *addr; - PyObject *access; - PyObject *item_str; - PyObject *name=NULL; - uint64_t buf_size; - size_t buf_size_st; - char* buf_data; - Py_ssize_t length; - uint64_t page_addr; - uint64_t page_access; - const char *name_ptr; - - struct memory_page_node * mpn; - - if (!PyArg_ParseTuple(args, "OOO|O", &addr, &access, &item_str, &name)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(addr, page_addr); - PyGetInt_uint64_t(access, page_access); - - if(!PyBytes_Check(item_str)) - RAISE(PyExc_TypeError,"arg must be bytes"); - - buf_size = PyBytes_Size(item_str); - PyBytes_AsStringAndSize(item_str, &buf_data, &length); - - if (name == NULL) { - name_ptr = (char*)""; - } else { - PyGetStr(name_ptr, name); - } - mpn = create_memory_page_node(page_addr, (size_t)buf_size, (unsigned int)page_access, name_ptr); - if (mpn == NULL) - RAISE(PyExc_TypeError,"cannot create page"); - if (is_mpn_in_tab(&self->vm_mngr, mpn)) { - free(mpn->ad_hp); - free(mpn); - RAISE(PyExc_TypeError,"known page in memory"); - } - - if (buf_size > SIZE_MAX) { - fprintf(stderr, "Size too big\n"); - exit(EXIT_FAILURE); - } - buf_size_st = (size_t) buf_size; - - memcpy(mpn->ad_hp, buf_data, buf_size_st); - add_memory_page(&self->vm_mngr, mpn); - - Py_INCREF(Py_None); - return Py_None; -} - - -PyObject* vm_remove_memory_page(VmMngr* self, PyObject* args) -{ - PyObject *addr; - uint64_t page_addr; - - if (!PyArg_ParseTuple(args, "O", &addr)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(addr, page_addr); - - remove_memory_page(&self->vm_mngr, page_addr); - - Py_INCREF(Py_None); - return Py_None; - - -} - -PyObject* vm_set_mem_access(VmMngr* self, PyObject* args) -{ - PyObject *addr; - PyObject *access; - uint64_t page_addr; - uint64_t page_access; - struct memory_page_node * mpn; - - if (!PyArg_ParseTuple(args, "OO", &addr, &access)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(addr, page_addr); - PyGetInt_uint64_t(access, page_access); - - mpn = get_memory_page_from_address(&self->vm_mngr, page_addr, 1); - if (!mpn){ - PyErr_SetString(PyExc_RuntimeError, "cannot find address"); - return 0; - } - - mpn->access = page_access; - - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* vm_set_mem(VmMngr* self, PyObject* args) -{ - PyObject *py_addr; - PyObject *py_buffer; - Py_ssize_t py_length; - - char * buffer; - Py_ssize_t pysize; - uint64_t addr; - int ret; - - if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_buffer)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(py_addr, addr); - - if (!PyBytes_Check(py_buffer)) - RAISE(PyExc_TypeError,"arg must be bytes"); - - pysize = PyBytes_Size(py_buffer); - if (pysize < 0) { - RAISE(PyExc_TypeError,"Python error"); - } - PyBytes_AsStringAndSize(py_buffer, &buffer, &py_length); - - ret = vm_write_mem(&self->vm_mngr, addr, buffer, pysize); - if (ret < 0) - RAISE(PyExc_TypeError, "Error in set_mem"); - - add_mem_write(&self->vm_mngr, addr, (size_t)pysize); - check_invalid_code_blocs(&self->vm_mngr); - - Py_INCREF(Py_None); - return Py_None; -} - - - -PyObject* vm_get_mem_access(VmMngr* self, PyObject* args) -{ - PyObject *py_addr; - uint64_t page_addr; - struct memory_page_node * mpn; - - if (!PyArg_ParseTuple(args, "O", &py_addr)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(py_addr, page_addr); - - mpn = get_memory_page_from_address(&self->vm_mngr, page_addr, 1); - if (!mpn){ - PyErr_SetString(PyExc_RuntimeError, "cannot find address"); - return 0; - } - - return PyLong_FromUnsignedLongLong((uint64_t)mpn->access); -} - -PyObject* vm_get_mem(VmMngr* self, PyObject* args) -{ - PyObject *py_addr; - PyObject *py_len; - - uint64_t addr; - uint64_t size; - size_t size_st; - PyObject *obj_out; - char * buf_out; - int ret; - - if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_len)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(py_addr, addr); - PyGetInt_uint64_t(py_len, size); - - if (size > SIZE_MAX) { - fprintf(stderr, "Size too big\n"); - exit(EXIT_FAILURE); - } - size_st = (size_t) size; - - ret = vm_read_mem(&self->vm_mngr, addr, &buf_out, size_st); - if (ret < 0) { - RAISE(PyExc_RuntimeError,"Cannot find address"); - } - - obj_out = PyBytes_FromStringAndSize(buf_out, size_st); - free(buf_out); - return obj_out; -} - -PyObject* vm_get_u8(VmMngr* self, PyObject* args) -{ - PyObject *py_addr; - - uint64_t addr; - PyObject *obj_out; - char * buf_out; - int ret; - uint32_t value; - - if (!PyArg_ParseTuple(args, "O", &py_addr)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(py_addr, addr); - - ret = vm_read_mem(&self->vm_mngr, addr, &buf_out, 1); - if (ret < 0) { - RAISE(PyExc_RuntimeError,"Cannot find address"); - } - - value = *(uint8_t*)buf_out; - - obj_out = PyLong_FromUnsignedLongLong(value); - free(buf_out); - return obj_out; -} - -PyObject* vm_get_u16(VmMngr* self, PyObject* args) -{ - PyObject *py_addr; - - uint64_t addr; - PyObject *obj_out; - char * buf_out; - int ret; - uint16_t value; - - if (!PyArg_ParseTuple(args, "O", &py_addr)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(py_addr, addr); - - ret = vm_read_mem(&self->vm_mngr, addr, &buf_out, 2); - if (ret < 0) { - RAISE(PyExc_RuntimeError,"Cannot find address"); - } - - value = set_endian16(&self->vm_mngr, *(uint16_t*)buf_out); - - obj_out = PyLong_FromUnsignedLongLong(value); - free(buf_out); - return obj_out; -} - -PyObject* vm_get_u32(VmMngr* self, PyObject* args) -{ - PyObject *py_addr; - - uint64_t addr; - PyObject *obj_out; - char * buf_out; - int ret; - uint32_t value; - - if (!PyArg_ParseTuple(args, "O", &py_addr)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(py_addr, addr); - - ret = vm_read_mem(&self->vm_mngr, addr, &buf_out, 4); - if (ret < 0) { - RAISE(PyExc_RuntimeError,"Cannot find address"); - } - - value = set_endian32(&self->vm_mngr, *(uint32_t*)buf_out); - - obj_out = PyLong_FromUnsignedLongLong(value); - free(buf_out); - return obj_out; -} - - -PyObject* vm_get_u64(VmMngr* self, PyObject* args) -{ - PyObject *py_addr; - - uint64_t addr; - PyObject *obj_out; - char * buf_out; - int ret; - uint64_t value; - - if (!PyArg_ParseTuple(args, "O", &py_addr)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(py_addr, addr); - - ret = vm_read_mem(&self->vm_mngr, addr, &buf_out, 8); - if (ret < 0) { - RAISE(PyExc_RuntimeError,"Cannot find address"); - } - - value = set_endian64(&self->vm_mngr, *(uint64_t*)buf_out); - - obj_out = PyLong_FromUnsignedLongLong(value); - free(buf_out); - return obj_out; -} - - -PyObject* vm_set_u8(VmMngr* self, PyObject* args) -{ - PyObject *py_addr; - PyObject *py_val; - uint8_t value; - uint64_t addr; - int ret; - - if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_val)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(py_addr, addr); - PyGetInt_uint8_t(py_val, value); - - ret = vm_write_mem(&self->vm_mngr, addr, (char*)&value, 1); - if (ret < 0) - RAISE(PyExc_TypeError, "Error in set_mem"); - - add_mem_write(&self->vm_mngr, addr, 1); - check_invalid_code_blocs(&self->vm_mngr); - - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* vm_set_u16(VmMngr* self, PyObject* args) -{ - PyObject *py_addr; - PyObject *py_val; - uint16_t value; - - uint64_t addr; - int ret; - - if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_val)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(py_addr, addr); - PyGetInt_uint16_t(py_val, value); - - value = set_endian16(&self->vm_mngr, value); - ret = vm_write_mem(&self->vm_mngr, addr, (char*)&value, 2); - if (ret < 0) - RAISE(PyExc_TypeError, "Error in set_mem"); - - add_mem_write(&self->vm_mngr, addr, 2); - check_invalid_code_blocs(&self->vm_mngr); - - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* vm_set_u32(VmMngr* self, PyObject* args) -{ - PyObject *py_addr; - PyObject *py_val; - uint32_t value; - uint64_t addr; - int ret; - - if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_val)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(py_addr, addr); - PyGetInt_uint32_t(py_val, value); - - value = set_endian32(&self->vm_mngr, value); - - ret = vm_write_mem(&self->vm_mngr, addr, (char*)&value, 4); - if (ret < 0) - RAISE(PyExc_TypeError, "Error in set_mem"); - - add_mem_write(&self->vm_mngr, addr, 4); - check_invalid_code_blocs(&self->vm_mngr); - - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* vm_set_u64(VmMngr* self, PyObject* args) -{ - PyObject *py_addr; - PyObject *py_val; - uint64_t value; - uint64_t addr; - int ret; - - if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_val)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(py_addr, addr); - PyGetInt_uint64_t(py_val, value); - - value = set_endian64(&self->vm_mngr, value); - - ret = vm_write_mem(&self->vm_mngr, addr, (char*)&value, 8); - if (ret < 0) - RAISE(PyExc_TypeError, "Error in set_mem"); - - add_mem_write(&self->vm_mngr, addr, 8); - check_invalid_code_blocs(&self->vm_mngr); - - Py_INCREF(Py_None); - return Py_None; -} - - - - - -PyObject* vm_add_memory_breakpoint(VmMngr* self, PyObject* args) -{ - PyObject *ad; - PyObject *size; - PyObject *access; - - uint64_t b_ad; - uint64_t b_size; - uint64_t b_access; - - if (!PyArg_ParseTuple(args, "OOO", &ad, &size, &access)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(ad, b_ad); - PyGetInt_uint64_t(size, b_size); - PyGetInt_uint64_t(access, b_access); - - add_memory_breakpoint(&self->vm_mngr, b_ad, b_size, (unsigned int)b_access); - - /* Raise exception in the following pattern: - - set_mem(XXX) - - add_memory_breakpoint(XXX) - -> Here, there is a pending breakpoint not raise - */ - check_memory_breakpoint(&self->vm_mngr); - - Py_INCREF(Py_None); - return Py_None; -} - - -PyObject* vm_remove_memory_breakpoint(VmMngr* self, PyObject* args) -{ - PyObject *ad; - PyObject *access; - uint64_t b_ad; - uint64_t b_access; - - if (!PyArg_ParseTuple(args, "OO", &ad, &access)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(ad, b_ad); - PyGetInt_uint64_t(access, b_access); - remove_memory_breakpoint(&self->vm_mngr, b_ad, (unsigned int)b_access); - - Py_INCREF(Py_None); - return Py_None; -} - - -PyObject* vm_set_exception(VmMngr* self, PyObject* args) -{ - PyObject *item1; - uint64_t exception_flags; - - if (!PyArg_ParseTuple(args, "O", &item1)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(item1, exception_flags); - - self->vm_mngr.exception_flags = exception_flags; - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* vm_get_exception(VmMngr* self, PyObject* args) -{ - return PyLong_FromUnsignedLongLong((uint64_t)self->vm_mngr.exception_flags); -} - - - - -PyObject* vm_init_memory_page_pool(VmMngr* self, PyObject* args) -{ - init_memory_page_pool(&self->vm_mngr); - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* vm_init_code_bloc_pool(VmMngr* self, PyObject* args) -{ - init_code_bloc_pool(&self->vm_mngr); - Py_INCREF(Py_None); - return Py_None; - -} - -PyObject* vm_init_memory_breakpoint(VmMngr* self, PyObject* args) -{ - init_memory_breakpoint(&self->vm_mngr); - Py_INCREF(Py_None); - return Py_None; - -} - -PyObject* vm_reset_memory_breakpoint(VmMngr* self, PyObject* args) -{ - reset_memory_breakpoint(&self->vm_mngr); - Py_INCREF(Py_None); - return Py_None; - -} - -PyObject* vm_reset_memory_access(VmMngr* self, PyObject* args) -{ - reset_memory_access(&self->vm_mngr); - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* py_add_mem_read(VmMngr* self, PyObject* args) -{ - PyObject *py_addr; - PyObject *py_size; - uint64_t addr; - uint64_t size; - - if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_size)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(py_addr, addr); - PyGetInt_uint64_t(py_size, size); - add_mem_read(&self->vm_mngr, addr, size); - Py_INCREF(Py_None); - return Py_None; - -} - -PyObject* py_add_mem_write(VmMngr* self, PyObject* args) -{ - PyObject *py_addr; - PyObject *py_size; - uint64_t addr; - uint64_t size; - - if (!PyArg_ParseTuple(args, "OO", &py_addr, &py_size)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(py_addr, addr); - PyGetInt_uint64_t(py_size, size); - add_mem_write(&self->vm_mngr, addr, size); - Py_INCREF(Py_None); - return Py_None; - -} - -PyObject* vm_check_invalid_code_blocs(VmMngr* self, PyObject* args) -{ - check_invalid_code_blocs(&self->vm_mngr); - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* vm_check_memory_breakpoint(VmMngr* self, PyObject* args) -{ - check_memory_breakpoint(&self->vm_mngr); - Py_INCREF(Py_None); - return Py_None; -} - -PyObject *vm_dump(PyObject* self) -{ - char* buf_final; - PyObject* ret_obj; - - buf_final = dump(&((VmMngr* )self)->vm_mngr); - ret_obj = PyUnicode_FromString(buf_final); - free(buf_final); - return ret_obj; -} - -PyObject* vm_dump_memory_breakpoint(VmMngr* self, PyObject* args) -{ - dump_memory_breakpoint_pool(&self->vm_mngr); - Py_INCREF(Py_None); - return Py_None; -} - - -PyObject* vm_get_all_memory(VmMngr* self, PyObject* args) -{ - PyObject *o; - struct memory_page_node * mpn; - PyObject *dict; - PyObject *dict2; - int i; - - - dict = PyDict_New(); - - for (i=0;i<self->vm_mngr.memory_pages_number; i++) { - mpn = &self->vm_mngr.memory_pages_array[i]; - - dict2 = PyDict_New(); - - o = PyBytes_FromStringAndSize(mpn->ad_hp, mpn->size); - PyDict_SetItemString(dict2, "data", o); - Py_DECREF(o); - - o = PyLong_FromLong((long)mpn->size); - PyDict_SetItemString(dict2, "size", o); - Py_DECREF(o); - - o = PyLong_FromLong((long)mpn->access); - PyDict_SetItemString(dict2, "access", o); - Py_DECREF(o); - - o = PyLong_FromUnsignedLongLong(mpn->ad); - PyDict_SetItem(dict, o, dict2); - Py_DECREF(o); - Py_DECREF(dict2); - } - return dict; -} - - -PyObject* vm_reset_memory_page_pool(VmMngr* self, PyObject* args) -{ - reset_memory_page_pool(&self->vm_mngr); - Py_INCREF(Py_None); - return Py_None; - -} - -PyObject* vm_reset_code_bloc_pool(VmMngr* self, PyObject* args) -{ - reset_code_bloc_pool(&self->vm_mngr); - Py_INCREF(Py_None); - return Py_None; - -} - - -PyObject* vm_add_code_bloc(VmMngr *self, PyObject *args) -{ - PyObject *item1; - PyObject *item2; - uint64_t ad_start, ad_stop, ad_code = 0; - - struct code_bloc_node * cbp; - - if (!PyArg_ParseTuple(args, "OO", &item1, &item2)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(item1, ad_start); - PyGetInt_uint64_t(item2, ad_stop); - - cbp = create_code_bloc_node(ad_start, ad_stop); - cbp->ad_start = ad_start; - cbp->ad_stop = ad_stop; - cbp->ad_code = ad_code; - add_code_bloc(&self->vm_mngr, cbp); - - Py_INCREF(Py_None); - return Py_None; -} - -PyObject* vm_dump_code_bloc_pool(VmMngr* self) -{ - dump_code_bloc_pool(&self->vm_mngr); - Py_INCREF(Py_None); - return Py_None; - -} - - - -PyObject* vm_is_mapped(VmMngr* self, PyObject* args) -{ - PyObject *ad; - PyObject *size; - uint64_t b_ad; - size_t b_size; - int ret; - - if (!PyArg_ParseTuple(args, "OO", &ad, &size)) - RAISE(PyExc_TypeError,"Cannot parse arguments"); - - PyGetInt_uint64_t(ad, b_ad); - PyGetInt_size_t(size, b_size); - ret = is_mapped(&self->vm_mngr, b_ad, b_size); - return PyLong_FromUnsignedLongLong((uint64_t)ret); -} - -PyObject* vm_get_memory_read(VmMngr* self, PyObject* args) -{ - PyObject* result; - result = get_memory_read(&self->vm_mngr); - Py_INCREF(result); - return result; -} - -PyObject* vm_get_memory_write(VmMngr* self, PyObject* args) -{ - PyObject* result; - result = get_memory_write(&self->vm_mngr); - Py_INCREF(result); - return result; -} - - - -static PyObject * -vm_set_big_endian(VmMngr *self, PyObject *value, void *closure) -{ - self->vm_mngr.sex = __BIG_ENDIAN; - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject * -vm_set_little_endian(VmMngr *self, PyObject *value, void *closure) -{ - self->vm_mngr.sex = __LITTLE_ENDIAN; - Py_INCREF(Py_None); - return Py_None; -} - - -static PyObject * -vm_is_little_endian(VmMngr *self, PyObject *value, void *closure) -{ - if (self->vm_mngr.sex == __BIG_ENDIAN) { - return PyLong_FromUnsignedLongLong(0); - } else { - return PyLong_FromUnsignedLongLong(1); - } -} - - -static void -VmMngr_dealloc(VmMngr* self) -{ - vm_reset_memory_page_pool(self, NULL); - vm_reset_code_bloc_pool(self, NULL); - vm_reset_memory_breakpoint(self, NULL); - Py_TYPE(self)->tp_free((PyObject*)self); -} - - -static PyObject * -VmMngr_new(PyTypeObject *type, PyObject *args, PyObject *kwds) -{ - VmMngr *self; - - self = (VmMngr *)type->tp_alloc(type, 0); - return (PyObject *)self; -} - -static PyObject * -VmMngr_get_vmmngr(VmMngr *self, void *closure) -{ - return PyLong_FromUnsignedLongLong((uint64_t)(intptr_t)&(self->vm_mngr)); -} - -static int -VmMngr_set_vmmngr(VmMngr *self, PyObject *value, void *closure) -{ - PyErr_SetString(PyExc_TypeError, "immutable vmmngr"); - return -1; -} - -static PyMemberDef VmMngr_members[] = { - {NULL} /* Sentinel */ -}; - -static PyMethodDef VmMngr_methods[] = { - {"init_memory_page_pool", (PyCFunction)vm_init_memory_page_pool, METH_VARARGS, - "init_memory_page_pool() -> Initialize the VmMngr memory"}, - {"init_memory_breakpoint", (PyCFunction)vm_init_memory_breakpoint, METH_VARARGS, - "init_memory_breakpoint() -> Initialize the VmMngr memory breakpoints"}, - {"init_code_bloc_pool",(PyCFunction)vm_init_code_bloc_pool, METH_VARARGS, - "init_code_bloc_pool() -> Initialize the VmMngr jitted code blocks"}, - {"set_mem_access", (PyCFunction)vm_set_mem_access, METH_VARARGS, - "set_mem_access(address, access) -> Change the protection of the page at @address with @access"}, - {"set_mem", (PyCFunction)vm_set_mem, METH_VARARGS, - "set_mem(address, data) -> Set a @data in memory at @address"}, - {"is_mapped", (PyCFunction)vm_is_mapped, METH_VARARGS, - "is_mapped(address, size) -> Check if the memory region at @address of @size bytes is fully mapped"}, - {"add_code_bloc",(PyCFunction)vm_add_code_bloc, METH_VARARGS, - "add_code_bloc(address_start, address_stop) -> Add a jitted code block between [@address_start, @address_stop["}, - {"get_mem_access", (PyCFunction)vm_get_mem_access, METH_VARARGS, - "get_mem_access(address) -> Retrieve the memory protection of the page at @address"}, - {"get_mem", (PyCFunction)vm_get_mem, METH_VARARGS, - "get_mem(addr, size) -> Get the memory content at @address of @size bytes"}, - - {"get_u8", (PyCFunction)vm_get_u8, METH_VARARGS, - "get_u8(addr) -> Get a u8 at @address of @size bytes (vm endianness)"}, - {"get_u16", (PyCFunction)vm_get_u16, METH_VARARGS, - "get_u16(addr) -> Get a u16 at @address of @size bytes (vm endianness)"}, - {"get_u32", (PyCFunction)vm_get_u32, METH_VARARGS, - "get_u32(addr) -> Get a u32 at @address of @size bytes (vm endianness)"}, - {"get_u64", (PyCFunction)vm_get_u64, METH_VARARGS, - "get_u64(addr) -> Get a u64 at @address of @size bytes (vm endianness)"}, - - - {"set_u8", (PyCFunction)vm_set_u8, METH_VARARGS, - "set_u8(addr, value) -> Set a u8 at @address of @size bytes (vm endianness)"}, - {"set_u16", (PyCFunction)vm_set_u16, METH_VARARGS, - "set_u16(addr, value) -> Set a u16 at @address of @size bytes (vm endianness)"}, - {"set_u32", (PyCFunction)vm_set_u32, METH_VARARGS, - "set_u32(addr, value) -> Set a u32 at @address of @size bytes (vm endianness)"}, - {"set_u64", (PyCFunction)vm_set_u64, METH_VARARGS, - "set_u64(addr, value) -> Set a u64 at @address of @size bytes (vm endianness)"}, - - {"add_memory_page",(PyCFunction)vm_add_memory_page, METH_VARARGS, - "add_memory_page(address, access, content [, cmt]) -> Maps a memory page at @address of len(@content) bytes containing @content with protection @access\n" - "@cmt is a comment linked to the memory page"}, - {"remove_memory_page",(PyCFunction)vm_remove_memory_page, METH_VARARGS, - "remove_memory_page(address) -> removes a previously allocated memory page at @address"}, - {"add_memory_breakpoint",(PyCFunction)vm_add_memory_breakpoint, METH_VARARGS, - "add_memory_breakpoint(address, size, access) -> Add a memory breakpoint at @address of @size bytes with @access type"}, - {"remove_memory_breakpoint",(PyCFunction)vm_remove_memory_breakpoint, METH_VARARGS, - "remove_memory_breakpoint(address, access) -> Remove a memory breakpoint at @address with @access type"}, - {"set_exception", (PyCFunction)vm_set_exception, METH_VARARGS, - "set_exception(exception) -> Set the VmMngr exception flags to @exception"}, - {"dump_memory_breakpoint", (PyCFunction)vm_dump_memory_breakpoint, METH_VARARGS, - "dump_memory_breakpoint() -> Lists each memory breakpoint"}, - {"get_all_memory",(PyCFunction)vm_get_all_memory, METH_VARARGS, - "get_all_memory() -> Returns a dictionary representing the VmMngr memory.\n" - "Keys are the addresses of each memory page.\n" - "Values are another dictionary containing page properties ('data', 'size', 'access')" - }, - {"reset_memory_page_pool", (PyCFunction)vm_reset_memory_page_pool, METH_VARARGS, - "reset_memory_page_pool() -> Remove all memory pages"}, - {"reset_memory_breakpoint", (PyCFunction)vm_reset_memory_breakpoint, METH_VARARGS, - "reset_memory_breakpoint() -> Remove all memory breakpoints"}, - {"reset_code_bloc_pool", (PyCFunction)vm_reset_code_bloc_pool, METH_VARARGS, - "reset_code_bloc_pool() -> Remove all jitted blocks"}, - {"set_alarm", (PyCFunction)set_alarm, METH_VARARGS, - "set_alarm() -> Force a timer based alarm during a code emulation"}, - {"get_exception",(PyCFunction)vm_get_exception, METH_VARARGS, - "get_exception() -> Returns the VmMngr exception flags"}, - {"set_big_endian",(PyCFunction)vm_set_big_endian, METH_VARARGS, - "set_big_endian() -> Set the VmMngr to Big Endian"}, - {"set_little_endian",(PyCFunction)vm_set_little_endian, METH_VARARGS, - "set_little_endian() -> Set the VmMngr to Little Endian"}, - {"is_little_endian",(PyCFunction)vm_is_little_endian, METH_VARARGS, - "is_little_endian() -> Return True if the VmMngr is Little Endian"}, - {"get_memory_read",(PyCFunction)vm_get_memory_read, METH_VARARGS, - "get_memory_read() -> Retrieve last instruction READ access\n" - "This function is only valid in a memory breakpoint callback." - }, - {"get_memory_write",(PyCFunction)vm_get_memory_write, METH_VARARGS, - "get_memory_write() -> Retrieve last instruction WRITE access\n" - "This function is only valid in a memory breakpoint callback." - }, - {"reset_memory_access",(PyCFunction)vm_reset_memory_access, METH_VARARGS, - "reset_memory_access() -> Reset last memory READ/WRITE"}, - {"add_mem_read",(PyCFunction)py_add_mem_read, METH_VARARGS, - "add_mem_read(address, size) -> Add a READ access at @address of @size bytes"}, - {"add_mem_write",(PyCFunction)py_add_mem_write, METH_VARARGS, - "add_mem_write(address, size) -> Add a WRITE access at @address of @size bytes"}, - {"check_invalid_code_blocs",(PyCFunction)vm_check_invalid_code_blocs, METH_VARARGS, - "check_invalid_code_blocs() -> Set the AUTOMOD flag in exception in case of automodified code"}, - {"check_memory_breakpoint",(PyCFunction)vm_check_memory_breakpoint, METH_VARARGS, - "check_memory_breakpoint() -> Set the BREAKPOINT_MEMORY flag in exception in case of memory breakpoint occurred"}, - - {NULL} /* Sentinel */ -}; - -static int -VmMngr_init(VmMngr *self, PyObject *args, PyObject *kwds) -{ - memset(&(self->vm_mngr), 0, sizeof(self->vm_mngr)); - return 0; -} - -static PyGetSetDef VmMngr_getseters[] = { - {"vmmngr", - (getter)VmMngr_get_vmmngr, (setter)VmMngr_set_vmmngr, - "vmmngr object", - NULL}, - {NULL} /* Sentinel */ -}; - -static PyTypeObject VmMngrType = { - PyVarObject_HEAD_INIT(NULL, 0) - "VmMngr", /*tp_name*/ - sizeof(VmMngr), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)VmMngr_dealloc,/*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - vm_dump, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash */ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - "VmMngr object", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - VmMngr_methods, /* tp_methods */ - VmMngr_members, /* tp_members */ - VmMngr_getseters, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)VmMngr_init, /* tp_init */ - 0, /* tp_alloc */ - VmMngr_new, /* tp_new */ -}; - -static PyMethodDef VmMngr_Methods[] = { - {NULL, NULL, 0, NULL} /* Sentinel */ - -}; - -char vm_mngr_mod_docs[] = "vm_mngr module."; -char vm_mngr_mod_name[] = "VmMngr"; - - -MOD_INIT(VmMngr) -{ - PyObject *module = NULL; - - MOD_DEF(module, "VmMngr", "vm_mngr module", VmMngr_Methods); - - if (module == NULL) - RET_MODULE; - - if (PyType_Ready(&VmMngrType) < 0) - RET_MODULE; - - Py_INCREF(&VmMngrType); - if (PyModule_AddObject(module, "Vm", (PyObject *)&VmMngrType) < 0) - RET_MODULE; - - RET_MODULE; -} - -bn_t PyLong_to_bn(PyObject* py_long) -{ - int j; - uint64_t tmp_mask; - PyObject* py_tmp; - PyObject* py_long_tmp; - PyObject* cst_32; - PyObject* cst_ffffffff; - bn_t bn; - - cst_ffffffff = PyLong_FromLong(0xffffffff); - cst_32 = PyLong_FromLong(32); - bn = bignum_from_int(0); - - for (j = 0; j < BN_BYTE_SIZE; j += 4) { - py_tmp = PyObject_CallMethod(py_long, "__and__", "O", cst_ffffffff); - py_long_tmp = PyObject_CallMethod(py_long, "__rshift__", "O", cst_32); - Py_DECREF(py_long); - py_long = py_long_tmp; - tmp_mask = PyLong_AsUnsignedLongLongMask(py_tmp); - Py_DECREF(py_tmp); - bn = bignum_or(bn, bignum_lshift(bignum_from_uint64(tmp_mask), 8 * j)); - } - - Py_DECREF(cst_32); - Py_DECREF(cst_ffffffff); - - return bn; -} - -PyObject* bn_to_PyLong(bn_t bn) -{ - int j; - PyObject* py_long; - PyObject* py_long_new; - PyObject* py_tmp; - PyObject* cst_32; - uint64_t tmp; - - py_long = PyLong_FromLong(0); - cst_32 = PyLong_FromLong(32); - - for (j = BN_BYTE_SIZE - 4; j >= 0 ; j -= 4) { - tmp = bignum_to_uint64(bignum_mask(bignum_rshift(bn, 8 * j), 32)); - py_tmp = PyLong_FromUnsignedLong((unsigned long)tmp); - py_long_new = PyObject_CallMethod(py_long, "__lshift__", "O", cst_32); - Py_DECREF(py_long); - py_long = PyObject_CallMethod(py_long_new, "__add__", "O", py_tmp); - Py_DECREF(py_long_new); - Py_DECREF(py_tmp); - } - - Py_DECREF(cst_32); - - return py_long; -} diff --git a/miasm/jitter/vm_mngr_py.h b/miasm/jitter/vm_mngr_py.h deleted file mode 100644 index a8f7dcd0..00000000 --- a/miasm/jitter/vm_mngr_py.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef VM_MNGR_PY_H -#define VM_MNGR_PY_H - -#ifdef _WIN32 -#define SIGALRM 0 -#endif - -typedef struct { - PyObject_HEAD - PyObject *vmmngr; - vm_mngr_t vm_mngr; -} VmMngr; - -#endif// VM_MNGR_PY_H - -bn_t PyLong_to_bn(PyObject* py_long); -PyObject* bn_to_PyLong(bn_t bn); |