|
From: <sv...@va...> - 2008-04-05 11:36:30
|
Author: sewardj
Date: 2008-04-05 12:36:35 +0100 (Sat, 05 Apr 2008)
New Revision: 7844
Log:
Understand and use the new third field in IR AbiHints (the
next-instruction-address field). This essentially makes Memcheck's
origin tracking work correctly for stack allocated values on
amd64-linux.
Modified:
branches/OTRACK_BY_INSTRUMENTATION/memcheck/mc_include.h
branches/OTRACK_BY_INSTRUMENTATION/memcheck/mc_main.c
branches/OTRACK_BY_INSTRUMENTATION/memcheck/mc_translate.c
Modified: branches/OTRACK_BY_INSTRUMENTATION/memcheck/mc_include.h
===================================================================
--- branches/OTRACK_BY_INSTRUMENTATION/memcheck/mc_include.h 2008-04-04 19:10:21 UTC (rev 7843)
+++ branches/OTRACK_BY_INSTRUMENTATION/memcheck/mc_include.h 2008-04-05 11:36:35 UTC (rev 7844)
@@ -320,7 +320,7 @@
extern VG_REGPARM(1) UWord MC_(helperc_LOADV8) ( Addr );
extern void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len,
- UInt otag );
+ Addr nia );
VG_REGPARM(2) void MC_(helperc_b_store1) ( Addr a, UWord d32 );
VG_REGPARM(2) void MC_(helperc_b_store2) ( Addr a, UWord d32 );
Modified: branches/OTRACK_BY_INSTRUMENTATION/memcheck/mc_main.c
===================================================================
--- branches/OTRACK_BY_INSTRUMENTATION/memcheck/mc_main.c 2008-04-04 19:10:21 UTC (rev 7843)
+++ branches/OTRACK_BY_INSTRUMENTATION/memcheck/mc_main.c 2008-04-05 11:36:35 UTC (rev 7844)
@@ -2380,12 +2380,65 @@
with defined values and g could mistakenly read them. So the RZ
also needs to be nuked on function calls.
*/
-void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len, UInt otag )
+
+
+/* Here's a simple cache to hold nia -> otag mappings. It could be
+ improved so as to have a lower miss rate. */
+
+static UWord stats__nia_cache_queries = 0;
+static UWord stats__nia_cache_misses = 0;
+
+typedef
+ struct { UWord arg1; UWord res; }
+ WCacheEnt;
+
+#define N_NIA_TO_OTAG_CACHE 511
+
+static WCacheEnt nia_to_otag_cache[N_NIA_TO_OTAG_CACHE];
+
+static void init_nia_to_otag_cache ( void ) {
+ VG_(memset)( &nia_to_otag_cache, 0, sizeof(nia_to_otag_cache) );
+}
+
+static inline UInt convert_nia_to_otag ( Addr nia )
{
+ UWord i;
+ UInt otag;
+ ExeContext* ec;
+
+ tl_assert( sizeof(nia_to_otag_cache[0].arg1) == sizeof(nia) );
+
+ stats__nia_cache_queries++;
+ i = nia % N_NIA_TO_OTAG_CACHE;
+ tl_assert(i >= 0 && i < N_NIA_TO_OTAG_CACHE);
+
+ if (LIKELY( nia_to_otag_cache[i].arg1 == nia ))
+ return nia_to_otag_cache[i].res;
+
+ stats__nia_cache_misses++;
+ ec = VG_(make_depth_1_ExeContext_from_Addr)(nia);
+ tl_assert(ec);
+ otag = VG_(get_ExeContext_uniq)(ec);
+ tl_assert(otag > 0);
+
+ nia_to_otag_cache[i].arg1 = nia;
+ nia_to_otag_cache[i].res = (UWord)otag;
+ return otag;
+}
+
+
+
+void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len, Addr nia )
+{
+ UInt otag;
tl_assert(sizeof(UWord) == sizeof(SizeT));
if (0)
- VG_(printf)("helperc_MAKE_STACK_UNINIT %p %lu\n", base, len );
+ VG_(printf)("helperc_MAKE_STACK_UNINIT (%p,%lu,nia=%p)\n",
+ base, len, nia );
+ otag = convert_nia_to_otag ( nia );
+ tl_assert(otag > 0);
+
# if 0
/* Really slow version */
MC_(make_mem_undefined)(base, len, otag);
@@ -5635,6 +5688,9 @@
- stats__ocacheline_found_at_N,
stats__ocacheline_found_at_1,
stats__ocacheline_found_at_N );
+ VG_(message)(Vg_DebugMsg,
+ " niacache: %,12lu finds %,12lu misses",
+ stats__nia_cache_queries, stats__nia_cache_misses);
}
if (0) {
@@ -5767,6 +5823,7 @@
tl_assert(-1 != VG_(log2)(BYTES_PER_SEC_VBIT_NODE));
init_OCache();
+ init_nia_to_otag_cache();
}
VG_DETERMINE_INTERFACE_VERSION(mc_pre_clo_init)
Modified: branches/OTRACK_BY_INSTRUMENTATION/memcheck/mc_translate.c
===================================================================
--- branches/OTRACK_BY_INSTRUMENTATION/memcheck/mc_translate.c 2008-04-04 19:10:21 UTC (rev 7843)
+++ branches/OTRACK_BY_INSTRUMENTATION/memcheck/mc_translate.c 2008-04-05 11:36:35 UTC (rev 7844)
@@ -3220,6 +3220,7 @@
void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len,
UInt otag );
*/
+#if 0
static
void do_AbiHint ( MCEnv* mce, IRExpr* base, Int len, Addr64 guest_IP )
{
@@ -3243,8 +3244,30 @@
);
stmt( 'V', mce, IRStmt_Dirty(di) );
}
+#else
+/* We have an ABI hint telling us that [base .. base+len-1] is to
+ become undefined ("writable"). Generate code to call a helper to
+ notify the A/V bit machinery of this fact.
+ We call
+ void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len,
+ Addr nia );
+*/
+static
+void do_AbiHint ( MCEnv* mce, IRExpr* base, Int len, IRExpr* nia )
+{
+ IRDirty* di;
+ di = unsafeIRDirty_0_N(
+ 0/*regparms*/,
+ "MC_(helperc_MAKE_STACK_UNINIT)",
+ VG_(fnptr_to_fnentry)( &MC_(helperc_MAKE_STACK_UNINIT) ),
+ mkIRExprVec_3( base, mkIRExpr_HWord( (UInt)len), nia )
+ );
+ stmt( 'V', mce, IRStmt_Dirty(di) );
+}
+#endif
+
/*------------------------------------------------------------*/
/*--- Memcheck main ---*/
/*------------------------------------------------------------*/
@@ -3347,7 +3370,8 @@
case Ist_Exit:
return isBogusAtom(st->Ist.Exit.guard);
case Ist_AbiHint:
- return isBogusAtom(st->Ist.AbiHint.base);
+ return isBogusAtom(st->Ist.AbiHint.base)
+ || isBogusAtom(st->Ist.AbiHint.nia);
case Ist_NoOp:
case Ist_IMark:
case Ist_MBE:
@@ -3560,8 +3584,9 @@
IMark is supposed to be at the start of *every*
instruction's IR. Hence this should never fail. */
tl_assert(curr_IP_known);
- do_AbiHint( &mce, st->Ist.AbiHint.base, st->Ist.AbiHint.len,
- curr_IP );
+ do_AbiHint( &mce, st->Ist.AbiHint.base,
+ st->Ist.AbiHint.len,
+ st->Ist.AbiHint.nia );
break;
default:
@@ -4452,7 +4477,7 @@
case Ist_AbiHint:
/* The value-check instrumenter handles this - by arranging
- to pass an origin-check tag to
+ to pass the address of the next instruction to
MC_(helperc_MAKE_STACK_UNINIT). This is all that needs to
happen for origin tracking w.r.t. AbiHints. So there is
nothing to do here. */
|