From c44555bb37e35d1c319d8ebf4542bfa394ffe170 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 2 Apr 2003 01:42:06 +0000 Subject: [PATCH] Added support for marking heap blocks as inaccessible/uninitialized if valgrind is installed, based on a patch by Adam Gundy. --- configure | 2 ++ configure.ac | 1 + dlls/ntdll/heap.c | 77 ++++++++++++++++++++++++++++++++++----------- include/config.h.in | 3 ++ 4 files changed, 64 insertions(+), 19 deletions(-) diff --git a/configure b/configure index 0451ec739f0..0149a3c6d8e 100755 --- a/configure +++ b/configure @@ -13459,6 +13459,7 @@ done + for ac_header in \ @@ -13532,6 +13533,7 @@ for ac_header in \ termios.h \ unistd.h \ utime.h \ + valgrind/memcheck.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` diff --git a/configure.ac b/configure.ac index 649a9da5720..f6c2ab87b68 100644 --- a/configure.ac +++ b/configure.ac @@ -1072,6 +1072,7 @@ AC_CHECK_HEADERS(\ termios.h \ unistd.h \ utime.h \ + valgrind/memcheck.h ) AC_HEADER_STAT() diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index 792a46b18bb..cc5c6d48865 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -25,6 +25,9 @@ #include #include #include +#ifdef HAVE_VALGRIND_MEMCHECK_H +#include +#endif #define NONAMELESSUNION #define NONAMELESSSTRUCT @@ -143,6 +146,45 @@ static void set_process_heap( HANDLE heap ) processHeap = heap; } +/* mark a block of memory as free for debugging purposes */ +static inline void mark_block_free( void *ptr, size_t size ) +{ + if (TRACE_ON(heap)) memset( ptr, ARENA_FREE_FILLER, size ); +#ifdef VALGRIND_MAKE_NOACCESS + VALGRIND_DISCARD( VALGRIND_MAKE_NOACCESS( ptr, size )); +#endif +} + +/* mark a block of memory as initialized for debugging purposes */ +static inline void mark_block_initialized( void *ptr, size_t size ) +{ +#ifdef VALGRIND_MAKE_READABLE + VALGRIND_DISCARD( VALGRIND_MAKE_READABLE( ptr, size )); +#endif +} + +/* mark a block of memory as uninitialized for debugging purposes */ +static inline void mark_block_uninitialized( void *ptr, size_t size ) +{ +#ifdef VALGRIND_MAKE_WRITABLE + VALGRIND_DISCARD( VALGRIND_MAKE_WRITABLE( ptr, size )); +#endif + if (TRACE_ON(heap)) + { + memset( ptr, ARENA_INUSE_FILLER, size ); +#ifdef VALGRIND_MAKE_WRITABLE + /* make it uninitialized to valgrind again */ + VALGRIND_DISCARD( VALGRIND_MAKE_WRITABLE( ptr, size )); +#endif + } +} + +/* clear contents of a block of memory */ +static inline void clear_block( void *ptr, size_t size ) +{ + mark_block_initialized( ptr, size ); + memset( ptr, 0, size ); +} /*********************************************************************** * HEAP_Dump @@ -345,22 +387,18 @@ static inline BOOL HEAP_Decommit( SUBHEAP *subheap, void *ptr ) static void HEAP_CreateFreeBlock( SUBHEAP *subheap, void *ptr, DWORD size ) { ARENA_FREE *pFree; + char *pEnd; /* Create a free arena */ - + mark_block_uninitialized( ptr, sizeof( ARENA_FREE ) ); pFree = (ARENA_FREE *)ptr; pFree->magic = ARENA_FREE_MAGIC; /* If debugging, erase the freed block content */ - if (TRACE_ON(heap)) - { - char *pEnd = (char *)ptr + size; - if (pEnd > (char *)subheap + subheap->commitSize) - pEnd = (char *)subheap + subheap->commitSize; - if (pEnd > (char *)(pFree + 1)) - memset( pFree + 1, ARENA_FREE_FILLER, pEnd - (char *)(pFree + 1) ); - } + pEnd = (char *)ptr + size; + if (pEnd > (char *)subheap + subheap->commitSize) pEnd = (char *)subheap + subheap->commitSize; + if (pEnd > (char *)(pFree + 1)) mark_block_free( pFree + 1, pEnd - (char *)(pFree + 1) ); /* Check if next block is free also */ @@ -372,8 +410,7 @@ static void HEAP_CreateFreeBlock( SUBHEAP *subheap, void *ptr, DWORD size ) pNext->next->prev = pNext->prev; pNext->prev->next = pNext->next; size += (pNext->size & ARENA_SIZE_MASK) + sizeof(*pNext); - if (TRACE_ON(heap)) - memset( pNext, ARENA_FREE_FILLER, sizeof(ARENA_FREE) ); + mark_block_free( pNext, sizeof(ARENA_FREE) ); } /* Set the next block PREV_FREE flag and pointer */ @@ -382,6 +419,7 @@ static void HEAP_CreateFreeBlock( SUBHEAP *subheap, void *ptr, DWORD size ) { DWORD *pNext = (DWORD *)((char *)ptr + size); *pNext |= ARENA_FLAG_PREV_FREE; + mark_block_initialized( pNext - 1, sizeof( ARENA_FREE * ) ); *(ARENA_FREE **)(pNext - 1) = pFree; } @@ -1089,9 +1127,9 @@ PVOID WINAPI RtlAllocateHeap( HANDLE heap, ULONG flags, ULONG size ) HEAP_ShrinkBlock( subheap, pInUse, size ); if (flags & HEAP_ZERO_MEMORY) - memset( pInUse + 1, 0, pInUse->size & ARENA_SIZE_MASK ); - else if (TRACE_ON(heap)) - memset( pInUse + 1, ARENA_INUSE_FILLER, pInUse->size & ARENA_SIZE_MASK ); + clear_block( pInUse + 1, pInUse->size & ARENA_SIZE_MASK ); + else + mark_block_uninitialized( pInUse + 1, pInUse->size & ARENA_SIZE_MASK ); if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection ); @@ -1254,6 +1292,7 @@ PVOID WINAPI RtlReAllocateHeap( HANDLE heap, ULONG flags, PVOID ptr, ULONG size + sizeof(ARENA_FREE) - sizeof(ARENA_INUSE); pInUse->magic = ARENA_INUSE_MAGIC; HEAP_ShrinkBlock( newsubheap, pInUse, size ); + mark_block_initialized( pInUse + 1, oldSize ); memcpy( pInUse + 1, pArena + 1, oldSize ); /* Free the previous block */ @@ -1270,11 +1309,11 @@ PVOID WINAPI RtlReAllocateHeap( HANDLE heap, ULONG flags, PVOID ptr, ULONG size if (size > oldSize) { if (flags & HEAP_ZERO_MEMORY) - memset( (char *)(pArena + 1) + oldSize, 0, - (pArena->size & ARENA_SIZE_MASK) - oldSize ); - else if (TRACE_ON(heap)) - memset( (char *)(pArena + 1) + oldSize, ARENA_INUSE_FILLER, - (pArena->size & ARENA_SIZE_MASK) - oldSize ); + clear_block( (char *)(pArena + 1) + oldSize, + (pArena->size & ARENA_SIZE_MASK) - oldSize ); + else + mark_block_uninitialized( (char *)(pArena + 1) + oldSize, + (pArena->size & ARENA_SIZE_MASK) - oldSize ); } /* Return the new arena */ diff --git a/include/config.h.in b/include/config.h.in index 4d37b997c9e..4b5a30a02e4 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -626,6 +626,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UTIME_H +/* Define to 1 if you have the header file. */ +#undef HAVE_VALGRIND_MEMCHECK_H + /* Define if we have va_copy */ #undef HAVE_VA_COPY