mirror of https://github.com/geohot/qira
all tests pass
This commit is contained in:
parent
8369d4b16d
commit
a93145f9e6
|
@ -59,3 +59,6 @@ def test():
|
|||
ret = t.fetch_memory(0, 0xf6fff080, 0x10)
|
||||
"""
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -1,235 +0,0 @@
|
|||
#include <Python.h>
|
||||
#include <structmember.h>
|
||||
#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<Clnum> ret = self->t->FetchClnumsByAddressAndType(address, type, start_clnum, end_clnum, limit);
|
||||
|
||||
PyObject *pyret = PyList_New(ret.size());
|
||||
int i = 0;
|
||||
FE(vector<Clnum>::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<struct change> ret = self->t->FetchChangesByClnum(clnum, limit);
|
||||
|
||||
PyObject *pyret = PyList_New(ret.size());
|
||||
int i = 0;
|
||||
FE(vector<struct change>::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<MemoryWithValid> ret = self->t->FetchMemory(clnum, address, len);
|
||||
|
||||
PyObject *pyret = PyList_New(ret.size());
|
||||
int i = 0;
|
||||
FE(vector<MemoryWithValid>::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<uint64_t> ret = self->t->FetchRegisters(clnum);
|
||||
|
||||
PyObject *pyret = PyList_New(ret.size());
|
||||
int i = 0;
|
||||
FE(vector<uint64_t>::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<Address, char> p = self->t->GetPages();
|
||||
PyObject *iit = PyDict_New();
|
||||
// no comma allowed in the template
|
||||
typedef map<Address, char>::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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
from qiradb import PyTrace
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue