*/
static struct vg_mallocfunc_info info;
static int init_done;
+#define DO_INIT if (UNLIKELY(!init_done)) init()
/* Startup hook - called as init section */
__attribute__((constructor))
replacing.
*/
+/* The replacement functions are running on the simulated CPU.
+ The code on the simulated CPU does not necessarily use
+ all arguments. E.g. args can be ignored and/or only given
+ to a NON SIMD call.
+ The definedness of such 'unused' arguments will not be verified
+ by memcheck.
+ A call to 'trigger_memcheck_error_if_undefined' allows
+ memcheck to detect such errors for the otherwise unused args.
+ Apart of allowing memcheck to detect an error, the function
+ trigger_memcheck_error_if_undefined has no effect and
+ has a minimal cost for other tools replacing malloc functions.
+*/
+static inline void trigger_memcheck_error_if_undefined ( ULong x )
+{
+ if (x == 0) __asm__ __volatile__( "" ::: "memory" );
+}
/*---------------------- malloc ----------------------*/
{ \
void* v; \
\
- if (!init_done) init(); \
+ DO_INIT; \
+ trigger_memcheck_error_if_undefined((ULong)n ); \
MALLOC_TRACE(#fnname "(%llu)", (ULong)n ); \
\
v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \
{ \
void* v; \
\
- if (!init_done) init(); \
+ DO_INIT; \
+ trigger_memcheck_error_if_undefined((ULong) zone); \
+ trigger_memcheck_error_if_undefined((ULong) n); \
MALLOC_TRACE(#fnname "(%p, %llu)", zone, (ULong)n ); \
\
v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \
{ \
void* v; \
\
- if (!init_done) init(); \
+ DO_INIT; \
+ trigger_memcheck_error_if_undefined((ULong) n); \
MALLOC_TRACE(#fnname "(%llu)", (ULong)n ); \
\
v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \
void VG_REPLACE_FUNCTION_EZU(10040,soname,fnname) (void *zone, void *p); \
void VG_REPLACE_FUNCTION_EZU(10040,soname,fnname) (void *zone, void *p) \
{ \
- if (!init_done) init(); \
+ DO_INIT; \
+ trigger_memcheck_error_if_undefined((ULong) zone); \
MALLOC_TRACE(#fnname "(%p, %p)\n", zone, p ); \
if (p == NULL) \
return; \
void VG_REPLACE_FUNCTION_EZU(10050,soname,fnname) (void *p); \
void VG_REPLACE_FUNCTION_EZU(10050,soname,fnname) (void *p) \
{ \
- if (!init_done) init(); \
+ DO_INIT; \
MALLOC_TRACE(#fnname "(%p)\n", p ); \
if (p == NULL) \
return; \
{ \
void* v; \
\
- if (!init_done) init(); \
+ DO_INIT; \
+ trigger_memcheck_error_if_undefined((ULong) zone); \
+ trigger_memcheck_error_if_undefined((ULong) nmemb); \
+ trigger_memcheck_error_if_undefined((ULong) size); \
MALLOC_TRACE("zone_calloc(%p, %llu,%llu)", zone, (ULong)nmemb, (ULong)size ); \
\
v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_calloc, nmemb, size ); \
{ \
void* v; \
\
- if (!init_done) init(); \
+ DO_INIT; \
MALLOC_TRACE("calloc(%llu,%llu)", (ULong)nmemb, (ULong)size ); \
\
/* Protect against overflow. See bug 24078. (that bug number is
{ \
void* v; \
\
- if (!init_done) init(); \
+ DO_INIT; \
MALLOC_TRACE("zone_realloc(%p,%p,%llu)", zone, ptrV, (ULong)new_size ); \
\
if (ptrV == NULL) \
{ \
void* v; \
\
- if (!init_done) init(); \
+ DO_INIT; \
MALLOC_TRACE("realloc(%p,%llu)", ptrV, (ULong)new_size ); \
\
if (ptrV == NULL) \
{ \
void* v; \
\
- if (!init_done) init(); \
+ DO_INIT; \
+ trigger_memcheck_error_if_undefined((ULong) zone); \
+ trigger_memcheck_error_if_undefined((ULong) n); \
MALLOC_TRACE("zone_memalign(%p, al %llu, size %llu)", \
zone, (ULong)alignment, (ULong)n ); \
\
{ \
void* v; \
\
- if (!init_done) init(); \
+ DO_INIT; \
+ trigger_memcheck_error_if_undefined((ULong) n); \
MALLOC_TRACE("memalign(al %llu, size %llu)", \
(ULong)alignment, (ULong)n ); \
\
static int pszB = 0; \
if (pszB == 0) \
pszB = my_getpagesize(); \
+ trigger_memcheck_error_if_undefined((ULong) zone); \
return VG_REPLACE_FUNCTION_EZU(10110,VG_Z_LIBC_SONAME,memalign) \
((SizeT)pszB, size); \
}
{ \
/* In glibc-2.2.4, 1 denotes a successful return value for \
mallopt */ \
+ trigger_memcheck_error_if_undefined((ULong) cmd); \
+ trigger_memcheck_error_if_undefined((ULong) value); \
return 1; \
}
{ \
/* 0 denotes that malloc_trim() either wasn't able \
to do anything, or was not implemented */ \
+ trigger_memcheck_error_if_undefined((ULong) pad); \
return 0; \
}
{ \
SizeT pszB; \
\
- if (!init_done) init(); \
+ DO_INIT; \
MALLOC_TRACE("malloc_usable_size(%p)", p ); \
if (NULL == p) \
return 0; \
struct vg_mallinfo VG_REPLACE_FUNCTION_EZU(10200,soname,fnname) ( void ) \
{ \
static struct vg_mallinfo mi; \
- if (!init_done) init(); \
+ DO_INIT; \
MALLOC_TRACE("mallinfo()\n"); \
(void)VALGRIND_NON_SIMD_CALL1( info.mallinfo, &mi ); \
return mi; \
{
/* Implement "malloc_size" by handing the request through to the
tool's .tl_usable_size method. */
- if (!init_done) init();
+ DO_INIT;
+ trigger_memcheck_error_if_undefined((ULong) zone);
+ trigger_memcheck_error_if_undefined((ULong) ptr);
size_t res = (size_t)VALGRIND_NON_SIMD_CALL1(
info.tl_malloc_usable_size, ptr);
return res;
int VG_REPLACE_FUNCTION_EZU(10230,soname,fnname)(void* zone); \
int VG_REPLACE_FUNCTION_EZU(10230,soname,fnname)(void* zone) \
{ \
+ trigger_memcheck_error_if_undefined((ULong) zone); \
return 1; \
}
--- /dev/null
+#include <stdlib.h>
+#include <malloc.h>
+#include "../memcheck.h"
+int main (int argc, char*argv[])
+{
+ size_t def_size = 1<<20;
+ char *p;
+ char *new_p;
+
+ if (argc > 10000) def_size = def_size * 2;
+
+ {
+ size_t size = def_size;
+ VALGRIND_MAKE_MEM_UNDEFINED(&size, 1);
+ p = malloc(size);
+ }
+
+ VALGRIND_MAKE_MEM_UNDEFINED(&p, 1);
+ new_p = realloc(p, def_size);
+
+ VALGRIND_MAKE_MEM_UNDEFINED(&new_p, 1);
+ new_p = realloc(new_p, def_size);
+
+ VALGRIND_MAKE_MEM_UNDEFINED(&new_p, 1);
+ free (new_p);
+
+ {
+ size_t nmemb = 1;
+ VALGRIND_MAKE_MEM_UNDEFINED(&nmemb, 1);
+ new_p = calloc(nmemb, def_size);
+ free (new_p);
+ }
+
+ {
+ size_t alignment = 1;
+ VALGRIND_MAKE_MEM_UNDEFINED(&alignment, 1);
+ new_p = memalign(alignment, def_size);
+ free(new_p);
+ }
+
+ {
+ size_t nmemb = 16;
+ size_t size = def_size;
+ VALGRIND_MAKE_MEM_UNDEFINED(&size, 1);
+ new_p = memalign(nmemb, size);
+ free(new_p);
+ }
+
+ {
+ size_t size = def_size;
+ VALGRIND_MAKE_MEM_UNDEFINED(&size, 1);
+ new_p = valloc(size);
+ free (new_p);
+ }
+
+ return 0;
+}
--- /dev/null
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: malloc (vg_replace_malloc.c:...)
+ by 0x........: main (undef_malloc_args.c:15)
+
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: realloc (vg_replace_malloc.c:...)
+ by 0x........: main (undef_malloc_args.c:19)
+
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: realloc (vg_replace_malloc.c:...)
+ by 0x........: main (undef_malloc_args.c:22)
+
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: free (vg_replace_malloc.c:...)
+ by 0x........: main (undef_malloc_args.c:25)
+
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: calloc (vg_replace_malloc.c:...)
+ by 0x........: main (undef_malloc_args.c:30)
+
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: memalign (vg_replace_malloc.c:...)
+ by 0x........: main (undef_malloc_args.c:37)
+
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: memalign (vg_replace_malloc.c:...)
+ by 0x........: main (undef_malloc_args.c:45)
+
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: memalign (vg_replace_malloc.c:...)
+ by 0x........: valloc (vg_replace_malloc.c:...)
+ by 0x........: main (undef_malloc_args.c:52)
+