blob: 35b66755f2b7c6fb9fba405d3c5ffb867ad3ba62 [file] [log] [blame]
njnc9539842002-10-02 13:26:35 +00001
njn25e49d8e72002-09-23 09:36:25 +00002/*--------------------------------------------------------------------*/
njnc9539842002-10-02 13:26:35 +00003/*--- MemCheck: Maintain bitmaps of memory, tracking the ---*/
4/*--- accessibility (A) and validity (V) status of each byte. ---*/
njn25cac76cb2002-09-23 11:21:57 +00005/*--- mc_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00006/*--------------------------------------------------------------------*/
7
8/*
nethercote137bc552003-11-14 17:47:54 +00009 This file is part of MemCheck, a heavyweight Valgrind tool for
njnc9539842002-10-02 13:26:35 +000010 detecting memory errors.
njn25e49d8e72002-09-23 09:36:25 +000011
njn53612422005-03-12 16:22:54 +000012 Copyright (C) 2000-2005 Julian Seward
njn25e49d8e72002-09-23 09:36:25 +000013 jseward@acm.org
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file COPYING.
31*/
32
sewardjc859fbf2005-04-22 21:10:28 +000033/* TODO 22 Apr 05
sewardj45d94cc2005-04-20 14:44:11 +000034
sewardjc859fbf2005-04-22 21:10:28 +000035 test whether it would be faster, for LOADV4, to check
36 only for 8-byte validity on the fast path
sewardj45d94cc2005-04-20 14:44:11 +000037*/
38
njn25cac76cb2002-09-23 11:21:57 +000039#include "mc_include.h"
40#include "memcheck.h" /* for client requests */
njn25e49d8e72002-09-23 09:36:25 +000041
sewardj45d94cc2005-04-20 14:44:11 +000042
sewardjc1a2cda2005-04-21 17:34:00 +000043#define EXPECTED_TAKEN(cond) __builtin_expect((cond),1)
44#define EXPECTED_NOT_TAKEN(cond) __builtin_expect((cond),0)
45
46/* Define to debug the mem audit system. Set to:
47 0 no debugging, fast cases are used
48 1 some sanity checking, fast cases are used
49 2 max sanity checking, only slow cases are used
50*/
sewardj23eb2fd2005-04-22 16:29:19 +000051#define VG_DEBUG_MEMORY 0
sewardjc1a2cda2005-04-21 17:34:00 +000052
53
sewardj45d94cc2005-04-20 14:44:11 +000054typedef enum {
55 MC_Ok = 5, MC_AddrErr = 6, MC_ValueErr = 7
56} MC_ReadResult;
njn25e49d8e72002-09-23 09:36:25 +000057
njn25e49d8e72002-09-23 09:36:25 +000058#define DEBUG(fmt, args...) //VG_(printf)(fmt, ## args)
59
njn25e49d8e72002-09-23 09:36:25 +000060
njn25e49d8e72002-09-23 09:36:25 +000061/*------------------------------------------------------------*/
sewardj45d94cc2005-04-20 14:44:11 +000062/*--- Basic A/V bitmap representation. ---*/
njn25e49d8e72002-09-23 09:36:25 +000063/*------------------------------------------------------------*/
64
sewardjc859fbf2005-04-22 21:10:28 +000065/* TODO: fix this comment */
66//zz /* All reads and writes are checked against a memory map, which
67//zz records the state of all memory in the process. The memory map is
68//zz organised like this:
69//zz
70//zz The top 16 bits of an address are used to index into a top-level
71//zz map table, containing 65536 entries. Each entry is a pointer to a
72//zz second-level map, which records the accesibililty and validity
73//zz permissions for the 65536 bytes indexed by the lower 16 bits of the
74//zz address. Each byte is represented by nine bits, one indicating
75//zz accessibility, the other eight validity. So each second-level map
76//zz contains 73728 bytes. This two-level arrangement conveniently
77//zz divides the 4G address space into 64k lumps, each size 64k bytes.
78//zz
79//zz All entries in the primary (top-level) map must point to a valid
80//zz secondary (second-level) map. Since most of the 4G of address
81//zz space will not be in use -- ie, not mapped at all -- there is a
82//zz distinguished secondary map, which indicates `not addressible and
83//zz not valid' writeable for all bytes. Entries in the primary map for
84//zz which the entire 64k is not in use at all point at this
85//zz distinguished map.
86//zz
87//zz There are actually 4 distinguished secondaries. These are used to
88//zz represent a memory range which is either not addressable (validity
89//zz doesn't matter), addressable+not valid, addressable+valid.
90//zz
91//zz [...] lots of stuff deleted due to out of date-ness
92//zz
93//zz As a final optimisation, the alignment and address checks for
94//zz 4-byte loads and stores are combined in a neat way. The primary
95//zz map is extended to have 262144 entries (2^18), rather than 2^16.
96//zz The top 3/4 of these entries are permanently set to the
97//zz distinguished secondary map. For a 4-byte load/store, the
98//zz top-level map is indexed not with (addr >> 16) but instead f(addr),
99//zz where
100//zz
101//zz f( XXXX XXXX XXXX XXXX ____ ____ ____ __YZ )
102//zz = ____ ____ ____ __YZ XXXX XXXX XXXX XXXX or
103//zz = ____ ____ ____ __ZY XXXX XXXX XXXX XXXX
104//zz
105//zz ie the lowest two bits are placed above the 16 high address bits.
106//zz If either of these two bits are nonzero, the address is misaligned;
107//zz this will select a secondary map from the upper 3/4 of the primary
108//zz map. Because this is always the distinguished secondary map, a
109//zz (bogus) address check failure will result. The failure handling
110//zz code can then figure out whether this is a genuine addr check
111//zz failure or whether it is a possibly-legitimate access at a
112//zz misaligned address.
113//zz */
114
sewardj45d94cc2005-04-20 14:44:11 +0000115/* --------------- Basic configuration --------------- */
sewardj95448072004-11-22 20:19:51 +0000116
sewardj23eb2fd2005-04-22 16:29:19 +0000117/* Only change this. N_PRIMARY_MAP *must* be a power of 2. */
sewardj45d94cc2005-04-20 14:44:11 +0000118#define N_PRIMARY_BITS 16
sewardj45d94cc2005-04-20 14:44:11 +0000119
sewardjc1a2cda2005-04-21 17:34:00 +0000120/* Do not change this. */
sewardj23eb2fd2005-04-22 16:29:19 +0000121#define N_PRIMARY_MAP (1 << N_PRIMARY_BITS)
sewardjc1a2cda2005-04-21 17:34:00 +0000122
123/* Do not change this. */
sewardj23eb2fd2005-04-22 16:29:19 +0000124#define MAX_PRIMARY_ADDRESS (Addr)((((Addr)65536) * N_PRIMARY_MAP)-1)
125
126
127/* --------------- Stats maps --------------- */
128
129static Int n_secmaps_issued = 0;
130static ULong n_auxmap_searches = 0;
131static ULong n_auxmap_cmps = 0;
132static Int n_sanity_cheap = 0;
133static Int n_sanity_expensive = 0;
sewardj45d94cc2005-04-20 14:44:11 +0000134
135
136/* --------------- Secondary maps --------------- */
njn25e49d8e72002-09-23 09:36:25 +0000137
138typedef
139 struct {
sewardj45d94cc2005-04-20 14:44:11 +0000140 UChar abits[8192];
141 UChar vbyte[65536];
njn25e49d8e72002-09-23 09:36:25 +0000142 }
143 SecMap;
144
sewardj45d94cc2005-04-20 14:44:11 +0000145/* 3 distinguished secondary maps, one for no-access, one for
146 accessible but undefined, and one for accessible and defined.
147 Distinguished secondaries may never be modified.
148*/
149#define SM_DIST_NOACCESS 0
150#define SM_DIST_ACCESS_UNDEFINED 1
151#define SM_DIST_ACCESS_DEFINED 2
njnb8dca862005-03-14 02:42:44 +0000152
sewardj45d94cc2005-04-20 14:44:11 +0000153static SecMap sm_distinguished[3];
njnb8dca862005-03-14 02:42:44 +0000154
sewardj45d94cc2005-04-20 14:44:11 +0000155static inline Bool is_distinguished_sm ( SecMap* sm ) {
156 return sm >= &sm_distinguished[0] && sm <= &sm_distinguished[2];
157}
njnb8dca862005-03-14 02:42:44 +0000158
sewardj45d94cc2005-04-20 14:44:11 +0000159/* dist_sm points to one of our three distinguished secondaries. Make
160 a copy of it so that we can write to it.
161*/
162static SecMap* copy_for_writing ( SecMap* dist_sm )
163{
164 SecMap* new_sm;
165 tl_assert(dist_sm == &sm_distinguished[0]
166 || dist_sm == &sm_distinguished[1]
167 || dist_sm == &sm_distinguished[2]);
njnb8dca862005-03-14 02:42:44 +0000168
sewardj45d94cc2005-04-20 14:44:11 +0000169 new_sm = VG_(shadow_alloc)(sizeof(SecMap));
170 VG_(memcpy)(new_sm, dist_sm, sizeof(SecMap));
sewardj23eb2fd2005-04-22 16:29:19 +0000171 n_secmaps_issued++;
sewardj45d94cc2005-04-20 14:44:11 +0000172 return new_sm;
173}
njnb8dca862005-03-14 02:42:44 +0000174
sewardj45d94cc2005-04-20 14:44:11 +0000175
176/* --------------- Primary maps --------------- */
177
178/* The main primary map. This covers some initial part of the address
sewardj23eb2fd2005-04-22 16:29:19 +0000179 space, addresses 0 .. (N_PRIMARY_MAP << 16)-1. The rest of it is
sewardj45d94cc2005-04-20 14:44:11 +0000180 handled using the auxiliary primary map.
181*/
sewardj23eb2fd2005-04-22 16:29:19 +0000182static SecMap* primary_map[N_PRIMARY_MAP];
sewardj45d94cc2005-04-20 14:44:11 +0000183
184
185/* An entry in the auxiliary primary map. base must be a 64k-aligned
186 value, and sm points at the relevant secondary map. As with the
187 main primary map, the secondary may be either a real secondary, or
188 one of the three distinguished secondaries.
189*/
190typedef
191 struct {
sewardj23eb2fd2005-04-22 16:29:19 +0000192 Addr base;
sewardj45d94cc2005-04-20 14:44:11 +0000193 SecMap* sm;
194 }
195 AuxMapEnt;
196
197/* An expanding array of AuxMapEnts. */
198#define N_AUXMAPS 500 /* HACK */
199static AuxMapEnt hacky_auxmaps[N_AUXMAPS];
200static Int auxmap_size = N_AUXMAPS;
201static Int auxmap_used = 0;
202static AuxMapEnt* auxmap = &hacky_auxmaps[0];
203
sewardj45d94cc2005-04-20 14:44:11 +0000204
205/* Find an entry in the auxiliary map. If an entry is found, move it
206 one step closer to the front of the array, then return its address.
sewardj05fe85e2005-04-27 22:46:36 +0000207 If an entry is not found, return NULL. Note carefully that
sewardj45d94cc2005-04-20 14:44:11 +0000208 because a each call potentially rearranges the entries, each call
209 to this function invalidates ALL AuxMapEnt*s previously obtained by
210 calling this fn.
211*/
sewardj05fe85e2005-04-27 22:46:36 +0000212static AuxMapEnt* maybe_find_in_auxmap ( Addr a )
sewardj45d94cc2005-04-20 14:44:11 +0000213{
214 UWord i;
215 tl_assert(a > MAX_PRIMARY_ADDRESS);
216
217 a &= ~(Addr)0xFFFF;
218
219 /* Search .. */
220 n_auxmap_searches++;
221 for (i = 0; i < auxmap_used; i++) {
222 if (auxmap[i].base == a)
223 break;
224 }
225 n_auxmap_cmps += (ULong)(i+1);
226
227 if (i < auxmap_used) {
228 /* Found it. Nudge it a bit closer to the front. */
229 if (i > 0) {
230 AuxMapEnt tmp = auxmap[i-1];
231 auxmap[i-1] = auxmap[i];
232 auxmap[i] = tmp;
233 i--;
234 }
235 return &auxmap[i];
236 }
237
sewardj05fe85e2005-04-27 22:46:36 +0000238 return NULL;
239}
240
241
242/* Find an entry in the auxiliary map. If an entry is found, move it
243 one step closer to the front of the array, then return its address.
244 If an entry is not found, allocate one. Note carefully that
245 because a each call potentially rearranges the entries, each call
246 to this function invalidates ALL AuxMapEnt*s previously obtained by
247 calling this fn.
248*/
249static AuxMapEnt* find_or_alloc_in_auxmap ( Addr a )
250{
251 AuxMapEnt* am = maybe_find_in_auxmap(a);
252 if (am)
253 return am;
254
sewardj45d94cc2005-04-20 14:44:11 +0000255 /* We didn't find it. Hmm. This is a new piece of address space.
256 We'll need to allocate a new AuxMap entry for it. */
257 if (auxmap_used >= auxmap_size) {
258 tl_assert(auxmap_used == auxmap_size);
259 /* Out of auxmap entries. */
260 tl_assert2(0, "failed to expand the auxmap table");
261 }
262
263 tl_assert(auxmap_used < auxmap_size);
264
265 auxmap[auxmap_used].base = a & ~(Addr)0xFFFF;
266 auxmap[auxmap_used].sm = &sm_distinguished[SM_DIST_NOACCESS];
267
268 if (0)
269 VG_(printf)("new auxmap, base = 0x%llx\n",
270 (ULong)auxmap[auxmap_used].base );
271
272 auxmap_used++;
273 return &auxmap[auxmap_used-1];
274}
275
276
277/* --------------- SecMap fundamentals --------------- */
278
279/* Produce the secmap for 'a', either from the primary map or by
280 ensuring there is an entry for it in the aux primary map. The
281 secmap may be a distinguished one as the caller will only want to
282 be able to read it.
283*/
284static SecMap* get_secmap_readable ( Addr a )
285{
286 if (a <= MAX_PRIMARY_ADDRESS) {
287 UWord pm_off = a >> 16;
288 return primary_map[ pm_off ];
289 } else {
290 AuxMapEnt* am = find_or_alloc_in_auxmap(a);
291 return am->sm;
292 }
293}
294
sewardj05fe85e2005-04-27 22:46:36 +0000295/* If 'a' has a SecMap, produce it. Else produce NULL. But don't
296 allocate one if one doesn't already exist. This is used by the
297 leak checker.
298*/
299static SecMap* maybe_get_secmap_for ( Addr a )
300{
301 if (a <= MAX_PRIMARY_ADDRESS) {
302 UWord pm_off = a >> 16;
303 return primary_map[ pm_off ];
304 } else {
305 AuxMapEnt* am = maybe_find_in_auxmap(a);
306 return am ? am->sm : NULL;
307 }
308}
309
310
311
sewardj45d94cc2005-04-20 14:44:11 +0000312/* Produce the secmap for 'a', either from the primary map or by
313 ensuring there is an entry for it in the aux primary map. The
314 secmap may not be a distinguished one, since the caller will want
315 to be able to write it. If it is a distinguished secondary, make a
316 writable copy of it, install it, and return the copy instead. (COW
317 semantics).
318*/
319static SecMap* get_secmap_writable ( Addr a )
320{
321 if (a <= MAX_PRIMARY_ADDRESS) {
322 UWord pm_off = a >> 16;
323 if (is_distinguished_sm(primary_map[ pm_off ]))
324 primary_map[pm_off] = copy_for_writing(primary_map[pm_off]);
325 return primary_map[pm_off];
326 } else {
327 AuxMapEnt* am = find_or_alloc_in_auxmap(a);
328 if (is_distinguished_sm(am->sm))
329 am->sm = copy_for_writing(am->sm);
330 return am->sm;
331 }
332}
333
334
335/* --------------- Endianness helpers --------------- */
336
337/* Returns the offset in memory of the byteno-th most significant byte
338 in a wordszB-sized word, given the specified endianness. */
339static inline UWord byte_offset_w ( UWord wordszB, Bool bigendian,
340 UWord byteno ) {
341 return bigendian ? (wordszB-1-byteno) : byteno;
342}
343
344
345/* --------------- Fundamental functions --------------- */
346
347static
348void get_abit_and_vbyte ( /*OUT*/UWord* abit,
349 /*OUT*/UWord* vbyte,
350 Addr a )
351{
352 SecMap* sm = get_secmap_readable(a);
353 *vbyte = 0xFF & sm->vbyte[a & 0xFFFF];
354 *abit = read_bit_array(sm->abits, a & 0xFFFF);
355}
356
357static
358UWord get_abit ( Addr a )
359{
360 SecMap* sm = get_secmap_readable(a);
361 return read_bit_array(sm->abits, a & 0xFFFF);
362}
363
364static
365void set_abit_and_vbyte ( Addr a, UWord abit, UWord vbyte )
366{
367 SecMap* sm = get_secmap_writable(a);
368 sm->vbyte[a & 0xFFFF] = 0xFF & vbyte;
369 write_bit_array(sm->abits, a & 0xFFFF, abit);
370}
371
372static
373void set_vbyte ( Addr a, UWord vbyte )
374{
375 SecMap* sm = get_secmap_writable(a);
376 sm->vbyte[a & 0xFFFF] = 0xFF & vbyte;
377}
378
379
380/* --------------- Load/store slow cases. --------------- */
381
382static
383ULong mc_LOADVn_slow ( Addr a, SizeT szB, Bool bigendian )
384{
385 /* Make up a result V word, which contains the loaded data for
sewardjf3d57dd2005-04-22 20:23:27 +0000386 valid addresses and Defined for invalid addresses. Iterate over
387 the bytes in the word, from the most significant down to the
388 least. */
sewardj45d94cc2005-04-20 14:44:11 +0000389 ULong vw = VGM_WORD64_INVALID;
390 SizeT i = szB-1;
391 SizeT n_addrs_bad = 0;
392 Addr ai;
393 Bool aok;
394 UWord abit, vbyte;
395
sewardjc1a2cda2005-04-21 17:34:00 +0000396 PROF_EVENT(30, "mc_LOADVn_slow");
sewardj45d94cc2005-04-20 14:44:11 +0000397 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
398
399 while (True) {
sewardjc1a2cda2005-04-21 17:34:00 +0000400 PROF_EVENT(31, "mc_LOADVn_slow(loop)");
sewardj45d94cc2005-04-20 14:44:11 +0000401 ai = a+byte_offset_w(szB,bigendian,i);
402 get_abit_and_vbyte(&abit, &vbyte, ai);
403 aok = abit == VGM_BIT_VALID;
404 if (!aok)
405 n_addrs_bad++;
406 vw <<= 8;
sewardjf3d57dd2005-04-22 20:23:27 +0000407 vw |= 0xFF & (aok ? vbyte : VGM_BYTE_VALID);
sewardj45d94cc2005-04-20 14:44:11 +0000408 if (i == 0) break;
409 i--;
410 }
411
412 if (n_addrs_bad > 0)
413 MAC_(record_address_error)( VG_(get_running_tid)(), a, szB, False );
414
sewardj45d94cc2005-04-20 14:44:11 +0000415 return vw;
416}
417
418
419static
420void mc_STOREVn_slow ( Addr a, SizeT szB, UWord vbytes, Bool bigendian )
421{
422 SizeT i;
423 SizeT n_addrs_bad = 0;
424 UWord abit;
425 Bool aok;
426 Addr ai;
427
sewardjc1a2cda2005-04-21 17:34:00 +0000428 PROF_EVENT(35, "mc_STOREVn_slow");
sewardj45d94cc2005-04-20 14:44:11 +0000429 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
430
431 /* Dump vbytes in memory, iterating from least to most significant
432 byte. At the same time establish addressibility of the
433 location. */
434 for (i = 0; i < szB; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +0000435 PROF_EVENT(36, "mc_STOREVn_slow(loop)");
sewardj45d94cc2005-04-20 14:44:11 +0000436 ai = a+byte_offset_w(szB,bigendian,i);
437 abit = get_abit(ai);
438 aok = abit == VGM_BIT_VALID;
439 if (!aok)
440 n_addrs_bad++;
441 set_vbyte(ai, vbytes & 0xFF );
442 vbytes >>= 8;
443 }
444
445 /* If an address error has happened, report it. */
446 if (n_addrs_bad > 0)
447 MAC_(record_address_error)( VG_(get_running_tid)(), a, szB, True );
448}
449
450
sewardj45d94cc2005-04-20 14:44:11 +0000451//zz /* Reading/writing of the bitmaps, for aligned word-sized accesses. */
452//zz
453//zz static __inline__ UChar get_abits4_ALIGNED ( Addr a )
454//zz {
455//zz SecMap* sm;
456//zz UInt sm_off;
457//zz UChar abits8;
458//zz PROF_EVENT(24);
459//zz # ifdef VG_DEBUG_MEMORY
460//zz tl_assert(VG_IS_4_ALIGNED(a));
461//zz # endif
462//zz sm = primary_map[PM_IDX(a)];
463//zz sm_off = SM_OFF(a);
464//zz abits8 = sm->abits[sm_off >> 3];
465//zz abits8 >>= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
466//zz abits8 &= 0x0F;
467//zz return abits8;
468//zz }
469//zz
470//zz static UInt __inline__ get_vbytes4_ALIGNED ( Addr a )
471//zz {
472//zz SecMap* sm = primary_map[PM_IDX(a)];
473//zz UInt sm_off = SM_OFF(a);
474//zz PROF_EVENT(25);
475//zz # ifdef VG_DEBUG_MEMORY
476//zz tl_assert(VG_IS_4_ALIGNED(a));
477//zz # endif
478//zz return ((UInt*)(sm->vbyte))[sm_off >> 2];
479//zz }
480//zz
481//zz
482//zz static void __inline__ set_vbytes4_ALIGNED ( Addr a, UInt vbytes )
483//zz {
484//zz SecMap* sm;
485//zz UInt sm_off;
486//zz ENSURE_MAPPABLE(a, "set_vbytes4_ALIGNED");
487//zz sm = primary_map[PM_IDX(a)];
488//zz sm_off = SM_OFF(a);
489//zz PROF_EVENT(23);
490//zz # ifdef VG_DEBUG_MEMORY
491//zz tl_assert(VG_IS_4_ALIGNED(a));
492//zz # endif
493//zz ((UInt*)(sm->vbyte))[sm_off >> 2] = vbytes;
494//zz }
sewardjee070842003-07-05 17:53:55 +0000495
496
njn25e49d8e72002-09-23 09:36:25 +0000497/*------------------------------------------------------------*/
498/*--- Setting permissions over address ranges. ---*/
499/*------------------------------------------------------------*/
500
sewardj23eb2fd2005-04-22 16:29:19 +0000501/* Given address 'a', find the place where the pointer to a's
502 secondary map lives. If a falls into the primary map, the returned
503 value points to one of the entries in primary_map[]. Otherwise,
504 the auxiliary primary map is searched for 'a', or an entry is
505 created for it; either way, the returned value points to the
506 relevant AuxMapEnt's .sm field.
507
508 The point of this is to enable set_address_range_perms to assign
509 secondary maps in a uniform way, without worrying about whether a
510 given secondary map is pointed to from the main or auxiliary
511 primary map.
512*/
513
514static SecMap** find_secmap_binder_for_addr ( Addr aA )
515{
516 if (aA > MAX_PRIMARY_ADDRESS) {
517 AuxMapEnt* am = find_or_alloc_in_auxmap(aA);
518 return &am->sm;
519 } else {
520 UWord a = (UWord)aA;
521 UWord sec_no = (UWord)(a >> 16);
522# if VG_DEBUG_MEMORY >= 1
523 tl_assert(sec_no < N_PRIMARY_MAP);
524# endif
525 return &primary_map[sec_no];
526 }
527}
528
529
530static void set_address_range_perms ( Addr aA, SizeT len,
sewardj45d94cc2005-04-20 14:44:11 +0000531 UWord example_a_bit,
532 UWord example_v_bit )
njn25e49d8e72002-09-23 09:36:25 +0000533{
sewardj23eb2fd2005-04-22 16:29:19 +0000534 PROF_EVENT(150, "set_address_range_perms");
535
536 /* Check the permissions make sense. */
537 tl_assert(example_a_bit == VGM_BIT_VALID
538 || example_a_bit == VGM_BIT_INVALID);
539 tl_assert(example_v_bit == VGM_BIT_VALID
540 || example_v_bit == VGM_BIT_INVALID);
541 if (example_a_bit == VGM_BIT_INVALID)
542 tl_assert(example_v_bit == VGM_BIT_INVALID);
543
544 if (len == 0)
545 return;
546
547 if (VG_(clo_verbosity) > 0) {
548 if (len > 100 * 1000 * 1000) {
549 VG_(message)(Vg_UserMsg,
550 "Warning: set address range perms: "
551 "large range %u, a %d, v %d",
552 len, example_a_bit, example_v_bit );
553 }
554 }
555
556 UWord a = (UWord)aA;
557
558# if VG_DEBUG_MEMORY >= 2
559
560 /*------------------ debug-only case ------------------ */
sewardj45d94cc2005-04-20 14:44:11 +0000561 SizeT i;
njn25e49d8e72002-09-23 09:36:25 +0000562
sewardj23eb2fd2005-04-22 16:29:19 +0000563 UWord example_vbyte = BIT_TO_BYTE(example_v_bit);
sewardj45d94cc2005-04-20 14:44:11 +0000564
565 tl_assert(sizeof(SizeT) == sizeof(Addr));
566
567 if (0 && len >= 4096)
568 VG_(printf)("s_a_r_p(0x%llx, %d, %d,%d)\n",
569 (ULong)a, len, example_a_bit, example_v_bit);
njn25e49d8e72002-09-23 09:36:25 +0000570
571 if (len == 0)
572 return;
573
sewardj45d94cc2005-04-20 14:44:11 +0000574 for (i = 0; i < len; i++) {
575 set_abit_and_vbyte(a+i, example_a_bit, example_vbyte);
njn25e49d8e72002-09-23 09:36:25 +0000576 }
njn25e49d8e72002-09-23 09:36:25 +0000577
sewardj23eb2fd2005-04-22 16:29:19 +0000578# else
579
580 /*------------------ standard handling ------------------ */
581 UWord vbits8, abits8, vbits32, v_off, a_off;
582 SecMap* sm;
583 SecMap** binder;
584 SecMap* example_dsm;
585
586 /* Decide on the distinguished secondary that we might want
587 to use (part of the space-compression scheme). */
588 if (example_a_bit == VGM_BIT_INVALID) {
589 example_dsm = &sm_distinguished[SM_DIST_NOACCESS];
590 } else {
591 if (example_v_bit == VGM_BIT_VALID) {
592 example_dsm = &sm_distinguished[SM_DIST_ACCESS_DEFINED];
593 } else {
594 example_dsm = &sm_distinguished[SM_DIST_ACCESS_UNDEFINED];
595 }
596 }
597
598 /* Make various wider versions of the A/V values to use. */
599 vbits8 = BIT_TO_BYTE(example_v_bit);
600 abits8 = BIT_TO_BYTE(example_a_bit);
601 vbits32 = (vbits8 << 24) | (vbits8 << 16) | (vbits8 << 8) | vbits8;
602
603 /* Slowly do parts preceding 8-byte alignment. */
604 while (True) {
605 if (len == 0) break;
606 PROF_EVENT(151, "set_address_range_perms-loop1-pre");
607 if (VG_IS_8_ALIGNED(a)) break;
608 set_abit_and_vbyte( a, example_a_bit, vbits8 );
609 a++;
610 len--;
611 }
612
613 if (len == 0)
614 return;
615
616 tl_assert(VG_IS_8_ALIGNED(a) && len > 0);
617
618 /* Now go in steps of 8 bytes. */
619 binder = find_secmap_binder_for_addr(a);
620
621 while (True) {
622
623 if (len < 8) break;
624
625 PROF_EVENT(152, "set_address_range_perms-loop8");
626
627 if ((a & SECONDARY_MASK) == 0) {
628 /* we just traversed a primary map boundary, so update the
629 binder. */
630 binder = find_secmap_binder_for_addr(a);
631 PROF_EVENT(153, "set_address_range_perms-update-binder");
632
633 /* Space-optimisation. If we are setting the entire
634 secondary map, just point this entry at one of our
635 distinguished secondaries. However, only do that if it
636 already points at a distinguished secondary, since doing
637 otherwise would leak the existing secondary. We could do
638 better and free up any pre-existing non-distinguished
639 secondary at this point, since we are guaranteed that each
640 non-dist secondary only has one pointer to it, and we have
641 that pointer right here. */
642 if (len >= SECONDARY_SIZE && is_distinguished_sm(*binder)) {
643 PROF_EVENT(154, "set_address_range_perms-entire-secmap");
644 *binder = example_dsm;
645 len -= SECONDARY_SIZE;
646 a += SECONDARY_SIZE;
647 continue;
648 }
649 }
650
651 /* If the primary is already pointing to a distinguished map
652 with the same properties as we're trying to set, then leave
653 it that way. */
654 if (*binder == example_dsm) {
655 a += 8;
656 len -= 8;
657 continue;
658 }
659
660 /* Make sure it's OK to write the secondary. */
661 if (is_distinguished_sm(*binder))
662 *binder = copy_for_writing(*binder);
663
664 sm = *binder;
665 v_off = a & 0xFFFF;
666 a_off = v_off >> 3;
667 sm->abits[a_off] = (UChar)abits8;
668 ((UInt*)(sm->vbyte))[(v_off >> 2) + 0] = (UInt)vbits32;
669 ((UInt*)(sm->vbyte))[(v_off >> 2) + 1] = (UInt)vbits32;
670
671 a += 8;
672 len -= 8;
673 }
674
675 if (len == 0)
676 return;
677
678 tl_assert(VG_IS_8_ALIGNED(a) && len > 0 && len < 8);
679
680 /* Finish the upper fragment. */
681 while (True) {
682 if (len == 0) break;
683 PROF_EVENT(155, "set_address_range_perms-loop1-post");
684 set_abit_and_vbyte ( a, example_a_bit, vbits8 );
685 a++;
686 len--;
687 }
688
689# endif
690}
sewardj45d94cc2005-04-20 14:44:11 +0000691
sewardjc859fbf2005-04-22 21:10:28 +0000692
693/* --- Set permissions for arbitrary address ranges --- */
njn25e49d8e72002-09-23 09:36:25 +0000694
nethercote8b76fe52004-11-08 19:20:09 +0000695static void mc_make_noaccess ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000696{
sewardjc1a2cda2005-04-21 17:34:00 +0000697 PROF_EVENT(40, "mc_make_noaccess");
nethercote8b76fe52004-11-08 19:20:09 +0000698 DEBUG("mc_make_noaccess(%p, %llu)\n", a, (ULong)len);
njn25e49d8e72002-09-23 09:36:25 +0000699 set_address_range_perms ( a, len, VGM_BIT_INVALID, VGM_BIT_INVALID );
700}
701
nethercote8b76fe52004-11-08 19:20:09 +0000702static void mc_make_writable ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000703{
sewardjc1a2cda2005-04-21 17:34:00 +0000704 PROF_EVENT(41, "mc_make_writable");
nethercote8b76fe52004-11-08 19:20:09 +0000705 DEBUG("mc_make_writable(%p, %llu)\n", a, (ULong)len);
njn25e49d8e72002-09-23 09:36:25 +0000706 set_address_range_perms ( a, len, VGM_BIT_VALID, VGM_BIT_INVALID );
707}
708
nethercote8b76fe52004-11-08 19:20:09 +0000709static void mc_make_readable ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000710{
sewardjc1a2cda2005-04-21 17:34:00 +0000711 PROF_EVENT(42, "mc_make_readable");
nethercote8b76fe52004-11-08 19:20:09 +0000712 DEBUG("mc_make_readable(%p, %llu)\n", a, (ULong)len);
njn25e49d8e72002-09-23 09:36:25 +0000713 set_address_range_perms ( a, len, VGM_BIT_VALID, VGM_BIT_VALID );
714}
715
njn9b007f62003-04-07 14:40:25 +0000716
sewardjc859fbf2005-04-22 21:10:28 +0000717/* --- Block-copy permissions (needed for implementing realloc()). --- */
718
719static void mc_copy_address_range_state ( Addr src, Addr dst, SizeT len )
720{
721 SizeT i;
722 UWord abit, vbyte;
723
724 DEBUG("mc_copy_address_range_state\n");
725
726 PROF_EVENT(50, "mc_copy_address_range_state");
727 for (i = 0; i < len; i++) {
728 PROF_EVENT(51, "mc_copy_address_range_state(loop)");
729 get_abit_and_vbyte( &abit, &vbyte, src+i );
730 set_abit_and_vbyte( dst+i, abit, vbyte );
731 }
732}
733
734
735/* --- Fast case permission setters, for dealing with stacks. --- */
736
njn9b007f62003-04-07 14:40:25 +0000737static __inline__
sewardj5d28efc2005-04-21 22:16:29 +0000738void make_aligned_word32_writable ( Addr aA )
njn9b007f62003-04-07 14:40:25 +0000739{
sewardj5d28efc2005-04-21 22:16:29 +0000740 PROF_EVENT(300, "make_aligned_word32_writable");
741
742# if VG_DEBUG_MEMORY >= 2
743 mc_make_writable(aA, 4);
744# else
745
746 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
sewardj23eb2fd2005-04-22 16:29:19 +0000747 PROF_EVENT(301, "make_aligned_word32_writable-slow1");
sewardj5d28efc2005-04-21 22:16:29 +0000748 mc_make_writable(aA, 4);
749 return;
750 }
751
752 UWord a = (UWord)aA;
753 UWord sec_no = (UWord)(a >> 16);
754# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +0000755 tl_assert(sec_no < N_PRIMARY_MAP);
sewardj5d28efc2005-04-21 22:16:29 +0000756# endif
757
758 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
759 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
760
761 SecMap* sm = primary_map[sec_no];
762 UWord v_off = a & 0xFFFF;
763 UWord a_off = v_off >> 3;
764
765 /* Paint the new area as uninitialised. */
766 ((UInt*)(sm->vbyte))[v_off >> 2] = VGM_WORD32_INVALID;
767
768 UWord mask = 0x0F;
769 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
770 /* mask now contains 1s where we wish to make address bits valid
771 (0s). */
772 sm->abits[a_off] &= ~mask;
773# endif
njn9b007f62003-04-07 14:40:25 +0000774}
775
sewardj5d28efc2005-04-21 22:16:29 +0000776
777static __inline__
778void make_aligned_word32_noaccess ( Addr aA )
779{
780 PROF_EVENT(310, "make_aligned_word32_noaccess");
781
782# if VG_DEBUG_MEMORY >= 2
783 mc_make_noaccess(aA, 4);
784# else
785
786 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
787 PROF_EVENT(311, "make_aligned_word32_noaccess-slow1");
788 mc_make_noaccess(aA, 4);
789 return;
790 }
791
792 UWord a = (UWord)aA;
793 UWord sec_no = (UWord)(a >> 16);
794# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +0000795 tl_assert(sec_no < N_PRIMARY_MAP);
sewardj5d28efc2005-04-21 22:16:29 +0000796# endif
797
798 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
799 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
800
801 SecMap* sm = primary_map[sec_no];
802 UWord v_off = a & 0xFFFF;
803 UWord a_off = v_off >> 3;
804
805 /* Paint the abandoned data as uninitialised. Probably not
806 necessary, but still .. */
807 ((UInt*)(sm->vbyte))[v_off >> 2] = VGM_WORD32_INVALID;
808
809 UWord mask = 0x0F;
810 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
811 /* mask now contains 1s where we wish to make address bits invalid
812 (1s). */
813 sm->abits[a_off] |= mask;
814# endif
815}
816
817
njn9b007f62003-04-07 14:40:25 +0000818/* Nb: by "aligned" here we mean 8-byte aligned */
819static __inline__
sewardj23eb2fd2005-04-22 16:29:19 +0000820void make_aligned_word64_writable ( Addr aA )
njn9b007f62003-04-07 14:40:25 +0000821{
sewardj23eb2fd2005-04-22 16:29:19 +0000822 PROF_EVENT(320, "make_aligned_word64_writable");
823
824# if VG_DEBUG_MEMORY >= 2
825 mc_make_writable(aA, 8);
826# else
827
828 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
829 PROF_EVENT(321, "make_aligned_word64_writable-slow1");
830 mc_make_writable(aA, 8);
831 return;
832 }
833
834 UWord a = (UWord)aA;
835 UWord sec_no = (UWord)(a >> 16);
836# if VG_DEBUG_MEMORY >= 1
837 tl_assert(sec_no < N_PRIMARY_MAP);
838# endif
839
840 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
841 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
842
843 SecMap* sm = primary_map[sec_no];
844 UWord v_off = a & 0xFFFF;
845 UWord a_off = v_off >> 3;
846
847 /* Paint the new area as uninitialised. */
848 ((ULong*)(sm->vbyte))[v_off >> 3] = VGM_WORD64_INVALID;
849
850 /* Make the relevant area accessible. */
851 sm->abits[a_off] = VGM_BYTE_VALID;
852# endif
njn9b007f62003-04-07 14:40:25 +0000853}
854
sewardj23eb2fd2005-04-22 16:29:19 +0000855
njn9b007f62003-04-07 14:40:25 +0000856static __inline__
sewardj23eb2fd2005-04-22 16:29:19 +0000857void make_aligned_word64_noaccess ( Addr aA )
njn9b007f62003-04-07 14:40:25 +0000858{
sewardj23eb2fd2005-04-22 16:29:19 +0000859 PROF_EVENT(330, "make_aligned_word64_noaccess");
860
861# if VG_DEBUG_MEMORY >= 2
862 mc_make_noaccess(aA, 8);
863# else
864
865 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
866 PROF_EVENT(331, "make_aligned_word64_noaccess-slow1");
867 mc_make_noaccess(aA, 8);
868 return;
869 }
870
871 UWord a = (UWord)aA;
872 UWord sec_no = (UWord)(a >> 16);
873# if VG_DEBUG_MEMORY >= 1
874 tl_assert(sec_no < N_PRIMARY_MAP);
875# endif
876
877 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
878 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
879
880 SecMap* sm = primary_map[sec_no];
881 UWord v_off = a & 0xFFFF;
882 UWord a_off = v_off >> 3;
883
884 /* Paint the abandoned data as uninitialised. Probably not
885 necessary, but still .. */
886 ((ULong*)(sm->vbyte))[v_off >> 3] = VGM_WORD64_INVALID;
887
888 /* Make the abandoned area inaccessible. */
889 sm->abits[a_off] = VGM_BYTE_INVALID;
890# endif
njn9b007f62003-04-07 14:40:25 +0000891}
892
sewardj23eb2fd2005-04-22 16:29:19 +0000893
sewardj45d94cc2005-04-20 14:44:11 +0000894/* The stack-pointer update handling functions */
895SP_UPDATE_HANDLERS ( make_aligned_word32_writable,
896 make_aligned_word32_noaccess,
897 make_aligned_word64_writable,
898 make_aligned_word64_noaccess,
899 mc_make_writable,
900 mc_make_noaccess
901 );
njn9b007f62003-04-07 14:40:25 +0000902
sewardj45d94cc2005-04-20 14:44:11 +0000903
nethercote8b76fe52004-11-08 19:20:09 +0000904/*------------------------------------------------------------*/
905/*--- Checking memory ---*/
906/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000907
908/* Check permissions for address range. If inadequate permissions
909 exist, *bad_addr is set to the offending address, so the caller can
910 know what it is. */
911
sewardjecf8e102003-07-12 12:11:39 +0000912/* Returns True if [a .. a+len) is not addressible. Otherwise,
913 returns False, and if bad_addr is non-NULL, sets *bad_addr to
914 indicate the lowest failing address. Functions below are
915 similar. */
nethercote8b76fe52004-11-08 19:20:09 +0000916static Bool mc_check_noaccess ( Addr a, SizeT len, Addr* bad_addr )
sewardjecf8e102003-07-12 12:11:39 +0000917{
nethercote451eae92004-11-02 13:06:32 +0000918 SizeT i;
sewardj45d94cc2005-04-20 14:44:11 +0000919 UWord abit;
sewardjc1a2cda2005-04-21 17:34:00 +0000920 PROF_EVENT(60, "mc_check_noaccess");
sewardjecf8e102003-07-12 12:11:39 +0000921 for (i = 0; i < len; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +0000922 PROF_EVENT(61, "mc_check_noaccess(loop)");
sewardjecf8e102003-07-12 12:11:39 +0000923 abit = get_abit(a);
924 if (abit == VGM_BIT_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +0000925 if (bad_addr != NULL)
926 *bad_addr = a;
sewardjecf8e102003-07-12 12:11:39 +0000927 return False;
928 }
929 a++;
930 }
931 return True;
932}
933
nethercote8b76fe52004-11-08 19:20:09 +0000934static Bool mc_check_writable ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000935{
nethercote451eae92004-11-02 13:06:32 +0000936 SizeT i;
sewardj45d94cc2005-04-20 14:44:11 +0000937 UWord abit;
sewardjc1a2cda2005-04-21 17:34:00 +0000938 PROF_EVENT(62, "mc_check_writable");
njn25e49d8e72002-09-23 09:36:25 +0000939 for (i = 0; i < len; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +0000940 PROF_EVENT(63, "mc_check_writable(loop)");
njn25e49d8e72002-09-23 09:36:25 +0000941 abit = get_abit(a);
942 if (abit == VGM_BIT_INVALID) {
943 if (bad_addr != NULL) *bad_addr = a;
944 return False;
945 }
946 a++;
947 }
948 return True;
949}
950
nethercote8b76fe52004-11-08 19:20:09 +0000951static MC_ReadResult mc_check_readable ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000952{
nethercote451eae92004-11-02 13:06:32 +0000953 SizeT i;
sewardj45d94cc2005-04-20 14:44:11 +0000954 UWord abit;
955 UWord vbyte;
njn25e49d8e72002-09-23 09:36:25 +0000956
sewardjc1a2cda2005-04-21 17:34:00 +0000957 PROF_EVENT(64, "mc_check_readable");
nethercote8b76fe52004-11-08 19:20:09 +0000958 DEBUG("mc_check_readable\n");
njn25e49d8e72002-09-23 09:36:25 +0000959 for (i = 0; i < len; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +0000960 PROF_EVENT(65, "mc_check_readable(loop)");
sewardj45d94cc2005-04-20 14:44:11 +0000961 get_abit_and_vbyte(&abit, &vbyte, a);
nethercote8b76fe52004-11-08 19:20:09 +0000962 // Report addressability errors in preference to definedness errors
963 // by checking the A bits first.
964 if (abit != VGM_BIT_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +0000965 if (bad_addr != NULL)
966 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +0000967 return MC_AddrErr;
968 }
969 if (vbyte != VGM_BYTE_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +0000970 if (bad_addr != NULL)
971 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +0000972 return MC_ValueErr;
njn25e49d8e72002-09-23 09:36:25 +0000973 }
974 a++;
975 }
nethercote8b76fe52004-11-08 19:20:09 +0000976 return MC_Ok;
njn25e49d8e72002-09-23 09:36:25 +0000977}
978
979
980/* Check a zero-terminated ascii string. Tricky -- don't want to
981 examine the actual bytes, to find the end, until we're sure it is
982 safe to do so. */
983
njn9b007f62003-04-07 14:40:25 +0000984static Bool mc_check_readable_asciiz ( Addr a, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000985{
sewardj45d94cc2005-04-20 14:44:11 +0000986 UWord abit;
987 UWord vbyte;
sewardjc1a2cda2005-04-21 17:34:00 +0000988 PROF_EVENT(66, "mc_check_readable_asciiz");
njn5c004e42002-11-18 11:04:50 +0000989 DEBUG("mc_check_readable_asciiz\n");
njn25e49d8e72002-09-23 09:36:25 +0000990 while (True) {
sewardjc1a2cda2005-04-21 17:34:00 +0000991 PROF_EVENT(67, "mc_check_readable_asciiz(loop)");
sewardj45d94cc2005-04-20 14:44:11 +0000992 get_abit_and_vbyte(&abit, &vbyte, a);
nethercote8b76fe52004-11-08 19:20:09 +0000993 // As in mc_check_readable(), check A bits first
994 if (abit != VGM_BIT_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +0000995 if (bad_addr != NULL)
996 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +0000997 return MC_AddrErr;
998 }
999 if (vbyte != VGM_BYTE_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001000 if (bad_addr != NULL)
1001 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +00001002 return MC_ValueErr;
njn25e49d8e72002-09-23 09:36:25 +00001003 }
1004 /* Ok, a is safe to read. */
sewardj45d94cc2005-04-20 14:44:11 +00001005 if (* ((UChar*)a) == 0)
1006 return MC_Ok;
njn25e49d8e72002-09-23 09:36:25 +00001007 a++;
1008 }
1009}
1010
1011
1012/*------------------------------------------------------------*/
1013/*--- Memory event handlers ---*/
1014/*------------------------------------------------------------*/
1015
njn25e49d8e72002-09-23 09:36:25 +00001016static
njn72718642003-07-24 08:45:32 +00001017void mc_check_is_writable ( CorePart part, ThreadId tid, Char* s,
nethercote451eae92004-11-02 13:06:32 +00001018 Addr base, SizeT size )
njn25e49d8e72002-09-23 09:36:25 +00001019{
1020 Bool ok;
1021 Addr bad_addr;
1022
1023 VGP_PUSHCC(VgpCheckMem);
1024
1025 /* VG_(message)(Vg_DebugMsg,"check is writable: %x .. %x",
1026 base,base+size-1); */
nethercote8b76fe52004-11-08 19:20:09 +00001027 ok = mc_check_writable ( base, size, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +00001028 if (!ok) {
1029 switch (part) {
1030 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +00001031 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
1032 /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +00001033 break;
1034
1035 case Vg_CorePThread:
1036 case Vg_CoreSignal:
nethercote8b76fe52004-11-08 19:20:09 +00001037 MAC_(record_core_mem_error)( tid, /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +00001038 break;
1039
1040 default:
njn67993252004-11-22 18:02:32 +00001041 VG_(tool_panic)("mc_check_is_writable: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +00001042 }
1043 }
1044
1045 VGP_POPCC(VgpCheckMem);
1046}
1047
1048static
njn72718642003-07-24 08:45:32 +00001049void mc_check_is_readable ( CorePart part, ThreadId tid, Char* s,
nethercote451eae92004-11-02 13:06:32 +00001050 Addr base, SizeT size )
njn25e49d8e72002-09-23 09:36:25 +00001051{
njn25e49d8e72002-09-23 09:36:25 +00001052 Addr bad_addr;
nethercote8b76fe52004-11-08 19:20:09 +00001053 MC_ReadResult res;
njn25e49d8e72002-09-23 09:36:25 +00001054
1055 VGP_PUSHCC(VgpCheckMem);
1056
1057 /* VG_(message)(Vg_DebugMsg,"check is readable: %x .. %x",
1058 base,base+size-1); */
nethercote8b76fe52004-11-08 19:20:09 +00001059 res = mc_check_readable ( base, size, &bad_addr );
1060 if (MC_Ok != res) {
1061 Bool isUnaddr = ( MC_AddrErr == res ? True : False );
1062
njn25e49d8e72002-09-23 09:36:25 +00001063 switch (part) {
1064 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +00001065 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
1066 isUnaddr, s );
njn25e49d8e72002-09-23 09:36:25 +00001067 break;
1068
1069 case Vg_CorePThread:
nethercote8b76fe52004-11-08 19:20:09 +00001070 MAC_(record_core_mem_error)( tid, isUnaddr, s );
njn25e49d8e72002-09-23 09:36:25 +00001071 break;
1072
1073 /* If we're being asked to jump to a silly address, record an error
1074 message before potentially crashing the entire system. */
1075 case Vg_CoreTranslate:
njn72718642003-07-24 08:45:32 +00001076 MAC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +00001077 break;
1078
1079 default:
njn67993252004-11-22 18:02:32 +00001080 VG_(tool_panic)("mc_check_is_readable: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +00001081 }
1082 }
1083 VGP_POPCC(VgpCheckMem);
1084}
1085
1086static
njn72718642003-07-24 08:45:32 +00001087void mc_check_is_readable_asciiz ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +00001088 Char* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +00001089{
nethercote8b76fe52004-11-08 19:20:09 +00001090 MC_ReadResult res;
sewardj45d94cc2005-04-20 14:44:11 +00001091 Addr bad_addr;
njn25e49d8e72002-09-23 09:36:25 +00001092 /* VG_(message)(Vg_DebugMsg,"check is readable asciiz: 0x%x",str); */
1093
1094 VGP_PUSHCC(VgpCheckMem);
1095
njnca82cc02004-11-22 17:18:48 +00001096 tl_assert(part == Vg_CoreSysCall);
nethercote8b76fe52004-11-08 19:20:09 +00001097 res = mc_check_readable_asciiz ( (Addr)str, &bad_addr );
1098 if (MC_Ok != res) {
1099 Bool isUnaddr = ( MC_AddrErr == res ? True : False );
1100 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False, isUnaddr, s );
njn25e49d8e72002-09-23 09:36:25 +00001101 }
1102
1103 VGP_POPCC(VgpCheckMem);
1104}
1105
njn25e49d8e72002-09-23 09:36:25 +00001106static
nethercote451eae92004-11-02 13:06:32 +00001107void mc_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +00001108{
njn1f3a9092002-10-04 09:22:30 +00001109 /* Ignore the permissions, just make it readable. Seems to work... */
nethercote451eae92004-11-02 13:06:32 +00001110 DEBUG("mc_new_mem_startup(%p, %llu, rr=%u, ww=%u, xx=%u)\n",
1111 a,(ULong)len,rr,ww,xx);
nethercote8b76fe52004-11-08 19:20:09 +00001112 mc_make_readable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001113}
1114
1115static
nethercote451eae92004-11-02 13:06:32 +00001116void mc_new_mem_heap ( Addr a, SizeT len, Bool is_inited )
njn25e49d8e72002-09-23 09:36:25 +00001117{
1118 if (is_inited) {
nethercote8b76fe52004-11-08 19:20:09 +00001119 mc_make_readable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001120 } else {
nethercote8b76fe52004-11-08 19:20:09 +00001121 mc_make_writable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001122 }
1123}
1124
1125static
njnb8dca862005-03-14 02:42:44 +00001126void mc_new_mem_mmap ( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +00001127{
njnb8dca862005-03-14 02:42:44 +00001128 mc_make_readable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001129}
1130
njncf45fd42004-11-24 16:30:22 +00001131static
1132void mc_post_mem_write(CorePart part, ThreadId tid, Addr a, SizeT len)
1133{
1134 mc_make_readable(a, len);
1135}
njn25e49d8e72002-09-23 09:36:25 +00001136
sewardj45d94cc2005-04-20 14:44:11 +00001137
njn25e49d8e72002-09-23 09:36:25 +00001138/*------------------------------------------------------------*/
njnd3040452003-05-19 15:04:06 +00001139/*--- Register event handlers ---*/
1140/*------------------------------------------------------------*/
1141
sewardj45d94cc2005-04-20 14:44:11 +00001142/* When some chunk of guest state is written, mark the corresponding
1143 shadow area as valid. This is used to initialise arbitrarily large
1144 chunks of guest state, hence the (somewhat arbitrary) 512 limit.
1145*/
1146static void mc_post_reg_write ( CorePart part, ThreadId tid,
1147 OffT offset, SizeT size)
njnd3040452003-05-19 15:04:06 +00001148{
sewardj6cf40ff2005-04-20 22:31:26 +00001149 UChar area[1024];
1150 tl_assert(size <= 1024);
njncf45fd42004-11-24 16:30:22 +00001151 VG_(memset)(area, VGM_BYTE_VALID, size);
1152 VG_(set_shadow_regs_area)( tid, offset, size, area );
njnd3040452003-05-19 15:04:06 +00001153}
1154
sewardj45d94cc2005-04-20 14:44:11 +00001155static
1156void mc_post_reg_write_clientcall ( ThreadId tid,
1157 OffT offset, SizeT size,
1158 Addr f)
njnd3040452003-05-19 15:04:06 +00001159{
njncf45fd42004-11-24 16:30:22 +00001160 mc_post_reg_write(/*dummy*/0, tid, offset, size);
njnd3040452003-05-19 15:04:06 +00001161}
1162
sewardj45d94cc2005-04-20 14:44:11 +00001163/* Look at the definedness of the guest's shadow state for
1164 [offset, offset+len). If any part of that is undefined, record
1165 a parameter error.
1166*/
1167static void mc_pre_reg_read ( CorePart part, ThreadId tid, Char* s,
1168 OffT offset, SizeT size)
nethercote8b76fe52004-11-08 19:20:09 +00001169{
sewardj45d94cc2005-04-20 14:44:11 +00001170 Int i;
1171 Bool bad;
1172
1173 UChar area[16];
1174 tl_assert(size <= 16);
1175
1176 VG_(get_shadow_regs_area)( tid, offset, size, area );
1177
1178 bad = False;
1179 for (i = 0; i < size; i++) {
1180 if (area[i] != VGM_BYTE_VALID) {
1181 bad = False;
1182 break;
1183 }
nethercote8b76fe52004-11-08 19:20:09 +00001184 }
1185
sewardj45d94cc2005-04-20 14:44:11 +00001186 if (bad)
nethercote8b76fe52004-11-08 19:20:09 +00001187 MAC_(record_param_error) ( tid, 0, /*isReg*/True, /*isUnaddr*/False, s );
1188}
njnd3040452003-05-19 15:04:06 +00001189
njn25e49d8e72002-09-23 09:36:25 +00001190
sewardj6cf40ff2005-04-20 22:31:26 +00001191/*------------------------------------------------------------*/
sewardjc859fbf2005-04-22 21:10:28 +00001192/*--- Functions called directly from generated code: ---*/
1193/*--- Load/store handlers. ---*/
sewardj6cf40ff2005-04-20 22:31:26 +00001194/*------------------------------------------------------------*/
1195
1196/* Types: LOADV4, LOADV2, LOADV1 are:
1197 UWord fn ( Addr a )
1198 so they return 32-bits on 32-bit machines and 64-bits on
1199 64-bit machines. Addr has the same size as a host word.
1200
1201 LOADV8 is always ULong fn ( Addr a )
1202
1203 Similarly for STOREV1, STOREV2, STOREV4, the supplied vbits
1204 are a UWord, and for STOREV8 they are a ULong.
1205*/
1206
sewardj95448072004-11-22 20:19:51 +00001207/* ------------------------ Size = 8 ------------------------ */
1208
njn9fb73db2005-03-27 01:55:21 +00001209VGA_REGPARM(1)
sewardjf9d81612005-04-23 23:25:49 +00001210ULong MC_(helperc_LOADV8) ( Addr aA )
sewardj95448072004-11-22 20:19:51 +00001211{
sewardjf9d81612005-04-23 23:25:49 +00001212 PROF_EVENT(200, "helperc_LOADV8");
1213
1214# if VG_DEBUG_MEMORY >= 2
1215 return mc_LOADVn_slow( aA, 8, False/*littleendian*/ );
1216# else
1217
1218 const UWord mask = ~((0x10000-8) | ((N_PRIMARY_MAP-1) << 16));
1219 UWord a = (UWord)aA;
1220
1221 /* If any part of 'a' indicated by the mask is 1, either 'a' is not
1222 naturally aligned, or 'a' exceeds the range covered by the
1223 primary map. Either way we defer to the slow-path case. */
1224 if (EXPECTED_NOT_TAKEN(a & mask)) {
1225 PROF_EVENT(201, "helperc_LOADV8-slow1");
1226 return (UWord)mc_LOADVn_slow( aA, 8, False/*littleendian*/ );
1227 }
1228
1229 UWord sec_no = (UWord)(a >> 16);
1230
1231# if VG_DEBUG_MEMORY >= 1
1232 tl_assert(sec_no < N_PRIMARY_MAP);
1233# endif
1234
1235 SecMap* sm = primary_map[sec_no];
1236 UWord v_off = a & 0xFFFF;
1237 UWord a_off = v_off >> 3;
1238 UWord abits = (UWord)(sm->abits[a_off]);
1239
1240 if (EXPECTED_TAKEN(abits == VGM_BYTE_VALID)) {
1241 /* Handle common case quickly: a is suitably aligned, is mapped,
1242 and is addressible. */
1243 return ((ULong*)(sm->vbyte))[ v_off >> 3 ];
1244 } else {
1245 /* Slow but general case. */
1246 PROF_EVENT(202, "helperc_LOADV8-slow2");
1247 return mc_LOADVn_slow( a, 8, False/*littleendian*/ );
1248 }
1249
1250# endif
sewardj95448072004-11-22 20:19:51 +00001251}
1252
njn9fb73db2005-03-27 01:55:21 +00001253VGA_REGPARM(1)
sewardjf9d81612005-04-23 23:25:49 +00001254void MC_(helperc_STOREV8) ( Addr aA, ULong vbytes )
sewardj95448072004-11-22 20:19:51 +00001255{
sewardjf9d81612005-04-23 23:25:49 +00001256 PROF_EVENT(210, "helperc_STOREV8");
1257
1258# if VG_DEBUG_MEMORY >= 2
1259 mc_STOREVn_slow( aA, 8, vbytes, False/*littleendian*/ );
1260# else
1261
1262 const UWord mask = ~((0x10000-8) | ((N_PRIMARY_MAP-1) << 16));
1263 UWord a = (UWord)aA;
1264
1265 /* If any part of 'a' indicated by the mask is 1, either 'a' is not
1266 naturally aligned, or 'a' exceeds the range covered by the
1267 primary map. Either way we defer to the slow-path case. */
1268 if (EXPECTED_NOT_TAKEN(a & mask)) {
1269 PROF_EVENT(211, "helperc_STOREV8-slow1");
1270 mc_STOREVn_slow( aA, 8, vbytes, False/*littleendian*/ );
1271 return;
1272 }
1273
1274 UWord sec_no = (UWord)(a >> 16);
1275
1276# if VG_DEBUG_MEMORY >= 1
1277 tl_assert(sec_no < N_PRIMARY_MAP);
1278# endif
1279
1280 SecMap* sm = primary_map[sec_no];
1281 UWord v_off = a & 0xFFFF;
1282 UWord a_off = v_off >> 3;
1283 UWord abits = (UWord)(sm->abits[a_off]);
1284
1285 if (EXPECTED_TAKEN(!is_distinguished_sm(sm)
1286 && abits == VGM_BYTE_VALID)) {
1287 /* Handle common case quickly: a is suitably aligned, is mapped,
1288 and is addressible. */
1289 ((ULong*)(sm->vbyte))[ v_off >> 3 ] = vbytes;
1290 } else {
1291 /* Slow but general case. */
1292 PROF_EVENT(212, "helperc_STOREV8-slow2");
1293 mc_STOREVn_slow( aA, 8, vbytes, False/*littleendian*/ );
1294 }
1295# endif
sewardj95448072004-11-22 20:19:51 +00001296}
1297
1298/* ------------------------ Size = 4 ------------------------ */
1299
njn9fb73db2005-03-27 01:55:21 +00001300VGA_REGPARM(1)
sewardjc1a2cda2005-04-21 17:34:00 +00001301UWord MC_(helperc_LOADV4) ( Addr aA )
njn25e49d8e72002-09-23 09:36:25 +00001302{
sewardjc1a2cda2005-04-21 17:34:00 +00001303 PROF_EVENT(220, "helperc_LOADV4");
1304
1305# if VG_DEBUG_MEMORY >= 2
1306 return (UWord)mc_LOADVn_slow( aA, 4, False/*littleendian*/ );
1307# else
1308
sewardj23eb2fd2005-04-22 16:29:19 +00001309 const UWord mask = ~((0x10000-4) | ((N_PRIMARY_MAP-1) << 16));
sewardjc1a2cda2005-04-21 17:34:00 +00001310 UWord a = (UWord)aA;
1311
1312 /* If any part of 'a' indicated by the mask is 1, either 'a' is not
1313 naturally aligned, or 'a' exceeds the range covered by the
1314 primary map. Either way we defer to the slow-path case. */
1315 if (EXPECTED_NOT_TAKEN(a & mask)) {
1316 PROF_EVENT(221, "helperc_LOADV4-slow1");
1317 return (UWord)mc_LOADVn_slow( aA, 4, False/*littleendian*/ );
1318 }
1319
1320 UWord sec_no = (UWord)(a >> 16);
1321
1322# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +00001323 tl_assert(sec_no < N_PRIMARY_MAP);
sewardjc1a2cda2005-04-21 17:34:00 +00001324# endif
1325
1326 SecMap* sm = primary_map[sec_no];
1327 UWord v_off = a & 0xFFFF;
1328 UWord a_off = v_off >> 3;
1329 UWord abits = (UWord)(sm->abits[a_off]);
1330 abits >>= (a & 4);
1331 abits &= 15;
1332 if (EXPECTED_TAKEN(abits == VGM_NIBBLE_VALID)) {
1333 /* Handle common case quickly: a is suitably aligned, is mapped,
1334 and is addressible. */
sewardj5d28efc2005-04-21 22:16:29 +00001335 /* On a 32-bit platform, simply hoick the required 32 bits out of
1336 the vbyte array. On a 64-bit platform, also set the upper 32
1337 bits to 1 ("undefined"), just in case. This almost certainly
1338 isn't necessary, but be paranoid. */
1339 UWord ret = (UWord)0xFFFFFFFF00000000ULL;
1340 ret |= (UWord)( ((UInt*)(sm->vbyte))[ v_off >> 2 ] );
1341 return ret;
sewardjc1a2cda2005-04-21 17:34:00 +00001342 } else {
1343 /* Slow but general case. */
1344 PROF_EVENT(222, "helperc_LOADV4-slow2");
1345 return (UWord)mc_LOADVn_slow( a, 4, False/*littleendian*/ );
1346 }
1347
1348# endif
njn25e49d8e72002-09-23 09:36:25 +00001349}
1350
njn9fb73db2005-03-27 01:55:21 +00001351VGA_REGPARM(2)
sewardjc1a2cda2005-04-21 17:34:00 +00001352void MC_(helperc_STOREV4) ( Addr aA, UWord vbytes )
njn25e49d8e72002-09-23 09:36:25 +00001353{
sewardjc1a2cda2005-04-21 17:34:00 +00001354 PROF_EVENT(230, "helperc_STOREV4");
1355
1356# if VG_DEBUG_MEMORY >= 2
sewardj23eb2fd2005-04-22 16:29:19 +00001357 mc_STOREVn_slow( aA, 4, (ULong)vbytes, False/*littleendian*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001358# else
1359
sewardj23eb2fd2005-04-22 16:29:19 +00001360 const UWord mask = ~((0x10000-4) | ((N_PRIMARY_MAP-1) << 16));
sewardjc1a2cda2005-04-21 17:34:00 +00001361 UWord a = (UWord)aA;
1362
1363 /* If any part of 'a' indicated by the mask is 1, either 'a' is not
1364 naturally aligned, or 'a' exceeds the range covered by the
1365 primary map. Either way we defer to the slow-path case. */
1366 if (EXPECTED_NOT_TAKEN(a & mask)) {
1367 PROF_EVENT(231, "helperc_STOREV4-slow1");
1368 mc_STOREVn_slow( aA, 4, (ULong)vbytes, False/*littleendian*/ );
1369 return;
1370 }
1371
1372 UWord sec_no = (UWord)(a >> 16);
1373
1374# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +00001375 tl_assert(sec_no < N_PRIMARY_MAP);
sewardjc1a2cda2005-04-21 17:34:00 +00001376# endif
1377
1378 SecMap* sm = primary_map[sec_no];
1379 UWord v_off = a & 0xFFFF;
1380 UWord a_off = v_off >> 3;
1381 UWord abits = (UWord)(sm->abits[a_off]);
1382 abits >>= (a & 4);
1383 abits &= 15;
1384 if (EXPECTED_TAKEN(!is_distinguished_sm(sm)
1385 && abits == VGM_NIBBLE_VALID)) {
1386 /* Handle common case quickly: a is suitably aligned, is mapped,
1387 and is addressible. */
1388 ((UInt*)(sm->vbyte))[ v_off >> 2 ] = (UInt)vbytes;
1389 } else {
1390 /* Slow but general case. */
1391 PROF_EVENT(232, "helperc_STOREV4-slow2");
1392 mc_STOREVn_slow( aA, 4, (ULong)vbytes, False/*littleendian*/ );
1393 }
1394# endif
njn25e49d8e72002-09-23 09:36:25 +00001395}
1396
sewardj95448072004-11-22 20:19:51 +00001397/* ------------------------ Size = 2 ------------------------ */
1398
njn9fb73db2005-03-27 01:55:21 +00001399VGA_REGPARM(1)
sewardjc1a2cda2005-04-21 17:34:00 +00001400UWord MC_(helperc_LOADV2) ( Addr aA )
njn25e49d8e72002-09-23 09:36:25 +00001401{
sewardjc1a2cda2005-04-21 17:34:00 +00001402 PROF_EVENT(240, "helperc_LOADV2");
1403
1404# if VG_DEBUG_MEMORY >= 2
1405 return (UWord)mc_LOADVn_slow( aA, 2, False/*littleendian*/ );
1406# else
1407
sewardj23eb2fd2005-04-22 16:29:19 +00001408 const UWord mask = ~((0x10000-2) | ((N_PRIMARY_MAP-1) << 16));
sewardjc1a2cda2005-04-21 17:34:00 +00001409 UWord a = (UWord)aA;
1410
1411 /* If any part of 'a' indicated by the mask is 1, either 'a' is not
1412 naturally aligned, or 'a' exceeds the range covered by the
1413 primary map. Either way we defer to the slow-path case. */
1414 if (EXPECTED_NOT_TAKEN(a & mask)) {
1415 PROF_EVENT(241, "helperc_LOADV2-slow1");
1416 return (UWord)mc_LOADVn_slow( aA, 2, False/*littleendian*/ );
1417 }
1418
1419 UWord sec_no = (UWord)(a >> 16);
1420
1421# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +00001422 tl_assert(sec_no < N_PRIMARY_MAP);
sewardjc1a2cda2005-04-21 17:34:00 +00001423# endif
1424
1425 SecMap* sm = primary_map[sec_no];
1426 UWord v_off = a & 0xFFFF;
1427 UWord a_off = v_off >> 3;
1428 UWord abits = (UWord)(sm->abits[a_off]);
sewardjc1a2cda2005-04-21 17:34:00 +00001429 if (EXPECTED_TAKEN(abits == VGM_BYTE_VALID)) {
1430 /* Handle common case quickly: a is mapped, and the entire
1431 word32 it lives in is addressible. */
sewardj5d28efc2005-04-21 22:16:29 +00001432 /* Set the upper 16/48 bits of the result to 1 ("undefined"),
1433 just in case. This almost certainly isn't necessary, but be
1434 paranoid. */
sewardjc1a2cda2005-04-21 17:34:00 +00001435 return (~(UWord)0xFFFF)
1436 |
1437 (UWord)( ((UShort*)(sm->vbyte))[ v_off >> 1 ] );
1438 } else {
1439 /* Slow but general case. */
1440 PROF_EVENT(242, "helperc_LOADV2-slow2");
1441 return (UWord)mc_LOADVn_slow( aA, 2, False/*littleendian*/ );
1442 }
1443
1444# endif
njn25e49d8e72002-09-23 09:36:25 +00001445}
1446
njn9fb73db2005-03-27 01:55:21 +00001447VGA_REGPARM(2)
sewardj5d28efc2005-04-21 22:16:29 +00001448void MC_(helperc_STOREV2) ( Addr aA, UWord vbytes )
njn25e49d8e72002-09-23 09:36:25 +00001449{
sewardjc1a2cda2005-04-21 17:34:00 +00001450 PROF_EVENT(250, "helperc_STOREV2");
sewardj5d28efc2005-04-21 22:16:29 +00001451
1452# if VG_DEBUG_MEMORY >= 2
sewardj23eb2fd2005-04-22 16:29:19 +00001453 mc_STOREVn_slow( aA, 2, (ULong)vbytes, False/*littleendian*/ );
sewardj5d28efc2005-04-21 22:16:29 +00001454# else
1455
sewardj23eb2fd2005-04-22 16:29:19 +00001456 const UWord mask = ~((0x10000-2) | ((N_PRIMARY_MAP-1) << 16));
sewardj5d28efc2005-04-21 22:16:29 +00001457 UWord a = (UWord)aA;
1458
1459 /* If any part of 'a' indicated by the mask is 1, either 'a' is not
1460 naturally aligned, or 'a' exceeds the range covered by the
1461 primary map. Either way we defer to the slow-path case. */
1462 if (EXPECTED_NOT_TAKEN(a & mask)) {
1463 PROF_EVENT(251, "helperc_STOREV2-slow1");
1464 mc_STOREVn_slow( aA, 2, (ULong)vbytes, False/*littleendian*/ );
1465 return;
1466 }
1467
1468 UWord sec_no = (UWord)(a >> 16);
1469
1470# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +00001471 tl_assert(sec_no < N_PRIMARY_MAP);
sewardj5d28efc2005-04-21 22:16:29 +00001472# endif
1473
1474 SecMap* sm = primary_map[sec_no];
1475 UWord v_off = a & 0xFFFF;
1476 UWord a_off = v_off >> 3;
1477 UWord abits = (UWord)(sm->abits[a_off]);
1478 if (EXPECTED_TAKEN(!is_distinguished_sm(sm)
1479 && abits == VGM_BYTE_VALID)) {
1480 /* Handle common case quickly. */
1481 ((UShort*)(sm->vbyte))[ v_off >> 1 ] = (UShort)vbytes;
1482 } else {
1483 /* Slow but general case. */
1484 PROF_EVENT(252, "helperc_STOREV2-slow2");
1485 mc_STOREVn_slow( aA, 2, (ULong)vbytes, False/*littleendian*/ );
1486 }
1487# endif
njn25e49d8e72002-09-23 09:36:25 +00001488}
1489
sewardj95448072004-11-22 20:19:51 +00001490/* ------------------------ Size = 1 ------------------------ */
1491
njn9fb73db2005-03-27 01:55:21 +00001492VGA_REGPARM(1)
sewardjc1a2cda2005-04-21 17:34:00 +00001493UWord MC_(helperc_LOADV1) ( Addr aA )
njn25e49d8e72002-09-23 09:36:25 +00001494{
sewardjc1a2cda2005-04-21 17:34:00 +00001495 PROF_EVENT(260, "helperc_LOADV1");
1496
1497# if VG_DEBUG_MEMORY >= 2
sewardj23eb2fd2005-04-22 16:29:19 +00001498 return (UWord)mc_LOADVn_slow( aA, 1, False/*littleendian*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001499# else
1500
sewardj23eb2fd2005-04-22 16:29:19 +00001501 const UWord mask = ~((0x10000-1) | ((N_PRIMARY_MAP-1) << 16));
sewardjc1a2cda2005-04-21 17:34:00 +00001502 UWord a = (UWord)aA;
1503
1504 /* If any part of 'a' indicated by the mask is 1, it means 'a'
1505 exceeds the range covered by the primary map. In which case we
1506 defer to the slow-path case. */
1507 if (EXPECTED_NOT_TAKEN(a & mask)) {
1508 PROF_EVENT(261, "helperc_LOADV1-slow1");
1509 return (UWord)mc_LOADVn_slow( aA, 1, False/*littleendian*/ );
1510 }
1511
1512 UWord sec_no = (UWord)(a >> 16);
1513
1514# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +00001515 tl_assert(sec_no < N_PRIMARY_MAP);
sewardjc1a2cda2005-04-21 17:34:00 +00001516# endif
1517
1518 SecMap* sm = primary_map[sec_no];
1519 UWord v_off = a & 0xFFFF;
1520 UWord a_off = v_off >> 3;
sewardj5d28efc2005-04-21 22:16:29 +00001521 UWord abits = (UWord)(sm->abits[a_off]);
sewardjc1a2cda2005-04-21 17:34:00 +00001522 if (EXPECTED_TAKEN(abits == VGM_BYTE_VALID)) {
1523 /* Handle common case quickly: a is mapped, and the entire
1524 word32 it lives in is addressible. */
sewardj5d28efc2005-04-21 22:16:29 +00001525 /* Set the upper 24/56 bits of the result to 1 ("undefined"),
1526 just in case. This almost certainly isn't necessary, but be
1527 paranoid. */
sewardjc1a2cda2005-04-21 17:34:00 +00001528 return (~(UWord)0xFF)
1529 |
1530 (UWord)( ((UChar*)(sm->vbyte))[ v_off ] );
1531 } else {
1532 /* Slow but general case. */
1533 PROF_EVENT(262, "helperc_LOADV1-slow2");
1534 return (UWord)mc_LOADVn_slow( aA, 1, False/*littleendian*/ );
1535 }
1536# endif
njn25e49d8e72002-09-23 09:36:25 +00001537}
1538
sewardjc1a2cda2005-04-21 17:34:00 +00001539
njn9fb73db2005-03-27 01:55:21 +00001540VGA_REGPARM(2)
sewardjc1a2cda2005-04-21 17:34:00 +00001541void MC_(helperc_STOREV1) ( Addr aA, UWord vbyte )
njn25e49d8e72002-09-23 09:36:25 +00001542{
sewardjc1a2cda2005-04-21 17:34:00 +00001543 PROF_EVENT(270, "helperc_STOREV1");
1544
1545# if VG_DEBUG_MEMORY >= 2
1546 mc_STOREVn_slow( aA, 1, (ULong)vbyte, False/*littleendian*/ );
1547# else
1548
sewardj23eb2fd2005-04-22 16:29:19 +00001549 const UWord mask = ~((0x10000-1) | ((N_PRIMARY_MAP-1) << 16));
sewardjc1a2cda2005-04-21 17:34:00 +00001550 UWord a = (UWord)aA;
1551 /* If any part of 'a' indicated by the mask is 1, it means 'a'
1552 exceeds the range covered by the primary map. In which case we
1553 defer to the slow-path case. */
1554 if (EXPECTED_NOT_TAKEN(a & mask)) {
1555 PROF_EVENT(271, "helperc_STOREV1-slow1");
1556 mc_STOREVn_slow( aA, 1, (ULong)vbyte, False/*littleendian*/ );
1557 return;
1558 }
1559
1560 UWord sec_no = (UWord)(a >> 16);
1561
1562# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +00001563 tl_assert(sec_no < N_PRIMARY_MAP);
sewardjc1a2cda2005-04-21 17:34:00 +00001564# endif
1565
1566 SecMap* sm = primary_map[sec_no];
1567 UWord v_off = a & 0xFFFF;
1568 UWord a_off = v_off >> 3;
sewardj5d28efc2005-04-21 22:16:29 +00001569 UWord abits = (UWord)(sm->abits[a_off]);
sewardjc1a2cda2005-04-21 17:34:00 +00001570 if (EXPECTED_TAKEN(!is_distinguished_sm(sm)
1571 && abits == VGM_BYTE_VALID)) {
1572 /* Handle common case quickly: a is mapped, the entire word32 it
1573 lives in is addressible. */
1574 ((UChar*)(sm->vbyte))[ v_off ] = (UChar)vbyte;
1575 } else {
1576 PROF_EVENT(272, "helperc_STOREV1-slow2");
1577 mc_STOREVn_slow( aA, 1, (ULong)vbyte, False/*littleendian*/ );
1578 }
1579
1580# endif
njn25e49d8e72002-09-23 09:36:25 +00001581}
1582
1583
sewardjc859fbf2005-04-22 21:10:28 +00001584/*------------------------------------------------------------*/
1585/*--- Functions called directly from generated code: ---*/
1586/*--- Value-check failure handlers. ---*/
1587/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00001588
njn5c004e42002-11-18 11:04:50 +00001589void MC_(helperc_value_check0_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001590{
njnb8dca862005-03-14 02:42:44 +00001591 MC_(record_value_error) ( VG_(get_running_tid)(), 0 );
njn25e49d8e72002-09-23 09:36:25 +00001592}
1593
njn5c004e42002-11-18 11:04:50 +00001594void MC_(helperc_value_check1_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001595{
njnb8dca862005-03-14 02:42:44 +00001596 MC_(record_value_error) ( VG_(get_running_tid)(), 1 );
njn25e49d8e72002-09-23 09:36:25 +00001597}
1598
njn5c004e42002-11-18 11:04:50 +00001599void MC_(helperc_value_check4_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001600{
njnb8dca862005-03-14 02:42:44 +00001601 MC_(record_value_error) ( VG_(get_running_tid)(), 4 );
njn25e49d8e72002-09-23 09:36:25 +00001602}
1603
sewardj11bcc4e2005-04-23 22:38:38 +00001604void MC_(helperc_value_check8_fail) ( void )
1605{
1606 MC_(record_value_error) ( VG_(get_running_tid)(), 8 );
1607}
1608
njn9fb73db2005-03-27 01:55:21 +00001609VGA_REGPARM(1) void MC_(helperc_complain_undef) ( HWord sz )
sewardj95448072004-11-22 20:19:51 +00001610{
njnb8dca862005-03-14 02:42:44 +00001611 MC_(record_value_error) ( VG_(get_running_tid)(), (Int)sz );
sewardj95448072004-11-22 20:19:51 +00001612}
1613
njn25e49d8e72002-09-23 09:36:25 +00001614
sewardj45d94cc2005-04-20 14:44:11 +00001615//zz /*------------------------------------------------------------*/
1616//zz /*--- Metadata get/set functions, for client requests. ---*/
1617//zz /*------------------------------------------------------------*/
1618//zz
1619//zz /* Copy Vbits for src into vbits. Returns: 1 == OK, 2 == alignment
1620//zz error, 3 == addressing error. */
1621//zz static Int mc_get_or_set_vbits_for_client (
1622//zz ThreadId tid,
1623//zz Addr dataV,
1624//zz Addr vbitsV,
1625//zz SizeT size,
1626//zz Bool setting /* True <=> set vbits, False <=> get vbits */
1627//zz )
1628//zz {
1629//zz Bool addressibleD = True;
1630//zz Bool addressibleV = True;
1631//zz UInt* data = (UInt*)dataV;
1632//zz UInt* vbits = (UInt*)vbitsV;
1633//zz SizeT szW = size / 4; /* sigh */
1634//zz SizeT i;
1635//zz UInt* dataP = NULL; /* bogus init to keep gcc happy */
1636//zz UInt* vbitsP = NULL; /* ditto */
1637//zz
1638//zz /* Check alignment of args. */
1639//zz if (!(VG_IS_4_ALIGNED(data) && VG_IS_4_ALIGNED(vbits)))
1640//zz return 2;
1641//zz if ((size & 3) != 0)
1642//zz return 2;
1643//zz
1644//zz /* Check that arrays are addressible. */
1645//zz for (i = 0; i < szW; i++) {
1646//zz dataP = &data[i];
1647//zz vbitsP = &vbits[i];
1648//zz if (get_abits4_ALIGNED((Addr)dataP) != VGM_NIBBLE_VALID) {
1649//zz addressibleD = False;
1650//zz break;
1651//zz }
1652//zz if (get_abits4_ALIGNED((Addr)vbitsP) != VGM_NIBBLE_VALID) {
1653//zz addressibleV = False;
1654//zz break;
1655//zz }
1656//zz }
1657//zz if (!addressibleD) {
1658//zz MAC_(record_address_error)( tid, (Addr)dataP, 4,
1659//zz setting ? True : False );
1660//zz return 3;
1661//zz }
1662//zz if (!addressibleV) {
1663//zz MAC_(record_address_error)( tid, (Addr)vbitsP, 4,
1664//zz setting ? False : True );
1665//zz return 3;
1666//zz }
1667//zz
1668//zz /* Do the copy */
1669//zz if (setting) {
1670//zz /* setting */
1671//zz for (i = 0; i < szW; i++) {
1672//zz if (get_vbytes4_ALIGNED( (Addr)&vbits[i] ) != VGM_WORD_VALID)
1673//zz MC_(record_value_error)(tid, 4);
1674//zz set_vbytes4_ALIGNED( (Addr)&data[i], vbits[i] );
1675//zz }
1676//zz } else {
1677//zz /* getting */
1678//zz for (i = 0; i < szW; i++) {
1679//zz vbits[i] = get_vbytes4_ALIGNED( (Addr)&data[i] );
1680//zz set_vbytes4_ALIGNED( (Addr)&vbits[i], VGM_WORD_VALID );
1681//zz }
1682//zz }
1683//zz
1684//zz return 1;
1685//zz }
sewardj05fe85e2005-04-27 22:46:36 +00001686
1687
1688/*------------------------------------------------------------*/
1689/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
1690/*------------------------------------------------------------*/
1691
1692/* For the memory leak detector, say whether an entire 64k chunk of
1693 address space is possibly in use, or not. If in doubt return
1694 True.
1695*/
1696static
1697Bool mc_is_within_valid_secondary ( Addr a )
1698{
1699 SecMap* sm = maybe_get_secmap_for ( a );
1700 if (sm == NULL || sm == &sm_distinguished[SM_DIST_NOACCESS]) {
1701 /* Definitely not in use. */
1702 return False;
1703 } else {
1704 return True;
1705 }
1706}
1707
1708
1709/* For the memory leak detector, say whether or not a given word
1710 address is to be regarded as valid. */
1711static
1712Bool mc_is_valid_aligned_word ( Addr a )
1713{
1714 tl_assert(sizeof(UWord) == 4 || sizeof(UWord) == 8);
1715 if (sizeof(UWord) == 4) {
1716 tl_assert(VG_IS_4_ALIGNED(a));
1717 } else {
1718 tl_assert(VG_IS_8_ALIGNED(a));
1719 }
1720 if (mc_check_readable( a, sizeof(UWord), NULL ) == MC_Ok) {
1721 return True;
1722 } else {
1723 return False;
1724 }
1725}
sewardja4495682002-10-21 07:29:59 +00001726
1727
nethercote996901a2004-08-03 13:29:09 +00001728/* Leak detector for this tool. We don't actually do anything, merely
sewardja4495682002-10-21 07:29:59 +00001729 run the generic leak detector with suitable parameters for this
nethercote996901a2004-08-03 13:29:09 +00001730 tool. */
njnb8dca862005-03-14 02:42:44 +00001731static void mc_detect_memory_leaks ( ThreadId tid, LeakCheckMode mode )
njn25e49d8e72002-09-23 09:36:25 +00001732{
sewardj05fe85e2005-04-27 22:46:36 +00001733 MAC_(do_detect_memory_leaks) (
1734 tid,
1735 mode,
1736 mc_is_within_valid_secondary,
1737 mc_is_valid_aligned_word
1738 );
njn25e49d8e72002-09-23 09:36:25 +00001739}
1740
1741
sewardjc859fbf2005-04-22 21:10:28 +00001742/*------------------------------------------------------------*/
1743/*--- Initialisation ---*/
1744/*------------------------------------------------------------*/
1745
1746static void init_shadow_memory ( void )
1747{
1748 Int i;
1749 SecMap* sm;
1750
1751 /* Build the 3 distinguished secondaries */
1752 tl_assert(VGM_BIT_INVALID == 1);
1753 tl_assert(VGM_BIT_VALID == 0);
1754 tl_assert(VGM_BYTE_INVALID == 0xFF);
1755 tl_assert(VGM_BYTE_VALID == 0);
1756
1757 /* Set A invalid, V invalid. */
1758 sm = &sm_distinguished[SM_DIST_NOACCESS];
1759 for (i = 0; i < 65536; i++)
1760 sm->vbyte[i] = VGM_BYTE_INVALID;
1761 for (i = 0; i < 8192; i++)
1762 sm->abits[i] = VGM_BYTE_INVALID;
1763
1764 /* Set A valid, V invalid. */
1765 sm = &sm_distinguished[SM_DIST_ACCESS_UNDEFINED];
1766 for (i = 0; i < 65536; i++)
1767 sm->vbyte[i] = VGM_BYTE_INVALID;
1768 for (i = 0; i < 8192; i++)
1769 sm->abits[i] = VGM_BYTE_VALID;
1770
1771 /* Set A valid, V valid. */
1772 sm = &sm_distinguished[SM_DIST_ACCESS_DEFINED];
1773 for (i = 0; i < 65536; i++)
1774 sm->vbyte[i] = VGM_BYTE_VALID;
1775 for (i = 0; i < 8192; i++)
1776 sm->abits[i] = VGM_BYTE_VALID;
1777
1778 /* Set up the primary map. */
1779 /* These entries gradually get overwritten as the used address
1780 space expands. */
1781 for (i = 0; i < N_PRIMARY_MAP; i++)
1782 primary_map[i] = &sm_distinguished[SM_DIST_NOACCESS];
1783
1784 /* auxmap_size = auxmap_used = 0;
1785 no ... these are statically initialised */
1786}
1787
1788
1789/*------------------------------------------------------------*/
1790/*--- Sanity check machinery (permanently engaged) ---*/
1791/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00001792
njn26f02512004-11-22 18:33:15 +00001793Bool TL_(cheap_sanity_check) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001794{
jseward9800fd32004-01-04 23:08:04 +00001795 /* nothing useful we can rapidly check */
sewardj23eb2fd2005-04-22 16:29:19 +00001796 n_sanity_cheap++;
sewardjc1a2cda2005-04-21 17:34:00 +00001797 PROF_EVENT(490, "cheap_sanity_check");
jseward9800fd32004-01-04 23:08:04 +00001798 return True;
njn25e49d8e72002-09-23 09:36:25 +00001799}
1800
njn26f02512004-11-22 18:33:15 +00001801Bool TL_(expensive_sanity_check) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001802{
sewardj23eb2fd2005-04-22 16:29:19 +00001803 Int i, n_secmaps_found;
sewardj45d94cc2005-04-20 14:44:11 +00001804 SecMap* sm;
sewardj23eb2fd2005-04-22 16:29:19 +00001805 Bool bad = False;
njn25e49d8e72002-09-23 09:36:25 +00001806
sewardj23eb2fd2005-04-22 16:29:19 +00001807 n_sanity_expensive++;
sewardjc1a2cda2005-04-21 17:34:00 +00001808 PROF_EVENT(491, "expensive_sanity_check");
1809
sewardj23eb2fd2005-04-22 16:29:19 +00001810 /* Check that the 3 distinguished SMs are still as they should
1811 be. */
njn25e49d8e72002-09-23 09:36:25 +00001812
sewardj45d94cc2005-04-20 14:44:11 +00001813 /* Check A invalid, V invalid. */
1814 sm = &sm_distinguished[SM_DIST_NOACCESS];
njn25e49d8e72002-09-23 09:36:25 +00001815 for (i = 0; i < 65536; i++)
sewardj45d94cc2005-04-20 14:44:11 +00001816 if (!(sm->vbyte[i] == VGM_BYTE_INVALID))
sewardj23eb2fd2005-04-22 16:29:19 +00001817 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00001818 for (i = 0; i < 8192; i++)
1819 if (!(sm->abits[i] == VGM_BYTE_INVALID))
sewardj23eb2fd2005-04-22 16:29:19 +00001820 bad = True;
njn25e49d8e72002-09-23 09:36:25 +00001821
sewardj45d94cc2005-04-20 14:44:11 +00001822 /* Check A valid, V invalid. */
1823 sm = &sm_distinguished[SM_DIST_ACCESS_UNDEFINED];
1824 for (i = 0; i < 65536; i++)
1825 if (!(sm->vbyte[i] == VGM_BYTE_INVALID))
sewardj23eb2fd2005-04-22 16:29:19 +00001826 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00001827 for (i = 0; i < 8192; i++)
1828 if (!(sm->abits[i] == VGM_BYTE_VALID))
sewardj23eb2fd2005-04-22 16:29:19 +00001829 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00001830
1831 /* Check A valid, V valid. */
1832 sm = &sm_distinguished[SM_DIST_ACCESS_DEFINED];
1833 for (i = 0; i < 65536; i++)
1834 if (!(sm->vbyte[i] == VGM_BYTE_VALID))
sewardj23eb2fd2005-04-22 16:29:19 +00001835 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00001836 for (i = 0; i < 8192; i++)
1837 if (!(sm->abits[i] == VGM_BYTE_VALID))
sewardj23eb2fd2005-04-22 16:29:19 +00001838 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00001839
sewardj23eb2fd2005-04-22 16:29:19 +00001840 if (bad) {
1841 VG_(printf)("memcheck expensive sanity: "
1842 "distinguished_secondaries have changed\n");
1843 return False;
1844 }
1845
1846 /* check nonsensical auxmap sizing */
sewardj45d94cc2005-04-20 14:44:11 +00001847 if (auxmap_used > auxmap_size)
sewardj23eb2fd2005-04-22 16:29:19 +00001848 bad = True;
1849
1850 if (bad) {
1851 VG_(printf)("memcheck expensive sanity: "
1852 "nonsensical auxmap sizing\n");
1853 return False;
1854 }
1855
1856 /* check that the number of secmaps issued matches the number that
1857 are reachable (iow, no secmap leaks) */
1858 n_secmaps_found = 0;
1859 for (i = 0; i < N_PRIMARY_MAP; i++) {
1860 if (primary_map[i] == NULL) {
1861 bad = True;
1862 } else {
1863 if (!is_distinguished_sm(primary_map[i]))
1864 n_secmaps_found++;
1865 }
1866 }
1867
1868 for (i = 0; i < auxmap_used; i++) {
1869 if (auxmap[i].sm == NULL) {
1870 bad = True;
1871 } else {
1872 if (!is_distinguished_sm(auxmap[i].sm))
1873 n_secmaps_found++;
1874 }
1875 }
1876
1877 if (n_secmaps_found != n_secmaps_issued)
1878 bad = True;
1879
1880 if (bad) {
1881 VG_(printf)("memcheck expensive sanity: "
1882 "apparent secmap leakage\n");
1883 return False;
1884 }
1885
1886 /* check that auxmap only covers address space that the primary
1887 doesn't */
1888
1889 for (i = 0; i < auxmap_used; i++)
1890 if (auxmap[i].base <= MAX_PRIMARY_ADDRESS)
1891 bad = True;
1892
1893 if (bad) {
1894 VG_(printf)("memcheck expensive sanity: "
1895 "auxmap covers wrong address space\n");
1896 return False;
1897 }
1898
1899 /* there is only one pointer to each secmap (expensive) */
njn25e49d8e72002-09-23 09:36:25 +00001900
1901 return True;
1902}
sewardj45d94cc2005-04-20 14:44:11 +00001903
njn25e49d8e72002-09-23 09:36:25 +00001904
njn25e49d8e72002-09-23 09:36:25 +00001905/*------------------------------------------------------------*/
njnd3040452003-05-19 15:04:06 +00001906/*--- Command line args ---*/
njn25e49d8e72002-09-23 09:36:25 +00001907/*------------------------------------------------------------*/
1908
njn43c799e2003-04-08 00:08:52 +00001909Bool MC_(clo_avoid_strlen_errors) = True;
njn43c799e2003-04-08 00:08:52 +00001910
njn26f02512004-11-22 18:33:15 +00001911Bool TL_(process_cmd_line_option)(Char* arg)
njn25e49d8e72002-09-23 09:36:25 +00001912{
njn45270a22005-03-27 01:00:11 +00001913 VG_BOOL_CLO(arg, "--avoid-strlen-errors", MC_(clo_avoid_strlen_errors))
njn25e49d8e72002-09-23 09:36:25 +00001914 else
njn43c799e2003-04-08 00:08:52 +00001915 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001916
1917 return True;
njn25e49d8e72002-09-23 09:36:25 +00001918}
1919
njn26f02512004-11-22 18:33:15 +00001920void TL_(print_usage)(void)
njn25e49d8e72002-09-23 09:36:25 +00001921{
njn3e884182003-04-15 13:03:23 +00001922 MAC_(print_common_usage)();
1923 VG_(printf)(
1924" --avoid-strlen-errors=no|yes suppress errs from inlined strlen [yes]\n"
1925 );
1926}
1927
njn26f02512004-11-22 18:33:15 +00001928void TL_(print_debug_usage)(void)
njn3e884182003-04-15 13:03:23 +00001929{
1930 MAC_(print_common_debug_usage)();
1931 VG_(printf)(
sewardj8ec2cfc2002-10-13 00:57:26 +00001932" --cleanup=no|yes improve after instrumentation? [yes]\n"
njn3e884182003-04-15 13:03:23 +00001933 );
njn25e49d8e72002-09-23 09:36:25 +00001934}
1935
nethercote8b76fe52004-11-08 19:20:09 +00001936/*------------------------------------------------------------*/
1937/*--- Client requests ---*/
1938/*------------------------------------------------------------*/
1939
1940/* Client block management:
1941
1942 This is managed as an expanding array of client block descriptors.
1943 Indices of live descriptors are issued to the client, so it can ask
1944 to free them later. Therefore we cannot slide live entries down
1945 over dead ones. Instead we must use free/inuse flags and scan for
1946 an empty slot at allocation time. This in turn means allocation is
1947 relatively expensive, so we hope this does not happen too often.
nethercote8b76fe52004-11-08 19:20:09 +00001948
sewardjedc75ab2005-03-15 23:30:32 +00001949 An unused block has start == size == 0
1950*/
nethercote8b76fe52004-11-08 19:20:09 +00001951
1952typedef
1953 struct {
1954 Addr start;
1955 SizeT size;
1956 ExeContext* where;
sewardjedc75ab2005-03-15 23:30:32 +00001957 Char* desc;
nethercote8b76fe52004-11-08 19:20:09 +00001958 }
1959 CGenBlock;
1960
1961/* This subsystem is self-initialising. */
njn695c16e2005-03-27 03:40:28 +00001962static UInt cgb_size = 0;
1963static UInt cgb_used = 0;
1964static CGenBlock* cgbs = NULL;
nethercote8b76fe52004-11-08 19:20:09 +00001965
1966/* Stats for this subsystem. */
njn695c16e2005-03-27 03:40:28 +00001967static UInt cgb_used_MAX = 0; /* Max in use. */
1968static UInt cgb_allocs = 0; /* Number of allocs. */
1969static UInt cgb_discards = 0; /* Number of discards. */
1970static UInt cgb_search = 0; /* Number of searches. */
nethercote8b76fe52004-11-08 19:20:09 +00001971
1972
1973static
njn695c16e2005-03-27 03:40:28 +00001974Int alloc_client_block ( void )
nethercote8b76fe52004-11-08 19:20:09 +00001975{
1976 UInt i, sz_new;
1977 CGenBlock* cgbs_new;
1978
njn695c16e2005-03-27 03:40:28 +00001979 cgb_allocs++;
nethercote8b76fe52004-11-08 19:20:09 +00001980
njn695c16e2005-03-27 03:40:28 +00001981 for (i = 0; i < cgb_used; i++) {
1982 cgb_search++;
1983 if (cgbs[i].start == 0 && cgbs[i].size == 0)
nethercote8b76fe52004-11-08 19:20:09 +00001984 return i;
1985 }
1986
1987 /* Not found. Try to allocate one at the end. */
njn695c16e2005-03-27 03:40:28 +00001988 if (cgb_used < cgb_size) {
1989 cgb_used++;
1990 return cgb_used-1;
nethercote8b76fe52004-11-08 19:20:09 +00001991 }
1992
1993 /* Ok, we have to allocate a new one. */
njn695c16e2005-03-27 03:40:28 +00001994 tl_assert(cgb_used == cgb_size);
1995 sz_new = (cgbs == NULL) ? 10 : (2 * cgb_size);
nethercote8b76fe52004-11-08 19:20:09 +00001996
1997 cgbs_new = VG_(malloc)( sz_new * sizeof(CGenBlock) );
njn695c16e2005-03-27 03:40:28 +00001998 for (i = 0; i < cgb_used; i++)
1999 cgbs_new[i] = cgbs[i];
nethercote8b76fe52004-11-08 19:20:09 +00002000
njn695c16e2005-03-27 03:40:28 +00002001 if (cgbs != NULL)
2002 VG_(free)( cgbs );
2003 cgbs = cgbs_new;
nethercote8b76fe52004-11-08 19:20:09 +00002004
njn695c16e2005-03-27 03:40:28 +00002005 cgb_size = sz_new;
2006 cgb_used++;
2007 if (cgb_used > cgb_used_MAX)
2008 cgb_used_MAX = cgb_used;
2009 return cgb_used-1;
nethercote8b76fe52004-11-08 19:20:09 +00002010}
2011
2012
2013static void show_client_block_stats ( void )
2014{
2015 VG_(message)(Vg_DebugMsg,
2016 "general CBs: %d allocs, %d discards, %d maxinuse, %d search",
njn695c16e2005-03-27 03:40:28 +00002017 cgb_allocs, cgb_discards, cgb_used_MAX, cgb_search
nethercote8b76fe52004-11-08 19:20:09 +00002018 );
2019}
2020
2021static Bool find_addr(VgHashNode* sh_ch, void* ap)
2022{
2023 MAC_Chunk *m = (MAC_Chunk*)sh_ch;
2024 Addr a = *(Addr*)ap;
2025
2026 return VG_(addr_is_in_block)(a, m->data, m->size);
2027}
2028
2029static Bool client_perm_maybe_describe( Addr a, AddrInfo* ai )
2030{
2031 UInt i;
2032 /* VG_(printf)("try to identify %d\n", a); */
2033
2034 /* Perhaps it's a general block ? */
njn695c16e2005-03-27 03:40:28 +00002035 for (i = 0; i < cgb_used; i++) {
2036 if (cgbs[i].start == 0 && cgbs[i].size == 0)
nethercote8b76fe52004-11-08 19:20:09 +00002037 continue;
njn695c16e2005-03-27 03:40:28 +00002038 if (VG_(addr_is_in_block)(a, cgbs[i].start, cgbs[i].size)) {
nethercote8b76fe52004-11-08 19:20:09 +00002039 MAC_Mempool **d, *mp;
2040
2041 /* OK - maybe it's a mempool, too? */
2042 mp = (MAC_Mempool*)VG_(HT_get_node)(MAC_(mempool_list),
njn695c16e2005-03-27 03:40:28 +00002043 (UWord)cgbs[i].start,
nethercote8b76fe52004-11-08 19:20:09 +00002044 (void*)&d);
2045 if(mp != NULL) {
2046 if(mp->chunks != NULL) {
2047 MAC_Chunk *mc;
2048
2049 mc = (MAC_Chunk*)VG_(HT_first_match)(mp->chunks, find_addr, &a);
2050 if(mc != NULL) {
2051 ai->akind = UserG;
2052 ai->blksize = mc->size;
2053 ai->rwoffset = (Int)(a) - (Int)mc->data;
2054 ai->lastchange = mc->where;
2055 return True;
2056 }
2057 }
2058 ai->akind = Mempool;
njn695c16e2005-03-27 03:40:28 +00002059 ai->blksize = cgbs[i].size;
2060 ai->rwoffset = (Int)(a) - (Int)(cgbs[i].start);
2061 ai->lastchange = cgbs[i].where;
nethercote8b76fe52004-11-08 19:20:09 +00002062 return True;
2063 }
2064 ai->akind = UserG;
njn695c16e2005-03-27 03:40:28 +00002065 ai->blksize = cgbs[i].size;
2066 ai->rwoffset = (Int)(a) - (Int)(cgbs[i].start);
2067 ai->lastchange = cgbs[i].where;
2068 ai->desc = cgbs[i].desc;
nethercote8b76fe52004-11-08 19:20:09 +00002069 return True;
2070 }
2071 }
2072 return False;
2073}
2074
njn26f02512004-11-22 18:33:15 +00002075Bool TL_(handle_client_request) ( ThreadId tid, UWord* arg, UWord* ret )
nethercote8b76fe52004-11-08 19:20:09 +00002076{
2077 Int i;
2078 Bool ok;
2079 Addr bad_addr;
2080
njnfc26ff92004-11-22 19:12:49 +00002081 if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
nethercote8b76fe52004-11-08 19:20:09 +00002082 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
2083 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
2084 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
2085 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
2086 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
2087 && VG_USERREQ__MEMPOOL_FREE != arg[0])
2088 return False;
2089
2090 switch (arg[0]) {
2091 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
2092 ok = mc_check_writable ( arg[1], arg[2], &bad_addr );
2093 if (!ok)
2094 MC_(record_user_error) ( tid, bad_addr, /*isWrite*/True,
2095 /*isUnaddr*/True );
2096 *ret = ok ? (UWord)NULL : bad_addr;
2097 break;
2098
2099 case VG_USERREQ__CHECK_READABLE: { /* check readable */
2100 MC_ReadResult res;
2101 res = mc_check_readable ( arg[1], arg[2], &bad_addr );
2102 if (MC_AddrErr == res)
2103 MC_(record_user_error) ( tid, bad_addr, /*isWrite*/False,
2104 /*isUnaddr*/True );
2105 else if (MC_ValueErr == res)
2106 MC_(record_user_error) ( tid, bad_addr, /*isWrite*/False,
2107 /*isUnaddr*/False );
2108 *ret = ( res==MC_Ok ? (UWord)NULL : bad_addr );
2109 break;
2110 }
2111
2112 case VG_USERREQ__DO_LEAK_CHECK:
njnb8dca862005-03-14 02:42:44 +00002113 mc_detect_memory_leaks(tid, arg[1] ? LC_Summary : LC_Full);
nethercote8b76fe52004-11-08 19:20:09 +00002114 *ret = 0; /* return value is meaningless */
2115 break;
2116
2117 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
nethercote8b76fe52004-11-08 19:20:09 +00002118 mc_make_noaccess ( arg[1], arg[2] );
sewardjedc75ab2005-03-15 23:30:32 +00002119 *ret = -1;
nethercote8b76fe52004-11-08 19:20:09 +00002120 break;
2121
2122 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
nethercote8b76fe52004-11-08 19:20:09 +00002123 mc_make_writable ( arg[1], arg[2] );
sewardjedc75ab2005-03-15 23:30:32 +00002124 *ret = -1;
nethercote8b76fe52004-11-08 19:20:09 +00002125 break;
2126
2127 case VG_USERREQ__MAKE_READABLE: /* make readable */
nethercote8b76fe52004-11-08 19:20:09 +00002128 mc_make_readable ( arg[1], arg[2] );
sewardjedc75ab2005-03-15 23:30:32 +00002129 *ret = -1;
nethercote8b76fe52004-11-08 19:20:09 +00002130 break;
2131
sewardjedc75ab2005-03-15 23:30:32 +00002132 case VG_USERREQ__CREATE_BLOCK: /* describe a block */
2133 if (arg[1] != 0 && arg[2] != 0) {
njn695c16e2005-03-27 03:40:28 +00002134 i = alloc_client_block();
2135 /* VG_(printf)("allocated %d %p\n", i, cgbs); */
2136 cgbs[i].start = arg[1];
2137 cgbs[i].size = arg[2];
2138 cgbs[i].desc = VG_(strdup)((Char *)arg[3]);
2139 cgbs[i].where = VG_(record_ExeContext) ( tid );
sewardjedc75ab2005-03-15 23:30:32 +00002140
2141 *ret = i;
2142 } else
2143 *ret = -1;
2144 break;
2145
nethercote8b76fe52004-11-08 19:20:09 +00002146 case VG_USERREQ__DISCARD: /* discard */
njn695c16e2005-03-27 03:40:28 +00002147 if (cgbs == NULL
2148 || arg[2] >= cgb_used ||
2149 (cgbs[arg[2]].start == 0 && cgbs[arg[2]].size == 0)) {
sewardjedc75ab2005-03-15 23:30:32 +00002150 *ret = 1;
2151 } else {
njn695c16e2005-03-27 03:40:28 +00002152 tl_assert(arg[2] >= 0 && arg[2] < cgb_used);
2153 cgbs[arg[2]].start = cgbs[arg[2]].size = 0;
2154 VG_(free)(cgbs[arg[2]].desc);
2155 cgb_discards++;
sewardjedc75ab2005-03-15 23:30:32 +00002156 *ret = 0;
2157 }
nethercote8b76fe52004-11-08 19:20:09 +00002158 break;
2159
sewardj45d94cc2005-04-20 14:44:11 +00002160//zz case VG_USERREQ__GET_VBITS:
2161//zz /* Returns: 1 == OK, 2 == alignment error, 3 == addressing
2162//zz error. */
2163//zz /* VG_(printf)("get_vbits %p %p %d\n", arg[1], arg[2], arg[3] ); */
2164//zz *ret = mc_get_or_set_vbits_for_client
2165//zz ( tid, arg[1], arg[2], arg[3], False /* get them */ );
2166//zz break;
2167//zz
2168//zz case VG_USERREQ__SET_VBITS:
2169//zz /* Returns: 1 == OK, 2 == alignment error, 3 == addressing
2170//zz error. */
2171//zz /* VG_(printf)("set_vbits %p %p %d\n", arg[1], arg[2], arg[3] ); */
2172//zz *ret = mc_get_or_set_vbits_for_client
2173//zz ( tid, arg[1], arg[2], arg[3], True /* set them */ );
2174//zz break;
nethercote8b76fe52004-11-08 19:20:09 +00002175
2176 default:
2177 if (MAC_(handle_common_client_requests)(tid, arg, ret )) {
2178 return True;
2179 } else {
2180 VG_(message)(Vg_UserMsg,
2181 "Warning: unknown memcheck client request code %llx",
2182 (ULong)arg[0]);
2183 return False;
2184 }
2185 }
2186 return True;
2187}
njn25e49d8e72002-09-23 09:36:25 +00002188
2189/*------------------------------------------------------------*/
2190/*--- Setup ---*/
2191/*------------------------------------------------------------*/
2192
njn26f02512004-11-22 18:33:15 +00002193void TL_(pre_clo_init)(void)
njn25e49d8e72002-09-23 09:36:25 +00002194{
njn810086f2002-11-14 12:42:47 +00002195 VG_(details_name) ("Memcheck");
2196 VG_(details_version) (NULL);
nethercote262eedf2003-11-13 17:57:18 +00002197 VG_(details_description) ("a memory error detector");
njn810086f2002-11-14 12:42:47 +00002198 VG_(details_copyright_author)(
njn53612422005-03-12 16:22:54 +00002199 "Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.");
nethercote421281e2003-11-20 16:20:55 +00002200 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardj9ebf9fd2004-11-28 16:56:51 +00002201 VG_(details_avg_translation_sizeB) ( 370 );
njn25e49d8e72002-09-23 09:36:25 +00002202
njn8a97c6d2005-03-31 04:37:24 +00002203 VG_(basic_tool_funcs) (TL_(post_clo_init),
2204 TL_(instrument),
2205 TL_(fini));
2206
njn810086f2002-11-14 12:42:47 +00002207 VG_(needs_core_errors) ();
njn8a97c6d2005-03-31 04:37:24 +00002208 VG_(needs_tool_errors) (TL_(eq_Error),
2209 TL_(pp_Error),
2210 TL_(update_extra),
2211 TL_(recognised_suppression),
2212 TL_(read_extra_suppression_info),
2213 TL_(error_matches_suppression),
2214 TL_(get_error_name),
2215 TL_(print_extra_suppression_info));
njn810086f2002-11-14 12:42:47 +00002216 VG_(needs_libc_freeres) ();
njn8a97c6d2005-03-31 04:37:24 +00002217 VG_(needs_command_line_options)(TL_(process_cmd_line_option),
2218 TL_(print_usage),
2219 TL_(print_debug_usage));
2220 VG_(needs_client_requests) (TL_(handle_client_request));
2221 VG_(needs_sanity_checks) (TL_(cheap_sanity_check),
2222 TL_(expensive_sanity_check));
fitzhardinge98abfc72003-12-16 02:05:15 +00002223 VG_(needs_shadow_memory) ();
njn25e49d8e72002-09-23 09:36:25 +00002224
njn8a97c6d2005-03-31 04:37:24 +00002225 VG_(malloc_funcs) (TL_(malloc),
2226 TL_(__builtin_new),
2227 TL_(__builtin_vec_new),
2228 TL_(memalign),
2229 TL_(calloc),
2230 TL_(free),
2231 TL_(__builtin_delete),
2232 TL_(__builtin_vec_delete),
2233 TL_(realloc),
2234 MALLOC_REDZONE_SZB );
2235
njn3e884182003-04-15 13:03:23 +00002236 MAC_( new_mem_heap) = & mc_new_mem_heap;
nethercote8b76fe52004-11-08 19:20:09 +00002237 MAC_( ban_mem_heap) = & mc_make_noaccess;
njn3e884182003-04-15 13:03:23 +00002238 MAC_(copy_mem_heap) = & mc_copy_address_range_state;
nethercote8b76fe52004-11-08 19:20:09 +00002239 MAC_( die_mem_heap) = & mc_make_noaccess;
2240 MAC_(check_noaccess) = & mc_check_noaccess;
njn3e884182003-04-15 13:03:23 +00002241
fitzhardinge98abfc72003-12-16 02:05:15 +00002242 VG_(init_new_mem_startup) ( & mc_new_mem_startup );
nethercote8b76fe52004-11-08 19:20:09 +00002243 VG_(init_new_mem_stack_signal) ( & mc_make_writable );
2244 VG_(init_new_mem_brk) ( & mc_make_writable );
njnb8dca862005-03-14 02:42:44 +00002245 VG_(init_new_mem_mmap) ( & mc_new_mem_mmap );
njn25e49d8e72002-09-23 09:36:25 +00002246
fitzhardinge98abfc72003-12-16 02:05:15 +00002247 VG_(init_copy_mem_remap) ( & mc_copy_address_range_state );
njn3e884182003-04-15 13:03:23 +00002248
nethercote8b76fe52004-11-08 19:20:09 +00002249 VG_(init_die_mem_stack_signal) ( & mc_make_noaccess );
2250 VG_(init_die_mem_brk) ( & mc_make_noaccess );
2251 VG_(init_die_mem_munmap) ( & mc_make_noaccess );
njn3e884182003-04-15 13:03:23 +00002252
fitzhardinge98abfc72003-12-16 02:05:15 +00002253 VG_(init_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
2254 VG_(init_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
2255 VG_(init_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
2256 VG_(init_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
2257 VG_(init_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
2258 VG_(init_new_mem_stack) ( & MAC_(new_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00002259
fitzhardinge98abfc72003-12-16 02:05:15 +00002260 VG_(init_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
2261 VG_(init_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
2262 VG_(init_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
2263 VG_(init_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
2264 VG_(init_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
2265 VG_(init_die_mem_stack) ( & MAC_(die_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00002266
nethercote8b76fe52004-11-08 19:20:09 +00002267 VG_(init_ban_mem_stack) ( & mc_make_noaccess );
njn25e49d8e72002-09-23 09:36:25 +00002268
fitzhardinge98abfc72003-12-16 02:05:15 +00002269 VG_(init_pre_mem_read) ( & mc_check_is_readable );
2270 VG_(init_pre_mem_read_asciiz) ( & mc_check_is_readable_asciiz );
2271 VG_(init_pre_mem_write) ( & mc_check_is_writable );
njncf45fd42004-11-24 16:30:22 +00002272 VG_(init_post_mem_write) ( & mc_post_mem_write );
nethercote8b76fe52004-11-08 19:20:09 +00002273
2274 VG_(init_pre_reg_read) ( & mc_pre_reg_read );
njn25e49d8e72002-09-23 09:36:25 +00002275
njncf45fd42004-11-24 16:30:22 +00002276 VG_(init_post_reg_write) ( & mc_post_reg_write );
fitzhardinge98abfc72003-12-16 02:05:15 +00002277 VG_(init_post_reg_write_clientcall_return) ( & mc_post_reg_write_clientcall );
njnd3040452003-05-19 15:04:06 +00002278
njn31066fd2005-03-26 00:42:02 +00002279 VG_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
2280 VG_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
2281 VG_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
njnd04b7c62002-10-03 14:05:52 +00002282
njn43c799e2003-04-08 00:08:52 +00002283 /* Additional block description for VG_(describe_addr)() */
nethercote8b76fe52004-11-08 19:20:09 +00002284 MAC_(describe_addr_supp) = client_perm_maybe_describe;
njn43c799e2003-04-08 00:08:52 +00002285
njnd04b7c62002-10-03 14:05:52 +00002286 init_shadow_memory();
njn3e884182003-04-15 13:03:23 +00002287 MAC_(common_pre_clo_init)();
sewardjc1a2cda2005-04-21 17:34:00 +00002288
2289 tl_assert( TL_(expensive_sanity_check)() );
njn5c004e42002-11-18 11:04:50 +00002290}
2291
njn26f02512004-11-22 18:33:15 +00002292void TL_(post_clo_init) ( void )
njn5c004e42002-11-18 11:04:50 +00002293{
2294}
2295
njn26f02512004-11-22 18:33:15 +00002296void TL_(fini) ( Int exitcode )
njn5c004e42002-11-18 11:04:50 +00002297{
nethercote8b76fe52004-11-08 19:20:09 +00002298 MAC_(common_fini)( mc_detect_memory_leaks );
sewardj45d94cc2005-04-20 14:44:11 +00002299
sewardj23eb2fd2005-04-22 16:29:19 +00002300 Int i, n_accessible_dist;
2301 SecMap* sm;
2302
sewardj45d94cc2005-04-20 14:44:11 +00002303 if (VG_(clo_verbosity) > 1) {
2304 VG_(message)(Vg_DebugMsg,
sewardj23eb2fd2005-04-22 16:29:19 +00002305 " memcheck: sanity checks: %d cheap, %d expensive",
2306 n_sanity_cheap, n_sanity_expensive );
sewardj45d94cc2005-04-20 14:44:11 +00002307 VG_(message)(Vg_DebugMsg,
sewardj23eb2fd2005-04-22 16:29:19 +00002308 " memcheck: auxmaps: %d auxmap entries (%dk, %dM) in use",
2309 auxmap_used,
2310 auxmap_used * 64,
2311 auxmap_used / 16 );
2312 VG_(message)(Vg_DebugMsg,
2313 " memcheck: auxmaps: %lld searches, %lld comparisons",
sewardj45d94cc2005-04-20 14:44:11 +00002314 n_auxmap_searches, n_auxmap_cmps );
sewardj23eb2fd2005-04-22 16:29:19 +00002315 VG_(message)(Vg_DebugMsg,
2316 " memcheck: secondaries: %d issued (%dk, %dM)",
2317 n_secmaps_issued,
2318 n_secmaps_issued * 64,
2319 n_secmaps_issued / 16 );
2320
2321 n_accessible_dist = 0;
2322 for (i = 0; i < N_PRIMARY_MAP; i++) {
2323 sm = primary_map[i];
2324 if (is_distinguished_sm(sm)
2325 && sm != &sm_distinguished[SM_DIST_NOACCESS])
2326 n_accessible_dist ++;
2327 }
2328 for (i = 0; i < auxmap_used; i++) {
2329 sm = auxmap[i].sm;
2330 if (is_distinguished_sm(sm)
2331 && sm != &sm_distinguished[SM_DIST_NOACCESS])
2332 n_accessible_dist ++;
2333 }
2334
2335 VG_(message)(Vg_DebugMsg,
2336 " memcheck: secondaries: %d accessible and distinguished (%dk, %dM)",
2337 n_accessible_dist,
2338 n_accessible_dist * 64,
2339 n_accessible_dist / 16 );
2340
sewardj45d94cc2005-04-20 14:44:11 +00002341 }
2342
njn5c004e42002-11-18 11:04:50 +00002343 if (0) {
2344 VG_(message)(Vg_DebugMsg,
2345 "------ Valgrind's client block stats follow ---------------" );
nethercote8b76fe52004-11-08 19:20:09 +00002346 show_client_block_stats();
njn5c004e42002-11-18 11:04:50 +00002347 }
njn25e49d8e72002-09-23 09:36:25 +00002348}
2349
njn26f02512004-11-22 18:33:15 +00002350VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 9./8)
fitzhardinge98abfc72003-12-16 02:05:15 +00002351
njn25e49d8e72002-09-23 09:36:25 +00002352/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00002353/*--- end mc_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00002354/*--------------------------------------------------------------------*/