Skip to content

Commit

Permalink
added support for IRDirty IRStmts
Browse files Browse the repository at this point in the history
  • Loading branch information
zardus committed Sep 18, 2013
1 parent 4c43384 commit 430b82a
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 5 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Awesome stuff!
- there is no memory management. VEX is kind of weird with this, so care will have to be taken...
- converting from string to tag is currently very slow (a hastily written consecutive bunch of strcmps)
- IRCallee assumes that addresses are 64-bytes long, and will corrupt memory otherwise. This can be fixed by writing a getter/setter instead of using the macroed ones.
- CCalls are created by passing in IRCallee and manually building the args list, instead of by calling the helper functions. Not sure if this is good or bad.
- CCalls are created by creating the IRCallee and manually building the args list, instead of by calling the helper functions. Not sure if this is good or bad. On the other hand, Dirty statements are created through helper functions.
- deepCopying a binder IRExpr seems to crash VEX
- IRDirty's fxState array access is untested
- equality (for those things that easily have it) should be implemented as a rich comparator
1 change: 1 addition & 0 deletions pyvex.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ initpyvex(void)
PYVEX_INITSUBTYPE(IRStmt, CAS);
PYVEX_INITSUBTYPE(IRStmt, LLSC);
PYVEX_INITSUBTYPE(IRStmt, MBE);
PYVEX_INITSUBTYPE(IRStmt, Dirty);
PYVEX_INITSUBTYPE(IRStmt, Exit);

// expressions
Expand Down
28 changes: 28 additions & 0 deletions pyvex_enums.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,34 @@ IRMBusEvent str_to_IRMBusEvent(const char *s)
return -1;
}

////////////////////////////
// IREffect translator //
////////////////////////////

const char *IREffect_to_str(IREffect t)
{
switch (t)
{
PYVEX_ENUMCONV_TOSTRCASE(Ifx_None)
PYVEX_ENUMCONV_TOSTRCASE(Ifx_Read)
PYVEX_ENUMCONV_TOSTRCASE(Ifx_Write)
PYVEX_ENUMCONV_TOSTRCASE(Ifx_Modify)
default:
fprintf(stderr, "PyVEX: Unknown IREffect");
return NULL;
}
}

IREffect str_to_IREffect(const char *s)
{
PYVEX_ENUMCONV_FROMSTR(Ifx_None)
PYVEX_ENUMCONV_FROMSTR(Ifx_Read)
PYVEX_ENUMCONV_FROMSTR(Ifx_Write)
PYVEX_ENUMCONV_FROMSTR(Ifx_Modify)

return -1;
}

///////////////////////////
// IRJumpKind translator //
///////////////////////////
Expand Down
4 changes: 4 additions & 0 deletions pyvex_enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ IREndness str_to_IREndness(const char *);
const char *IRMBusEvent_to_str(IRMBusEvent);
IRMBusEvent str_to_IRMBusEvent(const char *);

// ireffect
const char *IREffect_to_str(IREffect);
IREffect str_to_IREffect(const char *);

// jump kind
const char *IRJumpKind_to_str(IRJumpKind);
IRJumpKind str_to_IRJumpKind(const char *);
Expand Down
4 changes: 1 addition & 3 deletions pyvex_irexpr.c
Original file line number Diff line number Diff line change
Expand Up @@ -544,14 +544,12 @@ pyIRExprCCall_init(pyIRExpr *self, PyObject *args, PyObject *kwargs)
self->wrapped = IRExpr_CCall(callee->wrapped, ret_type, cargs);
return 0;
}

PYVEX_ACCESSOR_WRAPPED(IRExprCCall, IRExpr, wrapped->Iex.CCall.cee, callee, IRCallee)
PYVEX_ACCESSOR_ENUM(IRExprCCall, IRExpr, wrapped->Iex.CCall.retty, ret_type, IRType)

