mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-15 07:07:01 +00:00
Finish off Memcheck's handling of dirty helper calls. Memcheck is now
feature-complete (!) git-svn-id: svn://svn.valgrind.org/vex/trunk@534
This commit is contained in:
@@ -1032,6 +1032,7 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
|
||||
return assignNew(mce, Ity_Bit, unop(Iop_32to1, vatom));
|
||||
|
||||
case Iop_ReinterpF64asI64:
|
||||
case Iop_ReinterpI64asF64:
|
||||
case Iop_Not32:
|
||||
case Iop_Not16:
|
||||
case Iop_Not8:
|
||||
@@ -1045,12 +1046,13 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
|
||||
|
||||
|
||||
static
|
||||
IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr )
|
||||
IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
|
||||
{
|
||||
void* helper;
|
||||
Char* hname;
|
||||
IRDirty* di;
|
||||
IRTemp datavbits;
|
||||
IRAtom* addrAct;
|
||||
|
||||
sk_assert(isOriginalAtom(mce,addr));
|
||||
|
||||
@@ -1078,11 +1080,23 @@ IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr )
|
||||
VG_(skin_panic)("memcheck:do_shadow_LDle");
|
||||
}
|
||||
|
||||
/* Generate the actual address into addrAct. */
|
||||
if (bias == 0) {
|
||||
addrAct = addr;
|
||||
} else {
|
||||
IRType tyAddr = mce->hWordTy;
|
||||
sk_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
|
||||
IROp mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
|
||||
IRAtom* eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
|
||||
addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
|
||||
}
|
||||
|
||||
/* We need to have a place to park the V bits we're just about to
|
||||
read. */
|
||||
datavbits = newIRTemp(mce->bb->tyenv, ty);
|
||||
di = unsafeIRDirty_1_N( datavbits,
|
||||
1/*regparms*/, hname, helper, mkIRExprVec_1( addr ));
|
||||
1/*regparms*/, hname, helper,
|
||||
mkIRExprVec_1( addrAct ));
|
||||
setHelperAnns( mce, di );
|
||||
stmt( mce->bb, IRStmt_Dirty(di) );
|
||||
|
||||
@@ -1146,7 +1160,8 @@ IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
|
||||
return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
|
||||
|
||||
case Iex_LDle:
|
||||
return expr2vbits_LDle( mce, e->Iex.LDle.ty, e->Iex.LDle.addr );
|
||||
return expr2vbits_LDle( mce, e->Iex.LDle.ty,
|
||||
e->Iex.LDle.addr, 0/*addr bias*/ );
|
||||
|
||||
case Iex_CCall:
|
||||
return mkLazyN( mce, e->Iex.CCall.args,
|
||||
@@ -1196,27 +1211,41 @@ IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
|
||||
}
|
||||
|
||||
|
||||
/* Generate a shadow store. addr is always the original address atom.
|
||||
You can pass in either originals or V-bits for the data atom, but
|
||||
obviously not both. */
|
||||
|
||||
static
|
||||
void do_shadow_STle ( MCEnv* mce, IRAtom* addr, IRAtom* data )
|
||||
void do_shadow_STle ( MCEnv* mce,
|
||||
IRAtom* addr, UInt bias,
|
||||
IRAtom* data, IRAtom* vdata )
|
||||
{
|
||||
IRType ty;
|
||||
IRDirty* di;
|
||||
IRExpr* datavbits;
|
||||
void* helper = NULL;
|
||||
Char* hname = NULL;
|
||||
IRAtom* addrAct;
|
||||
|
||||
ty = shadowType(typeOfIRExpr(mce->bb->tyenv, data));
|
||||
if (data) {
|
||||
sk_assert(!vdata);
|
||||
sk_assert(isOriginalAtom(mce, data));
|
||||
sk_assert(bias == 0);
|
||||
vdata = expr2vbits( mce, data );
|
||||
} else {
|
||||
sk_assert(vdata);
|
||||
}
|
||||
|
||||
sk_assert(isOriginalAtom(mce,addr));
|
||||
sk_assert(isOriginalAtom(mce,data));
|
||||
sk_assert(isShadowAtom(mce,vdata));
|
||||
|
||||
ty = typeOfIRExpr(mce->bb->tyenv, vdata);
|
||||
|
||||
/* First, emit a definedness test for the address. This also sets
|
||||
the address (shadow) to 'defined' following the test. */
|
||||
complainIfUndefined( mce, addr);
|
||||
complainIfUndefined( mce, addr );
|
||||
|
||||
/* Now cook up a call to the relevant helper function, to write the
|
||||
data V bits into shadow memory. */
|
||||
datavbits = expr2vbits( mce, data );
|
||||
switch (ty) {
|
||||
case Ity_I64: helper = &MC_(helperc_STOREV8);
|
||||
hname = "MC_(helperc_STOREV8)";
|
||||
@@ -1233,18 +1262,29 @@ void do_shadow_STle ( MCEnv* mce, IRAtom* addr, IRAtom* data )
|
||||
default: VG_(skin_panic)("memcheck:do_shadow_STle");
|
||||
}
|
||||
|
||||
/* Generate the actual address into addrAct. */
|
||||
if (bias == 0) {
|
||||
addrAct = addr;
|
||||
} else {
|
||||
IRType tyAddr = mce->hWordTy;
|
||||
sk_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
|
||||
IROp mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
|
||||
IRAtom* eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
|
||||
addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
|
||||
}
|
||||
|
||||
if (ty == Ity_I64) {
|
||||
/* We can't do this with regparm 2 on 32-bit platforms, since
|
||||
the back ends aren't clever enough to handle 64-bit regparm
|
||||
args. Therefore be different. */
|
||||
di = unsafeIRDirty_0_N(
|
||||
1/*regparms*/, hname, helper,
|
||||
mkIRExprVec_2( addr, datavbits ));
|
||||
mkIRExprVec_2( addrAct, vdata ));
|
||||
} else {
|
||||
di = unsafeIRDirty_0_N(
|
||||
2/*regparms*/, hname, helper,
|
||||
mkIRExprVec_2( addr,
|
||||
zwidenToHostWord( mce, datavbits )));
|
||||
mkIRExprVec_2( addrAct,
|
||||
zwidenToHostWord( mce, vdata )));
|
||||
}
|
||||
setHelperAnns( mce, di );
|
||||
stmt( mce->bb, IRStmt_Dirty(di) );
|
||||
@@ -1269,11 +1309,10 @@ static IRType szToITy ( Int n )
|
||||
static
|
||||
void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
|
||||
{
|
||||
Int i, offset, toDo;
|
||||
IRAtom *two, *four, *addr, *src;
|
||||
IROp opAdd;
|
||||
IRType tyAddr, tySrc, tyDst;
|
||||
IRTemp dst;
|
||||
Int i, offset, toDo;
|
||||
IRAtom* src;
|
||||
IRType tyAddr, tySrc, tyDst;
|
||||
IRTemp dst;
|
||||
|
||||
/* First check the guard. */
|
||||
complainIfUndefined(mce, d->guard);
|
||||
@@ -1308,8 +1347,6 @@ void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
|
||||
|
||||
/* Inputs: memory. First set up some info needed regardless of
|
||||
whether we're doing reads or writes. */
|
||||
four = two = NULL;
|
||||
opAdd = Iop_INVALID;
|
||||
tyAddr = Ity_INVALID;
|
||||
|
||||
if (d->mFx != Ifx_None) {
|
||||
@@ -1322,36 +1359,31 @@ void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
|
||||
|
||||
tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
|
||||
sk_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
|
||||
opAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
|
||||
four = tyAddr==Ity_I32 ? mkU32(4) : mkU64(4);
|
||||
two = tyAddr==Ity_I32 ? mkU32(2) : mkU64(2);
|
||||
sk_assert(tyAddr == mce->hWordTy); /* not really right */
|
||||
}
|
||||
|
||||
/* Deal with memory inputs (reads or modifies) */
|
||||
if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
|
||||
offset = 0;
|
||||
toDo = d->mSize;
|
||||
addr = d->mAddr;
|
||||
/* chew off 32-bit chunks */
|
||||
while (toDo >= 4) {
|
||||
here = mkPCastTo(
|
||||
mce, Ity_I32,
|
||||
expr2vbits_LDle ( mce, Ity_I32, addr )
|
||||
expr2vbits_LDle ( mce, Ity_I32,
|
||||
d->mAddr, d->mSize - toDo )
|
||||
);
|
||||
curr = mkUifU32(mce, here, curr);
|
||||
addr = assignNew(mce, tyAddr,
|
||||
binop(opAdd, addr, four));
|
||||
toDo -= 4;
|
||||
}
|
||||
/* chew off 16-bit chunks */
|
||||
while (toDo >= 2) {
|
||||
here = mkPCastTo(
|
||||
mce, Ity_I32,
|
||||
expr2vbits_LDle ( mce, Ity_I16, addr )
|
||||
expr2vbits_LDle ( mce, Ity_I16,
|
||||
d->mAddr, d->mSize - toDo )
|
||||
);
|
||||
curr = mkUifU32(mce, here, curr);
|
||||
addr = assignNew(mce, tyAddr,
|
||||
binop(opAdd, addr, two));
|
||||
toDo -= 2;
|
||||
}
|
||||
sk_assert(toDo == 0); /* also need to handle 1-byte excess */
|
||||
@@ -1385,21 +1417,18 @@ void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
|
||||
if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
|
||||
offset = 0;
|
||||
toDo = d->mSize;
|
||||
addr = d->mAddr;
|
||||
/* chew off 32-bit chunks */
|
||||
while (toDo >= 4) {
|
||||
do_shadow_STle( mce, addr,
|
||||
do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
|
||||
NULL, /* original data */
|
||||
mkPCastTo( mce, Ity_I32, curr ) );
|
||||
addr = assignNew(mce, tyAddr,
|
||||
binop(opAdd, addr, four));
|
||||
toDo -= 4;
|
||||
}
|
||||
/* chew off 16-bit chunks */
|
||||
while (toDo >= 2) {
|
||||
do_shadow_STle( mce, addr,
|
||||
mkPCastTo( mce, Ity_I32, curr ) );
|
||||
addr = assignNew(mce, tyAddr,
|
||||
binop(opAdd, addr, two));
|
||||
do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
|
||||
NULL, /* original data */
|
||||
mkPCastTo( mce, Ity_I16, curr ) );
|
||||
toDo -= 2;
|
||||
}
|
||||
sk_assert(toDo == 0); /* also need to handle 1-byte excess */
|
||||
@@ -1556,7 +1585,9 @@ IRBB* SK_(instrument) ( IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
|
||||
break;
|
||||
|
||||
case Ist_STle:
|
||||
do_shadow_STle( &mce, st->Ist.STle.addr, st->Ist.STle.data );
|
||||
do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
|
||||
st->Ist.STle.data,
|
||||
NULL /* shadow data */ );
|
||||
break;
|
||||
|
||||
case Ist_Exit:
|
||||
|
||||
Reference in New Issue
Block a user