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 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h
index ec923b1..9474b60 100644
--- a/coregrind/vg_include.h
+++ b/coregrind/vg_include.h
@@ -915,7 +915,7 @@
             __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 ab87bdb..87f580d 100644
--- a/coregrind/vg_malloc2.c
+++ b/coregrind/vg_malloc2.c
@@ -233,7 +233,8 @@
    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 cd8eba1..4b4fe0c 100644
--- a/coregrind/vg_memory.c
+++ b/coregrind/vg_memory.c
@@ -332,7 +332,7 @@
       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 
 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 @@
                          + 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 @@
 
    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 b2b62b4..4f8cb71 100644
--- a/coregrind/vg_mylibc.c
+++ b/coregrind/vg_mylibc.c
@@ -1241,7 +1241,7 @@
    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 @@
    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 65a5196..4e68b67 100644
--- a/coregrind/vg_scheduler.c
+++ b/coregrind/vg_scheduler.c
@@ -2116,7 +2116,8 @@
          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 a364df0..e69dda2 100644
--- a/coregrind/vg_transtab.c
+++ b/coregrind/vg_transtab.c
@@ -508,11 +508,13 @@
 
    /* 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 d68b430..f873b9f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -30,4 +30,4 @@
 	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 0000000..2b7121c
--- /dev/null
+++ b/tests/nanoleak.c
@@ -0,0 +1,9 @@
+
+#include <malloc.h>
+
+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 ec923b1..9474b60 100644
--- a/vg_include.h
+++ b/vg_include.h
@@ -915,7 +915,7 @@
             __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 ab87bdb..87f580d 100644
--- a/vg_malloc2.c
+++ b/vg_malloc2.c
@@ -233,7 +233,8 @@
    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 cd8eba1..4b4fe0c 100644
--- a/vg_memory.c
+++ b/vg_memory.c
@@ -332,7 +332,7 @@
       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 
 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 @@
                          + 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 @@
 
    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 b2b62b4..4f8cb71 100644
--- a/vg_mylibc.c
+++ b/vg_mylibc.c
@@ -1241,7 +1241,7 @@
    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 @@
    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 65a5196..4e68b67 100644
--- a/vg_scheduler.c
+++ b/vg_scheduler.c
@@ -2116,7 +2116,8 @@
          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 a364df0..e69dda2 100644
--- a/vg_transtab.c
+++ b/vg_transtab.c
@@ -508,11 +508,13 @@
 
    /* 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. */