From: Julian Seward Date: Wed, 27 Apr 2005 22:46:36 +0000 (+0000) Subject: Reinstate the leak checker; it works at least on x86. X-Git-Tag: svn/VALGRIND_3_0_0~741 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f9156cb08c9fa195ae4c431732019c4bb5e48e61;p=thirdparty%2Fvalgrind.git Reinstate the leak checker; it works at least on x86. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3577 --- diff --git a/memcheck/mac_leakcheck.c b/memcheck/mac_leakcheck.c index bee38b25fb..afea0734f7 100644 --- a/memcheck/mac_leakcheck.c +++ b/memcheck/mac_leakcheck.c @@ -175,8 +175,8 @@ static Addr lc_min_mallocd_addr; 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 @@ static Int lc_markstack_pop(void) 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 @@ static void _lc_scan_memory(Addr start, SizeT len, Int clique) !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 @@ static void _lc_scan_memory(Addr start, SizeT len, Int clique) } 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 @@ static void _lc_scan_memory(Addr start, SizeT len, Int clique) VG_(sigprocmask)(VKI_SIG_SETMASK, &sigmask, NULL); VG_(set_fault_catcher)(NULL); -#endif } @@ -570,8 +568,8 @@ static void make_summary() */ 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 @@ void MAC_(do_detect_memory_leaks) ( } 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 8aa9322d63..f6b0653ea9 100644 --- a/memcheck/mac_shared.h +++ b/memcheck/mac_shared.h @@ -203,6 +203,12 @@ extern HChar* MAC_(event_ctr_name)[N_PROF_EVENTS]; /* 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_(print_malloc_stats) ( void ); 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 cbd0896864..35b66755f2 100644 --- a/memcheck/mc_main.c +++ b/memcheck/mc_main.c @@ -114,12 +114,6 @@ typedef enum { /* --------------- 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 @@ static AuxMapEnt* auxmap = &hacky_auxmaps[0]; /* 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 @@ static AuxMapEnt* find_or_alloc_in_auxmap ( Addr a ) 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 @@ static SecMap* get_secmap_readable ( Addr a ) } } +/* 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 @@ VGA_REGPARM(1) void MC_(helperc_complain_undef) ( HWord sz ) //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 @@ VGA_REGPARM(1) void MC_(helperc_complain_undef) ( HWord sz ) 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 + ); }