1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- malloc/free wrappers for detecting errors and updating bits. ---*/ 4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- mc_malloc_wrappers.c ---*/ 5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* 8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This file is part of MemCheck, a heavyweight Valgrind tool for 9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown detecting memory errors. 10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 11b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Copyright (C) 2000-2011 Julian Seward 12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown jseward@acm.org 13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is free software; you can redistribute it and/or 15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown modify it under the terms of the GNU General Public License as 16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown published by the Free Software Foundation; either version 2 of the 17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown License, or (at your option) any later version. 18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown This program is distributed in the hope that it will be useful, but 20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown WITHOUT ANY WARRANTY; without even the implied warranty of 21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown General Public License for more details. 23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown You should have received a copy of the GNU General Public License 25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown along with this program; if not, write to the Free Software 26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 02111-1307, USA. 28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown The GNU General Public License is contained in the file COPYING. 30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/ 31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_basics.h" 33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_execontext.h" 34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_hashtable.h" 35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcbase.h" 36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcassert.h" 37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_libcprint.h" 38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_mallocfree.h" 39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_options.h" 40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_replacemalloc.h" 41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_threadstate.h" 42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_tooliface.h" // Needed for mc_include.h 43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_tool_stacktrace.h" // For VG_(get_and_pp_StackTrace) 44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "mc_include.h" 46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Defns ---*/ 49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Stats ... */ 52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic SizeT cmalloc_n_mallocs = 0; 53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic SizeT cmalloc_n_frees = 0; 54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic ULong cmalloc_bs_mallocd = 0; 55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* For debug printing to do with mempools: what stack trace 57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown depth to show. */ 58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MEMPOOL_DEBUG_STACKTRACE_DEPTH 16 59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Tracking malloc'd and free'd blocks ---*/ 63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Record malloc'd blocks. */ 66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVgHashTable MC_(malloc_list) = NULL; 67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 68f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* Memory pools: a hash table of MC_Mempools. Search key is 69f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root MC_Mempool::pool. */ 70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownVgHashTable MC_(mempool_list) = NULL; 71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Records blocks after freeing. */ 73b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Blocks freed by the client are queued in one of two lists of 74b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov freed blocks not yet physically freed: 75b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "big blocks" freed list. 76b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov "small blocks" freed list 77b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov The blocks with a size >= MC_(clo_freelist_big_blocks) 78b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov are linked in the big blocks freed list. 79b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov This allows a client to allocate and free big blocks 80b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov (e.g. bigger than VG_(clo_freelist_vol)) without losing 81b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov immediately all protection against dangling pointers. 82b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov position [0] is for big blocks, [1] is for small blocks. */ 83b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic MC_Chunk* freed_list_start[2] = {NULL, NULL}; 84b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic MC_Chunk* freed_list_end[2] = {NULL, NULL}; 85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Put a shadow chunk on the freed blocks queue, possibly freeing up 87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown some of the oldest blocks in the queue at the same time. */ 88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_to_freed_queue ( MC_Chunk* mc ) 89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown const Bool show = False; 91b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov const int l = (mc->szB >= MC_(clo_freelist_big_blocks) ? 0 : 1); 92b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 93b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Put it at the end of the freed list, unless the block 94b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov would be directly released any way : in this case, we 95b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov put it at the head of the freed list. */ 96b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (freed_list_end[l] == NULL) { 97b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(freed_list_start[l] == NULL); 98b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mc->next = NULL; 99b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov freed_list_end[l] = freed_list_start[l] = mc; 100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 101b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(freed_list_end[l]->next == NULL); 102b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (mc->szB >= MC_(clo_freelist_vol)) { 103b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mc->next = freed_list_start[l]; 104b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov freed_list_start[l] = mc; 1059bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root } else { 106b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mc->next = NULL; 107b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov freed_list_end[l]->next = mc; 108b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov freed_list_end[l] = mc; 1099bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root } 110b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 111b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(free_queue_volume) += (Long)mc->szB; 112b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (show) 113b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)("mc_freelist: acquire: volume now %lld\n", 114b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(free_queue_volume)); 115b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(free_queue_length)++; 116b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 1179bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root 118b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Release enough of the oldest blocks to bring the free queue 119b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov volume below vg_clo_freelist_vol. 120b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov Start with big block list first. 121b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov On entry, VG_(free_queue_volume) must be > MC_(clo_freelist_vol). 122b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov On exit, VG_(free_queue_volume) will be <= MC_(clo_freelist_vol). */ 123b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovstatic void release_oldest_block(void) 124b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 125b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov const Bool show = False; 126b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int i; 127b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert (VG_(free_queue_volume) > MC_(clo_freelist_vol)); 128b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert (freed_list_start[0] != NULL || freed_list_start[1] != NULL); 129b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 130b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (i = 0; i < 2; i++) { 131b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (VG_(free_queue_volume) > MC_(clo_freelist_vol) 132b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov && freed_list_start[i] != NULL) { 133b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MC_Chunk* mc1; 134b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(freed_list_end[i] != NULL); 135b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 136b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mc1 = freed_list_start[i]; 137b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(free_queue_volume) -= (Long)mc1->szB; 138b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(free_queue_length)--; 139b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (show) 140b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(printf)("mc_freelist: discard: volume now %lld\n", 141b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(free_queue_volume)); 142b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov tl_assert(VG_(free_queue_volume) >= 0); 143b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 144b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (freed_list_start[i] == freed_list_end[i]) { 145b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov freed_list_start[i] = freed_list_end[i] = NULL; 146b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov freed_list_start[i] = mc1->next; 148b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 149b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mc1->next = NULL; /* just paranoia */ 150b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* free MC_Chunk */ 151b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (MC_AllocCustom != mc1->allockind) 152b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(cli_free) ( (void*)(mc1->data) ); 153b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VG_(free) ( mc1 ); 154b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 158b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy StepanovMC_Chunk* MC_(get_freed_block_bracketting) (Addr a) 159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 160b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov int i; 161b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov for (i = 0; i < 2; i++) { 162b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MC_Chunk* mc; 163b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mc = freed_list_start[i]; 164b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov while (mc) { 165b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(addr_is_in_block)( a, mc->data, mc->szB, 166b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MC_MALLOC_REDZONE_SZB )) 167b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return mc; 168b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mc = mc->next; 169b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 170b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 171b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return NULL; 172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 174b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* Allocate a shadow chunk, put it on the appropriate list. 175b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov If needed, release oldest blocks from freed list. */ 176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMC_Chunk* create_MC_Chunk ( ExeContext* ec, Addr p, SizeT szB, 178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_AllocKind kind) 179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Chunk* mc = VG_(malloc)("mc.cMC.1 (a MC_Chunk)", sizeof(MC_Chunk)); 181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc->data = p; 182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc->szB = szB; 183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc->allockind = kind; 184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc->where = ec; 185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 186b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Each time a new MC_Chunk is created, release oldest blocks 187b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if the free list volume is exceeded. */ 188b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (VG_(free_queue_volume) > MC_(clo_freelist_vol)) 189b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov release_oldest_block(); 190b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Paranoia ... ensure the MC_Chunk is off-limits to the client, so 192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the mc->data field isn't visible to the leak checker. If memory 193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown management is working correctly, any pointer returned by VG_(malloc) 194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown should be noaccess as far as the client is concerned. */ 195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!MC_(check_mem_is_noaccess)( (Addr)mc, sizeof(MC_Chunk), NULL )) { 196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tool_panic)("create_MC_Chunk: shadow area is accessible"); 197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return mc; 199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- client_malloc(), etc ---*/ 203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// XXX: should make this a proper error (bug #79311). 206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool complain_about_silly_args(SizeT sizeB, Char* fn) 207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Cast to a signed type to catch any unexpectedly negative args. We're 209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // assuming here that the size asked for is not greater than 2^31 bytes 210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // (for 32-bit platforms) or 2^63 bytes (for 64-bit platforms). 211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((SSizeT)sizeB < 0) { 212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_(clo_xml)) 213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "Warning: silly arg (%ld) to %s()\n", 214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (SSizeT)sizeB, fn ); 215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool complain_about_silly_args2(SizeT n, SizeT sizeB) 221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if ((SSizeT)n < 0 || (SSizeT)sizeB < 0) { 223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!VG_(clo_xml)) 224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Warning: silly args (%ld,%ld) to calloc()\n", 226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (SSizeT)n, (SSizeT)sizeB); 227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Allocate memory and note change in memory available */ 233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* MC_(new_block) ( ThreadId tid, 234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr p, SizeT szB, SizeT alignB, 235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Bool is_zeroed, MC_AllocKind kind, VgHashTable table) 236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ExeContext* ec; 238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cmalloc_n_mallocs ++; 240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Allocate and zero if necessary 242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (p) { 243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(MC_AllocCustom == kind); 244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(MC_AllocCustom != kind); 246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p = (Addr)VG_(cli_malloc)( alignB, szB ); 247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!p) { 248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_zeroed) { 251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)((void*)p, 0, szB); 252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else 253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (MC_(clo_malloc_fill) != -1) { 254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(MC_(clo_malloc_fill) >= 0x00 && MC_(clo_malloc_fill) <= 0xFF); 255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)((void*)p, MC_(clo_malloc_fill), szB); 256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Only update this stat if allocation succeeded. 260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cmalloc_bs_mallocd += (ULong)szB; 261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ec = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/); 263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(ec); 264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(HT_add_node)( table, create_MC_Chunk(ec, p, szB, kind) ); 266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (is_zeroed) 268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(make_mem_defined)( p, szB ); 269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown else { 270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt ecu = VG_(get_ECU_from_ExeContext)(ec); 271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(VG_(is_plausible_ECU)(ecu)); 272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(make_mem_undefined_w_otag)( p, szB, ecu | MC_OKIND_HEAP ); 273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return (void*)p; 276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* MC_(malloc) ( ThreadId tid, SizeT n ) 279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (complain_about_silly_args(n, "malloc")) { 281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return MC_(new_block) ( tid, 0, n, VG_(clo_alignment), 284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*is_zeroed*/False, MC_AllocMalloc, MC_(malloc_list)); 285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* MC_(__builtin_new) ( ThreadId tid, SizeT n ) 289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (complain_about_silly_args(n, "__builtin_new")) { 291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return MC_(new_block) ( tid, 0, n, VG_(clo_alignment), 294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*is_zeroed*/False, MC_AllocNew, MC_(malloc_list)); 295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* MC_(__builtin_vec_new) ( ThreadId tid, SizeT n ) 299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (complain_about_silly_args(n, "__builtin_vec_new")) { 301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return MC_(new_block) ( tid, 0, n, VG_(clo_alignment), 304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*is_zeroed*/False, MC_AllocNewVec, MC_(malloc_list)); 305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* MC_(memalign) ( ThreadId tid, SizeT alignB, SizeT n ) 309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (complain_about_silly_args(n, "memalign")) { 311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return MC_(new_block) ( tid, 0, n, alignB, 314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*is_zeroed*/False, MC_AllocMalloc, MC_(malloc_list)); 315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* MC_(calloc) ( ThreadId tid, SizeT nmemb, SizeT size1 ) 319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (complain_about_silly_args2(nmemb, size1)) { 321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return MC_(new_block) ( tid, 0, nmemb*size1, VG_(clo_alignment), 324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /*is_zeroed*/True, MC_AllocMalloc, MC_(malloc_list)); 325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic 329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid die_and_free_mem ( ThreadId tid, MC_Chunk* mc, SizeT rzB ) 330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (MC_(clo_free_fill) != -1) { 332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(MC_(clo_free_fill) >= 0x00 && MC_(clo_free_fill) <= 0xFF); 333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)((void*)mc->data, MC_(clo_free_fill), mc->szB); 334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note: make redzones noaccess again -- just in case user made them 337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown accessible with a client request... */ 338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(make_mem_noaccess)( mc->data-rzB, mc->szB + 2*rzB ); 339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Record where freed */ 341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc->where = VG_(record_ExeContext) ( tid, 0/*first_ip_delta*/ ); 342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Put it out of harm's way for a while */ 343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown add_to_freed_queue ( mc ); 344b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* If the free list volume is bigger than MC_(clo_freelist_vol), 345b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov we wait till the next block allocation to release blocks. 346b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov This increase the chance to discover dangling pointer usage, 347b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov even for big blocks being freed by the client. */ 348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(handle_free) ( ThreadId tid, Addr p, UInt rzB, MC_AllocKind kind ) 351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Chunk* mc; 353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cmalloc_n_frees++; 355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc = VG_(HT_remove) ( MC_(malloc_list), (UWord)p ); 357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mc == NULL) { 358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(record_free_error) ( tid, p ); 359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* check if it is a matching free() / delete / delete [] */ 361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (kind != mc->allockind) { 362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(p == mc->data); 363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(record_freemismatch_error) ( tid, mc ); 364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown die_and_free_mem ( tid, mc, rzB ); 366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(free) ( ThreadId tid, void* p ) 370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(handle_free)( 372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, (Addr)p, MC_MALLOC_REDZONE_SZB, MC_AllocMalloc ); 373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(__builtin_delete) ( ThreadId tid, void* p ) 376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(handle_free)( 378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, (Addr)p, MC_MALLOC_REDZONE_SZB, MC_AllocNew); 379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(__builtin_vec_delete) ( ThreadId tid, void* p ) 382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(handle_free)( 384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tid, (Addr)p, MC_MALLOC_REDZONE_SZB, MC_AllocNewVec); 385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* MC_(realloc) ( ThreadId tid, void* p_old, SizeT new_szB ) 388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Chunk* mc; 390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown void* p_new; 391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT old_szB; 392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cmalloc_n_frees ++; 394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cmalloc_n_mallocs ++; 395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cmalloc_bs_mallocd += (ULong)new_szB; 396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (complain_about_silly_args(new_szB, "realloc")) 398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Remove the old block */ 401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc = VG_(HT_remove) ( MC_(malloc_list), (UWord)p_old ); 402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mc == NULL) { 403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(record_free_error) ( tid, (Addr)p_old ); 404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* We return to the program regardless. */ 405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return NULL; 406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* check if its a matching free() / delete / delete [] */ 409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (MC_AllocMalloc != mc->allockind) { 410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* can not realloc a range that was allocated with new or new [] */ 411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert((Addr)p_old == mc->data); 412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(record_freemismatch_error) ( tid, mc ); 413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* but keep going anyway */ 414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old_szB = mc->szB; 417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* In all cases, even when the new size is smaller or unchanged, we 419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown reallocate and copy the contents, and make the old block 420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown inaccessible. This is so as to guarantee to catch all cases of 421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown accesses via the old address after reallocation, regardless of 422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the change in size. (Of course the ability to detect accesses 423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown to the old block also depends on the size of the freed blocks 424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown queue). */ 425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (new_szB <= old_szB) { 427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* new size is smaller or the same */ 428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a_new; 429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get new memory */ 430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_szB); 431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (a_new) { 433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ExeContext* ec; 434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ec = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/); 436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(ec); 437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Retained part is copied, red zones set as normal */ 439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(make_mem_noaccess)( a_new-MC_MALLOC_REDZONE_SZB, 440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_MALLOC_REDZONE_SZB ); 441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(copy_address_range_state) ( (Addr)p_old, a_new, new_szB ); 442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(make_mem_noaccess) ( a_new+new_szB, MC_MALLOC_REDZONE_SZB ); 443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy from old to new */ 445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memcpy)((void*)a_new, p_old, new_szB); 446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Possibly fill freed area with specified junk. */ 448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (MC_(clo_free_fill) != -1) { 449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(MC_(clo_free_fill) >= 0x00 && MC_(clo_free_fill) <= 0xFF); 450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)((void*)p_old, MC_(clo_free_fill), old_szB); 451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Free old memory */ 454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Nb: we have to allocate a new MC_Chunk for the new memory rather 455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown than recycling the old one, so that any erroneous accesses to the 456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old memory are reported. */ 457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown die_and_free_mem ( tid, mc, MC_MALLOC_REDZONE_SZB ); 458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Allocate a new chunk. 460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc = create_MC_Chunk( ec, a_new, new_szB, MC_AllocMalloc ); 461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p_new = (void*)a_new; 464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* new size is bigger */ 467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr a_new; 468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(old_szB < new_szB); 469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Get new memory */ 470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown a_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_szB); 471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (a_new) { 473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt ecu; 474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ExeContext* ec; 475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ec = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/); 477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(ec); 478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ecu = VG_(get_ECU_from_ExeContext)(ec); 479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(VG_(is_plausible_ECU)(ecu)); 480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* First half kept and copied, second half new, red zones as normal */ 482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(make_mem_noaccess)( a_new-MC_MALLOC_REDZONE_SZB, 483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_MALLOC_REDZONE_SZB ); 484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(copy_address_range_state) ( (Addr)p_old, a_new, mc->szB ); 485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(make_mem_undefined_w_otag)( a_new+mc->szB, new_szB-mc->szB, 486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ecu | MC_OKIND_HEAP ); 487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(make_mem_noaccess) ( a_new+new_szB, MC_MALLOC_REDZONE_SZB ); 488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Possibly fill new area with specified junk */ 490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (MC_(clo_malloc_fill) != -1) { 491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(MC_(clo_malloc_fill) >= 0x00 492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown && MC_(clo_malloc_fill) <= 0xFF); 493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)((void*)(a_new+old_szB), MC_(clo_malloc_fill), 494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown new_szB-old_szB); 495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Copy from old to new */ 498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memcpy)((void*)a_new, p_old, mc->szB); 499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Possibly fill freed area with specified junk. */ 501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (MC_(clo_free_fill) != -1) { 502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(MC_(clo_free_fill) >= 0x00 && MC_(clo_free_fill) <= 0xFF); 503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(memset)((void*)p_old, MC_(clo_free_fill), old_szB); 504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Free old memory */ 507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Nb: we have to allocate a new MC_Chunk for the new memory rather 508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown than recycling the old one, so that any erroneous accesses to the 509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown old memory are reported. */ 510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown die_and_free_mem ( tid, mc, MC_MALLOC_REDZONE_SZB ); 511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Allocate a new chunk. 513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc = create_MC_Chunk( ec, a_new, new_szB, MC_AllocMalloc ); 514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown p_new = (void*)a_new; 517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Now insert the new mc (with a possibly new 'data' field) into 520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // malloc_list. If this realloc() did not increase the memory size, we 521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // will have removed and then re-added mc unnecessarily. But that's ok 522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // because shrinking a block with realloc() is (presumably) much rarer 523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // than growing it, and this way simplifies the growing case. 524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(HT_add_node)( MC_(malloc_list), mc ); 525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return p_new; 527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT MC_(malloc_usable_size) ( ThreadId tid, void* p ) 530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Chunk* mc = VG_(HT_lookup) ( MC_(malloc_list), (UWord)p ); 532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // There may be slop, but pretend there isn't because only the asked-for 534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // area will be marked as addressable. 535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return ( mc ? mc->szB : 0 ); 536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 538b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov/* This handles the in place resize of a block, as performed by the 539b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov VALGRIND_RESIZEINPLACE_BLOCK client request. It is unrelated to, 540b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov and not used for, handling of the normal libc realloc() 541b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov function. */ 542b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid MC_(handle_resizeInPlace)(ThreadId tid, Addr p, 543b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov SizeT oldSizeB, SizeT newSizeB, SizeT rzB) 544b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov{ 545b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MC_Chunk* mc = VG_(HT_lookup) ( MC_(malloc_list), (UWord)p ); 546b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (!mc || mc->szB != oldSizeB || newSizeB == 0) { 547b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov /* Reject if: p is not found, or oldSizeB is wrong, 548b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov or new block would be empty. */ 549b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MC_(record_free_error) ( tid, p ); 550b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return; 551b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 552b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 553b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (oldSizeB == newSizeB) 554b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov return; 555b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 556b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov mc->szB = newSizeB; 557b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (newSizeB < oldSizeB) { 558b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MC_(make_mem_noaccess)( p + newSizeB, oldSizeB - newSizeB + rzB ); 559b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } else { 560b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ExeContext* ec = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/); 561b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov UInt ecu = VG_(get_ECU_from_ExeContext)(ec); 562b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MC_(make_mem_undefined_w_otag)( p + oldSizeB, newSizeB - oldSizeB, 563b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov ecu | MC_OKIND_HEAP ); 564b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov if (rzB > 0) 565b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov MC_(make_mem_noaccess)( p + newSizeB, rzB ); 566b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov } 567b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov} 568b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov 569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 570f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/*------------------------------------------------------------*/ 571f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/*--- Memory pool stuff. ---*/ 572f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/*------------------------------------------------------------*/ 573f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 574f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* Set to 1 for intensive sanity checking. Is very expensive though 575f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root and should not be used in production scenarios. See #255966. */ 576f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#define MP_DETAILED_SANITY_CHECKS 0 577f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 578f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Rootstatic void check_mempool_sane(MC_Mempool* mp); /*forward*/ 579f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root 580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(create_mempool)(Addr pool, UInt rzB, Bool is_zeroed) 582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Mempool* mp; 584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 2) { 586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "create_mempool(0x%lx, %d, %d)\n", 587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pool, rzB, is_zeroed); 588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace) 589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (VG_(get_running_tid)(), MEMPOOL_DEBUG_STACKTRACE_DEPTH); 590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mp = VG_(HT_lookup)(MC_(mempool_list), (UWord)pool); 593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mp != NULL) { 594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tool_panic)("MC_(create_mempool): duplicate pool creation"); 595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mp = VG_(malloc)("mc.cm.1", sizeof(MC_Mempool)); 598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mp->pool = pool; 599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mp->rzB = rzB; 600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mp->is_zeroed = is_zeroed; 601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mp->chunks = VG_(HT_construct)( "MC_(create_mempool)" ); 602f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root check_mempool_sane(mp); 603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Paranoia ... ensure this area is off-limits to the client, so 605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown the mp->data field isn't visible to the leak checker. If memory 606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown management is working correctly, anything pointer returned by 607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(malloc) should be noaccess as far as the client is 608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown concerned. */ 609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!MC_(check_mem_is_noaccess)( (Addr)mp, sizeof(MC_Mempool), NULL )) { 610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(tool_panic)("MC_(create_mempool): shadow area is accessible"); 611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(HT_add_node)( MC_(mempool_list), mp ); 614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(destroy_mempool)(Addr pool) 617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Chunk* mc; 619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Mempool* mp; 620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 2) { 622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "destroy_mempool(0x%lx)\n", pool); 623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace) 624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (VG_(get_running_tid)(), MEMPOOL_DEBUG_STACKTRACE_DEPTH); 625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mp = VG_(HT_remove) ( MC_(mempool_list), (UWord)pool ); 628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mp == NULL) { 630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = VG_(get_running_tid)(); 631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(record_illegal_mempool_error) ( tid, pool ); 632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 634f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root check_mempool_sane(mp); 635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Clean up the chunks, one by one 637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(HT_ResetIter)(mp->chunks); 638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( (mc = VG_(HT_Next)(mp->chunks)) ) { 639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Note: make redzones noaccess again -- just in case user made them 640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown accessible with a client request... */ 641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(make_mem_noaccess)(mc->data-mp->rzB, mc->szB + 2*mp->rzB ); 642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown // Destroy the chunk table 644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(HT_destruct)(mp->chunks); 645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(mp); 647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int 650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmp_compar(void* n1, void* n2) 651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Chunk* mc1 = *(MC_Chunk**)n1; 653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Chunk* mc2 = *(MC_Chunk**)n2; 654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mc1->data < mc2->data) return -1; 655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mc1->data > mc2->data) return 1; 656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return 0; 657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void 660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browncheck_mempool_sane(MC_Mempool* mp) 661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt n_chunks, i, bad = 0; 663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown static UInt tick = 0; 664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Chunk **chunks = (MC_Chunk**) VG_(HT_to_array)( mp->chunks, &n_chunks ); 666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (!chunks) 667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 1) { 670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (tick++ >= 10000) 671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown { 672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt total_pools = 0, total_chunks = 0; 673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Mempool* mp2; 674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(HT_ResetIter)(MC_(mempool_list)); 676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( (mp2 = VG_(HT_Next)(MC_(mempool_list))) ) { 677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown total_pools++; 678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(HT_ResetIter)(mp2->chunks); 679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while (VG_(HT_Next)(mp2->chunks)) { 680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown total_chunks++; 681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Total mempools active: %d pools, %d chunks\n", 686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown total_pools, total_chunks); 687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tick = 0; 688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(ssort)((void*)chunks, n_chunks, sizeof(VgHashNode*), mp_compar); 693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Sanity check; assert that the blocks are now in order */ 695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_chunks-1; i++) { 696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (chunks[i]->data > chunks[i+1]->data) { 697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Mempool chunk %d / %d is out of order " 699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "wrt. its successor\n", 700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i+1, n_chunks); 701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad = 1; 702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Sanity check -- make sure they don't overlap */ 706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_chunks-1; i++) { 707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (chunks[i]->data + chunks[i]->szB > chunks[i+1]->data ) { 708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Mempool chunk %d / %d overlaps with its successor\n", 710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i+1, n_chunks); 711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown bad = 1; 712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (bad) { 716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Bad mempool (%d chunks), dumping chunks for inspection:\n", 718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_chunks); 719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_chunks; ++i) { 720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "Mempool chunk %d / %d: %ld bytes " 722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "[%lx,%lx), allocated:\n", 723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown i+1, 724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown n_chunks, 725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown chunks[i]->szB + 0UL, 726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown chunks[i]->data, 727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown chunks[i]->data + chunks[i]->szB); 728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(pp_ExeContext)(chunks[i]->where); 730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(chunks); 733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(mempool_alloc)(ThreadId tid, Addr pool, Addr addr, SizeT szB) 736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Mempool* mp; 738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 2) { 740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "mempool_alloc(0x%lx, 0x%lx, %ld)\n", 741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pool, addr, szB); 742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace) (tid, MEMPOOL_DEBUG_STACKTRACE_DEPTH); 743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mp = VG_(HT_lookup) ( MC_(mempool_list), (UWord)pool ); 746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mp == NULL) { 747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(record_illegal_mempool_error) ( tid, pool ); 748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 749f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (MP_DETAILED_SANITY_CHECKS) check_mempool_sane(mp); 750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(new_block)(tid, addr, szB, /*ignored*/0, mp->is_zeroed, 751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_AllocCustom, mp->chunks); 752f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (MP_DETAILED_SANITY_CHECKS) check_mempool_sane(mp); 753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(mempool_free)(Addr pool, Addr addr) 757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Mempool* mp; 759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Chunk* mc; 760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = VG_(get_running_tid)(); 761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mp = VG_(HT_lookup)(MC_(mempool_list), (UWord)pool); 763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mp == NULL) { 764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(record_illegal_mempool_error)(tid, pool); 765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 2) { 769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "mempool_free(0x%lx, 0x%lx)\n", pool, addr); 770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace) (tid, MEMPOOL_DEBUG_STACKTRACE_DEPTH); 771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 773f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (MP_DETAILED_SANITY_CHECKS) check_mempool_sane(mp); 774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc = VG_(HT_remove)(mp->chunks, (UWord)addr); 775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mc == NULL) { 776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(record_free_error)(tid, (Addr)addr); 777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 2) { 781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, 782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "mempool_free(0x%lx, 0x%lx) freed chunk of %ld bytes\n", 783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pool, addr, mc->szB + 0UL); 784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown die_and_free_mem ( tid, mc, mp->rzB ); 787f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (MP_DETAILED_SANITY_CHECKS) check_mempool_sane(mp); 788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(mempool_trim)(Addr pool, Addr addr, SizeT szB) 792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Mempool* mp; 794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Chunk* mc; 795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = VG_(get_running_tid)(); 796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown UInt n_shadows, i; 797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VgHashNode** chunks; 798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 2) { 800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "mempool_trim(0x%lx, 0x%lx, %ld)\n", 801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pool, addr, szB); 802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace) (tid, MEMPOOL_DEBUG_STACKTRACE_DEPTH); 803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mp = VG_(HT_lookup)(MC_(mempool_list), (UWord)pool); 806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mp == NULL) { 807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(record_illegal_mempool_error)(tid, pool); 808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown check_mempool_sane(mp); 812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown chunks = VG_(HT_to_array) ( mp->chunks, &n_shadows ); 813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (n_shadows == 0) { 814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(chunks == NULL); 815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(chunks != NULL); 819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown for (i = 0; i < n_shadows; ++i) { 820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown Addr lo, hi, min, max; 822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc = (MC_Chunk*) chunks[i]; 824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lo = mc->data; 826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hi = mc->szB == 0 ? mc->data : mc->data + mc->szB - 1; 827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EXTENT_CONTAINS(x) ((addr <= (x)) && ((x) < addr + szB)) 829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (EXTENT_CONTAINS(lo) && EXTENT_CONTAINS(hi)) { 831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The current chunk is entirely within the trim extent: keep 833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown it. */ 834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown continue; 836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else if ( (! EXTENT_CONTAINS(lo)) && 838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (! EXTENT_CONTAINS(hi)) ) { 839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The current chunk is entirely outside the trim extent: 841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown delete it. */ 842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(HT_remove)(mp->chunks, (UWord)mc->data) == NULL) { 844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(record_free_error)(tid, (Addr)mc->data); 845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(chunks); 846f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (MP_DETAILED_SANITY_CHECKS) check_mempool_sane(mp); 847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown die_and_free_mem ( tid, mc, mp->rzB ); 850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* The current chunk intersects the trim extent: remove, 854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown trim, and reinsert it. */ 855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(EXTENT_CONTAINS(lo) || 857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown EXTENT_CONTAINS(hi)); 858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(HT_remove)(mp->chunks, (UWord)mc->data) == NULL) { 859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(record_free_error)(tid, (Addr)mc->data); 860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(chunks); 861f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root if (MP_DETAILED_SANITY_CHECKS) check_mempool_sane(mp); 862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mc->data < addr) { 866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown min = mc->data; 867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lo = addr; 868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown min = addr; 870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown lo = mc->data; 871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mc->data + szB > addr + szB) { 874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown max = mc->data + szB; 875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hi = addr + szB; 876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } else { 877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown max = addr + szB; 878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown hi = mc->data + szB; 879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(min <= lo); 882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(lo < hi); 883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown tl_assert(hi <= max); 884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (min < lo && !EXTENT_CONTAINS(min)) { 886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(make_mem_noaccess)( min, lo - min); 887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (hi < max && !EXTENT_CONTAINS(max)) { 890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(make_mem_noaccess)( hi, max - hi ); 891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc->data = lo; 894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc->szB = (UInt) (hi - lo); 895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(HT_add_node)( mp->chunks, mc ); 896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef EXTENT_CONTAINS 899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown check_mempool_sane(mp); 902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(free)(chunks); 903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(move_mempool)(Addr poolA, Addr poolB) 906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Mempool* mp; 908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 2) { 910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "move_mempool(0x%lx, 0x%lx)\n", poolA, poolB); 911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace) 912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown (VG_(get_running_tid)(), MEMPOOL_DEBUG_STACKTRACE_DEPTH); 913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mp = VG_(HT_remove) ( MC_(mempool_list), (UWord)poolA ); 916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mp == NULL) { 918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = VG_(get_running_tid)(); 919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(record_illegal_mempool_error) ( tid, poolA ); 920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mp->pool = poolB; 924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(HT_add_node)( MC_(mempool_list), mp ); 925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(mempool_change)(Addr pool, Addr addrA, Addr addrB, SizeT szB) 928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Mempool* mp; 930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Chunk* mc; 931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ThreadId tid = VG_(get_running_tid)(); 932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) > 2) { 934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(message)(Vg_UserMsg, "mempool_change(0x%lx, 0x%lx, 0x%lx, %ld)\n", 935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown pool, addrA, addrB, szB); 936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(get_and_pp_StackTrace) (tid, MEMPOOL_DEBUG_STACKTRACE_DEPTH); 937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mp = VG_(HT_lookup)(MC_(mempool_list), (UWord)pool); 940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mp == NULL) { 941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(record_illegal_mempool_error)(tid, pool); 942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown check_mempool_sane(mp); 946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc = VG_(HT_remove)(mp->chunks, (UWord)addrA); 948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mc == NULL) { 949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_(record_free_error)(tid, (Addr)addrA); 950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc->data = addrB; 954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mc->szB = szB; 955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(HT_add_node)( mp->chunks, mc ); 956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown check_mempool_sane(mp); 958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool MC_(mempool_exists)(Addr pool) 961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Mempool* mp; 963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown mp = VG_(HT_lookup)(MC_(mempool_list), (UWord)pool); 965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (mp == NULL) { 966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return False; 967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return True; 969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Statistics printing ---*/ 974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/ 975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(print_malloc_stats) ( void ) 977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ 978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown MC_Chunk* mc; 979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown SizeT nblocks = 0; 980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ULong nbytes = 0; 981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_verbosity) == 0) 983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown if (VG_(clo_xml)) 985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown return; 986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown /* Count memory still in use. */ 988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(HT_ResetIter)(MC_(malloc_list)); 989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown while ( (mc = VG_(HT_Next)(MC_(malloc_list))) ) { 990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nblocks++; 991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nbytes += (ULong)mc->szB; 992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown } 993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown VG_(umsg)( 995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "HEAP SUMMARY:\n" 996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " in use at exit: %'llu bytes in %'lu blocks\n" 997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown " total heap usage: %'lu allocs, %'lu frees, %'llu bytes allocated\n" 998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown "\n", 999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown nbytes, nblocks, 1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cmalloc_n_mallocs, 1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown cmalloc_n_frees, cmalloc_bs_mallocd 1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown ); 1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} 1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown 1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end ---*/ 1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/ 1008