]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Memcheck: handle origin data for 8-/16-bit shadow stores a bit more accurately.
authorJulian Seward <jseward@acm.org>
Wed, 4 Jan 2023 15:32:03 +0000 (16:32 +0100)
committerJulian Seward <jseward@acm.org>
Wed, 4 Jan 2023 15:32:03 +0000 (16:32 +0100)
With origin tracking enabled, 8- and 16-bit stores could sometimes lose origin
info unnecessarily.  This patch removes this avoidable lossage.  (Since MC
only stores 1 origin value for each 32-bit word of address space, there is
still unavoidable lossage of origins in some cases; this patch does not help
in those cases since it's a fundamental design limitation.)

memcheck/mc_main.c

index fe15d233214d2eb1cfa634e9f78540f6e5d4facb..8efd7cb40c6e867a89aa1c88a08f427266699b79 100644 (file)
@@ -79,6 +79,10 @@ static void ocache_sarp_Clear_Origins ( Addr, UWord ); /* fwds */
    paths */
 #define OC_ENABLE_ASSERTIONS 0
 
+/* Change this to 1 for experimental, higher precision origin tracking
+   8- and 16-bit store handling. */
+#define OC_PRECISION_STORE 1
+
 
 /*------------------------------------------------------------*/
 /*--- Comments on the origin tracking implementation       ---*/
@@ -7655,12 +7659,31 @@ void VG_REGPARM(2) MC_(helperc_b_store1)( Addr a, UWord d32 ) {
 
    line = find_OCacheLine( a );
 
+#if OC_PRECISION_STORE
+   if (LIKELY(d32 == 0)) {
+      // The byte is defined.  Just mark it as so in the descr and leave the w32
+      // unchanged.  This may make the descr become zero, so the line no longer
+      // contains useful info, but that's OK.  No loss of information.
+      line->u.main.descr[lineoff] &= ~(1 << byteoff);
+   } else if (d32 == line->u.main.w32[lineoff]) {
+      // At least one of the four bytes in the w32 is undefined with the same
+      // origin.  Just extend the mask.  No loss of information.
+      line->u.main.descr[lineoff] |= (1 << byteoff);
+   } else {
+      // Here, we have a conflict: at least one byte in the group is undefined
+      // but with some other origin.  We can't represent both origins, so we
+      // forget about the previous origin and install this one instead.
+      line->u.main.descr[lineoff] = (1 << byteoff);
+      line->u.main.w32[lineoff] = d32;
+   }
+#else
    if (d32 == 0) {
       line->u.main.descr[lineoff] &= ~(1 << byteoff);
    } else {
       line->u.main.descr[lineoff] |= (1 << byteoff);
       line->u.main.w32[lineoff] = d32;
    }
+#endif
 }
 
 void VG_REGPARM(2) MC_(helperc_b_store2)( Addr a, UWord d32 ) {
@@ -7683,12 +7706,25 @@ void VG_REGPARM(2) MC_(helperc_b_store2)( Addr a, UWord d32 ) {
 
    line = find_OCacheLine( a );
 
+#if OC_PRECISION_STORE
+   // Same logic as in the store1 case above.
+   if (LIKELY(d32 == 0)) {
+      line->u.main.descr[lineoff] &= ~(3 << byteoff);
+   } else if (d32 == line->u.main.w32[lineoff]) {
+      line->u.main.descr[lineoff] |= (3 << byteoff);
+      line->u.main.w32[lineoff] = d32;
+   } else {
+      line->u.main.descr[lineoff] = (3 << byteoff);
+      line->u.main.w32[lineoff] = d32;
+   }
+#else
    if (d32 == 0) {
       line->u.main.descr[lineoff] &= ~(3 << byteoff);
    } else {
       line->u.main.descr[lineoff] |= (3 << byteoff);
       line->u.main.w32[lineoff] = d32;
    }
+#endif
 }
 
 void VG_REGPARM(2) MC_(helperc_b_store4)( Addr a, UWord d32 ) {