diff options
Diffstat (limited to 'coregrind/m_replacemalloc/.svn')
5 files changed, 823 insertions, 0 deletions
diff --git a/coregrind/m_replacemalloc/.svn/dir-prop-base b/coregrind/m_replacemalloc/.svn/dir-prop-base new file mode 100644 index 0000000..67452d4 --- /dev/null +++ b/coregrind/m_replacemalloc/.svn/dir-prop-base @@ -0,0 +1,9 @@ +K 10 +svn:ignore +V 31 +*.a +.deps +Makefile +Makefile.in + +END diff --git a/coregrind/m_replacemalloc/.svn/entries b/coregrind/m_replacemalloc/.svn/entries new file mode 100644 index 0000000..e9dd2ec --- /dev/null +++ b/coregrind/m_replacemalloc/.svn/entries @@ -0,0 +1,52 @@ +8 + +dir +9703 +svn://svn.valgrind.org/valgrind/trunk/coregrind/m_replacemalloc +svn://svn.valgrind.org/valgrind + + + +2009-03-15T23:25:38.213170Z +9416 +njn +has-props + +svn:special svn:externals svn:needs-lock + + + + + + + + + + + +a5019735-40e9-0310-863c-91ae7b9d1cf9 + +vg_replace_malloc.c +file + + + + +2009-04-30T16:44:03.000000Z +668390256967085938a92b45f269e8ba +2009-03-15T23:25:38.213170Z +9416 +njn + +replacemalloc_core.c +file + + + + +2009-03-13T17:30:22.000000Z +9398a475146fb7a1371b9f917e1d2691 +2009-03-10T22:02:09.669944Z +9344 +njn + diff --git a/coregrind/m_replacemalloc/.svn/format b/coregrind/m_replacemalloc/.svn/format new file mode 100644 index 0000000..45a4fb7 --- /dev/null +++ b/coregrind/m_replacemalloc/.svn/format @@ -0,0 +1 @@ +8 diff --git a/coregrind/m_replacemalloc/.svn/text-base/replacemalloc_core.c.svn-base b/coregrind/m_replacemalloc/.svn/text-base/replacemalloc_core.c.svn-base new file mode 100644 index 0000000..fbae2bc --- /dev/null +++ b/coregrind/m_replacemalloc/.svn/text-base/replacemalloc_core.c.svn-base @@ -0,0 +1,118 @@ + +/*--------------------------------------------------------------------*/ +/*--- Malloc replacement. replacemalloc_core.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2009 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#include "pub_core_basics.h" +#include "pub_core_libcbase.h" +#include "pub_core_libcprint.h" +#include "pub_core_mallocfree.h" +#include "pub_core_options.h" +#include "pub_core_replacemalloc.h" + +/*------------------------------------------------------------*/ +/*--- Command line options ---*/ +/*------------------------------------------------------------*/ + +/* Nb: the allocator always rounds blocks up to a multiple of + VG_MIN_MALLOC_SZB. +*/ + +/* DEBUG: print malloc details? default: NO */ +Bool VG_(clo_trace_malloc) = False; + +/* Minimum alignment in functions that don't specify alignment explicitly. + default: 0, i.e. use VG_MIN_MALLOC_SZB. */ +UInt VG_(clo_alignment) = VG_MIN_MALLOC_SZB; + + +Bool VG_(replacement_malloc_process_cmd_line_option)(Char* arg) +{ + if VG_INT_CLO(arg, "--alignment", VG_(clo_alignment)) { + if (VG_(clo_alignment) < VG_MIN_MALLOC_SZB || + VG_(clo_alignment) > 4096 || + VG_(log2)( VG_(clo_alignment) ) == -1 /* not a power of 2 */) + { + VG_(message)(Vg_UserMsg, + "Invalid --alignment= setting. " + "Should be a power of 2, >= %d, <= 4096.", VG_MIN_MALLOC_SZB); + VG_(err_bad_option)("--alignment"); + } + } + + else if VG_BOOL_CLO(arg, "--trace-malloc", VG_(clo_trace_malloc)) {} + else + return False; + + return True; +} + +void VG_(replacement_malloc_print_usage)(void) +{ + VG_(printf)( +" --alignment=<number> set minimum alignment of allocations [%d]\n", + VG_MIN_MALLOC_SZB + ); +} + +void VG_(replacement_malloc_print_debug_usage)(void) +{ + VG_(printf)( +" --trace-malloc=no|yes show client malloc details? [no]\n" + ); +} + +/*------------------------------------------------------------*/ +/*--- Useful functions ---*/ +/*------------------------------------------------------------*/ + +void* VG_(cli_malloc) ( SizeT align, SizeT nbytes ) +{ + // 'align' should be valid (ie. big enough and a power of two) by now. + // VG_(arena_memalign)() will abort if it's not. + if (VG_MIN_MALLOC_SZB == align) + return VG_(arena_malloc) ( VG_AR_CLIENT, "replacemalloc.cm.1", + nbytes ); + else + return VG_(arena_memalign) ( VG_AR_CLIENT, "replacemalloc.cm.2", + align, nbytes ); +} + +void VG_(cli_free) ( void* p ) +{ + VG_(arena_free) ( VG_AR_CLIENT, p ); +} + +Bool VG_(addr_is_in_block)( Addr a, Addr start, SizeT size, SizeT rz_szB ) +{ + return ( start - rz_szB <= a && a < start + size + rz_szB ); +} + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ diff --git a/coregrind/m_replacemalloc/.svn/text-base/vg_replace_malloc.c.svn-base b/coregrind/m_replacemalloc/.svn/text-base/vg_replace_malloc.c.svn-base new file mode 100644 index 0000000..3de33f9 --- /dev/null +++ b/coregrind/m_replacemalloc/.svn/text-base/vg_replace_malloc.c.svn-base @@ -0,0 +1,643 @@ + +/*--------------------------------------------------------------------*/ +/*--- Replacements for malloc() et al, which run on the simulated ---*/ +/*--- CPU. vg_replace_malloc.c ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2000-2009 Julian Seward + jseward@acm.org + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +/* --------------------------------------------------------------------- + ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU. + + These functions are drop-in replacements for malloc() and friends. + They have global scope, but are not intended to be called directly. + See pub_core_redir.h for the gory details. + + This file can be linked into the vg_preload_<tool>.so file for any tool + that wishes to know about calls to malloc(). The tool must define all + the functions that will be called via 'info'. + + It is called vg_replace_malloc.c because this filename appears in stack + traces, so we want the name to be (hopefully!) meaningful to users. + ------------------------------------------------------------------ */ + +#include "pub_core_basics.h" +#include "pub_core_vki.h" // VKI_EINVAL, VKI_ENOMEM +#include "pub_core_clreq.h" // for VALGRIND_INTERNAL_PRINTF, + // VALGRIND_NON_SIMD_CALL[12] +#include "pub_core_debuginfo.h" // needed for pub_core_redir.h :( +#include "pub_core_mallocfree.h" // for VG_MIN_MALLOC_SZB, VG_AR_CLIENT +#include "pub_core_redir.h" // for VG_REPLACE_FUNCTION_* +#include "pub_core_replacemalloc.h" + + +/* 2 Apr 05: the Portland Group compiler, which uses cfront/ARM style + mangling, could be supported properly by the redirects in this + module. Except we can't because it doesn't put its allocation + functions in libpgc.so but instead hardwires them into the + compilation unit holding main(), which makes them impossible to + intercept directly. Fortunately those fns seem to route everything + through to malloc/free. + + mid-06: could be improved, since we can now intercept in the main + executable too. +*/ + +__attribute__ ((__noreturn__)) +extern void _exit(int); + +/* Apparently it is necessary to make ourselves free of any dependency + on memcpy() on ppc32-aix5; else programs linked with -brtl fail. + memcpy() is used by gcc for a struct assignment in mallinfo() + below. Add the following conservative implementation (memmove, + really). */ +#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) +__attribute__((weak)) +void *memcpy(void *destV, const void *srcV, unsigned long n) +{ + unsigned char* src = (unsigned char*)srcV; + unsigned char* dest = (unsigned char*)destV; + unsigned long i; + if (dest < src) { + for (i = 0; i < n; i++) + dest[i] = src[i]; + } + if (dest > src) { + for (i = n; i > 0; i--) + dest[i-1] = src[i-1]; + } + return dest; +} +#endif + + +/*------------------------------------------------------------*/ +/*--- Replacing malloc() et al ---*/ +/*------------------------------------------------------------*/ + +/* This struct is initially empty. Before the first use of any of + these functions, we make a client request which fills in the + fields. +*/ +static struct vg_mallocfunc_info info; +static int init_done; + +/* Startup hook - called as init section */ +static void init(void) __attribute__((constructor)); + +#define MALLOC_TRACE(format, args...) \ + if (info.clo_trace_malloc) \ + VALGRIND_INTERNAL_PRINTF(format, ## args ) + +/* Below are new versions of malloc, __builtin_new, free, + __builtin_delete, calloc, realloc, memalign, and friends. + + None of these functions are called directly - they are not meant to + be found by the dynamic linker. But ALL client calls to malloc() + and friends wind up here eventually. They get called because + vg_replace_malloc installs a bunch of code redirects which causes + Valgrind to use these functions rather than the ones they're + replacing. +*/ + + +/*---------------------- malloc ----------------------*/ + +/* Generate a replacement for 'fnname' in object 'soname', which calls + 'vg_replacement' to allocate memory. If that fails, return NULL. +*/ +#define ALLOC_or_NULL(soname, fnname, vg_replacement) \ + \ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n); \ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n) \ + { \ + void* v; \ + \ + if (!init_done) init(); \ + MALLOC_TRACE(#fnname "(%llu)", (ULong)n ); \ + \ + v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \ + MALLOC_TRACE(" = %p", v ); \ + return v; \ + } + + +/* Generate a replacement for 'fnname' in object 'soname', which calls + 'vg_replacement' to allocate memory. If that fails, it bombs the + system. +*/ +#define ALLOC_or_BOMB(soname, fnname, vg_replacement) \ + \ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n); \ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) (SizeT n) \ + { \ + void* v; \ + \ + if (!init_done) init(); \ + MALLOC_TRACE(#fnname "(%llu)", (ULong)n ); \ + \ + v = (void*)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, n ); \ + MALLOC_TRACE(" = %p", v ); \ + if (NULL == v) { \ + VALGRIND_PRINTF_BACKTRACE( \ + "new/new[] failed and should throw an exception, but Valgrind\n" \ + " cannot throw exceptions and so is aborting instead. Sorry."); \ + _exit(1); \ + } \ + return v; \ + } + +// Each of these lines generates a replacement function: +// (from_so, from_fn, v's replacement) + +// malloc +ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, malloc, malloc); +ALLOC_or_NULL(VG_Z_LIBC_SONAME, malloc, malloc); +#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) +ALLOC_or_NULL(VG_Z_LIBC_SONAME, malloc_common, malloc); +#endif + + +/*---------------------- new ----------------------*/ + +// operator new(unsigned int), not mangled (for gcc 2.96) +ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, builtin_new, __builtin_new); +ALLOC_or_BOMB(VG_Z_LIBC_SONAME, builtin_new, __builtin_new); + +ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, __builtin_new, __builtin_new); +ALLOC_or_BOMB(VG_Z_LIBC_SONAME, __builtin_new, __builtin_new); + +// operator new(unsigned int), GNU mangling +#if VG_WORDSIZE == 4 + ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwj, __builtin_new); + ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znwj, __builtin_new); +#endif + +// operator new(unsigned long), GNU mangling +#if VG_WORDSIZE == 8 || defined(VGP_ppc32_aix5) + ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znwm, __builtin_new); + ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znwm, __builtin_new); +#endif + +// operator new(unsigned long), ARM/cfront mangling +#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) + ALLOC_or_BOMB(VG_Z_LIBC_DOT_A, __nw__FUl, __builtin_new); +#endif + + +/*---------------------- new nothrow ----------------------*/ + +// operator new(unsigned, std::nothrow_t const&), GNU mangling +#if VG_WORDSIZE == 4 + ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwjRKSt9nothrow_t, __builtin_new); + ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnwjRKSt9nothrow_t, __builtin_new); +#endif + +// operator new(unsigned long, std::nothrow_t const&), GNU mangling +#if VG_WORDSIZE == 8 || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) + ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnwmRKSt9nothrow_t, __builtin_new); + ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnwmRKSt9nothrow_t, __builtin_new); +#endif + +// operator new(unsigned long, std::nothrow_t const&), ARM/cfront mangling +#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) + ALLOC_or_NULL(VG_Z_LIBC_DOT_A, __nw__FUlRCQ2_3std9nothrow_t, __builtin_new); +#endif + + +/*---------------------- new [] ----------------------*/ + +// operator new[](unsigned int), not mangled (for gcc 2.96) +ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, __builtin_vec_new, __builtin_vec_new ); +ALLOC_or_BOMB(VG_Z_LIBC_SONAME, __builtin_vec_new, __builtin_vec_new ); + +// operator new[](unsigned int), GNU mangling +#if VG_WORDSIZE == 4 + ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znaj, __builtin_vec_new ); + ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znaj, __builtin_vec_new ); +#endif + +// operator new[](unsigned long), GNU mangling +#if VG_WORDSIZE == 8 || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) + ALLOC_or_BOMB(VG_Z_LIBSTDCXX_SONAME, _Znam, __builtin_vec_new ); + ALLOC_or_BOMB(VG_Z_LIBC_SONAME, _Znam, __builtin_vec_new ); +#endif + +// operator new[](unsigned long), ARM/cfront mangling +#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) + ALLOC_or_BOMB(VG_Z_LIBC_DOT_A, __vn__FUl, __builtin_vec_new); +#endif + + +/*---------------------- new [] nothrow ----------------------*/ + +// operator new[](unsigned, std::nothrow_t const&), GNU mangling +#if VG_WORDSIZE == 4 + ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnajRKSt9nothrow_t, __builtin_vec_new ); + ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnajRKSt9nothrow_t, __builtin_vec_new ); +#endif + +// operator new[](unsigned long, std::nothrow_t const&), GNU mangling +#if VG_WORDSIZE == 8 || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) + ALLOC_or_NULL(VG_Z_LIBSTDCXX_SONAME, _ZnamRKSt9nothrow_t, __builtin_vec_new ); + ALLOC_or_NULL(VG_Z_LIBC_SONAME, _ZnamRKSt9nothrow_t, __builtin_vec_new ); +#endif + +// operator new [](unsigned long, std::nothrow_t const&), ARM/cfront mangling +#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) + ALLOC_or_BOMB(VG_Z_LIBC_DOT_A, __vn__FUlRCQ2_3std9nothrow_t, __builtin_vec_new ); +#endif + + +/*---------------------- free ----------------------*/ + +/* Generate a replacement for 'fnname' in object 'soname', which calls + 'vg_replacement' to free previously allocated memory. +*/ +#define FREE(soname, fnname, vg_replacement) \ + \ + void VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *p); \ + void VG_REPLACE_FUNCTION_ZU(soname,fnname) (void *p) \ + { \ + if (!init_done) init(); \ + MALLOC_TRACE(#vg_replacement "(%p)", p ); \ + if (p == NULL) \ + return; \ + (void)VALGRIND_NON_SIMD_CALL1( info.tl_##vg_replacement, p ); \ + } + +// free +FREE(VG_Z_LIBSTDCXX_SONAME, free, free ); +FREE(VG_Z_LIBC_SONAME, free, free ); +#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) +FREE(VG_Z_LIBC_SONAME, free_common, free ); +#endif + + +/*---------------------- cfree ----------------------*/ + +// cfree +FREE(VG_Z_LIBSTDCXX_SONAME, cfree, free ); +FREE(VG_Z_LIBC_SONAME, cfree, free ); + + +/*---------------------- delete ----------------------*/ +// operator delete(void*), not mangled (for gcc 2.96) +FREE(VG_Z_LIBSTDCXX_SONAME, __builtin_delete, __builtin_delete ); +FREE(VG_Z_LIBC_SONAME, __builtin_delete, __builtin_delete ); + +// operator delete(void*), GNU mangling +FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPv, __builtin_delete ); +FREE(VG_Z_LIBC_SONAME, _ZdlPv, __builtin_delete ); + +// operator delete(void*), ARM/cfront mangling +#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) +FREE(VG_Z_LIBC_DOT_A, __dl__FPv, __builtin_delete ); +#endif + + +/*---------------------- delete nothrow ----------------------*/ + +// operator delete(void*, std::nothrow_t const&), GNU mangling +FREE(VG_Z_LIBSTDCXX_SONAME, _ZdlPvRKSt9nothrow_t, __builtin_delete ); +FREE(VG_Z_LIBC_SONAME, _ZdlPvRKSt9nothrow_t, __builtin_delete ); + + +/*---------------------- delete [] ----------------------*/ +// operator delete[](void*), not mangled (for gcc 2.96) +FREE(VG_Z_LIBSTDCXX_SONAME, __builtin_vec_delete, __builtin_vec_delete ); +FREE(VG_Z_LIBC_SONAME, __builtin_vec_delete, __builtin_vec_delete ); + +// operator delete[](void*), GNU mangling +FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPv, __builtin_vec_delete ); +FREE(VG_Z_LIBC_SONAME, _ZdaPv, __builtin_vec_delete ); + +// operator delete[](void*), ARM/cfront mangling +#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) +FREE(VG_Z_LIBC_DOT_A, __vd__FPv, __builtin_vec_delete ); +#endif + + +/*---------------------- delete [] nothrow ----------------------*/ + +// operator delete[](void*, std::nothrow_t const&), GNU mangling +FREE(VG_Z_LIBSTDCXX_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete ); +FREE(VG_Z_LIBC_SONAME, _ZdaPvRKSt9nothrow_t, __builtin_vec_delete ); + + +/*---------------------- calloc ----------------------*/ + +#define CALLOC(soname, fnname) \ + \ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT nmemb, SizeT size ); \ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT nmemb, SizeT size ) \ + { \ + void* v; \ + \ + if (!init_done) init(); \ + MALLOC_TRACE("calloc(%llu,%llu)", (ULong)nmemb, (ULong)size ); \ + \ + v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_calloc, nmemb, size ); \ + MALLOC_TRACE(" = %p", v ); \ + return v; \ + } + +CALLOC(VG_Z_LIBC_SONAME, calloc); +#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) +CALLOC(VG_Z_LIBC_SONAME, calloc_common); +#endif + + +/*---------------------- realloc ----------------------*/ + +#define REALLOC(soname, fnname) \ + \ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void* ptrV, SizeT new_size );\ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( void* ptrV, SizeT new_size ) \ + { \ + void* v; \ + \ + if (!init_done) init(); \ + MALLOC_TRACE("realloc(%p,%llu)", ptrV, (ULong)new_size ); \ + \ + if (ptrV == NULL) \ + /* We need to call a malloc-like function; so let's use \ + one which we know exists. */ \ + return VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME,malloc) (new_size); \ + if (new_size <= 0) { \ + VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME,free)(ptrV); \ + MALLOC_TRACE(" = 0"); \ + return NULL; \ + } \ + v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_realloc, ptrV, new_size ); \ + MALLOC_TRACE(" = %p", v ); \ + return v; \ + } + +REALLOC(VG_Z_LIBC_SONAME, realloc); +#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) +REALLOC(VG_Z_LIBC_SONAME, realloc_common); +#endif + + +/*---------------------- memalign ----------------------*/ + +#define MEMALIGN(soname, fnname) \ + \ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT alignment, SizeT n ); \ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT alignment, SizeT n ) \ + { \ + void* v; \ + \ + if (!init_done) init(); \ + MALLOC_TRACE("memalign(al %llu, size %llu)", \ + (ULong)alignment, (ULong)n ); \ + \ + /* Round up to minimum alignment if necessary. */ \ + if (alignment < VG_MIN_MALLOC_SZB) \ + alignment = VG_MIN_MALLOC_SZB; \ + \ + /* Round up to nearest power-of-two if necessary (like glibc). */ \ + while (0 != (alignment & (alignment - 1))) alignment++; \ + \ + v = (void*)VALGRIND_NON_SIMD_CALL2( info.tl_memalign, alignment, n ); \ + MALLOC_TRACE(" = %p", v ); \ + return v; \ + } + +MEMALIGN(VG_Z_LIBC_SONAME, memalign); + + +/*---------------------- valloc ----------------------*/ + +static int local__getpagesize ( void ) { +# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) + return 4096; /* kludge - toc problems prevent calling getpagesize() */ +# else + extern int getpagesize (void); + return getpagesize(); +# endif +} + +#define VALLOC(soname, fnname) \ + \ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT size ); \ + void* VG_REPLACE_FUNCTION_ZU(soname,fnname) ( SizeT size ) \ + { \ + static int pszB = 0; \ + if (pszB == 0) \ + pszB = local__getpagesize(); \ + return VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME,memalign) \ + ((SizeT)pszB, size); \ + } + +VALLOC(VG_Z_LIBC_SONAME, valloc); + + +/*---------------------- mallopt ----------------------*/ + +/* Various compatibility wrapper functions, for glibc and libstdc++. */ + +#define MALLOPT(soname, fnname) \ + \ + int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( int cmd, int value ); \ + int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( int cmd, int value ) \ + { \ + /* In glibc-2.2.4, 1 denotes a successful return value for \ + mallopt */ \ + return 1; \ + } + +MALLOPT(VG_Z_LIBC_SONAME, mallopt); + + +/*---------------------- malloc_trim ----------------------*/ +// Documentation says: +// malloc_trim(size_t pad); +// +// If possible, gives memory back to the system (via negative arguments to +// sbrk) if there is unused memory at the `high' end of the malloc pool. +// You can call this after freeing large blocks of memory to potentially +// reduce the system-level memory requirements of a program. However, it +// cannot guarantee to reduce memory. Under some allocation patterns, +// some large free blocks of memory will be locked between two used +// chunks, so they cannot be given back to the system. +// +// The `pad' argument to malloc_trim represents the amount of free +// trailing space to leave untrimmed. If this argument is zero, only the +// minimum amount of memory to maintain internal data structures will be +// left (one page or less). Non-zero arguments can be supplied to maintain +// enough trailing space to service future expected allocations without +// having to re-obtain memory from the system. +// +// Malloc_trim returns 1 if it actually released any memory, else 0. On +// systems that do not support "negative sbrks", it will always return 0. +// +// For simplicity, we always return 0. +#define MALLOC_TRIM(soname, fnname) \ + \ + int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( SizeT pad ); \ + int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( SizeT pad ) \ + { \ + /* 0 denotes that malloc_trim() either wasn't able \ + to do anything, or was not implemented */ \ + return 0; \ + } + +MALLOC_TRIM(VG_Z_LIBC_SONAME, malloc_trim); + + +/*---------------------- posix_memalign ----------------------*/ + +#define POSIX_MEMALIGN(soname, fnname) \ + \ + int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void **memptr, \ + SizeT alignment, SizeT size ); \ + int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void **memptr, \ + SizeT alignment, SizeT size ) \ + { \ + void *mem; \ + \ + /* Test whether the alignment argument is valid. It must be \ + a power of two multiple of sizeof (void *). */ \ + if (alignment % sizeof (void *) != 0 \ + || (alignment & (alignment - 1)) != 0) \ + return VKI_EINVAL; \ + \ + mem = VG_REPLACE_FUNCTION_ZU(VG_Z_LIBC_SONAME,memalign)(alignment, size); \ + \ + if (mem != NULL) { \ + *memptr = mem; \ + return 0; \ + } \ + \ + return VKI_ENOMEM; \ + } + +POSIX_MEMALIGN(VG_Z_LIBC_SONAME, posix_memalign); +#if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) +/* 27 Nov 07: it appears that xlc links into executables, a + posix_memalign, which calls onwards to memalign_common, with the + same args. */ +POSIX_MEMALIGN(VG_Z_LIBC_SONAME, memalign_common); +#endif + + +/*---------------------- malloc_usable_size ----------------------*/ + +#define MALLOC_USABLE_SIZE(soname, fnname) \ + \ + int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void* p ); \ + int VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void* p ) \ + { \ + SizeT pszB; \ + \ + if (!init_done) init(); \ + MALLOC_TRACE("malloc_usable_size(%p)", p ); \ + if (NULL == p) \ + return 0; \ + \ + pszB = (SizeT)VALGRIND_NON_SIMD_CALL1( info.tl_malloc_usable_size, p ); \ + MALLOC_TRACE(" = %llu", (ULong)pszB ); \ + \ + return pszB; \ + } + +MALLOC_USABLE_SIZE(VG_Z_LIBC_SONAME, malloc_usable_size); + + +/*---------------------- (unimplemented) ----------------------*/ + +/* Bomb out if we get any of these. */ + +static void panic(const char *str) +{ + VALGRIND_PRINTF_BACKTRACE("Program aborting because of call to %s", str); + _exit(99); + *(int *)0 = 'x'; +} + +#define PANIC(soname, fnname) \ + \ + void VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ); \ + void VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ) \ + { \ + panic(#fnname); \ + } + +PANIC(VG_Z_LIBC_SONAME, pvalloc); +PANIC(VG_Z_LIBC_SONAME, malloc_get_state); +PANIC(VG_Z_LIBC_SONAME, malloc_set_state); + +#define MALLOC_STATS(soname, fnname) \ + \ + void VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ); \ + void VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ) \ + { \ + /* Valgrind's malloc_stats implementation does nothing. */ \ + } + +MALLOC_STATS(VG_Z_LIBC_SONAME, malloc_stats); + + +/*---------------------- mallinfo ----------------------*/ + +// mi must be static; if it is auto then Memcheck thinks it is +// uninitialised when used by the caller of this function, because Memcheck +// doesn't know that the call to mallinfo fills in mi. +#define MALLINFO(soname, fnname) \ + \ + struct vg_mallinfo VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ); \ + struct vg_mallinfo VG_REPLACE_FUNCTION_ZU(soname, fnname) ( void ) \ + { \ + static struct vg_mallinfo mi; \ + if (!init_done) init(); \ + MALLOC_TRACE("mallinfo()"); \ + (void)VALGRIND_NON_SIMD_CALL1( info.mallinfo, &mi ); \ + return mi; \ + } + +MALLINFO(VG_Z_LIBC_SONAME, mallinfo); + + +/* All the code in here is unused until this function is called */ + +static void init(void) +{ + int res; + + if (init_done) + return; + + init_done = 1; + + VALGRIND_DO_CLIENT_REQUEST(res, -1, VG_USERREQ__GET_MALLOCFUNCS, &info, + 0, 0, 0, 0); +} + +/*--------------------------------------------------------------------*/ +/*--- end vg_replace_malloc.c ---*/ +/*--------------------------------------------------------------------*/ |