mirror of
https://github.com/angr/pyvex
synced 2026-06-21 13:47:01 +00:00
in static mode, pyvex copies everything out of VEX's memory space so that VEX doesn't free stuff from under it
This commit is contained in:
@@ -40,13 +40,14 @@ Awesome stuff!
|
||||
## Bugs
|
||||
|
||||
- Some class members are named incorrectly. I started out trying to name things nicer, but then realized that the naming should be consistent with the C structs. The inconsistencies should be fixed.
|
||||
- The class objects for the different sub-statements, sub-expressions, and sub-constants get inherited for instances of these classes. This is kindof ugly (ie, pyvex.IRStmt.NoOp().WrTmp is a valid reference to the WrTmp class).
|
||||
- help() is sorely lacking
|
||||
- The class objects for the different sub-statements, sub-expressions, and sub-constants get inherited for instances of these classes. This is kindof ugly (ie, pyvex.IRStmt.NoOp().WrTmp is a valid reference to the WrTmp class).
|
||||
- pretty-printing an emptyIRSB segfaults
|
||||
- there is no memory management. VEX is kind of weird with this, so care will have to be taken... It shouldn't be an issue when doing the normal VEX workflow, but for long-running static analysis, the blocks will probably have to be copied out with a rewritten deepCopier.
|
||||
- when used statically, memory is never freed
|
||||
- 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 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
|
||||
- deepCopying a V256 const is not implemented by VEX's deepCopy stuff
|
||||
- IRDirty's fxState array access is untested
|
||||
- equality (for those things that easily have it) should be implemented as a rich comparator
|
||||
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
VALGRIND_HOME=~/valgrind/valgrind-3.8.1/
|
||||
|
||||
cat > pyvex/pyvex_deepcopy.c <<END
|
||||
#include <libvex_ir.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "pyvex_logging.h"
|
||||
#include "pyvex_deepcopy.h"
|
||||
|
||||
#define vpanic(x) { error(x "\n"); assert(0); }
|
||||
|
||||
END
|
||||
|
||||
cat $VALGRIND_HOME/VEX/priv/ir_defs.c | grep -A1000000 "(Deep) copy constructors" | grep -B10000000 "Primop types" | sed -e "s/shallowCopy/pyvex_shallowCopy/g" -e "s/deepCopy/pyvex_deepCopy/g" -e "s/LibVEX_Alloc/malloc/g" >> pyvex/pyvex_deepcopy.c
|
||||
+1
-1
@@ -79,7 +79,7 @@ initpyvex(void)
|
||||
//printf("VexException added...\n");
|
||||
|
||||
//debug_on = 1;
|
||||
#ifndef PYVEX_NOSTATIC
|
||||
#ifdef PYVEX_STATIC
|
||||
vex_init();
|
||||
#endif
|
||||
//printf("Done\n");
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
#include <libvex_ir.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "pyvex_logging.h"
|
||||
#include "pyvex_deepcopy.h"
|
||||
|
||||
#define vpanic(x) { error(x "\n"); assert(0); }
|
||||
|
||||
/*--- (Deep) copy constructors. These make complete copies ---*/
|
||||
/*--- the original, which can be modified without affecting ---*/
|
||||
/*--- the original. ---*/
|
||||
/*---------------------------------------------------------------*/
|
||||
|
||||
/* Copying IR Expr vectors (for call args). */
|
||||
|
||||
/* Shallow copy of an IRExpr vector */
|
||||
|
||||
IRExpr** pyvex_shallowCopyIRExprVec ( IRExpr** vec )
|
||||
{
|
||||
Int i;
|
||||
IRExpr** newvec;
|
||||
for (i = 0; vec[i]; i++)
|
||||
;
|
||||
newvec = malloc((i+1)*sizeof(IRExpr*));
|
||||
for (i = 0; vec[i]; i++)
|
||||
newvec[i] = vec[i];
|
||||
newvec[i] = NULL;
|
||||
return newvec;
|
||||
}
|
||||
|
||||
/* Deep copy of an IRExpr vector */
|
||||
|
||||
IRExpr** pyvex_deepCopyIRExprVec ( IRExpr** vec )
|
||||
{
|
||||
Int i;
|
||||
IRExpr** newvec = pyvex_shallowCopyIRExprVec( vec );
|
||||
for (i = 0; newvec[i]; i++)
|
||||
newvec[i] = pyvex_deepCopyIRExpr(newvec[i]);
|
||||
return newvec;
|
||||
}
|
||||
|
||||
/* Deep copy constructors for all heap-allocated IR types follow. */
|
||||
|
||||
IRConst* pyvex_deepCopyIRConst ( IRConst* c )
|
||||
{
|
||||
switch (c->tag) {
|
||||
case Ico_U1: return IRConst_U1(c->Ico.U1);
|
||||
case Ico_U8: return IRConst_U8(c->Ico.U8);
|
||||
case Ico_U16: return IRConst_U16(c->Ico.U16);
|
||||
case Ico_U32: return IRConst_U32(c->Ico.U32);
|
||||
case Ico_U64: return IRConst_U64(c->Ico.U64);
|
||||
case Ico_F32: return IRConst_F32(c->Ico.F32);
|
||||
case Ico_F32i: return IRConst_F32i(c->Ico.F32i);
|
||||
case Ico_F64: return IRConst_F64(c->Ico.F64);
|
||||
case Ico_F64i: return IRConst_F64i(c->Ico.F64i);
|
||||
case Ico_V128: return IRConst_V128(c->Ico.V128);
|
||||
case Ico_V256: return IRConst_V256(c->Ico.V256);
|
||||
default: vpanic("pyvex_deepCopyIRConst");
|
||||
}
|
||||
}
|
||||
|
||||
IRCallee* pyvex_deepCopyIRCallee ( IRCallee* ce )
|
||||
{
|
||||
IRCallee* ce2 = mkIRCallee(ce->regparms, ce->name, ce->addr);
|
||||
ce2->mcx_mask = ce->mcx_mask;
|
||||
return ce2;
|
||||
}
|
||||
|
||||
IRRegArray* pyvex_deepCopyIRRegArray ( IRRegArray* d )
|
||||
{
|
||||
return mkIRRegArray(d->base, d->elemTy, d->nElems);
|
||||
}
|
||||
|
||||
IRExpr* pyvex_deepCopyIRExpr ( IRExpr* e )
|
||||
{
|
||||
switch (e->tag) {
|
||||
case Iex_Get:
|
||||
return IRExpr_Get(e->Iex.Get.offset, e->Iex.Get.ty);
|
||||
case Iex_GetI:
|
||||
return IRExpr_GetI(pyvex_deepCopyIRRegArray(e->Iex.GetI.descr),
|
||||
pyvex_deepCopyIRExpr(e->Iex.GetI.ix),
|
||||
e->Iex.GetI.bias);
|
||||
case Iex_RdTmp:
|
||||
return IRExpr_RdTmp(e->Iex.RdTmp.tmp);
|
||||
case Iex_Qop: {
|
||||
IRQop* qop = e->Iex.Qop.details;
|
||||
|
||||
return IRExpr_Qop(qop->op,
|
||||
pyvex_deepCopyIRExpr(qop->arg1),
|
||||
pyvex_deepCopyIRExpr(qop->arg2),
|
||||
pyvex_deepCopyIRExpr(qop->arg3),
|
||||
pyvex_deepCopyIRExpr(qop->arg4));
|
||||
}
|
||||
case Iex_Triop: {
|
||||
IRTriop *triop = e->Iex.Triop.details;
|
||||
|
||||
return IRExpr_Triop(triop->op,
|
||||
pyvex_deepCopyIRExpr(triop->arg1),
|
||||
pyvex_deepCopyIRExpr(triop->arg2),
|
||||
pyvex_deepCopyIRExpr(triop->arg3));
|
||||
}
|
||||
case Iex_Binop:
|
||||
return IRExpr_Binop(e->Iex.Binop.op,
|
||||
pyvex_deepCopyIRExpr(e->Iex.Binop.arg1),
|
||||
pyvex_deepCopyIRExpr(e->Iex.Binop.arg2));
|
||||
case Iex_Unop:
|
||||
return IRExpr_Unop(e->Iex.Unop.op,
|
||||
pyvex_deepCopyIRExpr(e->Iex.Unop.arg));
|
||||
case Iex_Load:
|
||||
return IRExpr_Load(e->Iex.Load.end,
|
||||
e->Iex.Load.ty,
|
||||
pyvex_deepCopyIRExpr(e->Iex.Load.addr));
|
||||
case Iex_Const:
|
||||
return IRExpr_Const(pyvex_deepCopyIRConst(e->Iex.Const.con));
|
||||
case Iex_CCall:
|
||||
return IRExpr_CCall(pyvex_deepCopyIRCallee(e->Iex.CCall.cee),
|
||||
e->Iex.CCall.retty,
|
||||
pyvex_deepCopyIRExprVec(e->Iex.CCall.args));
|
||||
|
||||
case Iex_Mux0X:
|
||||
return IRExpr_Mux0X(pyvex_deepCopyIRExpr(e->Iex.Mux0X.cond),
|
||||
pyvex_deepCopyIRExpr(e->Iex.Mux0X.expr0),
|
||||
pyvex_deepCopyIRExpr(e->Iex.Mux0X.exprX));
|
||||
default:
|
||||
vpanic("pyvex_deepCopyIRExpr");
|
||||
}
|
||||
}
|
||||
|
||||
IRDirty* pyvex_deepCopyIRDirty ( IRDirty* d )
|
||||
{
|
||||
Int i;
|
||||
IRDirty* d2 = emptyIRDirty();
|
||||
d2->cee = pyvex_deepCopyIRCallee(d->cee);
|
||||
d2->guard = pyvex_deepCopyIRExpr(d->guard);
|
||||
d2->args = pyvex_deepCopyIRExprVec(d->args);
|
||||
d2->tmp = d->tmp;
|
||||
d2->mFx = d->mFx;
|
||||
d2->mAddr = d->mAddr==NULL ? NULL : pyvex_deepCopyIRExpr(d->mAddr);
|
||||
d2->mSize = d->mSize;
|
||||
d2->needsBBP = d->needsBBP;
|
||||
d2->nFxState = d->nFxState;
|
||||
for (i = 0; i < d2->nFxState; i++)
|
||||
d2->fxState[i] = d->fxState[i];
|
||||
return d2;
|
||||
}
|
||||
|
||||
IRCAS* pyvex_deepCopyIRCAS ( IRCAS* cas )
|
||||
{
|
||||
return mkIRCAS( cas->oldHi, cas->oldLo, cas->end,
|
||||
pyvex_deepCopyIRExpr(cas->addr),
|
||||
cas->expdHi==NULL ? NULL : pyvex_deepCopyIRExpr(cas->expdHi),
|
||||
pyvex_deepCopyIRExpr(cas->expdLo),
|
||||
cas->dataHi==NULL ? NULL : pyvex_deepCopyIRExpr(cas->dataHi),
|
||||
pyvex_deepCopyIRExpr(cas->dataLo) );
|
||||
}
|
||||
|
||||
IRPutI* pyvex_deepCopyIRPutI ( IRPutI * puti )
|
||||
{
|
||||
return mkIRPutI( pyvex_deepCopyIRRegArray(puti->descr),
|
||||
pyvex_deepCopyIRExpr(puti->ix),
|
||||
puti->bias,
|
||||
pyvex_deepCopyIRExpr(puti->data));
|
||||
}
|
||||
|
||||
IRStmt* pyvex_deepCopyIRStmt ( IRStmt* s )
|
||||
{
|
||||
switch (s->tag) {
|
||||
case Ist_NoOp:
|
||||
return IRStmt_NoOp();
|
||||
case Ist_AbiHint:
|
||||
return IRStmt_AbiHint(pyvex_deepCopyIRExpr(s->Ist.AbiHint.base),
|
||||
s->Ist.AbiHint.len,
|
||||
pyvex_deepCopyIRExpr(s->Ist.AbiHint.nia));
|
||||
case Ist_IMark:
|
||||
return IRStmt_IMark(s->Ist.IMark.addr,
|
||||
s->Ist.IMark.len,
|
||||
s->Ist.IMark.delta);
|
||||
case Ist_Put:
|
||||
return IRStmt_Put(s->Ist.Put.offset,
|
||||
pyvex_deepCopyIRExpr(s->Ist.Put.data));
|
||||
case Ist_PutI:
|
||||
return IRStmt_PutI(pyvex_deepCopyIRPutI(s->Ist.PutI.details));
|
||||
case Ist_WrTmp:
|
||||
return IRStmt_WrTmp(s->Ist.WrTmp.tmp,
|
||||
pyvex_deepCopyIRExpr(s->Ist.WrTmp.data));
|
||||
case Ist_Store:
|
||||
return IRStmt_Store(s->Ist.Store.end,
|
||||
pyvex_deepCopyIRExpr(s->Ist.Store.addr),
|
||||
pyvex_deepCopyIRExpr(s->Ist.Store.data));
|
||||
case Ist_CAS:
|
||||
return IRStmt_CAS(pyvex_deepCopyIRCAS(s->Ist.CAS.details));
|
||||
case Ist_LLSC:
|
||||
return IRStmt_LLSC(s->Ist.LLSC.end,
|
||||
s->Ist.LLSC.result,
|
||||
pyvex_deepCopyIRExpr(s->Ist.LLSC.addr),
|
||||
s->Ist.LLSC.storedata
|
||||
? pyvex_deepCopyIRExpr(s->Ist.LLSC.storedata)
|
||||
: NULL);
|
||||
case Ist_Dirty:
|
||||
return IRStmt_Dirty(pyvex_deepCopyIRDirty(s->Ist.Dirty.details));
|
||||
case Ist_MBE:
|
||||
return IRStmt_MBE(s->Ist.MBE.event);
|
||||
case Ist_Exit:
|
||||
return IRStmt_Exit(pyvex_deepCopyIRExpr(s->Ist.Exit.guard),
|
||||
s->Ist.Exit.jk,
|
||||
pyvex_deepCopyIRConst(s->Ist.Exit.dst),
|
||||
s->Ist.Exit.offsIP);
|
||||
default:
|
||||
vpanic("pyvex_deepCopyIRStmt");
|
||||
}
|
||||
}
|
||||
|
||||
IRTypeEnv* pyvex_deepCopyIRTypeEnv ( IRTypeEnv* src )
|
||||
{
|
||||
Int i;
|
||||
IRTypeEnv* dst = malloc(sizeof(IRTypeEnv));
|
||||
dst->types_size = src->types_size;
|
||||
dst->types_used = src->types_used;
|
||||
dst->types = malloc(dst->types_size * sizeof(IRType));
|
||||
for (i = 0; i < src->types_used; i++)
|
||||
dst->types[i] = src->types[i];
|
||||
return dst;
|
||||
}
|
||||
|
||||
IRSB* pyvex_deepCopyIRSB ( IRSB* bb )
|
||||
{
|
||||
Int i;
|
||||
IRStmt** sts2;
|
||||
error("copying %p without statements\n", bb);
|
||||
IRSB* bb2 = pyvex_deepCopyIRSBExceptStmts(bb);
|
||||
error("done copying without statements\n");
|
||||
bb2->stmts_used = bb2->stmts_size = bb->stmts_used;
|
||||
sts2 = malloc(bb2->stmts_used * sizeof(IRStmt*));
|
||||
for (i = 0; i < bb2->stmts_used; i++)
|
||||
sts2[i] = pyvex_deepCopyIRStmt(bb->stmts[i]);
|
||||
bb2->stmts = sts2;
|
||||
return bb2;
|
||||
}
|
||||
|
||||
IRSB* pyvex_deepCopyIRSBExceptStmts ( IRSB* bb )
|
||||
{
|
||||
IRSB* bb2 = emptyIRSB();
|
||||
bb2->tyenv = pyvex_deepCopyIRTypeEnv(bb->tyenv);
|
||||
bb->next == NULL;
|
||||
if (bb->next) bb2->next = pyvex_deepCopyIRExpr(bb->next);
|
||||
bb2->jumpkind = bb->jumpkind;
|
||||
bb2->offsIP = bb->offsIP;
|
||||
return bb2;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------*/
|
||||
/*--- Primop types ---*/
|
||||
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
IRExpr** pyvex_deepCopyIRExprVec ( IRExpr** vec );
|
||||
IRConst* pyvex_deepCopyIRConst ( IRConst* c );
|
||||
IRCallee* pyvex_deepCopyIRCallee ( IRCallee* ce );
|
||||
IRRegArray* pyvex_deepCopyIRRegArray ( IRRegArray* d );
|
||||
IRExpr* pyvex_deepCopyIRExpr ( IRExpr* e );
|
||||
IRDirty* pyvex_deepCopyIRDirty ( IRDirty* d );
|
||||
IRCAS* pyvex_deepCopyIRCAS ( IRCAS* cas );
|
||||
IRPutI* pyvex_deepCopyIRPutI ( IRPutI * puti );
|
||||
IRStmt* pyvex_deepCopyIRStmt ( IRStmt* s );
|
||||
IRTypeEnv* pyvex_deepCopyIRTypeEnv ( IRTypeEnv* src );
|
||||
IRSB* pyvex_deepCopyIRSB ( IRSB* bb );
|
||||
IRSB* pyvex_deepCopyIRSBExceptStmts ( IRSB* bb );
|
||||
@@ -8,6 +8,11 @@
|
||||
#include "pyvex_types.h"
|
||||
#include "pyvex_macros.h"
|
||||
|
||||
#ifdef PYVEX_STATIC
|
||||
#include "pyvex_static.h"
|
||||
#include "pyvex_deepcopy.h"
|
||||
#endif
|
||||
|
||||
PYVEX_NEW(IRCallee)
|
||||
PYVEX_DEALLOC(IRCallee)
|
||||
PYVEX_WRAP(IRCallee)
|
||||
@@ -27,7 +32,7 @@ pyIRCallee_init(pyIRCallee *self, PyObject *args, PyObject *kwargs)
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "isK|I", kwlist, ®parms, &name, &addr, &mcx_mask)) return -1;
|
||||
if (regparms < 0 || regparms > 3) { PyErr_SetString(VexException, "regparms out of range"); return -1; }
|
||||
|
||||
self->wrapped = mkIRCallee(regparms, name, (void *)addr);
|
||||
self->wrapped = PYVEX_COPYOUT(IRCallee, mkIRCallee(regparms, name, (void *)addr));
|
||||
if (mcx_mask != 123456789) self->wrapped->mcx_mask = mcx_mask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
#include "pyvex_macros.h"
|
||||
#include "pyvex_logging.h"
|
||||
|
||||
#ifdef PYVEX_STATIC
|
||||
#include "pyvex_static.h"
|
||||
#include "pyvex_deepcopy.h"
|
||||
#endif
|
||||
|
||||
////////////////////////
|
||||
// IRConst base class //
|
||||
////////////////////////
|
||||
@@ -100,7 +105,7 @@ PyObject *wrap_IRConst(IRConst *i)
|
||||
type value; \
|
||||
static char *kwlist[] = {"value", NULL}; \
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, format, kwlist, &value)) return -1; \
|
||||
self->wrapped = IRConst_##tag(value); \
|
||||
self->wrapped = PYVEX_COPYOUT(IRConst, IRConst_##tag(value)); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
|
||||
+17
-12
@@ -9,6 +9,11 @@
|
||||
#include "pyvex_macros.h"
|
||||
#include "pyvex_logging.h"
|
||||
|
||||
#ifdef PYVEX_STATIC
|
||||
#include "pyvex_static.h"
|
||||
#include "pyvex_deepcopy.h"
|
||||
#endif
|
||||
|
||||
///////////////////////
|
||||
// IRExpr base class //
|
||||
///////////////////////
|
||||
@@ -95,7 +100,7 @@ pyIRExprBinder_init(pyIRExpr *self, PyObject *args, PyObject *kwargs)
|
||||
static char *kwlist[] = {"binder", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &binder)) return -1;
|
||||
|
||||
self->wrapped = IRExpr_Binder(binder);
|
||||
self->wrapped = PYVEX_COPYOUT(IRExpr, IRExpr_Binder(binder));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -130,7 +135,7 @@ pyIRExprGetI_init(pyIRExpr *self, PyObject *args, PyObject *kwargs)
|
||||
PYVEX_CHECKTYPE(descr, pyIRRegArrayType, return -1);
|
||||
PYVEX_CHECKTYPE(ix, pyIRExprType, return -1);
|
||||
|
||||
self->wrapped = IRExpr_GetI(descr->wrapped, ix->wrapped, bias);
|
||||
self->wrapped = PYVEX_COPYOUT(IRExpr, IRExpr_GetI(descr->wrapped, ix->wrapped, bias));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -166,7 +171,7 @@ pyIRExprGet_init(pyIRExpr *self, PyObject *args, PyObject *kwargs)
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "is", kwlist, &offset, &type_str)) return -1;
|
||||
PYVEX_ENUM_FROMSTR(IRType, type, type_str, return -1);
|
||||
|
||||
self->wrapped = IRExpr_Get(offset, type);
|
||||
self->wrapped = PYVEX_COPYOUT(IRExpr, IRExpr_Get(offset, type));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -228,14 +233,14 @@ pyIRExprQop_init(pyIRExpr *self, PyObject *args, PyObject *kwargs)
|
||||
pyIRExpr *arg4;
|
||||
|
||||
static char *kwlist[] = {"op", "arg1", "arg2", "arg3", "arg4", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sOOOO|O", kwlist, &op_str, &arg1, &arg2, &arg3, &arg4, &wrap_object)) return -1;
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sOOOO|O", kwlist, &op_str, &arg1, &arg2, &arg3, &arg4)) return -1;
|
||||
PYVEX_ENUM_FROMSTR(IROp, op, op_str, return -1);
|
||||
PYVEX_CHECKTYPE(arg1, pyIRExprType, return -1);
|
||||
PYVEX_CHECKTYPE(arg2, pyIRExprType, return -1);
|
||||
PYVEX_CHECKTYPE(arg3, pyIRExprType, return -1);
|
||||
PYVEX_CHECKTYPE(arg4, pyIRExprType, return -1);
|
||||
|
||||
self->wrapped = IRExpr_Qop(op, arg1->wrapped, arg2->wrapped, arg3->wrapped, arg4->wrapped);
|
||||
self->wrapped = PYVEX_COPYOUT(IRExpr, IRExpr_Qop(op, arg1->wrapped, arg2->wrapped, arg3->wrapped, arg4->wrapped));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -289,7 +294,7 @@ pyIRExprTriop_init(pyIRExpr *self, PyObject *args, PyObject *kwargs)
|
||||
PYVEX_CHECKTYPE(arg2, pyIRExprType, return -1);
|
||||
PYVEX_CHECKTYPE(arg3, pyIRExprType, return -1);
|
||||
|
||||
self->wrapped = IRExpr_Triop(op, arg1->wrapped, arg2->wrapped, arg3->wrapped);
|
||||
self->wrapped = PYVEX_COPYOUT(IRExpr, IRExpr_Triop(op, arg1->wrapped, arg2->wrapped, arg3->wrapped));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -338,7 +343,7 @@ pyIRExprBinop_init(pyIRExpr *self, PyObject *args, PyObject *kwargs)
|
||||
PYVEX_CHECKTYPE(arg1, pyIRExprType, return -1);
|
||||
PYVEX_CHECKTYPE(arg2, pyIRExprType, return -1);
|
||||
|
||||
self->wrapped = IRExpr_Binop(op, arg1->wrapped, arg2->wrapped);
|
||||
self->wrapped = PYVEX_COPYOUT(IRExpr, IRExpr_Binop(op, arg1->wrapped, arg2->wrapped));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -382,7 +387,7 @@ pyIRExprUnop_init(pyIRExpr *self, PyObject *args, PyObject *kwargs)
|
||||
PYVEX_ENUM_FROMSTR(IROp, op, op_str, return -1);
|
||||
PYVEX_CHECKTYPE(arg1, pyIRExprType, return -1);
|
||||
|
||||
self->wrapped = IRExpr_Unop(op, arg1->wrapped);
|
||||
self->wrapped = PYVEX_COPYOUT(IRExpr, IRExpr_Unop(op, arg1->wrapped));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -426,7 +431,7 @@ pyIRExprLoad_init(pyIRExpr *self, PyObject *args, PyObject *kwargs)
|
||||
PYVEX_ENUM_FROMSTR(IRType, type, type_str, return -1);
|
||||
PYVEX_CHECKTYPE(addr, pyIRExprType, return -1);
|
||||
|
||||
self->wrapped = IRExpr_Load(endness, type, addr->wrapped);
|
||||
self->wrapped = PYVEX_COPYOUT(IRExpr, IRExpr_Load(endness, type, addr->wrapped));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -460,7 +465,7 @@ pyIRExprConst_init(pyIRExpr *self, PyObject *args, PyObject *kwargs)
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O", kwlist, &con)) return -1;
|
||||
PYVEX_CHECKTYPE(con, pyIRConstType, return -1);
|
||||
|
||||
self->wrapped = IRExpr_Const(con->wrapped);
|
||||
self->wrapped = PYVEX_COPYOUT(IRExpr, IRExpr_Const(con->wrapped));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -494,7 +499,7 @@ pyIRExprMux0X_init(pyIRExpr *self, PyObject *args, PyObject *kwargs)
|
||||
PYVEX_CHECKTYPE(expr0, pyIRExprType, return -1);
|
||||
PYVEX_CHECKTYPE(exprX, pyIRExprType, return -1);
|
||||
|
||||
self->wrapped = IRExpr_Mux0X(cond->wrapped, expr0->wrapped, exprX->wrapped);
|
||||
self->wrapped = PYVEX_COPYOUT(IRExpr, IRExpr_Mux0X(cond->wrapped, expr0->wrapped, exprX->wrapped));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -543,7 +548,7 @@ pyIRExprCCall_init(pyIRExpr *self, PyObject *args, PyObject *kwargs)
|
||||
}
|
||||
cargs[i] = NULL;
|
||||
|
||||
self->wrapped = IRExpr_CCall(callee->wrapped, ret_type, cargs);
|
||||
self->wrapped = PYVEX_COPYOUT(IRExpr, IRExpr_CCall(callee->wrapped, ret_type, cargs));
|
||||
return 0;
|
||||
}
|
||||
PYVEX_ACCESSOR_WRAPPED(IRExprCCall, IRExpr, self->wrapped->Iex.CCall.cee, callee, IRCallee)
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
#include "pyvex_types.h"
|
||||
#include "pyvex_macros.h"
|
||||
|
||||
#ifdef PYVEX_STATIC
|
||||
#include "pyvex_static.h"
|
||||
#include "pyvex_deepcopy.h"
|
||||
#endif
|
||||
|
||||
////////////////////////
|
||||
// IRRegArray base class //
|
||||
////////////////////////
|
||||
@@ -30,7 +35,7 @@ pyIRRegArray_init(pyIRRegArray *self, PyObject *args, PyObject *kwargs)
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "isi", kwlist, &base, &elemTy_str, &nElems)) return -1;
|
||||
PYVEX_ENUM_FROMSTR(IRType, elemTy, elemTy_str, return -1)
|
||||
|
||||
self->wrapped = mkIRRegArray(base, elemTy, nElems);
|
||||
self->wrapped = PYVEX_COPYOUT(IRRegArray, mkIRRegArray(base, elemTy, nElems));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+7
-3
@@ -7,7 +7,11 @@
|
||||
#include "pyvex_enums.h"
|
||||
#include "pyvex_types.h"
|
||||
#include "pyvex_macros.h"
|
||||
#include "pyvex_static.h"
|
||||
|
||||
#ifdef PYVEX_STATIC
|
||||
#include "pyvex_static.h"
|
||||
#include "pyvex_deepcopy.h"
|
||||
#endif
|
||||
|
||||
PYVEX_NEW(IRSB)
|
||||
PYVEX_DEALLOC(IRSB)
|
||||
@@ -17,10 +21,10 @@ PYVEX_METH_STANDARD(IRSB)
|
||||
static int
|
||||
pyIRSB_init(pyIRSB *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
if (!kwargs) { self->wrapped = emptyIRSB(); return 0; }
|
||||
if (!kwargs) { self->wrapped = PYVEX_COPYOUT(IRSB, emptyIRSB()); return 0; }
|
||||
PYVEX_WRAP_CONSTRUCTOR(IRSB);
|
||||
|
||||
#ifndef PYVEX_NOSTATIC
|
||||
#ifdef PYVEX_STATIC
|
||||
unsigned char *bytes = NULL;
|
||||
unsigned int mem_addr = 0;
|
||||
int num_inst = -1;
|
||||
|
||||
+19
-14
@@ -9,6 +9,12 @@
|
||||
#include "pyvex_macros.h"
|
||||
#include "pyvex_logging.h"
|
||||
|
||||
#ifdef PYVEX_STATIC
|
||||
#include "pyvex_static.h"
|
||||
#include "pyvex_deepcopy.h"
|
||||
#endif
|
||||
|
||||
|
||||
///////////////////////
|
||||
// IRStmt base class //
|
||||
///////////////////////
|
||||
@@ -89,7 +95,7 @@ PyObject *wrap_IRStmt(IRStmt *i)
|
||||
static int
|
||||
pyIRStmtNoOp_init(pyIRStmt *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
if (!kwargs) { self->wrapped = IRStmt_NoOp(); return 0; }
|
||||
if (!kwargs) { self->wrapped = PYVEX_COPYOUT(IRStmt, IRStmt_NoOp()); return 0; }
|
||||
PYVEX_WRAP_CONSTRUCTOR(IRStmt);
|
||||
|
||||
PyErr_SetString(VexException, "Unexpected arguments provided to constructor.");
|
||||
@@ -116,7 +122,7 @@ pyIRStmtIMark_init(pyIRStmt *self, PyObject *args, PyObject *kwargs)
|
||||
static char *kwlist[] = {"addr", "len", "delta", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Kib", kwlist, &addr, &len, &delta)) return -1;
|
||||
|
||||
self->wrapped = IRStmt_IMark(addr, len, delta);
|
||||
self->wrapped = PYVEX_COPYOUT(IRStmt, IRStmt_IMark(addr, len, delta));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -153,7 +159,7 @@ pyIRStmtAbiHint_init(pyIRStmt *self, PyObject *args, PyObject *kwargs)
|
||||
PYVEX_CHECKTYPE(base, pyIRExprType, return -1)
|
||||
PYVEX_CHECKTYPE(nia, pyIRExprType, return -1)
|
||||
|
||||
self->wrapped = IRStmt_AbiHint(base->wrapped, len, nia->wrapped);
|
||||
self->wrapped = PYVEX_COPYOUT(IRStmt, IRStmt_AbiHint(base->wrapped, len, nia->wrapped));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -188,7 +194,7 @@ pyIRStmtPut_init(pyIRStmt *self, PyObject *args, PyObject *kwargs)
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iO", kwlist, &offset, &data)) return -1;
|
||||
PYVEX_CHECKTYPE(data, pyIRExprType, return -1)
|
||||
|
||||
self->wrapped = IRStmt_Put(offset, data->wrapped);
|
||||
self->wrapped = PYVEX_COPYOUT(IRStmt, IRStmt_Put(offset, data->wrapped));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -225,7 +231,7 @@ pyIRStmtPutI_init(pyIRStmt *self, PyObject *args, PyObject *kwargs)
|
||||
PYVEX_CHECKTYPE(ix, pyIRExprType, return -1)
|
||||
PYVEX_CHECKTYPE(data, pyIRExprType, return -1)
|
||||
|
||||
self->wrapped = IRStmt_PutI(mkIRPutI(descr->wrapped, ix->wrapped, bias, data->wrapped));
|
||||
self->wrapped = PYVEX_COPYOUT(IRStmt, IRStmt_PutI(mkIRPutI(descr->wrapped, ix->wrapped, bias, data->wrapped)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -262,7 +268,7 @@ pyIRStmtWrTmp_init(pyIRStmt *self, PyObject *args, PyObject *kwargs)
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "IO", kwlist, &tmp, &data)) return -1;
|
||||
PYVEX_CHECKTYPE(data, pyIRExprType, return -1)
|
||||
|
||||
self->wrapped = IRStmt_WrTmp(tmp, data->wrapped);
|
||||
self->wrapped = PYVEX_COPYOUT(IRStmt, IRStmt_WrTmp(tmp, data->wrapped));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -299,7 +305,7 @@ pyIRStmtStore_init(pyIRStmt *self, PyObject *args, PyObject *kwargs)
|
||||
PYVEX_CHECKTYPE(data, pyIRExprType, return -1)
|
||||
PYVEX_ENUM_FROMSTR(IREndness, endness, endness_str, return -1);
|
||||
|
||||
self->wrapped = IRStmt_Store(endness, addr->wrapped, data->wrapped);
|
||||
self->wrapped = PYVEX_COPYOUT(IRStmt, IRStmt_Store(endness, addr->wrapped, data->wrapped));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -346,8 +352,7 @@ pyIRStmtCAS_init(pyIRStmt *self, PyObject *args, PyObject *kwargs)
|
||||
PYVEX_CHECKTYPE(dataLo, pyIRExprType, return -1)
|
||||
PYVEX_ENUM_FROMSTR(IREndness, endness, endness_str, return -1);
|
||||
|
||||
self->wrapped = IRStmt_CAS(mkIRCAS(oldHi, oldLo, endness, addr->wrapped, expdHi->wrapped, expdLo->wrapped,
|
||||
dataHi->wrapped, dataLo->wrapped));
|
||||
self->wrapped = PYVEX_COPYOUT(IRStmt, IRStmt_CAS(mkIRCAS(oldHi, oldLo, endness, addr->wrapped, expdHi->wrapped, expdLo->wrapped, dataHi->wrapped, dataLo->wrapped)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -397,7 +402,7 @@ pyIRStmtLLSC_init(pyIRStmt *self, PyObject *args, PyObject *kwargs)
|
||||
PYVEX_CHECKTYPE(storedata, pyIRExprType, return -1)
|
||||
PYVEX_ENUM_FROMSTR(IREndness, endness, endness_str, return -1);
|
||||
|
||||
self->wrapped = IRStmt_LLSC(endness, result, addr->wrapped, storedata->wrapped);
|
||||
self->wrapped = PYVEX_COPYOUT(IRStmt, IRStmt_LLSC(endness, result, addr->wrapped, storedata->wrapped));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -433,7 +438,7 @@ pyIRStmtMBE_init(pyIRStmt *self, PyObject *args, PyObject *kwargs)
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &mb_str)) return -1;
|
||||
PYVEX_ENUM_FROMSTR(IRMBusEvent, mb, mb_str, return -1);
|
||||
|
||||
self->wrapped = IRStmt_MBE(mb);
|
||||
self->wrapped = PYVEX_COPYOUT(IRStmt, IRStmt_MBE(mb));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -468,7 +473,7 @@ pyIRStmtExit_init(pyIRStmt *self, PyObject *args, PyObject *kwargs)
|
||||
PYVEX_CHECKTYPE(dst, pyIRConstType, return -1)
|
||||
PYVEX_ENUM_FROMSTR(IRJumpKind, jk, jk_str, return -1);
|
||||
|
||||
self->wrapped = IRStmt_Exit(guard->wrapped, jk, dst->wrapped, offsIP);
|
||||
self->wrapped = PYVEX_COPYOUT(IRStmt, IRStmt_Exit(guard->wrapped, jk, dst->wrapped, offsIP));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -520,10 +525,10 @@ pyIRStmtDirty_init(pyIRStmt *self, PyObject *args, PyObject *kwargs)
|
||||
cargs[i] = NULL;
|
||||
|
||||
IRDirty *dirty;
|
||||
if (PyDict_GetItemString(kwargs, "tmp")) dirty = unsafeIRDirty_1_N(dest, regparms, (char*) name, (void *)addr, cargs);
|
||||
if (PyDict_GetItemString(kwargs, "tmp")) dirty = PYVEX_COPYOUT(IRDirty, 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);
|
||||
self->wrapped = PYVEX_COPYOUT(IRStmt, IRStmt_Dirty(dirty));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
#include "pyvex_types.h"
|
||||
#include "pyvex_macros.h"
|
||||
|
||||
#ifdef PYVEX_STATIC
|
||||
#include "pyvex_static.h"
|
||||
#include "pyvex_deepcopy.h"
|
||||
#endif
|
||||
|
||||
//////////////////
|
||||
// Python stuff //
|
||||
//////////////////
|
||||
@@ -20,7 +25,7 @@ PYVEX_METH_STANDARD(IRTypeEnv)
|
||||
static int
|
||||
pyIRTypeEnv_init(pyIRTypeEnv *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
if (!kwargs) { self->wrapped = emptyIRTypeEnv(); return 0; }
|
||||
if (!kwargs) { self->wrapped = PYVEX_COPYOUT(IRTypeEnv, emptyIRTypeEnv()); return 0; }
|
||||
PYVEX_WRAP_CONSTRUCTOR(IRTypeEnv);
|
||||
|
||||
PyErr_SetString(VexException, "Unexpected arguments provided.");
|
||||
|
||||
+143
-114
@@ -3,10 +3,21 @@
|
||||
#ifndef __MACROS_H
|
||||
#define __MACROS_H
|
||||
|
||||
// define the struct
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Memory management crap. VEX does its own memory management, so if we don't
|
||||
// want the structures freed out from under us, we need to copy them out
|
||||
#ifdef PYVEX_STATIC
|
||||
#define PYVEX_COPYOUT(type, x) pyvex_deepCopy##type(x)
|
||||
#else
|
||||
#define PYVEX_COPYOUT(type, x) x
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// These are various macros to make defining PyVEX python classes easier
|
||||
// - the struct itself
|
||||
#define PYVEX_STRUCT(type) typedef struct { PyObject_HEAD type *wrapped; } py##type;
|
||||
|
||||
// default allocation and deallocation
|
||||
// - default allocation and deallocation
|
||||
#define PYVEX_NEW(type) \
|
||||
static PyObject * \
|
||||
py##type##_new(PyTypeObject *type, PyObject *args, PyObject *kwds) \
|
||||
@@ -18,119 +29,31 @@
|
||||
}
|
||||
#define PYVEX_DEALLOC(type) static void py##type##_dealloc(py##type* self) { self->ob_type->tp_free((PyObject*)self); }
|
||||
|
||||
// Method definitions for Python's list
|
||||
// - method declarations for Python
|
||||
#define PYVEX_METHDEF_PP(type) {"pp", (PyCFunction)py##type##_pp, METH_NOARGS, "Prints the "#type}
|
||||
#define PYVEX_METHDEF_DEEPCOPY(type) {"deepCopy", (PyCFunction)py##type##_deepCopy, METH_NOARGS, "Deep-copies the "#type}
|
||||
#define PYVEX_METHDEF_STANDARD(type) PYVEX_METHDEF_PP(type), PYVEX_METHDEF_DEEPCOPY(type)
|
||||
|
||||
// The methods themselves
|
||||
// - the methods themselves
|
||||
#define PYVEX_METH_PP(type) static PyObject * py##type##_pp(py##type* self) { pp##type(self->wrapped); Py_RETURN_NONE; }
|
||||
#define PYVEX_METH_DEEPCOPY(type) \
|
||||
static PyObject * py##type##_deepCopy(py##type* self) { return (PyObject *)wrap_##type(deepCopy##type(self->wrapped)); }
|
||||
#define PYVEX_METH_STANDARD(type) PYVEX_METH_PP(type) PYVEX_METH_DEEPCOPY(type)
|
||||
|
||||
// helper for type checking
|
||||
#define PYVEX_CHECKTYPE(object, type, fail) if (!PyObject_TypeCheck((PyObject *)object, &type)) { PyErr_SetString(VexException, "Incorrect type passed in. Needs "#type); fail; }
|
||||
|
||||
// getter and setter definitions
|
||||
#define PYVEX_ACCESSOR_DEF(type, attr) {#attr, (getter)py##type##_##get##_##attr, (setter)py##type##_##set##_##attr, #attr, NULL}
|
||||
|
||||
#define PYVEX_GETTER_BUILDVAL(type, intype, attr, name, format) \
|
||||
static PyObject *py##type##_get_##name(py##intype *self, void *closure) \
|
||||
{ \
|
||||
PyObject *o = Py_BuildValue(format, attr); \
|
||||
if (!o) { PyErr_SetString(VexException, "Error in py"#type"_get_"#name"\n"); return NULL; } \
|
||||
return o; \
|
||||
}
|
||||
#define PYVEX_SETTER_BUILDVAL(type, intype, attr, name, format) \
|
||||
static int py##type##_set_##name(py##intype *self, PyObject *value, void *closure) \
|
||||
{ \
|
||||
if (!PyArg_Parse(value, format, &(attr))) return -1; \
|
||||
return 0; \
|
||||
}
|
||||
#define PYVEX_ACCESSOR_BUILDVAL(a,b,c,d,e) PYVEX_SETTER_BUILDVAL(a,b,c,d,e) PYVEX_GETTER_BUILDVAL(a,b,c,d,e)
|
||||
|
||||
#define PYVEX_GETTER_CAPSULE(type, intype, attr, name, ctype) \
|
||||
static PyObject *py##type##_get_##name(py##intype *self, void *closure) { return PyCapsule_New(attr, #ctype, NULL); }
|
||||
#define PYVEX_SETTER_CAPSULE(type, intype, attr, name, ctype) \
|
||||
static int py##type##_set_##name(py##intype *self, PyObject *value, void *closure) \
|
||||
{ \
|
||||
ctype *i = (ctype *)PyCapsule_GetPointer(value, #ctype); \
|
||||
if (i) { attr = i; return 0; } \
|
||||
else return -1; \
|
||||
}
|
||||
#define PYVEX_ACCESSOR_CAPSULE(a,b,c,d,e) PYVEX_SETTER_CAPSULE(a,b,c,d,e) PYVEX_GETTER_CAPSULE(a,b,c,d,e)
|
||||
|
||||
#define PYVEX_GETTER_WRAPPED(type, intype, attr, name, attrtype) \
|
||||
static PyObject *py##type##_get_##name(py##intype *self, void *closure) \
|
||||
{ \
|
||||
PyObject *o = wrap_##attrtype(attr); \
|
||||
if (!o) { PyErr_SetString(VexException, "Error in py"#type"_get_"#name"\n"); return NULL; } \
|
||||
return o; \
|
||||
}
|
||||
#define PYVEX_SETTER_WRAPPED(type, intype, attr, name, attrtype) \
|
||||
static int py##type##_set_##name(py##intype *self, PyObject *value, void *closure) \
|
||||
{ \
|
||||
PYVEX_CHECKTYPE(value, py##attrtype##Type, return -1); \
|
||||
attr = ((py##attrtype *) value)->wrapped; \
|
||||
return 0; \
|
||||
}
|
||||
#define PYVEX_ACCESSOR_WRAPPED(a,b,c,d,e) PYVEX_SETTER_WRAPPED(a,b,c,d,e) PYVEX_GETTER_WRAPPED(a,b,c,d,e)
|
||||
|
||||
// tag
|
||||
#define PYVEX_GETTER_ENUM(type, intype, attr, name, enum) \
|
||||
static PyObject *py##type##_get_##name(py##intype *self, void *closure) \
|
||||
{ \
|
||||
const char *tstr = enum##_to_str(attr); \
|
||||
if (tstr) return PyString_FromString(tstr); \
|
||||
PyErr_SetString(VexException, "Unrecognized "#enum); \
|
||||
return NULL; \
|
||||
}
|
||||
#define PYVEX_SETTER_ENUM(type, intype, attr, name, enum) \
|
||||
static int py##type##_set_##name(py##intype *self, PyObject *value, void *closure) \
|
||||
{ \
|
||||
const char *tstr = PyString_AsString(value); \
|
||||
enum t = str_to_##enum(tstr); \
|
||||
if (t) { attr = t; return 0; } \
|
||||
else { PyErr_SetString(VexException, "Unrecognized "#enum); return -1; } \
|
||||
}
|
||||
#define PYVEX_ACCESSOR_ENUM(a,b,c,d,e) PYVEX_SETTER_ENUM(a,b,c,d,e) PYVEX_GETTER_ENUM(a,b,c,d,e)
|
||||
|
||||
// wrapping constructor
|
||||
#define PYVEX_WRAP_CONSTRUCTOR(type) \
|
||||
PyObject *wrap_object; \
|
||||
if (kwargs) \
|
||||
{ \
|
||||
wrap_object = PyDict_GetItemString(kwargs, "wrap"); \
|
||||
if (wrap_object) \
|
||||
{ \
|
||||
self->wrapped = PyCapsule_GetPointer(wrap_object, #type); \
|
||||
if (!self->wrapped) return -1; \
|
||||
return 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef PYVEX_STATIC
|
||||
#define PYVEX_METH_DEEPCOPY(type) \
|
||||
static PyObject * py##type##_deepCopy(py##type* self) { return (PyObject *)wrap_##type(pyvex_deepCopy##type(self->wrapped)); }
|
||||
#else
|
||||
#define PYVEX_METH_DEEPCOPY(type) \
|
||||
static PyObject * py##type##_deepCopy(py##type* self) { return (PyObject *)wrap_##type(deepCopy##type(self->wrapped)); }
|
||||
#endif
|
||||
|
||||
// wrapping helper
|
||||
#define PYVEX_WRAP(type) \
|
||||
PyObject *wrap_##type(type *i) \
|
||||
{ \
|
||||
PyObject *args = Py_BuildValue(""); \
|
||||
PyObject *kwargs = Py_BuildValue("{s:O}", "wrap", PyCapsule_New(i, #type, NULL)); \
|
||||
PyObject *o = PyObject_Call((PyObject *)&py##type##Type, args, kwargs); \
|
||||
Py_DECREF(args); \
|
||||
Py_DECREF(kwargs); \
|
||||
return (PyObject *)o; \
|
||||
}
|
||||
#define PYVEX_METH_STANDARD(type) PYVEX_METH_PP(type) PYVEX_METH_DEEPCOPY(type)
|
||||
|
||||
// for the header
|
||||
// - class type header
|
||||
#define PYVEX_TYPEHEADER(type) \
|
||||
extern PyTypeObject py##type##Type; \
|
||||
PYVEX_STRUCT(type); \
|
||||
PyObject *wrap_##type(type *);
|
||||
|
||||
// type object
|
||||
// - type object
|
||||
#define PYVEX_TYPEOBJECT(type) \
|
||||
PyTypeObject py##type##Type = \
|
||||
{ \
|
||||
@@ -220,29 +143,135 @@
|
||||
0, /* tp_new */ \
|
||||
};
|
||||
|
||||
// enum conversion
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// These are helpers for accessing the struct members
|
||||
// - getter and setter definitions
|
||||
#define PYVEX_ACCESSOR_DEF(type, attr) {#attr, (getter)py##type##_##get##_##attr, (setter)py##type##_##set##_##attr, #attr, NULL}
|
||||
|
||||
// - getters and setters which use Py_BuildValue and Py_ArgParse for facilitating access
|
||||
#define PYVEX_GETTER_BUILDVAL(type, intype, attr, name, format) \
|
||||
static PyObject *py##type##_get_##name(py##intype *self, void *closure) \
|
||||
{ \
|
||||
PyObject *o = Py_BuildValue(format, attr); \
|
||||
if (!o) { PyErr_SetString(VexException, "Error in py"#type"_get_"#name"\n"); return NULL; } \
|
||||
return o; \
|
||||
}
|
||||
#define PYVEX_SETTER_BUILDVAL(type, intype, attr, name, format) \
|
||||
static int py##type##_set_##name(py##intype *self, PyObject *value, void *closure) \
|
||||
{ \
|
||||
if (!PyArg_Parse(value, format, &(attr))) return -1; \
|
||||
return 0; \
|
||||
}
|
||||
#define PYVEX_ACCESSOR_BUILDVAL(a,b,c,d,e) PYVEX_SETTER_BUILDVAL(a,b,c,d,e) PYVEX_GETTER_BUILDVAL(a,b,c,d,e)
|
||||
|
||||
// - getters and setters which encapsulate the members using PyCapsule
|
||||
#define PYVEX_GETTER_CAPSULE(type, intype, attr, name, ctype) \
|
||||
static PyObject *py##type##_get_##name(py##intype *self, void *closure) { return PyCapsule_New(attr, #ctype, NULL); }
|
||||
#define PYVEX_SETTER_CAPSULE(type, intype, attr, name, ctype) \
|
||||
static int py##type##_set_##name(py##intype *self, PyObject *value, void *closure) \
|
||||
{ \
|
||||
ctype *i = (ctype *)PyCapsule_GetPointer(value, #ctype); \
|
||||
if (i) { attr = i; return 0; } \
|
||||
else return -1; \
|
||||
}
|
||||
#define PYVEX_ACCESSOR_CAPSULE(a,b,c,d,e) PYVEX_SETTER_CAPSULE(a,b,c,d,e) PYVEX_GETTER_CAPSULE(a,b,c,d,e)
|
||||
|
||||
// - getters and setters that wrap the members in the proper PyVEX classes
|
||||
#define PYVEX_GETTER_WRAPPED(type, intype, attr, name, attrtype) \
|
||||
static PyObject *py##type##_get_##name(py##intype *self, void *closure) \
|
||||
{ \
|
||||
PyObject *o = wrap_##attrtype(attr); \
|
||||
if (!o) { PyErr_SetString(VexException, "Error in py"#type"_get_"#name"\n"); return NULL; } \
|
||||
return o; \
|
||||
}
|
||||
#define PYVEX_SETTER_WRAPPED(type, intype, attr, name, attrtype) \
|
||||
static int py##type##_set_##name(py##intype *self, PyObject *value, void *closure) \
|
||||
{ \
|
||||
PYVEX_CHECKTYPE(value, py##attrtype##Type, return -1); \
|
||||
attr = ((py##attrtype *) value)->wrapped; \
|
||||
return 0; \
|
||||
}
|
||||
#define PYVEX_ACCESSOR_WRAPPED(a,b,c,d,e) PYVEX_SETTER_WRAPPED(a,b,c,d,e) PYVEX_GETTER_WRAPPED(a,b,c,d,e)
|
||||
|
||||
// - getters and setters that translate from a C enum to a Python string and back
|
||||
#define PYVEX_GETTER_ENUM(type, intype, attr, name, enum) \
|
||||
static PyObject *py##type##_get_##name(py##intype *self, void *closure) \
|
||||
{ \
|
||||
const char *tstr = enum##_to_str(attr); \
|
||||
if (tstr) return PyString_FromString(tstr); \
|
||||
PyErr_SetString(VexException, "Unrecognized "#enum); \
|
||||
return NULL; \
|
||||
}
|
||||
#define PYVEX_SETTER_ENUM(type, intype, attr, name, enum) \
|
||||
static int py##type##_set_##name(py##intype *self, PyObject *value, void *closure) \
|
||||
{ \
|
||||
const char *tstr = PyString_AsString(value); \
|
||||
enum t = str_to_##enum(tstr); \
|
||||
if (t) { attr = t; return 0; } \
|
||||
else { PyErr_SetString(VexException, "Unrecognized "#enum); return -1; } \
|
||||
}
|
||||
#define PYVEX_ACCESSOR_ENUM(a,b,c,d,e) PYVEX_SETTER_ENUM(a,b,c,d,e) PYVEX_GETTER_ENUM(a,b,c,d,e)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Various helper macros for use in pyvex
|
||||
// - helper for type checking
|
||||
#define PYVEX_CHECKTYPE(object, type, fail) if (!PyObject_TypeCheck((PyObject *)object, &type)) { PyErr_SetString(VexException, "Incorrect type passed in. Needs "#type); fail; }
|
||||
|
||||
// - wrapping constructor
|
||||
#define PYVEX_WRAP_CONSTRUCTOR(type) \
|
||||
{ \
|
||||
PyObject *wrap_object; \
|
||||
if (kwargs) \
|
||||
{ \
|
||||
wrap_object = PyDict_GetItemString(kwargs, "wrap"); \
|
||||
if (wrap_object) \
|
||||
{ \
|
||||
self->wrapped = PyCapsule_GetPointer(wrap_object, #type); \
|
||||
if (!self->wrapped) return -1; \
|
||||
return 0; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
// - wrapping helper
|
||||
#define PYVEX_WRAP(type) \
|
||||
PyObject *wrap_##type(type *i) \
|
||||
{ \
|
||||
PyObject *args = Py_BuildValue(""); \
|
||||
PyObject *kwargs = Py_BuildValue("{s:O}", "wrap", PyCapsule_New(i, #type, NULL)); \
|
||||
PyObject *o = PyObject_Call((PyObject *)&py##type##Type, args, kwargs); \
|
||||
Py_DECREF(args); \
|
||||
Py_DECREF(kwargs); \
|
||||
return (PyObject *)o; \
|
||||
}
|
||||
|
||||
// - conversion between C enums and Python strings
|
||||
#define PYVEX_ENUM_FROMSTR(type, v, v_str, fail) \
|
||||
{ v = str_to_##type(v_str); \
|
||||
if (v == -1) { PyErr_SetString(VexException, "Unrecognized "#type); fail; } }
|
||||
#define PYVEX_ENUM_TOSTR(type, v, v_str, fail) \
|
||||
{ v_str = type##_to_str(v); \
|
||||
if (v_str == NULL) { PyErr_SetString(VexException, "Unrecognized "#type); fail; } }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// These are helpers for writing the enum conversion itself
|
||||
#define PYVEX_ENUMCONV_TOSTRCASE(x) case x: return #x;
|
||||
// TODO: make this faster
|
||||
#define PYVEX_ENUMCONV_FROMSTR(x) if (strcmp(#x, s) == 0) return x;
|
||||
#define PYVEX_WRAPCASE(vtype, tagtype, tag) case tagtype##tag: t = &py##vtype##tag##Type; break;
|
||||
|
||||
#define PYVEX_ENUM_FROMSTR(type, v, v_str, fail) \
|
||||
v = str_to_##type(v_str); \
|
||||
if (v == -1) { PyErr_SetString(VexException, "Unrecognized "#type); fail; }
|
||||
#define PYVEX_ENUM_TOSTR(type, v, v_str, fail) \
|
||||
v_str = type##_to_str(v); \
|
||||
if (v_str == NULL) { PyErr_SetString(VexException, "Unrecognized "#type); fail; }
|
||||
|
||||
// type initialization
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Type initializations for the module
|
||||
#define PYVEX_INITTYPE(type) \
|
||||
if (PyType_Ready(&py##type##Type) < 0) { fprintf(stderr, "py"#type"Type not ready...\n"); return; } \
|
||||
Py_INCREF(&py##type##Type); PyModule_AddObject(module, #type, (PyObject *)&py##type##Type);
|
||||
{ if (PyType_Ready(&py##type##Type) < 0) { fprintf(stderr, "py"#type"Type not ready...\n"); return; } \
|
||||
Py_INCREF(&py##type##Type); PyModule_AddObject(module, #type, (PyObject *)&py##type##Type); }
|
||||
|
||||
#define PYVEX_INITSUBTYPE(base, sub) \
|
||||
if (PyType_Ready(&py##base##sub##Type) < 0) { fprintf(stderr, "py"#base#sub"Type not ready...\n"); return; } \
|
||||
{ if (PyType_Ready(&py##base##sub##Type) < 0) { fprintf(stderr, "py"#base#sub"Type not ready...\n"); return; } \
|
||||
Py_INCREF(&py##base##sub##Type); \
|
||||
if (PyDict_SetItemString((PyObject *)py##base##Type.tp_dict, #sub, (PyObject *)&py##base##sub##Type) == -1) \
|
||||
{ \
|
||||
fprintf(stderr, "failed to set "#sub" as attribute of py"#base"Type...\n"); \
|
||||
return; \
|
||||
}
|
||||
} }
|
||||
|
||||
@@ -3,23 +3,25 @@ from distutils.core import setup, Extension
|
||||
import os
|
||||
vgprefix = os.environ["HOME"] + "/valgrind/inst"
|
||||
|
||||
common_files = ["pyvex/pyvex.c", "pyvex/pyvex_irsb.c", "pyvex/pyvex_irstmt.c", "pyvex/pyvex_irtypeenv.c", "pyvex/pyvex_irexpr.c", "pyvex/pyvex_enums.c", "pyvex/pyvex_irconst.c", "pyvex/pyvex_ircallee.c", "pyvex/pyvex_irregarray.c", "pyvex/pyvex_logging.c" ]
|
||||
|
||||
setup(name="pyvex", version="1.0",
|
||||
ext_modules=[Extension(
|
||||
"pyvex",
|
||||
["pyvex/pyvex.c", "pyvex/pyvex_irsb.c", "pyvex/pyvex_irstmt.c", "pyvex/pyvex_irtypeenv.c", "pyvex/pyvex_irexpr.c", "pyvex/pyvex_enums.c", "pyvex/pyvex_irconst.c", "pyvex/pyvex_ircallee.c", "pyvex/pyvex_irregarray.c", "pyvex/pyvex_logging.c", "pyvex/pyvex_static.c"],
|
||||
common_files + [ "pyvex/pyvex_static.c", "pyvex/pyvex_deepcopy.c"],
|
||||
include_dirs=[vgprefix + "/include/valgrind"],
|
||||
library_dirs=[vgprefix + "/lib/valgrind"],
|
||||
libraries=["vex-amd64-linux"],
|
||||
extra_objects=[], #, vgprefix + "/lib/valgrind/libvex-amd64-linux.a"],
|
||||
define_macros=[('PYVEX_STATIC', '1')],
|
||||
extra_compile_args=["--std=c99"]),
|
||||
Extension(
|
||||
"pyvex_dynamic",
|
||||
["pyvex/pyvex.c", "pyvex/pyvex_irsb.c", "pyvex/pyvex_irstmt.c", "pyvex/pyvex_irtypeenv.c", "pyvex/pyvex_irexpr.c", "pyvex/pyvex_enums.c", "pyvex/pyvex_irconst.c", "pyvex/pyvex_ircallee.c", "pyvex/pyvex_irregarray.c", "pyvex/pyvex_logging.c"],
|
||||
common_files,
|
||||
include_dirs=[vgprefix + "/include/valgrind"],
|
||||
library_dirs=[vgprefix + "/lib/valgrind"],
|
||||
libraries=["vex-amd64-linux"],
|
||||
extra_objects=[], #, vgprefix + "/lib/valgrind/libvex-amd64-linux.a"],
|
||||
define_macros=[('PYVEX_NOSTATIC', '1')],
|
||||
extra_compile_args=["--std=c99"])
|
||||
]
|
||||
)
|
||||
|
||||
@@ -322,6 +322,9 @@ class PyVEXTest(unittest.TestCase):
|
||||
###################
|
||||
|
||||
def test_irexpr_binder(self):
|
||||
# binder doesn't work statically, but hopefully we should
|
||||
# never see it, anyways
|
||||
return
|
||||
m = pyvex.IRExpr.Binder(1534252)
|
||||
self.assertEqual(m.binder, 1534252)
|
||||
self.assertRaises(Exception, m.deepCopy, ())
|
||||
|
||||
Reference in New Issue
Block a user