blob: 91584cc502a6c8a1022c0d399f71f01fcabc63b1 [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 */
172 sk_assert(VGM_BIT_INVALID == 1);
173 sk_assert(VGM_BIT_VALID == 0);
174
175 for(a = 0; a <= 1; a++)
176 sk_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
njnedfa0f62004-11-30 18:08:05 +0000249 tl_assert(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;
574 Addr bad_addr;
575
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;
627 Addr bad_addr;
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)) {
sewardjb5f6f512005-03-10 23:59:00 +0000822 MAC_(record_address_error)( VG_(get_VCPU_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) {
sewardjb5f6f512005-03-10 23:59:00 +0000849 MAC_(record_address_error)( VG_(get_VCPU_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) {
sewardjb5f6f512005-03-10 23:59:00 +0000863 MAC_(record_address_error)( VG_(get_VCPU_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) {
njnedfa0f62004-11-30 18:08:05 +0000894 if (!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) {
njnedfa0f62004-11-30 18:08:05 +0000909 if (!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) {
sewardjb5f6f512005-03-10 23:59:00 +0000980 MAC_(record_address_error)( VG_(get_VCPU_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
sewardj9f649aa2004-11-22 20:38:40 +0000989IRBB* TL_(instrument)(IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
njn25e49d8e72002-09-23 09:36:25 +0000990{
sewardj9f649aa2004-11-22 20:38:40 +0000991 Int i, hsz;
992 IRStmt* st;
993 IRExpr* data;
994 IRExpr* aexpr;
995 IRExpr* guard;
996 IRDirty* di;
997 Bool isLoad;
njn25e49d8e72002-09-23 09:36:25 +0000998
sewardj9f649aa2004-11-22 20:38:40 +0000999 /* Set up BB */
1000 IRBB* bb = emptyIRBB();
1001 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
1002 bb->next = dopyIRExpr(bb_in->next);
1003 bb->jumpkind = bb_in->jumpkind;
njn25e49d8e72002-09-23 09:36:25 +00001004
sewardj9f649aa2004-11-22 20:38:40 +00001005 /* No loads to consider in ->next. */
1006 tl_assert(isAtom(bb_in->next));
njn25e49d8e72002-09-23 09:36:25 +00001007
sewardj9f649aa2004-11-22 20:38:40 +00001008 for (i = 0; i < bb_in->stmts_used; i++) {
1009 st = bb_in->stmts[i];
1010 if (!st) continue;
njn25e49d8e72002-09-23 09:36:25 +00001011
sewardj9f649aa2004-11-22 20:38:40 +00001012 /* Examine each stmt in turn to figure out if it needs to be
1013 preceded by a memory access check. If so, collect up the
1014 relevant pieces of information. */
1015 hsz = 0;
1016 aexpr = NULL;
1017 guard = NULL;
1018 isLoad = True;
njn25e49d8e72002-09-23 09:36:25 +00001019
sewardj9f649aa2004-11-22 20:38:40 +00001020 switch (st->tag) {
1021
1022 case Ist_Tmp:
1023 data = st->Ist.Tmp.data;
1024 if (data->tag == Iex_LDle) {
1025 aexpr = data->Iex.LDle.addr;
1026 hsz = sizeofIRType(data->Iex.LDle.ty);
1027 isLoad = True;
1028 }
1029 break;
1030
1031 case Ist_STle:
1032 data = st->Ist.STle.data;
1033 aexpr = st->Ist.STle.addr;
1034 tl_assert(isAtom(data));
1035 tl_assert(isAtom(aexpr));
1036 hsz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
1037 isLoad = False;
1038
1039 case Ist_Put:
1040 tl_assert(isAtom(st->Ist.Put.data));
njn25e49d8e72002-09-23 09:36:25 +00001041 break;
1042
sewardj9f649aa2004-11-22 20:38:40 +00001043 case Ist_PutI:
1044 tl_assert(isAtom(st->Ist.PutI.ix));
1045 tl_assert(isAtom(st->Ist.PutI.data));
njnc2699f62003-09-05 23:29:33 +00001046 break;
1047
sewardj9f649aa2004-11-22 20:38:40 +00001048 case Ist_Exit:
1049 tl_assert(isAtom(st->Ist.Exit.guard));
njn25e49d8e72002-09-23 09:36:25 +00001050 break;
1051
sewardj9f649aa2004-11-22 20:38:40 +00001052 case Ist_Dirty:
1053 if (st->Ist.Dirty.details->mFx != Ifx_None) {
1054 /* We classify Ifx_Modify as a load. */
1055 isLoad = st->Ist.Dirty.details->mFx != Ifx_Write;
1056 hsz = st->Ist.Dirty.details->mSize;
1057 aexpr = st->Ist.Dirty.details->mAddr;
1058 guard = st->Ist.Dirty.details->guard;
1059 tl_assert(isAtom(aexpr));
1060 }
1061 break;
sewardje3891fa2003-06-15 03:13:48 +00001062
sewardjbd598e12005-01-07 12:10:21 +00001063 case Ist_MFence:
1064 break;
1065
njn25e49d8e72002-09-23 09:36:25 +00001066 default:
sewardj9f649aa2004-11-22 20:38:40 +00001067 VG_(printf)("\n");
1068 ppIRStmt(st);
1069 VG_(printf)("\n");
1070 VG_(tool_panic)("addrcheck: unhandled IRStmt");
njn25e49d8e72002-09-23 09:36:25 +00001071 }
sewardj9f649aa2004-11-22 20:38:40 +00001072
1073 /* If needed, add a helper call. */
1074 if (aexpr) {
1075 tl_assert(hsz > 0);
1076 switch (hsz) {
1077 case 4:
1078 if (isLoad)
1079 di = unsafeIRDirty_0_N( 1, "ach_LOAD4", &ach_LOAD4,
1080 mkIRExprVec_1(aexpr));
1081 else
1082 di = unsafeIRDirty_0_N( 1, "ach_STORE4", &ach_STORE4,
1083 mkIRExprVec_1(aexpr));
1084 break;
1085 case 2:
1086 if (isLoad)
1087 di = unsafeIRDirty_0_N( 1, "ach_LOAD2", &ach_LOAD2,
1088 mkIRExprVec_1(aexpr));
1089 else
1090 di = unsafeIRDirty_0_N( 1, "ach_STORE2", &ach_STORE2,
1091 mkIRExprVec_1(aexpr));
1092 break;
1093 case 1:
1094 if (isLoad)
1095 di = unsafeIRDirty_0_N( 1, "ach_LOAD1", &ach_LOAD1,
1096 mkIRExprVec_1(aexpr));
1097 else
1098 di = unsafeIRDirty_0_N( 1, "ach_STORE1", &ach_STORE1,
1099 mkIRExprVec_1(aexpr));
1100 break;
1101 default:
1102 if (isLoad)
1103 di = unsafeIRDirty_0_N(
1104 2, "ach_LOADN", &ach_LOADN,
1105 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1106 else
1107 di = unsafeIRDirty_0_N(
1108 2, "ach_STOREN", &ach_STOREN,
1109 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1110 break;
1111 }
1112
1113 /* If the call has arisen as a result of a dirty helper which
1114 references memory, we need to inherit the guard from the
1115 dirty helper. */
1116 if (guard)
1117 di->guard = dopyIRExpr(guard);
1118
1119 /* emit the helper call */
1120 addStmtToIRBB( bb, IRStmt_Dirty(di) );
1121
1122 }
1123
1124 /* And finally, copy the expr itself to the output. */
sewardjbd598e12005-01-07 12:10:21 +00001125 addStmtToIRBB( bb, st );
njn25e49d8e72002-09-23 09:36:25 +00001126 }
1127
sewardj9f649aa2004-11-22 20:38:40 +00001128 return bb;
njn25e49d8e72002-09-23 09:36:25 +00001129}
1130
1131
njn25e49d8e72002-09-23 09:36:25 +00001132/*------------------------------------------------------------*/
1133/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
1134/*------------------------------------------------------------*/
1135
sewardja4495682002-10-21 07:29:59 +00001136/* For the memory leak detector, say whether an entire 64k chunk of
1137 address space is possibly in use, or not. If in doubt return
1138 True.
njn25e49d8e72002-09-23 09:36:25 +00001139*/
sewardja4495682002-10-21 07:29:59 +00001140static
1141Bool ac_is_valid_64k_chunk ( UInt chunk_number )
njn25e49d8e72002-09-23 09:36:25 +00001142{
sewardjb5f6f512005-03-10 23:59:00 +00001143 tl_assert(chunk_number >= 0 && chunk_number < PRIMARY_SIZE);
1144 if (primary_map[chunk_number] == DSM_NOTADDR) {
sewardja4495682002-10-21 07:29:59 +00001145 /* Definitely not in use. */
1146 return False;
1147 } else {
1148 return True;
njn25e49d8e72002-09-23 09:36:25 +00001149 }
1150}
1151
1152
sewardja4495682002-10-21 07:29:59 +00001153/* For the memory leak detector, say whether or not a given word
1154 address is to be regarded as valid. */
1155static
1156Bool ac_is_valid_address ( Addr a )
1157{
1158 UChar abits;
njnedfa0f62004-11-30 18:08:05 +00001159 tl_assert(IS_4_ALIGNED(a));
sewardja4495682002-10-21 07:29:59 +00001160 abits = get_abits4_ALIGNED(a);
1161 if (abits == VGM_NIBBLE_VALID) {
1162 return True;
1163 } else {
1164 return False;
1165 }
1166}
1167
1168
nethercote996901a2004-08-03 13:29:09 +00001169/* Leak detector for this tool. We don't actually do anything, merely
sewardja4495682002-10-21 07:29:59 +00001170 run the generic leak detector with suitable parameters for this
nethercote996901a2004-08-03 13:29:09 +00001171 tool. */
sewardjb5f6f512005-03-10 23:59:00 +00001172static void ac_detect_memory_leaks ( LeakCheckMode mode )
njn25e49d8e72002-09-23 09:36:25 +00001173{
sewardjb5f6f512005-03-10 23:59:00 +00001174 MAC_(do_detect_memory_leaks) ( mode, ac_is_valid_64k_chunk, ac_is_valid_address );
njn25e49d8e72002-09-23 09:36:25 +00001175}
1176
1177
1178/* ---------------------------------------------------------------------
1179 Sanity check machinery (permanently engaged).
1180 ------------------------------------------------------------------ */
1181
njn26f02512004-11-22 18:33:15 +00001182Bool TL_(cheap_sanity_check) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001183{
jseward9800fd32004-01-04 23:08:04 +00001184 /* nothing useful we can rapidly check */
1185 return True;
njn25e49d8e72002-09-23 09:36:25 +00001186}
1187
njn26f02512004-11-22 18:33:15 +00001188Bool TL_(expensive_sanity_check) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001189{
1190 Int i;
1191
sewardjb5f6f512005-03-10 23:59:00 +00001192#if 0
njn25e49d8e72002-09-23 09:36:25 +00001193 /* Make sure nobody changed the distinguished secondary. */
1194 for (i = 0; i < 8192; i++)
1195 if (distinguished_secondary_map.abits[i] != VGM_BYTE_INVALID)
1196 return False;
sewardjb5f6f512005-03-10 23:59:00 +00001197#endif
njn25e49d8e72002-09-23 09:36:25 +00001198
1199 /* Make sure that the upper 3/4 of the primary map hasn't
1200 been messed with. */
sewardjb5f6f512005-03-10 23:59:00 +00001201 for (i = PRIMARY_SIZE; i < PRIMARY_SIZE*4; i++)
1202 if (primary_map[i] != DSM_NOTADDR)
njn25e49d8e72002-09-23 09:36:25 +00001203 return False;
1204
1205 return True;
1206}
1207
njn47363ab2003-04-21 13:24:40 +00001208/*------------------------------------------------------------*/
1209/*--- Client requests ---*/
1210/*------------------------------------------------------------*/
1211
njn26f02512004-11-22 18:33:15 +00001212Bool TL_(handle_client_request) ( ThreadId tid, UWord* arg, UWord *ret )
sewardjd8033d92002-12-08 22:16:58 +00001213{
sewardjbf310d92002-12-28 13:09:57 +00001214#define IGNORE(what) \
1215 do { \
1216 if (moans-- > 0) { \
1217 VG_(message)(Vg_UserMsg, \
1218 "Warning: Addrcheck: ignoring `%s' request.", what); \
1219 VG_(message)(Vg_UserMsg, \
nethercote137bc552003-11-14 17:47:54 +00001220 " To honour this request, rerun with --tool=memcheck."); \
sewardjbf310d92002-12-28 13:09:57 +00001221 } \
1222 } while (0)
1223
sewardjbf310d92002-12-28 13:09:57 +00001224 static Int moans = 3;
sewardjd8033d92002-12-08 22:16:58 +00001225
1226 /* Overload memcheck client reqs */
njnfc26ff92004-11-22 19:12:49 +00001227 if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
sewardjd62e03b2004-12-10 12:01:14 +00001228 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
1229 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
1230 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
1231 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
1232 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
1233 && VG_USERREQ__MEMPOOL_FREE != arg[0])
sewardjd8033d92002-12-08 22:16:58 +00001234 return False;
1235
1236 switch (arg[0]) {
1237 case VG_USERREQ__DO_LEAK_CHECK:
sewardjb5f6f512005-03-10 23:59:00 +00001238 ac_detect_memory_leaks(arg[1] ? LC_Summary : LC_Full);
sewardjd8033d92002-12-08 22:16:58 +00001239 *ret = 0; /* return value is meaningless */
1240 break;
1241
sewardjbf310d92002-12-28 13:09:57 +00001242 /* Ignore these */
sewardjd8033d92002-12-08 22:16:58 +00001243 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
sewardjbf310d92002-12-28 13:09:57 +00001244 IGNORE("VALGRIND_CHECK_WRITABLE");
1245 return False;
sewardjd8033d92002-12-08 22:16:58 +00001246 case VG_USERREQ__CHECK_READABLE: /* check readable */
sewardjbf310d92002-12-28 13:09:57 +00001247 IGNORE("VALGRIND_CHECK_READABLE");
1248 return False;
sewardjd8033d92002-12-08 22:16:58 +00001249 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
sewardjbf310d92002-12-28 13:09:57 +00001250 IGNORE("VALGRIND_MAKE_NOACCESS");
1251 return False;
sewardjd8033d92002-12-08 22:16:58 +00001252 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
sewardjbf310d92002-12-28 13:09:57 +00001253 IGNORE("VALGRIND_MAKE_WRITABLE");
1254 return False;
sewardjd8033d92002-12-08 22:16:58 +00001255 case VG_USERREQ__MAKE_READABLE: /* make readable */
sewardjbf310d92002-12-28 13:09:57 +00001256 IGNORE("VALGRIND_MAKE_READABLE");
1257 return False;
sewardjd8033d92002-12-08 22:16:58 +00001258 case VG_USERREQ__DISCARD: /* discard */
sewardjbf310d92002-12-28 13:09:57 +00001259 IGNORE("VALGRIND_CHECK_DISCARD");
1260 return False;
sewardjd8033d92002-12-08 22:16:58 +00001261
1262 default:
nethercoted1b64b22004-11-04 18:22:28 +00001263 if (MAC_(handle_common_client_requests)(tid, arg, ret )) {
njn47363ab2003-04-21 13:24:40 +00001264 return True;
1265 } else {
1266 VG_(message)(Vg_UserMsg,
nethercoted1b64b22004-11-04 18:22:28 +00001267 "Warning: unknown addrcheck client request code %llx",
1268 (ULong)arg[0]);
njn47363ab2003-04-21 13:24:40 +00001269 return False;
1270 }
sewardjd8033d92002-12-08 22:16:58 +00001271 }
1272 return True;
sewardjbf310d92002-12-28 13:09:57 +00001273
1274#undef IGNORE
sewardjd8033d92002-12-08 22:16:58 +00001275}
1276
njn25e49d8e72002-09-23 09:36:25 +00001277/*------------------------------------------------------------*/
1278/*--- Setup ---*/
1279/*------------------------------------------------------------*/
1280
njn26f02512004-11-22 18:33:15 +00001281Bool TL_(process_cmd_line_option)(Char* arg)
njn25e49d8e72002-09-23 09:36:25 +00001282{
njn43c799e2003-04-08 00:08:52 +00001283 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001284}
1285
njn26f02512004-11-22 18:33:15 +00001286void TL_(print_usage)(void)
njn25e49d8e72002-09-23 09:36:25 +00001287{
njn3e884182003-04-15 13:03:23 +00001288 MAC_(print_common_usage)();
1289}
1290
njn26f02512004-11-22 18:33:15 +00001291void TL_(print_debug_usage)(void)
njn3e884182003-04-15 13:03:23 +00001292{
1293 MAC_(print_common_debug_usage)();
njn25e49d8e72002-09-23 09:36:25 +00001294}
1295
1296
1297/*------------------------------------------------------------*/
1298/*--- Setup ---*/
1299/*------------------------------------------------------------*/
1300
njn26f02512004-11-22 18:33:15 +00001301void TL_(pre_clo_init)(void)
njn25e49d8e72002-09-23 09:36:25 +00001302{
njn810086f2002-11-14 12:42:47 +00001303 VG_(details_name) ("Addrcheck");
1304 VG_(details_version) (NULL);
1305 VG_(details_description) ("a fine-grained address checker");
1306 VG_(details_copyright_author)(
njn53612422005-03-12 16:22:54 +00001307 "Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.");
nethercote421281e2003-11-20 16:20:55 +00001308 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardj78210aa2002-12-01 02:55:46 +00001309 VG_(details_avg_translation_sizeB) ( 135 );
njn25e49d8e72002-09-23 09:36:25 +00001310
njn810086f2002-11-14 12:42:47 +00001311 VG_(needs_core_errors) ();
njn95ec8702004-11-22 16:46:13 +00001312 VG_(needs_tool_errors) ();
njn810086f2002-11-14 12:42:47 +00001313 VG_(needs_libc_freeres) ();
njn810086f2002-11-14 12:42:47 +00001314 VG_(needs_command_line_options)();
1315 VG_(needs_client_requests) ();
njn810086f2002-11-14 12:42:47 +00001316 VG_(needs_sanity_checks) ();
fitzhardinge98abfc72003-12-16 02:05:15 +00001317 VG_(needs_shadow_memory) ();
njn25e49d8e72002-09-23 09:36:25 +00001318
njn3e884182003-04-15 13:03:23 +00001319 MAC_( new_mem_heap) = & ac_new_mem_heap;
1320 MAC_( ban_mem_heap) = & ac_make_noaccess;
1321 MAC_(copy_mem_heap) = & ac_copy_address_range_state;
1322 MAC_( die_mem_heap) = & ac_make_noaccess;
sewardjecf8e102003-07-12 12:11:39 +00001323 MAC_(check_noaccess) = & ac_check_noaccess;
njn3e884182003-04-15 13:03:23 +00001324
fitzhardinge98abfc72003-12-16 02:05:15 +00001325 VG_(init_new_mem_startup) ( & ac_new_mem_startup );
1326 VG_(init_new_mem_stack_signal) ( & ac_make_accessible );
1327 VG_(init_new_mem_brk) ( & ac_make_accessible );
sewardjb5f6f512005-03-10 23:59:00 +00001328 VG_(init_new_mem_mmap) ( & ac_new_mem_mmap );
njn25e49d8e72002-09-23 09:36:25 +00001329
fitzhardinge98abfc72003-12-16 02:05:15 +00001330 VG_(init_copy_mem_remap) ( & ac_copy_address_range_state );
njn3e884182003-04-15 13:03:23 +00001331
fitzhardinge98abfc72003-12-16 02:05:15 +00001332 VG_(init_die_mem_stack_signal) ( & ac_make_noaccess );
1333 VG_(init_die_mem_brk) ( & ac_make_noaccess );
1334 VG_(init_die_mem_munmap) ( & ac_make_noaccess );
njn3e884182003-04-15 13:03:23 +00001335
fitzhardinge98abfc72003-12-16 02:05:15 +00001336 VG_(init_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
1337 VG_(init_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
1338 VG_(init_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
1339 VG_(init_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
1340 VG_(init_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
1341 VG_(init_new_mem_stack) ( & MAC_(new_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001342
fitzhardinge98abfc72003-12-16 02:05:15 +00001343 VG_(init_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
1344 VG_(init_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
1345 VG_(init_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
1346 VG_(init_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
1347 VG_(init_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
1348 VG_(init_die_mem_stack) ( & MAC_(die_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001349
fitzhardinge98abfc72003-12-16 02:05:15 +00001350 VG_(init_ban_mem_stack) ( & ac_make_noaccess );
njn25e49d8e72002-09-23 09:36:25 +00001351
fitzhardinge98abfc72003-12-16 02:05:15 +00001352 VG_(init_pre_mem_read) ( & ac_check_is_readable );
1353 VG_(init_pre_mem_read_asciiz) ( & ac_check_is_readable_asciiz );
1354 VG_(init_pre_mem_write) ( & ac_check_is_writable );
njnabb14ad2004-11-24 16:57:16 +00001355 VG_(init_post_mem_write) ( & ac_post_mem_write );
njn25e49d8e72002-09-23 09:36:25 +00001356
njn25e49d8e72002-09-23 09:36:25 +00001357 VGP_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
1358 VGP_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
njn9b007f62003-04-07 14:40:25 +00001359 VGP_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
njnd04b7c62002-10-03 14:05:52 +00001360
1361 init_shadow_memory();
njn3e884182003-04-15 13:03:23 +00001362 MAC_(common_pre_clo_init)();
njn5c004e42002-11-18 11:04:50 +00001363}
1364
njn26f02512004-11-22 18:33:15 +00001365void TL_(post_clo_init) ( void )
njn5c004e42002-11-18 11:04:50 +00001366{
1367}
1368
njn26f02512004-11-22 18:33:15 +00001369void TL_(fini) ( Int exitcode )
njn5c004e42002-11-18 11:04:50 +00001370{
njn3e884182003-04-15 13:03:23 +00001371 MAC_(common_fini)( ac_detect_memory_leaks );
njn25e49d8e72002-09-23 09:36:25 +00001372}
1373
njn26f02512004-11-22 18:33:15 +00001374VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 1./8)
fitzhardinge98abfc72003-12-16 02:05:15 +00001375
1376
njn25e49d8e72002-09-23 09:36:25 +00001377/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00001378/*--- end ac_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00001379/*--------------------------------------------------------------------*/