PyObject *pyIRExprCCall_args(pyIRExpr* self)
{
int size;
for (size = 0; self->wrapped->Iex.CCall.args[size] != NULL; size++);
int size; for (size = 0; self->wrapped->Iex.CCall.args[size] != NULL; size++);

PyObject *result = PyTuple_New(size);
for (int i = 0; i < size; i++)
Expand Down
105 changes: 104 additions & 1 deletion pyvex_irstmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ PyObject *wrap_IRStmt(IRStmt *i)
PYVEX_WRAPCASE(IRStmt, Ist_, Store)
PYVEX_WRAPCASE(IRStmt, Ist_, CAS)
PYVEX_WRAPCASE(IRStmt, Ist_, LLSC)
//PYVEX_WRAPCASE(IRStmt, Ist_, Dirty)
PYVEX_WRAPCASE(IRStmt, Ist_, Dirty)
PYVEX_WRAPCASE(IRStmt, Ist_, MBE)
PYVEX_WRAPCASE(IRStmt, Ist_, Exit)
default:
Expand Down Expand Up @@ -487,3 +487,106 @@ static PyGetSetDef pyIRStmtExit_getseters[] =

static PyMethodDef pyIRStmtExit_methods[] = { {NULL} };
PYVEX_SUBTYPEOBJECT(Exit, IRStmt);

/////////////////
// Dirty IRStmt //
/////////////////

static int
pyIRStmtDirty_init(pyIRStmt *self, PyObject *args, PyObject *kwargs)
{
PYVEX_WRAP_CONSTRUCTOR(IRStmt);

IRTemp dest;
Int regparms;
const char *name;
unsigned long long addr;
PyObject *args_seq;

static char *kwlist[] = {"regparms", "name", "addr", "args", "tmp", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "isKO|I", kwlist, &regparms, &name, &addr, &args_seq, &dest)) return -1;
if (!PySequence_Check(args_seq)) { PyErr_SetString(VexException, "need sequence of args for Dirty"); return -1; }

int seq_size = PySequence_Size(args_seq);
IRExpr **cargs = (IRExpr **) malloc((seq_size + 1) * sizeof(IRExpr *));
int i;
for (i = 0; i < seq_size; i++)
{
pyIRExpr *expr = (pyIRExpr *)PySequence_GetItem(args_seq, i);
PYVEX_CHECKTYPE(expr, pyIRExprType, return -1);
cargs[i] = expr->wrapped;
}
cargs[i] = NULL;

IRDirty *dirty;
if (PyDict_GetItemString(kwargs, "tmp")) dirty = unsafeIRDirty_1_N(dest, regparms, (char*) name, (void *)addr, cargs);
else dirty = unsafeIRDirty_0_N(regparms, (char*)name, (void *)addr, cargs);

self->wrapped = IRStmt_Dirty(dirty);
return 0;
}

PYVEX_ACCESSOR_WRAPPED(IRStmtDirty, IRStmt, wrapped->Ist.Dirty.details->cee, cee, IRCallee)
PYVEX_ACCESSOR_WRAPPED(IRStmtDirty, IRStmt, wrapped->Ist.Dirty.details->guard, guard, IRExpr)
PYVEX_ACCESSOR_BUILDVAL(IRStmtDirty, IRStmt, wrapped->Ist.Dirty.details->tmp, tmp, "I")
PYVEX_ACCESSOR_ENUM(IRStmtDirty, IRStmt, wrapped->Ist.Dirty.details->mFx, mFx, IREffect)
PYVEX_ACCESSOR_WRAPPED(IRStmtDirty, IRStmt, wrapped->Ist.Dirty.details->mAddr, mAddr, IRExpr)
PYVEX_ACCESSOR_BUILDVAL(IRStmtDirty, IRStmt, wrapped->Ist.Dirty.details->mSize, mSize, "I")
PYVEX_ACCESSOR_BUILDVAL(IRStmtDirty, IRStmt, wrapped->Ist.Dirty.details->needsBBP, needsBBP, "b")
PYVEX_ACCESSOR_BUILDVAL(IRStmtDirty, IRStmt, wrapped->Ist.Dirty.details->nFxState, nFxState, "i")

