diff --git a/README.md b/README.md index 505883d..325854f 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/generate_deepcopy.sh b/generate_deepcopy.sh new file mode 100755 index 0000000..d5a091f --- /dev/null +++ b/generate_deepcopy.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +VALGRIND_HOME=~/valgrind/valgrind-3.8.1/ + +cat > pyvex/pyvex_deepcopy.c < +#include +#include + +#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 diff --git a/pyvex/pyvex.c b/pyvex/pyvex.c index e529aec..c8092cd 100644 --- a/pyvex/pyvex.c +++ b/pyvex/pyvex.c @@ -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"); diff --git a/pyvex/pyvex_deepcopy.c b/pyvex/pyvex_deepcopy.c new file mode 100644 index 0000000..4615686 --- /dev/null +++ b/pyvex/pyvex_deepcopy.c @@ -0,0 +1,254 @@ +#include +#include +#include + +#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 ---*/ diff --git a/pyvex/pyvex_deepcopy.h b/pyvex/pyvex_deepcopy.h new file mode 100644 index 0000000..3c6d83c --- /dev/null +++ b/pyvex/pyvex_deepcopy.h @@ -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 ); diff --git a/pyvex/pyvex_ircallee.c b/pyvex/pyvex_ircallee.c index 6d359aa..31e3591 100644 --- a/pyvex/pyvex_ircallee.c +++ b/pyvex/pyvex_ircallee.c @@ -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; } diff --git a/pyvex/pyvex_irconst.c b/pyvex/pyvex_irconst.c index 4f21ad5..078ef78 100644 --- a/pyvex/pyvex_irconst.c +++ b/pyvex/pyvex_irconst.c @@ -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; \ } \ \ diff --git a/pyvex/pyvex_irexpr.c b/pyvex/pyvex_irexpr.c index 4470626..7d72f21 100644 --- a/pyvex/pyvex_irexpr.c +++ b/pyvex/pyvex_irexpr.c @@ -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) diff --git a/pyvex/pyvex_irregarray.c b/pyvex/pyvex_irregarray.c index c7c6078..3a57e6b 100644 --- a/pyvex/pyvex_irregarray.c +++ b/pyvex/pyvex_irregarray.c @@ -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; } diff --git a/pyvex/pyvex_irsb.c b/pyvex/pyvex_irsb.c index d7c6ff9..999e519 100644 --- a/pyvex/pyvex_irsb.c +++ b/pyvex/pyvex_irsb.c @@ -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; diff --git a/pyvex/pyvex_irstmt.c b/pyvex/pyvex_irstmt.c index ef26eaa..98d7f4c 100644 --- a/pyvex/pyvex_irstmt.c +++ b/pyvex/pyvex_irstmt.c @@ -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; } diff --git a/pyvex/pyvex_irtypeenv.c b/pyvex/pyvex_irtypeenv.c index a884115..7eb42f2 100644 --- a/pyvex/pyvex_irtypeenv.c +++ b/pyvex/pyvex_irtypeenv.c @@ -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."); diff --git a/pyvex/pyvex_macros.h b/pyvex/pyvex_macros.h index 565bcba..38ae00d 100644 --- a/pyvex/pyvex_macros.h +++ b/pyvex/pyvex_macros.h @@ -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; \ - } + } } diff --git a/setup.py b/setup.py index 527dc88..d47f4c0 100644 --- a/setup.py +++ b/setup.py @@ -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"]) ] ) diff --git a/test.py b/test.py index faef1c5..96d05c3 100644 --- a/test.py +++ b/test.py @@ -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, ())