blob: 94667c8137ff5b253dac67e71f8be3bb78c86ee1 [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
nethercotebb1c9912004-01-04 16:43:23 +000012 Copyright (C) 2000-2004 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
njn25cac76cb2002-09-23 11:21:57 +000033#include "mc_include.h"
34#include "memcheck.h" /* for client requests */
njn25e49d8e72002-09-23 09:36:25 +000035//#include "vg_profile.c"
36
37/* Define to debug the mem audit system. */
38/* #define VG_DEBUG_MEMORY */
39
njn25e49d8e72002-09-23 09:36:25 +000040#define DEBUG(fmt, args...) //VG_(printf)(fmt, ## args)
41
42/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000043/*--- Low-level support for memory checking. ---*/
44/*------------------------------------------------------------*/
45
46/* All reads and writes are checked against a memory map, which
47 records the state of all memory in the process. The memory map is
48 organised like this:
49
50 The top 16 bits of an address are used to index into a top-level
51 map table, containing 65536 entries. Each entry is a pointer to a
52 second-level map, which records the accesibililty and validity
53 permissions for the 65536 bytes indexed by the lower 16 bits of the
54 address. Each byte is represented by nine bits, one indicating
55 accessibility, the other eight validity. So each second-level map
56 contains 73728 bytes. This two-level arrangement conveniently
57 divides the 4G address space into 64k lumps, each size 64k bytes.
58
59 All entries in the primary (top-level) map must point to a valid
60 secondary (second-level) map. Since most of the 4G of address
61 space will not be in use -- ie, not mapped at all -- there is a
62 distinguished secondary map, which indicates `not addressible and
63 not valid' writeable for all bytes. Entries in the primary map for
64 which the entire 64k is not in use at all point at this
65 distinguished map.
66
67 [...] lots of stuff deleted due to out of date-ness
68
69 As a final optimisation, the alignment and address checks for
70 4-byte loads and stores are combined in a neat way. The primary
71 map is extended to have 262144 entries (2^18), rather than 2^16.
72 The top 3/4 of these entries are permanently set to the
73 distinguished secondary map. For a 4-byte load/store, the
74 top-level map is indexed not with (addr >> 16) but instead f(addr),
75 where
76
77 f( XXXX XXXX XXXX XXXX ____ ____ ____ __YZ )
78 = ____ ____ ____ __YZ XXXX XXXX XXXX XXXX or
79 = ____ ____ ____ __ZY XXXX XXXX XXXX XXXX
80
81 ie the lowest two bits are placed above the 16 high address bits.
82 If either of these two bits are nonzero, the address is misaligned;
83 this will select a secondary map from the upper 3/4 of the primary
84 map. Because this is always the distinguished secondary map, a
85 (bogus) address check failure will result. The failure handling
86 code can then figure out whether this is a genuine addr check
87 failure or whether it is a possibly-legitimate access at a
88 misaligned address.
89*/
90
91
92/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000093/*--- Function declarations. ---*/
94/*------------------------------------------------------------*/
95
sewardj95448072004-11-22 20:19:51 +000096static ULong mc_rd_V8_SLOWLY ( Addr a );
97static UInt mc_rd_V4_SLOWLY ( Addr a );
98static UInt mc_rd_V2_SLOWLY ( Addr a );
99static UInt mc_rd_V1_SLOWLY ( Addr a );
100
101static void mc_wr_V8_SLOWLY ( Addr a, ULong vbytes );
njn5c004e42002-11-18 11:04:50 +0000102static void mc_wr_V4_SLOWLY ( Addr a, UInt vbytes );
103static void mc_wr_V2_SLOWLY ( Addr a, UInt vbytes );
104static void mc_wr_V1_SLOWLY ( Addr a, UInt vbytes );
sewardj95448072004-11-22 20:19:51 +0000105
njn25e49d8e72002-09-23 09:36:25 +0000106/*------------------------------------------------------------*/
107/*--- Data defns. ---*/
108/*------------------------------------------------------------*/
109
110typedef
111 struct {
112 UChar abits[8192];
113 UChar vbyte[65536];
114 }
115 SecMap;
116
117static SecMap* primary_map[ /*65536*/ 262144 ];
118static SecMap distinguished_secondary_map;
119
njn25e49d8e72002-09-23 09:36:25 +0000120static void init_shadow_memory ( void )
121{
122 Int i;
123
124 for (i = 0; i < 8192; i++) /* Invalid address */
125 distinguished_secondary_map.abits[i] = VGM_BYTE_INVALID;
126 for (i = 0; i < 65536; i++) /* Invalid Value */
127 distinguished_secondary_map.vbyte[i] = VGM_BYTE_INVALID;
128
129 /* These entries gradually get overwritten as the used address
130 space expands. */
131 for (i = 0; i < 65536; i++)
132 primary_map[i] = &distinguished_secondary_map;
133
134 /* These ones should never change; it's a bug in Valgrind if they do. */
135 for (i = 65536; i < 262144; i++)
136 primary_map[i] = &distinguished_secondary_map;
137}
138
njn25e49d8e72002-09-23 09:36:25 +0000139/*------------------------------------------------------------*/
140/*--- Basic bitmap management, reading and writing. ---*/
141/*------------------------------------------------------------*/
142
143/* Allocate and initialise a secondary map. */
144
145static SecMap* alloc_secondary_map ( __attribute__ ((unused))
146 Char* caller )
147{
148 SecMap* map;
149 UInt i;
150 PROF_EVENT(10);
151
152 /* Mark all bytes as invalid access and invalid value. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000153 map = (SecMap *)VG_(shadow_alloc)(sizeof(SecMap));
njn25e49d8e72002-09-23 09:36:25 +0000154
155 for (i = 0; i < 8192; i++)
156 map->abits[i] = VGM_BYTE_INVALID; /* Invalid address */
157 for (i = 0; i < 65536; i++)
158 map->vbyte[i] = VGM_BYTE_INVALID; /* Invalid Value */
159
160 /* VG_(printf)("ALLOC_2MAP(%s)\n", caller ); */
161 return map;
162}
163
164
165/* Basic reading/writing of the bitmaps, for byte-sized accesses. */
166
167static __inline__ UChar get_abit ( Addr a )
168{
169 SecMap* sm = primary_map[a >> 16];
170 UInt sm_off = a & 0xFFFF;
171 PROF_EVENT(20);
172# if 0
173 if (IS_DISTINGUISHED_SM(sm))
174 VG_(message)(Vg_DebugMsg,
175 "accessed distinguished 2ndary (A)map! 0x%x\n", a);
176# endif
177 return BITARR_TEST(sm->abits, sm_off)
178 ? VGM_BIT_INVALID : VGM_BIT_VALID;
179}
180
181static __inline__ UChar get_vbyte ( Addr a )
182{
183 SecMap* sm = primary_map[a >> 16];
184 UInt sm_off = a & 0xFFFF;
185 PROF_EVENT(21);
186# if 0
187 if (IS_DISTINGUISHED_SM(sm))
188 VG_(message)(Vg_DebugMsg,
189 "accessed distinguished 2ndary (V)map! 0x%x\n", a);
190# endif
191 return sm->vbyte[sm_off];
192}
193
sewardj56867352003-10-12 10:27:06 +0000194static /* __inline__ */ void set_abit ( Addr a, UChar abit )
njn25e49d8e72002-09-23 09:36:25 +0000195{
196 SecMap* sm;
197 UInt sm_off;
198 PROF_EVENT(22);
199 ENSURE_MAPPABLE(a, "set_abit");
200 sm = primary_map[a >> 16];
201 sm_off = a & 0xFFFF;
202 if (abit)
203 BITARR_SET(sm->abits, sm_off);
204 else
205 BITARR_CLEAR(sm->abits, sm_off);
206}
207
208static __inline__ void set_vbyte ( Addr a, UChar vbyte )
209{
210 SecMap* sm;
211 UInt sm_off;
212 PROF_EVENT(23);
213 ENSURE_MAPPABLE(a, "set_vbyte");
214 sm = primary_map[a >> 16];
215 sm_off = a & 0xFFFF;
216 sm->vbyte[sm_off] = vbyte;
217}
218
219
220/* Reading/writing of the bitmaps, for aligned word-sized accesses. */
221
222static __inline__ UChar get_abits4_ALIGNED ( Addr a )
223{
224 SecMap* sm;
225 UInt sm_off;
226 UChar abits8;
227 PROF_EVENT(24);
228# ifdef VG_DEBUG_MEMORY
njnca82cc02004-11-22 17:18:48 +0000229 tl_assert(IS_ALIGNED4_ADDR(a));
njn25e49d8e72002-09-23 09:36:25 +0000230# endif
231 sm = primary_map[a >> 16];
232 sm_off = a & 0xFFFF;
233 abits8 = sm->abits[sm_off >> 3];
234 abits8 >>= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
235 abits8 &= 0x0F;
236 return abits8;
237}
238
239static UInt __inline__ get_vbytes4_ALIGNED ( Addr a )
240{
241 SecMap* sm = primary_map[a >> 16];
242 UInt sm_off = a & 0xFFFF;
243 PROF_EVENT(25);
244# ifdef VG_DEBUG_MEMORY
njnca82cc02004-11-22 17:18:48 +0000245 tl_assert(IS_ALIGNED4_ADDR(a));
njn25e49d8e72002-09-23 09:36:25 +0000246# endif
247 return ((UInt*)(sm->vbyte))[sm_off >> 2];
248}
249
250
sewardjee070842003-07-05 17:53:55 +0000251static void __inline__ set_vbytes4_ALIGNED ( Addr a, UInt vbytes )
252{
253 SecMap* sm;
254 UInt sm_off;
255 ENSURE_MAPPABLE(a, "set_vbytes4_ALIGNED");
256 sm = primary_map[a >> 16];
257 sm_off = a & 0xFFFF;
258 PROF_EVENT(23);
259# ifdef VG_DEBUG_MEMORY
njnca82cc02004-11-22 17:18:48 +0000260 tl_assert(IS_ALIGNED4_ADDR(a));
sewardjee070842003-07-05 17:53:55 +0000261# endif
262 ((UInt*)(sm->vbyte))[sm_off >> 2] = vbytes;
263}
264
265
njn25e49d8e72002-09-23 09:36:25 +0000266/*------------------------------------------------------------*/
267/*--- Setting permissions over address ranges. ---*/
268/*------------------------------------------------------------*/
269
nethercote451eae92004-11-02 13:06:32 +0000270static void set_address_range_perms ( Addr a, SizeT len,
njn25e49d8e72002-09-23 09:36:25 +0000271 UInt example_a_bit,
272 UInt example_v_bit )
273{
274 UChar vbyte, abyte8;
275 UInt vword4, sm_off;
276 SecMap* sm;
277
278 PROF_EVENT(30);
279
280 if (len == 0)
281 return;
282
nethercotea66033c2004-03-08 15:37:58 +0000283 if (VG_(clo_verbosity) > 0) {
284 if (len > 100 * 1000 * 1000) {
285 VG_(message)(Vg_UserMsg,
286 "Warning: set address range perms: "
287 "large range %u, a %d, v %d",
288 len, example_a_bit, example_v_bit );
289 }
njn25e49d8e72002-09-23 09:36:25 +0000290 }
291
292 VGP_PUSHCC(VgpSetMem);
293
294 /* Requests to change permissions of huge address ranges may
295 indicate bugs in our machinery. 30,000,000 is arbitrary, but so
296 far all legitimate requests have fallen beneath that size. */
297 /* 4 Mar 02: this is just stupid; get rid of it. */
njnca82cc02004-11-22 17:18:48 +0000298 /* tl_assert(len < 30000000); */
njn25e49d8e72002-09-23 09:36:25 +0000299
300 /* Check the permissions make sense. */
njnca82cc02004-11-22 17:18:48 +0000301 tl_assert(example_a_bit == VGM_BIT_VALID
njn25e49d8e72002-09-23 09:36:25 +0000302 || example_a_bit == VGM_BIT_INVALID);
njnca82cc02004-11-22 17:18:48 +0000303 tl_assert(example_v_bit == VGM_BIT_VALID
njn25e49d8e72002-09-23 09:36:25 +0000304 || example_v_bit == VGM_BIT_INVALID);
305 if (example_a_bit == VGM_BIT_INVALID)
njnca82cc02004-11-22 17:18:48 +0000306 tl_assert(example_v_bit == VGM_BIT_INVALID);
njn25e49d8e72002-09-23 09:36:25 +0000307
308 /* The validity bits to write. */
309 vbyte = example_v_bit==VGM_BIT_VALID
310 ? VGM_BYTE_VALID : VGM_BYTE_INVALID;
311
312 /* In order that we can charge through the address space at 8
313 bytes/main-loop iteration, make up some perms. */
314 abyte8 = (example_a_bit << 7)
315 | (example_a_bit << 6)
316 | (example_a_bit << 5)
317 | (example_a_bit << 4)
318 | (example_a_bit << 3)
319 | (example_a_bit << 2)
320 | (example_a_bit << 1)
321 | (example_a_bit << 0);
322 vword4 = (vbyte << 24) | (vbyte << 16) | (vbyte << 8) | vbyte;
323
324# ifdef VG_DEBUG_MEMORY
325 /* Do it ... */
326 while (True) {
327 PROF_EVENT(31);
328 if (len == 0) break;
329 set_abit ( a, example_a_bit );
330 set_vbyte ( a, vbyte );
331 a++;
332 len--;
333 }
334
335# else
336 /* Slowly do parts preceding 8-byte alignment. */
337 while (True) {
338 PROF_EVENT(31);
339 if (len == 0) break;
340 if ((a % 8) == 0) break;
341 set_abit ( a, example_a_bit );
342 set_vbyte ( a, vbyte );
343 a++;
344 len--;
345 }
346
347 if (len == 0) {
348 VGP_POPCC(VgpSetMem);
349 return;
350 }
njnca82cc02004-11-22 17:18:48 +0000351 tl_assert((a % 8) == 0 && len > 0);
njn25e49d8e72002-09-23 09:36:25 +0000352
353 /* Once aligned, go fast. */
354 while (True) {
355 PROF_EVENT(32);
356 if (len < 8) break;
357 ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
358 sm = primary_map[a >> 16];
359 sm_off = a & 0xFFFF;
360 sm->abits[sm_off >> 3] = abyte8;
361 ((UInt*)(sm->vbyte))[(sm_off >> 2) + 0] = vword4;
362 ((UInt*)(sm->vbyte))[(sm_off >> 2) + 1] = vword4;
363 a += 8;
364 len -= 8;
365 }
366
367 if (len == 0) {
368 VGP_POPCC(VgpSetMem);
369 return;
370 }
njnca82cc02004-11-22 17:18:48 +0000371 tl_assert((a % 8) == 0 && len > 0 && len < 8);
njn25e49d8e72002-09-23 09:36:25 +0000372
373 /* Finish the upper fragment. */
374 while (True) {
375 PROF_EVENT(33);
376 if (len == 0) break;
377 set_abit ( a, example_a_bit );
378 set_vbyte ( a, vbyte );
379 a++;
380 len--;
381 }
382# endif
383
384 /* Check that zero page and highest page have not been written to
385 -- this could happen with buggy syscall wrappers. Today
386 (2001-04-26) had precisely such a problem with __NR_setitimer. */
njn26f02512004-11-22 18:33:15 +0000387 tl_assert(TL_(cheap_sanity_check)());
njn25e49d8e72002-09-23 09:36:25 +0000388 VGP_POPCC(VgpSetMem);
389}
390
391/* Set permissions for address ranges ... */
392
nethercote8b76fe52004-11-08 19:20:09 +0000393static void mc_make_noaccess ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000394{
395 PROF_EVENT(35);
nethercote8b76fe52004-11-08 19:20:09 +0000396 DEBUG("mc_make_noaccess(%p, %llu)\n", a, (ULong)len);
njn25e49d8e72002-09-23 09:36:25 +0000397 set_address_range_perms ( a, len, VGM_BIT_INVALID, VGM_BIT_INVALID );
398}
399
nethercote8b76fe52004-11-08 19:20:09 +0000400static void mc_make_writable ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000401{
402 PROF_EVENT(36);
nethercote8b76fe52004-11-08 19:20:09 +0000403 DEBUG("mc_make_writable(%p, %llu)\n", a, (ULong)len);
njn25e49d8e72002-09-23 09:36:25 +0000404 set_address_range_perms ( a, len, VGM_BIT_VALID, VGM_BIT_INVALID );
405}
406
nethercote8b76fe52004-11-08 19:20:09 +0000407static void mc_make_readable ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000408{
409 PROF_EVENT(37);
nethercote8b76fe52004-11-08 19:20:09 +0000410 DEBUG("mc_make_readable(%p, %llu)\n", a, (ULong)len);
njn25e49d8e72002-09-23 09:36:25 +0000411 set_address_range_perms ( a, len, VGM_BIT_VALID, VGM_BIT_VALID );
412}
413
njn9b007f62003-04-07 14:40:25 +0000414static __inline__
415void make_aligned_word_writable(Addr a)
416{
417 SecMap* sm;
418 UInt sm_off;
419 UChar mask;
njn25e49d8e72002-09-23 09:36:25 +0000420
njn9b007f62003-04-07 14:40:25 +0000421 VGP_PUSHCC(VgpESPAdj);
422 ENSURE_MAPPABLE(a, "make_aligned_word_writable");
423 sm = primary_map[a >> 16];
424 sm_off = a & 0xFFFF;
425 ((UInt*)(sm->vbyte))[sm_off >> 2] = VGM_WORD_INVALID;
426 mask = 0x0F;
427 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
428 /* mask now contains 1s where we wish to make address bits invalid (0s). */
429 sm->abits[sm_off >> 3] &= ~mask;
430 VGP_POPCC(VgpESPAdj);
431}
432
433static __inline__
434void make_aligned_word_noaccess(Addr a)
435{
436 SecMap* sm;
437 UInt sm_off;
438 UChar mask;
439
440 VGP_PUSHCC(VgpESPAdj);
441 ENSURE_MAPPABLE(a, "make_aligned_word_noaccess");
442 sm = primary_map[a >> 16];
443 sm_off = a & 0xFFFF;
444 ((UInt*)(sm->vbyte))[sm_off >> 2] = VGM_WORD_INVALID;
445 mask = 0x0F;
446 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
447 /* mask now contains 1s where we wish to make address bits invalid (1s). */
448 sm->abits[sm_off >> 3] |= mask;
449 VGP_POPCC(VgpESPAdj);
450}
451
452/* Nb: by "aligned" here we mean 8-byte aligned */
453static __inline__
454void make_aligned_doubleword_writable(Addr a)
455{
456 SecMap* sm;
457 UInt sm_off;
458
459 VGP_PUSHCC(VgpESPAdj);
460 ENSURE_MAPPABLE(a, "make_aligned_doubleword_writable");
461 sm = primary_map[a >> 16];
462 sm_off = a & 0xFFFF;
463 sm->abits[sm_off >> 3] = VGM_BYTE_VALID;
464 ((UInt*)(sm->vbyte))[(sm_off >> 2) + 0] = VGM_WORD_INVALID;
465 ((UInt*)(sm->vbyte))[(sm_off >> 2) + 1] = VGM_WORD_INVALID;
466 VGP_POPCC(VgpESPAdj);
467}
468
469static __inline__
470void make_aligned_doubleword_noaccess(Addr a)
471{
472 SecMap* sm;
473 UInt sm_off;
474
475 VGP_PUSHCC(VgpESPAdj);
476 ENSURE_MAPPABLE(a, "make_aligned_doubleword_noaccess");
477 sm = primary_map[a >> 16];
478 sm_off = a & 0xFFFF;
479 sm->abits[sm_off >> 3] = VGM_BYTE_INVALID;
480 ((UInt*)(sm->vbyte))[(sm_off >> 2) + 0] = VGM_WORD_INVALID;
481 ((UInt*)(sm->vbyte))[(sm_off >> 2) + 1] = VGM_WORD_INVALID;
482 VGP_POPCC(VgpESPAdj);
483}
484
485/* The %esp update handling functions */
486ESP_UPDATE_HANDLERS ( make_aligned_word_writable,
487 make_aligned_word_noaccess,
488 make_aligned_doubleword_writable,
489 make_aligned_doubleword_noaccess,
nethercote8b76fe52004-11-08 19:20:09 +0000490 mc_make_writable,
491 mc_make_noaccess
njn9b007f62003-04-07 14:40:25 +0000492 );
493
494/* Block-copy permissions (needed for implementing realloc()). */
nethercote451eae92004-11-02 13:06:32 +0000495static void mc_copy_address_range_state ( Addr src, Addr dst, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000496{
nethercote451eae92004-11-02 13:06:32 +0000497 SizeT i;
njn25e49d8e72002-09-23 09:36:25 +0000498
njn5c004e42002-11-18 11:04:50 +0000499 DEBUG("mc_copy_address_range_state\n");
njn25e49d8e72002-09-23 09:36:25 +0000500
501 PROF_EVENT(40);
502 for (i = 0; i < len; i++) {
503 UChar abit = get_abit ( src+i );
504 UChar vbyte = get_vbyte ( src+i );
505 PROF_EVENT(41);
506 set_abit ( dst+i, abit );
507 set_vbyte ( dst+i, vbyte );
508 }
509}
510
nethercote8b76fe52004-11-08 19:20:09 +0000511/*------------------------------------------------------------*/
512/*--- Checking memory ---*/
513/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000514
515/* Check permissions for address range. If inadequate permissions
516 exist, *bad_addr is set to the offending address, so the caller can
517 know what it is. */
518
sewardjecf8e102003-07-12 12:11:39 +0000519/* Returns True if [a .. a+len) is not addressible. Otherwise,
520 returns False, and if bad_addr is non-NULL, sets *bad_addr to
521 indicate the lowest failing address. Functions below are
522 similar. */
nethercote8b76fe52004-11-08 19:20:09 +0000523static Bool mc_check_noaccess ( Addr a, SizeT len, Addr* bad_addr )
sewardjecf8e102003-07-12 12:11:39 +0000524{
nethercote451eae92004-11-02 13:06:32 +0000525 SizeT i;
sewardjecf8e102003-07-12 12:11:39 +0000526 UChar abit;
527 PROF_EVENT(42);
528 for (i = 0; i < len; i++) {
529 PROF_EVENT(43);
530 abit = get_abit(a);
531 if (abit == VGM_BIT_VALID) {
532 if (bad_addr != NULL) *bad_addr = a;
533 return False;
534 }
535 a++;
536 }
537 return True;
538}
539
nethercote8b76fe52004-11-08 19:20:09 +0000540static Bool mc_check_writable ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000541{
nethercote451eae92004-11-02 13:06:32 +0000542 SizeT i;
njn25e49d8e72002-09-23 09:36:25 +0000543 UChar abit;
544 PROF_EVENT(42);
545 for (i = 0; i < len; i++) {
546 PROF_EVENT(43);
547 abit = get_abit(a);
548 if (abit == VGM_BIT_INVALID) {
549 if (bad_addr != NULL) *bad_addr = a;
550 return False;
551 }
552 a++;
553 }
554 return True;
555}
556
nethercote8b76fe52004-11-08 19:20:09 +0000557typedef enum {
558 MC_Ok = 5, MC_AddrErr = 6, MC_ValueErr = 7
559} MC_ReadResult;
560
561static MC_ReadResult mc_check_readable ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000562{
nethercote451eae92004-11-02 13:06:32 +0000563 SizeT i;
njn25e49d8e72002-09-23 09:36:25 +0000564 UChar abit;
565 UChar vbyte;
566
567 PROF_EVENT(44);
nethercote8b76fe52004-11-08 19:20:09 +0000568 DEBUG("mc_check_readable\n");
njn25e49d8e72002-09-23 09:36:25 +0000569 for (i = 0; i < len; i++) {
570 abit = get_abit(a);
571 vbyte = get_vbyte(a);
572 PROF_EVENT(45);
nethercote8b76fe52004-11-08 19:20:09 +0000573 // Report addressability errors in preference to definedness errors
574 // by checking the A bits first.
575 if (abit != VGM_BIT_VALID) {
njn25e49d8e72002-09-23 09:36:25 +0000576 if (bad_addr != NULL) *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +0000577 return MC_AddrErr;
578 }
579 if (vbyte != VGM_BYTE_VALID) {
580 if (bad_addr != NULL) *bad_addr = a;
581 return MC_ValueErr;
njn25e49d8e72002-09-23 09:36:25 +0000582 }
583 a++;
584 }
nethercote8b76fe52004-11-08 19:20:09 +0000585 return MC_Ok;
njn25e49d8e72002-09-23 09:36:25 +0000586}
587
588
589/* Check a zero-terminated ascii string. Tricky -- don't want to
590 examine the actual bytes, to find the end, until we're sure it is
591 safe to do so. */
592
njn9b007f62003-04-07 14:40:25 +0000593static Bool mc_check_readable_asciiz ( Addr a, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000594{
595 UChar abit;
596 UChar vbyte;
597 PROF_EVENT(46);
njn5c004e42002-11-18 11:04:50 +0000598 DEBUG("mc_check_readable_asciiz\n");
njn25e49d8e72002-09-23 09:36:25 +0000599 while (True) {
600 PROF_EVENT(47);
601 abit = get_abit(a);
602 vbyte = get_vbyte(a);
nethercote8b76fe52004-11-08 19:20:09 +0000603 // As in mc_check_readable(), check A bits first
604 if (abit != VGM_BIT_VALID) {
njn25e49d8e72002-09-23 09:36:25 +0000605 if (bad_addr != NULL) *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +0000606 return MC_AddrErr;
607 }
608 if (vbyte != VGM_BYTE_VALID) {
609 if (bad_addr != NULL) *bad_addr = a;
610 return MC_ValueErr;
njn25e49d8e72002-09-23 09:36:25 +0000611 }
612 /* Ok, a is safe to read. */
nethercote8b76fe52004-11-08 19:20:09 +0000613 if (* ((UChar*)a) == 0) return MC_Ok;
njn25e49d8e72002-09-23 09:36:25 +0000614 a++;
615 }
616}
617
618
619/*------------------------------------------------------------*/
620/*--- Memory event handlers ---*/
621/*------------------------------------------------------------*/
622
njn25e49d8e72002-09-23 09:36:25 +0000623static
njn72718642003-07-24 08:45:32 +0000624void mc_check_is_writable ( CorePart part, ThreadId tid, Char* s,
nethercote451eae92004-11-02 13:06:32 +0000625 Addr base, SizeT size )
njn25e49d8e72002-09-23 09:36:25 +0000626{
627 Bool ok;
628 Addr bad_addr;
629
630 VGP_PUSHCC(VgpCheckMem);
631
632 /* VG_(message)(Vg_DebugMsg,"check is writable: %x .. %x",
633 base,base+size-1); */
nethercote8b76fe52004-11-08 19:20:09 +0000634 ok = mc_check_writable ( base, size, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000635 if (!ok) {
636 switch (part) {
637 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +0000638 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
639 /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000640 break;
641
642 case Vg_CorePThread:
643 case Vg_CoreSignal:
nethercote8b76fe52004-11-08 19:20:09 +0000644 MAC_(record_core_mem_error)( tid, /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000645 break;
646
647 default:
njn67993252004-11-22 18:02:32 +0000648 VG_(tool_panic)("mc_check_is_writable: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +0000649 }
650 }
651
652 VGP_POPCC(VgpCheckMem);
653}
654
655static
njn72718642003-07-24 08:45:32 +0000656void mc_check_is_readable ( CorePart part, ThreadId tid, Char* s,
nethercote451eae92004-11-02 13:06:32 +0000657 Addr base, SizeT size )
njn25e49d8e72002-09-23 09:36:25 +0000658{
njn25e49d8e72002-09-23 09:36:25 +0000659 Addr bad_addr;
nethercote8b76fe52004-11-08 19:20:09 +0000660 MC_ReadResult res;
njn25e49d8e72002-09-23 09:36:25 +0000661
662 VGP_PUSHCC(VgpCheckMem);
663
664 /* VG_(message)(Vg_DebugMsg,"check is readable: %x .. %x",
665 base,base+size-1); */
nethercote8b76fe52004-11-08 19:20:09 +0000666 res = mc_check_readable ( base, size, &bad_addr );
667 if (MC_Ok != res) {
668 Bool isUnaddr = ( MC_AddrErr == res ? True : False );
669
njn25e49d8e72002-09-23 09:36:25 +0000670 switch (part) {
671 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +0000672 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
673 isUnaddr, s );
njn25e49d8e72002-09-23 09:36:25 +0000674 break;
675
676 case Vg_CorePThread:
nethercote8b76fe52004-11-08 19:20:09 +0000677 MAC_(record_core_mem_error)( tid, isUnaddr, s );
njn25e49d8e72002-09-23 09:36:25 +0000678 break;
679
680 /* If we're being asked to jump to a silly address, record an error
681 message before potentially crashing the entire system. */
682 case Vg_CoreTranslate:
njn72718642003-07-24 08:45:32 +0000683 MAC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000684 break;
685
686 default:
njn67993252004-11-22 18:02:32 +0000687 VG_(tool_panic)("mc_check_is_readable: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +0000688 }
689 }
690 VGP_POPCC(VgpCheckMem);
691}
692
693static
njn72718642003-07-24 08:45:32 +0000694void mc_check_is_readable_asciiz ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000695 Char* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +0000696{
nethercote8b76fe52004-11-08 19:20:09 +0000697 MC_ReadResult res;
njn25e49d8e72002-09-23 09:36:25 +0000698 Addr bad_addr;
699 /* VG_(message)(Vg_DebugMsg,"check is readable asciiz: 0x%x",str); */
700
701 VGP_PUSHCC(VgpCheckMem);
702
njnca82cc02004-11-22 17:18:48 +0000703 tl_assert(part == Vg_CoreSysCall);
nethercote8b76fe52004-11-08 19:20:09 +0000704 res = mc_check_readable_asciiz ( (Addr)str, &bad_addr );
705 if (MC_Ok != res) {
706 Bool isUnaddr = ( MC_AddrErr == res ? True : False );
707 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False, isUnaddr, s );
njn25e49d8e72002-09-23 09:36:25 +0000708 }
709
710 VGP_POPCC(VgpCheckMem);
711}
712
713
714static
nethercote451eae92004-11-02 13:06:32 +0000715void mc_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +0000716{
njn1f3a9092002-10-04 09:22:30 +0000717 /* Ignore the permissions, just make it readable. Seems to work... */
nethercote451eae92004-11-02 13:06:32 +0000718 DEBUG("mc_new_mem_startup(%p, %llu, rr=%u, ww=%u, xx=%u)\n",
719 a,(ULong)len,rr,ww,xx);
nethercote8b76fe52004-11-08 19:20:09 +0000720 mc_make_readable(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000721}
722
723static
nethercote451eae92004-11-02 13:06:32 +0000724void mc_new_mem_heap ( Addr a, SizeT len, Bool is_inited )
njn25e49d8e72002-09-23 09:36:25 +0000725{
726 if (is_inited) {
nethercote8b76fe52004-11-08 19:20:09 +0000727 mc_make_readable(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000728 } else {
nethercote8b76fe52004-11-08 19:20:09 +0000729 mc_make_writable(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000730 }
731}
732
733static
nethercote451eae92004-11-02 13:06:32 +0000734void mc_set_perms (Addr a, SizeT len, Bool rr, Bool ww, Bool xx)
njn25e49d8e72002-09-23 09:36:25 +0000735{
nethercote451eae92004-11-02 13:06:32 +0000736 DEBUG("mc_set_perms(%p, %llu, rr=%u ww=%u, xx=%u)\n",
737 a, (ULong)len, rr, ww, xx);
nethercote8b76fe52004-11-08 19:20:09 +0000738 if (rr) mc_make_readable(a, len);
739 else if (ww) mc_make_writable(a, len);
740 else mc_make_noaccess(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000741}
742
743
744/*------------------------------------------------------------*/
njnd3040452003-05-19 15:04:06 +0000745/*--- Register event handlers ---*/
746/*------------------------------------------------------------*/
747
748static void mc_post_regs_write_init ( void )
749{
sewardj95448072004-11-22 20:19:51 +0000750#if 0
njnd3040452003-05-19 15:04:06 +0000751 UInt i;
nethercotec06e2132004-09-03 13:45:29 +0000752 for (i = FIRST_ARCH_REG; i <= LAST_ARCH_REG; i++)
njnd3040452003-05-19 15:04:06 +0000753 VG_(set_shadow_archreg)( i, VGM_WORD_VALID );
754 VG_(set_shadow_eflags)( VGM_EFLAGS_VALID );
sewardj95448072004-11-22 20:19:51 +0000755#endif
njnd3040452003-05-19 15:04:06 +0000756}
757
758static void mc_post_reg_write(ThreadId tid, UInt reg)
759{
sewardj084a4e82004-11-22 20:51:49 +0000760 VGA_(set_thread_shadow_archreg)( tid, reg, VGM_WORD_VALID );
njnd3040452003-05-19 15:04:06 +0000761}
762
763static void mc_post_reg_write_clientcall(ThreadId tid, UInt reg, Addr f )
764{
sewardj084a4e82004-11-22 20:51:49 +0000765 VGA_(set_thread_shadow_archreg)( tid, reg, VGM_WORD_VALID );
njnd3040452003-05-19 15:04:06 +0000766}
767
nethercote8b76fe52004-11-08 19:20:09 +0000768static void mc_pre_reg_read(CorePart part, ThreadId tid, Char* s, UInt reg,
769 SizeT size)
770{
771 UWord mask;
772
773 // XXX: the only one at the moment
njnca82cc02004-11-22 17:18:48 +0000774 tl_assert(Vg_CoreSysCall == part);
nethercote8b76fe52004-11-08 19:20:09 +0000775
776 switch (size) {
777 case 4: mask = 0xffffffff; break;
778 case 2: mask = 0xffff; break;
779 case 1: mask = 0xff; break;
njn67993252004-11-22 18:02:32 +0000780 default: VG_(tool_panic)("Unhandled size in mc_pre_reg_read");
nethercote8b76fe52004-11-08 19:20:09 +0000781 }
782
sewardj084a4e82004-11-22 20:51:49 +0000783 if (VGM_WORD_VALID != (mask & VGA_(get_thread_shadow_archreg)( tid, reg )) )
nethercote8b76fe52004-11-08 19:20:09 +0000784 MAC_(record_param_error) ( tid, 0, /*isReg*/True, /*isUnaddr*/False, s );
785}
njnd3040452003-05-19 15:04:06 +0000786
787/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000788/*--- Functions called directly from generated code. ---*/
789/*------------------------------------------------------------*/
790
791static __inline__ UInt rotateRight16 ( UInt x )
792{
793 /* Amazingly, gcc turns this into a single rotate insn. */
794 return (x >> 16) | (x << 16);
795}
796
797
798static __inline__ UInt shiftRight16 ( UInt x )
799{
800 return x >> 16;
801}
802
803
sewardj95448072004-11-22 20:19:51 +0000804/* Read/write 1/2/4/8 sized V bytes, and emit an address error if
njn25e49d8e72002-09-23 09:36:25 +0000805 needed. */
806
sewardj95448072004-11-22 20:19:51 +0000807/* MC_(helperc_{LD,ST}V{1,2,4,8}) handle the common case fast.
njn25e49d8e72002-09-23 09:36:25 +0000808 Under all other circumstances, it defers to the relevant _SLOWLY
809 function, which can handle all situations.
810*/
sewardj95448072004-11-22 20:19:51 +0000811
812/* ------------------------ Size = 8 ------------------------ */
813
814REGPARM(1)
815ULong MC_(helperc_LOADV8) ( Addr a )
816{
817# ifdef VG_DEBUG_MEMORY
818 return mc_rd_V8_SLOWLY(a);
819# else
820 if (IS_ALIGNED8_ADDR(a)) {
821 UInt sec_no = shiftRight16(a) & 0xFFFF;
822 SecMap* sm = primary_map[sec_no];
823 UInt a_off = (a & 0xFFFF) >> 3;
824 UChar abits = sm->abits[a_off];
825 if (abits == VGM_BYTE_VALID) {
826 /* a is 8-aligned, mapped, and addressible. */
827 UInt v_off = a & 0xFFFF;
828 /* LITTLE-ENDIAN */
829 UInt vLo = ((UInt*)(sm->vbyte))[ (v_off >> 2) ];
830 UInt vHi = ((UInt*)(sm->vbyte))[ (v_off >> 2) + 1 ];
831 return ( ((ULong)vHi) << 32 ) | ((ULong)vLo);
832 } else {
833 return mc_rd_V8_SLOWLY(a);
834 }
835 }
836 else
837 if (IS_ALIGNED4_ADDR(a)) {
838 /* LITTLE-ENDIAN */
839 UInt vLo = MC_(helperc_LOADV4)(a+0);
840 UInt vHi = MC_(helperc_LOADV4)(a+4);
841 return ( ((ULong)vHi) << 32 ) | ((ULong)vLo);
842 }
843 else
844 return mc_rd_V8_SLOWLY(a);
845# endif
846}
847
848REGPARM(1)
849void MC_(helperc_STOREV8) ( Addr a, ULong vbytes )
850{
851# ifdef VG_DEBUG_MEMORY
852 mc_wr_V8_SLOWLY(a, vbytes);
853# else
854 if (IS_ALIGNED8_ADDR(a)) {
855 UInt sec_no = shiftRight16(a) & 0xFFFF;
856 SecMap* sm = primary_map[sec_no];
857 UInt a_off = (a & 0xFFFF) >> 3;
858 UChar abits = sm->abits[a_off];
859 if (abits == VGM_BYTE_VALID) {
860 /* a is 8-aligned, mapped, and addressible. */
861 UInt v_off = a & 0xFFFF;
862 UInt vHi = (UInt)(vbytes >> 32);
863 UInt vLo = (UInt)vbytes;
864 /* LITTLE-ENDIAN */
865 ((UInt*)(sm->vbyte))[ (v_off >> 2) ] = vLo;
866 ((UInt*)(sm->vbyte))[ (v_off >> 2) + 1 ] = vHi;
867 } else {
868 mc_wr_V8_SLOWLY(a, vbytes);
869 }
870 return;
871 }
872 else
873 if (IS_ALIGNED4_ADDR(a)) {
874 UInt vHi = (UInt)(vbytes >> 32);
875 UInt vLo = (UInt)vbytes;
876 /* LITTLE-ENDIAN */
877 MC_(helperc_STOREV4)(a+0, vLo);
878 MC_(helperc_STOREV4)(a+4, vHi);
879 return;
880 }
881 else
882 mc_wr_V8_SLOWLY(a, vbytes);
883# endif
884}
885
886/* ------------------------ Size = 4 ------------------------ */
887
nethercoteeec46302004-08-23 15:06:23 +0000888REGPARM(1)
njn5c004e42002-11-18 11:04:50 +0000889UInt MC_(helperc_LOADV4) ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +0000890{
891# ifdef VG_DEBUG_MEMORY
njn5c004e42002-11-18 11:04:50 +0000892 return mc_rd_V4_SLOWLY(a);
njn25e49d8e72002-09-23 09:36:25 +0000893# else
894 UInt sec_no = rotateRight16(a) & 0x3FFFF;
895 SecMap* sm = primary_map[sec_no];
896 UInt a_off = (a & 0xFFFF) >> 3;
897 UChar abits = sm->abits[a_off];
898 abits >>= (a & 4);
899 abits &= 15;
900 PROF_EVENT(60);
901 if (abits == VGM_NIBBLE_VALID) {
902 /* Handle common case quickly: a is suitably aligned, is mapped,
903 and is addressible. */
904 UInt v_off = a & 0xFFFF;
905 return ((UInt*)(sm->vbyte))[ v_off >> 2 ];
906 } else {
907 /* Slow but general case. */
njn5c004e42002-11-18 11:04:50 +0000908 return mc_rd_V4_SLOWLY(a);
njn25e49d8e72002-09-23 09:36:25 +0000909 }
910# endif
911}
912
nethercoteeec46302004-08-23 15:06:23 +0000913REGPARM(2)
njn5c004e42002-11-18 11:04:50 +0000914void MC_(helperc_STOREV4) ( Addr a, UInt vbytes )
njn25e49d8e72002-09-23 09:36:25 +0000915{
916# ifdef VG_DEBUG_MEMORY
njn5c004e42002-11-18 11:04:50 +0000917 mc_wr_V4_SLOWLY(a, vbytes);
njn25e49d8e72002-09-23 09:36:25 +0000918# else
919 UInt sec_no = rotateRight16(a) & 0x3FFFF;
920 SecMap* sm = primary_map[sec_no];
921 UInt a_off = (a & 0xFFFF) >> 3;
922 UChar abits = sm->abits[a_off];
923 abits >>= (a & 4);
924 abits &= 15;
925 PROF_EVENT(61);
926 if (abits == VGM_NIBBLE_VALID) {
927 /* Handle common case quickly: a is suitably aligned, is mapped,
928 and is addressible. */
929 UInt v_off = a & 0xFFFF;
930 ((UInt*)(sm->vbyte))[ v_off >> 2 ] = vbytes;
931 } else {
932 /* Slow but general case. */
njn5c004e42002-11-18 11:04:50 +0000933 mc_wr_V4_SLOWLY(a, vbytes);
njn25e49d8e72002-09-23 09:36:25 +0000934 }
935# endif
936}
937
sewardj95448072004-11-22 20:19:51 +0000938/* ------------------------ Size = 2 ------------------------ */
939
nethercoteeec46302004-08-23 15:06:23 +0000940REGPARM(1)
njn5c004e42002-11-18 11:04:50 +0000941UInt MC_(helperc_LOADV2) ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +0000942{
943# ifdef VG_DEBUG_MEMORY
njn5c004e42002-11-18 11:04:50 +0000944 return mc_rd_V2_SLOWLY(a);
njn25e49d8e72002-09-23 09:36:25 +0000945# else
946 UInt sec_no = rotateRight16(a) & 0x1FFFF;
947 SecMap* sm = primary_map[sec_no];
948 UInt a_off = (a & 0xFFFF) >> 3;
949 PROF_EVENT(62);
950 if (sm->abits[a_off] == VGM_BYTE_VALID) {
951 /* Handle common case quickly. */
952 UInt v_off = a & 0xFFFF;
953 return 0xFFFF0000
954 |
955 (UInt)( ((UShort*)(sm->vbyte))[ v_off >> 1 ] );
956 } else {
957 /* Slow but general case. */
njn5c004e42002-11-18 11:04:50 +0000958 return mc_rd_V2_SLOWLY(a);
njn25e49d8e72002-09-23 09:36:25 +0000959 }
960# endif
961}
962
nethercoteeec46302004-08-23 15:06:23 +0000963REGPARM(2)
njn5c004e42002-11-18 11:04:50 +0000964void MC_(helperc_STOREV2) ( Addr a, UInt vbytes )
njn25e49d8e72002-09-23 09:36:25 +0000965{
966# ifdef VG_DEBUG_MEMORY
njn5c004e42002-11-18 11:04:50 +0000967 mc_wr_V2_SLOWLY(a, vbytes);
njn25e49d8e72002-09-23 09:36:25 +0000968# else
969 UInt sec_no = rotateRight16(a) & 0x1FFFF;
970 SecMap* sm = primary_map[sec_no];
971 UInt a_off = (a & 0xFFFF) >> 3;
972 PROF_EVENT(63);
973 if (sm->abits[a_off] == VGM_BYTE_VALID) {
974 /* Handle common case quickly. */
975 UInt v_off = a & 0xFFFF;
976 ((UShort*)(sm->vbyte))[ v_off >> 1 ] = vbytes & 0x0000FFFF;
977 } else {
978 /* Slow but general case. */
njn5c004e42002-11-18 11:04:50 +0000979 mc_wr_V2_SLOWLY(a, vbytes);
njn25e49d8e72002-09-23 09:36:25 +0000980 }
981# endif
982}
983
sewardj95448072004-11-22 20:19:51 +0000984/* ------------------------ Size = 1 ------------------------ */
985
nethercoteeec46302004-08-23 15:06:23 +0000986REGPARM(1)
njn5c004e42002-11-18 11:04:50 +0000987UInt MC_(helperc_LOADV1) ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +0000988{
989# ifdef VG_DEBUG_MEMORY
njn5c004e42002-11-18 11:04:50 +0000990 return mc_rd_V1_SLOWLY(a);
njn25e49d8e72002-09-23 09:36:25 +0000991# else
992 UInt sec_no = shiftRight16(a);
993 SecMap* sm = primary_map[sec_no];
994 UInt a_off = (a & 0xFFFF) >> 3;
995 PROF_EVENT(64);
996 if (sm->abits[a_off] == VGM_BYTE_VALID) {
997 /* Handle common case quickly. */
998 UInt v_off = a & 0xFFFF;
999 return 0xFFFFFF00
1000 |
1001 (UInt)( ((UChar*)(sm->vbyte))[ v_off ] );
1002 } else {
1003 /* Slow but general case. */
njn5c004e42002-11-18 11:04:50 +00001004 return mc_rd_V1_SLOWLY(a);
njn25e49d8e72002-09-23 09:36:25 +00001005 }
1006# endif
1007}
1008
nethercoteeec46302004-08-23 15:06:23 +00001009REGPARM(2)
njn5c004e42002-11-18 11:04:50 +00001010void MC_(helperc_STOREV1) ( Addr a, UInt vbytes )
njn25e49d8e72002-09-23 09:36:25 +00001011{
1012# ifdef VG_DEBUG_MEMORY
njn5c004e42002-11-18 11:04:50 +00001013 mc_wr_V1_SLOWLY(a, vbytes);
njn25e49d8e72002-09-23 09:36:25 +00001014# else
1015 UInt sec_no = shiftRight16(a);
1016 SecMap* sm = primary_map[sec_no];
1017 UInt a_off = (a & 0xFFFF) >> 3;
1018 PROF_EVENT(65);
1019 if (sm->abits[a_off] == VGM_BYTE_VALID) {
1020 /* Handle common case quickly. */
1021 UInt v_off = a & 0xFFFF;
1022 ((UChar*)(sm->vbyte))[ v_off ] = vbytes & 0x000000FF;
1023 } else {
1024 /* Slow but general case. */
njn5c004e42002-11-18 11:04:50 +00001025 mc_wr_V1_SLOWLY(a, vbytes);
njn25e49d8e72002-09-23 09:36:25 +00001026 }
1027# endif
1028}
1029
1030
1031/*------------------------------------------------------------*/
1032/*--- Fallback functions to handle cases that the above ---*/
sewardj95448072004-11-22 20:19:51 +00001033/*--- VG_(helperc_{LD,ST}V{1,2,4,8}) can't manage. ---*/
njn25e49d8e72002-09-23 09:36:25 +00001034/*------------------------------------------------------------*/
1035
sewardj95448072004-11-22 20:19:51 +00001036/* ------------------------ Size = 8 ------------------------ */
1037
1038static ULong mc_rd_V8_SLOWLY ( Addr a )
1039{
1040 Bool a0ok, a1ok, a2ok, a3ok, a4ok, a5ok, a6ok, a7ok;
1041 UInt vb0, vb1, vb2, vb3, vb4, vb5, vb6, vb7;
1042
1043 PROF_EVENT(70);
1044
1045 /* First establish independently the addressibility of the 4 bytes
1046 involved. */
1047 a0ok = get_abit(a+0) == VGM_BIT_VALID;
1048 a1ok = get_abit(a+1) == VGM_BIT_VALID;
1049 a2ok = get_abit(a+2) == VGM_BIT_VALID;
1050 a3ok = get_abit(a+3) == VGM_BIT_VALID;
1051 a4ok = get_abit(a+4) == VGM_BIT_VALID;
1052 a5ok = get_abit(a+5) == VGM_BIT_VALID;
1053 a6ok = get_abit(a+6) == VGM_BIT_VALID;
1054 a7ok = get_abit(a+7) == VGM_BIT_VALID;
1055
1056 /* Also get the validity bytes for the address. */
1057 vb0 = (UInt)get_vbyte(a+0);
1058 vb1 = (UInt)get_vbyte(a+1);
1059 vb2 = (UInt)get_vbyte(a+2);
1060 vb3 = (UInt)get_vbyte(a+3);
1061 vb4 = (UInt)get_vbyte(a+4);
1062 vb5 = (UInt)get_vbyte(a+5);
1063 vb6 = (UInt)get_vbyte(a+6);
1064 vb7 = (UInt)get_vbyte(a+7);
1065
1066 /* Now distinguish 3 cases */
1067
1068 /* Case 1: the address is completely valid, so:
1069 - no addressing error
1070 - return V bytes as read from memory
1071 */
1072 if (a0ok && a1ok && a2ok && a3ok && a4ok && a5ok && a6ok && a7ok) {
1073 ULong vw = VGM_WORD64_INVALID;
1074 vw <<= 8; vw |= vb7;
1075 vw <<= 8; vw |= vb6;
1076 vw <<= 8; vw |= vb5;
1077 vw <<= 8; vw |= vb4;
1078 vw <<= 8; vw |= vb3;
1079 vw <<= 8; vw |= vb2;
1080 vw <<= 8; vw |= vb1;
1081 vw <<= 8; vw |= vb0;
1082 return vw;
1083 }
1084
1085 /* Case 2: the address is completely invalid.
1086 - emit addressing error
1087 - return V word indicating validity.
1088 This sounds strange, but if we make loads from invalid addresses
1089 give invalid data, we also risk producing a number of confusing
1090 undefined-value errors later, which confuses the fact that the
1091 error arose in the first place from an invalid address.
1092 */
1093 /* VG_(printf)("%p (%d %d %d %d)\n", a, a0ok, a1ok, a2ok, a3ok); */
1094 if (!MAC_(clo_partial_loads_ok)
1095 || ((a & 7) != 0)
1096 || (!a0ok && !a1ok && !a2ok && !a3ok && !a4ok && !a5ok && !a6ok && !a7ok)) {
1097 MAC_(record_address_error)( VG_(get_current_tid)(), a, 8, False );
1098 return VGM_WORD64_VALID;
1099 }
1100
1101 /* Case 3: the address is partially valid.
1102 - no addressing error
1103 - returned V word is invalid where the address is invalid,
1104 and contains V bytes from memory otherwise.
1105 Case 3 is only allowed if MC_(clo_partial_loads_ok) is True
1106 (which is the default), and the address is 4-aligned.
1107 If not, Case 2 will have applied.
1108 */
1109 tl_assert(MAC_(clo_partial_loads_ok));
1110 {
1111 ULong vw = VGM_WORD64_INVALID;
1112 vw <<= 8; vw |= (a7ok ? vb7 : VGM_BYTE_INVALID);
1113 vw <<= 8; vw |= (a6ok ? vb6 : VGM_BYTE_INVALID);
1114 vw <<= 8; vw |= (a5ok ? vb5 : VGM_BYTE_INVALID);
1115 vw <<= 8; vw |= (a4ok ? vb4 : VGM_BYTE_INVALID);
1116 vw <<= 8; vw |= (a3ok ? vb3 : VGM_BYTE_INVALID);
1117 vw <<= 8; vw |= (a2ok ? vb2 : VGM_BYTE_INVALID);
1118 vw <<= 8; vw |= (a1ok ? vb1 : VGM_BYTE_INVALID);
1119 vw <<= 8; vw |= (a0ok ? vb0 : VGM_BYTE_INVALID);
1120 return vw;
1121 }
1122}
1123
1124static void mc_wr_V8_SLOWLY ( Addr a, ULong vbytes )
1125{
1126 /* Check the address for validity. */
1127 Bool aerr = False;
1128 PROF_EVENT(71);
1129
1130 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
1131 if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
1132 if (get_abit(a+2) != VGM_BIT_VALID) aerr = True;
1133 if (get_abit(a+3) != VGM_BIT_VALID) aerr = True;
1134 if (get_abit(a+4) != VGM_BIT_VALID) aerr = True;
1135 if (get_abit(a+5) != VGM_BIT_VALID) aerr = True;
1136 if (get_abit(a+6) != VGM_BIT_VALID) aerr = True;
1137 if (get_abit(a+7) != VGM_BIT_VALID) aerr = True;
1138
1139 /* Store the V bytes, remembering to do it little-endian-ly. */
1140 set_vbyte( a+0, vbytes & 0x000000FF ); vbytes >>= 8;
1141 set_vbyte( a+1, vbytes & 0x000000FF ); vbytes >>= 8;
1142 set_vbyte( a+2, vbytes & 0x000000FF ); vbytes >>= 8;
1143 set_vbyte( a+3, vbytes & 0x000000FF ); vbytes >>= 8;
1144 set_vbyte( a+4, vbytes & 0x000000FF ); vbytes >>= 8;
1145 set_vbyte( a+5, vbytes & 0x000000FF ); vbytes >>= 8;
1146 set_vbyte( a+6, vbytes & 0x000000FF ); vbytes >>= 8;
1147 set_vbyte( a+7, vbytes & 0x000000FF );
1148
1149 /* If an address error has happened, report it. */
1150 if (aerr)
1151 MAC_(record_address_error)( VG_(get_current_tid)(), a, 8, True );
1152}
1153
1154/* ------------------------ Size = 4 ------------------------ */
1155
njn5c004e42002-11-18 11:04:50 +00001156static UInt mc_rd_V4_SLOWLY ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00001157{
1158 Bool a0ok, a1ok, a2ok, a3ok;
1159 UInt vb0, vb1, vb2, vb3;
1160
1161 PROF_EVENT(70);
1162
1163 /* First establish independently the addressibility of the 4 bytes
1164 involved. */
1165 a0ok = get_abit(a+0) == VGM_BIT_VALID;
1166 a1ok = get_abit(a+1) == VGM_BIT_VALID;
1167 a2ok = get_abit(a+2) == VGM_BIT_VALID;
1168 a3ok = get_abit(a+3) == VGM_BIT_VALID;
1169
1170 /* Also get the validity bytes for the address. */
1171 vb0 = (UInt)get_vbyte(a+0);
1172 vb1 = (UInt)get_vbyte(a+1);
1173 vb2 = (UInt)get_vbyte(a+2);
1174 vb3 = (UInt)get_vbyte(a+3);
1175
1176 /* Now distinguish 3 cases */
1177
1178 /* Case 1: the address is completely valid, so:
1179 - no addressing error
1180 - return V bytes as read from memory
1181 */
1182 if (a0ok && a1ok && a2ok && a3ok) {
1183 UInt vw = VGM_WORD_INVALID;
1184 vw <<= 8; vw |= vb3;
1185 vw <<= 8; vw |= vb2;
1186 vw <<= 8; vw |= vb1;
1187 vw <<= 8; vw |= vb0;
1188 return vw;
1189 }
1190
1191 /* Case 2: the address is completely invalid.
1192 - emit addressing error
1193 - return V word indicating validity.
1194 This sounds strange, but if we make loads from invalid addresses
1195 give invalid data, we also risk producing a number of confusing
1196 undefined-value errors later, which confuses the fact that the
1197 error arose in the first place from an invalid address.
1198 */
1199 /* VG_(printf)("%p (%d %d %d %d)\n", a, a0ok, a1ok, a2ok, a3ok); */
njn43c799e2003-04-08 00:08:52 +00001200 if (!MAC_(clo_partial_loads_ok)
njn25e49d8e72002-09-23 09:36:25 +00001201 || ((a & 3) != 0)
1202 || (!a0ok && !a1ok && !a2ok && !a3ok)) {
njn72718642003-07-24 08:45:32 +00001203 MAC_(record_address_error)( VG_(get_current_tid)(), a, 4, False );
njn25e49d8e72002-09-23 09:36:25 +00001204 return (VGM_BYTE_VALID << 24) | (VGM_BYTE_VALID << 16)
1205 | (VGM_BYTE_VALID << 8) | VGM_BYTE_VALID;
1206 }
1207
1208 /* Case 3: the address is partially valid.
1209 - no addressing error
1210 - returned V word is invalid where the address is invalid,
1211 and contains V bytes from memory otherwise.
njn5c004e42002-11-18 11:04:50 +00001212 Case 3 is only allowed if MC_(clo_partial_loads_ok) is True
njn25e49d8e72002-09-23 09:36:25 +00001213 (which is the default), and the address is 4-aligned.
1214 If not, Case 2 will have applied.
1215 */
njnca82cc02004-11-22 17:18:48 +00001216 tl_assert(MAC_(clo_partial_loads_ok));
njn25e49d8e72002-09-23 09:36:25 +00001217 {
1218 UInt vw = VGM_WORD_INVALID;
1219 vw <<= 8; vw |= (a3ok ? vb3 : VGM_BYTE_INVALID);
1220 vw <<= 8; vw |= (a2ok ? vb2 : VGM_BYTE_INVALID);
1221 vw <<= 8; vw |= (a1ok ? vb1 : VGM_BYTE_INVALID);
1222 vw <<= 8; vw |= (a0ok ? vb0 : VGM_BYTE_INVALID);
1223 return vw;
1224 }
1225}
1226
njn5c004e42002-11-18 11:04:50 +00001227static void mc_wr_V4_SLOWLY ( Addr a, UInt vbytes )
njn25e49d8e72002-09-23 09:36:25 +00001228{
1229 /* Check the address for validity. */
1230 Bool aerr = False;
1231 PROF_EVENT(71);
1232
1233 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
1234 if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
1235 if (get_abit(a+2) != VGM_BIT_VALID) aerr = True;
1236 if (get_abit(a+3) != VGM_BIT_VALID) aerr = True;
1237
1238 /* Store the V bytes, remembering to do it little-endian-ly. */
1239 set_vbyte( a+0, vbytes & 0x000000FF ); vbytes >>= 8;
1240 set_vbyte( a+1, vbytes & 0x000000FF ); vbytes >>= 8;
1241 set_vbyte( a+2, vbytes & 0x000000FF ); vbytes >>= 8;
1242 set_vbyte( a+3, vbytes & 0x000000FF );
1243
1244 /* If an address error has happened, report it. */
1245 if (aerr)
njn72718642003-07-24 08:45:32 +00001246 MAC_(record_address_error)( VG_(get_current_tid)(), a, 4, True );
njn25e49d8e72002-09-23 09:36:25 +00001247}
1248
sewardj95448072004-11-22 20:19:51 +00001249/* ------------------------ Size = 2 ------------------------ */
1250
njn5c004e42002-11-18 11:04:50 +00001251static UInt mc_rd_V2_SLOWLY ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00001252{
1253 /* Check the address for validity. */
1254 UInt vw = VGM_WORD_INVALID;
1255 Bool aerr = False;
1256 PROF_EVENT(72);
1257
1258 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
1259 if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
1260
1261 /* Fetch the V bytes, remembering to do it little-endian-ly. */
1262 vw <<= 8; vw |= (UInt)get_vbyte(a+1);
1263 vw <<= 8; vw |= (UInt)get_vbyte(a+0);
1264
1265 /* If an address error has happened, report it. */
1266 if (aerr) {
njn72718642003-07-24 08:45:32 +00001267 MAC_(record_address_error)( VG_(get_current_tid)(), a, 2, False );
njn25e49d8e72002-09-23 09:36:25 +00001268 vw = (VGM_BYTE_INVALID << 24) | (VGM_BYTE_INVALID << 16)
1269 | (VGM_BYTE_VALID << 8) | (VGM_BYTE_VALID);
1270 }
1271 return vw;
1272}
1273
njn5c004e42002-11-18 11:04:50 +00001274static void mc_wr_V2_SLOWLY ( Addr a, UInt vbytes )
njn25e49d8e72002-09-23 09:36:25 +00001275{
1276 /* Check the address for validity. */
1277 Bool aerr = False;
1278 PROF_EVENT(73);
1279
1280 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
1281 if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
1282
1283 /* Store the V bytes, remembering to do it little-endian-ly. */
1284 set_vbyte( a+0, vbytes & 0x000000FF ); vbytes >>= 8;
1285 set_vbyte( a+1, vbytes & 0x000000FF );
1286
1287 /* If an address error has happened, report it. */
1288 if (aerr)
njn72718642003-07-24 08:45:32 +00001289 MAC_(record_address_error)( VG_(get_current_tid)(), a, 2, True );
njn25e49d8e72002-09-23 09:36:25 +00001290}
1291
sewardj95448072004-11-22 20:19:51 +00001292/* ------------------------ Size = 1 ------------------------ */
1293
njn5c004e42002-11-18 11:04:50 +00001294static UInt mc_rd_V1_SLOWLY ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00001295{
1296 /* Check the address for validity. */
1297 UInt vw = VGM_WORD_INVALID;
1298 Bool aerr = False;
1299 PROF_EVENT(74);
1300
1301 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
1302
1303 /* Fetch the V byte. */
1304 vw <<= 8; vw |= (UInt)get_vbyte(a+0);
1305
1306 /* If an address error has happened, report it. */
1307 if (aerr) {
njn72718642003-07-24 08:45:32 +00001308 MAC_(record_address_error)( VG_(get_current_tid)(), a, 1, False );
njn25e49d8e72002-09-23 09:36:25 +00001309 vw = (VGM_BYTE_INVALID << 24) | (VGM_BYTE_INVALID << 16)
1310 | (VGM_BYTE_INVALID << 8) | (VGM_BYTE_VALID);
1311 }
1312 return vw;
1313}
1314
njn5c004e42002-11-18 11:04:50 +00001315static void mc_wr_V1_SLOWLY ( Addr a, UInt vbytes )
njn25e49d8e72002-09-23 09:36:25 +00001316{
1317 /* Check the address for validity. */
1318 Bool aerr = False;
1319 PROF_EVENT(75);
1320 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
1321
1322 /* Store the V bytes, remembering to do it little-endian-ly. */
1323 set_vbyte( a+0, vbytes & 0x000000FF );
1324
1325 /* If an address error has happened, report it. */
1326 if (aerr)
njn72718642003-07-24 08:45:32 +00001327 MAC_(record_address_error)( VG_(get_current_tid)(), a, 1, True );
njn25e49d8e72002-09-23 09:36:25 +00001328}
1329
1330
1331/* ---------------------------------------------------------------------
1332 Called from generated code, or from the assembly helpers.
1333 Handlers for value check failures.
1334 ------------------------------------------------------------------ */
1335
njn5c004e42002-11-18 11:04:50 +00001336void MC_(helperc_value_check0_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001337{
njn72718642003-07-24 08:45:32 +00001338 MC_(record_value_error) ( VG_(get_current_tid)(), 0 );
njn25e49d8e72002-09-23 09:36:25 +00001339}
1340
njn5c004e42002-11-18 11:04:50 +00001341void MC_(helperc_value_check1_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001342{
njn72718642003-07-24 08:45:32 +00001343 MC_(record_value_error) ( VG_(get_current_tid)(), 1 );
njn25e49d8e72002-09-23 09:36:25 +00001344}
1345
njn5c004e42002-11-18 11:04:50 +00001346void MC_(helperc_value_check2_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001347{
njn72718642003-07-24 08:45:32 +00001348 MC_(record_value_error) ( VG_(get_current_tid)(), 2 );
njn25e49d8e72002-09-23 09:36:25 +00001349}
1350
njn5c004e42002-11-18 11:04:50 +00001351void MC_(helperc_value_check4_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001352{
njn72718642003-07-24 08:45:32 +00001353 MC_(record_value_error) ( VG_(get_current_tid)(), 4 );
njn25e49d8e72002-09-23 09:36:25 +00001354}
1355
sewardj95448072004-11-22 20:19:51 +00001356REGPARM(1) void MC_(helperc_complain_undef) ( HWord sz )
1357{
1358 MC_(record_value_error) ( VG_(get_current_tid)(), (Int)sz );
1359}
1360
njn25e49d8e72002-09-23 09:36:25 +00001361
njn25e49d8e72002-09-23 09:36:25 +00001362/*------------------------------------------------------------*/
sewardjee070842003-07-05 17:53:55 +00001363/*--- Metadata get/set functions, for client requests. ---*/
1364/*------------------------------------------------------------*/
1365
1366/* Copy Vbits for src into vbits. Returns: 1 == OK, 2 == alignment
1367 error, 3 == addressing error. */
nethercote8b76fe52004-11-08 19:20:09 +00001368static Int mc_get_or_set_vbits_for_client (
njn72718642003-07-24 08:45:32 +00001369 ThreadId tid,
sewardjee070842003-07-05 17:53:55 +00001370 Addr dataV,
1371 Addr vbitsV,
nethercote451eae92004-11-02 13:06:32 +00001372 SizeT size,
sewardjee070842003-07-05 17:53:55 +00001373 Bool setting /* True <=> set vbits, False <=> get vbits */
1374)
1375{
1376 Bool addressibleD = True;
1377 Bool addressibleV = True;
1378 UInt* data = (UInt*)dataV;
1379 UInt* vbits = (UInt*)vbitsV;
nethercote451eae92004-11-02 13:06:32 +00001380 SizeT szW = size / 4; /* sigh */
1381 SizeT i;
sewardjaf48a602003-07-06 00:54:47 +00001382 UInt* dataP = NULL; /* bogus init to keep gcc happy */
1383 UInt* vbitsP = NULL; /* ditto */
sewardjee070842003-07-05 17:53:55 +00001384
1385 /* Check alignment of args. */
1386 if (!(IS_ALIGNED4_ADDR(data) && IS_ALIGNED4_ADDR(vbits)))
1387 return 2;
1388 if ((size & 3) != 0)
1389 return 2;
1390
1391 /* Check that arrays are addressible. */
1392 for (i = 0; i < szW; i++) {
sewardjaf48a602003-07-06 00:54:47 +00001393 dataP = &data[i];
1394 vbitsP = &vbits[i];
sewardjee070842003-07-05 17:53:55 +00001395 if (get_abits4_ALIGNED((Addr)dataP) != VGM_NIBBLE_VALID) {
1396 addressibleD = False;
1397 break;
1398 }
1399 if (get_abits4_ALIGNED((Addr)vbitsP) != VGM_NIBBLE_VALID) {
1400 addressibleV = False;
1401 break;
1402 }
1403 }
1404 if (!addressibleD) {
njn72718642003-07-24 08:45:32 +00001405 MAC_(record_address_error)( tid, (Addr)dataP, 4,
sewardjee070842003-07-05 17:53:55 +00001406 setting ? True : False );
1407 return 3;
1408 }
1409 if (!addressibleV) {
njn72718642003-07-24 08:45:32 +00001410 MAC_(record_address_error)( tid, (Addr)vbitsP, 4,
sewardjee070842003-07-05 17:53:55 +00001411 setting ? False : True );
1412 return 3;
1413 }
1414
1415 /* Do the copy */
1416 if (setting) {
1417 /* setting */
1418 for (i = 0; i < szW; i++) {
1419 if (get_vbytes4_ALIGNED( (Addr)&vbits[i] ) != VGM_WORD_VALID)
njn72718642003-07-24 08:45:32 +00001420 MC_(record_value_error)(tid, 4);
sewardjee070842003-07-05 17:53:55 +00001421 set_vbytes4_ALIGNED( (Addr)&data[i], vbits[i] );
1422 }
1423 } else {
1424 /* getting */
1425 for (i = 0; i < szW; i++) {
1426 vbits[i] = get_vbytes4_ALIGNED( (Addr)&data[i] );
1427 set_vbytes4_ALIGNED( (Addr)&vbits[i], VGM_WORD_VALID );
1428 }
1429 }
1430
1431 return 1;
1432}
1433
1434
1435/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00001436/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
1437/*------------------------------------------------------------*/
1438
sewardja4495682002-10-21 07:29:59 +00001439/* For the memory leak detector, say whether an entire 64k chunk of
1440 address space is possibly in use, or not. If in doubt return
1441 True.
njn25e49d8e72002-09-23 09:36:25 +00001442*/
sewardja4495682002-10-21 07:29:59 +00001443static
1444Bool mc_is_valid_64k_chunk ( UInt chunk_number )
njn25e49d8e72002-09-23 09:36:25 +00001445{
njnca82cc02004-11-22 17:18:48 +00001446 tl_assert(chunk_number >= 0 && chunk_number < 65536);
sewardja4495682002-10-21 07:29:59 +00001447 if (IS_DISTINGUISHED_SM(primary_map[chunk_number])) {
1448 /* Definitely not in use. */
1449 return False;
1450 } else {
1451 return True;
njn25e49d8e72002-09-23 09:36:25 +00001452 }
1453}
1454
1455
sewardja4495682002-10-21 07:29:59 +00001456/* For the memory leak detector, say whether or not a given word
1457 address is to be regarded as valid. */
1458static
1459Bool mc_is_valid_address ( Addr a )
1460{
1461 UInt vbytes;
1462 UChar abits;
njnca82cc02004-11-22 17:18:48 +00001463 tl_assert(IS_ALIGNED4_ADDR(a));
sewardja4495682002-10-21 07:29:59 +00001464 abits = get_abits4_ALIGNED(a);
1465 vbytes = get_vbytes4_ALIGNED(a);
1466 if (abits == VGM_NIBBLE_VALID && vbytes == VGM_WORD_VALID) {
1467 return True;
1468 } else {
1469 return False;
1470 }
1471}
1472
1473
nethercote996901a2004-08-03 13:29:09 +00001474/* Leak detector for this tool. We don't actually do anything, merely
sewardja4495682002-10-21 07:29:59 +00001475 run the generic leak detector with suitable parameters for this
nethercote996901a2004-08-03 13:29:09 +00001476 tool. */
sewardj2a99cf62004-11-24 10:44:19 +00001477static void mc_detect_memory_leaks ( ThreadId tid )
njn25e49d8e72002-09-23 09:36:25 +00001478{
sewardj2a99cf62004-11-24 10:44:19 +00001479 MAC_(do_detect_memory_leaks) (
1480 tid, mc_is_valid_64k_chunk, mc_is_valid_address );
njn25e49d8e72002-09-23 09:36:25 +00001481}
1482
1483
1484/* ---------------------------------------------------------------------
1485 Sanity check machinery (permanently engaged).
1486 ------------------------------------------------------------------ */
1487
njn26f02512004-11-22 18:33:15 +00001488Bool TL_(cheap_sanity_check) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001489{
jseward9800fd32004-01-04 23:08:04 +00001490 /* nothing useful we can rapidly check */
1491 return True;
njn25e49d8e72002-09-23 09:36:25 +00001492}
1493
njn26f02512004-11-22 18:33:15 +00001494Bool TL_(expensive_sanity_check) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001495{
1496 Int i;
1497
1498 /* Make sure nobody changed the distinguished secondary. */
1499 for (i = 0; i < 8192; i++)
1500 if (distinguished_secondary_map.abits[i] != VGM_BYTE_INVALID)
1501 return False;
1502
1503 for (i = 0; i < 65536; i++)
1504 if (distinguished_secondary_map.vbyte[i] != VGM_BYTE_INVALID)
1505 return False;
1506
1507 /* Make sure that the upper 3/4 of the primary map hasn't
1508 been messed with. */
1509 for (i = 65536; i < 262144; i++)
1510 if (primary_map[i] != & distinguished_secondary_map)
1511 return False;
1512
1513 return True;
1514}
1515
1516/* ---------------------------------------------------------------------
1517 Debugging machinery (turn on to debug). Something of a mess.
1518 ------------------------------------------------------------------ */
1519
1520#if 0
1521/* Print the value tags on the 8 integer registers & flag reg. */
1522
1523static void uint_to_bits ( UInt x, Char* str )
1524{
1525 Int i;
1526 Int w = 0;
1527 /* str must point to a space of at least 36 bytes. */
1528 for (i = 31; i >= 0; i--) {
1529 str[w++] = (x & ( ((UInt)1) << i)) ? '1' : '0';
1530 if (i == 24 || i == 16 || i == 8)
1531 str[w++] = ' ';
1532 }
1533 str[w++] = 0;
njnca82cc02004-11-22 17:18:48 +00001534 tl_assert(w == 36);
njn25e49d8e72002-09-23 09:36:25 +00001535}
1536
1537/* Caution! Not vthread-safe; looks in VG_(baseBlock), not the thread
1538 state table. */
1539
1540static void vg_show_reg_tags ( void )
1541{
1542 Char buf1[36];
1543 Char buf2[36];
1544 UInt z_eax, z_ebx, z_ecx, z_edx,
1545 z_esi, z_edi, z_ebp, z_esp, z_eflags;
1546
1547 z_eax = VG_(baseBlock)[VGOFF_(sh_eax)];
1548 z_ebx = VG_(baseBlock)[VGOFF_(sh_ebx)];
1549 z_ecx = VG_(baseBlock)[VGOFF_(sh_ecx)];
1550 z_edx = VG_(baseBlock)[VGOFF_(sh_edx)];
1551 z_esi = VG_(baseBlock)[VGOFF_(sh_esi)];
1552 z_edi = VG_(baseBlock)[VGOFF_(sh_edi)];
1553 z_ebp = VG_(baseBlock)[VGOFF_(sh_ebp)];
1554 z_esp = VG_(baseBlock)[VGOFF_(sh_esp)];
1555 z_eflags = VG_(baseBlock)[VGOFF_(sh_eflags)];
1556
1557 uint_to_bits(z_eflags, buf1);
njn9b6d34e2002-10-15 08:48:08 +00001558 VG_(message)(Vg_DebugMsg, "efl %s\n", buf1);
njn25e49d8e72002-09-23 09:36:25 +00001559
1560 uint_to_bits(z_eax, buf1);
1561 uint_to_bits(z_ebx, buf2);
1562 VG_(message)(Vg_DebugMsg, "eax %s ebx %s\n", buf1, buf2);
1563
1564 uint_to_bits(z_ecx, buf1);
1565 uint_to_bits(z_edx, buf2);
1566 VG_(message)(Vg_DebugMsg, "ecx %s edx %s\n", buf1, buf2);
1567
1568 uint_to_bits(z_esi, buf1);
1569 uint_to_bits(z_edi, buf2);
1570 VG_(message)(Vg_DebugMsg, "esi %s edi %s\n", buf1, buf2);
1571
1572 uint_to_bits(z_ebp, buf1);
1573 uint_to_bits(z_esp, buf2);
1574 VG_(message)(Vg_DebugMsg, "ebp %s esp %s\n", buf1, buf2);
1575}
1576
1577
1578/* For debugging only. Scan the address space and touch all allegedly
1579 addressible words. Useful for establishing where Valgrind's idea of
1580 addressibility has diverged from what the kernel believes. */
1581
1582static
1583void zzzmemscan_notify_word ( Addr a, UInt w )
1584{
1585}
1586
1587void zzzmemscan ( void )
1588{
1589 Int n_notifies
1590 = VG_(scan_all_valid_memory)( zzzmemscan_notify_word );
1591 VG_(printf)("zzzmemscan: n_bytes = %d\n", 4 * n_notifies );
1592}
1593#endif
1594
1595
1596
1597
1598#if 0
1599static Int zzz = 0;
1600
1601void show_bb ( Addr eip_next )
1602{
1603 VG_(printf)("[%4d] ", zzz);
1604 vg_show_reg_tags( &VG_(m_shadow );
1605 VG_(translate) ( eip_next, NULL, NULL, NULL );
1606}
1607#endif /* 0 */
1608
njn25e49d8e72002-09-23 09:36:25 +00001609
1610/*------------------------------------------------------------*/
njnd3040452003-05-19 15:04:06 +00001611/*--- Command line args ---*/
njn25e49d8e72002-09-23 09:36:25 +00001612/*------------------------------------------------------------*/
1613
njn43c799e2003-04-08 00:08:52 +00001614Bool MC_(clo_avoid_strlen_errors) = True;
njn43c799e2003-04-08 00:08:52 +00001615
njn26f02512004-11-22 18:33:15 +00001616Bool TL_(process_cmd_line_option)(Char* arg)
njn25e49d8e72002-09-23 09:36:25 +00001617{
nethercote27fec902004-06-16 21:26:32 +00001618 VG_BOOL_CLO("--avoid-strlen-errors", MC_(clo_avoid_strlen_errors))
njn25e49d8e72002-09-23 09:36:25 +00001619 else
njn43c799e2003-04-08 00:08:52 +00001620 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001621
1622 return True;
njn25e49d8e72002-09-23 09:36:25 +00001623}
1624
njn26f02512004-11-22 18:33:15 +00001625void TL_(print_usage)(void)
njn25e49d8e72002-09-23 09:36:25 +00001626{
njn3e884182003-04-15 13:03:23 +00001627 MAC_(print_common_usage)();
1628 VG_(printf)(
1629" --avoid-strlen-errors=no|yes suppress errs from inlined strlen [yes]\n"
1630 );
1631}
1632
njn26f02512004-11-22 18:33:15 +00001633void TL_(print_debug_usage)(void)
njn3e884182003-04-15 13:03:23 +00001634{
1635 MAC_(print_common_debug_usage)();
1636 VG_(printf)(
sewardj8ec2cfc2002-10-13 00:57:26 +00001637" --cleanup=no|yes improve after instrumentation? [yes]\n"
njn3e884182003-04-15 13:03:23 +00001638 );
njn25e49d8e72002-09-23 09:36:25 +00001639}
1640
nethercote8b76fe52004-11-08 19:20:09 +00001641/*------------------------------------------------------------*/
1642/*--- Client requests ---*/
1643/*------------------------------------------------------------*/
1644
1645/* Client block management:
1646
1647 This is managed as an expanding array of client block descriptors.
1648 Indices of live descriptors are issued to the client, so it can ask
1649 to free them later. Therefore we cannot slide live entries down
1650 over dead ones. Instead we must use free/inuse flags and scan for
1651 an empty slot at allocation time. This in turn means allocation is
1652 relatively expensive, so we hope this does not happen too often.
1653*/
1654
1655typedef
1656 enum { CG_NotInUse, CG_NoAccess, CG_Writable, CG_Readable }
1657 CGenBlockKind;
1658
1659typedef
1660 struct {
1661 Addr start;
1662 SizeT size;
1663 ExeContext* where;
1664 CGenBlockKind kind;
1665 }
1666 CGenBlock;
1667
1668/* This subsystem is self-initialising. */
1669static UInt vg_cgb_size = 0;
1670static UInt vg_cgb_used = 0;
1671static CGenBlock* vg_cgbs = NULL;
1672
1673/* Stats for this subsystem. */
1674static UInt vg_cgb_used_MAX = 0; /* Max in use. */
1675static UInt vg_cgb_allocs = 0; /* Number of allocs. */
1676static UInt vg_cgb_discards = 0; /* Number of discards. */
1677static UInt vg_cgb_search = 0; /* Number of searches. */
1678
1679
1680static
1681Int vg_alloc_client_block ( void )
1682{
1683 UInt i, sz_new;
1684 CGenBlock* cgbs_new;
1685
1686 vg_cgb_allocs++;
1687
1688 for (i = 0; i < vg_cgb_used; i++) {
1689 vg_cgb_search++;
1690 if (vg_cgbs[i].kind == CG_NotInUse)
1691 return i;
1692 }
1693
1694 /* Not found. Try to allocate one at the end. */
1695 if (vg_cgb_used < vg_cgb_size) {
1696 vg_cgb_used++;
1697 return vg_cgb_used-1;
1698 }
1699
1700 /* Ok, we have to allocate a new one. */
njnca82cc02004-11-22 17:18:48 +00001701 tl_assert(vg_cgb_used == vg_cgb_size);
nethercote8b76fe52004-11-08 19:20:09 +00001702 sz_new = (vg_cgbs == NULL) ? 10 : (2 * vg_cgb_size);
1703
1704 cgbs_new = VG_(malloc)( sz_new * sizeof(CGenBlock) );
1705 for (i = 0; i < vg_cgb_used; i++)
1706 cgbs_new[i] = vg_cgbs[i];
1707
1708 if (vg_cgbs != NULL)
1709 VG_(free)( vg_cgbs );
1710 vg_cgbs = cgbs_new;
1711
1712 vg_cgb_size = sz_new;
1713 vg_cgb_used++;
1714 if (vg_cgb_used > vg_cgb_used_MAX)
1715 vg_cgb_used_MAX = vg_cgb_used;
1716 return vg_cgb_used-1;
1717}
1718
1719
1720static void show_client_block_stats ( void )
1721{
1722 VG_(message)(Vg_DebugMsg,
1723 "general CBs: %d allocs, %d discards, %d maxinuse, %d search",
1724 vg_cgb_allocs, vg_cgb_discards, vg_cgb_used_MAX, vg_cgb_search
1725 );
1726}
1727
1728static Bool find_addr(VgHashNode* sh_ch, void* ap)
1729{
1730 MAC_Chunk *m = (MAC_Chunk*)sh_ch;
1731 Addr a = *(Addr*)ap;
1732
1733 return VG_(addr_is_in_block)(a, m->data, m->size);
1734}
1735
1736static Bool client_perm_maybe_describe( Addr a, AddrInfo* ai )
1737{
1738 UInt i;
1739 /* VG_(printf)("try to identify %d\n", a); */
1740
1741 /* Perhaps it's a general block ? */
1742 for (i = 0; i < vg_cgb_used; i++) {
1743 if (vg_cgbs[i].kind == CG_NotInUse)
1744 continue;
1745 if (VG_(addr_is_in_block)(a, vg_cgbs[i].start, vg_cgbs[i].size)) {
1746 MAC_Mempool **d, *mp;
1747
1748 /* OK - maybe it's a mempool, too? */
1749 mp = (MAC_Mempool*)VG_(HT_get_node)(MAC_(mempool_list),
1750 (UWord)vg_cgbs[i].start,
1751 (void*)&d);
1752 if(mp != NULL) {
1753 if(mp->chunks != NULL) {
1754 MAC_Chunk *mc;
1755
1756 mc = (MAC_Chunk*)VG_(HT_first_match)(mp->chunks, find_addr, &a);
1757 if(mc != NULL) {
1758 ai->akind = UserG;
1759 ai->blksize = mc->size;
1760 ai->rwoffset = (Int)(a) - (Int)mc->data;
1761 ai->lastchange = mc->where;
1762 return True;
1763 }
1764 }
1765 ai->akind = Mempool;
1766 ai->blksize = vg_cgbs[i].size;
1767 ai->rwoffset = (Int)(a) - (Int)(vg_cgbs[i].start);
1768 ai->lastchange = vg_cgbs[i].where;
1769 return True;
1770 }
1771 ai->akind = UserG;
1772 ai->blksize = vg_cgbs[i].size;
1773 ai->rwoffset = (Int)(a) - (Int)(vg_cgbs[i].start);
1774 ai->lastchange = vg_cgbs[i].where;
1775 return True;
1776 }
1777 }
1778 return False;
1779}
1780
njn26f02512004-11-22 18:33:15 +00001781Bool TL_(handle_client_request) ( ThreadId tid, UWord* arg, UWord* ret )
nethercote8b76fe52004-11-08 19:20:09 +00001782{
1783 Int i;
1784 Bool ok;
1785 Addr bad_addr;
1786
njnfc26ff92004-11-22 19:12:49 +00001787 if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
nethercote8b76fe52004-11-08 19:20:09 +00001788 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
1789 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
1790 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
1791 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
1792 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
1793 && VG_USERREQ__MEMPOOL_FREE != arg[0])
1794 return False;
1795
1796 switch (arg[0]) {
1797 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
1798 ok = mc_check_writable ( arg[1], arg[2], &bad_addr );
1799 if (!ok)
1800 MC_(record_user_error) ( tid, bad_addr, /*isWrite*/True,
1801 /*isUnaddr*/True );
1802 *ret = ok ? (UWord)NULL : bad_addr;
1803 break;
1804
1805 case VG_USERREQ__CHECK_READABLE: { /* check readable */
1806 MC_ReadResult res;
1807 res = mc_check_readable ( arg[1], arg[2], &bad_addr );
1808 if (MC_AddrErr == res)
1809 MC_(record_user_error) ( tid, bad_addr, /*isWrite*/False,
1810 /*isUnaddr*/True );
1811 else if (MC_ValueErr == res)
1812 MC_(record_user_error) ( tid, bad_addr, /*isWrite*/False,
1813 /*isUnaddr*/False );
1814 *ret = ( res==MC_Ok ? (UWord)NULL : bad_addr );
1815 break;
1816 }
1817
1818 case VG_USERREQ__DO_LEAK_CHECK:
sewardj2a99cf62004-11-24 10:44:19 +00001819 mc_detect_memory_leaks(tid);
nethercote8b76fe52004-11-08 19:20:09 +00001820 *ret = 0; /* return value is meaningless */
1821 break;
1822
1823 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
1824 i = vg_alloc_client_block();
1825 /* VG_(printf)("allocated %d %p\n", i, vg_cgbs); */
1826 vg_cgbs[i].kind = CG_NoAccess;
1827 vg_cgbs[i].start = arg[1];
1828 vg_cgbs[i].size = arg[2];
1829 vg_cgbs[i].where = VG_(get_ExeContext) ( tid );
1830 mc_make_noaccess ( arg[1], arg[2] );
1831 *ret = i;
1832 break;
1833
1834 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
1835 i = vg_alloc_client_block();
1836 vg_cgbs[i].kind = CG_Writable;
1837 vg_cgbs[i].start = arg[1];
1838 vg_cgbs[i].size = arg[2];
1839 vg_cgbs[i].where = VG_(get_ExeContext) ( tid );
1840 mc_make_writable ( arg[1], arg[2] );
1841 *ret = i;
1842 break;
1843
1844 case VG_USERREQ__MAKE_READABLE: /* make readable */
1845 i = vg_alloc_client_block();
1846 vg_cgbs[i].kind = CG_Readable;
1847 vg_cgbs[i].start = arg[1];
1848 vg_cgbs[i].size = arg[2];
1849 vg_cgbs[i].where = VG_(get_ExeContext) ( tid );
1850 mc_make_readable ( arg[1], arg[2] );
1851 *ret = i;
1852 break;
1853
1854 case VG_USERREQ__DISCARD: /* discard */
1855 if (vg_cgbs == NULL
1856 || arg[2] >= vg_cgb_used || vg_cgbs[arg[2]].kind == CG_NotInUse)
1857 return 1;
njnca82cc02004-11-22 17:18:48 +00001858 tl_assert(arg[2] >= 0 && arg[2] < vg_cgb_used);
nethercote8b76fe52004-11-08 19:20:09 +00001859 vg_cgbs[arg[2]].kind = CG_NotInUse;
1860 vg_cgb_discards++;
1861 *ret = 0;
1862 break;
1863
1864 case VG_USERREQ__GET_VBITS:
1865 /* Returns: 1 == OK, 2 == alignment error, 3 == addressing
1866 error. */
1867 /* VG_(printf)("get_vbits %p %p %d\n", arg[1], arg[2], arg[3] ); */
1868 *ret = mc_get_or_set_vbits_for_client
1869 ( tid, arg[1], arg[2], arg[3], False /* get them */ );
1870 break;
1871
1872 case VG_USERREQ__SET_VBITS:
1873 /* Returns: 1 == OK, 2 == alignment error, 3 == addressing
1874 error. */
1875 /* VG_(printf)("set_vbits %p %p %d\n", arg[1], arg[2], arg[3] ); */
1876 *ret = mc_get_or_set_vbits_for_client
1877 ( tid, arg[1], arg[2], arg[3], True /* set them */ );
1878 break;
1879
1880 default:
1881 if (MAC_(handle_common_client_requests)(tid, arg, ret )) {
1882 return True;
1883 } else {
1884 VG_(message)(Vg_UserMsg,
1885 "Warning: unknown memcheck client request code %llx",
1886 (ULong)arg[0]);
1887 return False;
1888 }
1889 }
1890 return True;
1891}
njn25e49d8e72002-09-23 09:36:25 +00001892
1893/*------------------------------------------------------------*/
1894/*--- Setup ---*/
1895/*------------------------------------------------------------*/
1896
njn26f02512004-11-22 18:33:15 +00001897void TL_(pre_clo_init)(void)
njn25e49d8e72002-09-23 09:36:25 +00001898{
njn810086f2002-11-14 12:42:47 +00001899 VG_(details_name) ("Memcheck");
1900 VG_(details_version) (NULL);
nethercote262eedf2003-11-13 17:57:18 +00001901 VG_(details_description) ("a memory error detector");
njn810086f2002-11-14 12:42:47 +00001902 VG_(details_copyright_author)(
nethercote08fa9a72004-07-16 17:44:00 +00001903 "Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al.");
nethercote421281e2003-11-20 16:20:55 +00001904 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardj78210aa2002-12-01 02:55:46 +00001905 VG_(details_avg_translation_sizeB) ( 228 );
njn25e49d8e72002-09-23 09:36:25 +00001906
njn810086f2002-11-14 12:42:47 +00001907 VG_(needs_core_errors) ();
njn95ec8702004-11-22 16:46:13 +00001908 VG_(needs_tool_errors) ();
njn810086f2002-11-14 12:42:47 +00001909 VG_(needs_libc_freeres) ();
njn810086f2002-11-14 12:42:47 +00001910 VG_(needs_shadow_regs) ();
1911 VG_(needs_command_line_options)();
1912 VG_(needs_client_requests) ();
njn810086f2002-11-14 12:42:47 +00001913 VG_(needs_sanity_checks) ();
fitzhardinge98abfc72003-12-16 02:05:15 +00001914 VG_(needs_shadow_memory) ();
njn25e49d8e72002-09-23 09:36:25 +00001915
njn3e884182003-04-15 13:03:23 +00001916 MAC_( new_mem_heap) = & mc_new_mem_heap;
nethercote8b76fe52004-11-08 19:20:09 +00001917 MAC_( ban_mem_heap) = & mc_make_noaccess;
njn3e884182003-04-15 13:03:23 +00001918 MAC_(copy_mem_heap) = & mc_copy_address_range_state;
nethercote8b76fe52004-11-08 19:20:09 +00001919 MAC_( die_mem_heap) = & mc_make_noaccess;
1920 MAC_(check_noaccess) = & mc_check_noaccess;
njn3e884182003-04-15 13:03:23 +00001921
fitzhardinge98abfc72003-12-16 02:05:15 +00001922 VG_(init_new_mem_startup) ( & mc_new_mem_startup );
nethercote8b76fe52004-11-08 19:20:09 +00001923 VG_(init_new_mem_stack_signal) ( & mc_make_writable );
1924 VG_(init_new_mem_brk) ( & mc_make_writable );
fitzhardinge98abfc72003-12-16 02:05:15 +00001925 VG_(init_new_mem_mmap) ( & mc_set_perms );
njn25e49d8e72002-09-23 09:36:25 +00001926
fitzhardinge98abfc72003-12-16 02:05:15 +00001927 VG_(init_copy_mem_remap) ( & mc_copy_address_range_state );
1928 VG_(init_change_mem_mprotect) ( & mc_set_perms );
njn3e884182003-04-15 13:03:23 +00001929
nethercote8b76fe52004-11-08 19:20:09 +00001930 VG_(init_die_mem_stack_signal) ( & mc_make_noaccess );
1931 VG_(init_die_mem_brk) ( & mc_make_noaccess );
1932 VG_(init_die_mem_munmap) ( & mc_make_noaccess );
njn3e884182003-04-15 13:03:23 +00001933
fitzhardinge98abfc72003-12-16 02:05:15 +00001934 VG_(init_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
1935 VG_(init_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
1936 VG_(init_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
1937 VG_(init_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
1938 VG_(init_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
1939 VG_(init_new_mem_stack) ( & MAC_(new_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001940
fitzhardinge98abfc72003-12-16 02:05:15 +00001941 VG_(init_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
1942 VG_(init_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
1943 VG_(init_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
1944 VG_(init_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
1945 VG_(init_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
1946 VG_(init_die_mem_stack) ( & MAC_(die_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001947
nethercote8b76fe52004-11-08 19:20:09 +00001948 VG_(init_ban_mem_stack) ( & mc_make_noaccess );
njn25e49d8e72002-09-23 09:36:25 +00001949
fitzhardinge98abfc72003-12-16 02:05:15 +00001950 VG_(init_pre_mem_read) ( & mc_check_is_readable );
1951 VG_(init_pre_mem_read_asciiz) ( & mc_check_is_readable_asciiz );
1952 VG_(init_pre_mem_write) ( & mc_check_is_writable );
nethercote8b76fe52004-11-08 19:20:09 +00001953 VG_(init_post_mem_write) ( & mc_make_readable );
1954
1955 VG_(init_pre_reg_read) ( & mc_pre_reg_read );
njn25e49d8e72002-09-23 09:36:25 +00001956
fitzhardinge98abfc72003-12-16 02:05:15 +00001957 VG_(init_post_regs_write_init) ( & mc_post_regs_write_init );
1958 VG_(init_post_reg_write_syscall_return) ( & mc_post_reg_write );
1959 VG_(init_post_reg_write_deliver_signal) ( & mc_post_reg_write );
1960 VG_(init_post_reg_write_pthread_return) ( & mc_post_reg_write );
1961 VG_(init_post_reg_write_clientreq_return) ( & mc_post_reg_write );
1962 VG_(init_post_reg_write_clientcall_return) ( & mc_post_reg_write_clientcall );
njnd3040452003-05-19 15:04:06 +00001963
njn25e49d8e72002-09-23 09:36:25 +00001964 VGP_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
1965 VGP_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
njn9b007f62003-04-07 14:40:25 +00001966 VGP_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
njnd04b7c62002-10-03 14:05:52 +00001967
njn43c799e2003-04-08 00:08:52 +00001968 /* Additional block description for VG_(describe_addr)() */
nethercote8b76fe52004-11-08 19:20:09 +00001969 MAC_(describe_addr_supp) = client_perm_maybe_describe;
njn43c799e2003-04-08 00:08:52 +00001970
njnd04b7c62002-10-03 14:05:52 +00001971 init_shadow_memory();
njn3e884182003-04-15 13:03:23 +00001972 MAC_(common_pre_clo_init)();
njn5c004e42002-11-18 11:04:50 +00001973}
1974
njn26f02512004-11-22 18:33:15 +00001975void TL_(post_clo_init) ( void )
njn5c004e42002-11-18 11:04:50 +00001976{
1977}
1978
njn26f02512004-11-22 18:33:15 +00001979void TL_(fini) ( Int exitcode )
njn5c004e42002-11-18 11:04:50 +00001980{
nethercote8b76fe52004-11-08 19:20:09 +00001981 MAC_(common_fini)( mc_detect_memory_leaks );
njn3e884182003-04-15 13:03:23 +00001982
njn5c004e42002-11-18 11:04:50 +00001983 if (0) {
1984 VG_(message)(Vg_DebugMsg,
1985 "------ Valgrind's client block stats follow ---------------" );
nethercote8b76fe52004-11-08 19:20:09 +00001986 show_client_block_stats();
njn5c004e42002-11-18 11:04:50 +00001987 }
njn25e49d8e72002-09-23 09:36:25 +00001988}
1989
njn26f02512004-11-22 18:33:15 +00001990VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 9./8)
fitzhardinge98abfc72003-12-16 02:05:15 +00001991
njn25e49d8e72002-09-23 09:36:25 +00001992/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00001993/*--- end mc_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00001994/*--------------------------------------------------------------------*/