]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fix 388174 - valgrind with Wine quits with "Assertion 'cfsi_fits' failed"
authorJulian Seward <jseward@acm.org>
Fri, 17 Aug 2018 07:31:37 +0000 (09:31 +0200)
committerJulian Seward <jseward@acm.org>
Fri, 17 Aug 2018 07:31:37 +0000 (09:31 +0200)
In check_CFSI_related_invariants, this commit improves the check for invariant
(2), which, as noted in an existing comment, "might need to be improved".
Instead of assuming that the CFSI range fits entirely into one "rx" mapping,
check that it is covered by the union of all the "rx" mappings we have.  This
is the correct check.  The previous check was observed to have failed as below
for at least some Clang generated objects (possibly in conjunction with lld as
the linker.)

valgrind: m_debuginfo/debuginfo.c:717 (check_CFSI_related_invariants): Assertion 'cfsi_fits' failed.

coregrind/m_debuginfo/debuginfo.c

index a4e660d0b56ba4933ea63c75933f8fdc8db49a63..a30c7b44e51385bf3cb89dcc9643f8e1dd57cd74 100644 (file)
@@ -658,7 +658,6 @@ static void check_CFSI_related_invariants ( const DebugInfo* di )
 {
    DebugInfo* di2 = NULL;
    Bool has_nonempty_rx = False;
-   Bool cfsi_fits = False;
    Word i, j;
    vg_assert(di);
    /* This fn isn't called until after debuginfo for this object has
@@ -694,16 +693,6 @@ static void check_CFSI_related_invariants ( const DebugInfo* di )
          }
       }
       di2 = NULL;
-
-      /* invariant (2) */
-      if (di->cfsi_rd) {
-         vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */
-         /* Assume the csfi fits completely into one individual mapping
-            for now. This might need to be improved/reworked later. */
-         if (di->cfsi_minavma >= map->avma &&
-             di->cfsi_maxavma <  map->avma + map->size)
-            cfsi_fits = True;
-      }
    }
 
    /* degenerate case: all r-x sections are empty */
@@ -712,10 +701,44 @@ static void check_CFSI_related_invariants ( const DebugInfo* di )
       return;
    }
 
-   /* invariant (2) - cont. */
-   if (di->cfsi_rd)
+   /* invariant (2) */
+   if (di->cfsi_rd) {
+      vg_assert(di->cfsi_minavma <= di->cfsi_maxavma); /* duh! */
+      /* It may be that the cfsi range doesn't fit into any one individual
+         mapping, but it is covered by the combination of all the mappings.
+         That's a bit tricky to establish.  To do so, create a RangeMap with
+         the cfsi range as the single only non-zero mapping, then zero out all
+         the parts described by di->fsm.maps, and check that there's nothing
+         left. */
+      RangeMap* rm = VG_(newRangeMap)( ML_(dinfo_zalloc),
+                        "di.debuginfo. cCri.1", ML_(dinfo_free),
+                        /*initialVal*/0 );
+      VG_(bindRangeMap)(rm, di->cfsi_minavma, di->cfsi_maxavma, 1);
+      for (i = 0; i < VG_(sizeXA)(di->fsm.maps); i++) {
+         const DebugInfoMapping* map = VG_(indexXA)(di->fsm.maps, i);
+         /* We are interested in r-x mappings only */
+         if (!map->rx)
+            continue;
+         if (map->size > 0)
+            VG_(bindRangeMap)(rm, map->avma, map->avma + map->size - 1, 0);
+      }
+      /* If the map isn't now empty, it means the cfsi range isn't covered
+         entirely by the rx mappings. */
+      Bool cfsi_fits = VG_(sizeRangeMap)(rm) == 1;
+      if (cfsi_fits) {
+         // Sanity-check the range-map operation
+         UWord key_min = 0x55, key_max = 0x56, val = 0x57;
+         /* We can look up any address at all since we expect only one range */
+         VG_(lookupRangeMap)(&key_min, &key_max, &val, rm, 0x1234);
+         vg_assert(key_min == (UWord)0);
+         vg_assert(key_max == ~(UWord)0);
+         vg_assert(val == 0);
+      }
       vg_assert(cfsi_fits);
 
+      VG_(deleteRangeMap)(rm);
+   }
+
    /* invariants (3) and (4) */
    if (di->cfsi_rd) {
       vg_assert(di->cfsi_used > 0);