From: Nicholas Nethercote Date: Tue, 17 Feb 2009 04:31:18 +0000 (+0000) Subject: In the core, include malloc_usable_size() as one of the functions that must X-Git-Tag: svn/VALGRIND_3_5_0~965 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3ed4532cded9d6a563ef97a803a77f4a325ec5bd;p=thirdparty%2Fvalgrind.git In the core, include malloc_usable_size() as one of the functions that must be replaced if malloc() et al are replaced by a tool. This is because different tools implement the function in different ways. Add an appropriate malloc_usable_size() replacement to each of Memcheck, Helgrind, DRD, Ptrcheck, Massif. Update memcheck/tests/malloc_usable and add massif/tests/malloc_usable. Merged from the DARWIN branch. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@9193 --- diff --git a/coregrind/m_mallocfree.c b/coregrind/m_mallocfree.c index c775a163f2..e31a3b7221 100644 --- a/coregrind/m_mallocfree.c +++ b/coregrind/m_mallocfree.c @@ -1664,8 +1664,7 @@ void* VG_(arena_memalign) ( ArenaId aid, HChar* cc, } -// The ThreadId doesn't matter, it's not used. -SizeT VG_(arena_payload_szB) ( ThreadId tid, ArenaId aid, void* ptr ) +SizeT VG_(arena_malloc_usable_size) ( ArenaId aid, void* ptr ) { Arena* a = arenaId_to_ArenaP(aid); Block* b = get_payload_block(a, ptr); @@ -1853,7 +1852,7 @@ Char* VG_(strdup) ( HChar* cc, const Char* s ) // Useful for querying user blocks. SizeT VG_(malloc_usable_size) ( void* p ) { - return VG_(arena_payload_szB)(VG_INVALID_THREADID, VG_AR_CLIENT, p); + return VG_(arena_malloc_usable_size)(VG_AR_CLIENT, p); } diff --git a/coregrind/m_replacemalloc/vg_replace_malloc.c b/coregrind/m_replacemalloc/vg_replace_malloc.c index eaa568deb7..c60b1fe900 100644 --- a/coregrind/m_replacemalloc/vg_replace_malloc.c +++ b/coregrind/m_replacemalloc/vg_replace_malloc.c @@ -559,8 +559,7 @@ POSIX_MEMALIGN(VG_Z_LIBC_SONAME, memalign_common); if (NULL == p) \ return 0; \ \ - pszB = (SizeT)VALGRIND_NON_SIMD_CALL2( info.arena_payload_szB, \ - VG_AR_CLIENT, p ); \ + pszB = (SizeT)VALGRIND_NON_SIMD_CALL1( info.tl_malloc_usable_size, p ); \ MALLOC_TRACE(" = %llu", (ULong)pszB ); \ \ return pszB; \ diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c index d8bc44d45e..7176f30f73 100644 --- a/coregrind/m_scheduler/scheduler.c +++ b/coregrind/m_scheduler/scheduler.c @@ -1372,8 +1372,8 @@ void do_client_request ( ThreadId tid ) info->tl_free = VG_(tdict).tool_free; info->tl___builtin_delete = VG_(tdict).tool___builtin_delete; info->tl___builtin_vec_delete = VG_(tdict).tool___builtin_vec_delete; + info->tl_malloc_usable_size = VG_(tdict).tool_malloc_usable_size; - info->arena_payload_szB = VG_(arena_payload_szB); info->mallinfo = VG_(mallinfo); info->clo_trace_malloc = VG_(clo_trace_malloc); diff --git a/coregrind/m_tooliface.c b/coregrind/m_tooliface.c index 6504aa97b2..74b1b7205b 100644 --- a/coregrind/m_tooliface.c +++ b/coregrind/m_tooliface.c @@ -298,6 +298,7 @@ void VG_(needs_malloc_replacement)( void (*__builtin_delete) ( ThreadId, void* ), void (*__builtin_vec_delete) ( ThreadId, void* ), void* (*realloc) ( ThreadId, void*, SizeT ), + SizeT (*malloc_usable_size) ( ThreadId, void* ), SizeT client_malloc_redzone_szB ) { @@ -311,6 +312,7 @@ void VG_(needs_malloc_replacement)( VG_(tdict).tool___builtin_delete = __builtin_delete; VG_(tdict).tool___builtin_vec_delete = __builtin_vec_delete; VG_(tdict).tool_realloc = realloc; + VG_(tdict).tool_malloc_usable_size = malloc_usable_size; VG_(tdict).tool_client_redzone_szB = client_malloc_redzone_szB; } diff --git a/coregrind/pub_core_mallocfree.h b/coregrind/pub_core_mallocfree.h index 510a22faaf..4797b0b4ce 100644 --- a/coregrind/pub_core_mallocfree.h +++ b/coregrind/pub_core_mallocfree.h @@ -100,6 +100,8 @@ extern Char* VG_(arena_strdup) ( ArenaId aid, HChar* cc, // Nb: The ThreadId doesn't matter, it's not used. extern SizeT VG_(arena_payload_szB) ( ThreadId tid, ArenaId aid, void* payload ); +extern SizeT VG_(arena_malloc_usable_size) ( ArenaId aid, void* payload ); + extern void VG_(mallinfo) ( ThreadId tid, struct vg_mallinfo* mi ); extern void VG_(sanity_check_malloc_all) ( void ); diff --git a/coregrind/pub_core_replacemalloc.h b/coregrind/pub_core_replacemalloc.h index ae7acf710b..4c8adbbb70 100644 --- a/coregrind/pub_core_replacemalloc.h +++ b/coregrind/pub_core_replacemalloc.h @@ -49,7 +49,7 @@ struct vg_mallocfunc_info { void (*tl___builtin_delete) (ThreadId tid, void* p); void (*tl___builtin_vec_delete)(ThreadId tid, void* p); void* (*tl_realloc) (ThreadId tid, void* p, SizeT size); - SizeT (*arena_payload_szB) (ThreadId tid, ArenaId aid, void* payload); + SizeT (*tl_malloc_usable_size) (ThreadId tid, void* payload); void (*mallinfo) (ThreadId tid, struct vg_mallinfo* mi); Bool clo_trace_malloc; }; diff --git a/coregrind/pub_core_tooliface.h b/coregrind/pub_core_tooliface.h index 1e1535ac67..09743b3f9f 100644 --- a/coregrind/pub_core_tooliface.h +++ b/coregrind/pub_core_tooliface.h @@ -155,6 +155,7 @@ typedef struct { void (*tool___builtin_delete) (ThreadId, void*); void (*tool___builtin_vec_delete)(ThreadId, void*); void* (*tool_realloc) (ThreadId, void*, SizeT); + SizeT (*tool_malloc_usable_size) (ThreadId, void*); SizeT tool_client_redzone_szB; // VG_(needs).final_IR_tidy_pass diff --git a/drd/drd_malloc_wrappers.c b/drd/drd_malloc_wrappers.c index 556ff5f52b..086f82f70e 100644 --- a/drd/drd_malloc_wrappers.c +++ b/drd/drd_malloc_wrappers.c @@ -243,6 +243,15 @@ static void DRD_(__builtin_vec_delete)(ThreadId tid, void* p) DRD_(handle_free)(tid, (Addr)p); } +static SizeT DRD_(malloc_usable_size) ( ThreadId tid, void* p ) +{ + DRD_Chunk *mc = VG_(HT_lookup)( DRD_(s_malloc_list), (UWord)p ); + + // There may be slop, but pretend there isn't because only the asked-for + // area will have been shadowed properly. + return ( mc ? mc->size : 0 ); +} + void DRD_(register_malloc_wrappers)(const StartUsingMem start_callback, const StopUsingMem stop_callback) { @@ -264,6 +273,7 @@ void DRD_(register_malloc_wrappers)(const StartUsingMem start_callback, DRD_(__builtin_delete), DRD_(__builtin_vec_delete), DRD_(realloc), + DRD_(malloc_usable_size), 0); } diff --git a/exp-ptrcheck/h_main.c b/exp-ptrcheck/h_main.c index 4762051ddc..49ccd1b4d4 100644 --- a/exp-ptrcheck/h_main.c +++ b/exp-ptrcheck/h_main.c @@ -999,6 +999,15 @@ void* h_replace_realloc ( ThreadId tid, void* p_old, SizeT new_size ) } } +SizeT h_replace_malloc_usable_size ( ThreadId tid, void* p ) +{ + Seg* seg = find_Seg_by_addr( (Addr)p ); + + // There may be slop, but pretend there isn't because only the asked-for + // area will have been shadowed properly. + return ( seg ? seg->szB : 0 ); +} + /*------------------------------------------------------------*/ /*--- Memory events ---*/ diff --git a/exp-ptrcheck/h_main.h b/exp-ptrcheck/h_main.h index 83e17b17ae..b8aae92267 100644 --- a/exp-ptrcheck/h_main.h +++ b/exp-ptrcheck/h_main.h @@ -65,6 +65,7 @@ void h_replace_free ( ThreadId tid, void* p ); void h_replace___builtin_delete ( ThreadId tid, void* p ); void h_replace___builtin_vec_delete ( ThreadId tid, void* p ); void* h_replace_realloc ( ThreadId tid, void* p_old, SizeT new_size ); +SizeT h_replace_malloc_usable_size ( ThreadId tid, void* p ); void h_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx, ULong di_handle ); diff --git a/exp-ptrcheck/pc_main.c b/exp-ptrcheck/pc_main.c index 3183f9980b..c98666a2ae 100644 --- a/exp-ptrcheck/pc_main.c +++ b/exp-ptrcheck/pc_main.c @@ -166,6 +166,7 @@ static void pc_pre_clo_init(void) h_replace___builtin_delete, h_replace___builtin_vec_delete, h_replace_realloc, + h_replace_malloc_usable_size, 0 /* no need for client heap redzones */ ); VG_(needs_var_info) (); diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c index 51fa2f8e2d..be0d408c0f 100644 --- a/helgrind/hg_main.c +++ b/helgrind/hg_main.c @@ -3475,6 +3475,15 @@ static void* hg_cli__realloc ( ThreadId tid, void* payloadV, SizeT new_size ) } } +static SizeT hg_cli_malloc_usable_size ( ThreadId tid, void* p ) +{ + MallocMeta *md = VG_(HT_lookup)( hg_mallocmeta_table, (UWord)p ); + + // There may be slop, but pretend there isn't because only the asked-for + // area will have been shadowed properly. + return ( md ? md->szB : 0 ); +} + /*--------------------------------------------------------------*/ /*--- Instrumentation ---*/ @@ -4222,6 +4231,7 @@ static void hg_pre_clo_init ( void ) hg_cli____builtin_delete, hg_cli____builtin_vec_delete, hg_cli__realloc, + hg_cli_malloc_usable_size, HG_CLI__MALLOC_REDZONE_SZB ); /* 21 Dec 08: disabled this; it mostly causes H to start more diff --git a/include/pub_tool_tooliface.h b/include/pub_tool_tooliface.h index 8194706c8b..10c9a855fa 100644 --- a/include/pub_tool_tooliface.h +++ b/include/pub_tool_tooliface.h @@ -433,6 +433,7 @@ extern void VG_(needs_malloc_replacement)( void (*p__builtin_delete) ( ThreadId tid, void* p ), void (*p__builtin_vec_delete) ( ThreadId tid, void* p ), void* (*prealloc) ( ThreadId tid, void* p, SizeT new_size ), + SizeT (*pmalloc_usable_size) ( ThreadId tid, void* p), SizeT client_malloc_redzone_szB ); diff --git a/massif/ms_main.c b/massif/ms_main.c index 1f63ef0dfc..0df97e1668 100644 --- a/massif/ms_main.c +++ b/massif/ms_main.c @@ -1687,6 +1687,12 @@ static void* ms_realloc ( ThreadId tid, void* p_old, SizeT new_szB ) return renew_block(tid, p_old, new_szB); } +static SizeT ms_malloc_usable_size ( ThreadId tid, void* p ) +{ + HP_Chunk* hc = VG_(HT_lookup)( malloc_list, (UWord)p ); + + return ( hc ? hc->req_szB + hc->slop_szB : 0 ); +} //------------------------------------------------------------// //--- Stacks ---// @@ -2225,6 +2231,7 @@ static void ms_pre_clo_init(void) ms___builtin_delete, ms___builtin_vec_delete, ms_realloc, + ms_malloc_usable_size, 0 ); // HP_Chunks diff --git a/massif/tests/Makefile.am b/massif/tests/Makefile.am index fd5a01db0d..ef19aff7e5 100644 --- a/massif/tests/Makefile.am +++ b/massif/tests/Makefile.am @@ -21,6 +21,7 @@ EXTRA_DIST = $(noinst_SCRIPTS) \ ignoring.post.exp ignoring.stderr.exp ignoring.vgtest \ long-names.post.exp long-names.stderr.exp long-names.vgtest \ long-time.post.exp long-time.stderr.exp long-time.vgtest \ + malloc_usable.stderr.exp malloc_usable.vgtest \ new-cpp.post.exp new-cpp.stderr.exp new-cpp.vgtest \ no-stack-no-heap.post.exp no-stack-no-heap.stderr.exp no-stack-no-heap.vgtest \ null.post.exp null.stderr.exp null.vgtest \ @@ -57,6 +58,7 @@ check_PROGRAMS = \ insig \ long-names \ long-time \ + malloc_usable \ new-cpp \ null \ one \ diff --git a/massif/tests/malloc_usable.c b/massif/tests/malloc_usable.c new file mode 100644 index 0000000000..e825e3d98b --- /dev/null +++ b/massif/tests/malloc_usable.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +int main(void) +{ + // Because our allocations are in multiples of 8 or 16, 99 will round up + // to 104 or 112. + int* x = malloc(99); + + // XXX: would be better to have a HAVE_MALLOC_USABLE_SIZE variable here +# if !defined(_AIX) + assert(104 == malloc_usable_size(x) || + 112 == malloc_usable_size(x)); + assert( 0 == malloc_usable_size(NULL)); + assert( 0 == malloc_usable_size((void*)0xdeadbeef)); +# endif + + return 0; +} diff --git a/massif/tests/malloc_usable.stderr.exp b/massif/tests/malloc_usable.stderr.exp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/massif/tests/malloc_usable.vgtest b/massif/tests/malloc_usable.vgtest new file mode 100644 index 0000000000..407d872618 --- /dev/null +++ b/massif/tests/malloc_usable.vgtest @@ -0,0 +1,2 @@ +prog: malloc_usable +vgopts: -q diff --git a/memcheck/mc_include.h b/memcheck/mc_include.h index f9108a84ff..ddc441b979 100644 --- a/memcheck/mc_include.h +++ b/memcheck/mc_include.h @@ -121,6 +121,7 @@ void MC_(free) ( ThreadId tid, void* p ); void MC_(__builtin_delete) ( ThreadId tid, void* p ); void MC_(__builtin_vec_delete) ( ThreadId tid, void* p ); void* MC_(realloc) ( ThreadId tid, void* p, SizeT new_size ); +SizeT MC_(malloc_usable_size) ( ThreadId tid, void* p ); /*------------------------------------------------------------*/ diff --git a/memcheck/mc_main.c b/memcheck/mc_main.c index fe3941a583..6363e925df 100644 --- a/memcheck/mc_main.c +++ b/memcheck/mc_main.c @@ -5711,6 +5711,7 @@ static void mc_pre_clo_init(void) MC_(__builtin_delete), MC_(__builtin_vec_delete), MC_(realloc), + MC_(malloc_usable_size), MC_MALLOC_REDZONE_SZB ); VG_(needs_xml_output) (); diff --git a/memcheck/mc_malloc_wrappers.c b/memcheck/mc_malloc_wrappers.c index e2a9eae677..a37288add9 100644 --- a/memcheck/mc_malloc_wrappers.c +++ b/memcheck/mc_malloc_wrappers.c @@ -483,6 +483,15 @@ void* MC_(realloc) ( ThreadId tid, void* p_old, SizeT new_szB ) return p_new; } +SizeT MC_(malloc_usable_size) ( ThreadId tid, void* p ) +{ + MC_Chunk* mc = VG_(HT_lookup) ( MC_(malloc_list), (UWord)p ); + + // There may be slop, but pretend there isn't because only the asked-for + // area will be marked as addressable. + return ( mc ? mc->szB : 0 ); +} + /* Memory pool stuff. */ void MC_(create_mempool)(Addr pool, UInt rzB, Bool is_zeroed) diff --git a/memcheck/tests/malloc_usable.c b/memcheck/tests/malloc_usable.c index a42a5a5b32..8055c95d2f 100644 --- a/memcheck/tests/malloc_usable.c +++ b/memcheck/tests/malloc_usable.c @@ -5,10 +5,16 @@ int main(void) { - // Since our allocations are in multiples of 8, 99 will round up to 104. + // Because Memcheck marks any slop as inaccessible, it doesn't round up + // sizes for malloc_usable_size(). int* x = malloc(99); + + // DDD: would be better to have a HAVE_MALLOC_USABLE_SIZE variable here # if !defined(_AIX) - assert(104 == malloc_usable_size(x)); + assert(99 == malloc_usable_size(x)); + assert( 0 == malloc_usable_size(NULL)); + assert( 0 == malloc_usable_size((void*)0xdeadbeef)); # endif + return 0; }