all tests pass

This commit is contained in:
George Hotz 2019-03-23 14:04:41 -07:00
parent 8369d4b16d
commit a93145f9e6
6 changed files with 76 additions and 253 deletions

View File

@ -59,3 +59,6 @@ def test():
ret = t.fetch_memory(0, 0xf6fff080, 0x10)
"""
if __name__ == "__main__":
test()

View File

@ -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;

View File

@ -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)

View File

@ -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, &register_size, &register_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);
}
}

View File

@ -0,0 +1 @@
from qiradb import PyTrace

View File

@ -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