__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 );
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)
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 */
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 );
+ 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)
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)) {
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,
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",
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
/* 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. */
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
--- /dev/null
+
+#include <malloc.h>
+
+int main ( void )
+{
+ volatile int* a = malloc(1000);
+ a[0] = 0;
+ return a[0];
+}
__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 );
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)
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 */
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 );
+ 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)
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)) {
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,
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",
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
/* 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. */