blob: d36684d45d8ed65a74a8942ad8ab913c033ebd71 [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
njn9b007f62003-04-07 14:40:25 +000036
njn25e49d8e72002-09-23 09:36:25 +000037/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000038/*--- Comparing and printing errors ---*/
39/*------------------------------------------------------------*/
40
njn51d827b2005-05-09 01:02:08 +000041static void ac_pp_Error ( Error* err )
njn25e49d8e72002-09-23 09:36:25 +000042{
njn43c799e2003-04-08 00:08:52 +000043 MAC_Error* err_extra = VG_(get_error_extra)(err);
njn25e49d8e72002-09-23 09:36:25 +000044
njn810086f2002-11-14 12:42:47 +000045 switch (VG_(get_error_kind)(err)) {
njn25e49d8e72002-09-23 09:36:25 +000046 case CoreMemErr:
njn43c799e2003-04-08 00:08:52 +000047 VG_(message)(Vg_UserMsg, "%s contains unaddressable byte(s)",
48 VG_(get_error_string)(err));
49 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
njn25e49d8e72002-09-23 09:36:25 +000050 break;
51
njn25e49d8e72002-09-23 09:36:25 +000052 case ParamErr:
njn43c799e2003-04-08 00:08:52 +000053 VG_(message)(Vg_UserMsg,
54 "Syscall param %s contains unaddressable byte(s)",
55 VG_(get_error_string)(err) );
56 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
57 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
njn25e49d8e72002-09-23 09:36:25 +000058 break;
59
60 case UserErr:
njn43c799e2003-04-08 00:08:52 +000061 VG_(message)(Vg_UserMsg,
62 "Unaddressable byte(s) found during client check request");
63 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
64 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
njn25e49d8e72002-09-23 09:36:25 +000065 break;
66
67 default:
njnb126f732004-11-22 17:57:07 +000068 MAC_(pp_shared_Error)(err);
njn43c799e2003-04-08 00:08:52 +000069 break;
njn25e49d8e72002-09-23 09:36:25 +000070 }
71}
72
73/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000074/*--- Suppressions ---*/
75/*------------------------------------------------------------*/
76
njn51d827b2005-05-09 01:02:08 +000077static Bool ac_recognised_suppression ( Char* name, Supp* su )
njn25e49d8e72002-09-23 09:36:25 +000078{
njn43c799e2003-04-08 00:08:52 +000079 return MAC_(shared_recognised_suppression)(name, su);
njn25e49d8e72002-09-23 09:36:25 +000080}
81
njn5c004e42002-11-18 11:04:50 +000082#define DEBUG(fmt, args...) //VG_(printf)(fmt, ## args)
83
njn25e49d8e72002-09-23 09:36:25 +000084/*------------------------------------------------------------*/
85/*--- Low-level support for memory checking. ---*/
86/*------------------------------------------------------------*/
87
88/* All reads and writes are checked against a memory map, which
89 records the state of all memory in the process. The memory map is
90 organised like this:
91
92 The top 16 bits of an address are used to index into a top-level
93 map table, containing 65536 entries. Each entry is a pointer to a
94 second-level map, which records the accesibililty and validity
95 permissions for the 65536 bytes indexed by the lower 16 bits of the
96 address. Each byte is represented by one bit, indicating
97 accessibility. So each second-level map contains 8192 bytes. This
98 two-level arrangement conveniently divides the 4G address space
99 into 64k lumps, each size 64k bytes.
100
101 All entries in the primary (top-level) map must point to a valid
102 secondary (second-level) map. Since most of the 4G of address
103 space will not be in use -- ie, not mapped at all -- there is a
njn02bc4b82005-05-15 17:28:26 +0000104 distinguished secondary map, which indicates 'not addressible and
njn25e49d8e72002-09-23 09:36:25 +0000105 not valid' writeable for all bytes. Entries in the primary map for
106 which the entire 64k is not in use at all point at this
107 distinguished map.
108
109 [...] lots of stuff deleted due to out of date-ness
110
111 As a final optimisation, the alignment and address checks for
112 4-byte loads and stores are combined in a neat way. The primary
113 map is extended to have 262144 entries (2^18), rather than 2^16.
114 The top 3/4 of these entries are permanently set to the
115 distinguished secondary map. For a 4-byte load/store, the
116 top-level map is indexed not with (addr >> 16) but instead f(addr),
117 where
118
119 f( XXXX XXXX XXXX XXXX ____ ____ ____ __YZ )
120 = ____ ____ ____ __YZ XXXX XXXX XXXX XXXX or
121 = ____ ____ ____ __ZY XXXX XXXX XXXX XXXX
122
123 ie the lowest two bits are placed above the 16 high address bits.
124 If either of these two bits are nonzero, the address is misaligned;
125 this will select a secondary map from the upper 3/4 of the primary
126 map. Because this is always the distinguished secondary map, a
127 (bogus) address check failure will result. The failure handling
128 code can then figure out whether this is a genuine addr check
129 failure or whether it is a possibly-legitimate access at a
130 misaligned address. */
131
132
133/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000134/*--- Function declarations. ---*/
135/*------------------------------------------------------------*/
136
njnc2699f62003-09-05 23:29:33 +0000137static void ac_ACCESS4_SLOWLY ( Addr a, Bool isWrite );
138static void ac_ACCESS2_SLOWLY ( Addr a, Bool isWrite );
139static void ac_ACCESS1_SLOWLY ( Addr a, Bool isWrite );
nethercote928a5f72004-11-03 18:10:37 +0000140static void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, SizeT size, Bool isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000141
142/*------------------------------------------------------------*/
143/*--- Data defns. ---*/
144/*------------------------------------------------------------*/
145
146typedef
147 struct {
sewardjb5f6f512005-03-10 23:59:00 +0000148 UChar abits[SECONDARY_SIZE / 8];
njn25e49d8e72002-09-23 09:36:25 +0000149 }
150 AcSecMap;
151
sewardjb5f6f512005-03-10 23:59:00 +0000152static AcSecMap* primary_map[ /*PRIMARY_SIZE*/ PRIMARY_SIZE*4 ];
153static const AcSecMap distinguished_secondary_maps[2] = {
154 [ VGM_BIT_INVALID ] = { { [0 ... (SECONDARY_SIZE/8) - 1] = VGM_BYTE_INVALID } },
155 [ VGM_BIT_VALID ] = { { [0 ... (SECONDARY_SIZE/8) - 1] = VGM_BYTE_VALID } },
156};
157#define N_SECONDARY_MAPS (sizeof(distinguished_secondary_maps)/sizeof(*distinguished_secondary_maps))
158
159#define DSM_IDX(a) ((a) & 1)
160
161#define DSM(a) ((AcSecMap *)&distinguished_secondary_maps[DSM_IDX(a)])
162
163#define DSM_NOTADDR DSM(VGM_BIT_INVALID)
164#define DSM_ADDR DSM(VGM_BIT_VALID)
njn25e49d8e72002-09-23 09:36:25 +0000165
njn25e49d8e72002-09-23 09:36:25 +0000166static void init_shadow_memory ( void )
167{
sewardjb5f6f512005-03-10 23:59:00 +0000168 Int i, a;
njn25e49d8e72002-09-23 09:36:25 +0000169
sewardjb5f6f512005-03-10 23:59:00 +0000170 /* check construction of the distinguished secondaries */
sewardj76754cf2005-03-14 00:14:04 +0000171 tl_assert(VGM_BIT_INVALID == 1);
172 tl_assert(VGM_BIT_VALID == 0);
sewardjb5f6f512005-03-10 23:59:00 +0000173
174 for(a = 0; a <= 1; a++)
sewardj76754cf2005-03-14 00:14:04 +0000175 tl_assert(distinguished_secondary_maps[DSM_IDX(a)].abits[0] == BIT_EXPAND(a));
njn25e49d8e72002-09-23 09:36:25 +0000176
177 /* These entries gradually get overwritten as the used address
178 space expands. */
sewardjb5f6f512005-03-10 23:59:00 +0000179 for (i = 0; i < PRIMARY_SIZE; i++)
180 primary_map[i] = DSM_NOTADDR;
njn25e49d8e72002-09-23 09:36:25 +0000181
182 /* These ones should never change; it's a bug in Valgrind if they do. */
sewardjb5f6f512005-03-10 23:59:00 +0000183 for (i = PRIMARY_SIZE; i < PRIMARY_SIZE*4; i++)
184 primary_map[i] = DSM_NOTADDR;
njn25e49d8e72002-09-23 09:36:25 +0000185}
186
njn25e49d8e72002-09-23 09:36:25 +0000187/*------------------------------------------------------------*/
188/*--- Basic bitmap management, reading and writing. ---*/
189/*------------------------------------------------------------*/
190
191/* Allocate and initialise a secondary map. */
192
193static AcSecMap* alloc_secondary_map ( __attribute__ ((unused))
sewardjb5f6f512005-03-10 23:59:00 +0000194 Char* caller,
195 const AcSecMap *prototype)
njn25e49d8e72002-09-23 09:36:25 +0000196{
197 AcSecMap* map;
njn25e49d8e72002-09-23 09:36:25 +0000198 PROF_EVENT(10);
199
fitzhardinge98abfc72003-12-16 02:05:15 +0000200 map = (AcSecMap *)VG_(shadow_alloc)(sizeof(AcSecMap));
sewardjb5f6f512005-03-10 23:59:00 +0000201 VG_(memcpy)(map, prototype, sizeof(*map));
njn25e49d8e72002-09-23 09:36:25 +0000202
203 /* VG_(printf)("ALLOC_2MAP(%s)\n", caller ); */
204 return map;
205}
206
207
208/* Basic reading/writing of the bitmaps, for byte-sized accesses. */
209
210static __inline__ UChar get_abit ( Addr a )
211{
sewardjb5f6f512005-03-10 23:59:00 +0000212 AcSecMap* sm = primary_map[PM_IDX(a)];
213 UInt sm_off = SM_OFF(a);
njn25e49d8e72002-09-23 09:36:25 +0000214 PROF_EVENT(20);
215# if 0
216 if (IS_DISTINGUISHED_SM(sm))
217 VG_(message)(Vg_DebugMsg,
218 "accessed distinguished 2ndary (A)map! 0x%x\n", a);
219# endif
220 return BITARR_TEST(sm->abits, sm_off)
221 ? VGM_BIT_INVALID : VGM_BIT_VALID;
222}
223
sewardj56867352003-10-12 10:27:06 +0000224static /* __inline__ */ void set_abit ( Addr a, UChar abit )
njn25e49d8e72002-09-23 09:36:25 +0000225{
226 AcSecMap* sm;
227 UInt sm_off;
228 PROF_EVENT(22);
229 ENSURE_MAPPABLE(a, "set_abit");
sewardjb5f6f512005-03-10 23:59:00 +0000230 sm = primary_map[PM_IDX(a)];
231 sm_off = SM_OFF(a);
njn25e49d8e72002-09-23 09:36:25 +0000232 if (abit)
233 BITARR_SET(sm->abits, sm_off);
234 else
235 BITARR_CLEAR(sm->abits, sm_off);
236}
237
238
239/* Reading/writing of the bitmaps, for aligned word-sized accesses. */
240
241static __inline__ UChar get_abits4_ALIGNED ( Addr a )
242{
243 AcSecMap* sm;
244 UInt sm_off;
245 UChar abits8;
246 PROF_EVENT(24);
247# ifdef VG_DEBUG_MEMORY
njnbe91aae2005-03-27 01:42:41 +0000248 tl_assert(VG_IS_4_ALIGNED(a));
njn25e49d8e72002-09-23 09:36:25 +0000249# endif
sewardjb5f6f512005-03-10 23:59:00 +0000250 sm = primary_map[PM_IDX(a)];
251 sm_off = SM_OFF(a);
njn25e49d8e72002-09-23 09:36:25 +0000252 abits8 = sm->abits[sm_off >> 3];
253 abits8 >>= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
254 abits8 &= 0x0F;
255 return abits8;
256}
257
258
259
260/*------------------------------------------------------------*/
261/*--- Setting permissions over address ranges. ---*/
262/*------------------------------------------------------------*/
263
sewardj56867352003-10-12 10:27:06 +0000264static /* __inline__ */
nethercote451eae92004-11-02 13:06:32 +0000265void set_address_range_perms ( Addr a, SizeT len, UInt example_a_bit )
njn25e49d8e72002-09-23 09:36:25 +0000266{
267 UChar abyte8;
268 UInt sm_off;
269 AcSecMap* sm;
270
271 PROF_EVENT(30);
272
273 if (len == 0)
274 return;
275
276 if (len > 100 * 1000 * 1000) {
277 VG_(message)(Vg_UserMsg,
278 "Warning: set address range perms: "
279 "large range %u, a %d",
280 len, example_a_bit );
281 }
282
283 VGP_PUSHCC(VgpSetMem);
284
285 /* Requests to change permissions of huge address ranges may
286 indicate bugs in our machinery. 30,000,000 is arbitrary, but so
287 far all legitimate requests have fallen beneath that size. */
288 /* 4 Mar 02: this is just stupid; get rid of it. */
njnca82cc02004-11-22 17:18:48 +0000289 /* tl_assert(len < 30000000); */
njn25e49d8e72002-09-23 09:36:25 +0000290
291 /* Check the permissions make sense. */
njnca82cc02004-11-22 17:18:48 +0000292 tl_assert(example_a_bit == VGM_BIT_VALID
njn25e49d8e72002-09-23 09:36:25 +0000293 || example_a_bit == VGM_BIT_INVALID);
294
295 /* In order that we can charge through the address space at 8
296 bytes/main-loop iteration, make up some perms. */
sewardjb5f6f512005-03-10 23:59:00 +0000297 abyte8 = BIT_EXPAND(example_a_bit);
njn25e49d8e72002-09-23 09:36:25 +0000298
299# ifdef VG_DEBUG_MEMORY
300 /* Do it ... */
301 while (True) {
302 PROF_EVENT(31);
303 if (len == 0) break;
304 set_abit ( a, example_a_bit );
305 set_vbyte ( a, vbyte );
306 a++;
307 len--;
308 }
309
310# else
311 /* Slowly do parts preceding 8-byte alignment. */
312 while (True) {
313 PROF_EVENT(31);
314 if (len == 0) break;
315 if ((a % 8) == 0) break;
316 set_abit ( a, example_a_bit );
317 a++;
318 len--;
319 }
320
321 if (len == 0) {
322 VGP_POPCC(VgpSetMem);
323 return;
324 }
njnca82cc02004-11-22 17:18:48 +0000325 tl_assert((a % 8) == 0 && len > 0);
njn25e49d8e72002-09-23 09:36:25 +0000326
sewardjb5f6f512005-03-10 23:59:00 +0000327 /* Once aligned, go fast up to primary boundary. */
328 for (; (a & SECONDARY_MASK) && len >= 8; a += 8, len -= 8) {
njn25e49d8e72002-09-23 09:36:25 +0000329 PROF_EVENT(32);
sewardjb5f6f512005-03-10 23:59:00 +0000330
331 /* If the primary is already pointing to a distinguished map
332 with the same properties as we're trying to set, then leave
333 it that way. */
334 if (primary_map[PM_IDX(a)] == DSM(example_a_bit))
335 continue;
njn25e49d8e72002-09-23 09:36:25 +0000336 ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
sewardjb5f6f512005-03-10 23:59:00 +0000337 sm = primary_map[PM_IDX(a)];
338 sm_off = SM_OFF(a);
njn25e49d8e72002-09-23 09:36:25 +0000339 sm->abits[sm_off >> 3] = abyte8;
njn25e49d8e72002-09-23 09:36:25 +0000340 }
341
sewardjb5f6f512005-03-10 23:59:00 +0000342 /* Now set whole secondary maps to the right distinguished value.
343
344 Note that if the primary already points to a non-distinguished
345 secondary, then don't replace the reference. That would just
346 leak memory.
347 */
348 for(; len >= SECONDARY_SIZE; a += SECONDARY_SIZE, len -= SECONDARY_SIZE) {
349 sm = primary_map[PM_IDX(a)];
350
351 if (IS_DISTINGUISHED_SM(sm))
352 primary_map[PM_IDX(a)] = DSM(example_a_bit);
353 else
354 VG_(memset)(sm->abits, abyte8, sizeof(sm->abits));
njn25e49d8e72002-09-23 09:36:25 +0000355 }
sewardjb5f6f512005-03-10 23:59:00 +0000356
357 /* Now finished the remains. */
358 for (; len >= 8; a += 8, len -= 8) {
359 PROF_EVENT(32);
360
361 /* If the primary is already pointing to a distinguished map
362 with the same properties as we're trying to set, then leave
363 it that way. */
364 if (primary_map[PM_IDX(a)] == DSM(example_a_bit))
365 continue;
366 ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
367 sm = primary_map[PM_IDX(a)];
368 sm_off = SM_OFF(a);
369 sm->abits[sm_off >> 3] = abyte8;
370 }
371
njn25e49d8e72002-09-23 09:36:25 +0000372
373 /* Finish the upper fragment. */
374 while (True) {
375 PROF_EVENT(33);
376 if (len == 0) break;
377 set_abit ( a, example_a_bit );
378 a++;
379 len--;
380 }
381# endif
382
njn25e49d8e72002-09-23 09:36:25 +0000383 VGP_POPCC(VgpSetMem);
384}
385
386/* Set permissions for address ranges ... */
387
nethercote451eae92004-11-02 13:06:32 +0000388static void ac_make_noaccess ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000389{
390 PROF_EVENT(35);
njn5c004e42002-11-18 11:04:50 +0000391 DEBUG("ac_make_noaccess(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000392 set_address_range_perms ( a, len, VGM_BIT_INVALID );
393}
394
nethercote451eae92004-11-02 13:06:32 +0000395static void ac_make_accessible ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000396{
njn5c004e42002-11-18 11:04:50 +0000397 PROF_EVENT(38);
398 DEBUG("ac_make_accessible(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000399 set_address_range_perms ( a, len, VGM_BIT_VALID );
400}
401
njn9b007f62003-04-07 14:40:25 +0000402static __inline__
403void make_aligned_word_noaccess(Addr a)
404{
405 AcSecMap* sm;
406 UInt sm_off;
407 UChar mask;
408
409 VGP_PUSHCC(VgpESPAdj);
410 ENSURE_MAPPABLE(a, "make_aligned_word_noaccess");
sewardjb5f6f512005-03-10 23:59:00 +0000411 sm = primary_map[PM_IDX(a)];
412 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000413 mask = 0x0F;
414 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
415 /* mask now contains 1s where we wish to make address bits invalid (1s). */
416 sm->abits[sm_off >> 3] |= mask;
417 VGP_POPCC(VgpESPAdj);
418}
419
420static __inline__
421void make_aligned_word_accessible(Addr a)
422{
423 AcSecMap* sm;
424 UInt sm_off;
425 UChar mask;
426
427 VGP_PUSHCC(VgpESPAdj);
428 ENSURE_MAPPABLE(a, "make_aligned_word_accessible");
sewardjb5f6f512005-03-10 23:59:00 +0000429 sm = primary_map[PM_IDX(a)];
430 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000431 mask = 0x0F;
432 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
433 /* mask now contains 1s where we wish to make address bits
434 invalid (0s). */
435 sm->abits[sm_off >> 3] &= ~mask;
436 VGP_POPCC(VgpESPAdj);
437}
438
439/* Nb: by "aligned" here we mean 8-byte aligned */
440static __inline__
441void make_aligned_doubleword_accessible(Addr a)
442{
443 AcSecMap* sm;
444 UInt sm_off;
445
446 VGP_PUSHCC(VgpESPAdj);
447 ENSURE_MAPPABLE(a, "make_aligned_doubleword_accessible");
sewardjb5f6f512005-03-10 23:59:00 +0000448 sm = primary_map[PM_IDX(a)];
449 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000450 sm->abits[sm_off >> 3] = VGM_BYTE_VALID;
451 VGP_POPCC(VgpESPAdj);
452}
453
454static __inline__
455void make_aligned_doubleword_noaccess(Addr a)
456{
457 AcSecMap* sm;
458 UInt sm_off;
459
460 VGP_PUSHCC(VgpESPAdj);
461 ENSURE_MAPPABLE(a, "make_aligned_doubleword_noaccess");
sewardjb5f6f512005-03-10 23:59:00 +0000462 sm = primary_map[PM_IDX(a)];
463 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000464 sm->abits[sm_off >> 3] = VGM_BYTE_INVALID;
465 VGP_POPCC(VgpESPAdj);
466}
467
468/* The %esp update handling functions */
469ESP_UPDATE_HANDLERS ( make_aligned_word_accessible,
470 make_aligned_word_noaccess,
471 make_aligned_doubleword_accessible,
472 make_aligned_doubleword_noaccess,
473 ac_make_accessible,
474 ac_make_noaccess
475 );
476
477
njn25e49d8e72002-09-23 09:36:25 +0000478/* Block-copy permissions (needed for implementing realloc()). */
479
nethercote451eae92004-11-02 13:06:32 +0000480static void ac_copy_address_range_state ( Addr src, Addr dst, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000481{
482 UInt i;
483
njn5c004e42002-11-18 11:04:50 +0000484 DEBUG("ac_copy_address_range_state\n");
njn25e49d8e72002-09-23 09:36:25 +0000485
486 PROF_EVENT(40);
487 for (i = 0; i < len; i++) {
488 UChar abit = get_abit ( src+i );
489 PROF_EVENT(41);
490 set_abit ( dst+i, abit );
491 }
492}
493
494
495/* Check permissions for address range. If inadequate permissions
496 exist, *bad_addr is set to the offending address, so the caller can
497 know what it is. */
498
njn5c004e42002-11-18 11:04:50 +0000499static __inline__
nethercote451eae92004-11-02 13:06:32 +0000500Bool ac_check_accessible ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000501{
502 UInt i;
503 UChar abit;
njn5c004e42002-11-18 11:04:50 +0000504 PROF_EVENT(48);
njn25e49d8e72002-09-23 09:36:25 +0000505 for (i = 0; i < len; i++) {
njn5c004e42002-11-18 11:04:50 +0000506 PROF_EVENT(49);
njn25e49d8e72002-09-23 09:36:25 +0000507 abit = get_abit(a);
508 if (abit == VGM_BIT_INVALID) {
509 if (bad_addr != NULL) *bad_addr = a;
510 return False;
511 }
512 a++;
513 }
514 return True;
515}
516
sewardjecf8e102003-07-12 12:11:39 +0000517/* The opposite; check that an address range is inaccessible. */
518static
nethercote451eae92004-11-02 13:06:32 +0000519Bool ac_check_noaccess ( Addr a, SizeT len, Addr* bad_addr )
sewardjecf8e102003-07-12 12:11:39 +0000520{
521 UInt i;
522 UChar abit;
523 PROF_EVENT(48);
524 for (i = 0; i < len; i++) {
525 PROF_EVENT(49);
526 abit = get_abit(a);
527 if (abit == VGM_BIT_VALID) {
528 if (bad_addr != NULL) *bad_addr = a;
529 return False;
530 }
531 a++;
532 }
533 return True;
534}
535
njn25e49d8e72002-09-23 09:36:25 +0000536/* Check a zero-terminated ascii string. Tricky -- don't want to
537 examine the actual bytes, to find the end, until we're sure it is
538 safe to do so. */
539
njn5c004e42002-11-18 11:04:50 +0000540static __inline__
541Bool ac_check_readable_asciiz ( Addr a, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000542{
543 UChar abit;
544 PROF_EVENT(46);
njn5c004e42002-11-18 11:04:50 +0000545 DEBUG("ac_check_readable_asciiz\n");
njn25e49d8e72002-09-23 09:36:25 +0000546 while (True) {
547 PROF_EVENT(47);
548 abit = get_abit(a);
549 if (abit != VGM_BIT_VALID) {
550 if (bad_addr != NULL) *bad_addr = a;
551 return False;
552 }
553 /* Ok, a is safe to read. */
554 if (* ((UChar*)a) == 0) return True;
555 a++;
556 }
557}
558
559
560/*------------------------------------------------------------*/
561/*--- Memory event handlers ---*/
562/*------------------------------------------------------------*/
563
njn5c004e42002-11-18 11:04:50 +0000564static __inline__
njn72718642003-07-24 08:45:32 +0000565void ac_check_is_accessible ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000566 Char* s, Addr base, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000567{
568 Bool ok;
njn86f12dc2005-03-14 01:16:05 +0000569 Addr bad_addr = 0; // Initialise to shut gcc up
njn25e49d8e72002-09-23 09:36:25 +0000570
571 VGP_PUSHCC(VgpCheckMem);
572
njn5c004e42002-11-18 11:04:50 +0000573 ok = ac_check_accessible ( base, size, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000574 if (!ok) {
575 switch (part) {
576 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +0000577 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
578 /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000579 break;
580
njn25e49d8e72002-09-23 09:36:25 +0000581 case Vg_CoreSignal:
njnca82cc02004-11-22 17:18:48 +0000582 tl_assert(isWrite); /* Should only happen with isWrite case */
njn5c004e42002-11-18 11:04:50 +0000583 /* fall through */
njn25e49d8e72002-09-23 09:36:25 +0000584 case Vg_CorePThread:
nethercote8b76fe52004-11-08 19:20:09 +0000585 MAC_(record_core_mem_error)( tid, /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000586 break;
587
588 /* If we're being asked to jump to a silly address, record an error
589 message before potentially crashing the entire system. */
590 case Vg_CoreTranslate:
njnca82cc02004-11-22 17:18:48 +0000591 tl_assert(!isWrite); /* Should only happen with !isWrite case */
njn72718642003-07-24 08:45:32 +0000592 MAC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000593 break;
594
595 default:
njn67993252004-11-22 18:02:32 +0000596 VG_(tool_panic)("ac_check_is_accessible: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +0000597 }
598 }
njn5c004e42002-11-18 11:04:50 +0000599
njn25e49d8e72002-09-23 09:36:25 +0000600 VGP_POPCC(VgpCheckMem);
601}
602
603static
njn72718642003-07-24 08:45:32 +0000604void ac_check_is_writable ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000605 Char* s, Addr base, SizeT size )
njn5c004e42002-11-18 11:04:50 +0000606{
njn72718642003-07-24 08:45:32 +0000607 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/True );
njn5c004e42002-11-18 11:04:50 +0000608}
609
610static
njn72718642003-07-24 08:45:32 +0000611void ac_check_is_readable ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000612 Char* s, Addr base, SizeT size )
njn5c004e42002-11-18 11:04:50 +0000613{
njn72718642003-07-24 08:45:32 +0000614 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/False );
njn5c004e42002-11-18 11:04:50 +0000615}
616
617static
njn72718642003-07-24 08:45:32 +0000618void ac_check_is_readable_asciiz ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000619 Char* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +0000620{
621 Bool ok = True;
njn86f12dc2005-03-14 01:16:05 +0000622 Addr bad_addr = 0; // Initialise to shut gcc up
njn25e49d8e72002-09-23 09:36:25 +0000623
624 VGP_PUSHCC(VgpCheckMem);
625
njnca82cc02004-11-22 17:18:48 +0000626 tl_assert(part == Vg_CoreSysCall);
njn5c004e42002-11-18 11:04:50 +0000627 ok = ac_check_readable_asciiz ( (Addr)str, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000628 if (!ok) {
nethercote8b76fe52004-11-08 19:20:09 +0000629 MAC_(record_param_error) ( tid, bad_addr, /*IsReg*/False,
630 /*IsUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000631 }
632
633 VGP_POPCC(VgpCheckMem);
634}
635
636static
nethercote451eae92004-11-02 13:06:32 +0000637void ac_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +0000638{
njn1f3a9092002-10-04 09:22:30 +0000639 /* Ignore the permissions, just make it readable. Seems to work... */
njn25e49d8e72002-09-23 09:36:25 +0000640 DEBUG("new_mem_startup(%p, %u, rr=%u, ww=%u, xx=%u)\n", a,len,rr,ww,xx);
njn5c004e42002-11-18 11:04:50 +0000641 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000642}
643
644static
nethercote451eae92004-11-02 13:06:32 +0000645void ac_new_mem_heap ( Addr a, SizeT len, Bool is_inited )
njn25e49d8e72002-09-23 09:36:25 +0000646{
njn5c004e42002-11-18 11:04:50 +0000647 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000648}
649
650static
sewardjb5f6f512005-03-10 23:59:00 +0000651void ac_new_mem_mmap (Addr a, SizeT len, Bool rr, Bool ww, Bool xx)
njn25e49d8e72002-09-23 09:36:25 +0000652{
njn5c004e42002-11-18 11:04:50 +0000653 DEBUG("ac_set_perms(%p, %u, rr=%u ww=%u, xx=%u)\n",
sewardj40f8ebe2002-10-23 21:46:13 +0000654 a, len, rr, ww, xx);
sewardjb5f6f512005-03-10 23:59:00 +0000655 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000656}
657
njncf45fd42004-11-24 16:30:22 +0000658static
659void ac_post_mem_write(CorePart part, ThreadId tid, Addr a, SizeT len)
660{
661 ac_make_accessible(a, len);
662}
663
njn25e49d8e72002-09-23 09:36:25 +0000664
665/*------------------------------------------------------------*/
666/*--- Functions called directly from generated code. ---*/
667/*------------------------------------------------------------*/
668
669static __inline__ UInt rotateRight16 ( UInt x )
670{
671 /* Amazingly, gcc turns this into a single rotate insn. */
672 return (x >> 16) | (x << 16);
673}
674
njn25e49d8e72002-09-23 09:36:25 +0000675static __inline__ UInt shiftRight16 ( UInt x )
676{
677 return x >> 16;
678}
679
680
681/* Read/write 1/2/4 sized V bytes, and emit an address error if
682 needed. */
683
njn5c004e42002-11-18 11:04:50 +0000684/* ac_helperc_ACCESS{1,2,4} handle the common case fast.
njn25e49d8e72002-09-23 09:36:25 +0000685 Under all other circumstances, it defers to the relevant _SLOWLY
686 function, which can handle all situations.
687*/
njnc2699f62003-09-05 23:29:33 +0000688static __inline__ void ac_helperc_ACCESS4 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000689{
690# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000691 return ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000692# else
693 UInt sec_no = rotateRight16(a) & 0x3FFFF;
njnda2e36d2003-09-30 13:33:24 +0000694 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000695 UInt a_off = (SM_OFF(a)) >> 3;
njn25e49d8e72002-09-23 09:36:25 +0000696 UChar abits = sm->abits[a_off];
697 abits >>= (a & 4);
698 abits &= 15;
njn5c004e42002-11-18 11:04:50 +0000699 PROF_EVENT(66);
njn25e49d8e72002-09-23 09:36:25 +0000700 if (abits == VGM_NIBBLE_VALID) {
701 /* Handle common case quickly: a is suitably aligned, is mapped,
702 and is addressible. So just return. */
703 return;
704 } else {
705 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000706 ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000707 }
708# endif
709}
710
njnc2699f62003-09-05 23:29:33 +0000711static __inline__ void ac_helperc_ACCESS2 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000712{
713# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000714 return ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000715# else
716 UInt sec_no = rotateRight16(a) & 0x1FFFF;
717 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000718 UInt a_off = (SM_OFF(a)) >> 3;
njn5c004e42002-11-18 11:04:50 +0000719 PROF_EVENT(67);
njn25e49d8e72002-09-23 09:36:25 +0000720 if (sm->abits[a_off] == VGM_BYTE_VALID) {
721 /* Handle common case quickly. */
722 return;
723 } else {
724 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000725 ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000726 }
727# endif
728}
729
njnc2699f62003-09-05 23:29:33 +0000730static __inline__ void ac_helperc_ACCESS1 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000731{
732# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000733 return ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000734# else
735 UInt sec_no = shiftRight16(a);
736 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000737 UInt a_off = (SM_OFF(a)) >> 3;
njn5c004e42002-11-18 11:04:50 +0000738 PROF_EVENT(68);
njn25e49d8e72002-09-23 09:36:25 +0000739 if (sm->abits[a_off] == VGM_BYTE_VALID) {
740 /* Handle common case quickly. */
741 return;
742 } else {
743 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000744 ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000745 }
746# endif
747}
748
njn9fb73db2005-03-27 01:55:21 +0000749VGA_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000750static void ach_LOAD4 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000751{
752 ac_helperc_ACCESS4 ( a, /*isWrite*/False );
753}
njn9fb73db2005-03-27 01:55:21 +0000754VGA_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000755static void ach_STORE4 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000756{
757 ac_helperc_ACCESS4 ( a, /*isWrite*/True );
758}
759
njn9fb73db2005-03-27 01:55:21 +0000760VGA_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000761static void ach_LOAD2 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000762{
763 ac_helperc_ACCESS2 ( a, /*isWrite*/False );
764}
njn9fb73db2005-03-27 01:55:21 +0000765VGA_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000766static void ach_STORE2 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000767{
768 ac_helperc_ACCESS2 ( a, /*isWrite*/True );
769}
770
njn9fb73db2005-03-27 01:55:21 +0000771VGA_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000772static void ach_LOAD1 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000773{
774 ac_helperc_ACCESS1 ( a, /*isWrite*/False );
775}
njn9fb73db2005-03-27 01:55:21 +0000776VGA_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000777static void ach_STORE1 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000778{
779 ac_helperc_ACCESS1 ( a, /*isWrite*/True );
780}
781
njn25e49d8e72002-09-23 09:36:25 +0000782
783/*------------------------------------------------------------*/
784/*--- Fallback functions to handle cases that the above ---*/
njnc2699f62003-09-05 23:29:33 +0000785/*--- ac_helperc_ACCESS{1,2,4} can't manage. ---*/
njn25e49d8e72002-09-23 09:36:25 +0000786/*------------------------------------------------------------*/
787
njnc2699f62003-09-05 23:29:33 +0000788static void ac_ACCESS4_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000789{
790 Bool a0ok, a1ok, a2ok, a3ok;
791
njn5c004e42002-11-18 11:04:50 +0000792 PROF_EVENT(76);
njn25e49d8e72002-09-23 09:36:25 +0000793
794 /* First establish independently the addressibility of the 4 bytes
795 involved. */
796 a0ok = get_abit(a+0) == VGM_BIT_VALID;
797 a1ok = get_abit(a+1) == VGM_BIT_VALID;
798 a2ok = get_abit(a+2) == VGM_BIT_VALID;
799 a3ok = get_abit(a+3) == VGM_BIT_VALID;
800
801 /* Now distinguish 3 cases */
802
803 /* Case 1: the address is completely valid, so:
804 - no addressing error
805 */
806 if (a0ok && a1ok && a2ok && a3ok) {
807 return;
808 }
809
810 /* Case 2: the address is completely invalid.
811 - emit addressing error
812 */
813 /* VG_(printf)("%p (%d %d %d %d)\n", a, a0ok, a1ok, a2ok, a3ok); */
njn43c799e2003-04-08 00:08:52 +0000814 if (!MAC_(clo_partial_loads_ok)
njn25e49d8e72002-09-23 09:36:25 +0000815 || ((a & 3) != 0)
816 || (!a0ok && !a1ok && !a2ok && !a3ok)) {
sewardj76754cf2005-03-14 00:14:04 +0000817 MAC_(record_address_error)( VG_(get_running_tid)(), a, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000818 return;
819 }
820
821 /* Case 3: the address is partially valid.
822 - no addressing error
njn43c799e2003-04-08 00:08:52 +0000823 Case 3 is only allowed if MAC_(clo_partial_loads_ok) is True
njn25e49d8e72002-09-23 09:36:25 +0000824 (which is the default), and the address is 4-aligned.
825 If not, Case 2 will have applied.
826 */
njnca82cc02004-11-22 17:18:48 +0000827 tl_assert(MAC_(clo_partial_loads_ok));
njn25e49d8e72002-09-23 09:36:25 +0000828 {
829 return;
830 }
831}
832
njnc2699f62003-09-05 23:29:33 +0000833static void ac_ACCESS2_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000834{
835 /* Check the address for validity. */
836 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000837 PROF_EVENT(77);
njn25e49d8e72002-09-23 09:36:25 +0000838
839 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
840 if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
841
842 /* If an address error has happened, report it. */
843 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000844 MAC_(record_address_error)( VG_(get_running_tid)(), a, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000845 }
846}
847
njnc2699f62003-09-05 23:29:33 +0000848static void ac_ACCESS1_SLOWLY ( Addr a, Bool isWrite)
njn25e49d8e72002-09-23 09:36:25 +0000849{
850 /* Check the address for validity. */
851 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000852 PROF_EVENT(78);
njn25e49d8e72002-09-23 09:36:25 +0000853
854 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
855
856 /* If an address error has happened, report it. */
857 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000858 MAC_(record_address_error)( VG_(get_running_tid)(), a, 1, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000859 }
860}
861
862
863/* ---------------------------------------------------------------------
864 FPU load and store checks, called from generated code.
865 ------------------------------------------------------------------ */
866
sewardj56867352003-10-12 10:27:06 +0000867static
nethercote928a5f72004-11-03 18:10:37 +0000868void ac_fpu_ACCESS_check ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000869{
870 /* Ensure the read area is both addressible and valid (ie,
871 readable). If there's an address error, don't report a value
872 error too; but if there isn't an address error, check for a
873 value error.
874
875 Try to be reasonably fast on the common case; wimp out and defer
njn5c004e42002-11-18 11:04:50 +0000876 to ac_fpu_ACCESS_check_SLOWLY for everything else. */
njn25e49d8e72002-09-23 09:36:25 +0000877
878 AcSecMap* sm;
879 UInt sm_off, a_off;
880 Addr addr4;
881
njn5c004e42002-11-18 11:04:50 +0000882 PROF_EVENT(90);
njn25e49d8e72002-09-23 09:36:25 +0000883
884# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000885 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000886# else
887
888 if (size == 4) {
njnbe91aae2005-03-27 01:42:41 +0000889 if (!VG_IS_4_ALIGNED(addr)) goto slow4;
njn5c004e42002-11-18 11:04:50 +0000890 PROF_EVENT(91);
njn25e49d8e72002-09-23 09:36:25 +0000891 /* Properly aligned. */
sewardjb5f6f512005-03-10 23:59:00 +0000892 sm = primary_map[PM_IDX(addr)];
893 sm_off = SM_OFF(addr);
njn25e49d8e72002-09-23 09:36:25 +0000894 a_off = sm_off >> 3;
895 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow4;
896 /* Properly aligned and addressible. */
897 return;
898 slow4:
njnc2699f62003-09-05 23:29:33 +0000899 ac_fpu_ACCESS_check_SLOWLY ( addr, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000900 return;
901 }
902
903 if (size == 8) {
njnbe91aae2005-03-27 01:42:41 +0000904 if (!VG_IS_4_ALIGNED(addr)) goto slow8;
njn5c004e42002-11-18 11:04:50 +0000905 PROF_EVENT(92);
njn25e49d8e72002-09-23 09:36:25 +0000906 /* Properly aligned. Do it in two halves. */
907 addr4 = addr + 4;
908 /* First half. */
sewardjb5f6f512005-03-10 23:59:00 +0000909 sm = primary_map[PM_IDX(addr)];
910 sm_off = SM_OFF(addr);
njn25e49d8e72002-09-23 09:36:25 +0000911 a_off = sm_off >> 3;
912 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
913 /* First half properly aligned and addressible. */
914 /* Second half. */
sewardjb5f6f512005-03-10 23:59:00 +0000915 sm = primary_map[PM_IDX(addr4)];
916 sm_off = SM_OFF(addr4);
njn25e49d8e72002-09-23 09:36:25 +0000917 a_off = sm_off >> 3;
918 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
919 /* Second half properly aligned and addressible. */
920 /* Both halves properly aligned and addressible. */
921 return;
922 slow8:
njnc2699f62003-09-05 23:29:33 +0000923 ac_fpu_ACCESS_check_SLOWLY ( addr, 8, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000924 return;
925 }
926
927 /* Can't be bothered to huff'n'puff to make these (allegedly) rare
928 cases go quickly. */
929 if (size == 2) {
njn5c004e42002-11-18 11:04:50 +0000930 PROF_EVENT(93);
njnc2699f62003-09-05 23:29:33 +0000931 ac_fpu_ACCESS_check_SLOWLY ( addr, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000932 return;
933 }
934
jsewardfca60182004-01-04 23:30:55 +0000935 if (size == 16 || size == 10 || size == 28 || size == 108 || size == 512) {
njn5c004e42002-11-18 11:04:50 +0000936 PROF_EVENT(94);
njnc2699f62003-09-05 23:29:33 +0000937 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000938 return;
939 }
940
941 VG_(printf)("size is %d\n", size);
njn67993252004-11-22 18:02:32 +0000942 VG_(tool_panic)("fpu_ACCESS_check: unhandled size");
njn25e49d8e72002-09-23 09:36:25 +0000943# endif
944}
945
njn9fb73db2005-03-27 01:55:21 +0000946VGA_REGPARM(2)
sewardj9f649aa2004-11-22 20:38:40 +0000947static void ach_LOADN ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000948{
949 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/False );
950}
951
njn9fb73db2005-03-27 01:55:21 +0000952VGA_REGPARM(2)
sewardj9f649aa2004-11-22 20:38:40 +0000953static void ach_STOREN ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000954{
955 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/True );
956}
njn25e49d8e72002-09-23 09:36:25 +0000957
sewardjd62e03b2004-12-10 12:01:14 +0000958
njn25e49d8e72002-09-23 09:36:25 +0000959/* ---------------------------------------------------------------------
960 Slow, general cases for FPU access checks.
961 ------------------------------------------------------------------ */
962
nethercote928a5f72004-11-03 18:10:37 +0000963void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000964{
965 Int i;
966 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000967 PROF_EVENT(100);
njn25e49d8e72002-09-23 09:36:25 +0000968 for (i = 0; i < size; i++) {
njn5c004e42002-11-18 11:04:50 +0000969 PROF_EVENT(101);
njn25e49d8e72002-09-23 09:36:25 +0000970 if (get_abit(addr+i) != VGM_BIT_VALID)
971 aerr = True;
972 }
973
974 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000975 MAC_(record_address_error)( VG_(get_running_tid)(), addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000976 }
977}
978
979
980/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000981/*--- Our instrumenter ---*/
982/*------------------------------------------------------------*/
983
njn51d827b2005-05-09 01:02:08 +0000984static IRBB* ac_instrument(IRBB* bb_in, VexGuestLayout* layout,
985 IRType gWordTy, IRType hWordTy )
njn25e49d8e72002-09-23 09:36:25 +0000986{
sewardj9f649aa2004-11-22 20:38:40 +0000987 Int i, hsz;
988 IRStmt* st;
989 IRExpr* data;
990 IRExpr* aexpr;
991 IRExpr* guard;
992 IRDirty* di;
993 Bool isLoad;
sewardjd54babf2005-03-21 00:55:49 +0000994 IRBB* bb;
995
996 if (gWordTy != hWordTy) {
997 /* We don't currently support this case. */
998 VG_(tool_panic)("host/guest word size mismatch");
999 }
njn25e49d8e72002-09-23 09:36:25 +00001000
sewardj9f649aa2004-11-22 20:38:40 +00001001 /* Set up BB */
sewardjd54babf2005-03-21 00:55:49 +00001002 bb = emptyIRBB();
sewardj9f649aa2004-11-22 20:38:40 +00001003 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
1004 bb->next = dopyIRExpr(bb_in->next);
1005 bb->jumpkind = bb_in->jumpkind;
njn25e49d8e72002-09-23 09:36:25 +00001006
sewardj9f649aa2004-11-22 20:38:40 +00001007 /* No loads to consider in ->next. */
sewardj710d6c22005-03-20 18:55:15 +00001008 tl_assert(isIRAtom(bb_in->next));
njn25e49d8e72002-09-23 09:36:25 +00001009
sewardj9f649aa2004-11-22 20:38:40 +00001010 for (i = 0; i < bb_in->stmts_used; i++) {
1011 st = bb_in->stmts[i];
sewardj21dc3452005-03-21 00:27:41 +00001012 tl_assert(st);
njn25e49d8e72002-09-23 09:36:25 +00001013
sewardj9f649aa2004-11-22 20:38:40 +00001014 /* Examine each stmt in turn to figure out if it needs to be
1015 preceded by a memory access check. If so, collect up the
1016 relevant pieces of information. */
1017 hsz = 0;
1018 aexpr = NULL;
1019 guard = NULL;
1020 isLoad = True;
njn25e49d8e72002-09-23 09:36:25 +00001021
sewardj9f649aa2004-11-22 20:38:40 +00001022 switch (st->tag) {
1023
1024 case Ist_Tmp:
1025 data = st->Ist.Tmp.data;
1026 if (data->tag == Iex_LDle) {
1027 aexpr = data->Iex.LDle.addr;
1028 hsz = sizeofIRType(data->Iex.LDle.ty);
1029 isLoad = True;
1030 }
1031 break;
1032
1033 case Ist_STle:
1034 data = st->Ist.STle.data;
1035 aexpr = st->Ist.STle.addr;
sewardj710d6c22005-03-20 18:55:15 +00001036 tl_assert(isIRAtom(data));
1037 tl_assert(isIRAtom(aexpr));
sewardj9f649aa2004-11-22 20:38:40 +00001038 hsz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
1039 isLoad = False;
sewardj08ccc5c2005-03-17 03:17:54 +00001040 break;
sewardj9f649aa2004-11-22 20:38:40 +00001041
1042 case Ist_Put:
sewardj710d6c22005-03-20 18:55:15 +00001043 tl_assert(isIRAtom(st->Ist.Put.data));
njn25e49d8e72002-09-23 09:36:25 +00001044 break;
1045
sewardj9f649aa2004-11-22 20:38:40 +00001046 case Ist_PutI:
sewardj710d6c22005-03-20 18:55:15 +00001047 tl_assert(isIRAtom(st->Ist.PutI.ix));
1048 tl_assert(isIRAtom(st->Ist.PutI.data));
njnc2699f62003-09-05 23:29:33 +00001049 break;
1050
sewardj9f649aa2004-11-22 20:38:40 +00001051 case Ist_Exit:
sewardj710d6c22005-03-20 18:55:15 +00001052 tl_assert(isIRAtom(st->Ist.Exit.guard));
njn25e49d8e72002-09-23 09:36:25 +00001053 break;
1054
sewardj9f649aa2004-11-22 20:38:40 +00001055 case Ist_Dirty:
1056 if (st->Ist.Dirty.details->mFx != Ifx_None) {
1057 /* We classify Ifx_Modify as a load. */
1058 isLoad = st->Ist.Dirty.details->mFx != Ifx_Write;
1059 hsz = st->Ist.Dirty.details->mSize;
1060 aexpr = st->Ist.Dirty.details->mAddr;
1061 guard = st->Ist.Dirty.details->guard;
sewardj710d6c22005-03-20 18:55:15 +00001062 tl_assert(isIRAtom(aexpr));
sewardj9f649aa2004-11-22 20:38:40 +00001063 }
1064 break;
sewardje3891fa2003-06-15 03:13:48 +00001065
sewardj21dc3452005-03-21 00:27:41 +00001066 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00001067 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00001068 case Ist_MFence:
1069 break;
1070
njn25e49d8e72002-09-23 09:36:25 +00001071 default:
sewardj9f649aa2004-11-22 20:38:40 +00001072 VG_(printf)("\n");
1073 ppIRStmt(st);
1074 VG_(printf)("\n");
1075 VG_(tool_panic)("addrcheck: unhandled IRStmt");
njn25e49d8e72002-09-23 09:36:25 +00001076 }
sewardj9f649aa2004-11-22 20:38:40 +00001077
1078 /* If needed, add a helper call. */
1079 if (aexpr) {
1080 tl_assert(hsz > 0);
1081 switch (hsz) {
1082 case 4:
1083 if (isLoad)
1084 di = unsafeIRDirty_0_N( 1, "ach_LOAD4", &ach_LOAD4,
1085 mkIRExprVec_1(aexpr));
1086 else
1087 di = unsafeIRDirty_0_N( 1, "ach_STORE4", &ach_STORE4,
1088 mkIRExprVec_1(aexpr));
1089 break;
1090 case 2:
1091 if (isLoad)
1092 di = unsafeIRDirty_0_N( 1, "ach_LOAD2", &ach_LOAD2,
1093 mkIRExprVec_1(aexpr));
1094 else
1095 di = unsafeIRDirty_0_N( 1, "ach_STORE2", &ach_STORE2,
1096 mkIRExprVec_1(aexpr));
1097 break;
1098 case 1:
1099 if (isLoad)
1100 di = unsafeIRDirty_0_N( 1, "ach_LOAD1", &ach_LOAD1,
1101 mkIRExprVec_1(aexpr));
1102 else
1103 di = unsafeIRDirty_0_N( 1, "ach_STORE1", &ach_STORE1,
1104 mkIRExprVec_1(aexpr));
1105 break;
1106 default:
1107 if (isLoad)
1108 di = unsafeIRDirty_0_N(
1109 2, "ach_LOADN", &ach_LOADN,
1110 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1111 else
1112 di = unsafeIRDirty_0_N(
1113 2, "ach_STOREN", &ach_STOREN,
1114 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1115 break;
1116 }
1117
1118 /* If the call has arisen as a result of a dirty helper which
1119 references memory, we need to inherit the guard from the
1120 dirty helper. */
1121 if (guard)
1122 di->guard = dopyIRExpr(guard);
1123
1124 /* emit the helper call */
1125 addStmtToIRBB( bb, IRStmt_Dirty(di) );
1126
1127 }
1128
1129 /* And finally, copy the expr itself to the output. */
sewardjbd598e12005-01-07 12:10:21 +00001130 addStmtToIRBB( bb, st );
njn25e49d8e72002-09-23 09:36:25 +00001131 }
1132
sewardj9f649aa2004-11-22 20:38:40 +00001133 return bb;
njn25e49d8e72002-09-23 09:36:25 +00001134}
1135
1136
njn25e49d8e72002-09-23 09:36:25 +00001137/*------------------------------------------------------------*/
1138/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
1139/*------------------------------------------------------------*/
1140
sewardja4495682002-10-21 07:29:59 +00001141/* For the memory leak detector, say whether an entire 64k chunk of
1142 address space is possibly in use, or not. If in doubt return
1143 True.
njn25e49d8e72002-09-23 09:36:25 +00001144*/
sewardja4495682002-10-21 07:29:59 +00001145static
1146Bool ac_is_valid_64k_chunk ( UInt chunk_number )
njn25e49d8e72002-09-23 09:36:25 +00001147{
sewardjb5f6f512005-03-10 23:59:00 +00001148 tl_assert(chunk_number >= 0 && chunk_number < PRIMARY_SIZE);
1149 if (primary_map[chunk_number] == DSM_NOTADDR) {
sewardja4495682002-10-21 07:29:59 +00001150 /* Definitely not in use. */
1151 return False;
1152 } else {
1153 return True;
njn25e49d8e72002-09-23 09:36:25 +00001154 }
1155}
1156
1157
sewardja4495682002-10-21 07:29:59 +00001158/* For the memory leak detector, say whether or not a given word
1159 address is to be regarded as valid. */
1160static
1161Bool ac_is_valid_address ( Addr a )
1162{
1163 UChar abits;
njnbe91aae2005-03-27 01:42:41 +00001164 tl_assert(VG_IS_4_ALIGNED(a));
sewardja4495682002-10-21 07:29:59 +00001165 abits = get_abits4_ALIGNED(a);
1166 if (abits == VGM_NIBBLE_VALID) {
1167 return True;
1168 } else {
1169 return False;
1170 }
1171}
1172
1173
nethercote996901a2004-08-03 13:29:09 +00001174/* Leak detector for this tool. We don't actually do anything, merely
sewardja4495682002-10-21 07:29:59 +00001175 run the generic leak detector with suitable parameters for this
nethercote996901a2004-08-03 13:29:09 +00001176 tool. */
njnb8dca862005-03-14 02:42:44 +00001177static void ac_detect_memory_leaks ( ThreadId tid, LeakCheckMode mode )
njn25e49d8e72002-09-23 09:36:25 +00001178{
njnb8dca862005-03-14 02:42:44 +00001179 MAC_(do_detect_memory_leaks) ( tid, mode, ac_is_valid_64k_chunk, ac_is_valid_address );
njn25e49d8e72002-09-23 09:36:25 +00001180}
1181
1182
1183/* ---------------------------------------------------------------------
1184 Sanity check machinery (permanently engaged).
1185 ------------------------------------------------------------------ */
1186
njn51d827b2005-05-09 01:02:08 +00001187static Bool ac_cheap_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00001188{
jseward9800fd32004-01-04 23:08:04 +00001189 /* nothing useful we can rapidly check */
1190 return True;
njn25e49d8e72002-09-23 09:36:25 +00001191}
1192
njn51d827b2005-05-09 01:02:08 +00001193static Bool ac_expensive_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00001194{
1195 Int i;
1196
sewardjb5f6f512005-03-10 23:59:00 +00001197#if 0
njn25e49d8e72002-09-23 09:36:25 +00001198 /* Make sure nobody changed the distinguished secondary. */
1199 for (i = 0; i < 8192; i++)
1200 if (distinguished_secondary_map.abits[i] != VGM_BYTE_INVALID)
1201 return False;
sewardjb5f6f512005-03-10 23:59:00 +00001202#endif
njn25e49d8e72002-09-23 09:36:25 +00001203
1204 /* Make sure that the upper 3/4 of the primary map hasn't
1205 been messed with. */
sewardjb5f6f512005-03-10 23:59:00 +00001206 for (i = PRIMARY_SIZE; i < PRIMARY_SIZE*4; i++)
1207 if (primary_map[i] != DSM_NOTADDR)
njn25e49d8e72002-09-23 09:36:25 +00001208 return False;
1209
1210 return True;
1211}
1212
njn47363ab2003-04-21 13:24:40 +00001213/*------------------------------------------------------------*/
1214/*--- Client requests ---*/
1215/*------------------------------------------------------------*/
1216
njn51d827b2005-05-09 01:02:08 +00001217static Bool ac_handle_client_request ( ThreadId tid, UWord* arg, UWord *ret )
sewardjd8033d92002-12-08 22:16:58 +00001218{
sewardjbf310d92002-12-28 13:09:57 +00001219#define IGNORE(what) \
1220 do { \
1221 if (moans-- > 0) { \
1222 VG_(message)(Vg_UserMsg, \
njn02bc4b82005-05-15 17:28:26 +00001223 "Warning: Addrcheck: ignoring '%s' request.", what); \
sewardjbf310d92002-12-28 13:09:57 +00001224 VG_(message)(Vg_UserMsg, \
nethercote137bc552003-11-14 17:47:54 +00001225 " To honour this request, rerun with --tool=memcheck."); \
sewardjbf310d92002-12-28 13:09:57 +00001226 } \
1227 } while (0)
1228
sewardjbf310d92002-12-28 13:09:57 +00001229 static Int moans = 3;
sewardjd8033d92002-12-08 22:16:58 +00001230
1231 /* Overload memcheck client reqs */
njnfc26ff92004-11-22 19:12:49 +00001232 if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
sewardjd62e03b2004-12-10 12:01:14 +00001233 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
1234 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
1235 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
1236 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
1237 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
1238 && VG_USERREQ__MEMPOOL_FREE != arg[0])
sewardjd8033d92002-12-08 22:16:58 +00001239 return False;
1240
1241 switch (arg[0]) {
1242 case VG_USERREQ__DO_LEAK_CHECK:
njnb8dca862005-03-14 02:42:44 +00001243 ac_detect_memory_leaks(tid, arg[1] ? LC_Summary : LC_Full);
sewardjd8033d92002-12-08 22:16:58 +00001244 *ret = 0; /* return value is meaningless */
1245 break;
1246
sewardjbf310d92002-12-28 13:09:57 +00001247 /* Ignore these */
sewardjd8033d92002-12-08 22:16:58 +00001248 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
sewardjbf310d92002-12-28 13:09:57 +00001249 IGNORE("VALGRIND_CHECK_WRITABLE");
1250 return False;
sewardjd8033d92002-12-08 22:16:58 +00001251 case VG_USERREQ__CHECK_READABLE: /* check readable */
sewardjbf310d92002-12-28 13:09:57 +00001252 IGNORE("VALGRIND_CHECK_READABLE");
1253 return False;
sewardjd8033d92002-12-08 22:16:58 +00001254 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
sewardjbf310d92002-12-28 13:09:57 +00001255 IGNORE("VALGRIND_MAKE_NOACCESS");
1256 return False;
sewardjd8033d92002-12-08 22:16:58 +00001257 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
sewardjbf310d92002-12-28 13:09:57 +00001258 IGNORE("VALGRIND_MAKE_WRITABLE");
1259 return False;
sewardjd8033d92002-12-08 22:16:58 +00001260 case VG_USERREQ__MAKE_READABLE: /* make readable */
sewardjbf310d92002-12-28 13:09:57 +00001261 IGNORE("VALGRIND_MAKE_READABLE");
1262 return False;
sewardjd8033d92002-12-08 22:16:58 +00001263 case VG_USERREQ__DISCARD: /* discard */
sewardjbf310d92002-12-28 13:09:57 +00001264 IGNORE("VALGRIND_CHECK_DISCARD");
1265 return False;
sewardjd8033d92002-12-08 22:16:58 +00001266
1267 default:
nethercoted1b64b22004-11-04 18:22:28 +00001268 if (MAC_(handle_common_client_requests)(tid, arg, ret )) {
njn47363ab2003-04-21 13:24:40 +00001269 return True;
1270 } else {
1271 VG_(message)(Vg_UserMsg,
nethercoted1b64b22004-11-04 18:22:28 +00001272 "Warning: unknown addrcheck client request code %llx",
1273 (ULong)arg[0]);
njn47363ab2003-04-21 13:24:40 +00001274 return False;
1275 }
sewardjd8033d92002-12-08 22:16:58 +00001276 }
1277 return True;
sewardjbf310d92002-12-28 13:09:57 +00001278
1279#undef IGNORE
sewardjd8033d92002-12-08 22:16:58 +00001280}
1281
njn25e49d8e72002-09-23 09:36:25 +00001282/*------------------------------------------------------------*/
1283/*--- Setup ---*/
1284/*------------------------------------------------------------*/
1285
njn51d827b2005-05-09 01:02:08 +00001286static Bool ac_process_cmd_line_option(Char* arg)
njn25e49d8e72002-09-23 09:36:25 +00001287{
njn43c799e2003-04-08 00:08:52 +00001288 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001289}
1290
njn51d827b2005-05-09 01:02:08 +00001291static void ac_print_usage(void)
njn25e49d8e72002-09-23 09:36:25 +00001292{
njn3e884182003-04-15 13:03:23 +00001293 MAC_(print_common_usage)();
1294}
1295
njn51d827b2005-05-09 01:02:08 +00001296static void ac_print_debug_usage(void)
njn3e884182003-04-15 13:03:23 +00001297{
1298 MAC_(print_common_debug_usage)();
njn25e49d8e72002-09-23 09:36:25 +00001299}
1300
1301
1302/*------------------------------------------------------------*/
njn51d827b2005-05-09 01:02:08 +00001303/*--- Setup and finalisation ---*/
njn25e49d8e72002-09-23 09:36:25 +00001304/*------------------------------------------------------------*/
1305
njn51d827b2005-05-09 01:02:08 +00001306static void ac_post_clo_init ( void )
1307{
1308}
1309
1310static void ac_fini ( Int exitcode )
1311{
1312 MAC_(common_fini)( ac_detect_memory_leaks );
1313}
1314
1315static void ac_pre_clo_init(void)
njn25e49d8e72002-09-23 09:36:25 +00001316{
njn810086f2002-11-14 12:42:47 +00001317 VG_(details_name) ("Addrcheck");
1318 VG_(details_version) (NULL);
1319 VG_(details_description) ("a fine-grained address checker");
1320 VG_(details_copyright_author)(
njn53612422005-03-12 16:22:54 +00001321 "Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.");
nethercote421281e2003-11-20 16:20:55 +00001322 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardj78210aa2002-12-01 02:55:46 +00001323 VG_(details_avg_translation_sizeB) ( 135 );
njn25e49d8e72002-09-23 09:36:25 +00001324
njn51d827b2005-05-09 01:02:08 +00001325 VG_(basic_tool_funcs) (ac_post_clo_init,
1326 ac_instrument,
1327 ac_fini);
njn8a97c6d2005-03-31 04:37:24 +00001328
njn810086f2002-11-14 12:42:47 +00001329 VG_(needs_core_errors) ();
njn51d827b2005-05-09 01:02:08 +00001330 VG_(needs_tool_errors) (MAC_(eq_Error),
1331 ac_pp_Error,
1332 MAC_(update_extra),
1333 MAC_(shared_recognised_suppression),
1334 MAC_(read_extra_suppression_info),
1335 MAC_(error_matches_suppression),
1336 MAC_(get_error_name),
1337 MAC_(print_extra_suppression_info));
njn810086f2002-11-14 12:42:47 +00001338 VG_(needs_libc_freeres) ();
njn51d827b2005-05-09 01:02:08 +00001339 VG_(needs_command_line_options)(MAC_(process_common_cmd_line_option),
1340 MAC_(print_common_usage),
1341 MAC_(print_common_debug_usage));
1342 VG_(needs_client_requests) (ac_handle_client_request);
1343 VG_(needs_sanity_checks) (ac_cheap_sanity_check,
1344 ac_expensive_sanity_check);
fitzhardinge98abfc72003-12-16 02:05:15 +00001345 VG_(needs_shadow_memory) ();
njn25e49d8e72002-09-23 09:36:25 +00001346
njn51d827b2005-05-09 01:02:08 +00001347 VG_(malloc_funcs) (MAC_(malloc),
1348 MAC_(__builtin_new),
1349 MAC_(__builtin_vec_new),
1350 MAC_(memalign),
1351 MAC_(calloc),
1352 MAC_(free),
1353 MAC_(__builtin_delete),
1354 MAC_(__builtin_vec_delete),
1355 MAC_(realloc),
1356 MAC_MALLOC_REDZONE_SZB );
njn8a97c6d2005-03-31 04:37:24 +00001357
njn3e884182003-04-15 13:03:23 +00001358 MAC_( new_mem_heap) = & ac_new_mem_heap;
1359 MAC_( ban_mem_heap) = & ac_make_noaccess;
1360 MAC_(copy_mem_heap) = & ac_copy_address_range_state;
1361 MAC_( die_mem_heap) = & ac_make_noaccess;
sewardjecf8e102003-07-12 12:11:39 +00001362 MAC_(check_noaccess) = & ac_check_noaccess;
njn3e884182003-04-15 13:03:23 +00001363
njn51d827b2005-05-09 01:02:08 +00001364 VG_(track_new_mem_startup) ( & ac_new_mem_startup );
1365 VG_(track_new_mem_stack_signal)( & ac_make_accessible );
1366 VG_(track_new_mem_brk) ( & ac_make_accessible );
1367 VG_(track_new_mem_mmap) ( & ac_new_mem_mmap );
njn25e49d8e72002-09-23 09:36:25 +00001368
njn51d827b2005-05-09 01:02:08 +00001369 VG_(track_copy_mem_remap) ( & ac_copy_address_range_state );
njn3e884182003-04-15 13:03:23 +00001370
njn51d827b2005-05-09 01:02:08 +00001371 VG_(track_die_mem_stack_signal)( & ac_make_noaccess );
1372 VG_(track_die_mem_brk) ( & ac_make_noaccess );
1373 VG_(track_die_mem_munmap) ( & ac_make_noaccess );
njn3e884182003-04-15 13:03:23 +00001374
njn51d827b2005-05-09 01:02:08 +00001375 VG_(track_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
1376 VG_(track_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
1377 VG_(track_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
1378 VG_(track_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
1379 VG_(track_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
1380 VG_(track_new_mem_stack) ( & MAC_(new_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001381
njn51d827b2005-05-09 01:02:08 +00001382 VG_(track_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
1383 VG_(track_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
1384 VG_(track_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
1385 VG_(track_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
1386 VG_(track_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
1387 VG_(track_die_mem_stack) ( & MAC_(die_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001388
njn51d827b2005-05-09 01:02:08 +00001389 VG_(track_ban_mem_stack) ( & ac_make_noaccess );
njn25e49d8e72002-09-23 09:36:25 +00001390
njn51d827b2005-05-09 01:02:08 +00001391 VG_(track_pre_mem_read) ( & ac_check_is_readable );
1392 VG_(track_pre_mem_read_asciiz) ( & ac_check_is_readable_asciiz );
1393 VG_(track_pre_mem_write) ( & ac_check_is_writable );
1394 VG_(track_post_mem_write) ( & ac_post_mem_write );
njn25e49d8e72002-09-23 09:36:25 +00001395
njn31066fd2005-03-26 00:42:02 +00001396 VG_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
1397 VG_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
1398 VG_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
njnd04b7c62002-10-03 14:05:52 +00001399
1400 init_shadow_memory();
njn3e884182003-04-15 13:03:23 +00001401 MAC_(common_pre_clo_init)();
njn5c004e42002-11-18 11:04:50 +00001402}
1403
njn51d827b2005-05-09 01:02:08 +00001404VG_DETERMINE_INTERFACE_VERSION(ac_pre_clo_init, 1./8)
fitzhardinge98abfc72003-12-16 02:05:15 +00001405
1406
njn25e49d8e72002-09-23 09:36:25 +00001407/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00001408/*--- end ac_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00001409/*--------------------------------------------------------------------*/