blob: 026fce2758aa6712bd6455eed5b1649b9cf7c377 [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
njn51d827b2005-05-09 01:02:08 +000042static void ac_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
njn51d827b2005-05-09 01:02:08 +000078static Bool ac_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
njn02bc4b82005-05-15 17:28:26 +0000105 distinguished secondary map, which indicates 'not addressible and
njn25e49d8e72002-09-23 09:36:25 +0000106 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
njn25e49d8e72002-09-23 09:36:25 +0000384 VGP_POPCC(VgpSetMem);
385}
386
387/* Set permissions for address ranges ... */
388
nethercote451eae92004-11-02 13:06:32 +0000389static void ac_make_noaccess ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000390{
391 PROF_EVENT(35);
njn5c004e42002-11-18 11:04:50 +0000392 DEBUG("ac_make_noaccess(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000393 set_address_range_perms ( a, len, VGM_BIT_INVALID );
394}
395
nethercote451eae92004-11-02 13:06:32 +0000396static void ac_make_accessible ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000397{
njn5c004e42002-11-18 11:04:50 +0000398 PROF_EVENT(38);
399 DEBUG("ac_make_accessible(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000400 set_address_range_perms ( a, len, VGM_BIT_VALID );
401}
402
njn9b007f62003-04-07 14:40:25 +0000403static __inline__
404void make_aligned_word_noaccess(Addr a)
405{
406 AcSecMap* sm;
407 UInt sm_off;
408 UChar mask;
409
410 VGP_PUSHCC(VgpESPAdj);
411 ENSURE_MAPPABLE(a, "make_aligned_word_noaccess");
sewardjb5f6f512005-03-10 23:59:00 +0000412 sm = primary_map[PM_IDX(a)];
413 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000414 mask = 0x0F;
415 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
416 /* mask now contains 1s where we wish to make address bits invalid (1s). */
417 sm->abits[sm_off >> 3] |= mask;
418 VGP_POPCC(VgpESPAdj);
419}
420
421static __inline__
422void make_aligned_word_accessible(Addr a)
423{
424 AcSecMap* sm;
425 UInt sm_off;
426 UChar mask;
427
428 VGP_PUSHCC(VgpESPAdj);
429 ENSURE_MAPPABLE(a, "make_aligned_word_accessible");
sewardjb5f6f512005-03-10 23:59:00 +0000430 sm = primary_map[PM_IDX(a)];
431 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000432 mask = 0x0F;
433 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
434 /* mask now contains 1s where we wish to make address bits
435 invalid (0s). */
436 sm->abits[sm_off >> 3] &= ~mask;
437 VGP_POPCC(VgpESPAdj);
438}
439
440/* Nb: by "aligned" here we mean 8-byte aligned */
441static __inline__
442void make_aligned_doubleword_accessible(Addr a)
443{
444 AcSecMap* sm;
445 UInt sm_off;
446
447 VGP_PUSHCC(VgpESPAdj);
448 ENSURE_MAPPABLE(a, "make_aligned_doubleword_accessible");
sewardjb5f6f512005-03-10 23:59:00 +0000449 sm = primary_map[PM_IDX(a)];
450 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000451 sm->abits[sm_off >> 3] = VGM_BYTE_VALID;
452 VGP_POPCC(VgpESPAdj);
453}
454
455static __inline__
456void make_aligned_doubleword_noaccess(Addr a)
457{
458 AcSecMap* sm;
459 UInt sm_off;
460
461 VGP_PUSHCC(VgpESPAdj);
462 ENSURE_MAPPABLE(a, "make_aligned_doubleword_noaccess");
sewardjb5f6f512005-03-10 23:59:00 +0000463 sm = primary_map[PM_IDX(a)];
464 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000465 sm->abits[sm_off >> 3] = VGM_BYTE_INVALID;
466 VGP_POPCC(VgpESPAdj);
467}
468
469/* The %esp update handling functions */
470ESP_UPDATE_HANDLERS ( make_aligned_word_accessible,
471 make_aligned_word_noaccess,
472 make_aligned_doubleword_accessible,
473 make_aligned_doubleword_noaccess,
474 ac_make_accessible,
475 ac_make_noaccess
476 );
477
478
njn25e49d8e72002-09-23 09:36:25 +0000479/* Block-copy permissions (needed for implementing realloc()). */
480
nethercote451eae92004-11-02 13:06:32 +0000481static void ac_copy_address_range_state ( Addr src, Addr dst, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000482{
483 UInt i;
484
njn5c004e42002-11-18 11:04:50 +0000485 DEBUG("ac_copy_address_range_state\n");
njn25e49d8e72002-09-23 09:36:25 +0000486
487 PROF_EVENT(40);
488 for (i = 0; i < len; i++) {
489 UChar abit = get_abit ( src+i );
490 PROF_EVENT(41);
491 set_abit ( dst+i, abit );
492 }
493}
494
495
496/* Check permissions for address range. If inadequate permissions
497 exist, *bad_addr is set to the offending address, so the caller can
498 know what it is. */
499
njn5c004e42002-11-18 11:04:50 +0000500static __inline__
nethercote451eae92004-11-02 13:06:32 +0000501Bool ac_check_accessible ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000502{
503 UInt i;
504 UChar abit;
njn5c004e42002-11-18 11:04:50 +0000505 PROF_EVENT(48);
njn25e49d8e72002-09-23 09:36:25 +0000506 for (i = 0; i < len; i++) {
njn5c004e42002-11-18 11:04:50 +0000507 PROF_EVENT(49);
njn25e49d8e72002-09-23 09:36:25 +0000508 abit = get_abit(a);
509 if (abit == VGM_BIT_INVALID) {
510 if (bad_addr != NULL) *bad_addr = a;
511 return False;
512 }
513 a++;
514 }
515 return True;
516}
517
sewardjecf8e102003-07-12 12:11:39 +0000518/* The opposite; check that an address range is inaccessible. */
519static
nethercote451eae92004-11-02 13:06:32 +0000520Bool ac_check_noaccess ( Addr a, SizeT len, Addr* bad_addr )
sewardjecf8e102003-07-12 12:11:39 +0000521{
522 UInt i;
523 UChar abit;
524 PROF_EVENT(48);
525 for (i = 0; i < len; i++) {
526 PROF_EVENT(49);
527 abit = get_abit(a);
528 if (abit == VGM_BIT_VALID) {
529 if (bad_addr != NULL) *bad_addr = a;
530 return False;
531 }
532 a++;
533 }
534 return True;
535}
536
njn25e49d8e72002-09-23 09:36:25 +0000537/* Check a zero-terminated ascii string. Tricky -- don't want to
538 examine the actual bytes, to find the end, until we're sure it is
539 safe to do so. */
540
njn5c004e42002-11-18 11:04:50 +0000541static __inline__
542Bool ac_check_readable_asciiz ( Addr a, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000543{
544 UChar abit;
545 PROF_EVENT(46);
njn5c004e42002-11-18 11:04:50 +0000546 DEBUG("ac_check_readable_asciiz\n");
njn25e49d8e72002-09-23 09:36:25 +0000547 while (True) {
548 PROF_EVENT(47);
549 abit = get_abit(a);
550 if (abit != VGM_BIT_VALID) {
551 if (bad_addr != NULL) *bad_addr = a;
552 return False;
553 }
554 /* Ok, a is safe to read. */
555 if (* ((UChar*)a) == 0) return True;
556 a++;
557 }
558}
559
560
561/*------------------------------------------------------------*/
562/*--- Memory event handlers ---*/
563/*------------------------------------------------------------*/
564
njn5c004e42002-11-18 11:04:50 +0000565static __inline__
njn72718642003-07-24 08:45:32 +0000566void ac_check_is_accessible ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000567 Char* s, Addr base, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000568{
569 Bool ok;
njn86f12dc2005-03-14 01:16:05 +0000570 Addr bad_addr = 0; // Initialise to shut gcc up
njn25e49d8e72002-09-23 09:36:25 +0000571
572 VGP_PUSHCC(VgpCheckMem);
573
njn5c004e42002-11-18 11:04:50 +0000574 ok = ac_check_accessible ( base, size, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000575 if (!ok) {
576 switch (part) {
577 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +0000578 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
579 /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000580 break;
581
njn25e49d8e72002-09-23 09:36:25 +0000582 case Vg_CoreSignal:
njnca82cc02004-11-22 17:18:48 +0000583 tl_assert(isWrite); /* Should only happen with isWrite case */
njn5c004e42002-11-18 11:04:50 +0000584 /* fall through */
njn25e49d8e72002-09-23 09:36:25 +0000585 case Vg_CorePThread:
nethercote8b76fe52004-11-08 19:20:09 +0000586 MAC_(record_core_mem_error)( tid, /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000587 break;
588
589 /* If we're being asked to jump to a silly address, record an error
590 message before potentially crashing the entire system. */
591 case Vg_CoreTranslate:
njnca82cc02004-11-22 17:18:48 +0000592 tl_assert(!isWrite); /* Should only happen with !isWrite case */
njn72718642003-07-24 08:45:32 +0000593 MAC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000594 break;
595
596 default:
njn67993252004-11-22 18:02:32 +0000597 VG_(tool_panic)("ac_check_is_accessible: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +0000598 }
599 }
njn5c004e42002-11-18 11:04:50 +0000600
njn25e49d8e72002-09-23 09:36:25 +0000601 VGP_POPCC(VgpCheckMem);
602}
603
604static
njn72718642003-07-24 08:45:32 +0000605void ac_check_is_writable ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000606 Char* s, Addr base, SizeT size )
njn5c004e42002-11-18 11:04:50 +0000607{
njn72718642003-07-24 08:45:32 +0000608 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/True );
njn5c004e42002-11-18 11:04:50 +0000609}
610
611static
njn72718642003-07-24 08:45:32 +0000612void ac_check_is_readable ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000613 Char* s, Addr base, SizeT size )
njn5c004e42002-11-18 11:04:50 +0000614{
njn72718642003-07-24 08:45:32 +0000615 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/False );
njn5c004e42002-11-18 11:04:50 +0000616}
617
618static
njn72718642003-07-24 08:45:32 +0000619void ac_check_is_readable_asciiz ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000620 Char* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +0000621{
622 Bool ok = True;
njn86f12dc2005-03-14 01:16:05 +0000623 Addr bad_addr = 0; // Initialise to shut gcc up
njn25e49d8e72002-09-23 09:36:25 +0000624
625 VGP_PUSHCC(VgpCheckMem);
626
njnca82cc02004-11-22 17:18:48 +0000627 tl_assert(part == Vg_CoreSysCall);
njn5c004e42002-11-18 11:04:50 +0000628 ok = ac_check_readable_asciiz ( (Addr)str, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000629 if (!ok) {
nethercote8b76fe52004-11-08 19:20:09 +0000630 MAC_(record_param_error) ( tid, bad_addr, /*IsReg*/False,
631 /*IsUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000632 }
633
634 VGP_POPCC(VgpCheckMem);
635}
636
637static
nethercote451eae92004-11-02 13:06:32 +0000638void ac_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +0000639{
njn1f3a9092002-10-04 09:22:30 +0000640 /* Ignore the permissions, just make it readable. Seems to work... */
njn25e49d8e72002-09-23 09:36:25 +0000641 DEBUG("new_mem_startup(%p, %u, rr=%u, ww=%u, xx=%u)\n", a,len,rr,ww,xx);
njn5c004e42002-11-18 11:04:50 +0000642 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000643}
644
645static
nethercote451eae92004-11-02 13:06:32 +0000646void ac_new_mem_heap ( Addr a, SizeT len, Bool is_inited )
njn25e49d8e72002-09-23 09:36:25 +0000647{
njn5c004e42002-11-18 11:04:50 +0000648 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000649}
650
651static
sewardjb5f6f512005-03-10 23:59:00 +0000652void ac_new_mem_mmap (Addr a, SizeT len, Bool rr, Bool ww, Bool xx)
njn25e49d8e72002-09-23 09:36:25 +0000653{
njn5c004e42002-11-18 11:04:50 +0000654 DEBUG("ac_set_perms(%p, %u, rr=%u ww=%u, xx=%u)\n",
sewardj40f8ebe2002-10-23 21:46:13 +0000655 a, len, rr, ww, xx);
sewardjb5f6f512005-03-10 23:59:00 +0000656 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000657}
658
njncf45fd42004-11-24 16:30:22 +0000659static
660void ac_post_mem_write(CorePart part, ThreadId tid, Addr a, SizeT len)
661{
662 ac_make_accessible(a, len);
663}
664
njn25e49d8e72002-09-23 09:36:25 +0000665
666/*------------------------------------------------------------*/
667/*--- Functions called directly from generated code. ---*/
668/*------------------------------------------------------------*/
669
670static __inline__ UInt rotateRight16 ( UInt x )
671{
672 /* Amazingly, gcc turns this into a single rotate insn. */
673 return (x >> 16) | (x << 16);
674}
675
njn25e49d8e72002-09-23 09:36:25 +0000676static __inline__ UInt shiftRight16 ( UInt x )
677{
678 return x >> 16;
679}
680
681
682/* Read/write 1/2/4 sized V bytes, and emit an address error if
683 needed. */
684
njn5c004e42002-11-18 11:04:50 +0000685/* ac_helperc_ACCESS{1,2,4} handle the common case fast.
njn25e49d8e72002-09-23 09:36:25 +0000686 Under all other circumstances, it defers to the relevant _SLOWLY
687 function, which can handle all situations.
688*/
njnc2699f62003-09-05 23:29:33 +0000689static __inline__ void ac_helperc_ACCESS4 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000690{
691# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000692 return ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000693# else
694 UInt sec_no = rotateRight16(a) & 0x3FFFF;
njnda2e36d2003-09-30 13:33:24 +0000695 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000696 UInt a_off = (SM_OFF(a)) >> 3;
njn25e49d8e72002-09-23 09:36:25 +0000697 UChar abits = sm->abits[a_off];
698 abits >>= (a & 4);
699 abits &= 15;
njn5c004e42002-11-18 11:04:50 +0000700 PROF_EVENT(66);
njn25e49d8e72002-09-23 09:36:25 +0000701 if (abits == VGM_NIBBLE_VALID) {
702 /* Handle common case quickly: a is suitably aligned, is mapped,
703 and is addressible. So just return. */
704 return;
705 } else {
706 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000707 ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000708 }
709# endif
710}
711
njnc2699f62003-09-05 23:29:33 +0000712static __inline__ void ac_helperc_ACCESS2 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000713{
714# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000715 return ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000716# else
717 UInt sec_no = rotateRight16(a) & 0x1FFFF;
718 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000719 UInt a_off = (SM_OFF(a)) >> 3;
njn5c004e42002-11-18 11:04:50 +0000720 PROF_EVENT(67);
njn25e49d8e72002-09-23 09:36:25 +0000721 if (sm->abits[a_off] == VGM_BYTE_VALID) {
722 /* Handle common case quickly. */
723 return;
724 } else {
725 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000726 ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000727 }
728# endif
729}
730
njnc2699f62003-09-05 23:29:33 +0000731static __inline__ void ac_helperc_ACCESS1 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000732{
733# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000734 return ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000735# else
736 UInt sec_no = shiftRight16(a);
737 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000738 UInt a_off = (SM_OFF(a)) >> 3;
njn5c004e42002-11-18 11:04:50 +0000739 PROF_EVENT(68);
njn25e49d8e72002-09-23 09:36:25 +0000740 if (sm->abits[a_off] == VGM_BYTE_VALID) {
741 /* Handle common case quickly. */
742 return;
743 } else {
744 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000745 ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000746 }
747# endif
748}
749
njn9fb73db2005-03-27 01:55:21 +0000750VGA_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000751static void ach_LOAD4 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000752{
753 ac_helperc_ACCESS4 ( a, /*isWrite*/False );
754}
njn9fb73db2005-03-27 01:55:21 +0000755VGA_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000756static void ach_STORE4 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000757{
758 ac_helperc_ACCESS4 ( a, /*isWrite*/True );
759}
760
njn9fb73db2005-03-27 01:55:21 +0000761VGA_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000762static void ach_LOAD2 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000763{
764 ac_helperc_ACCESS2 ( a, /*isWrite*/False );
765}
njn9fb73db2005-03-27 01:55:21 +0000766VGA_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000767static void ach_STORE2 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000768{
769 ac_helperc_ACCESS2 ( a, /*isWrite*/True );
770}
771
njn9fb73db2005-03-27 01:55:21 +0000772VGA_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000773static void ach_LOAD1 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000774{
775 ac_helperc_ACCESS1 ( a, /*isWrite*/False );
776}
njn9fb73db2005-03-27 01:55:21 +0000777VGA_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000778static void ach_STORE1 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000779{
780 ac_helperc_ACCESS1 ( a, /*isWrite*/True );
781}
782
njn25e49d8e72002-09-23 09:36:25 +0000783
784/*------------------------------------------------------------*/
785/*--- Fallback functions to handle cases that the above ---*/
njnc2699f62003-09-05 23:29:33 +0000786/*--- ac_helperc_ACCESS{1,2,4} can't manage. ---*/
njn25e49d8e72002-09-23 09:36:25 +0000787/*------------------------------------------------------------*/
788
njnc2699f62003-09-05 23:29:33 +0000789static void ac_ACCESS4_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000790{
791 Bool a0ok, a1ok, a2ok, a3ok;
792
njn5c004e42002-11-18 11:04:50 +0000793 PROF_EVENT(76);
njn25e49d8e72002-09-23 09:36:25 +0000794
795 /* First establish independently the addressibility of the 4 bytes
796 involved. */
797 a0ok = get_abit(a+0) == VGM_BIT_VALID;
798 a1ok = get_abit(a+1) == VGM_BIT_VALID;
799 a2ok = get_abit(a+2) == VGM_BIT_VALID;
800 a3ok = get_abit(a+3) == VGM_BIT_VALID;
801
802 /* Now distinguish 3 cases */
803
804 /* Case 1: the address is completely valid, so:
805 - no addressing error
806 */
807 if (a0ok && a1ok && a2ok && a3ok) {
808 return;
809 }
810
811 /* Case 2: the address is completely invalid.
812 - emit addressing error
813 */
814 /* VG_(printf)("%p (%d %d %d %d)\n", a, a0ok, a1ok, a2ok, a3ok); */
njn43c799e2003-04-08 00:08:52 +0000815 if (!MAC_(clo_partial_loads_ok)
njn25e49d8e72002-09-23 09:36:25 +0000816 || ((a & 3) != 0)
817 || (!a0ok && !a1ok && !a2ok && !a3ok)) {
sewardj76754cf2005-03-14 00:14:04 +0000818 MAC_(record_address_error)( VG_(get_running_tid)(), a, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000819 return;
820 }
821
822 /* Case 3: the address is partially valid.
823 - no addressing error
njn43c799e2003-04-08 00:08:52 +0000824 Case 3 is only allowed if MAC_(clo_partial_loads_ok) is True
njn25e49d8e72002-09-23 09:36:25 +0000825 (which is the default), and the address is 4-aligned.
826 If not, Case 2 will have applied.
827 */
njnca82cc02004-11-22 17:18:48 +0000828 tl_assert(MAC_(clo_partial_loads_ok));
njn25e49d8e72002-09-23 09:36:25 +0000829 {
830 return;
831 }
832}
833
njnc2699f62003-09-05 23:29:33 +0000834static void ac_ACCESS2_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000835{
836 /* Check the address for validity. */
837 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000838 PROF_EVENT(77);
njn25e49d8e72002-09-23 09:36:25 +0000839
840 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
841 if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
842
843 /* If an address error has happened, report it. */
844 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000845 MAC_(record_address_error)( VG_(get_running_tid)(), a, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000846 }
847}
848
njnc2699f62003-09-05 23:29:33 +0000849static void ac_ACCESS1_SLOWLY ( Addr a, Bool isWrite)
njn25e49d8e72002-09-23 09:36:25 +0000850{
851 /* Check the address for validity. */
852 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000853 PROF_EVENT(78);
njn25e49d8e72002-09-23 09:36:25 +0000854
855 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
856
857 /* If an address error has happened, report it. */
858 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000859 MAC_(record_address_error)( VG_(get_running_tid)(), a, 1, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000860 }
861}
862
863
864/* ---------------------------------------------------------------------
865 FPU load and store checks, called from generated code.
866 ------------------------------------------------------------------ */
867
sewardj56867352003-10-12 10:27:06 +0000868static
nethercote928a5f72004-11-03 18:10:37 +0000869void ac_fpu_ACCESS_check ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000870{
871 /* Ensure the read area is both addressible and valid (ie,
872 readable). If there's an address error, don't report a value
873 error too; but if there isn't an address error, check for a
874 value error.
875
876 Try to be reasonably fast on the common case; wimp out and defer
njn5c004e42002-11-18 11:04:50 +0000877 to ac_fpu_ACCESS_check_SLOWLY for everything else. */
njn25e49d8e72002-09-23 09:36:25 +0000878
879 AcSecMap* sm;
880 UInt sm_off, a_off;
881 Addr addr4;
882
njn5c004e42002-11-18 11:04:50 +0000883 PROF_EVENT(90);
njn25e49d8e72002-09-23 09:36:25 +0000884
885# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000886 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000887# else
888
889 if (size == 4) {
njnbe91aae2005-03-27 01:42:41 +0000890 if (!VG_IS_4_ALIGNED(addr)) goto slow4;
njn5c004e42002-11-18 11:04:50 +0000891 PROF_EVENT(91);
njn25e49d8e72002-09-23 09:36:25 +0000892 /* Properly aligned. */
sewardjb5f6f512005-03-10 23:59:00 +0000893 sm = primary_map[PM_IDX(addr)];
894 sm_off = SM_OFF(addr);
njn25e49d8e72002-09-23 09:36:25 +0000895 a_off = sm_off >> 3;
896 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow4;
897 /* Properly aligned and addressible. */
898 return;
899 slow4:
njnc2699f62003-09-05 23:29:33 +0000900 ac_fpu_ACCESS_check_SLOWLY ( addr, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000901 return;
902 }
903
904 if (size == 8) {
njnbe91aae2005-03-27 01:42:41 +0000905 if (!VG_IS_4_ALIGNED(addr)) goto slow8;
njn5c004e42002-11-18 11:04:50 +0000906 PROF_EVENT(92);
njn25e49d8e72002-09-23 09:36:25 +0000907 /* Properly aligned. Do it in two halves. */
908 addr4 = addr + 4;
909 /* First half. */
sewardjb5f6f512005-03-10 23:59:00 +0000910 sm = primary_map[PM_IDX(addr)];
911 sm_off = SM_OFF(addr);
njn25e49d8e72002-09-23 09:36:25 +0000912 a_off = sm_off >> 3;
913 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
914 /* First half properly aligned and addressible. */
915 /* Second half. */
sewardjb5f6f512005-03-10 23:59:00 +0000916 sm = primary_map[PM_IDX(addr4)];
917 sm_off = SM_OFF(addr4);
njn25e49d8e72002-09-23 09:36:25 +0000918 a_off = sm_off >> 3;
919 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
920 /* Second half properly aligned and addressible. */
921 /* Both halves properly aligned and addressible. */
922 return;
923 slow8:
njnc2699f62003-09-05 23:29:33 +0000924 ac_fpu_ACCESS_check_SLOWLY ( addr, 8, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000925 return;
926 }
927
928 /* Can't be bothered to huff'n'puff to make these (allegedly) rare
929 cases go quickly. */
930 if (size == 2) {
njn5c004e42002-11-18 11:04:50 +0000931 PROF_EVENT(93);
njnc2699f62003-09-05 23:29:33 +0000932 ac_fpu_ACCESS_check_SLOWLY ( addr, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000933 return;
934 }
935
jsewardfca60182004-01-04 23:30:55 +0000936 if (size == 16 || size == 10 || size == 28 || size == 108 || size == 512) {
njn5c004e42002-11-18 11:04:50 +0000937 PROF_EVENT(94);
njnc2699f62003-09-05 23:29:33 +0000938 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000939 return;
940 }
941
942 VG_(printf)("size is %d\n", size);
njn67993252004-11-22 18:02:32 +0000943 VG_(tool_panic)("fpu_ACCESS_check: unhandled size");
njn25e49d8e72002-09-23 09:36:25 +0000944# endif
945}
946
njn9fb73db2005-03-27 01:55:21 +0000947VGA_REGPARM(2)
sewardj9f649aa2004-11-22 20:38:40 +0000948static void ach_LOADN ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000949{
950 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/False );
951}
952
njn9fb73db2005-03-27 01:55:21 +0000953VGA_REGPARM(2)
sewardj9f649aa2004-11-22 20:38:40 +0000954static void ach_STOREN ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000955{
956 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/True );
957}
njn25e49d8e72002-09-23 09:36:25 +0000958
sewardjd62e03b2004-12-10 12:01:14 +0000959
njn25e49d8e72002-09-23 09:36:25 +0000960/* ---------------------------------------------------------------------
961 Slow, general cases for FPU access checks.
962 ------------------------------------------------------------------ */
963
nethercote928a5f72004-11-03 18:10:37 +0000964void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000965{
966 Int i;
967 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000968 PROF_EVENT(100);
njn25e49d8e72002-09-23 09:36:25 +0000969 for (i = 0; i < size; i++) {
njn5c004e42002-11-18 11:04:50 +0000970 PROF_EVENT(101);
njn25e49d8e72002-09-23 09:36:25 +0000971 if (get_abit(addr+i) != VGM_BIT_VALID)
972 aerr = True;
973 }
974
975 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000976 MAC_(record_address_error)( VG_(get_running_tid)(), addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000977 }
978}
979
980
981/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000982/*--- Our instrumenter ---*/
983/*------------------------------------------------------------*/
984
njn51d827b2005-05-09 01:02:08 +0000985static IRBB* ac_instrument(IRBB* bb_in, VexGuestLayout* layout,
986 IRType gWordTy, IRType hWordTy )
njn25e49d8e72002-09-23 09:36:25 +0000987{
sewardj9f649aa2004-11-22 20:38:40 +0000988 Int i, hsz;
989 IRStmt* st;
990 IRExpr* data;
991 IRExpr* aexpr;
992 IRExpr* guard;
993 IRDirty* di;
994 Bool isLoad;
sewardjd54babf2005-03-21 00:55:49 +0000995 IRBB* bb;
996
997 if (gWordTy != hWordTy) {
998 /* We don't currently support this case. */
999 VG_(tool_panic)("host/guest word size mismatch");
1000 }
njn25e49d8e72002-09-23 09:36:25 +00001001
sewardj9f649aa2004-11-22 20:38:40 +00001002 /* Set up BB */
sewardjd54babf2005-03-21 00:55:49 +00001003 bb = emptyIRBB();
sewardj9f649aa2004-11-22 20:38:40 +00001004 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
1005 bb->next = dopyIRExpr(bb_in->next);
1006 bb->jumpkind = bb_in->jumpkind;
njn25e49d8e72002-09-23 09:36:25 +00001007
sewardj9f649aa2004-11-22 20:38:40 +00001008 /* No loads to consider in ->next. */
sewardj710d6c22005-03-20 18:55:15 +00001009 tl_assert(isIRAtom(bb_in->next));
njn25e49d8e72002-09-23 09:36:25 +00001010
sewardj9f649aa2004-11-22 20:38:40 +00001011 for (i = 0; i < bb_in->stmts_used; i++) {
1012 st = bb_in->stmts[i];
sewardj21dc3452005-03-21 00:27:41 +00001013 tl_assert(st);
njn25e49d8e72002-09-23 09:36:25 +00001014
sewardj9f649aa2004-11-22 20:38:40 +00001015 /* Examine each stmt in turn to figure out if it needs to be
1016 preceded by a memory access check. If so, collect up the
1017 relevant pieces of information. */
1018 hsz = 0;
1019 aexpr = NULL;
1020 guard = NULL;
1021 isLoad = True;
njn25e49d8e72002-09-23 09:36:25 +00001022
sewardj9f649aa2004-11-22 20:38:40 +00001023 switch (st->tag) {
1024
1025 case Ist_Tmp:
1026 data = st->Ist.Tmp.data;
1027 if (data->tag == Iex_LDle) {
1028 aexpr = data->Iex.LDle.addr;
1029 hsz = sizeofIRType(data->Iex.LDle.ty);
1030 isLoad = True;
1031 }
1032 break;
1033
1034 case Ist_STle:
1035 data = st->Ist.STle.data;
1036 aexpr = st->Ist.STle.addr;
sewardj710d6c22005-03-20 18:55:15 +00001037 tl_assert(isIRAtom(data));
1038 tl_assert(isIRAtom(aexpr));
sewardj9f649aa2004-11-22 20:38:40 +00001039 hsz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
1040 isLoad = False;
sewardj08ccc5c2005-03-17 03:17:54 +00001041 break;
sewardj9f649aa2004-11-22 20:38:40 +00001042
1043 case Ist_Put:
sewardj710d6c22005-03-20 18:55:15 +00001044 tl_assert(isIRAtom(st->Ist.Put.data));
njn25e49d8e72002-09-23 09:36:25 +00001045 break;
1046
sewardj9f649aa2004-11-22 20:38:40 +00001047 case Ist_PutI:
sewardj710d6c22005-03-20 18:55:15 +00001048 tl_assert(isIRAtom(st->Ist.PutI.ix));
1049 tl_assert(isIRAtom(st->Ist.PutI.data));
njnc2699f62003-09-05 23:29:33 +00001050 break;
1051
sewardj9f649aa2004-11-22 20:38:40 +00001052 case Ist_Exit:
sewardj710d6c22005-03-20 18:55:15 +00001053 tl_assert(isIRAtom(st->Ist.Exit.guard));
njn25e49d8e72002-09-23 09:36:25 +00001054 break;
1055
sewardj9f649aa2004-11-22 20:38:40 +00001056 case Ist_Dirty:
1057 if (st->Ist.Dirty.details->mFx != Ifx_None) {
1058 /* We classify Ifx_Modify as a load. */
1059 isLoad = st->Ist.Dirty.details->mFx != Ifx_Write;
1060 hsz = st->Ist.Dirty.details->mSize;
1061 aexpr = st->Ist.Dirty.details->mAddr;
1062 guard = st->Ist.Dirty.details->guard;
sewardj710d6c22005-03-20 18:55:15 +00001063 tl_assert(isIRAtom(aexpr));
sewardj9f649aa2004-11-22 20:38:40 +00001064 }
1065 break;
sewardje3891fa2003-06-15 03:13:48 +00001066
sewardj21dc3452005-03-21 00:27:41 +00001067 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00001068 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00001069 case Ist_MFence:
1070 break;
1071
njn25e49d8e72002-09-23 09:36:25 +00001072 default:
sewardj9f649aa2004-11-22 20:38:40 +00001073 VG_(printf)("\n");
1074 ppIRStmt(st);
1075 VG_(printf)("\n");
1076 VG_(tool_panic)("addrcheck: unhandled IRStmt");
njn25e49d8e72002-09-23 09:36:25 +00001077 }
sewardj9f649aa2004-11-22 20:38:40 +00001078
1079 /* If needed, add a helper call. */
1080 if (aexpr) {
1081 tl_assert(hsz > 0);
1082 switch (hsz) {
1083 case 4:
1084 if (isLoad)
1085 di = unsafeIRDirty_0_N( 1, "ach_LOAD4", &ach_LOAD4,
1086 mkIRExprVec_1(aexpr));
1087 else
1088 di = unsafeIRDirty_0_N( 1, "ach_STORE4", &ach_STORE4,
1089 mkIRExprVec_1(aexpr));
1090 break;
1091 case 2:
1092 if (isLoad)
1093 di = unsafeIRDirty_0_N( 1, "ach_LOAD2", &ach_LOAD2,
1094 mkIRExprVec_1(aexpr));
1095 else
1096 di = unsafeIRDirty_0_N( 1, "ach_STORE2", &ach_STORE2,
1097 mkIRExprVec_1(aexpr));
1098 break;
1099 case 1:
1100 if (isLoad)
1101 di = unsafeIRDirty_0_N( 1, "ach_LOAD1", &ach_LOAD1,
1102 mkIRExprVec_1(aexpr));
1103 else
1104 di = unsafeIRDirty_0_N( 1, "ach_STORE1", &ach_STORE1,
1105 mkIRExprVec_1(aexpr));
1106 break;
1107 default:
1108 if (isLoad)
1109 di = unsafeIRDirty_0_N(
1110 2, "ach_LOADN", &ach_LOADN,
1111 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1112 else
1113 di = unsafeIRDirty_0_N(
1114 2, "ach_STOREN", &ach_STOREN,
1115 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1116 break;
1117 }
1118
1119 /* If the call has arisen as a result of a dirty helper which
1120 references memory, we need to inherit the guard from the
1121 dirty helper. */
1122 if (guard)
1123 di->guard = dopyIRExpr(guard);
1124
1125 /* emit the helper call */
1126 addStmtToIRBB( bb, IRStmt_Dirty(di) );
1127
1128 }
1129
1130 /* And finally, copy the expr itself to the output. */
sewardjbd598e12005-01-07 12:10:21 +00001131 addStmtToIRBB( bb, st );
njn25e49d8e72002-09-23 09:36:25 +00001132 }
1133
sewardj9f649aa2004-11-22 20:38:40 +00001134 return bb;
njn25e49d8e72002-09-23 09:36:25 +00001135}
1136
1137
njn25e49d8e72002-09-23 09:36:25 +00001138/*------------------------------------------------------------*/
1139/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
1140/*------------------------------------------------------------*/
1141
sewardja4495682002-10-21 07:29:59 +00001142/* For the memory leak detector, say whether an entire 64k chunk of
1143 address space is possibly in use, or not. If in doubt return
1144 True.
njn25e49d8e72002-09-23 09:36:25 +00001145*/
sewardja4495682002-10-21 07:29:59 +00001146static
1147Bool ac_is_valid_64k_chunk ( UInt chunk_number )
njn25e49d8e72002-09-23 09:36:25 +00001148{
sewardjb5f6f512005-03-10 23:59:00 +00001149 tl_assert(chunk_number >= 0 && chunk_number < PRIMARY_SIZE);
1150 if (primary_map[chunk_number] == DSM_NOTADDR) {
sewardja4495682002-10-21 07:29:59 +00001151 /* Definitely not in use. */
1152 return False;
1153 } else {
1154 return True;
njn25e49d8e72002-09-23 09:36:25 +00001155 }
1156}
1157
1158
sewardja4495682002-10-21 07:29:59 +00001159/* For the memory leak detector, say whether or not a given word
1160 address is to be regarded as valid. */
1161static
1162Bool ac_is_valid_address ( Addr a )
1163{
1164 UChar abits;
njnbe91aae2005-03-27 01:42:41 +00001165 tl_assert(VG_IS_4_ALIGNED(a));
sewardja4495682002-10-21 07:29:59 +00001166 abits = get_abits4_ALIGNED(a);
1167 if (abits == VGM_NIBBLE_VALID) {
1168 return True;
1169 } else {
1170 return False;
1171 }
1172}
1173
1174
nethercote996901a2004-08-03 13:29:09 +00001175/* Leak detector for this tool. We don't actually do anything, merely
sewardja4495682002-10-21 07:29:59 +00001176 run the generic leak detector with suitable parameters for this
nethercote996901a2004-08-03 13:29:09 +00001177 tool. */
njnb8dca862005-03-14 02:42:44 +00001178static void ac_detect_memory_leaks ( ThreadId tid, LeakCheckMode mode )
njn25e49d8e72002-09-23 09:36:25 +00001179{
njnb8dca862005-03-14 02:42:44 +00001180 MAC_(do_detect_memory_leaks) ( tid, mode, ac_is_valid_64k_chunk, ac_is_valid_address );
njn25e49d8e72002-09-23 09:36:25 +00001181}
1182
1183
1184/* ---------------------------------------------------------------------
1185 Sanity check machinery (permanently engaged).
1186 ------------------------------------------------------------------ */
1187
njn51d827b2005-05-09 01:02:08 +00001188static Bool ac_cheap_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00001189{
jseward9800fd32004-01-04 23:08:04 +00001190 /* nothing useful we can rapidly check */
1191 return True;
njn25e49d8e72002-09-23 09:36:25 +00001192}
1193
njn51d827b2005-05-09 01:02:08 +00001194static Bool ac_expensive_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00001195{
1196 Int i;
1197
sewardjb5f6f512005-03-10 23:59:00 +00001198#if 0
njn25e49d8e72002-09-23 09:36:25 +00001199 /* Make sure nobody changed the distinguished secondary. */
1200 for (i = 0; i < 8192; i++)
1201 if (distinguished_secondary_map.abits[i] != VGM_BYTE_INVALID)
1202 return False;
sewardjb5f6f512005-03-10 23:59:00 +00001203#endif
njn25e49d8e72002-09-23 09:36:25 +00001204
1205 /* Make sure that the upper 3/4 of the primary map hasn't
1206 been messed with. */
sewardjb5f6f512005-03-10 23:59:00 +00001207 for (i = PRIMARY_SIZE; i < PRIMARY_SIZE*4; i++)
1208 if (primary_map[i] != DSM_NOTADDR)
njn25e49d8e72002-09-23 09:36:25 +00001209 return False;
1210
1211 return True;
1212}
1213
njn47363ab2003-04-21 13:24:40 +00001214/*------------------------------------------------------------*/
1215/*--- Client requests ---*/
1216/*------------------------------------------------------------*/
1217
njn51d827b2005-05-09 01:02:08 +00001218static Bool ac_handle_client_request ( ThreadId tid, UWord* arg, UWord *ret )
sewardjd8033d92002-12-08 22:16:58 +00001219{
sewardjbf310d92002-12-28 13:09:57 +00001220#define IGNORE(what) \
1221 do { \
1222 if (moans-- > 0) { \
1223 VG_(message)(Vg_UserMsg, \
njn02bc4b82005-05-15 17:28:26 +00001224 "Warning: Addrcheck: ignoring '%s' request.", what); \
sewardjbf310d92002-12-28 13:09:57 +00001225 VG_(message)(Vg_UserMsg, \
nethercote137bc552003-11-14 17:47:54 +00001226 " To honour this request, rerun with --tool=memcheck."); \
sewardjbf310d92002-12-28 13:09:57 +00001227 } \
1228 } while (0)
1229
sewardjbf310d92002-12-28 13:09:57 +00001230 static Int moans = 3;
sewardjd8033d92002-12-08 22:16:58 +00001231
1232 /* Overload memcheck client reqs */
njnfc26ff92004-11-22 19:12:49 +00001233 if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
sewardjd62e03b2004-12-10 12:01:14 +00001234 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
1235 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
1236 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
1237 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
1238 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
1239 && VG_USERREQ__MEMPOOL_FREE != arg[0])
sewardjd8033d92002-12-08 22:16:58 +00001240 return False;
1241
1242 switch (arg[0]) {
1243 case VG_USERREQ__DO_LEAK_CHECK:
njnb8dca862005-03-14 02:42:44 +00001244 ac_detect_memory_leaks(tid, arg[1] ? LC_Summary : LC_Full);
sewardjd8033d92002-12-08 22:16:58 +00001245 *ret = 0; /* return value is meaningless */
1246 break;
1247
sewardjbf310d92002-12-28 13:09:57 +00001248 /* Ignore these */
sewardjd8033d92002-12-08 22:16:58 +00001249 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
sewardjbf310d92002-12-28 13:09:57 +00001250 IGNORE("VALGRIND_CHECK_WRITABLE");
1251 return False;
sewardjd8033d92002-12-08 22:16:58 +00001252 case VG_USERREQ__CHECK_READABLE: /* check readable */
sewardjbf310d92002-12-28 13:09:57 +00001253 IGNORE("VALGRIND_CHECK_READABLE");
1254 return False;
sewardjd8033d92002-12-08 22:16:58 +00001255 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
sewardjbf310d92002-12-28 13:09:57 +00001256 IGNORE("VALGRIND_MAKE_NOACCESS");
1257 return False;
sewardjd8033d92002-12-08 22:16:58 +00001258 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
sewardjbf310d92002-12-28 13:09:57 +00001259 IGNORE("VALGRIND_MAKE_WRITABLE");
1260 return False;
sewardjd8033d92002-12-08 22:16:58 +00001261 case VG_USERREQ__MAKE_READABLE: /* make readable */
sewardjbf310d92002-12-28 13:09:57 +00001262 IGNORE("VALGRIND_MAKE_READABLE");
1263 return False;
sewardjd8033d92002-12-08 22:16:58 +00001264 case VG_USERREQ__DISCARD: /* discard */
sewardjbf310d92002-12-28 13:09:57 +00001265 IGNORE("VALGRIND_CHECK_DISCARD");
1266 return False;
sewardjd8033d92002-12-08 22:16:58 +00001267
1268 default:
nethercoted1b64b22004-11-04 18:22:28 +00001269 if (MAC_(handle_common_client_requests)(tid, arg, ret )) {
njn47363ab2003-04-21 13:24:40 +00001270 return True;
1271 } else {
1272 VG_(message)(Vg_UserMsg,
nethercoted1b64b22004-11-04 18:22:28 +00001273 "Warning: unknown addrcheck client request code %llx",
1274 (ULong)arg[0]);
njn47363ab2003-04-21 13:24:40 +00001275 return False;
1276 }
sewardjd8033d92002-12-08 22:16:58 +00001277 }
1278 return True;
sewardjbf310d92002-12-28 13:09:57 +00001279
1280#undef IGNORE
sewardjd8033d92002-12-08 22:16:58 +00001281}
1282
njn25e49d8e72002-09-23 09:36:25 +00001283/*------------------------------------------------------------*/
1284/*--- Setup ---*/
1285/*------------------------------------------------------------*/
1286
njn51d827b2005-05-09 01:02:08 +00001287static Bool ac_process_cmd_line_option(Char* arg)
njn25e49d8e72002-09-23 09:36:25 +00001288{
njn43c799e2003-04-08 00:08:52 +00001289 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001290}
1291
njn51d827b2005-05-09 01:02:08 +00001292static void ac_print_usage(void)
njn25e49d8e72002-09-23 09:36:25 +00001293{
njn3e884182003-04-15 13:03:23 +00001294 MAC_(print_common_usage)();
1295}
1296
njn51d827b2005-05-09 01:02:08 +00001297static void ac_print_debug_usage(void)
njn3e884182003-04-15 13:03:23 +00001298{
1299 MAC_(print_common_debug_usage)();
njn25e49d8e72002-09-23 09:36:25 +00001300}
1301
1302
1303/*------------------------------------------------------------*/
njn51d827b2005-05-09 01:02:08 +00001304/*--- Setup and finalisation ---*/
njn25e49d8e72002-09-23 09:36:25 +00001305/*------------------------------------------------------------*/
1306
njn51d827b2005-05-09 01:02:08 +00001307static void ac_post_clo_init ( void )
1308{
1309}
1310
1311static void ac_fini ( Int exitcode )
1312{
1313 MAC_(common_fini)( ac_detect_memory_leaks );
1314}
1315
1316static void ac_pre_clo_init(void)
njn25e49d8e72002-09-23 09:36:25 +00001317{
njn810086f2002-11-14 12:42:47 +00001318 VG_(details_name) ("Addrcheck");
1319 VG_(details_version) (NULL);
1320 VG_(details_description) ("a fine-grained address checker");
1321 VG_(details_copyright_author)(
njn53612422005-03-12 16:22:54 +00001322 "Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.");
nethercote421281e2003-11-20 16:20:55 +00001323 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardj78210aa2002-12-01 02:55:46 +00001324 VG_(details_avg_translation_sizeB) ( 135 );
njn25e49d8e72002-09-23 09:36:25 +00001325
njn51d827b2005-05-09 01:02:08 +00001326 VG_(basic_tool_funcs) (ac_post_clo_init,
1327 ac_instrument,
1328 ac_fini);
njn8a97c6d2005-03-31 04:37:24 +00001329
njn810086f2002-11-14 12:42:47 +00001330 VG_(needs_core_errors) ();
njn51d827b2005-05-09 01:02:08 +00001331 VG_(needs_tool_errors) (MAC_(eq_Error),
1332 ac_pp_Error,
1333 MAC_(update_extra),
1334 MAC_(shared_recognised_suppression),
1335 MAC_(read_extra_suppression_info),
1336 MAC_(error_matches_suppression),
1337 MAC_(get_error_name),
1338 MAC_(print_extra_suppression_info));
njn810086f2002-11-14 12:42:47 +00001339 VG_(needs_libc_freeres) ();
njn51d827b2005-05-09 01:02:08 +00001340 VG_(needs_command_line_options)(MAC_(process_common_cmd_line_option),
1341 MAC_(print_common_usage),
1342 MAC_(print_common_debug_usage));
1343 VG_(needs_client_requests) (ac_handle_client_request);
1344 VG_(needs_sanity_checks) (ac_cheap_sanity_check,
1345 ac_expensive_sanity_check);
fitzhardinge98abfc72003-12-16 02:05:15 +00001346 VG_(needs_shadow_memory) ();
njn25e49d8e72002-09-23 09:36:25 +00001347
njn51d827b2005-05-09 01:02:08 +00001348 VG_(malloc_funcs) (MAC_(malloc),
1349 MAC_(__builtin_new),
1350 MAC_(__builtin_vec_new),
1351 MAC_(memalign),
1352 MAC_(calloc),
1353 MAC_(free),
1354 MAC_(__builtin_delete),
1355 MAC_(__builtin_vec_delete),
1356 MAC_(realloc),
1357 MAC_MALLOC_REDZONE_SZB );
njn8a97c6d2005-03-31 04:37:24 +00001358
njn3e884182003-04-15 13:03:23 +00001359 MAC_( new_mem_heap) = & ac_new_mem_heap;
1360 MAC_( ban_mem_heap) = & ac_make_noaccess;
1361 MAC_(copy_mem_heap) = & ac_copy_address_range_state;
1362 MAC_( die_mem_heap) = & ac_make_noaccess;
sewardjecf8e102003-07-12 12:11:39 +00001363 MAC_(check_noaccess) = & ac_check_noaccess;
njn3e884182003-04-15 13:03:23 +00001364
njn51d827b2005-05-09 01:02:08 +00001365 VG_(track_new_mem_startup) ( & ac_new_mem_startup );
1366 VG_(track_new_mem_stack_signal)( & ac_make_accessible );
1367 VG_(track_new_mem_brk) ( & ac_make_accessible );
1368 VG_(track_new_mem_mmap) ( & ac_new_mem_mmap );
njn25e49d8e72002-09-23 09:36:25 +00001369
njn51d827b2005-05-09 01:02:08 +00001370 VG_(track_copy_mem_remap) ( & ac_copy_address_range_state );
njn3e884182003-04-15 13:03:23 +00001371
njn51d827b2005-05-09 01:02:08 +00001372 VG_(track_die_mem_stack_signal)( & ac_make_noaccess );
1373 VG_(track_die_mem_brk) ( & ac_make_noaccess );
1374 VG_(track_die_mem_munmap) ( & ac_make_noaccess );
njn3e884182003-04-15 13:03:23 +00001375
njn51d827b2005-05-09 01:02:08 +00001376 VG_(track_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
1377 VG_(track_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
1378 VG_(track_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
1379 VG_(track_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
1380 VG_(track_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
1381 VG_(track_new_mem_stack) ( & MAC_(new_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001382
njn51d827b2005-05-09 01:02:08 +00001383 VG_(track_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
1384 VG_(track_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
1385 VG_(track_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
1386 VG_(track_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
1387 VG_(track_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
1388 VG_(track_die_mem_stack) ( & MAC_(die_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001389
njn51d827b2005-05-09 01:02:08 +00001390 VG_(track_ban_mem_stack) ( & ac_make_noaccess );
njn25e49d8e72002-09-23 09:36:25 +00001391
njn51d827b2005-05-09 01:02:08 +00001392 VG_(track_pre_mem_read) ( & ac_check_is_readable );
1393 VG_(track_pre_mem_read_asciiz) ( & ac_check_is_readable_asciiz );
1394 VG_(track_pre_mem_write) ( & ac_check_is_writable );
1395 VG_(track_post_mem_write) ( & ac_post_mem_write );
njn25e49d8e72002-09-23 09:36:25 +00001396
njn31066fd2005-03-26 00:42:02 +00001397 VG_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
1398 VG_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
1399 VG_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
njnd04b7c62002-10-03 14:05:52 +00001400
1401 init_shadow_memory();
njn3e884182003-04-15 13:03:23 +00001402 MAC_(common_pre_clo_init)();
njn5c004e42002-11-18 11:04:50 +00001403}
1404
njn51d827b2005-05-09 01:02:08 +00001405VG_DETERMINE_INTERFACE_VERSION(ac_pre_clo_init, 1./8)
fitzhardinge98abfc72003-12-16 02:05:15 +00001406
1407
njn25e49d8e72002-09-23 09:36:25 +00001408/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00001409/*--- end ac_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00001410/*--------------------------------------------------------------------*/