]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fix 398028 Assertion `cfsi_fits` failing in simple C program
authorPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Wed, 26 Sep 2018 16:04:43 +0000 (18:04 +0200)
committerPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Wed, 26 Sep 2018 16:04:43 +0000 (18:04 +0200)
At least with libopenblas, we can have several rx mappings
with some holes between mappings.
Change the invariant (2) checking so that such holes are ok,
as long as no cfsi refers to such an hole.

NEWS
coregrind/m_debuginfo/debuginfo.c
coregrind/m_debuginfo/priv_storage.h

diff --git a/NEWS b/NEWS
index ad188da19badb5f54b0d2147a7bbaf3d64b874d7..384cc9d357503ed18b318dfe0f009d6442c76f7e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -167,6 +167,7 @@ where XXXXXX is the bug number as listed below.
 397089  amd64: Incorrect decoding of three-register vmovss/vmovsd opcode 11h
 397354  utimensat should ignore timespec tv_sec if tv_nsec is UTIME_NOW/OMIT
 397424  glibc 2.27 and gdb_server tests
+398028  Assertion `cfsi_fits` failing in simple C program
 398066  s390x: cgijl dep1, 0 reports false unitialised values warning
 
 n-i-bz  Fix missing workq_ops operations (macOS)
index 0fc54bf1dd17391d1a4f9473d60b07bc77519396..1aa43146fee59af0faf66da70a085fe5e79c79f0 100644 (file)
@@ -660,6 +660,8 @@ static void check_CFSI_related_invariants ( const DebugInfo* di )
    DebugInfo* di2 = NULL;
    Bool has_nonempty_rx = False;
    Word i, j;
+   const Bool debug = VG_(debugLog_getLevel)() >= 3;
+
    vg_assert(di);
    /* This fn isn't called until after debuginfo for this object has
       been successfully read.  And that shouldn't happen until we have
@@ -676,7 +678,7 @@ static void check_CFSI_related_invariants ( const DebugInfo* di )
       if (map->size == 0)
          continue;
       has_nonempty_rx = True;
-        
+
       /* normal case: r-x section is nonempty */
       /* invariant (0) */
       vg_assert(map->size > 0);
@@ -689,8 +691,9 @@ static void check_CFSI_related_invariants ( const DebugInfo* di )
             const DebugInfoMapping* map2 = VG_(indexXA)(di2->fsm.maps, j);
             if (!map2->rx || map2->size == 0)
                continue;
-            vg_assert(!ranges_overlap(map->avma,  map->size,
-                                      map2->avma, map2->size));
+            vg_assert2(!ranges_overlap(map->avma,  map->size,
+                                       map2->avma, map2->size),
+                       "DiCfsi invariant (1) verification failed");
          }
       }
       di2 = NULL;
@@ -723,17 +726,44 @@ static void check_CFSI_related_invariants ( const DebugInfo* di )
          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
+      /* Typically, the range map contains one single range with value 0,
+         meaning that the cfsi range is entirely covered by the rx mappings.
+         However, in some cases, there are holes in the rx mappings
+         (see BZ #398028).
+         In such a case, check that no cfsi refers to these holes.  */
+      Bool cfsi_fits = VG_(sizeRangeMap)(rm) >= 1;
+      // Check the ranges in the map.
+      for (Word ix = 0; ix < VG_(sizeRangeMap)(rm); ix++) {
          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_(indexRangeMap)(&key_min, &key_max, &val, rm, ix);
+         if (debug)
+            VG_(dmsg)("cfsi range rx-mappings coverage check: %s %#lx-%#lx\n",
+                      val == 1 ? "Uncovered" : "Covered",
+                      key_min, key_max);
+         {
+            // Sanity-check the range-map operation
+            UWord check_key_min = 0x55, check_key_max = 0x56, check_val = 0x57;
+            VG_(lookupRangeMap)(&check_key_min, &check_key_max, &check_val, rm,
+                                key_min + (key_max - key_min) / 2);
+            if (ix == 0)
+               vg_assert(key_min == (UWord)0);
+            if (ix == VG_(sizeRangeMap)(rm) - 1)
+               vg_assert(key_max == ~(UWord)0);
+            vg_assert(key_min == check_key_min);
+            vg_assert(key_max == check_key_max);
+            vg_assert(val == 0 || val == 1);
+            vg_assert(val == check_val);
+         }
+         if (val == 1) {
+            /* This is a part of cfsi_minavma .. cfsi_maxavma not covered.
+               Check no cfsi overlaps with this range. */
+            for (i = 0; i < di->cfsi_used; i++) {
+               DiCfSI* cfsi = &di->cfsi_rd[i];
+               vg_assert2(cfsi->base > key_max
+                          || cfsi->base + cfsi->len - 1 < key_min,
+                          "DiCfsi invariant (2) verification failed");
+            }
+         }
       }
       vg_assert(cfsi_fits);
 
index 713acbea87849cafa2c2a354f8f31604523bdcb4..98e715658f75941f2cc77149ed54f124a4c4424c 100644 (file)
@@ -670,9 +670,12 @@ struct _DebugInfo {
       (0) size of at least one rx mapping > 0
       (1) no two non-archived DebugInfos with some rx mapping of size > 0
           have overlapping rx mappings
-      (2) [cfsi_minavma,cfsi_maxavma] does not extend beyond
-          [avma,+size) of one rx mapping; that is, the former
-          is a subrange or equal to the latter.
+      (2) Each address in [cfsi_minavma,cfsi_maxavma] is in an rx mapping
+          or else no cfsi can cover this address.
+          The typical case is a single rx mapping covering the full range.
+          In some cases, the union of several rx mappings covers the range,
+          with possibly some holes between the rx mappings, and no cfsi fall
+          within such an hole.
       (3) all DiCfSI in the cfsi array all have ranges that fall within
           [avma,+size) of that rx mapping.
       (4) all DiCfSI in the cfsi array are non-overlapping