mc_malloc_wrappers.c revision 9bea4c13fca0e3bb4b719dcb3ed63d47d479294e
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
119bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root   Copyright (C) 2000-2010 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. */
739bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Rootstatic MC_Chunk* freed_list_start  = NULL;
749bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Rootstatic MC_Chunk* freed_list_end    = NULL;
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Put a shadow chunk on the freed blocks queue, possibly freeing up
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   some of the oldest blocks in the queue at the same time. */
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void add_to_freed_queue ( MC_Chunk* mc )
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const Bool show = False;
819bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root
829bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root   /* Put it at the end of the freed list */
839bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root   if (freed_list_end == NULL) {
849bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      tl_assert(freed_list_start == NULL);
859bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      freed_list_end    = freed_list_start = mc;
869bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      VG_(free_queue_volume) = (Long)mc->szB;
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
889bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      tl_assert(freed_list_end->next == NULL);
899bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      freed_list_end->next = mc;
909bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      freed_list_end       = mc;
919bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      VG_(free_queue_volume) += (Long)mc->szB;
929bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      if (show)
939bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root         VG_(printf)("mc_freelist: acquire: volume now %lld\n",
949bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root                     VG_(free_queue_volume));
958f943afc22a6a683b78271836c8ddc462b4824a9Evgeniy Stepanov   }
968f943afc22a6a683b78271836c8ddc462b4824a9Evgeniy Stepanov   VG_(free_queue_length)++;
979bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root   mc->next = NULL;
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
999bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root   /* Release enough of the oldest blocks to bring the free queue
1009bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      volume below vg_clo_freelist_vol. */
1019bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root
1029bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root   while (VG_(free_queue_volume) > MC_(clo_freelist_vol)) {
1039bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      MC_Chunk* mc1;
1049bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root
1059bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      tl_assert(freed_list_start != NULL);
1069bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      tl_assert(freed_list_end != NULL);
1079bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root
1089bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      mc1 = freed_list_start;
1099bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      VG_(free_queue_volume) -= (Long)mc1->szB;
1109bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      VG_(free_queue_length)--;
1119bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      if (show)
1129bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root         VG_(printf)("mc_freelist: discard: volume now %lld\n",
1139bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root                     VG_(free_queue_volume));
1149bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      tl_assert(VG_(free_queue_volume) >= 0);
1159bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root
1169bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      if (freed_list_start == freed_list_end) {
1179bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root         freed_list_start = freed_list_end = NULL;
1189bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      } else {
1199bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root         freed_list_start = mc1->next;
1209bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      }
1219bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      mc1->next = NULL; /* just paranoia */
1229bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root
1239bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      /* free MC_Chunk */
1249bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      if (MC_AllocCustom != mc1->allockind) {
1259bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root         VG_(cli_free) ( (void*)(mc1->data) );
1269bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      }
1279bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root      VG_(free) ( mc1 );
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1319bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny RootMC_Chunk* MC_(get_freed_list_head)(void)
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1339bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root   return freed_list_start;
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1369bea4c13fca0e3bb4b719dcb3ed63d47d479294eKenny Root/* Allocate its shadow chunk, put it on the appropriate list. */
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMC_Chunk* create_MC_Chunk ( ExeContext* ec, Addr p, SizeT szB,
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                            MC_AllocKind kind)
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Chunk* mc  = VG_(malloc)("mc.cMC.1 (a MC_Chunk)", sizeof(MC_Chunk));
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mc->data      = p;
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mc->szB       = szB;
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mc->allockind = kind;
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mc->where     = ec;
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Paranoia ... ensure the MC_Chunk is off-limits to the client, so
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the mc->data field isn't visible to the leak checker.  If memory
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      management is working correctly, any pointer returned by VG_(malloc)
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      should be noaccess as far as the client is concerned. */
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!MC_(check_mem_is_noaccess)( (Addr)mc, sizeof(MC_Chunk), NULL )) {
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(tool_panic)("create_MC_Chunk: shadow area is accessible");
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return mc;
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- client_malloc(), etc                                 ---*/
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// XXX: should make this a proper error (bug #79311).
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool complain_about_silly_args(SizeT sizeB, Char* fn)
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Cast to a signed type to catch any unexpectedly negative args.  We're
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // assuming here that the size asked for is not greater than 2^31 bytes
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // (for 32-bit platforms) or 2^63 bytes (for 64-bit platforms).
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((SSizeT)sizeB < 0) {
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!VG_(clo_xml))
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg, "Warning: silly arg (%ld) to %s()\n",
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      (SSizeT)sizeB, fn );
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Bool complain_about_silly_args2(SizeT n, SizeT sizeB)
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if ((SSizeT)n < 0 || (SSizeT)sizeB < 0) {
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!VG_(clo_xml))
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg,
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      "Warning: silly args (%ld,%ld) to calloc()\n",
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      (SSizeT)n, (SSizeT)sizeB);
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return True;
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return False;
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Allocate memory and note change in memory available */
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* MC_(new_block) ( ThreadId tid,
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       Addr p, SizeT szB, SizeT alignB,
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       Bool is_zeroed, MC_AllocKind kind, VgHashTable table)
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ExeContext* ec;
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cmalloc_n_mallocs ++;
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Allocate and zero if necessary
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (p) {
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(MC_AllocCustom == kind);
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(MC_AllocCustom != kind);
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p = (Addr)VG_(cli_malloc)( alignB, szB );
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!p) {
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return NULL;
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (is_zeroed) {
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(memset)((void*)p, 0, szB);
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (MC_(clo_malloc_fill) != -1) {
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(MC_(clo_malloc_fill) >= 0x00 && MC_(clo_malloc_fill) <= 0xFF);
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(memset)((void*)p, MC_(clo_malloc_fill), szB);
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Only update this stat if allocation succeeded.
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cmalloc_bs_mallocd += (ULong)szB;
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ec = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(ec);
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(HT_add_node)( table, create_MC_Chunk(ec, p, szB, kind) );
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (is_zeroed)
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(make_mem_defined)( p, szB );
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else {
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt ecu = VG_(get_ECU_from_ExeContext)(ec);
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(VG_(is_plausible_ECU)(ecu));
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(make_mem_undefined_w_otag)( p, szB, ecu | MC_OKIND_HEAP );
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (void*)p;
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* MC_(malloc) ( ThreadId tid, SizeT n )
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (complain_about_silly_args(n, "malloc")) {
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return MC_(new_block) ( tid, 0, n, VG_(clo_alignment),
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*is_zeroed*/False, MC_AllocMalloc, MC_(malloc_list));
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* MC_(__builtin_new) ( ThreadId tid, SizeT n )
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (complain_about_silly_args(n, "__builtin_new")) {
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return MC_(new_block) ( tid, 0, n, VG_(clo_alignment),
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*is_zeroed*/False, MC_AllocNew, MC_(malloc_list));
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* MC_(__builtin_vec_new) ( ThreadId tid, SizeT n )
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (complain_about_silly_args(n, "__builtin_vec_new")) {
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return MC_(new_block) ( tid, 0, n, VG_(clo_alignment),
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*is_zeroed*/False, MC_AllocNewVec, MC_(malloc_list));
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* MC_(memalign) ( ThreadId tid, SizeT alignB, SizeT n )
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (complain_about_silly_args(n, "memalign")) {
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return MC_(new_block) ( tid, 0, n, alignB,
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*is_zeroed*/False, MC_AllocMalloc, MC_(malloc_list));
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* MC_(calloc) ( ThreadId tid, SizeT nmemb, SizeT size1 )
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (complain_about_silly_args2(nmemb, size1)) {
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return MC_(new_block) ( tid, 0, nmemb*size1, VG_(clo_alignment),
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /*is_zeroed*/True, MC_AllocMalloc, MC_(malloc_list));
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid die_and_free_mem ( ThreadId tid, MC_Chunk* mc, SizeT rzB )
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (MC_(clo_free_fill) != -1) {
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(MC_(clo_free_fill) >= 0x00 && MC_(clo_free_fill) <= 0xFF);
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(memset)((void*)mc->data, MC_(clo_free_fill), mc->szB);
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note: make redzones noaccess again -- just in case user made them
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      accessible with a client request... */
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_(make_mem_noaccess)( mc->data-rzB, mc->szB + 2*rzB );
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Record where freed */
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mc->where = VG_(record_ExeContext) ( tid, 0/*first_ip_delta*/ );
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Put it out of harm's way for a while */
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   add_to_freed_queue ( mc );
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(handle_free) ( ThreadId tid, Addr p, UInt rzB, MC_AllocKind kind )
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Chunk* mc;
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cmalloc_n_frees++;
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mc = VG_(HT_remove) ( MC_(malloc_list), (UWord)p );
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mc == NULL) {
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(record_free_error) ( tid, p );
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* check if it is a matching free() / delete / delete [] */
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (kind != mc->allockind) {
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(p == mc->data);
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         MC_(record_freemismatch_error) ( tid, mc );
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      die_and_free_mem ( tid, mc, rzB );
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(free) ( ThreadId tid, void* p )
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_(handle_free)(
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tid, (Addr)p, MC_MALLOC_REDZONE_SZB, MC_AllocMalloc );
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(__builtin_delete) ( ThreadId tid, void* p )
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_(handle_free)(
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tid, (Addr)p, MC_MALLOC_REDZONE_SZB, MC_AllocNew);
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(__builtin_vec_delete) ( ThreadId tid, void* p )
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_(handle_free)(
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tid, (Addr)p, MC_MALLOC_REDZONE_SZB, MC_AllocNewVec);
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid* MC_(realloc) ( ThreadId tid, void* p_old, SizeT new_szB )
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Chunk* mc;
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   void*     p_new;
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SizeT     old_szB;
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cmalloc_n_frees ++;
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cmalloc_n_mallocs ++;
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cmalloc_bs_mallocd += (ULong)new_szB;
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (complain_about_silly_args(new_szB, "realloc"))
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Remove the old block */
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mc = VG_(HT_remove) ( MC_(malloc_list), (UWord)p_old );
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mc == NULL) {
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(record_free_error) ( tid, (Addr)p_old );
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We return to the program regardless. */
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return NULL;
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* check if its a matching free() / delete / delete [] */
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (MC_AllocMalloc != mc->allockind) {
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* can not realloc a range that was allocated with new or new [] */
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert((Addr)p_old == mc->data);
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(record_freemismatch_error) ( tid, mc );
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* but keep going anyway */
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   old_szB = mc->szB;
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* In all cases, even when the new size is smaller or unchanged, we
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      reallocate and copy the contents, and make the old block
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      inaccessible.  This is so as to guarantee to catch all cases of
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      accesses via the old address after reallocation, regardless of
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the change in size.  (Of course the ability to detect accesses
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      to the old block also depends on the size of the freed blocks
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      queue). */
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (new_szB <= old_szB) {
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* new size is smaller or the same */
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr a_new;
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Get new memory */
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_szB);
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (a_new) {
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ExeContext* ec;
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ec = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(ec);
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Retained part is copied, red zones set as normal */
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         MC_(make_mem_noaccess)( a_new-MC_MALLOC_REDZONE_SZB,
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 MC_MALLOC_REDZONE_SZB );
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         MC_(copy_address_range_state) ( (Addr)p_old, a_new, new_szB );
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         MC_(make_mem_noaccess)        ( a_new+new_szB, MC_MALLOC_REDZONE_SZB );
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Copy from old to new */
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(memcpy)((void*)a_new, p_old, new_szB);
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Possibly fill freed area with specified junk. */
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (MC_(clo_free_fill) != -1) {
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(MC_(clo_free_fill) >= 0x00 && MC_(clo_free_fill) <= 0xFF);
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(memset)((void*)p_old, MC_(clo_free_fill), old_szB);
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Free old memory */
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Nb: we have to allocate a new MC_Chunk for the new memory rather
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            than recycling the old one, so that any erroneous accesses to the
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            old memory are reported. */
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         die_and_free_mem ( tid, mc, MC_MALLOC_REDZONE_SZB );
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Allocate a new chunk.
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mc = create_MC_Chunk( ec, a_new, new_szB, MC_AllocMalloc );
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p_new = (void*)a_new;
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* new size is bigger */
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr a_new;
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      tl_assert(old_szB < new_szB);
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Get new memory */
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a_new = (Addr)VG_(cli_malloc)(VG_(clo_alignment), new_szB);
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (a_new) {
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         UInt        ecu;
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ExeContext* ec;
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ec = VG_(record_ExeContext)(tid, 0/*first_ip_delta*/);
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(ec);
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ecu = VG_(get_ECU_from_ExeContext)(ec);
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(VG_(is_plausible_ECU)(ecu));
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* First half kept and copied, second half new, red zones as normal */
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         MC_(make_mem_noaccess)( a_new-MC_MALLOC_REDZONE_SZB,
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 MC_MALLOC_REDZONE_SZB );
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         MC_(copy_address_range_state) ( (Addr)p_old, a_new, mc->szB );
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         MC_(make_mem_undefined_w_otag)( a_new+mc->szB, new_szB-mc->szB,
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                        ecu | MC_OKIND_HEAP );
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         MC_(make_mem_noaccess)        ( a_new+new_szB, MC_MALLOC_REDZONE_SZB );
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Possibly fill new area with specified junk */
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (MC_(clo_malloc_fill) != -1) {
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(MC_(clo_malloc_fill) >= 0x00
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      && MC_(clo_malloc_fill) <= 0xFF);
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(memset)((void*)(a_new+old_szB), MC_(clo_malloc_fill),
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                                new_szB-old_szB);
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Copy from old to new */
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(memcpy)((void*)a_new, p_old, mc->szB);
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Possibly fill freed area with specified junk. */
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (MC_(clo_free_fill) != -1) {
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            tl_assert(MC_(clo_free_fill) >= 0x00 && MC_(clo_free_fill) <= 0xFF);
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(memset)((void*)p_old, MC_(clo_free_fill), old_szB);
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Free old memory */
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Nb: we have to allocate a new MC_Chunk for the new memory rather
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            than recycling the old one, so that any erroneous accesses to the
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            old memory are reported. */
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         die_and_free_mem ( tid, mc, MC_MALLOC_REDZONE_SZB );
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Allocate a new chunk.
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mc = create_MC_Chunk( ec, a_new, new_szB, MC_AllocMalloc );
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p_new = (void*)a_new;
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Now insert the new mc (with a possibly new 'data' field) into
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // malloc_list.  If this realloc() did not increase the memory size, we
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // will have removed and then re-added mc unnecessarily.  But that's ok
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // because shrinking a block with realloc() is (presumably) much rarer
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // than growing it, and this way simplifies the growing case.
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(HT_add_node)( MC_(malloc_list), mc );
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return p_new;
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSizeT MC_(malloc_usable_size) ( ThreadId tid, void* p )
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Chunk* mc = VG_(HT_lookup) ( MC_(malloc_list), (UWord)p );
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // There may be slop, but pretend there isn't because only the asked-for
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // area will be marked as addressable.
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ( mc ? mc->szB : 0 );
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
491f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/*------------------------------------------------------------*/
492f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/*--- Memory pool stuff.                                   ---*/
493f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/*------------------------------------------------------------*/
494f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
495f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root/* Set to 1 for intensive sanity checking.  Is very expensive though
496f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   and should not be used in production scenarios.  See #255966. */
497f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root#define MP_DETAILED_SANITY_CHECKS 0
498f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
499f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Rootstatic void check_mempool_sane(MC_Mempool* mp); /*forward*/
500f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(create_mempool)(Addr pool, UInt rzB, Bool is_zeroed)
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Mempool* mp;
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 2) {
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, "create_mempool(0x%lx, %d, %d)\n",
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               pool, rzB, is_zeroed);
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(get_and_pp_StackTrace)
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (VG_(get_running_tid)(), MEMPOOL_DEBUG_STACKTRACE_DEPTH);
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mp = VG_(HT_lookup)(MC_(mempool_list), (UWord)pool);
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mp != NULL) {
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     VG_(tool_panic)("MC_(create_mempool): duplicate pool creation");
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mp = VG_(malloc)("mc.cm.1", sizeof(MC_Mempool));
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mp->pool       = pool;
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mp->rzB        = rzB;
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mp->is_zeroed  = is_zeroed;
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mp->chunks     = VG_(HT_construct)( "MC_(create_mempool)" );
523f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   check_mempool_sane(mp);
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Paranoia ... ensure this area is off-limits to the client, so
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      the mp->data field isn't visible to the leak checker.  If memory
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      management is working correctly, anything pointer returned by
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(malloc) should be noaccess as far as the client is
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      concerned. */
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!MC_(check_mem_is_noaccess)( (Addr)mp, sizeof(MC_Mempool), NULL )) {
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(tool_panic)("MC_(create_mempool): shadow area is accessible");
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(HT_add_node)( MC_(mempool_list), mp );
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(destroy_mempool)(Addr pool)
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Chunk*   mc;
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Mempool* mp;
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 2) {
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, "destroy_mempool(0x%lx)\n", pool);
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(get_and_pp_StackTrace)
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (VG_(get_running_tid)(), MEMPOOL_DEBUG_STACKTRACE_DEPTH);
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mp = VG_(HT_remove) ( MC_(mempool_list), (UWord)pool );
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mp == NULL) {
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ThreadId tid = VG_(get_running_tid)();
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(record_illegal_mempool_error) ( tid, pool );
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
555f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   check_mempool_sane(mp);
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Clean up the chunks, one by one
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(HT_ResetIter)(mp->chunks);
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while ( (mc = VG_(HT_Next)(mp->chunks)) ) {
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Note: make redzones noaccess again -- just in case user made them
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         accessible with a client request... */
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(make_mem_noaccess)(mc->data-mp->rzB, mc->szB + 2*mp->rzB );
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Destroy the chunk table
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(HT_destruct)(mp->chunks);
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(free)(mp);
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Int
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmp_compar(void* n1, void* n2)
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Chunk* mc1 = *(MC_Chunk**)n1;
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Chunk* mc2 = *(MC_Chunk**)n2;
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mc1->data < mc2->data) return -1;
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mc1->data > mc2->data) return  1;
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return 0;
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browncheck_mempool_sane(MC_Mempool* mp)
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt n_chunks, i, bad = 0;
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static UInt tick = 0;
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Chunk **chunks = (MC_Chunk**) VG_(HT_to_array)( mp->chunks, &n_chunks );
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!chunks)
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 1) {
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (tick++ >= 10000)
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       {
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 UInt total_pools = 0, total_chunks = 0;
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 MC_Mempool* mp2;
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(HT_ResetIter)(MC_(mempool_list));
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 while ( (mp2 = VG_(HT_Next)(MC_(mempool_list))) ) {
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   total_pools++;
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   VG_(HT_ResetIter)(mp2->chunks);
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   while (VG_(HT_Next)(mp2->chunks)) {
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	     total_chunks++;
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	   }
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 }
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg,
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      "Total mempools active: %d pools, %d chunks\n",
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		      total_pools, total_chunks);
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 tick = 0;
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       }
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(ssort)((void*)chunks, n_chunks, sizeof(VgHashNode*), mp_compar);
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Sanity check; assert that the blocks are now in order */
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_chunks-1; i++) {
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (chunks[i]->data > chunks[i+1]->data) {
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg,
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      "Mempool chunk %d / %d is out of order "
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      "wrt. its successor\n",
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      i+1, n_chunks);
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bad = 1;
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Sanity check -- make sure they don't overlap */
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_chunks-1; i++) {
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (chunks[i]->data + chunks[i]->szB > chunks[i+1]->data ) {
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg,
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      "Mempool chunk %d / %d overlaps with its successor\n",
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                      i+1, n_chunks);
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         bad = 1;
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bad) {
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(message)(Vg_UserMsg,
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                "Bad mempool (%d chunks), dumping chunks for inspection:\n",
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                n_chunks);
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (i = 0; i < n_chunks; ++i) {
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(message)(Vg_UserMsg,
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         "Mempool chunk %d / %d: %ld bytes "
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         "[%lx,%lx), allocated:\n",
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         i+1,
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         n_chunks,
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         chunks[i]->szB + 0UL,
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         chunks[i]->data,
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         chunks[i]->data + chunks[i]->szB);
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(pp_ExeContext)(chunks[i]->where);
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(free)(chunks);
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(mempool_alloc)(ThreadId tid, Addr pool, Addr addr, SizeT szB)
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Mempool* mp;
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 2) {
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, "mempool_alloc(0x%lx, 0x%lx, %ld)\n",
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               pool, addr, szB);
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(get_and_pp_StackTrace) (tid, MEMPOOL_DEBUG_STACKTRACE_DEPTH);
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mp = VG_(HT_lookup) ( MC_(mempool_list), (UWord)pool );
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mp == NULL) {
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(record_illegal_mempool_error) ( tid, pool );
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
670f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      if (MP_DETAILED_SANITY_CHECKS) check_mempool_sane(mp);
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(new_block)(tid, addr, szB, /*ignored*/0, mp->is_zeroed,
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     MC_AllocCustom, mp->chunks);
673f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root      if (MP_DETAILED_SANITY_CHECKS) check_mempool_sane(mp);
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(mempool_free)(Addr pool, Addr addr)
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Mempool*  mp;
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Chunk*    mc;
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadId     tid = VG_(get_running_tid)();
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mp = VG_(HT_lookup)(MC_(mempool_list), (UWord)pool);
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mp == NULL) {
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(record_illegal_mempool_error)(tid, pool);
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 2) {
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, "mempool_free(0x%lx, 0x%lx)\n", pool, addr);
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(get_and_pp_StackTrace) (tid, MEMPOOL_DEBUG_STACKTRACE_DEPTH);
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
694f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   if (MP_DETAILED_SANITY_CHECKS) check_mempool_sane(mp);
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mc = VG_(HT_remove)(mp->chunks, (UWord)addr);
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mc == NULL) {
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(record_free_error)(tid, (Addr)addr);
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 2) {
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   "mempool_free(0x%lx, 0x%lx) freed chunk of %ld bytes\n",
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   pool, addr, mc->szB + 0UL);
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   die_and_free_mem ( tid, mc, mp->rzB );
708f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root   if (MP_DETAILED_SANITY_CHECKS) check_mempool_sane(mp);
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(mempool_trim)(Addr pool, Addr addr, SizeT szB)
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Mempool*  mp;
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Chunk*    mc;
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadId     tid = VG_(get_running_tid)();
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt         n_shadows, i;
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VgHashNode** chunks;
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 2) {
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, "mempool_trim(0x%lx, 0x%lx, %ld)\n",
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               pool, addr, szB);
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(get_and_pp_StackTrace) (tid, MEMPOOL_DEBUG_STACKTRACE_DEPTH);
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mp = VG_(HT_lookup)(MC_(mempool_list), (UWord)pool);
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mp == NULL) {
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(record_illegal_mempool_error)(tid, pool);
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   check_mempool_sane(mp);
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   chunks = VG_(HT_to_array) ( mp->chunks, &n_shadows );
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (n_shadows == 0) {
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     tl_assert(chunks == NULL);
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     return;
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tl_assert(chunks != NULL);
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < n_shadows; ++i) {
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr lo, hi, min, max;
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mc = (MC_Chunk*) chunks[i];
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      lo = mc->data;
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      hi = mc->szB == 0 ? mc->data : mc->data + mc->szB - 1;
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define EXTENT_CONTAINS(x) ((addr <= (x)) && ((x) < addr + szB))
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (EXTENT_CONTAINS(lo) && EXTENT_CONTAINS(hi)) {
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* The current chunk is entirely within the trim extent: keep
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            it. */
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         continue;
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else if ( (! EXTENT_CONTAINS(lo)) &&
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (! EXTENT_CONTAINS(hi)) ) {
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* The current chunk is entirely outside the trim extent:
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            delete it. */
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (VG_(HT_remove)(mp->chunks, (UWord)mc->data) == NULL) {
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            MC_(record_free_error)(tid, (Addr)mc->data);
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(free)(chunks);
767f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            if (MP_DETAILED_SANITY_CHECKS) check_mempool_sane(mp);
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         die_and_free_mem ( tid, mc, mp->rzB );
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else {
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* The current chunk intersects the trim extent: remove,
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            trim, and reinsert it. */
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(EXTENT_CONTAINS(lo) ||
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   EXTENT_CONTAINS(hi));
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (VG_(HT_remove)(mp->chunks, (UWord)mc->data) == NULL) {
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            MC_(record_free_error)(tid, (Addr)mc->data);
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            VG_(free)(chunks);
782f673d1bf8bfb172f0eccbe4d3a908b3c65b55b33Kenny Root            if (MP_DETAILED_SANITY_CHECKS) check_mempool_sane(mp);
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            return;
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mc->data < addr) {
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           min = mc->data;
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           lo = addr;
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           min = addr;
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           lo = mc->data;
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mc->data + szB > addr + szB) {
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           max = mc->data + szB;
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           hi = addr + szB;
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         } else {
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           max = addr + szB;
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           hi = mc->data + szB;
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(min <= lo);
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(lo < hi);
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         tl_assert(hi <= max);
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (min < lo && !EXTENT_CONTAINS(min)) {
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           MC_(make_mem_noaccess)( min, lo - min);
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (hi < max && !EXTENT_CONTAINS(max)) {
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           MC_(make_mem_noaccess)( hi, max - hi );
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         }
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mc->data = lo;
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         mc->szB = (UInt) (hi - lo);
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         VG_(HT_add_node)( mp->chunks, mc );
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef EXTENT_CONTAINS
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   check_mempool_sane(mp);
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(free)(chunks);
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(move_mempool)(Addr poolA, Addr poolB)
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Mempool* mp;
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 2) {
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, "move_mempool(0x%lx, 0x%lx)\n", poolA, poolB);
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(get_and_pp_StackTrace)
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (VG_(get_running_tid)(), MEMPOOL_DEBUG_STACKTRACE_DEPTH);
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mp = VG_(HT_remove) ( MC_(mempool_list), (UWord)poolA );
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mp == NULL) {
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ThreadId tid = VG_(get_running_tid)();
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(record_illegal_mempool_error) ( tid, poolA );
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mp->pool = poolB;
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(HT_add_node)( MC_(mempool_list), mp );
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(mempool_change)(Addr pool, Addr addrA, Addr addrB, SizeT szB)
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Mempool*  mp;
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Chunk*    mc;
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadId     tid = VG_(get_running_tid)();
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) > 2) {
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, "mempool_change(0x%lx, 0x%lx, 0x%lx, %ld)\n",
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   pool, addrA, addrB, szB);
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(get_and_pp_StackTrace) (tid, MEMPOOL_DEBUG_STACKTRACE_DEPTH);
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mp = VG_(HT_lookup)(MC_(mempool_list), (UWord)pool);
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mp == NULL) {
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(record_illegal_mempool_error)(tid, pool);
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   check_mempool_sane(mp);
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mc = VG_(HT_remove)(mp->chunks, (UWord)addrA);
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mc == NULL) {
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MC_(record_free_error)(tid, (Addr)addrA);
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mc->data = addrB;
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mc->szB  = szB;
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(HT_add_node)( mp->chunks, mc );
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   check_mempool_sane(mp);
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBool MC_(mempool_exists)(Addr pool)
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Mempool*  mp;
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   mp = VG_(HT_lookup)(MC_(mempool_list), (UWord)pool);
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (mp == NULL) {
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       return False;
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return True;
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Statistics printing                                  ---*/
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*------------------------------------------------------------*/
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid MC_(print_malloc_stats) ( void )
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MC_Chunk* mc;
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SizeT     nblocks = 0;
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ULong     nbytes  = 0;
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_verbosity) == 0)
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (VG_(clo_xml))
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Count memory still in use. */
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(HT_ResetIter)(MC_(malloc_list));
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while ( (mc = VG_(HT_Next)(MC_(malloc_list))) ) {
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      nblocks++;
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      nbytes += (ULong)mc->szB;
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(umsg)(
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      "HEAP SUMMARY:\n"
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      "    in use at exit: %'llu bytes in %'lu blocks\n"
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      "  total heap usage: %'lu allocs, %'lu frees, %'llu bytes allocated\n"
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      "\n",
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      nbytes, nblocks,
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cmalloc_n_mallocs,
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cmalloc_n_frees, cmalloc_bs_mallocd
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   );
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                                          ---*/
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
929