blob: eb06979998e2579778c1b76ed2981264e06d5f6a [file] [log] [blame]
njn25e49d8e72002-09-23 09:36:25 +00001
2/*--------------------------------------------------------------------*/
nethercote137bc552003-11-14 17:47:54 +00003/*--- The AddrCheck tool: like MemCheck, but only does address ---*/
njn25e49d8e72002-09-23 09:36:25 +00004/*--- checking. No definedness checking. ---*/
njn25cac76cb2002-09-23 11:21:57 +00005/*--- ac_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00006/*--------------------------------------------------------------------*/
7
8/*
nethercote137bc552003-11-14 17:47:54 +00009 This file is part of AddrCheck, a lightweight 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
njn43c799e2003-04-08 00:08:52 +000033#include "mac_shared.h"
sewardjd8033d92002-12-08 22:16:58 +000034#include "memcheck.h"
njn25e49d8e72002-09-23 09:36:25 +000035//#include "vg_profile.c"
36
njn9b007f62003-04-07 14:40:25 +000037
njn25e49d8e72002-09-23 09:36:25 +000038/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000039/*--- Comparing and printing errors ---*/
40/*------------------------------------------------------------*/
41
njn26f02512004-11-22 18:33:15 +000042void TL_(pp_Error) ( Error* err )
njn25e49d8e72002-09-23 09:36:25 +000043{
njn43c799e2003-04-08 00:08:52 +000044 MAC_Error* err_extra = VG_(get_error_extra)(err);
njn25e49d8e72002-09-23 09:36:25 +000045
njn810086f2002-11-14 12:42:47 +000046 switch (VG_(get_error_kind)(err)) {
njn25e49d8e72002-09-23 09:36:25 +000047 case CoreMemErr:
njn43c799e2003-04-08 00:08:52 +000048 VG_(message)(Vg_UserMsg, "%s contains unaddressable byte(s)",
49 VG_(get_error_string)(err));
50 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
njn25e49d8e72002-09-23 09:36:25 +000051 break;
52
njn25e49d8e72002-09-23 09:36:25 +000053 case ParamErr:
njn43c799e2003-04-08 00:08:52 +000054 VG_(message)(Vg_UserMsg,
55 "Syscall param %s contains unaddressable byte(s)",
56 VG_(get_error_string)(err) );
57 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
58 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
njn25e49d8e72002-09-23 09:36:25 +000059 break;
60
61 case UserErr:
njn43c799e2003-04-08 00:08:52 +000062 VG_(message)(Vg_UserMsg,
63 "Unaddressable byte(s) found during client check request");
64 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
65 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
njn25e49d8e72002-09-23 09:36:25 +000066 break;
67
68 default:
njnb126f732004-11-22 17:57:07 +000069 MAC_(pp_shared_Error)(err);
njn43c799e2003-04-08 00:08:52 +000070 break;
njn25e49d8e72002-09-23 09:36:25 +000071 }
72}
73
74/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000075/*--- Suppressions ---*/
76/*------------------------------------------------------------*/
77
njn26f02512004-11-22 18:33:15 +000078Bool TL_(recognised_suppression) ( Char* name, Supp* su )
njn25e49d8e72002-09-23 09:36:25 +000079{
njn43c799e2003-04-08 00:08:52 +000080 return MAC_(shared_recognised_suppression)(name, su);
njn25e49d8e72002-09-23 09:36:25 +000081}
82
njn5c004e42002-11-18 11:04:50 +000083#define DEBUG(fmt, args...) //VG_(printf)(fmt, ## args)
84
njn25e49d8e72002-09-23 09:36:25 +000085/*------------------------------------------------------------*/
86/*--- Low-level support for memory checking. ---*/
87/*------------------------------------------------------------*/
88
89/* All reads and writes are checked against a memory map, which
90 records the state of all memory in the process. The memory map is
91 organised like this:
92
93 The top 16 bits of an address are used to index into a top-level
94 map table, containing 65536 entries. Each entry is a pointer to a
95 second-level map, which records the accesibililty and validity
96 permissions for the 65536 bytes indexed by the lower 16 bits of the
97 address. Each byte is represented by one bit, indicating
98 accessibility. So each second-level map contains 8192 bytes. This
99 two-level arrangement conveniently divides the 4G address space
100 into 64k lumps, each size 64k bytes.
101
102 All entries in the primary (top-level) map must point to a valid
103 secondary (second-level) map. Since most of the 4G of address
104 space will not be in use -- ie, not mapped at all -- there is a
105 distinguished secondary map, which indicates `not addressible and
106 not valid' writeable for all bytes. Entries in the primary map for
107 which the entire 64k is not in use at all point at this
108 distinguished map.
109
110 [...] lots of stuff deleted due to out of date-ness
111
112 As a final optimisation, the alignment and address checks for
113 4-byte loads and stores are combined in a neat way. The primary
114 map is extended to have 262144 entries (2^18), rather than 2^16.
115 The top 3/4 of these entries are permanently set to the
116 distinguished secondary map. For a 4-byte load/store, the
117 top-level map is indexed not with (addr >> 16) but instead f(addr),
118 where
119
120 f( XXXX XXXX XXXX XXXX ____ ____ ____ __YZ )
121 = ____ ____ ____ __YZ XXXX XXXX XXXX XXXX or
122 = ____ ____ ____ __ZY XXXX XXXX XXXX XXXX
123
124 ie the lowest two bits are placed above the 16 high address bits.
125 If either of these two bits are nonzero, the address is misaligned;
126 this will select a secondary map from the upper 3/4 of the primary
127 map. Because this is always the distinguished secondary map, a
128 (bogus) address check failure will result. The failure handling
129 code can then figure out whether this is a genuine addr check
130 failure or whether it is a possibly-legitimate access at a
131 misaligned address. */
132
133
134/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000135/*--- Function declarations. ---*/
136/*------------------------------------------------------------*/
137
njnc2699f62003-09-05 23:29:33 +0000138static void ac_ACCESS4_SLOWLY ( Addr a, Bool isWrite );
139static void ac_ACCESS2_SLOWLY ( Addr a, Bool isWrite );
140static void ac_ACCESS1_SLOWLY ( Addr a, Bool isWrite );
nethercote928a5f72004-11-03 18:10:37 +0000141static void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, SizeT size, Bool isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000142
143/*------------------------------------------------------------*/
144/*--- Data defns. ---*/
145/*------------------------------------------------------------*/
146
147typedef
148 struct {
sewardjb5f6f512005-03-10 23:59:00 +0000149 UChar abits[SECONDARY_SIZE / 8];
njn25e49d8e72002-09-23 09:36:25 +0000150 }
151 AcSecMap;
152
sewardjb5f6f512005-03-10 23:59:00 +0000153static AcSecMap* primary_map[ /*PRIMARY_SIZE*/ PRIMARY_SIZE*4 ];
154static const AcSecMap distinguished_secondary_maps[2] = {
155 [ VGM_BIT_INVALID ] = { { [0 ... (SECONDARY_SIZE/8) - 1] = VGM_BYTE_INVALID } },
156 [ VGM_BIT_VALID ] = { { [0 ... (SECONDARY_SIZE/8) - 1] = VGM_BYTE_VALID } },
157};
158#define N_SECONDARY_MAPS (sizeof(distinguished_secondary_maps)/sizeof(*distinguished_secondary_maps))
159
160#define DSM_IDX(a) ((a) & 1)
161
162#define DSM(a) ((AcSecMap *)&distinguished_secondary_maps[DSM_IDX(a)])
163
164#define DSM_NOTADDR DSM(VGM_BIT_INVALID)
165#define DSM_ADDR DSM(VGM_BIT_VALID)
njn25e49d8e72002-09-23 09:36:25 +0000166
njn25e49d8e72002-09-23 09:36:25 +0000167static void init_shadow_memory ( void )
168{
sewardjb5f6f512005-03-10 23:59:00 +0000169 Int i, a;
njn25e49d8e72002-09-23 09:36:25 +0000170
sewardjb5f6f512005-03-10 23:59:00 +0000171 /* check construction of the distinguished secondaries */
sewardj76754cf2005-03-14 00:14:04 +0000172 tl_assert(VGM_BIT_INVALID == 1);
173 tl_assert(VGM_BIT_VALID == 0);
sewardjb5f6f512005-03-10 23:59:00 +0000174
175 for(a = 0; a <= 1; a++)
sewardj76754cf2005-03-14 00:14:04 +0000176 tl_assert(distinguished_secondary_maps[DSM_IDX(a)].abits[0] == BIT_EXPAND(a));
njn25e49d8e72002-09-23 09:36:25 +0000177
178 /* These entries gradually get overwritten as the used address
179 space expands. */
sewardjb5f6f512005-03-10 23:59:00 +0000180 for (i = 0; i < PRIMARY_SIZE; i++)
181 primary_map[i] = DSM_NOTADDR;
njn25e49d8e72002-09-23 09:36:25 +0000182
183 /* These ones should never change; it's a bug in Valgrind if they do. */
sewardjb5f6f512005-03-10 23:59:00 +0000184 for (i = PRIMARY_SIZE; i < PRIMARY_SIZE*4; i++)
185 primary_map[i] = DSM_NOTADDR;
njn25e49d8e72002-09-23 09:36:25 +0000186}
187
njn25e49d8e72002-09-23 09:36:25 +0000188/*------------------------------------------------------------*/
189/*--- Basic bitmap management, reading and writing. ---*/
190/*------------------------------------------------------------*/
191
192/* Allocate and initialise a secondary map. */
193
194static AcSecMap* alloc_secondary_map ( __attribute__ ((unused))
sewardjb5f6f512005-03-10 23:59:00 +0000195 Char* caller,
196 const AcSecMap *prototype)
njn25e49d8e72002-09-23 09:36:25 +0000197{
198 AcSecMap* map;
njn25e49d8e72002-09-23 09:36:25 +0000199 PROF_EVENT(10);
200
fitzhardinge98abfc72003-12-16 02:05:15 +0000201 map = (AcSecMap *)VG_(shadow_alloc)(sizeof(AcSecMap));
sewardjb5f6f512005-03-10 23:59:00 +0000202 VG_(memcpy)(map, prototype, sizeof(*map));
njn25e49d8e72002-09-23 09:36:25 +0000203
204 /* VG_(printf)("ALLOC_2MAP(%s)\n", caller ); */
205 return map;
206}
207
208
209/* Basic reading/writing of the bitmaps, for byte-sized accesses. */
210
211static __inline__ UChar get_abit ( Addr a )
212{
sewardjb5f6f512005-03-10 23:59:00 +0000213 AcSecMap* sm = primary_map[PM_IDX(a)];
214 UInt sm_off = SM_OFF(a);
njn25e49d8e72002-09-23 09:36:25 +0000215 PROF_EVENT(20);
216# if 0
217 if (IS_DISTINGUISHED_SM(sm))
218 VG_(message)(Vg_DebugMsg,
219 "accessed distinguished 2ndary (A)map! 0x%x\n", a);
220# endif
221 return BITARR_TEST(sm->abits, sm_off)
222 ? VGM_BIT_INVALID : VGM_BIT_VALID;
223}
224
sewardj56867352003-10-12 10:27:06 +0000225static /* __inline__ */ void set_abit ( Addr a, UChar abit )
njn25e49d8e72002-09-23 09:36:25 +0000226{
227 AcSecMap* sm;
228 UInt sm_off;
229 PROF_EVENT(22);
230 ENSURE_MAPPABLE(a, "set_abit");
sewardjb5f6f512005-03-10 23:59:00 +0000231 sm = primary_map[PM_IDX(a)];
232 sm_off = SM_OFF(a);
njn25e49d8e72002-09-23 09:36:25 +0000233 if (abit)
234 BITARR_SET(sm->abits, sm_off);
235 else
236 BITARR_CLEAR(sm->abits, sm_off);
237}
238
239
240/* Reading/writing of the bitmaps, for aligned word-sized accesses. */
241
242static __inline__ UChar get_abits4_ALIGNED ( Addr a )
243{
244 AcSecMap* sm;
245 UInt sm_off;
246 UChar abits8;
247 PROF_EVENT(24);
248# ifdef VG_DEBUG_MEMORY
njnbe91aae2005-03-27 01:42:41 +0000249 tl_assert(VG_IS_4_ALIGNED(a));
njn25e49d8e72002-09-23 09:36:25 +0000250# endif
sewardjb5f6f512005-03-10 23:59:00 +0000251 sm = primary_map[PM_IDX(a)];
252 sm_off = SM_OFF(a);
njn25e49d8e72002-09-23 09:36:25 +0000253 abits8 = sm->abits[sm_off >> 3];
254 abits8 >>= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
255 abits8 &= 0x0F;
256 return abits8;
257}
258
259
260
261/*------------------------------------------------------------*/
262/*--- Setting permissions over address ranges. ---*/
263/*------------------------------------------------------------*/
264
sewardj56867352003-10-12 10:27:06 +0000265static /* __inline__ */
nethercote451eae92004-11-02 13:06:32 +0000266void set_address_range_perms ( Addr a, SizeT len, UInt example_a_bit )
njn25e49d8e72002-09-23 09:36:25 +0000267{
268 UChar abyte8;
269 UInt sm_off;
270 AcSecMap* sm;
271
272 PROF_EVENT(30);
273
274 if (len == 0)
275 return;
276
277 if (len > 100 * 1000 * 1000) {
278 VG_(message)(Vg_UserMsg,
279 "Warning: set address range perms: "
280 "large range %u, a %d",
281 len, example_a_bit );
282 }
283
284 VGP_PUSHCC(VgpSetMem);
285
286 /* Requests to change permissions of huge address ranges may
287 indicate bugs in our machinery. 30,000,000 is arbitrary, but so
288 far all legitimate requests have fallen beneath that size. */
289 /* 4 Mar 02: this is just stupid; get rid of it. */
njnca82cc02004-11-22 17:18:48 +0000290 /* tl_assert(len < 30000000); */
njn25e49d8e72002-09-23 09:36:25 +0000291
292 /* Check the permissions make sense. */
njnca82cc02004-11-22 17:18:48 +0000293 tl_assert(example_a_bit == VGM_BIT_VALID
njn25e49d8e72002-09-23 09:36:25 +0000294 || example_a_bit == VGM_BIT_INVALID);
295
296 /* In order that we can charge through the address space at 8
297 bytes/main-loop iteration, make up some perms. */
sewardjb5f6f512005-03-10 23:59:00 +0000298 abyte8 = BIT_EXPAND(example_a_bit);
njn25e49d8e72002-09-23 09:36:25 +0000299
300# ifdef VG_DEBUG_MEMORY
301 /* Do it ... */
302 while (True) {
303 PROF_EVENT(31);
304 if (len == 0) break;
305 set_abit ( a, example_a_bit );
306 set_vbyte ( a, vbyte );
307 a++;
308 len--;
309 }
310
311# else
312 /* Slowly do parts preceding 8-byte alignment. */
313 while (True) {
314 PROF_EVENT(31);
315 if (len == 0) break;
316 if ((a % 8) == 0) break;
317 set_abit ( a, example_a_bit );
318 a++;
319 len--;
320 }
321
322 if (len == 0) {
323 VGP_POPCC(VgpSetMem);
324 return;
325 }
njnca82cc02004-11-22 17:18:48 +0000326 tl_assert((a % 8) == 0 && len > 0);
njn25e49d8e72002-09-23 09:36:25 +0000327
sewardjb5f6f512005-03-10 23:59:00 +0000328 /* Once aligned, go fast up to primary boundary. */
329 for (; (a & SECONDARY_MASK) && len >= 8; a += 8, len -= 8) {
njn25e49d8e72002-09-23 09:36:25 +0000330 PROF_EVENT(32);
sewardjb5f6f512005-03-10 23:59:00 +0000331
332 /* If the primary is already pointing to a distinguished map
333 with the same properties as we're trying to set, then leave
334 it that way. */
335 if (primary_map[PM_IDX(a)] == DSM(example_a_bit))
336 continue;
njn25e49d8e72002-09-23 09:36:25 +0000337 ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
sewardjb5f6f512005-03-10 23:59:00 +0000338 sm = primary_map[PM_IDX(a)];
339 sm_off = SM_OFF(a);
njn25e49d8e72002-09-23 09:36:25 +0000340 sm->abits[sm_off >> 3] = abyte8;
njn25e49d8e72002-09-23 09:36:25 +0000341 }
342
sewardjb5f6f512005-03-10 23:59:00 +0000343 /* Now set whole secondary maps to the right distinguished value.
344
345 Note that if the primary already points to a non-distinguished
346 secondary, then don't replace the reference. That would just
347 leak memory.
348 */
349 for(; len >= SECONDARY_SIZE; a += SECONDARY_SIZE, len -= SECONDARY_SIZE) {
350 sm = primary_map[PM_IDX(a)];
351
352 if (IS_DISTINGUISHED_SM(sm))
353 primary_map[PM_IDX(a)] = DSM(example_a_bit);
354 else
355 VG_(memset)(sm->abits, abyte8, sizeof(sm->abits));
njn25e49d8e72002-09-23 09:36:25 +0000356 }
sewardjb5f6f512005-03-10 23:59:00 +0000357
358 /* Now finished the remains. */
359 for (; len >= 8; a += 8, len -= 8) {
360 PROF_EVENT(32);
361
362 /* If the primary is already pointing to a distinguished map
363 with the same properties as we're trying to set, then leave
364 it that way. */
365 if (primary_map[PM_IDX(a)] == DSM(example_a_bit))
366 continue;
367 ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
368 sm = primary_map[PM_IDX(a)];
369 sm_off = SM_OFF(a);
370 sm->abits[sm_off >> 3] = abyte8;
371 }
372
njn25e49d8e72002-09-23 09:36:25 +0000373
374 /* Finish the upper fragment. */
375 while (True) {
376 PROF_EVENT(33);
377 if (len == 0) break;
378 set_abit ( a, example_a_bit );
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
nethercote451eae92004-11-02 13:06:32 +0000393static void ac_make_noaccess ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000394{
395 PROF_EVENT(35);
njn5c004e42002-11-18 11:04:50 +0000396 DEBUG("ac_make_noaccess(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000397 set_address_range_perms ( a, len, VGM_BIT_INVALID );
398}
399
nethercote451eae92004-11-02 13:06:32 +0000400static void ac_make_accessible ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000401{
njn5c004e42002-11-18 11:04:50 +0000402 PROF_EVENT(38);
403 DEBUG("ac_make_accessible(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000404 set_address_range_perms ( a, len, VGM_BIT_VALID );
405}
406
njn9b007f62003-04-07 14:40:25 +0000407static __inline__
408void make_aligned_word_noaccess(Addr a)
409{
410 AcSecMap* sm;
411 UInt sm_off;
412 UChar mask;
413
414 VGP_PUSHCC(VgpESPAdj);
415 ENSURE_MAPPABLE(a, "make_aligned_word_noaccess");
sewardjb5f6f512005-03-10 23:59:00 +0000416 sm = primary_map[PM_IDX(a)];
417 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000418 mask = 0x0F;
419 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
420 /* mask now contains 1s where we wish to make address bits invalid (1s). */
421 sm->abits[sm_off >> 3] |= mask;
422 VGP_POPCC(VgpESPAdj);
423}
424
425static __inline__
426void make_aligned_word_accessible(Addr a)
427{
428 AcSecMap* sm;
429 UInt sm_off;
430 UChar mask;
431
432 VGP_PUSHCC(VgpESPAdj);
433 ENSURE_MAPPABLE(a, "make_aligned_word_accessible");
sewardjb5f6f512005-03-10 23:59:00 +0000434 sm = primary_map[PM_IDX(a)];
435 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000436 mask = 0x0F;
437 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
438 /* mask now contains 1s where we wish to make address bits
439 invalid (0s). */
440 sm->abits[sm_off >> 3] &= ~mask;
441 VGP_POPCC(VgpESPAdj);
442}
443
444/* Nb: by "aligned" here we mean 8-byte aligned */
445static __inline__
446void make_aligned_doubleword_accessible(Addr a)
447{
448 AcSecMap* sm;
449 UInt sm_off;
450
451 VGP_PUSHCC(VgpESPAdj);
452 ENSURE_MAPPABLE(a, "make_aligned_doubleword_accessible");
sewardjb5f6f512005-03-10 23:59:00 +0000453 sm = primary_map[PM_IDX(a)];
454 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000455 sm->abits[sm_off >> 3] = VGM_BYTE_VALID;
456 VGP_POPCC(VgpESPAdj);
457}
458
459static __inline__
460void make_aligned_doubleword_noaccess(Addr a)
461{
462 AcSecMap* sm;
463 UInt sm_off;
464
465 VGP_PUSHCC(VgpESPAdj);
466 ENSURE_MAPPABLE(a, "make_aligned_doubleword_noaccess");
sewardjb5f6f512005-03-10 23:59:00 +0000467 sm = primary_map[PM_IDX(a)];
468 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000469 sm->abits[sm_off >> 3] = VGM_BYTE_INVALID;
470 VGP_POPCC(VgpESPAdj);
471}
472
473/* The %esp update handling functions */
474ESP_UPDATE_HANDLERS ( make_aligned_word_accessible,
475 make_aligned_word_noaccess,
476 make_aligned_doubleword_accessible,
477 make_aligned_doubleword_noaccess,
478 ac_make_accessible,
479 ac_make_noaccess
480 );
481
482
njn25e49d8e72002-09-23 09:36:25 +0000483/* Block-copy permissions (needed for implementing realloc()). */
484
nethercote451eae92004-11-02 13:06:32 +0000485static void ac_copy_address_range_state ( Addr src, Addr dst, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000486{
487 UInt i;
488
njn5c004e42002-11-18 11:04:50 +0000489 DEBUG("ac_copy_address_range_state\n");
njn25e49d8e72002-09-23 09:36:25 +0000490
491 PROF_EVENT(40);
492 for (i = 0; i < len; i++) {
493 UChar abit = get_abit ( src+i );
494 PROF_EVENT(41);
495 set_abit ( dst+i, abit );
496 }
497}
498
499
500/* Check permissions for address range. If inadequate permissions
501 exist, *bad_addr is set to the offending address, so the caller can
502 know what it is. */
503
njn5c004e42002-11-18 11:04:50 +0000504static __inline__
nethercote451eae92004-11-02 13:06:32 +0000505Bool ac_check_accessible ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000506{
507 UInt i;
508 UChar abit;
njn5c004e42002-11-18 11:04:50 +0000509 PROF_EVENT(48);
njn25e49d8e72002-09-23 09:36:25 +0000510 for (i = 0; i < len; i++) {
njn5c004e42002-11-18 11:04:50 +0000511 PROF_EVENT(49);
njn25e49d8e72002-09-23 09:36:25 +0000512 abit = get_abit(a);
513 if (abit == VGM_BIT_INVALID) {
514 if (bad_addr != NULL) *bad_addr = a;
515 return False;
516 }
517 a++;
518 }
519 return True;
520}
521
sewardjecf8e102003-07-12 12:11:39 +0000522/* The opposite; check that an address range is inaccessible. */
523static
nethercote451eae92004-11-02 13:06:32 +0000524Bool ac_check_noaccess ( Addr a, SizeT len, Addr* bad_addr )
sewardjecf8e102003-07-12 12:11:39 +0000525{
526 UInt i;
527 UChar abit;
528 PROF_EVENT(48);
529 for (i = 0; i < len; i++) {
530 PROF_EVENT(49);
531 abit = get_abit(a);
532 if (abit == VGM_BIT_VALID) {
533 if (bad_addr != NULL) *bad_addr = a;
534 return False;
535 }
536 a++;
537 }
538 return True;
539}
540
njn25e49d8e72002-09-23 09:36:25 +0000541/* Check a zero-terminated ascii string. Tricky -- don't want to
542 examine the actual bytes, to find the end, until we're sure it is
543 safe to do so. */
544
njn5c004e42002-11-18 11:04:50 +0000545static __inline__
546Bool ac_check_readable_asciiz ( Addr a, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000547{
548 UChar abit;
549 PROF_EVENT(46);
njn5c004e42002-11-18 11:04:50 +0000550 DEBUG("ac_check_readable_asciiz\n");
njn25e49d8e72002-09-23 09:36:25 +0000551 while (True) {
552 PROF_EVENT(47);
553 abit = get_abit(a);
554 if (abit != VGM_BIT_VALID) {
555 if (bad_addr != NULL) *bad_addr = a;
556 return False;
557 }
558 /* Ok, a is safe to read. */
559 if (* ((UChar*)a) == 0) return True;
560 a++;
561 }
562}
563
564
565/*------------------------------------------------------------*/
566/*--- Memory event handlers ---*/
567/*------------------------------------------------------------*/
568
njn5c004e42002-11-18 11:04:50 +0000569static __inline__
njn72718642003-07-24 08:45:32 +0000570void ac_check_is_accessible ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000571 Char* s, Addr base, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000572{
573 Bool ok;
njn86f12dc2005-03-14 01:16:05 +0000574 Addr bad_addr = 0; // Initialise to shut gcc up
njn25e49d8e72002-09-23 09:36:25 +0000575
576 VGP_PUSHCC(VgpCheckMem);
577
njn5c004e42002-11-18 11:04:50 +0000578 ok = ac_check_accessible ( base, size, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000579 if (!ok) {
580 switch (part) {
581 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +0000582 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
583 /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000584 break;
585
njn25e49d8e72002-09-23 09:36:25 +0000586 case Vg_CoreSignal:
njnca82cc02004-11-22 17:18:48 +0000587 tl_assert(isWrite); /* Should only happen with isWrite case */
njn5c004e42002-11-18 11:04:50 +0000588 /* fall through */
njn25e49d8e72002-09-23 09:36:25 +0000589 case Vg_CorePThread:
nethercote8b76fe52004-11-08 19:20:09 +0000590 MAC_(record_core_mem_error)( tid, /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000591 break;
592
593 /* If we're being asked to jump to a silly address, record an error
594 message before potentially crashing the entire system. */
595 case Vg_CoreTranslate:
njnca82cc02004-11-22 17:18:48 +0000596 tl_assert(!isWrite); /* Should only happen with !isWrite case */
njn72718642003-07-24 08:45:32 +0000597 MAC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000598 break;
599
600 default:
njn67993252004-11-22 18:02:32 +0000601 VG_(tool_panic)("ac_check_is_accessible: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +0000602 }
603 }
njn5c004e42002-11-18 11:04:50 +0000604
njn25e49d8e72002-09-23 09:36:25 +0000605 VGP_POPCC(VgpCheckMem);
606}
607
608static
njn72718642003-07-24 08:45:32 +0000609void ac_check_is_writable ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000610 Char* s, Addr base, SizeT size )
njn5c004e42002-11-18 11:04:50 +0000611{
njn72718642003-07-24 08:45:32 +0000612 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/True );
njn5c004e42002-11-18 11:04:50 +0000613}
614
615static
njn72718642003-07-24 08:45:32 +0000616void ac_check_is_readable ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000617 Char* s, Addr base, SizeT size )
njn5c004e42002-11-18 11:04:50 +0000618{
njn72718642003-07-24 08:45:32 +0000619 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/False );
njn5c004e42002-11-18 11:04:50 +0000620}
621
622static
njn72718642003-07-24 08:45:32 +0000623void ac_check_is_readable_asciiz ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000624 Char* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +0000625{
626 Bool ok = True;
njn86f12dc2005-03-14 01:16:05 +0000627 Addr bad_addr = 0; // Initialise to shut gcc up
njn25e49d8e72002-09-23 09:36:25 +0000628
629 VGP_PUSHCC(VgpCheckMem);
630
njnca82cc02004-11-22 17:18:48 +0000631 tl_assert(part == Vg_CoreSysCall);
njn5c004e42002-11-18 11:04:50 +0000632 ok = ac_check_readable_asciiz ( (Addr)str, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000633 if (!ok) {
nethercote8b76fe52004-11-08 19:20:09 +0000634 MAC_(record_param_error) ( tid, bad_addr, /*IsReg*/False,
635 /*IsUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000636 }
637
638 VGP_POPCC(VgpCheckMem);
639}
640
641static
nethercote451eae92004-11-02 13:06:32 +0000642void ac_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +0000643{
njn1f3a9092002-10-04 09:22:30 +0000644 /* Ignore the permissions, just make it readable. Seems to work... */
njn25e49d8e72002-09-23 09:36:25 +0000645 DEBUG("new_mem_startup(%p, %u, rr=%u, ww=%u, xx=%u)\n", a,len,rr,ww,xx);
njn5c004e42002-11-18 11:04:50 +0000646 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000647}
648
649static
nethercote451eae92004-11-02 13:06:32 +0000650void ac_new_mem_heap ( Addr a, SizeT len, Bool is_inited )
njn25e49d8e72002-09-23 09:36:25 +0000651{
njn5c004e42002-11-18 11:04:50 +0000652 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000653}
654
655static
sewardjb5f6f512005-03-10 23:59:00 +0000656void ac_new_mem_mmap (Addr a, SizeT len, Bool rr, Bool ww, Bool xx)
njn25e49d8e72002-09-23 09:36:25 +0000657{
njn5c004e42002-11-18 11:04:50 +0000658 DEBUG("ac_set_perms(%p, %u, rr=%u ww=%u, xx=%u)\n",
sewardj40f8ebe2002-10-23 21:46:13 +0000659 a, len, rr, ww, xx);
sewardjb5f6f512005-03-10 23:59:00 +0000660 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000661}
662
njncf45fd42004-11-24 16:30:22 +0000663static
664void ac_post_mem_write(CorePart part, ThreadId tid, Addr a, SizeT len)
665{
666 ac_make_accessible(a, len);
667}
668
njn25e49d8e72002-09-23 09:36:25 +0000669
670/*------------------------------------------------------------*/
671/*--- Functions called directly from generated code. ---*/
672/*------------------------------------------------------------*/
673
674static __inline__ UInt rotateRight16 ( UInt x )
675{
676 /* Amazingly, gcc turns this into a single rotate insn. */
677 return (x >> 16) | (x << 16);
678}
679
njn25e49d8e72002-09-23 09:36:25 +0000680static __inline__ UInt shiftRight16 ( UInt x )
681{
682 return x >> 16;
683}
684
685
686/* Read/write 1/2/4 sized V bytes, and emit an address error if
687 needed. */
688
njn5c004e42002-11-18 11:04:50 +0000689/* ac_helperc_ACCESS{1,2,4} handle the common case fast.
njn25e49d8e72002-09-23 09:36:25 +0000690 Under all other circumstances, it defers to the relevant _SLOWLY
691 function, which can handle all situations.
692*/
njnc2699f62003-09-05 23:29:33 +0000693static __inline__ void ac_helperc_ACCESS4 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000694{
695# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000696 return ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000697# else
698 UInt sec_no = rotateRight16(a) & 0x3FFFF;
njnda2e36d2003-09-30 13:33:24 +0000699 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000700 UInt a_off = (SM_OFF(a)) >> 3;
njn25e49d8e72002-09-23 09:36:25 +0000701 UChar abits = sm->abits[a_off];
702 abits >>= (a & 4);
703 abits &= 15;
njn5c004e42002-11-18 11:04:50 +0000704 PROF_EVENT(66);
njn25e49d8e72002-09-23 09:36:25 +0000705 if (abits == VGM_NIBBLE_VALID) {
706 /* Handle common case quickly: a is suitably aligned, is mapped,
707 and is addressible. So just return. */
708 return;
709 } else {
710 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000711 ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000712 }
713# endif
714}
715
njnc2699f62003-09-05 23:29:33 +0000716static __inline__ void ac_helperc_ACCESS2 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000717{
718# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000719 return ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000720# else
721 UInt sec_no = rotateRight16(a) & 0x1FFFF;
722 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000723 UInt a_off = (SM_OFF(a)) >> 3;
njn5c004e42002-11-18 11:04:50 +0000724 PROF_EVENT(67);
njn25e49d8e72002-09-23 09:36:25 +0000725 if (sm->abits[a_off] == VGM_BYTE_VALID) {
726 /* Handle common case quickly. */
727 return;
728 } else {
729 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000730 ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000731 }
732# endif
733}
734
njnc2699f62003-09-05 23:29:33 +0000735static __inline__ void ac_helperc_ACCESS1 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000736{
737# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000738 return ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000739# else
740 UInt sec_no = shiftRight16(a);
741 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000742 UInt a_off = (SM_OFF(a)) >> 3;
njn5c004e42002-11-18 11:04:50 +0000743 PROF_EVENT(68);
njn25e49d8e72002-09-23 09:36:25 +0000744 if (sm->abits[a_off] == VGM_BYTE_VALID) {
745 /* Handle common case quickly. */
746 return;
747 } else {
748 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000749 ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000750 }
751# endif
752}
753
nethercoteeec46302004-08-23 15:06:23 +0000754REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000755static void ach_LOAD4 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000756{
757 ac_helperc_ACCESS4 ( a, /*isWrite*/False );
758}
nethercoteeec46302004-08-23 15:06:23 +0000759REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000760static void ach_STORE4 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000761{
762 ac_helperc_ACCESS4 ( a, /*isWrite*/True );
763}
764
nethercoteeec46302004-08-23 15:06:23 +0000765REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000766static void ach_LOAD2 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000767{
768 ac_helperc_ACCESS2 ( a, /*isWrite*/False );
769}
nethercoteeec46302004-08-23 15:06:23 +0000770REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000771static void ach_STORE2 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000772{
773 ac_helperc_ACCESS2 ( a, /*isWrite*/True );
774}
775
nethercoteeec46302004-08-23 15:06:23 +0000776REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000777static void ach_LOAD1 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000778{
779 ac_helperc_ACCESS1 ( a, /*isWrite*/False );
780}
nethercoteeec46302004-08-23 15:06:23 +0000781REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000782static void ach_STORE1 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000783{
784 ac_helperc_ACCESS1 ( a, /*isWrite*/True );
785}
786
njn25e49d8e72002-09-23 09:36:25 +0000787
788/*------------------------------------------------------------*/
789/*--- Fallback functions to handle cases that the above ---*/
njnc2699f62003-09-05 23:29:33 +0000790/*--- ac_helperc_ACCESS{1,2,4} can't manage. ---*/
njn25e49d8e72002-09-23 09:36:25 +0000791/*------------------------------------------------------------*/
792
njnc2699f62003-09-05 23:29:33 +0000793static void ac_ACCESS4_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000794{
795 Bool a0ok, a1ok, a2ok, a3ok;
796
njn5c004e42002-11-18 11:04:50 +0000797 PROF_EVENT(76);
njn25e49d8e72002-09-23 09:36:25 +0000798
799 /* First establish independently the addressibility of the 4 bytes
800 involved. */
801 a0ok = get_abit(a+0) == VGM_BIT_VALID;
802 a1ok = get_abit(a+1) == VGM_BIT_VALID;
803 a2ok = get_abit(a+2) == VGM_BIT_VALID;
804 a3ok = get_abit(a+3) == VGM_BIT_VALID;
805
806 /* Now distinguish 3 cases */
807
808 /* Case 1: the address is completely valid, so:
809 - no addressing error
810 */
811 if (a0ok && a1ok && a2ok && a3ok) {
812 return;
813 }
814
815 /* Case 2: the address is completely invalid.
816 - emit addressing error
817 */
818 /* VG_(printf)("%p (%d %d %d %d)\n", a, a0ok, a1ok, a2ok, a3ok); */
njn43c799e2003-04-08 00:08:52 +0000819 if (!MAC_(clo_partial_loads_ok)
njn25e49d8e72002-09-23 09:36:25 +0000820 || ((a & 3) != 0)
821 || (!a0ok && !a1ok && !a2ok && !a3ok)) {
sewardj76754cf2005-03-14 00:14:04 +0000822 MAC_(record_address_error)( VG_(get_running_tid)(), a, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000823 return;
824 }
825
826 /* Case 3: the address is partially valid.
827 - no addressing error
njn43c799e2003-04-08 00:08:52 +0000828 Case 3 is only allowed if MAC_(clo_partial_loads_ok) is True
njn25e49d8e72002-09-23 09:36:25 +0000829 (which is the default), and the address is 4-aligned.
830 If not, Case 2 will have applied.
831 */
njnca82cc02004-11-22 17:18:48 +0000832 tl_assert(MAC_(clo_partial_loads_ok));
njn25e49d8e72002-09-23 09:36:25 +0000833 {
834 return;
835 }
836}
837
njnc2699f62003-09-05 23:29:33 +0000838static void ac_ACCESS2_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000839{
840 /* Check the address for validity. */
841 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000842 PROF_EVENT(77);
njn25e49d8e72002-09-23 09:36:25 +0000843
844 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
845 if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
846
847 /* If an address error has happened, report it. */
848 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000849 MAC_(record_address_error)( VG_(get_running_tid)(), a, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000850 }
851}
852
njnc2699f62003-09-05 23:29:33 +0000853static void ac_ACCESS1_SLOWLY ( Addr a, Bool isWrite)
njn25e49d8e72002-09-23 09:36:25 +0000854{
855 /* Check the address for validity. */
856 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000857 PROF_EVENT(78);
njn25e49d8e72002-09-23 09:36:25 +0000858
859 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
860
861 /* If an address error has happened, report it. */
862 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000863 MAC_(record_address_error)( VG_(get_running_tid)(), a, 1, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000864 }
865}
866
867
868/* ---------------------------------------------------------------------
869 FPU load and store checks, called from generated code.
870 ------------------------------------------------------------------ */
871
sewardj56867352003-10-12 10:27:06 +0000872static
nethercote928a5f72004-11-03 18:10:37 +0000873void ac_fpu_ACCESS_check ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000874{
875 /* Ensure the read area is both addressible and valid (ie,
876 readable). If there's an address error, don't report a value
877 error too; but if there isn't an address error, check for a
878 value error.
879
880 Try to be reasonably fast on the common case; wimp out and defer
njn5c004e42002-11-18 11:04:50 +0000881 to ac_fpu_ACCESS_check_SLOWLY for everything else. */
njn25e49d8e72002-09-23 09:36:25 +0000882
883 AcSecMap* sm;
884 UInt sm_off, a_off;
885 Addr addr4;
886
njn5c004e42002-11-18 11:04:50 +0000887 PROF_EVENT(90);
njn25e49d8e72002-09-23 09:36:25 +0000888
889# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000890 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000891# else
892
893 if (size == 4) {
njnbe91aae2005-03-27 01:42:41 +0000894 if (!VG_IS_4_ALIGNED(addr)) goto slow4;
njn5c004e42002-11-18 11:04:50 +0000895 PROF_EVENT(91);
njn25e49d8e72002-09-23 09:36:25 +0000896 /* Properly aligned. */
sewardjb5f6f512005-03-10 23:59:00 +0000897 sm = primary_map[PM_IDX(addr)];
898 sm_off = SM_OFF(addr);
njn25e49d8e72002-09-23 09:36:25 +0000899 a_off = sm_off >> 3;
900 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow4;
901 /* Properly aligned and addressible. */
902 return;
903 slow4:
njnc2699f62003-09-05 23:29:33 +0000904 ac_fpu_ACCESS_check_SLOWLY ( addr, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000905 return;
906 }
907
908 if (size == 8) {
njnbe91aae2005-03-27 01:42:41 +0000909 if (!VG_IS_4_ALIGNED(addr)) goto slow8;
njn5c004e42002-11-18 11:04:50 +0000910 PROF_EVENT(92);
njn25e49d8e72002-09-23 09:36:25 +0000911 /* Properly aligned. Do it in two halves. */
912 addr4 = addr + 4;
913 /* First half. */
sewardjb5f6f512005-03-10 23:59:00 +0000914 sm = primary_map[PM_IDX(addr)];
915 sm_off = SM_OFF(addr);
njn25e49d8e72002-09-23 09:36:25 +0000916 a_off = sm_off >> 3;
917 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
918 /* First half properly aligned and addressible. */
919 /* Second half. */
sewardjb5f6f512005-03-10 23:59:00 +0000920 sm = primary_map[PM_IDX(addr4)];
921 sm_off = SM_OFF(addr4);
njn25e49d8e72002-09-23 09:36:25 +0000922 a_off = sm_off >> 3;
923 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
924 /* Second half properly aligned and addressible. */
925 /* Both halves properly aligned and addressible. */
926 return;
927 slow8:
njnc2699f62003-09-05 23:29:33 +0000928 ac_fpu_ACCESS_check_SLOWLY ( addr, 8, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000929 return;
930 }
931
932 /* Can't be bothered to huff'n'puff to make these (allegedly) rare
933 cases go quickly. */
934 if (size == 2) {
njn5c004e42002-11-18 11:04:50 +0000935 PROF_EVENT(93);
njnc2699f62003-09-05 23:29:33 +0000936 ac_fpu_ACCESS_check_SLOWLY ( addr, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000937 return;
938 }
939
jsewardfca60182004-01-04 23:30:55 +0000940 if (size == 16 || size == 10 || size == 28 || size == 108 || size == 512) {
njn5c004e42002-11-18 11:04:50 +0000941 PROF_EVENT(94);
njnc2699f62003-09-05 23:29:33 +0000942 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000943 return;
944 }
945
946 VG_(printf)("size is %d\n", size);
njn67993252004-11-22 18:02:32 +0000947 VG_(tool_panic)("fpu_ACCESS_check: unhandled size");
njn25e49d8e72002-09-23 09:36:25 +0000948# endif
949}
950
nethercoteeec46302004-08-23 15:06:23 +0000951REGPARM(2)
sewardj9f649aa2004-11-22 20:38:40 +0000952static void ach_LOADN ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000953{
954 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/False );
955}
956
nethercoteeec46302004-08-23 15:06:23 +0000957REGPARM(2)
sewardj9f649aa2004-11-22 20:38:40 +0000958static void ach_STOREN ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000959{
960 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/True );
961}
njn25e49d8e72002-09-23 09:36:25 +0000962
sewardjd62e03b2004-12-10 12:01:14 +0000963
njn25e49d8e72002-09-23 09:36:25 +0000964/* ---------------------------------------------------------------------
965 Slow, general cases for FPU access checks.
966 ------------------------------------------------------------------ */
967
nethercote928a5f72004-11-03 18:10:37 +0000968void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000969{
970 Int i;
971 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000972 PROF_EVENT(100);
njn25e49d8e72002-09-23 09:36:25 +0000973 for (i = 0; i < size; i++) {
njn5c004e42002-11-18 11:04:50 +0000974 PROF_EVENT(101);
njn25e49d8e72002-09-23 09:36:25 +0000975 if (get_abit(addr+i) != VGM_BIT_VALID)
976 aerr = True;
977 }
978
979 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000980 MAC_(record_address_error)( VG_(get_running_tid)(), addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000981 }
982}
983
984
985/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000986/*--- Our instrumenter ---*/
987/*------------------------------------------------------------*/
988
sewardjd54babf2005-03-21 00:55:49 +0000989IRBB* TL_(instrument)(IRBB* bb_in, VexGuestLayout* layout,
990 IRType gWordTy, IRType hWordTy )
njn25e49d8e72002-09-23 09:36:25 +0000991{
sewardj9f649aa2004-11-22 20:38:40 +0000992 Int i, hsz;
993 IRStmt* st;
994 IRExpr* data;
995 IRExpr* aexpr;
996 IRExpr* guard;
997 IRDirty* di;
998 Bool isLoad;
sewardjd54babf2005-03-21 00:55:49 +0000999 IRBB* bb;
1000
1001 if (gWordTy != hWordTy) {
1002 /* We don't currently support this case. */
1003 VG_(tool_panic)("host/guest word size mismatch");
1004 }
njn25e49d8e72002-09-23 09:36:25 +00001005
sewardj9f649aa2004-11-22 20:38:40 +00001006 /* Set up BB */
sewardjd54babf2005-03-21 00:55:49 +00001007 bb = emptyIRBB();
sewardj9f649aa2004-11-22 20:38:40 +00001008 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
1009 bb->next = dopyIRExpr(bb_in->next);
1010 bb->jumpkind = bb_in->jumpkind;
njn25e49d8e72002-09-23 09:36:25 +00001011
sewardj9f649aa2004-11-22 20:38:40 +00001012 /* No loads to consider in ->next. */
sewardj710d6c22005-03-20 18:55:15 +00001013 tl_assert(isIRAtom(bb_in->next));
njn25e49d8e72002-09-23 09:36:25 +00001014
sewardj9f649aa2004-11-22 20:38:40 +00001015 for (i = 0; i < bb_in->stmts_used; i++) {
1016 st = bb_in->stmts[i];
sewardj21dc3452005-03-21 00:27:41 +00001017 tl_assert(st);
njn25e49d8e72002-09-23 09:36:25 +00001018
sewardj9f649aa2004-11-22 20:38:40 +00001019 /* Examine each stmt in turn to figure out if it needs to be
1020 preceded by a memory access check. If so, collect up the
1021 relevant pieces of information. */
1022 hsz = 0;
1023 aexpr = NULL;
1024 guard = NULL;
1025 isLoad = True;
njn25e49d8e72002-09-23 09:36:25 +00001026
sewardj9f649aa2004-11-22 20:38:40 +00001027 switch (st->tag) {
1028
1029 case Ist_Tmp:
1030 data = st->Ist.Tmp.data;
1031 if (data->tag == Iex_LDle) {
1032 aexpr = data->Iex.LDle.addr;
1033 hsz = sizeofIRType(data->Iex.LDle.ty);
1034 isLoad = True;
1035 }
1036 break;
1037
1038 case Ist_STle:
1039 data = st->Ist.STle.data;
1040 aexpr = st->Ist.STle.addr;
sewardj710d6c22005-03-20 18:55:15 +00001041 tl_assert(isIRAtom(data));
1042 tl_assert(isIRAtom(aexpr));
sewardj9f649aa2004-11-22 20:38:40 +00001043 hsz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
1044 isLoad = False;
sewardj08ccc5c2005-03-17 03:17:54 +00001045 break;
sewardj9f649aa2004-11-22 20:38:40 +00001046
1047 case Ist_Put:
sewardj710d6c22005-03-20 18:55:15 +00001048 tl_assert(isIRAtom(st->Ist.Put.data));
njn25e49d8e72002-09-23 09:36:25 +00001049 break;
1050
sewardj9f649aa2004-11-22 20:38:40 +00001051 case Ist_PutI:
sewardj710d6c22005-03-20 18:55:15 +00001052 tl_assert(isIRAtom(st->Ist.PutI.ix));
1053 tl_assert(isIRAtom(st->Ist.PutI.data));
njnc2699f62003-09-05 23:29:33 +00001054 break;
1055
sewardj9f649aa2004-11-22 20:38:40 +00001056 case Ist_Exit:
sewardj710d6c22005-03-20 18:55:15 +00001057 tl_assert(isIRAtom(st->Ist.Exit.guard));
njn25e49d8e72002-09-23 09:36:25 +00001058 break;
1059
sewardj9f649aa2004-11-22 20:38:40 +00001060 case Ist_Dirty:
1061 if (st->Ist.Dirty.details->mFx != Ifx_None) {
1062 /* We classify Ifx_Modify as a load. */
1063 isLoad = st->Ist.Dirty.details->mFx != Ifx_Write;
1064 hsz = st->Ist.Dirty.details->mSize;
1065 aexpr = st->Ist.Dirty.details->mAddr;
1066 guard = st->Ist.Dirty.details->guard;
sewardj710d6c22005-03-20 18:55:15 +00001067 tl_assert(isIRAtom(aexpr));
sewardj9f649aa2004-11-22 20:38:40 +00001068 }
1069 break;
sewardje3891fa2003-06-15 03:13:48 +00001070
sewardj21dc3452005-03-21 00:27:41 +00001071 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00001072 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00001073 case Ist_MFence:
1074 break;
1075
njn25e49d8e72002-09-23 09:36:25 +00001076 default:
sewardj9f649aa2004-11-22 20:38:40 +00001077 VG_(printf)("\n");
1078 ppIRStmt(st);
1079 VG_(printf)("\n");
1080 VG_(tool_panic)("addrcheck: unhandled IRStmt");
njn25e49d8e72002-09-23 09:36:25 +00001081 }
sewardj9f649aa2004-11-22 20:38:40 +00001082
1083 /* If needed, add a helper call. */
1084 if (aexpr) {
1085 tl_assert(hsz > 0);
1086 switch (hsz) {
1087 case 4:
1088 if (isLoad)
1089 di = unsafeIRDirty_0_N( 1, "ach_LOAD4", &ach_LOAD4,
1090 mkIRExprVec_1(aexpr));
1091 else
1092 di = unsafeIRDirty_0_N( 1, "ach_STORE4", &ach_STORE4,
1093 mkIRExprVec_1(aexpr));
1094 break;
1095 case 2:
1096 if (isLoad)
1097 di = unsafeIRDirty_0_N( 1, "ach_LOAD2", &ach_LOAD2,
1098 mkIRExprVec_1(aexpr));
1099 else
1100 di = unsafeIRDirty_0_N( 1, "ach_STORE2", &ach_STORE2,
1101 mkIRExprVec_1(aexpr));
1102 break;
1103 case 1:
1104 if (isLoad)
1105 di = unsafeIRDirty_0_N( 1, "ach_LOAD1", &ach_LOAD1,
1106 mkIRExprVec_1(aexpr));
1107 else
1108 di = unsafeIRDirty_0_N( 1, "ach_STORE1", &ach_STORE1,
1109 mkIRExprVec_1(aexpr));
1110 break;
1111 default:
1112 if (isLoad)
1113 di = unsafeIRDirty_0_N(
1114 2, "ach_LOADN", &ach_LOADN,
1115 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1116 else
1117 di = unsafeIRDirty_0_N(
1118 2, "ach_STOREN", &ach_STOREN,
1119 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1120 break;
1121 }
1122
1123 /* If the call has arisen as a result of a dirty helper which
1124 references memory, we need to inherit the guard from the
1125 dirty helper. */
1126 if (guard)
1127 di->guard = dopyIRExpr(guard);
1128
1129 /* emit the helper call */
1130 addStmtToIRBB( bb, IRStmt_Dirty(di) );
1131
1132 }
1133
1134 /* And finally, copy the expr itself to the output. */
sewardjbd598e12005-01-07 12:10:21 +00001135 addStmtToIRBB( bb, st );
njn25e49d8e72002-09-23 09:36:25 +00001136 }
1137
sewardj9f649aa2004-11-22 20:38:40 +00001138 return bb;
njn25e49d8e72002-09-23 09:36:25 +00001139}
1140
1141
njn25e49d8e72002-09-23 09:36:25 +00001142/*------------------------------------------------------------*/
1143/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
1144/*------------------------------------------------------------*/
1145
sewardja4495682002-10-21 07:29:59 +00001146/* For the memory leak detector, say whether an entire 64k chunk of
1147 address space is possibly in use, or not. If in doubt return
1148 True.
njn25e49d8e72002-09-23 09:36:25 +00001149*/
sewardja4495682002-10-21 07:29:59 +00001150static
1151Bool ac_is_valid_64k_chunk ( UInt chunk_number )
njn25e49d8e72002-09-23 09:36:25 +00001152{
sewardjb5f6f512005-03-10 23:59:00 +00001153 tl_assert(chunk_number >= 0 && chunk_number < PRIMARY_SIZE);
1154 if (primary_map[chunk_number] == DSM_NOTADDR) {
sewardja4495682002-10-21 07:29:59 +00001155 /* Definitely not in use. */
1156 return False;
1157 } else {
1158 return True;
njn25e49d8e72002-09-23 09:36:25 +00001159 }
1160}
1161
1162
sewardja4495682002-10-21 07:29:59 +00001163/* For the memory leak detector, say whether or not a given word
1164 address is to be regarded as valid. */
1165static
1166Bool ac_is_valid_address ( Addr a )
1167{
1168 UChar abits;
njnbe91aae2005-03-27 01:42:41 +00001169 tl_assert(VG_IS_4_ALIGNED(a));
sewardja4495682002-10-21 07:29:59 +00001170 abits = get_abits4_ALIGNED(a);
1171 if (abits == VGM_NIBBLE_VALID) {
1172 return True;
1173 } else {
1174 return False;
1175 }
1176}
1177
1178
nethercote996901a2004-08-03 13:29:09 +00001179/* Leak detector for this tool. We don't actually do anything, merely
sewardja4495682002-10-21 07:29:59 +00001180 run the generic leak detector with suitable parameters for this
nethercote996901a2004-08-03 13:29:09 +00001181 tool. */
njnb8dca862005-03-14 02:42:44 +00001182static void ac_detect_memory_leaks ( ThreadId tid, LeakCheckMode mode )
njn25e49d8e72002-09-23 09:36:25 +00001183{
njnb8dca862005-03-14 02:42:44 +00001184 MAC_(do_detect_memory_leaks) ( tid, mode, ac_is_valid_64k_chunk, ac_is_valid_address );
njn25e49d8e72002-09-23 09:36:25 +00001185}
1186
1187
1188/* ---------------------------------------------------------------------
1189 Sanity check machinery (permanently engaged).
1190 ------------------------------------------------------------------ */
1191
njn26f02512004-11-22 18:33:15 +00001192Bool TL_(cheap_sanity_check) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001193{
jseward9800fd32004-01-04 23:08:04 +00001194 /* nothing useful we can rapidly check */
1195 return True;
njn25e49d8e72002-09-23 09:36:25 +00001196}
1197
njn26f02512004-11-22 18:33:15 +00001198Bool TL_(expensive_sanity_check) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001199{
1200 Int i;
1201
sewardjb5f6f512005-03-10 23:59:00 +00001202#if 0
njn25e49d8e72002-09-23 09:36:25 +00001203 /* Make sure nobody changed the distinguished secondary. */
1204 for (i = 0; i < 8192; i++)
1205 if (distinguished_secondary_map.abits[i] != VGM_BYTE_INVALID)
1206 return False;
sewardjb5f6f512005-03-10 23:59:00 +00001207#endif
njn25e49d8e72002-09-23 09:36:25 +00001208
1209 /* Make sure that the upper 3/4 of the primary map hasn't
1210 been messed with. */
sewardjb5f6f512005-03-10 23:59:00 +00001211 for (i = PRIMARY_SIZE; i < PRIMARY_SIZE*4; i++)
1212 if (primary_map[i] != DSM_NOTADDR)
njn25e49d8e72002-09-23 09:36:25 +00001213 return False;
1214
1215 return True;
1216}
1217
njn47363ab2003-04-21 13:24:40 +00001218/*------------------------------------------------------------*/
1219/*--- Client requests ---*/
1220/*------------------------------------------------------------*/
1221
njn26f02512004-11-22 18:33:15 +00001222Bool TL_(handle_client_request) ( ThreadId tid, UWord* arg, UWord *ret )
sewardjd8033d92002-12-08 22:16:58 +00001223{
sewardjbf310d92002-12-28 13:09:57 +00001224#define IGNORE(what) \
1225 do { \
1226 if (moans-- > 0) { \
1227 VG_(message)(Vg_UserMsg, \
1228 "Warning: Addrcheck: ignoring `%s' request.", what); \
1229 VG_(message)(Vg_UserMsg, \
nethercote137bc552003-11-14 17:47:54 +00001230 " To honour this request, rerun with --tool=memcheck."); \
sewardjbf310d92002-12-28 13:09:57 +00001231 } \
1232 } while (0)
1233
sewardjbf310d92002-12-28 13:09:57 +00001234 static Int moans = 3;
sewardjd8033d92002-12-08 22:16:58 +00001235
1236 /* Overload memcheck client reqs */
njnfc26ff92004-11-22 19:12:49 +00001237 if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
sewardjd62e03b2004-12-10 12:01:14 +00001238 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
1239 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
1240 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
1241 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
1242 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
1243 && VG_USERREQ__MEMPOOL_FREE != arg[0])
sewardjd8033d92002-12-08 22:16:58 +00001244 return False;
1245
1246 switch (arg[0]) {
1247 case VG_USERREQ__DO_LEAK_CHECK:
njnb8dca862005-03-14 02:42:44 +00001248 ac_detect_memory_leaks(tid, arg[1] ? LC_Summary : LC_Full);
sewardjd8033d92002-12-08 22:16:58 +00001249 *ret = 0; /* return value is meaningless */
1250 break;
1251
sewardjbf310d92002-12-28 13:09:57 +00001252 /* Ignore these */
sewardjd8033d92002-12-08 22:16:58 +00001253 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
sewardjbf310d92002-12-28 13:09:57 +00001254 IGNORE("VALGRIND_CHECK_WRITABLE");
1255 return False;
sewardjd8033d92002-12-08 22:16:58 +00001256 case VG_USERREQ__CHECK_READABLE: /* check readable */
sewardjbf310d92002-12-28 13:09:57 +00001257 IGNORE("VALGRIND_CHECK_READABLE");
1258 return False;
sewardjd8033d92002-12-08 22:16:58 +00001259 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
sewardjbf310d92002-12-28 13:09:57 +00001260 IGNORE("VALGRIND_MAKE_NOACCESS");
1261 return False;
sewardjd8033d92002-12-08 22:16:58 +00001262 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
sewardjbf310d92002-12-28 13:09:57 +00001263 IGNORE("VALGRIND_MAKE_WRITABLE");
1264 return False;
sewardjd8033d92002-12-08 22:16:58 +00001265 case VG_USERREQ__MAKE_READABLE: /* make readable */
sewardjbf310d92002-12-28 13:09:57 +00001266 IGNORE("VALGRIND_MAKE_READABLE");
1267 return False;
sewardjd8033d92002-12-08 22:16:58 +00001268 case VG_USERREQ__DISCARD: /* discard */
sewardjbf310d92002-12-28 13:09:57 +00001269 IGNORE("VALGRIND_CHECK_DISCARD");
1270 return False;
sewardjd8033d92002-12-08 22:16:58 +00001271
1272 default:
nethercoted1b64b22004-11-04 18:22:28 +00001273 if (MAC_(handle_common_client_requests)(tid, arg, ret )) {
njn47363ab2003-04-21 13:24:40 +00001274 return True;
1275 } else {
1276 VG_(message)(Vg_UserMsg,
nethercoted1b64b22004-11-04 18:22:28 +00001277 "Warning: unknown addrcheck client request code %llx",
1278 (ULong)arg[0]);
njn47363ab2003-04-21 13:24:40 +00001279 return False;
1280 }
sewardjd8033d92002-12-08 22:16:58 +00001281 }
1282 return True;
sewardjbf310d92002-12-28 13:09:57 +00001283
1284#undef IGNORE
sewardjd8033d92002-12-08 22:16:58 +00001285}
1286
njn25e49d8e72002-09-23 09:36:25 +00001287/*------------------------------------------------------------*/
1288/*--- Setup ---*/
1289/*------------------------------------------------------------*/
1290
njn26f02512004-11-22 18:33:15 +00001291Bool TL_(process_cmd_line_option)(Char* arg)
njn25e49d8e72002-09-23 09:36:25 +00001292{
njn43c799e2003-04-08 00:08:52 +00001293 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001294}
1295
njn26f02512004-11-22 18:33:15 +00001296void TL_(print_usage)(void)
njn25e49d8e72002-09-23 09:36:25 +00001297{
njn3e884182003-04-15 13:03:23 +00001298 MAC_(print_common_usage)();
1299}
1300
njn26f02512004-11-22 18:33:15 +00001301void TL_(print_debug_usage)(void)
njn3e884182003-04-15 13:03:23 +00001302{
1303 MAC_(print_common_debug_usage)();
njn25e49d8e72002-09-23 09:36:25 +00001304}
1305
1306
1307/*------------------------------------------------------------*/
1308/*--- Setup ---*/
1309/*------------------------------------------------------------*/
1310
njn26f02512004-11-22 18:33:15 +00001311void TL_(pre_clo_init)(void)
njn25e49d8e72002-09-23 09:36:25 +00001312{
njn810086f2002-11-14 12:42:47 +00001313 VG_(details_name) ("Addrcheck");
1314 VG_(details_version) (NULL);
1315 VG_(details_description) ("a fine-grained address checker");
1316 VG_(details_copyright_author)(
njn53612422005-03-12 16:22:54 +00001317 "Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.");
nethercote421281e2003-11-20 16:20:55 +00001318 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardj78210aa2002-12-01 02:55:46 +00001319 VG_(details_avg_translation_sizeB) ( 135 );
njn25e49d8e72002-09-23 09:36:25 +00001320
njn810086f2002-11-14 12:42:47 +00001321 VG_(needs_core_errors) ();
njn95ec8702004-11-22 16:46:13 +00001322 VG_(needs_tool_errors) ();
njn810086f2002-11-14 12:42:47 +00001323 VG_(needs_libc_freeres) ();
njn810086f2002-11-14 12:42:47 +00001324 VG_(needs_command_line_options)();
1325 VG_(needs_client_requests) ();
njn810086f2002-11-14 12:42:47 +00001326 VG_(needs_sanity_checks) ();
fitzhardinge98abfc72003-12-16 02:05:15 +00001327 VG_(needs_shadow_memory) ();
njn25e49d8e72002-09-23 09:36:25 +00001328
njn3e884182003-04-15 13:03:23 +00001329 MAC_( new_mem_heap) = & ac_new_mem_heap;
1330 MAC_( ban_mem_heap) = & ac_make_noaccess;
1331 MAC_(copy_mem_heap) = & ac_copy_address_range_state;
1332 MAC_( die_mem_heap) = & ac_make_noaccess;
sewardjecf8e102003-07-12 12:11:39 +00001333 MAC_(check_noaccess) = & ac_check_noaccess;
njn3e884182003-04-15 13:03:23 +00001334
fitzhardinge98abfc72003-12-16 02:05:15 +00001335 VG_(init_new_mem_startup) ( & ac_new_mem_startup );
1336 VG_(init_new_mem_stack_signal) ( & ac_make_accessible );
1337 VG_(init_new_mem_brk) ( & ac_make_accessible );
sewardjb5f6f512005-03-10 23:59:00 +00001338 VG_(init_new_mem_mmap) ( & ac_new_mem_mmap );
njn25e49d8e72002-09-23 09:36:25 +00001339
fitzhardinge98abfc72003-12-16 02:05:15 +00001340 VG_(init_copy_mem_remap) ( & ac_copy_address_range_state );
njn3e884182003-04-15 13:03:23 +00001341
fitzhardinge98abfc72003-12-16 02:05:15 +00001342 VG_(init_die_mem_stack_signal) ( & ac_make_noaccess );
1343 VG_(init_die_mem_brk) ( & ac_make_noaccess );
1344 VG_(init_die_mem_munmap) ( & ac_make_noaccess );
njn3e884182003-04-15 13:03:23 +00001345
fitzhardinge98abfc72003-12-16 02:05:15 +00001346 VG_(init_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
1347 VG_(init_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
1348 VG_(init_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
1349 VG_(init_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
1350 VG_(init_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
1351 VG_(init_new_mem_stack) ( & MAC_(new_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001352
fitzhardinge98abfc72003-12-16 02:05:15 +00001353 VG_(init_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
1354 VG_(init_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
1355 VG_(init_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
1356 VG_(init_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
1357 VG_(init_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
1358 VG_(init_die_mem_stack) ( & MAC_(die_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001359
fitzhardinge98abfc72003-12-16 02:05:15 +00001360 VG_(init_ban_mem_stack) ( & ac_make_noaccess );
njn25e49d8e72002-09-23 09:36:25 +00001361
fitzhardinge98abfc72003-12-16 02:05:15 +00001362 VG_(init_pre_mem_read) ( & ac_check_is_readable );
1363 VG_(init_pre_mem_read_asciiz) ( & ac_check_is_readable_asciiz );
1364 VG_(init_pre_mem_write) ( & ac_check_is_writable );
njnabb14ad2004-11-24 16:57:16 +00001365 VG_(init_post_mem_write) ( & ac_post_mem_write );
njn25e49d8e72002-09-23 09:36:25 +00001366
njn31066fd2005-03-26 00:42:02 +00001367 VG_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
1368 VG_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
1369 VG_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
njnd04b7c62002-10-03 14:05:52 +00001370
1371 init_shadow_memory();
njn3e884182003-04-15 13:03:23 +00001372 MAC_(common_pre_clo_init)();
njn5c004e42002-11-18 11:04:50 +00001373}
1374
njn26f02512004-11-22 18:33:15 +00001375void TL_(post_clo_init) ( void )
njn5c004e42002-11-18 11:04:50 +00001376{
1377}
1378
njn26f02512004-11-22 18:33:15 +00001379void TL_(fini) ( Int exitcode )
njn5c004e42002-11-18 11:04:50 +00001380{
njn3e884182003-04-15 13:03:23 +00001381 MAC_(common_fini)( ac_detect_memory_leaks );
njn25e49d8e72002-09-23 09:36:25 +00001382}
1383
njn26f02512004-11-22 18:33:15 +00001384VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 1./8)
fitzhardinge98abfc72003-12-16 02:05:15 +00001385
1386
njn25e49d8e72002-09-23 09:36:25 +00001387/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00001388/*--- end ac_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00001389/*--------------------------------------------------------------------*/