static PyGetSetDef pyIRStmtDirty_getseters[] =
{
PYVEX_ACCESSOR_DEF(IRStmtDirty, cee),
PYVEX_ACCESSOR_DEF(IRStmtDirty, guard),
PYVEX_ACCESSOR_DEF(IRStmtDirty, tmp),
PYVEX_ACCESSOR_DEF(IRStmtDirty, mFx),
PYVEX_ACCESSOR_DEF(IRStmtDirty, mAddr),
PYVEX_ACCESSOR_DEF(IRStmtDirty, mSize),
PYVEX_ACCESSOR_DEF(IRStmtDirty, needsBBP),
PYVEX_ACCESSOR_DEF(IRStmtDirty, nFxState),
{NULL}
};

PyObject *pyIRStmtDirty_args(pyIRStmt* self)
{
int size; for (size = 0; self->wrapped->Ist.Dirty.details->args[size] != NULL; size++);

PyObject *result = PyTuple_New(size);
for (int i = 0; i < size; i++)
{
PyObject *wrapped = wrap_IRExpr(self->wrapped->Ist.Dirty.details->args[i]);
PyTuple_SetItem(result, i, wrapped);
}
return result;
}

PyObject *pyIRStmtDirty_fxState(pyIRStmt* self)
{
int size = self->wrapped->Ist.Dirty.details->nFxState;
PyObject *result = PyTuple_New(size);
for (int i = 0; i < size; i++)
{
IREffect e = self->wrapped->Ist.Dirty.details->fxState[i].fx;
const char *e_str;
PYVEX_ENUM_TOSTR(IREffect, e, e_str, return NULL);

PyObject *dict = Py_BuildValue("{s:s,s:H,s:H,s:B,s:B}",
"fx", e_str,
"offset", self->wrapped->Ist.Dirty.details->fxState[i].offset,
"size", self->wrapped->Ist.Dirty.details->fxState[i].size,
"nRepeats", self->wrapped->Ist.Dirty.details->fxState[i].nRepeats,
"repeatLen", self->wrapped->Ist.Dirty.details->fxState[i].repeatLen);

PyTuple_SetItem(result, i, dict);
}
return result;
}

static PyMethodDef pyIRStmtDirty_methods[] =
{
{"args", (PyCFunction)pyIRStmtDirty_args, METH_NOARGS, "Returns a tuple of the IRExpr arguments to the callee"},
{"fxState", (PyCFunction)pyIRStmtDirty_fxState, METH_NOARGS, "Returns a tuple of the fxState descriptions for the call"},
{NULL}
};
PYVEX_SUBTYPEOBJECT(Dirty, IRStmt);
1 change: 1 addition & 0 deletions pyvex_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ extern PyTypeObject pyIRStmtStoreType;
extern PyTypeObject pyIRStmtCASType;
extern PyTypeObject pyIRStmtLLSCType;
extern PyTypeObject pyIRStmtMBEType;
extern PyTypeObject pyIRStmtDirtyType;
extern PyTypeObject pyIRStmtExitType;

// expressions
Expand Down
15 changes: 15 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,21 @@ def test_irstmt_mbe(self):
m.event = "Imbe_Fence"
self.assertEqual(m.event, "Imbe_Fence")

def test_irstmt_dirty(self):
args = [ pyvex.IRExpr.RdTmp(i) for i in range(10) ]
m = pyvex.IRStmt.Dirty(3, "test_dirty", 1234, args, tmp=15)
self.assertEqual(m.cee.name, "test_dirty")
self.assertEquals(type(m.guard), pyvex.IRExpr.Const)
self.assertEquals(m.tmp, 15)
self.assertEquals(m.mFx, "Ifx_None")
self.assertEquals(m.needsBBP, 0)
self.assertEquals(m.nFxState, 0)

for n,a in enumerate(m.args()):
self.assertEquals(a.tmp, args[n].tmp)

self.assertEquals(len(m.fxState()), 0)

def test_irstmt_exit(self):
self.assertRaises(Exception, pyvex.IRStmt.Exit, ())

Expand Down

0 comments on commit 430b82a

Please sign in to comment.