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