From: Julian Seward Date: Wed, 5 Jun 2002 20:28:33 +0000 (+0000) Subject: Minor mods to stop make the leak detector behave properly for the X-Git-Tag: svn/VALGRIND_1_0_3~84 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=46e09a22f62ad9b8a5f6b8c1d5c9eff3bfadc861;p=thirdparty%2Fvalgrind.git Minor mods to stop make the leak detector behave properly for the following kind of stupid test program int main (void) { char* a = malloc(100); return 0; } which many people seem fond of trying for some reason. In general the leak detector works fine. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@387 --- diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h index ec923b1881..9474b60596 100644 --- a/coregrind/vg_include.h +++ b/coregrind/vg_include.h @@ -915,7 +915,7 @@ extern void VG_(panic) ( Char* str ) __attribute__ ((__noreturn__)); /* Get memory by anonymous mmap. */ -extern void* VG_(get_memory_from_mmap) ( Int nBytes ); +extern void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who ); /* Crude stand-in for the glibc system() call. */ extern Int VG_(system) ( Char* cmd ); diff --git a/coregrind/vg_malloc2.c b/coregrind/vg_malloc2.c index ab87bdb5c5..87f580d01a 100644 --- a/coregrind/vg_malloc2.c +++ b/coregrind/vg_malloc2.c @@ -233,7 +233,8 @@ Superblock* newSuperblock ( Arena* a, Int cszW ) cszW += 2; /* Take into account sb->next and sb->n_words fields */ if (cszW < a->min_sblockW) cszW = a->min_sblockW; while ((cszW % VKI_WORDS_PER_PAGE) > 0) cszW++; - sb = VG_(get_memory_from_mmap) ( cszW * sizeof(Word) ); + sb = VG_(get_memory_from_mmap) ( cszW * sizeof(Word), + "newSuperblock" ); sb->n_payload_words = cszW - 2; a->bytes_mmaped += cszW * sizeof(Word); if (0) diff --git a/coregrind/vg_memory.c b/coregrind/vg_memory.c index cd8eba12fa..4b4fe0cff5 100644 --- a/coregrind/vg_memory.c +++ b/coregrind/vg_memory.c @@ -332,7 +332,7 @@ static SecMap* alloc_secondary_map ( __attribute__ ((unused)) although this isn't important, so the following assert is spurious. */ vg_assert(0 == (sizeof(SecMap) % VKI_BYTES_PER_PAGE)); - map = VG_(get_memory_from_mmap)( sizeof(SecMap) ); + map = VG_(get_memory_from_mmap)( sizeof(SecMap), caller ); for (i = 0; i < 8192; i++) map->abits[i] = VGM_BYTE_INVALID; /* Invalid address */ @@ -1963,8 +1963,40 @@ static Addr vglc_max_mallocd_addr; static void vg_detect_memory_leaks_notify_addr ( Addr a, UInt word_at_a ) { - Int sh_no; - Addr ptr = (Addr)word_at_a; + Int sh_no; + Addr ptr; + + /* Rule out some known causes of bogus pointers. Mostly these do + not cause much trouble because only a few false pointers can + ever lurk in these places. This mainly stops it reporting that + blocks are still reachable in stupid test programs like this + + int main (void) { char* a = malloc(100); return 0; } + + which people seem inordinately fond of writing, for some reason. + + Note that this is a complete kludge. It would be better to + ignore any addresses corresponding to valgrind.so's .bss and + .data segments, but I cannot think of a reliable way to identify + where the .bss segment has been put. If you can, drop me a + line. + */ + if (a >= ((Addr)(&VG_(stack))) + && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack))) { + return; + } + if (a >= ((Addr)(&VG_(m_state_static))) + && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static))) { + return; + } + if (a == (Addr)(&vglc_min_mallocd_addr)) + return; + if (a == (Addr)(&vglc_max_mallocd_addr)) + return; + + /* OK, let's get on and do something Useful for a change. */ + + ptr = (Addr)word_at_a; if (ptr >= vglc_min_mallocd_addr && ptr <= vglc_max_mallocd_addr) { /* Might be legitimate; we'll have to investigate further. */ sh_no = find_shadow_for ( ptr, vglc_shadows, vglc_n_shadows ); @@ -1975,6 +2007,7 @@ void vg_detect_memory_leaks_notify_addr ( Addr a, UInt word_at_a ) + vglc_shadows[sh_no]->size); /* Decide whether Proper-ly or Interior-ly reached. */ if (ptr == vglc_shadows[sh_no]->data) { + if (0) VG_(printf)("pointer at %p to %p\n", a, word_at_a ); vglc_reachedness[sh_no] = Proper; } else { if (vglc_reachedness[sh_no] == Unreached) @@ -2147,10 +2180,10 @@ void VG_(detect_memory_leaks) ( void ) VG_(message)(Vg_UserMsg, ""); VG_(message)(Vg_UserMsg, "LEAK SUMMARY:"); - VG_(message)(Vg_UserMsg, " possibly lost: %d bytes in %d blocks.", - bytes_dubious, blocks_dubious ); VG_(message)(Vg_UserMsg, " definitely lost: %d bytes in %d blocks.", bytes_leaked, blocks_leaked ); + VG_(message)(Vg_UserMsg, " possibly lost: %d bytes in %d blocks.", + bytes_dubious, blocks_dubious ); VG_(message)(Vg_UserMsg, " still reachable: %d bytes in %d blocks.", bytes_reachable, blocks_reachable ); if (!VG_(clo_show_reachable)) { diff --git a/coregrind/vg_mylibc.c b/coregrind/vg_mylibc.c index b2b62b4d00..4f8cb71921 100644 --- a/coregrind/vg_mylibc.c +++ b/coregrind/vg_mylibc.c @@ -1241,7 +1241,7 @@ void VG_(end_rdtsc_calibration) ( void ) Primitive support for bagging memory via mmap. ------------------------------------------------------------------ */ -void* VG_(get_memory_from_mmap) ( Int nBytes ) +void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who ) { static UInt tot_alloc = 0; void* p = VG_(mmap)( 0, nBytes, @@ -1250,8 +1250,9 @@ void* VG_(get_memory_from_mmap) ( Int nBytes ) if (p != ((void*)(-1))) { tot_alloc += (UInt)nBytes; if (0) - VG_(printf)("get_memory_from_mmap: %d tot, %d req\n", - tot_alloc, nBytes); + VG_(printf)( + "get_memory_from_mmap: %d tot, %d req = %p .. %p, caller %s\n", + tot_alloc, nBytes, p, ((char*)p) + nBytes - 1, who ); return p; } VG_(printf)("vg_get_memory_from_mmap failed on request of %d\n", diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c index 65a5196676..4e68b67f80 100644 --- a/coregrind/vg_scheduler.c +++ b/coregrind/vg_scheduler.c @@ -2116,7 +2116,8 @@ void do__apply_in_new_thread ( ThreadId parent_tid, assigning it for the first time. */ vg_assert(VG_(threads)[tid].stack_size == 0); vg_assert(VG_(threads)[tid].stack_base == (Addr)NULL); - new_stack = (Addr)VG_(get_memory_from_mmap)( new_stk_szb ); + new_stack = (Addr)VG_(get_memory_from_mmap)( new_stk_szb, + "new thread stack" ); VG_(threads)[tid].stack_base = new_stack; VG_(threads)[tid].stack_size = new_stk_szb; VG_(threads)[tid].stack_highest_word diff --git a/coregrind/vg_transtab.c b/coregrind/vg_transtab.c index a364df0b86..e69dda2d09 100644 --- a/coregrind/vg_transtab.c +++ b/coregrind/vg_transtab.c @@ -508,11 +508,13 @@ void VG_(init_tt_tc) ( void ) /* Allocate the translation table and translation cache. */ vg_assert(vg_tc == NULL); - vg_tc = VG_(get_memory_from_mmap) ( VG_TC_SIZE * sizeof(UChar) ); + vg_tc = VG_(get_memory_from_mmap) ( VG_TC_SIZE * sizeof(UChar), + "trans-cache" ); vg_assert(vg_tc != NULL); vg_assert(vg_tt == NULL); - vg_tt = VG_(get_memory_from_mmap) ( VG_TT_SIZE * sizeof(TTEntry) ); + vg_tt = VG_(get_memory_from_mmap) ( VG_TT_SIZE * sizeof(TTEntry), + "trans-table" ); vg_assert(vg_tt != NULL); /* The main translation table is empty. */ diff --git a/tests/Makefile.am b/tests/Makefile.am index d68b430d75..f873b9f66b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -30,4 +30,4 @@ EXTRA_DIST = \ pth_once.c weirdioctl.c pth_signal1.c pth_signal2.c \ discard.c pth_semaphore1.c new_override.cpp pth_yield.c \ sigaltstack.c erringfds.c sigwait_all.c \ - pth_cancel1.c pth_cancel2.c pth_signal_gober.c + pth_cancel1.c pth_cancel2.c pth_signal_gober.c nanoleak.c diff --git a/tests/nanoleak.c b/tests/nanoleak.c new file mode 100644 index 0000000000..2b7121cbf4 --- /dev/null +++ b/tests/nanoleak.c @@ -0,0 +1,9 @@ + +#include + +int main ( void ) +{ + volatile int* a = malloc(1000); + a[0] = 0; + return a[0]; +} diff --git a/vg_include.h b/vg_include.h index ec923b1881..9474b60596 100644 --- a/vg_include.h +++ b/vg_include.h @@ -915,7 +915,7 @@ extern void VG_(panic) ( Char* str ) __attribute__ ((__noreturn__)); /* Get memory by anonymous mmap. */ -extern void* VG_(get_memory_from_mmap) ( Int nBytes ); +extern void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who ); /* Crude stand-in for the glibc system() call. */ extern Int VG_(system) ( Char* cmd ); diff --git a/vg_malloc2.c b/vg_malloc2.c index ab87bdb5c5..87f580d01a 100644 --- a/vg_malloc2.c +++ b/vg_malloc2.c @@ -233,7 +233,8 @@ Superblock* newSuperblock ( Arena* a, Int cszW ) cszW += 2; /* Take into account sb->next and sb->n_words fields */ if (cszW < a->min_sblockW) cszW = a->min_sblockW; while ((cszW % VKI_WORDS_PER_PAGE) > 0) cszW++; - sb = VG_(get_memory_from_mmap) ( cszW * sizeof(Word) ); + sb = VG_(get_memory_from_mmap) ( cszW * sizeof(Word), + "newSuperblock" ); sb->n_payload_words = cszW - 2; a->bytes_mmaped += cszW * sizeof(Word); if (0) diff --git a/vg_memory.c b/vg_memory.c index cd8eba12fa..4b4fe0cff5 100644 --- a/vg_memory.c +++ b/vg_memory.c @@ -332,7 +332,7 @@ static SecMap* alloc_secondary_map ( __attribute__ ((unused)) although this isn't important, so the following assert is spurious. */ vg_assert(0 == (sizeof(SecMap) % VKI_BYTES_PER_PAGE)); - map = VG_(get_memory_from_mmap)( sizeof(SecMap) ); + map = VG_(get_memory_from_mmap)( sizeof(SecMap), caller ); for (i = 0; i < 8192; i++) map->abits[i] = VGM_BYTE_INVALID; /* Invalid address */ @@ -1963,8 +1963,40 @@ static Addr vglc_max_mallocd_addr; static void vg_detect_memory_leaks_notify_addr ( Addr a, UInt word_at_a ) { - Int sh_no; - Addr ptr = (Addr)word_at_a; + Int sh_no; + Addr ptr; + + /* Rule out some known causes of bogus pointers. Mostly these do + not cause much trouble because only a few false pointers can + ever lurk in these places. This mainly stops it reporting that + blocks are still reachable in stupid test programs like this + + int main (void) { char* a = malloc(100); return 0; } + + which people seem inordinately fond of writing, for some reason. + + Note that this is a complete kludge. It would be better to + ignore any addresses corresponding to valgrind.so's .bss and + .data segments, but I cannot think of a reliable way to identify + where the .bss segment has been put. If you can, drop me a + line. + */ + if (a >= ((Addr)(&VG_(stack))) + && a <= ((Addr)(&VG_(stack))) + sizeof(VG_(stack))) { + return; + } + if (a >= ((Addr)(&VG_(m_state_static))) + && a <= ((Addr)(&VG_(m_state_static))) + sizeof(VG_(m_state_static))) { + return; + } + if (a == (Addr)(&vglc_min_mallocd_addr)) + return; + if (a == (Addr)(&vglc_max_mallocd_addr)) + return; + + /* OK, let's get on and do something Useful for a change. */ + + ptr = (Addr)word_at_a; if (ptr >= vglc_min_mallocd_addr && ptr <= vglc_max_mallocd_addr) { /* Might be legitimate; we'll have to investigate further. */ sh_no = find_shadow_for ( ptr, vglc_shadows, vglc_n_shadows ); @@ -1975,6 +2007,7 @@ void vg_detect_memory_leaks_notify_addr ( Addr a, UInt word_at_a ) + vglc_shadows[sh_no]->size); /* Decide whether Proper-ly or Interior-ly reached. */ if (ptr == vglc_shadows[sh_no]->data) { + if (0) VG_(printf)("pointer at %p to %p\n", a, word_at_a ); vglc_reachedness[sh_no] = Proper; } else { if (vglc_reachedness[sh_no] == Unreached) @@ -2147,10 +2180,10 @@ void VG_(detect_memory_leaks) ( void ) VG_(message)(Vg_UserMsg, ""); VG_(message)(Vg_UserMsg, "LEAK SUMMARY:"); - VG_(message)(Vg_UserMsg, " possibly lost: %d bytes in %d blocks.", - bytes_dubious, blocks_dubious ); VG_(message)(Vg_UserMsg, " definitely lost: %d bytes in %d blocks.", bytes_leaked, blocks_leaked ); + VG_(message)(Vg_UserMsg, " possibly lost: %d bytes in %d blocks.", + bytes_dubious, blocks_dubious ); VG_(message)(Vg_UserMsg, " still reachable: %d bytes in %d blocks.", bytes_reachable, blocks_reachable ); if (!VG_(clo_show_reachable)) { diff --git a/vg_mylibc.c b/vg_mylibc.c index b2b62b4d00..4f8cb71921 100644 --- a/vg_mylibc.c +++ b/vg_mylibc.c @@ -1241,7 +1241,7 @@ void VG_(end_rdtsc_calibration) ( void ) Primitive support for bagging memory via mmap. ------------------------------------------------------------------ */ -void* VG_(get_memory_from_mmap) ( Int nBytes ) +void* VG_(get_memory_from_mmap) ( Int nBytes, Char* who ) { static UInt tot_alloc = 0; void* p = VG_(mmap)( 0, nBytes, @@ -1250,8 +1250,9 @@ void* VG_(get_memory_from_mmap) ( Int nBytes ) if (p != ((void*)(-1))) { tot_alloc += (UInt)nBytes; if (0) - VG_(printf)("get_memory_from_mmap: %d tot, %d req\n", - tot_alloc, nBytes); + VG_(printf)( + "get_memory_from_mmap: %d tot, %d req = %p .. %p, caller %s\n", + tot_alloc, nBytes, p, ((char*)p) + nBytes - 1, who ); return p; } VG_(printf)("vg_get_memory_from_mmap failed on request of %d\n", diff --git a/vg_scheduler.c b/vg_scheduler.c index 65a5196676..4e68b67f80 100644 --- a/vg_scheduler.c +++ b/vg_scheduler.c @@ -2116,7 +2116,8 @@ void do__apply_in_new_thread ( ThreadId parent_tid, assigning it for the first time. */ vg_assert(VG_(threads)[tid].stack_size == 0); vg_assert(VG_(threads)[tid].stack_base == (Addr)NULL); - new_stack = (Addr)VG_(get_memory_from_mmap)( new_stk_szb ); + new_stack = (Addr)VG_(get_memory_from_mmap)( new_stk_szb, + "new thread stack" ); VG_(threads)[tid].stack_base = new_stack; VG_(threads)[tid].stack_size = new_stk_szb; VG_(threads)[tid].stack_highest_word diff --git a/vg_transtab.c b/vg_transtab.c index a364df0b86..e69dda2d09 100644 --- a/vg_transtab.c +++ b/vg_transtab.c @@ -508,11 +508,13 @@ void VG_(init_tt_tc) ( void ) /* Allocate the translation table and translation cache. */ vg_assert(vg_tc == NULL); - vg_tc = VG_(get_memory_from_mmap) ( VG_TC_SIZE * sizeof(UChar) ); + vg_tc = VG_(get_memory_from_mmap) ( VG_TC_SIZE * sizeof(UChar), + "trans-cache" ); vg_assert(vg_tc != NULL); vg_assert(vg_tt == NULL); - vg_tt = VG_(get_memory_from_mmap) ( VG_TT_SIZE * sizeof(TTEntry) ); + vg_tt = VG_(get_memory_from_mmap) ( VG_TT_SIZE * sizeof(TTEntry), + "trans-table" ); vg_assert(vg_tt != NULL); /* The main translation table is empty. */