|
From: <sv...@va...> - 2006-01-11 21:58:49
|
Author: njn
Date: 2006-01-11 21:58:39 +0000 (Wed, 11 Jan 2006)
New Revision: 5517
Log:
Add a thorough test of the LOADV*/STOREV* shadow memory access functions.
Added:
branches/COMPVBITS/memcheck/tests/sh-mem.c
branches/COMPVBITS/memcheck/tests/sh-mem.stderr.exp
branches/COMPVBITS/memcheck/tests/sh-mem.vgtest
Modified:
branches/COMPVBITS/memcheck/tests/Makefile.am
Modified: branches/COMPVBITS/memcheck/tests/Makefile.am
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/COMPVBITS/memcheck/tests/Makefile.am 2006-01-11 21:56:19 UTC=
(rev 5516)
+++ branches/COMPVBITS/memcheck/tests/Makefile.am 2006-01-11 21:58:39 UTC=
(rev 5517)
@@ -82,6 +82,7 @@
realloc1.stderr.exp realloc1.vgtest \
realloc2.stderr.exp realloc2.vgtest \
realloc3.stderr.exp realloc3.vgtest \
+ sh-mem.stderr.exp sh-mem.vgtest \
sigaltstack.stderr.exp sigaltstack.vgtest \
sigkill.stderr.exp sigkill.stderr.exp2 sigkill.stderr.exp3 sigkill.vgte=
st \
signal2.stderr.exp signal2.stdout.exp signal2.vgtest \
@@ -126,6 +127,7 @@
pipe pointer-trace \
post-syscall \
realloc1 realloc2 realloc3 \
+ sh-mem \
sigaltstack signal2 sigprocmask sigkill \
stack_changes stack_switch strchr str_tester \
supp_unknown supp1 supp2 suppfree \
Added: branches/COMPVBITS/memcheck/tests/sh-mem.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/COMPVBITS/memcheck/tests/sh-mem.c (r=
ev 0)
+++ branches/COMPVBITS/memcheck/tests/sh-mem.c 2006-01-11 21:58:39 UTC (r=
ev 5517)
@@ -0,0 +1,193 @@
+// This program is a thorough test of the LOADVn/STOREVn shadow memory
+// operations.
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "memcheck/memcheck.h"
+
+// All the sizes here are in *bytes*, not bits.
+
+typedef unsigned char U1;
+typedef unsigned short U2;
+typedef unsigned int U4;
+typedef unsigned long long U8;
+
+typedef float F4;
+typedef double F8;
+
+#define SZB_OF_a 64
+
+// a[] is the array in which we do our loads and stores. =20
+// b[] is another one in which we do some copying.
+U8 a [SZB_OF_a / 8]; // Type is U8 to ensure it's 8-aligned
+U8 b [SZB_OF_a / 8]; // same size as a[]
+
+// XXX: should check the error cases for SET/GET_VBITS also
+
+// For the byte 'x', build a value of 'size' bytes from that byte, eg:
+// size 1 --> x
+// size 2 --> xx
+// size 4 --> xxxx
+// size 8 --> xxxxxxxx
+// where the 0 bits are seen by Memcheck as defined, and the 1 bits are
+// seen as undefined (ie. the value of each bit matches its V bit, ie. t=
he
+// resulting value is the same as its metavalue).
+//
+U8 build(int size, U1 byte)
+{
+ int i;
+ U8 mask =3D 0;
+ U8 shres;
+ U8 res =3D 0xffffffffffffffffULL, res2;
+ VALGRIND_MAKE_WRITABLE(&res, 8);
+ assert(1 =3D=3D size || 2 =3D=3D size || 4 =3D=3D size || 8 =3D=3D si=
ze);
+
+ for (i =3D 0; i < size; i++) {
+ mask <<=3D 8;
+ mask |=3D (U8)byte;
+ }
+
+ res &=3D mask; =20
+ =20
+ // res is now considered partially defined, but we know exactly what =
its
+ // value is (it happens to be the same as its metavalue).
+ =20
+ VALGRIND_GET_VBITS(&res, &shres, 8);
+ res2 =3D res;
+ VALGRIND_MAKE_READABLE(&res2, 8); // avoid the 'undefined' warni=
ng
+ assert(res2 =3D=3D shres);
+ return res;
+}
+
+// Check that all the bytes in a[x..y-1] have their V byte equal to 'byt=
e'.
+// 'str' and 'offset' are only used for printing an error message if
+// something goes wrong.
+void check_all(U4 x, U4 y, U1 byte, char* str, int offset)
+{
+ U1 sh[SZB_OF_a]; // Used for getting a[]'s V bits
+ int i;
+
+ VALGRIND_GET_VBITS(a, sh, sizeof(a));
+ for (i =3D x; i < y; i++) {
+ if ( byte !=3D sh[i] ) {
+ fprintf(stderr, "\n\nFAILURE: %s, offset %d, byte %d -- "
+ "is 0x%x, should be 0x%x\n\n",
+ str, offset, i, sh[i], byte);
+ exit(1);
+ }
+ }
+}
+
+int main(void)
+{
+ int h, i, j;
+ U1 *undefA;
+
+ if (0 =3D=3D RUNNING_ON_VALGRIND) {
+ fprintf(stderr, "error: this program only works when run under Val=
grind\n");
+ exit(1);
+ }
+
+ // Check a[] has the expected alignment, and that it's not too high i=
n
+ // the address space (which would trigger the slow cases in
+ // LOADVn/STOREVn) on 64-bit platforms).
+ assert( 0 =3D=3D (long)a % 8);
+ assert((U1*)a < (U1*)0xefffffff);
+
+ // Check basic types have the expected sizes.
+ assert(1 =3D=3D sizeof(U1));
+ assert(2 =3D=3D sizeof(U2));
+ assert(4 =3D=3D sizeof(U4));
+ assert(8 =3D=3D sizeof(U8));
+
+ // Create an array of values that has all the possible V bit metavalu=
es.
+ // Because 0 represents a defined bit, and because undefA[] is initia=
lly
+ // zeroed, we have the nice property that:
+ //
+ // i =3D=3D undefA[i] =3D=3D V_bits_of(undefA[i])
+ //
+ // which is useful for testing below.
+ undefA =3D calloc(1, 256); // one for each possible undefined=
ness value
+ VALGRIND_MAKE_WRITABLE(undefA, 256);
+ for (i =3D 0; i < 256; i++) {
+ undefA[i] &=3D i;=20
+ }
+
+ // This code does a whole lot of reads and writes of a particular siz=
e
+ // (NNN =3D 1, 2, 4 or 8), with varying alignments, of values with
+ // different not/partially/fully defined metavalues, and checks that =
the
+ // V bits are set in a[] as expected using GET_VBITS.
+ //
+ // 'Ty' is the type of the thing we are copying. It can be an intege=
r
+ // type or an FP type. 'ITy' is the same-sized integer type (and thu=
s
+ // will be the same as 'Ty' if 'ITy' is an integer type). 'ITy' is u=
sed
+ // when doing shifting/masking and stuff like that.
+
+#define DO(NNN, Ty, ITy) \
+ fprintf(stderr, "-- NNN: %d %s %s ------------------------\n", NNN, #=
Ty, #ITy); \
+ /* For all of the alignments from (0..NNN-1), eg. if NNN=3D=3D4, we d=
o */ \
+ /* alignments of 0, 1, 2, 3. */ \
+ for (h =3D 0; h < NNN; h++) { \
+ \
+ size_t n =3D sizeof(a); \
+ size_t nN =3D n / sizeof(Ty); \
+ Ty* aN =3D (Ty*)a; \
+ Ty* bN =3D (Ty*)b; \
+ Ty* aNb =3D (Ty*)(((U1*)aN) + h); /* set offset from a[] */ \
+ Ty* bNb =3D (Ty*)(((U1*)bN) + h); /* set offset from b[] */ \
+ \
+ fprintf(stderr, "h =3D %d (checking %d..%d) ", h, h, n-NNN+h); \
+ \
+ /* For each of the 256 possible V byte values... */ \
+ for (j =3D 0; j < 256; j++) { \
+ /* build the value for i (one of: i, ii, iiii, iiiiiiii) */ \
+ U8 tmp =3D build(NNN, j); \
+ ITy undefN_ITy =3D (ITy)tmp; \
+ Ty* undefN_Ty; \
+ { /* This just checks that no overflow occurred when squeezing =
*/ \
+ /* the output of build() into a variable of type 'Ty'. */ \
+ U8 tmpDef =3D tmp; \
+ ITy undefN_ITyDef =3D undefN_ITy; \
+ VALGRIND_MAKE_READABLE(&tmpDef, 8 ); \
+ VALGRIND_MAKE_READABLE(&undefN_ITyDef, NNN); \
+ assert(tmpDef =3D=3D (U8)undefN_ITyDef); \
+ } \
+ \
+ /* We have to use an array for undefN_Ty -- because if we try t=
o
+ * convert an integer type from build into an FP type with a
+ * straight cast -- eg "float f =3D (float)i" -- the value gets
+ * converted. With this pointer/array nonsense the exact bit
+ * pattern gets used as an FP value unchanged (that FP value is
+ * undoubtedly nonsense, but that's not a problem here). */ \
+ undefN_Ty =3D (Ty*)&undefN_ITy; \
+ if (0 =3D=3D j % 32) fprintf(stderr, "%d...", j); /* progress m=
eter */ \
+ \
+ /* STOREVn. Note that we use the first element of the undefN_T=
y
+ * array, as explained above. */ \
+ for (i =3D 0; i < nN-1; i++) { aNb[i] =3D undefN_Ty[0]; } \
+ check_all(h, n-NNN+h, j, "STOREVn", h); \
+ \
+ /* LOADVn -- by copying the values to one place and then back,=20
+ * we ensure that LOADVn gets exercised. */ \
+ for (i =3D 0; i < nN-1; i++) { bNb[i] =3D aNb[i]; } \
+ for (i =3D 0; i < nN-1; i++) { aNb[i] =3D bNb[i]; } \
+ check_all(h, n-NNN+h, j, "LOADVn", h); \
+ } \
+ fprintf(stderr, "\n"); \
+ }
+
+ // For sizes 4 and 8 we do both integer and floating-point types. Th=
e
+ // reason being that on 32-bit machines just using integer types neve=
r
+ // exercises LOADV8/STOREV8 -- for integer types these loads/stores g=
et
+ // broken into two 32-bit loads/stores.
+ DO(1, U1, U1);
+ DO(2, U2, U2);
+ DO(4, U4, U4);
+ DO(4, F4, U4);
+ DO(8, U8, U8);
+ DO(8, F8, U8);
+ =20
+ return 0;
+}
Added: branches/COMPVBITS/memcheck/tests/sh-mem.stderr.exp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/COMPVBITS/memcheck/tests/sh-mem.stderr.exp =
(rev 0)
+++ branches/COMPVBITS/memcheck/tests/sh-mem.stderr.exp 2006-01-11 21:58:=
39 UTC (rev 5517)
@@ -0,0 +1,33 @@
+-- NNN: 1 U1 U1 ------------------------
+h =3D 0 (checking 0..63) 0...32...64...96...128...160...192...224...
+-- NNN: 2 U2 U2 ------------------------
+h =3D 0 (checking 0..62) 0...32...64...96...128...160...192...224...
+h =3D 1 (checking 1..63) 0...32...64...96...128...160...192...224...
+-- NNN: 4 U4 U4 ------------------------
+h =3D 0 (checking 0..60) 0...32...64...96...128...160...192...224...
+h =3D 1 (checking 1..61) 0...32...64...96...128...160...192...224...
+h =3D 2 (checking 2..62) 0...32...64...96...128...160...192...224...
+h =3D 3 (checking 3..63) 0...32...64...96...128...160...192...224...
+-- NNN: 4 F4 U4 ------------------------
+h =3D 0 (checking 0..60) 0...32...64...96...128...160...192...224...
+h =3D 1 (checking 1..61) 0...32...64...96...128...160...192...224...
+h =3D 2 (checking 2..62) 0...32...64...96...128...160...192...224...
+h =3D 3 (checking 3..63) 0...32...64...96...128...160...192...224...
+-- NNN: 8 U8 U8 ------------------------
+h =3D 0 (checking 0..56) 0...32...64...96...128...160...192...224...
+h =3D 1 (checking 1..57) 0...32...64...96...128...160...192...224...
+h =3D 2 (checking 2..58) 0...32...64...96...128...160...192...224...
+h =3D 3 (checking 3..59) 0...32...64...96...128...160...192...224...
+h =3D 4 (checking 4..60) 0...32...64...96...128...160...192...224...
+h =3D 5 (checking 5..61) 0...32...64...96...128...160...192...224...
+h =3D 6 (checking 6..62) 0...32...64...96...128...160...192...224...
+h =3D 7 (checking 7..63) 0...32...64...96...128...160...192...224...
+-- NNN: 8 F8 U8 ------------------------
+h =3D 0 (checking 0..56) 0...32...64...96...128...160...192...224...
+h =3D 1 (checking 1..57) 0...32...64...96...128...160...192...224...
+h =3D 2 (checking 2..58) 0...32...64...96...128...160...192...224...
+h =3D 3 (checking 3..59) 0...32...64...96...128...160...192...224...
+h =3D 4 (checking 4..60) 0...32...64...96...128...160...192...224...
+h =3D 5 (checking 5..61) 0...32...64...96...128...160...192...224...
+h =3D 6 (checking 6..62) 0...32...64...96...128...160...192...224...
+h =3D 7 (checking 7..63) 0...32...64...96...128...160...192...224...
Added: branches/COMPVBITS/memcheck/tests/sh-mem.vgtest
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- branches/COMPVBITS/memcheck/tests/sh-mem.vgtest =
(rev 0)
+++ branches/COMPVBITS/memcheck/tests/sh-mem.vgtest 2006-01-11 21:58:39 U=
TC (rev 5517)
@@ -0,0 +1,2 @@
+prog: sh-mem
+vgopts: -q
|