diff --git a/qira_tests/test_qiradb.py b/qira_tests/test_qiradb.py index 888c2533..9a530955 100644 --- a/qira_tests/test_qiradb.py +++ b/qira_tests/test_qiradb.py @@ -59,3 +59,6 @@ def test(): ret = t.fetch_memory(0, 0xf6fff080, 0x10) """ +if __name__ == "__main__": + test() + diff --git a/qiradb/qiradb/Trace/Trace.cpp b/qiradb/qiradb/Trace/Trace.cpp index 573b06b4..8f153378 100644 --- a/qiradb/qiradb/Trace/Trace.cpp +++ b/qiradb/qiradb/Trace/Trace.cpp @@ -143,10 +143,16 @@ bool Trace::ConnectToFileAndStart(char *filename, unsigned int trace_index, int fd_ = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); #else fd_ = open(filename, O_RDONLY); - if (fd_ <= 0) return false; + if (fd_ == -1) { + printf("ERROR: file open failed\n"); + return false; + } #endif - if (!remap_backing(sizeof(struct change))) return false; + if (!remap_backing(sizeof(struct change))) { + printf("ERROR: remap backing failed\n"); + return false; + } THREAD_CREATE(thread, thread_entry, this); return true; diff --git a/qiradb/qiradb/Trace/Trace.pxd b/qiradb/qiradb/Trace/Trace.pxd index 695261e1..044ced99 100644 --- a/qiradb/qiradb/Trace/Trace.pxd +++ b/qiradb/qiradb/Trace/Trace.pxd @@ -1,15 +1,36 @@ -from libc.stdint cimport uint32_t +# distutils: language = c++ + +from libc.stdint cimport uint32_t, uint64_t, uint16_t from libcpp cimport bool +from libcpp.map cimport map +from libcpp.vector cimport vector cdef extern from "Trace.cpp": pass cdef extern from "Trace.h": ctypedef uint32_t Clnum; + ctypedef uint64_t Address; + ctypedef uint16_t MemoryWithValid; + + cdef struct change: + Address address + uint64_t data + Clnum clnum + uint32_t flags cdef cppclass Trace: Trace() bool ConnectToFileAndStart(char *filename, unsigned int trace_index, int register_size, int register_count, bool is_big_endian) Clnum GetMaxClnum() Clnum GetMinClnum() + bool GetDidUpdate() + + map[Address, char] GetPages() + vector[Clnum] FetchClnumsByAddressAndType(Address, char, Clnum, Clnum, unsigned int) + vector[uint64_t] FetchRegisters(Clnum clnum) + vector[MemoryWithValid] FetchMemory(Clnum clnum, Address address, int len) + vector[change] FetchChangesByClnum(Clnum clnum, unsigned int limit) + + char get_type_from_flags(uint32_t flags) diff --git a/qiradb/qiradb/Trace/_qiradb.cpp b/qiradb/qiradb/Trace/_qiradb.cpp deleted file mode 100644 index 93a376f3..00000000 --- a/qiradb/qiradb/Trace/_qiradb.cpp +++ /dev/null @@ -1,235 +0,0 @@ -#include -#include -#include "Trace.h" - -#define FE(z,x,y) for (z y = x.begin(); y != x.end(); ++y) - -extern "C" { - -typedef struct { - PyObject_HEAD - Trace *t; -} PyTrace; - -static int Trace_init(PyTrace *self, PyObject *args, PyObject *kwds) { - char *filename; - int register_size, register_count; - unsigned int ti; - int is_big_endian; - if (!PyArg_ParseTuple(args, "sIiii", &filename, &ti, ®ister_size, ®ister_count, &is_big_endian)) { return -1; } - Trace *t = new Trace(ti); - if (!t->ConnectToFileAndStart(filename, register_size, register_count, is_big_endian!=0)) { delete t; return -1; } - self->t = t; - return 0; -} - -static void Trace_dealloc(PyTrace *self) { - if (self->t != NULL) { delete self->t; } - self->ob_type->tp_free((PyObject*)self); -} - -static PyObject *get_maxclnum(PyTrace *self) { - if (self->t == NULL) { return NULL; } - return Py_BuildValue("I", self->t->GetMaxClnum()); -} - -static PyObject *get_minclnum(PyTrace *self) { - if (self->t == NULL) { return NULL; } - return Py_BuildValue("I", self->t->GetMinClnum()); -} - -static PyObject *did_update(PyTrace *self) { - if (self->t == NULL) { return NULL; } - if (self->t->GetDidUpdate()) { - Py_INCREF(Py_True); - return Py_True; - } else { - Py_INCREF(Py_False); - return Py_False; - } -} - -static PyObject *fetch_clnums_by_address_and_type(PyTrace *self, PyObject *args) { - Address address; - char type; - Clnum start_clnum, end_clnum; - unsigned int limit; - if (!PyArg_ParseTuple(args, "KcIII", &address, &type, &start_clnum, &end_clnum, &limit)) { return NULL; } - if (self->t == NULL) { return NULL; } - - vector ret = self->t->FetchClnumsByAddressAndType(address, type, start_clnum, end_clnum, limit); - - PyObject *pyret = PyList_New(ret.size()); - int i = 0; - FE(vector::iterator, ret, it) { - PyList_SetItem(pyret, i++, Py_BuildValue("I", *it)); - } - return pyret; -} - -static PyObject *fetch_changes_by_clnum(PyTrace *self, PyObject *args) { - static PyObject *pystr_address = Py_BuildValue("s", "address"); - static PyObject *pystr_data = Py_BuildValue("s", "data"); - static PyObject *pystr_clnum = Py_BuildValue("s", "clnum"); - static PyObject *pystr_type = Py_BuildValue("s", "type"); - static PyObject *pystr_size = Py_BuildValue("s", "size"); - - Clnum clnum; - unsigned int limit; - if (!PyArg_ParseTuple(args, "II", &clnum, &limit)) { return NULL; } - if (self->t == NULL) { return NULL; } - - vector ret = self->t->FetchChangesByClnum(clnum, limit); - - PyObject *pyret = PyList_New(ret.size()); - int i = 0; - FE(vector::iterator, ret, it) { - // copied (address, data, clnum, flags) from qira_log.py, but type instead of flags - PyObject *iit = PyDict_New(); - PyObject *py_address = Py_BuildValue("K", it->address); - PyObject *py_data = Py_BuildValue("K", it->data); - PyObject *py_clnum = Py_BuildValue("I", it->clnum); - PyObject *py_type = Py_BuildValue("c", Trace::get_type_from_flags(it->flags)); - PyObject *py_size = Py_BuildValue("I", it->flags & SIZE_MASK); - PyDict_SetItem(iit, pystr_address, py_address); - PyDict_SetItem(iit, pystr_data, py_data); - PyDict_SetItem(iit, pystr_clnum, py_clnum); - PyDict_SetItem(iit, pystr_type, py_type); - PyDict_SetItem(iit, pystr_size, py_size); - Py_DECREF(py_address); - Py_DECREF(py_data); - Py_DECREF(py_clnum); - Py_DECREF(py_type); - Py_DECREF(py_size); - PyList_SetItem(pyret, i++, iit); - } - return pyret; -} - -static PyObject *fetch_memory(PyTrace *self, PyObject *args) { - Clnum clnum; - Address address; - int len; - if (!PyArg_ParseTuple(args, "IKi", &clnum, &address, &len)) { return NULL; } - if (self->t == NULL) { return NULL; } - - vector ret = self->t->FetchMemory(clnum, address, len); - - PyObject *pyret = PyList_New(ret.size()); - int i = 0; - FE(vector::iterator, ret, it) { - PyList_SetItem(pyret, i++, Py_BuildValue("I", *it)); - } - - return pyret; -} - -static PyObject *fetch_registers(PyTrace *self, PyObject *args) { - Clnum clnum; - if (!PyArg_ParseTuple(args, "I", &clnum)) { return NULL; } - if (self->t == NULL) { return NULL; } - - vector ret = self->t->FetchRegisters(clnum); - - PyObject *pyret = PyList_New(ret.size()); - int i = 0; - FE(vector::iterator, ret, it) { - PyList_SetItem(pyret, i++, Py_BuildValue("K", *it)); - } - return pyret; -} - -static PyObject *get_pmaps(PyTrace *self, PyObject *args) { - static PyObject *pystr_instruction = Py_BuildValue("s", "instruction"); - static PyObject *pystr_memory = Py_BuildValue("s", "memory"); - static PyObject *pystr_romemory = Py_BuildValue("s", "romemory"); - - if (self->t == NULL) { return NULL; } - map p = self->t->GetPages(); - PyObject *iit = PyDict_New(); - // no comma allowed in the template - typedef map::iterator p_iter; - FE(p_iter, p, it) { - // eww these strings are long - PyObject *py_addr = Py_BuildValue("K", it->first); - if (it->second & PAGE_INSTRUCTION) { - PyDict_SetItem(iit, py_addr, pystr_instruction); - } else if (it->second & PAGE_WRITE) { - PyDict_SetItem(iit, py_addr, pystr_memory); - } else if (it->second & PAGE_READ) { - PyDict_SetItem(iit, py_addr, pystr_romemory); - } - Py_DECREF(py_addr); - } - return iit; -} - - -// python stuff follows - -static PyMethodDef Trace_methods[] = { - { "get_maxclnum", (PyCFunction)get_maxclnum, METH_NOARGS, NULL }, - { "get_minclnum", (PyCFunction)get_minclnum, METH_NOARGS, NULL }, - { "get_pmaps", (PyCFunction)get_pmaps, METH_NOARGS, NULL }, - { "did_update", (PyCFunction)did_update, METH_NOARGS, NULL }, - { "fetch_clnums_by_address_and_type", (PyCFunction)fetch_clnums_by_address_and_type, METH_VARARGS, NULL }, - { "fetch_changes_by_clnum", (PyCFunction)fetch_changes_by_clnum, METH_VARARGS, NULL }, - { "fetch_memory", (PyCFunction)fetch_memory, METH_VARARGS, NULL }, - { "fetch_registers", (PyCFunction)fetch_registers, METH_VARARGS, NULL }, - { NULL, NULL, 0, NULL } -}; - -static PyMethodDef Methods[] = { {NULL} }; - -static PyTypeObject qiradb_TraceType = { - PyObject_HEAD_INIT(NULL) - 0, /*ob_size*/ - "qiradb_Trace", /*tp_name*/ - sizeof(PyTrace), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - (destructor)Trace_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, /*tp_flags*/ - "Trace object", /* tp_doc */ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - Trace_methods, /* tp_methods */ - 0, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)Trace_init, /* tp_init */ -}; - -void init_qiradb(void) { - PyObject* m; - qiradb_TraceType.tp_new = PyType_GenericNew; - if (PyType_Ready(&qiradb_TraceType) < 0) return; - m = Py_InitModule("_qiradb", Methods); - if (m == NULL) return; - Py_INCREF(&qiradb_TraceType); - PyModule_AddObject(m, "Trace", (PyObject *)&qiradb_TraceType); -} - -} - diff --git a/qiradb/qiradb/__init__.py b/qiradb/qiradb/__init__.py index e69de29b..7ee25f90 100644 --- a/qiradb/qiradb/__init__.py +++ b/qiradb/qiradb/__init__.py @@ -0,0 +1 @@ +from qiradb import PyTrace diff --git a/qiradb/qiradb/qiradb.pyx b/qiradb/qiradb/qiradb.pyx index e2ce0702..d22fd3b2 100644 --- a/qiradb/qiradb/qiradb.pyx +++ b/qiradb/qiradb/qiradb.pyx @@ -1,27 +1,19 @@ # distutils: language = c++ -""" -static PyMethodDef Trace_methods[] = { - { "get_maxclnum", (PyCFunction)get_maxclnum, METH_NOARGS, NULL }, - { "get_minclnum", (PyCFunction)get_minclnum, METH_NOARGS, NULL }, - { "get_pmaps", (PyCFunction)get_pmaps, METH_NOARGS, NULL }, - { "did_update", (PyCFunction)did_update, METH_NOARGS, NULL }, - { "fetch_clnums_by_address_and_type", (PyCFunction)fetch_clnums_by_address_and_type, METH_VARARGS, NULL }, - { "fetch_changes_by_clnum", (PyCFunction)fetch_changes_by_clnum, METH_VARARGS, NULL }, - { "fetch_memory", (PyCFunction)fetch_memory, METH_VARARGS, NULL }, - { "fetch_registers", (PyCFunction)fetch_registers, METH_VARARGS, NULL }, - { NULL, NULL, 0, NULL } -}; -""" - from Trace.Trace cimport Trace +# copied from Trace.h +SIZE_MASK = 0xFF +PAGE_INSTRUCTION = 1 +PAGE_READ = 2 +PAGE_WRITE = 4 + cdef class PyTrace: cdef Trace t def __cinit__(self, filename, trace_index, register_size, register_count, is_big_endian): self.t = Trace() - self.t.ConnectToFileAndStart(filename, trace_index, register_size, register_count, is_big_endian) + assert self.t.ConnectToFileAndStart(filename, trace_index, register_size, register_count, is_big_endian !=0 ) def get_maxclnum(self): return self.t.GetMaxClnum() @@ -29,4 +21,39 @@ cdef class PyTrace: def get_minclnum(self): return self.t.GetMinClnum() + def did_update(self): + return self.t.GetDidUpdate() + + def get_pmaps(self): + ret = {} + pagemap = self.t.GetPages() + for address,ttype in pagemap: + if ttype == PAGE_INSTRUCTION: + ret[address] = "instruction" + elif ttype == PAGE_WRITE: + ret[address] = "memory" + elif ttype == PAGE_READ: + ret[address] = "romemory" + return ret + + def fetch_clnums_by_address_and_type(self, address, ttype, start_clnum, end_clnum, limit): + return self.t.FetchClnumsByAddressAndType(address, ord(ttype), start_clnum, end_clnum, limit) + + def fetch_registers(self, clnum): + return self.t.FetchRegisters(clnum) + + def fetch_memory(self, clnum, address, llen): + return self.t.FetchMemory(clnum, address, llen) + + def fetch_changes_by_clnum(self, clnum, limit): + ret = [] + its = self.t.FetchChangesByClnum(clnum, limit) + for it in its: + tl = {"address": it.address, + "data": it.data, + "clnum": it.clnum, + "type": self.t.get_type_from_flags(it.flags), + "size": it.flags & SIZE_MASK} + ret.append(tl) + return ret