|
From: <sv...@va...> - 2008-04-05 11:34:46
|
Author: sewardj
Date: 2008-04-05 12:34:48 +0100 (Sat, 05 Apr 2008)
New Revision: 1820
Log:
Give the IR "AbiHint" construction, a third argument which indicates
the address of the next instruction to be executed. This is needed to
support origin tracking in Memcheck on platforms which use stack
redzones (amd64-linux, ppc64-linux, ppc{32,64}-aix5).
AbiHints indicate places where the redzone below the stack pointer
logically becomes undefined as per that target's calling conventions.
With origin tracking enabled, we must also set the origins of that
undefined area correctly, otherwise origins on stack allocated
undefined values are wrong -- they are often incorrectly reported as
deriving from the current function's caller, or from a function called
by the current function, which has since returned (to the current
function).
Modified:
branches/OTRACK_BY_INSTRUMENTATION/priv/guest-amd64/toIR.c
branches/OTRACK_BY_INSTRUMENTATION/priv/guest-ppc/toIR.c
branches/OTRACK_BY_INSTRUMENTATION/priv/ir/irdefs.c
branches/OTRACK_BY_INSTRUMENTATION/priv/ir/iropt.c
branches/OTRACK_BY_INSTRUMENTATION/pub/libvex_ir.h
Modified: branches/OTRACK_BY_INSTRUMENTATION/priv/guest-amd64/toIR.c
===================================================================
--- branches/OTRACK_BY_INSTRUMENTATION/priv/guest-amd64/toIR.c 2008-04-03 12:17:53 UTC (rev 1819)
+++ branches/OTRACK_BY_INSTRUMENTATION/priv/guest-amd64/toIR.c 2008-04-05 11:34:48 UTC (rev 1820)
@@ -1944,12 +1944,15 @@
}
}
-/* Let new_rsp be the %rsp value after a call/return. This function
- generates an AbiHint to say that -128(%rsp) .. -1(%rsp) should now
- be regarded as uninitialised.
+/* Let new_rsp be the %rsp value after a call/return. Let nia be the
+ guest address of the next instruction to be executed.
+
+ This function generates an AbiHint to say that -128(%rsp)
+ .. -1(%rsp) should now be regarded as uninitialised.
*/
static
-void make_redzone_AbiHint ( VexAbiInfo* vbi, IRTemp new_rsp, HChar* who )
+void make_redzone_AbiHint ( VexAbiInfo* vbi,
+ IRTemp new_rsp, IRTemp nia, HChar* who )
{
Int szB = vbi->guest_stack_redzone_size;
vassert(szB >= 0);
@@ -1961,10 +1964,12 @@
if (0) vex_printf("AbiHint: %s\n", who);
vassert(typeOfIRTemp(irsb->tyenv, new_rsp) == Ity_I64);
+ vassert(typeOfIRTemp(irsb->tyenv, nia) == Ity_I64);
if (szB > 0)
stmt( IRStmt_AbiHint(
binop(Iop_Sub64, mkexpr(new_rsp), mkU64(szB)),
- szB
+ szB,
+ mkexpr(nia)
));
}
@@ -3713,7 +3718,7 @@
assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
putIReg64(R_RSP, mkexpr(t2));
storeLE( mkexpr(t2), mkU64(guest_RIP_bbstart+delta+1));
- make_redzone_AbiHint(vbi, t2, "call-Ev(reg)");
+ make_redzone_AbiHint(vbi, t2, t3/*nia*/, "call-Ev(reg)");
jmp_treg(Ijk_Call,t3);
dres->whatNext = Dis_StopHere;
showSz = False;
@@ -3767,7 +3772,7 @@
assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
putIReg64(R_RSP, mkexpr(t2));
storeLE( mkexpr(t2), mkU64(guest_RIP_bbstart+delta+len));
- make_redzone_AbiHint(vbi, t2, "call-Ev(mem)");
+ make_redzone_AbiHint(vbi, t2, t3/*nia*/, "call-Ev(mem)");
jmp_treg(Ijk_Call,t3);
dres->whatNext = Dis_StopHere;
showSz = False;
@@ -7678,7 +7683,7 @@
assign(t2, loadLE(Ity_I64,mkexpr(t1)));
assign(t3, binop(Iop_Add64, mkexpr(t1), mkU64(8+d64)));
putIReg64(R_RSP, mkexpr(t3));
- make_redzone_AbiHint(vbi, t3, "ret");
+ make_redzone_AbiHint(vbi, t3, t2/*nia*/, "ret");
jmp_treg(Ijk_Ret,t2);
}
@@ -13493,7 +13498,9 @@
assign(t1, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
putIReg64(R_RSP, mkexpr(t1));
storeLE( mkexpr(t1), mkU64(guest_RIP_bbstart+delta));
- make_redzone_AbiHint(vmi, t1, "call-d32");
+ t2 = newTemp(Ity_I64);
+ assign(t2, mkU64((Addr64)d64));
+ make_redzone_AbiHint(vmi, t1, t2/*nia*/, "call-d32");
if (resteerOkFn( callback_opaque, (Addr64)d64) ) {
/* follow into the call target. */
dres.whatNext = Dis_Resteer;
Modified: branches/OTRACK_BY_INSTRUMENTATION/priv/guest-ppc/toIR.c
===================================================================
--- branches/OTRACK_BY_INSTRUMENTATION/priv/guest-ppc/toIR.c 2008-04-03 12:17:53 UTC (rev 1819)
+++ branches/OTRACK_BY_INSTRUMENTATION/priv/guest-ppc/toIR.c 2008-04-05 11:34:48 UTC (rev 1820)
@@ -1217,17 +1217,20 @@
{
Int szB = vbi->guest_stack_redzone_size;
if (0) vex_printf("AbiHint: %s\n", who);
+vassert(0); /*FIXME*/
vassert(szB >= 0);
if (szB > 0) {
if (mode64)
stmt( IRStmt_AbiHint(
binop(Iop_Sub64, getIReg(1), mkU64(szB)),
szB
+,mkU64(0)
));
else
stmt( IRStmt_AbiHint(
binop(Iop_Sub32, getIReg(1), mkU32(szB)),
szB
+,mkU32(0)
));
}
}
Modified: branches/OTRACK_BY_INSTRUMENTATION/priv/ir/irdefs.c
===================================================================
--- branches/OTRACK_BY_INSTRUMENTATION/priv/ir/irdefs.c 2008-04-03 12:17:53 UTC (rev 1819)
+++ branches/OTRACK_BY_INSTRUMENTATION/priv/ir/irdefs.c 2008-04-05 11:34:48 UTC (rev 1820)
@@ -769,7 +769,9 @@
case Ist_AbiHint:
vex_printf("====== AbiHint(");
ppIRExpr(s->Ist.AbiHint.base);
- vex_printf(", %d) ======", s->Ist.AbiHint.len);
+ vex_printf(", %d, ", s->Ist.AbiHint.len);
+ ppIRExpr(s->Ist.AbiHint.nia);
+ vex_printf(") ======");
break;
case Ist_Put:
vex_printf( "PUT(%d) = ", s->Ist.Put.offset);
@@ -1156,11 +1158,12 @@
s->Ist.IMark.len = len;
return s;
}
-IRStmt* IRStmt_AbiHint ( IRExpr* base, Int len ) {
+IRStmt* IRStmt_AbiHint ( IRExpr* base, Int len, IRExpr* nia ) {
IRStmt* s = LibVEX_Alloc(sizeof(IRStmt));
s->tag = Ist_AbiHint;
s->Ist.AbiHint.base = base;
s->Ist.AbiHint.len = len;
+ s->Ist.AbiHint.nia = nia;
return s;
}
IRStmt* IRStmt_Put ( Int off, IRExpr* data ) {
@@ -1384,7 +1387,8 @@
return IRStmt_NoOp();
case Ist_AbiHint:
return IRStmt_AbiHint(deepCopyIRExpr(s->Ist.AbiHint.base),
- s->Ist.AbiHint.len);
+ s->Ist.AbiHint.len,
+ deepCopyIRExpr(s->Ist.AbiHint.nia));
case Ist_IMark:
return IRStmt_IMark(s->Ist.IMark.addr, s->Ist.IMark.len);
case Ist_Put:
@@ -1984,7 +1988,8 @@
switch (st->tag) {
case Ist_AbiHint:
- return isIRAtom(st->Ist.AbiHint.base);
+ return isIRAtom(st->Ist.AbiHint.base)
+ && isIRAtom(st->Ist.AbiHint.nia);
case Ist_Put:
return isIRAtom(st->Ist.Put.data);
case Ist_PutI:
@@ -2194,6 +2199,7 @@
break;
case Ist_AbiHint:
useBeforeDef_Expr(bb,stmt,stmt->Ist.AbiHint.base,def_counts);
+ useBeforeDef_Expr(bb,stmt,stmt->Ist.AbiHint.nia,def_counts);
break;
case Ist_Put:
useBeforeDef_Expr(bb,stmt,stmt->Ist.Put.data,def_counts);
@@ -2447,6 +2453,9 @@
if (typeOfIRExpr(tyenv, stmt->Ist.AbiHint.base) != gWordTy)
sanityCheckFail(bb,stmt,"IRStmt.AbiHint.base: "
"not :: guest word type");
+ if (typeOfIRExpr(tyenv, stmt->Ist.AbiHint.nia) != gWordTy)
+ sanityCheckFail(bb,stmt,"IRStmt.AbiHint.nia: "
+ "not :: guest word type");
break;
case Ist_Put:
tcExpr( bb, stmt, stmt->Ist.Put.data, gWordTy );
Modified: branches/OTRACK_BY_INSTRUMENTATION/priv/ir/iropt.c
===================================================================
--- branches/OTRACK_BY_INSTRUMENTATION/priv/ir/iropt.c 2008-04-03 12:17:53 UTC (rev 1819)
+++ branches/OTRACK_BY_INSTRUMENTATION/priv/ir/iropt.c 2008-04-05 11:34:48 UTC (rev 1820)
@@ -448,7 +448,8 @@
break;
case Ist_AbiHint:
e1 = flatten_Expr(bb, st->Ist.AbiHint.base);
- addStmtToIRSB(bb, IRStmt_AbiHint(e1, st->Ist.AbiHint.len));
+ e2 = flatten_Expr(bb, st->Ist.AbiHint.nia);
+ addStmtToIRSB(bb, IRStmt_AbiHint(e1, st->Ist.AbiHint.len, e2));
break;
case Ist_Exit:
e1 = flatten_Expr(bb, st->Ist.Exit.guard);
@@ -712,6 +713,7 @@
AbiHints.*/
case Ist_AbiHint:
vassert(isIRAtom(st->Ist.AbiHint.base));
+ vassert(isIRAtom(st->Ist.AbiHint.nia));
/* fall through */
case Ist_MBE:
case Ist_Dirty:
@@ -1707,9 +1709,11 @@
switch (st->tag) {
case Ist_AbiHint:
vassert(isIRAtom(st->Ist.AbiHint.base));
+ vassert(isIRAtom(st->Ist.AbiHint.nia));
return IRStmt_AbiHint(
fold_Expr(subst_Expr(env, st->Ist.AbiHint.base)),
- st->Ist.AbiHint.len
+ st->Ist.AbiHint.len,
+ fold_Expr(subst_Expr(env, st->Ist.AbiHint.nia))
);
case Ist_Put:
vassert(isIRAtom(st->Ist.Put.data));
@@ -1953,6 +1957,7 @@
switch (st->tag) {
case Ist_AbiHint:
addUses_Expr(set, st->Ist.AbiHint.base);
+ addUses_Expr(set, st->Ist.AbiHint.nia);
return;
case Ist_PutI:
addUses_Expr(set, st->Ist.PutI.ix);
@@ -3221,6 +3226,7 @@
break;
case Ist_AbiHint:
deltaIRExpr(st->Ist.AbiHint.base, delta);
+ deltaIRExpr(st->Ist.AbiHint.nia, delta);
break;
case Ist_Put:
deltaIRExpr(st->Ist.Put.data, delta);
@@ -3677,6 +3683,7 @@
switch (st->tag) {
case Ist_AbiHint:
aoccCount_Expr(uses, st->Ist.AbiHint.base);
+ aoccCount_Expr(uses, st->Ist.AbiHint.nia);
return;
case Ist_WrTmp:
aoccCount_Expr(uses, st->Ist.WrTmp.data);
@@ -3908,7 +3915,8 @@
case Ist_AbiHint:
return IRStmt_AbiHint(
atbSubst_Expr(env, st->Ist.AbiHint.base),
- st->Ist.AbiHint.len
+ st->Ist.AbiHint.len,
+ atbSubst_Expr(env, st->Ist.AbiHint.nia)
);
case Ist_Store:
return IRStmt_Store(
@@ -4241,6 +4249,7 @@
switch (st->tag) {
case Ist_AbiHint:
vassert(isIRAtom(st->Ist.AbiHint.base));
+ vassert(isIRAtom(st->Ist.AbiHint.nia));
break;
case Ist_PutI:
*hasGetIorPutI = True;
Modified: branches/OTRACK_BY_INSTRUMENTATION/pub/libvex_ir.h
===================================================================
--- branches/OTRACK_BY_INSTRUMENTATION/pub/libvex_ir.h 2008-04-03 12:17:53 UTC (rev 1819)
+++ branches/OTRACK_BY_INSTRUMENTATION/pub/libvex_ir.h 2008-04-05 11:34:48 UTC (rev 1820)
@@ -1412,14 +1412,17 @@
that a given chunk of address space, [base .. base+len-1],
has become undefined. This is used on amd64-linux and
some ppc variants to pass stack-redzoning hints to whoever
- wants to see them.
+ wants to see them. It also indicates the address of the
+ next (dynamic) instruction that will be executed. This is
+ to help Memcheck to origin tracking.
- ppIRExpr output: ====== AbiHint(<base>, <len>) ======
- eg. ====== AbiHint(t1, 16) ======
+ ppIRExpr output: ====== AbiHint(<base>, <len>, <nia>) ======
+ eg. ====== AbiHint(t1, 16, t2) ======
*/
struct {
IRExpr* base; /* Start of undefined chunk */
Int len; /* Length of undefined chunk */
+ IRExpr* nia; /* Address of next (guest) insn */
} AbiHint;
/* Write a guest register, at a fixed offset in the guest state.
@@ -1506,7 +1509,7 @@
/* Statement constructors. */
extern IRStmt* IRStmt_NoOp ( void );
extern IRStmt* IRStmt_IMark ( Addr64 addr, Int len );
-extern IRStmt* IRStmt_AbiHint ( IRExpr* base, Int len );
+extern IRStmt* IRStmt_AbiHint ( IRExpr* base, Int len, IRExpr* nia );
extern IRStmt* IRStmt_Put ( Int off, IRExpr* data );
extern IRStmt* IRStmt_PutI ( IRRegArray* descr, IRExpr* ix, Int bias,
IRExpr* data );
|