Reinstate the leak checker; it works at least on x86.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3577 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/memcheck/mac_leakcheck.c b/memcheck/mac_leakcheck.c
index bee38b2..afea073 100644
--- a/memcheck/mac_leakcheck.c
+++ b/memcheck/mac_leakcheck.c
@@ -175,8 +175,8 @@
 static Addr         lc_max_mallocd_addr;
 static SizeT	    lc_scanned;
 
-static Bool	  (*lc_is_valid_chunk)  (UInt chunk);
-static Bool	  (*lc_is_valid_address)(Addr addr);
+static Bool	  (*lc_is_within_valid_secondary) (Addr addr);
+static Bool	  (*lc_is_valid_aligned_word)     (Addr addr);
 
 static const Char *pp_lossmode(Reachedness lossmode)
 {
@@ -324,7 +324,6 @@
    cliques, and clique is the index of the current clique leader. */
 static void _lc_scan_memory(Addr start, SizeT len, Int clique)
 {
-#if 0
    Addr ptr = ROUNDUP(start, sizeof(Addr));
    Addr end = ROUNDDN(start+len, sizeof(Addr));
    vki_sigset_t sigmask;
@@ -340,11 +339,11 @@
        !VG_(is_addressable)(ptr, sizeof(Addr), VKI_PROT_READ))
       ptr = PGROUNDUP(ptr+1);	/* first page bad */
 
-   while(ptr < end) {
+   while (ptr < end) {
       Addr addr;
 
       /* Skip invalid chunks */
-      if (!(*lc_is_valid_chunk)(PM_IDX(ptr))) {
+      if (!(*lc_is_within_valid_secondary)(ptr)) {
 	 ptr = ROUNDUP(ptr+1, SECONDARY_SIZE);
 	 continue;
       }
@@ -357,7 +356,7 @@
       }
 
       if (__builtin_setjmp(memscan_jmpbuf) == 0) {
-	 if ((*lc_is_valid_address)(ptr)) {
+	 if ((*lc_is_valid_aligned_word)(ptr)) {
 	    addr = *(Addr *)ptr;
 	    _lc_markstack_push(addr, clique);
 	 } else if (0 && VG_DEBUG_LEAKCHECK)
@@ -374,7 +373,6 @@
 
    VG_(sigprocmask)(VKI_SIG_SETMASK, &sigmask, NULL);
    VG_(set_fault_catcher)(NULL);
-#endif
 }
 
 
@@ -570,8 +568,8 @@
 */
 void MAC_(do_detect_memory_leaks) (
    ThreadId tid, LeakCheckMode mode,
-   Bool (*is_valid_64k_chunk) ( UInt ),
-   Bool (*is_valid_address)   ( Addr )
+   Bool (*is_within_valid_secondary) ( Addr ),
+   Bool (*is_valid_aligned_word)     ( Addr )
 )
 {
    Int i;
@@ -622,8 +620,8 @@
    }
    lc_markstack_top = -1;
 
-   lc_is_valid_chunk   = is_valid_64k_chunk;
-   lc_is_valid_address = is_valid_address;
+   lc_is_within_valid_secondary = is_within_valid_secondary;
+   lc_is_valid_aligned_word     = is_valid_aligned_word;
 
    lc_scanned = 0;
 
diff --git a/memcheck/mac_shared.h b/memcheck/mac_shared.h
index 8aa9322..f6b0653 100644
--- a/memcheck/mac_shared.h
+++ b/memcheck/mac_shared.h
@@ -203,6 +203,12 @@
 /* expand 1 bit -> 8 */
 #define BIT_TO_BYTE(b)  ((~(((UChar)(b) & 1) - 1)) & 0xFF)
 
+/* The number of entries in the primary map can be altered.  However
+   we hardwire the assumption that each secondary map covers precisely
+   64k of address space. */
+#define SECONDARY_SIZE 65536               /* DO NOT CHANGE */
+#define SECONDARY_MASK (SECONDARY_SIZE-1)  /* DO NOT CHANGE */
+
 //zz #define SECONDARY_SHIFT	16
 //zz #define SECONDARY_SIZE	(1 << SECONDARY_SHIFT)
 //zz #define SECONDARY_MASK	(SECONDARY_SIZE - 1)
@@ -407,8 +413,8 @@
 
 extern void MAC_(do_detect_memory_leaks) (
           ThreadId tid, LeakCheckMode mode,
-          Bool (*is_valid_64k_chunk) ( UInt ),
-          Bool (*is_valid_address)   ( Addr )
+          Bool (*is_within_valid_secondary) ( Addr ),
+          Bool (*is_valid_aligned_word)     ( Addr )
        );
 
 extern VGA_REGPARM(1) void MAC_(new_mem_stack_4)  ( Addr old_ESP );
diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c
index cbd0896..35b6675 100644
--- a/memcheck/mc_main.c
+++ b/memcheck/mc_main.c
@@ -114,12 +114,6 @@
 
 /* --------------- Basic configuration --------------- */
 
-/* The number of entries in the primary map can be altered.  However
-   we hardwire the assumption that each secondary map covers precisely
-   64k of address space. */
-#define SECONDARY_SIZE 65536               /* DO NOT CHANGE */
-#define SECONDARY_MASK (SECONDARY_SIZE-1)  /* DO NOT CHANGE */
-
 /* Only change this.  N_PRIMARY_MAP *must* be a power of 2. */
 #define N_PRIMARY_BITS  16
 
@@ -210,12 +204,12 @@
 
 /* Find an entry in the auxiliary map.  If an entry is found, move it
    one step closer to the front of the array, then return its address.
-   If an entry is not found, allocate one.  Note carefully that
+   If an entry is not found, return NULL.  Note carefully that
    because a each call potentially rearranges the entries, each call
    to this function invalidates ALL AuxMapEnt*s previously obtained by
    calling this fn.  
 */
-static AuxMapEnt* find_or_alloc_in_auxmap ( Addr a )
+static AuxMapEnt* maybe_find_in_auxmap ( Addr a )
 {
    UWord i;
    tl_assert(a > MAX_PRIMARY_ADDRESS);
@@ -241,6 +235,23 @@
       return &auxmap[i];
    }
 
+   return NULL;
+}
+
+
+/* Find an entry in the auxiliary map.  If an entry is found, move it
+   one step closer to the front of the array, then return its address.
+   If an entry is not found, allocate one.  Note carefully that
+   because a each call potentially rearranges the entries, each call
+   to this function invalidates ALL AuxMapEnt*s previously obtained by
+   calling this fn.  
+*/
+static AuxMapEnt* find_or_alloc_in_auxmap ( Addr a )
+{
+   AuxMapEnt* am = maybe_find_in_auxmap(a);
+   if (am)
+      return am;
+
    /* We didn't find it.  Hmm.  This is a new piece of address space.
       We'll need to allocate a new AuxMap entry for it. */
    if (auxmap_used >= auxmap_size) {
@@ -281,6 +292,23 @@
    }
 }
 
+/* If 'a' has a SecMap, produce it.  Else produce NULL.  But don't
+   allocate one if one doesn't already exist.  This is used by the
+   leak checker.
+*/
+static SecMap* maybe_get_secmap_for ( Addr a )
+{
+   if (a <= MAX_PRIMARY_ADDRESS) {
+      UWord pm_off = a >> 16;
+      return primary_map[ pm_off ];
+   } else {
+      AuxMapEnt* am = maybe_find_in_auxmap(a);
+      return am ? am->sm : NULL;
+   }
+}
+
+
+
 /* Produce the secmap for 'a', either from the primary map or by
    ensuring there is an entry for it in the aux primary map.  The
    secmap may not be a distinguished one, since the caller will want
@@ -1655,45 +1683,46 @@
 //zz 
 //zz    return 1;
 //zz }
-//zz 
-//zz 
-//zz /*------------------------------------------------------------*/
-//zz /*--- Detecting leaked (unreachable) malloc'd blocks.      ---*/
-//zz /*------------------------------------------------------------*/
-//zz 
-//zz /* For the memory leak detector, say whether an entire 64k chunk of
-//zz    address space is possibly in use, or not.  If in doubt return
-//zz    True.
-//zz */
-//zz static
-//zz Bool mc_is_valid_64k_chunk ( UInt chunk_number )
-//zz {
-//zz    tl_assert(chunk_number >= 0 && chunk_number < PRIMARY_SIZE);
-//zz    if (primary_map[chunk_number] == DSM_NOTADDR) {
-//zz       /* Definitely not in use. */
-//zz       return False;
-//zz    } else {
-//zz       return True;
-//zz    }
-//zz }
-//zz 
-//zz 
-//zz /* For the memory leak detector, say whether or not a given word
-//zz    address is to be regarded as valid. */
-//zz static
-//zz Bool mc_is_valid_address ( Addr a )
-//zz {
-//zz    UInt vbytes;
-//zz    UChar abits;
-//zz    tl_assert(VG_IS_4_ALIGNED(a));
-//zz    abits  = get_abits4_ALIGNED(a);
-//zz    vbytes = get_vbytes4_ALIGNED(a);
-//zz    if (abits == VGM_NIBBLE_VALID && vbytes == VGM_WORD_VALID) {
-//zz       return True;
-//zz    } else {
-//zz       return False;
-//zz    }
-//zz }
+
+
+/*------------------------------------------------------------*/
+/*--- Detecting leaked (unreachable) malloc'd blocks.      ---*/
+/*------------------------------------------------------------*/
+
+/* For the memory leak detector, say whether an entire 64k chunk of
+   address space is possibly in use, or not.  If in doubt return
+   True.
+*/
+static
+Bool mc_is_within_valid_secondary ( Addr a )
+{
+   SecMap* sm = maybe_get_secmap_for ( a );
+   if (sm == NULL || sm == &sm_distinguished[SM_DIST_NOACCESS]) {
+      /* Definitely not in use. */
+      return False;
+   } else {
+      return True;
+   }
+}
+
+
+/* For the memory leak detector, say whether or not a given word
+   address is to be regarded as valid. */
+static
+Bool mc_is_valid_aligned_word ( Addr a )
+{
+   tl_assert(sizeof(UWord) == 4 || sizeof(UWord) == 8);
+   if (sizeof(UWord) == 4) {
+      tl_assert(VG_IS_4_ALIGNED(a));
+   } else {
+      tl_assert(VG_IS_8_ALIGNED(a));
+   }
+   if (mc_check_readable( a, sizeof(UWord), NULL ) == MC_Ok) {
+      return True;
+   } else {
+      return False;
+   }
+}
 
 
 /* Leak detector for this tool.  We don't actually do anything, merely
@@ -1701,9 +1730,12 @@
    tool. */
 static void mc_detect_memory_leaks ( ThreadId tid, LeakCheckMode mode )
 {
-   VG_(printf)("memcheck: leak detection currently disabled\n");
-   //   MAC_(do_detect_memory_leaks) ( 
-   //      tid, mode, mc_is_valid_64k_chunk, mc_is_valid_address );
+   MAC_(do_detect_memory_leaks) ( 
+      tid, 
+      mode, 
+      mc_is_within_valid_secondary, 
+      mc_is_valid_aligned_word 
+   );
 }