|
From: <sv...@va...> - 2009-09-19 00:51:39
|
Author: sewardj
Date: 2009-09-19 01:15:36 +0100 (Sat, 19 Sep 2009)
New Revision: 10893
Log:
The shadow memory reads/tests for 16-byte loads are done using two
calls to MC_(helperc_LOADV64{le,be}), one at the base address and one
at the base address + 8. This commit marks the split halves so that
in C_(helperc_LOADV64{le,be}) it is possible to know whether the call
results from a 64- or 128-bit load in the original code, and in the
latter case, which half it is.
There's also beginnings of logic to ignore addressing errors from
128-bit loads under certain circumstances, to do with dealing with
SSE2-based strlen implementations.
Modified:
branches/ICC111/memcheck/mc_include.h
branches/ICC111/memcheck/mc_main.c
branches/ICC111/memcheck/mc_translate.c
Modified: branches/ICC111/memcheck/mc_include.h
===================================================================
--- branches/ICC111/memcheck/mc_include.h 2009-09-18 23:03:38 UTC (rev 10892)
+++ branches/ICC111/memcheck/mc_include.h 2009-09-19 00:15:36 UTC (rev 10893)
@@ -458,22 +458,38 @@
VG_REGPARM(0) void MC_(helperc_value_check1_fail_no_o) ( void );
VG_REGPARM(0) void MC_(helperc_value_check0_fail_no_o) ( void );
-/* V-bits load/store helpers */
+/* V-bits load/store helpers. 64-bit loads have 3 variants: the plain
+ variant, which really is 64-bit, and the LA64of128 and HA64of128
+ variants, which denote that the load is actually the low or high
+ addressed half of a 128-bit load. These variants all behave the
+ same in the fast paths; they are only distinguished so that
+ mc_LOADVn_slow knows they are components of 128-bit loads when it
+ comes to deciding the precise circumstances under which an
+ addressing error should be reported. */
+
+typedef
+ enum { MoNone=99, MoLA64of128, MoHA64of128 }
+ Modifier;
+
VG_REGPARM(1) void MC_(helperc_STOREV64be) ( Addr, ULong );
VG_REGPARM(1) void MC_(helperc_STOREV64le) ( Addr, ULong );
VG_REGPARM(2) void MC_(helperc_STOREV32be) ( Addr, UWord );
VG_REGPARM(2) void MC_(helperc_STOREV32le) ( Addr, UWord );
VG_REGPARM(2) void MC_(helperc_STOREV16be) ( Addr, UWord );
VG_REGPARM(2) void MC_(helperc_STOREV16le) ( Addr, UWord );
-VG_REGPARM(2) void MC_(helperc_STOREV8) ( Addr, UWord );
+VG_REGPARM(2) void MC_(helperc_STOREV8) ( Addr, UWord );
-VG_REGPARM(1) ULong MC_(helperc_LOADV64be) ( Addr );
-VG_REGPARM(1) ULong MC_(helperc_LOADV64le) ( Addr );
-VG_REGPARM(1) UWord MC_(helperc_LOADV32be) ( Addr );
-VG_REGPARM(1) UWord MC_(helperc_LOADV32le) ( Addr );
-VG_REGPARM(1) UWord MC_(helperc_LOADV16be) ( Addr );
-VG_REGPARM(1) UWord MC_(helperc_LOADV16le) ( Addr );
-VG_REGPARM(1) UWord MC_(helperc_LOADV8) ( Addr );
+VG_REGPARM(1) ULong MC_(helperc_LOADV64be) ( Addr );
+VG_REGPARM(1) ULong MC_(helperc_LOADV64be_LA64of128) ( Addr );
+VG_REGPARM(1) ULong MC_(helperc_LOADV64be_HA64of128) ( Addr );
+VG_REGPARM(1) ULong MC_(helperc_LOADV64le) ( Addr );
+VG_REGPARM(1) ULong MC_(helperc_LOADV64le_LA64of128) ( Addr );
+VG_REGPARM(1) ULong MC_(helperc_LOADV64le_HA64of128) ( Addr );
+VG_REGPARM(1) UWord MC_(helperc_LOADV32be) ( Addr );
+VG_REGPARM(1) UWord MC_(helperc_LOADV32le) ( Addr );
+VG_REGPARM(1) UWord MC_(helperc_LOADV16be) ( Addr );
+VG_REGPARM(1) UWord MC_(helperc_LOADV16le) ( Addr );
+VG_REGPARM(1) UWord MC_(helperc_LOADV8) ( Addr );
void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len,
Addr nia );
Modified: branches/ICC111/memcheck/mc_main.c
===================================================================
--- branches/ICC111/memcheck/mc_main.c 2009-09-18 23:03:38 UTC (rev 10892)
+++ branches/ICC111/memcheck/mc_main.c 2009-09-19 00:15:36 UTC (rev 10893)
@@ -1151,7 +1151,7 @@
#ifndef PERF_FAST_LOADV
INLINE
#endif
-ULong mc_LOADVn_slow ( Addr a, SizeT nBits, Bool bigendian )
+ULong mc_LOADVn_slow ( Addr a, SizeT nBits, Bool bigendian, Modifier mo )
{
/* Make up a 64-bit result V word, which contains the loaded data for
valid addresses and Defined for invalid addresses. Iterate over
@@ -1162,7 +1162,6 @@
SSizeT i; // Must be signed.
SizeT n_addrs_bad = 0;
Addr ai;
- Bool partial_load_exemption_applies;
UChar vbits8;
Bool ok;
@@ -1211,26 +1210,37 @@
vbits64 |= vbits8;
}
- /* This is a hack which avoids producing errors for code which
- insists in stepping along byte strings in aligned word-sized
- chunks, and there is a partially defined word at the end. (eg,
- optimised strlen). Such code is basically broken at least WRT
- semantics of ANSI C, but sometimes users don't have the option
- to fix it, and so this option is provided. Note it is now
- defaulted to not-engaged.
+ /* If there's an addressing error, report it, unless we can find
+ some reason to ignore it. */
+ if (n_addrs_bad > 0) {
+ /* This is a hack which avoids producing errors for code which
+ insists in stepping along byte strings in aligned word-sized
+ chunks, and there is a partially defined word at the end.
+ (eg, optimised strlen). Such code is basically broken at
+ least WRT semantics of ANSI C, but sometimes users don't have
+ the option to fix it, and so this option is provided. Note
+ it is now defaulted to not-engaged.
- A load from a partially-addressible place is allowed if:
- - the command-line flag is set
- - it's a word-sized, word-aligned load
- - at least one of the addresses in the word *is* valid
- */
- partial_load_exemption_applies
- = MC_(clo_partial_loads_ok) && szB == VG_WORDSIZE
- && VG_IS_WORD_ALIGNED(a)
- && n_addrs_bad < VG_WORDSIZE;
+ A load from a partially-addressible place is allowed if:
+ - the command-line flag is set
+ - it's a word-sized, word-aligned load
+ - at least one of the addresses in the word *is* valid
+ */
+ Bool partial_load_exemption_applies
+ = MC_(clo_partial_loads_ok)
+ && szB == VG_WORDSIZE
+ && VG_IS_WORD_ALIGNED(a)
+ && n_addrs_bad < VG_WORDSIZE;
+ Bool sse2_strlen_exemption_applies
+ = szB == 8
+ && (mo == MoLA64of128 || mo == MoHA64of128);
- if (n_addrs_bad > 0 && !partial_load_exemption_applies)
- MC_(record_address_error)( VG_(get_running_tid)(), a, szB, False );
+ /* If we can't find any reason not to, report the error. */
+ if (! (partial_load_exemption_applies
+ || sse2_strlen_exemption_applies))
+ MC_(record_address_error)( VG_(get_running_tid)(),
+ a, szB, False );
+ }
return vbits64;
}
@@ -3921,7 +3931,7 @@
/* ------------------------ Size = 8 ------------------------ */
static INLINE
-ULong mc_LOADV64 ( Addr a, Bool isBigEndian )
+ULong mc_LOADV64 ( Addr a, Bool isBigEndian, Modifier mo )
{
PROF_EVENT(200, "mc_LOADV64");
@@ -3934,7 +3944,7 @@
if (UNLIKELY( UNALIGNED_OR_HIGH(a,64) )) {
PROF_EVENT(201, "mc_LOADV64-slow1");
- return (ULong)mc_LOADVn_slow( a, 64, isBigEndian );
+ return (ULong)mc_LOADVn_slow( a, 64, isBigEndian, mo );
}
sm = get_secmap_for_reading_low(a);
@@ -3951,7 +3961,7 @@
} else {
/* Slow case: the 8 bytes are not all-defined or all-undefined. */
PROF_EVENT(202, "mc_LOADV64-slow2");
- return mc_LOADVn_slow( a, 64, isBigEndian );
+ return mc_LOADVn_slow( a, 64, isBigEndian, mo );
}
}
#endif
@@ -3959,12 +3969,29 @@
VG_REGPARM(1) ULong MC_(helperc_LOADV64be) ( Addr a )
{
- return mc_LOADV64(a, True);
+ return mc_LOADV64(a, True, MoNone);
}
+VG_REGPARM(1) ULong MC_(helperc_LOADV64be_LA64of128) ( Addr a )
+{
+ return mc_LOADV64(a, True, MoLA64of128);
+}
+VG_REGPARM(1) ULong MC_(helperc_LOADV64be_HA64of128) ( Addr a )
+{
+ return mc_LOADV64(a, True, MoHA64of128);
+}
+
VG_REGPARM(1) ULong MC_(helperc_LOADV64le) ( Addr a )
{
- return mc_LOADV64(a, False);
+ return mc_LOADV64(a, False, MoNone);
}
+VG_REGPARM(1) ULong MC_(helperc_LOADV64le_LA64of128) ( Addr a )
+{
+ return mc_LOADV64(a, False, MoLA64of128);
+}
+VG_REGPARM(1) ULong MC_(helperc_LOADV64le_HA64of128) ( Addr a )
+{
+ return mc_LOADV64(a, False, MoHA64of128);
+}
static INLINE
@@ -4042,7 +4069,7 @@
if (UNLIKELY( UNALIGNED_OR_HIGH(a,32) )) {
PROF_EVENT(221, "mc_LOADV32-slow1");
- return (UWord)mc_LOADVn_slow( a, 32, isBigEndian );
+ return (UWord)mc_LOADVn_slow( a, 32, isBigEndian, MoNone );
}
sm = get_secmap_for_reading_low(a);
@@ -4061,7 +4088,7 @@
} else {
/* Slow case: the 4 bytes are not all-defined or all-undefined. */
PROF_EVENT(222, "mc_LOADV32-slow2");
- return (UWord)mc_LOADVn_slow( a, 32, isBigEndian );
+ return (UWord)mc_LOADVn_slow( a, 32, isBigEndian, MoNone );
}
}
#endif
@@ -4158,7 +4185,7 @@
if (UNLIKELY( UNALIGNED_OR_HIGH(a,16) )) {
PROF_EVENT(241, "mc_LOADV16-slow1");
- return (UWord)mc_LOADVn_slow( a, 16, isBigEndian );
+ return (UWord)mc_LOADVn_slow( a, 16, isBigEndian, MoNone );
}
sm = get_secmap_for_reading_low(a);
@@ -4178,7 +4205,7 @@
else {
/* Slow case: the two bytes are not all-defined or all-undefined. */
PROF_EVENT(242, "mc_LOADV16-slow2");
- return (UWord)mc_LOADVn_slow( a, 16, isBigEndian );
+ return (UWord)mc_LOADVn_slow( a, 16, isBigEndian, MoNone );
}
}
}
@@ -4270,7 +4297,7 @@
if (UNLIKELY( UNALIGNED_OR_HIGH(a,8) )) {
PROF_EVENT(261, "mc_LOADV8-slow1");
- return (UWord)mc_LOADVn_slow( a, 8, False/*irrelevant*/ );
+ return (UWord)mc_LOADVn_slow( a, 8, False/*irrelevant*/, MoNone );
}
sm = get_secmap_for_reading_low(a);
@@ -4290,7 +4317,7 @@
else {
/* Slow case: the byte is not all-defined or all-undefined. */
PROF_EVENT(262, "mc_LOADV8-slow2");
- return (UWord)mc_LOADVn_slow( a, 8, False/*irrelevant*/ );
+ return (UWord)mc_LOADVn_slow( a, 8, False/*irrelevant*/, MoNone );
}
}
}
Modified: branches/ICC111/memcheck/mc_translate.c
===================================================================
--- branches/ICC111/memcheck/mc_translate.c 2009-09-18 23:03:38 UTC (rev 10892)
+++ branches/ICC111/memcheck/mc_translate.c 2009-09-19 00:15:36 UTC (rev 10893)
@@ -2855,7 +2855,8 @@
/* Worker function; do not call directly. */
static
IRAtom* expr2vbits_Load_WRK ( MCEnv* mce,
- IREndness end, IRType ty,
+ IREndness end, IRType ty,
+ Modifier mo,
IRAtom* addr, UInt bias )
{
void* helper;
@@ -2866,6 +2867,8 @@
tl_assert(isOriginalAtom(mce,addr));
tl_assert(end == Iend_LE || end == Iend_BE);
+ if (ty != Ity_I64)
+ tl_assert(mo == MoNone);
/* First, emit a definedness test for the address. This also sets
the address (shadow) to 'defined' following the test. */
@@ -2877,37 +2880,68 @@
if (end == Iend_LE) {
switch (ty) {
- case Ity_I64: helper = &MC_(helperc_LOADV64le);
- hname = "MC_(helperc_LOADV64le)";
- break;
- case Ity_I32: helper = &MC_(helperc_LOADV32le);
- hname = "MC_(helperc_LOADV32le)";
- break;
- case Ity_I16: helper = &MC_(helperc_LOADV16le);
- hname = "MC_(helperc_LOADV16le)";
- break;
- case Ity_I8: helper = &MC_(helperc_LOADV8);
- hname = "MC_(helperc_LOADV8)";
- break;
- default: ppIRType(ty);
- VG_(tool_panic)("memcheck:do_shadow_Load(LE)");
+ case Ity_I64:
+ if (mo == MoLA64of128) {
+ helper = &MC_(helperc_LOADV64le_LA64of128);
+ hname = "MC_(helperc_LOADV64le_LA64of128)";
+ }
+ else if (mo == MoHA64of128) {
+ helper = &MC_(helperc_LOADV64le_HA64of128);
+ hname = "MC_(helperc_LOADV64le_HA64of128)";
+ }
+ else {
+ tl_assert(mo == MoNone);
+ helper = &MC_(helperc_LOADV64le);
+ hname = "MC_(helperc_LOADV64le)";
+ }
+ break;
+ case Ity_I32:
+ helper = &MC_(helperc_LOADV32le);
+ hname = "MC_(helperc_LOADV32le)";
+ break;
+ case Ity_I16:
+ helper = &MC_(helperc_LOADV16le);
+ hname = "MC_(helperc_LOADV16le)";
+ break;
+ case Ity_I8:
+ helper = &MC_(helperc_LOADV8);
+ hname = "MC_(helperc_LOADV8)";
+ break;
+ default:
+ ppIRType(ty);
+ VG_(tool_panic)("memcheck:do_shadow_Load(LE)");
}
} else {
switch (ty) {
- case Ity_I64: helper = &MC_(helperc_LOADV64be);
- hname = "MC_(helperc_LOADV64be)";
- break;
- case Ity_I32: helper = &MC_(helperc_LOADV32be);
- hname = "MC_(helperc_LOADV32be)";
- break;
- case Ity_I16: helper = &MC_(helperc_LOADV16be);
- hname = "MC_(helperc_LOADV16be)";
- break;
- case Ity_I8: helper = &MC_(helperc_LOADV8);
- hname = "MC_(helperc_LOADV8)";
- break;
- default: ppIRType(ty);
- VG_(tool_panic)("memcheck:do_shadow_Load(BE)");
+ case Ity_I64:
+ if (mo == MoLA64of128) {
+ helper = &MC_(helperc_LOADV64be_LA64of128);
+ hname = "MC_(helperc_LOADV64be_LA64of128)";
+ }
+ else if (mo == MoHA64of128) {
+ helper = &MC_(helperc_LOADV64be_HA64of128);
+ hname = "MC_(helperc_LOADV64be_HA64of128)";
+ }
+ else {
+ helper = &MC_(helperc_LOADV64be);
+ hname = "MC_(helperc_LOADV64be)";
+ }
+ break;
+ case Ity_I32:
+ helper = &MC_(helperc_LOADV32be);
+ hname = "MC_(helperc_LOADV32be)";
+ break;
+ case Ity_I16:
+ helper = &MC_(helperc_LOADV16be);
+ hname = "MC_(helperc_LOADV16be)";
+ break;
+ case Ity_I8:
+ helper = &MC_(helperc_LOADV8);
+ hname = "MC_(helperc_LOADV8)";
+ break;
+ default:
+ ppIRType(ty);
+ VG_(tool_panic)("memcheck:do_shadow_Load(BE)");
}
}
@@ -2950,14 +2984,18 @@
case Ity_I16:
case Ity_I32:
case Ity_I64:
- return expr2vbits_Load_WRK(mce, end, ty, addr, bias);
+ return expr2vbits_Load_WRK(mce, end, ty, MoNone, addr, bias);
case Ity_V128:
if (end == Iend_LE) {
- v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
- v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
+ v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, MoLA64of128,
+ addr, bias);
+ v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, MoHA64of128,
+ addr, bias+8);
} else {
- v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias);
- v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, addr, bias+8);
+ v64hi = expr2vbits_Load_WRK(mce, end, Ity_I64, MoLA64of128,
+ addr, bias);
+ v64lo = expr2vbits_Load_WRK(mce, end, Ity_I64, MoHA64of128,
+ addr, bias+8);
}
return assignNew( 'V', mce,
Ity_V128,
|