blob: 5d2f67f02c6ecf88f17855daac1e5814b0e540d4 [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
njn0da7ac62005-07-19 21:11:54 +000033#include "pub_tool_basics.h"
34#include "pub_tool_hashtable.h" // For mac_shared.h
35#include "pub_tool_libcbase.h"
36#include "pub_tool_libcassert.h"
37#include "pub_tool_libcprint.h"
38#include "pub_tool_profile.h" // For mac_shared.h
39#include "pub_tool_tooliface.h"
40#include "pub_tool_threadstate.h"
41
njn43c799e2003-04-08 00:08:52 +000042#include "mac_shared.h"
sewardjd8033d92002-12-08 22:16:58 +000043#include "memcheck.h"
njn25e49d8e72002-09-23 09:36:25 +000044
njn9b007f62003-04-07 14:40:25 +000045
njn25e49d8e72002-09-23 09:36:25 +000046/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000047/*--- Comparing and printing errors ---*/
48/*------------------------------------------------------------*/
49
njn51d827b2005-05-09 01:02:08 +000050static void ac_pp_Error ( Error* err )
njn25e49d8e72002-09-23 09:36:25 +000051{
njn43c799e2003-04-08 00:08:52 +000052 MAC_Error* err_extra = VG_(get_error_extra)(err);
njn25e49d8e72002-09-23 09:36:25 +000053
njn810086f2002-11-14 12:42:47 +000054 switch (VG_(get_error_kind)(err)) {
njn25e49d8e72002-09-23 09:36:25 +000055 case CoreMemErr:
njn43c799e2003-04-08 00:08:52 +000056 VG_(message)(Vg_UserMsg, "%s contains unaddressable byte(s)",
57 VG_(get_error_string)(err));
58 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
njn25e49d8e72002-09-23 09:36:25 +000059 break;
60
njn25e49d8e72002-09-23 09:36:25 +000061 case ParamErr:
njn43c799e2003-04-08 00:08:52 +000062 VG_(message)(Vg_UserMsg,
63 "Syscall param %s contains unaddressable byte(s)",
64 VG_(get_error_string)(err) );
65 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
66 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
njn25e49d8e72002-09-23 09:36:25 +000067 break;
68
69 case UserErr:
njn43c799e2003-04-08 00:08:52 +000070 VG_(message)(Vg_UserMsg,
71 "Unaddressable byte(s) found during client check request");
72 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
73 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
njn25e49d8e72002-09-23 09:36:25 +000074 break;
75
76 default:
njnb126f732004-11-22 17:57:07 +000077 MAC_(pp_shared_Error)(err);
njn43c799e2003-04-08 00:08:52 +000078 break;
njn25e49d8e72002-09-23 09:36:25 +000079 }
80}
81
82/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000083/*--- Suppressions ---*/
84/*------------------------------------------------------------*/
85
njn51d827b2005-05-09 01:02:08 +000086static Bool ac_recognised_suppression ( Char* name, Supp* su )
njn25e49d8e72002-09-23 09:36:25 +000087{
njn43c799e2003-04-08 00:08:52 +000088 return MAC_(shared_recognised_suppression)(name, su);
njn25e49d8e72002-09-23 09:36:25 +000089}
90
njn5c004e42002-11-18 11:04:50 +000091#define DEBUG(fmt, args...) //VG_(printf)(fmt, ## args)
92
njn25e49d8e72002-09-23 09:36:25 +000093/*------------------------------------------------------------*/
94/*--- Low-level support for memory checking. ---*/
95/*------------------------------------------------------------*/
96
97/* All reads and writes are checked against a memory map, which
98 records the state of all memory in the process. The memory map is
99 organised like this:
100
101 The top 16 bits of an address are used to index into a top-level
102 map table, containing 65536 entries. Each entry is a pointer to a
103 second-level map, which records the accesibililty and validity
104 permissions for the 65536 bytes indexed by the lower 16 bits of the
105 address. Each byte is represented by one bit, indicating
106 accessibility. So each second-level map contains 8192 bytes. This
107 two-level arrangement conveniently divides the 4G address space
108 into 64k lumps, each size 64k bytes.
109
110 All entries in the primary (top-level) map must point to a valid
111 secondary (second-level) map. Since most of the 4G of address
112 space will not be in use -- ie, not mapped at all -- there is a
njn02bc4b82005-05-15 17:28:26 +0000113 distinguished secondary map, which indicates 'not addressible and
njn25e49d8e72002-09-23 09:36:25 +0000114 not valid' writeable for all bytes. Entries in the primary map for
115 which the entire 64k is not in use at all point at this
116 distinguished map.
117
118 [...] lots of stuff deleted due to out of date-ness
119
120 As a final optimisation, the alignment and address checks for
121 4-byte loads and stores are combined in a neat way. The primary
122 map is extended to have 262144 entries (2^18), rather than 2^16.
123 The top 3/4 of these entries are permanently set to the
124 distinguished secondary map. For a 4-byte load/store, the
125 top-level map is indexed not with (addr >> 16) but instead f(addr),
126 where
127
128 f( XXXX XXXX XXXX XXXX ____ ____ ____ __YZ )
129 = ____ ____ ____ __YZ XXXX XXXX XXXX XXXX or
130 = ____ ____ ____ __ZY XXXX XXXX XXXX XXXX
131
132 ie the lowest two bits are placed above the 16 high address bits.
133 If either of these two bits are nonzero, the address is misaligned;
134 this will select a secondary map from the upper 3/4 of the primary
135 map. Because this is always the distinguished secondary map, a
136 (bogus) address check failure will result. The failure handling
137 code can then figure out whether this is a genuine addr check
138 failure or whether it is a possibly-legitimate access at a
139 misaligned address. */
140
141
142/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000143/*--- Function declarations. ---*/
144/*------------------------------------------------------------*/
145
njnc2699f62003-09-05 23:29:33 +0000146static void ac_ACCESS4_SLOWLY ( Addr a, Bool isWrite );
147static void ac_ACCESS2_SLOWLY ( Addr a, Bool isWrite );
148static void ac_ACCESS1_SLOWLY ( Addr a, Bool isWrite );
nethercote928a5f72004-11-03 18:10:37 +0000149static void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, SizeT size, Bool isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000150
151/*------------------------------------------------------------*/
152/*--- Data defns. ---*/
153/*------------------------------------------------------------*/
154
155typedef
156 struct {
sewardjb5f6f512005-03-10 23:59:00 +0000157 UChar abits[SECONDARY_SIZE / 8];
njn25e49d8e72002-09-23 09:36:25 +0000158 }
159 AcSecMap;
160
sewardjb5f6f512005-03-10 23:59:00 +0000161static AcSecMap* primary_map[ /*PRIMARY_SIZE*/ PRIMARY_SIZE*4 ];
162static const AcSecMap distinguished_secondary_maps[2] = {
163 [ VGM_BIT_INVALID ] = { { [0 ... (SECONDARY_SIZE/8) - 1] = VGM_BYTE_INVALID } },
164 [ VGM_BIT_VALID ] = { { [0 ... (SECONDARY_SIZE/8) - 1] = VGM_BYTE_VALID } },
165};
166#define N_SECONDARY_MAPS (sizeof(distinguished_secondary_maps)/sizeof(*distinguished_secondary_maps))
167
168#define DSM_IDX(a) ((a) & 1)
169
170#define DSM(a) ((AcSecMap *)&distinguished_secondary_maps[DSM_IDX(a)])
171
172#define DSM_NOTADDR DSM(VGM_BIT_INVALID)
173#define DSM_ADDR DSM(VGM_BIT_VALID)
njn25e49d8e72002-09-23 09:36:25 +0000174
njn25e49d8e72002-09-23 09:36:25 +0000175static void init_shadow_memory ( void )
176{
sewardjb5f6f512005-03-10 23:59:00 +0000177 Int i, a;
njn25e49d8e72002-09-23 09:36:25 +0000178
sewardjb5f6f512005-03-10 23:59:00 +0000179 /* check construction of the distinguished secondaries */
sewardj76754cf2005-03-14 00:14:04 +0000180 tl_assert(VGM_BIT_INVALID == 1);
181 tl_assert(VGM_BIT_VALID == 0);
sewardjb5f6f512005-03-10 23:59:00 +0000182
183 for(a = 0; a <= 1; a++)
sewardj76754cf2005-03-14 00:14:04 +0000184 tl_assert(distinguished_secondary_maps[DSM_IDX(a)].abits[0] == BIT_EXPAND(a));
njn25e49d8e72002-09-23 09:36:25 +0000185
186 /* These entries gradually get overwritten as the used address
187 space expands. */
sewardjb5f6f512005-03-10 23:59:00 +0000188 for (i = 0; i < PRIMARY_SIZE; i++)
189 primary_map[i] = DSM_NOTADDR;
njn25e49d8e72002-09-23 09:36:25 +0000190
191 /* These ones should never change; it's a bug in Valgrind if they do. */
sewardjb5f6f512005-03-10 23:59:00 +0000192 for (i = PRIMARY_SIZE; i < PRIMARY_SIZE*4; i++)
193 primary_map[i] = DSM_NOTADDR;
njn25e49d8e72002-09-23 09:36:25 +0000194}
195
njn25e49d8e72002-09-23 09:36:25 +0000196/*------------------------------------------------------------*/
197/*--- Basic bitmap management, reading and writing. ---*/
198/*------------------------------------------------------------*/
199
200/* Allocate and initialise a secondary map. */
201
202static AcSecMap* alloc_secondary_map ( __attribute__ ((unused))
sewardjb5f6f512005-03-10 23:59:00 +0000203 Char* caller,
204 const AcSecMap *prototype)
njn25e49d8e72002-09-23 09:36:25 +0000205{
206 AcSecMap* map;
njn0da7ac62005-07-19 21:11:54 +0000207 PROF_EVENT(10, "");
njn25e49d8e72002-09-23 09:36:25 +0000208
fitzhardinge98abfc72003-12-16 02:05:15 +0000209 map = (AcSecMap *)VG_(shadow_alloc)(sizeof(AcSecMap));
sewardjb5f6f512005-03-10 23:59:00 +0000210 VG_(memcpy)(map, prototype, sizeof(*map));
njn25e49d8e72002-09-23 09:36:25 +0000211
212 /* VG_(printf)("ALLOC_2MAP(%s)\n", caller ); */
213 return map;
214}
215
216
217/* Basic reading/writing of the bitmaps, for byte-sized accesses. */
218
219static __inline__ UChar get_abit ( Addr a )
220{
sewardjb5f6f512005-03-10 23:59:00 +0000221 AcSecMap* sm = primary_map[PM_IDX(a)];
222 UInt sm_off = SM_OFF(a);
njn0da7ac62005-07-19 21:11:54 +0000223 PROF_EVENT(20, "");
njn25e49d8e72002-09-23 09:36:25 +0000224# if 0
225 if (IS_DISTINGUISHED_SM(sm))
226 VG_(message)(Vg_DebugMsg,
227 "accessed distinguished 2ndary (A)map! 0x%x\n", a);
228# endif
229 return BITARR_TEST(sm->abits, sm_off)
230 ? VGM_BIT_INVALID : VGM_BIT_VALID;
231}
232
sewardj56867352003-10-12 10:27:06 +0000233static /* __inline__ */ void set_abit ( Addr a, UChar abit )
njn25e49d8e72002-09-23 09:36:25 +0000234{
235 AcSecMap* sm;
236 UInt sm_off;
njn0da7ac62005-07-19 21:11:54 +0000237 PROF_EVENT(22, "");
njn25e49d8e72002-09-23 09:36:25 +0000238 ENSURE_MAPPABLE(a, "set_abit");
sewardjb5f6f512005-03-10 23:59:00 +0000239 sm = primary_map[PM_IDX(a)];
240 sm_off = SM_OFF(a);
njn25e49d8e72002-09-23 09:36:25 +0000241 if (abit)
242 BITARR_SET(sm->abits, sm_off);
243 else
244 BITARR_CLEAR(sm->abits, sm_off);
245}
246
247
248/* Reading/writing of the bitmaps, for aligned word-sized accesses. */
249
250static __inline__ UChar get_abits4_ALIGNED ( Addr a )
251{
252 AcSecMap* sm;
253 UInt sm_off;
254 UChar abits8;
njn0da7ac62005-07-19 21:11:54 +0000255 PROF_EVENT(24, "");
njn25e49d8e72002-09-23 09:36:25 +0000256# ifdef VG_DEBUG_MEMORY
njnbe91aae2005-03-27 01:42:41 +0000257 tl_assert(VG_IS_4_ALIGNED(a));
njn25e49d8e72002-09-23 09:36:25 +0000258# endif
sewardjb5f6f512005-03-10 23:59:00 +0000259 sm = primary_map[PM_IDX(a)];
260 sm_off = SM_OFF(a);
njn25e49d8e72002-09-23 09:36:25 +0000261 abits8 = sm->abits[sm_off >> 3];
262 abits8 >>= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
263 abits8 &= 0x0F;
264 return abits8;
265}
266
267
268
269/*------------------------------------------------------------*/
270/*--- Setting permissions over address ranges. ---*/
271/*------------------------------------------------------------*/
272
sewardj56867352003-10-12 10:27:06 +0000273static /* __inline__ */
nethercote451eae92004-11-02 13:06:32 +0000274void set_address_range_perms ( Addr a, SizeT len, UInt example_a_bit )
njn25e49d8e72002-09-23 09:36:25 +0000275{
276 UChar abyte8;
277 UInt sm_off;
278 AcSecMap* sm;
279
njn0da7ac62005-07-19 21:11:54 +0000280 PROF_EVENT(30, "");
njn25e49d8e72002-09-23 09:36:25 +0000281
282 if (len == 0)
283 return;
284
285 if (len > 100 * 1000 * 1000) {
286 VG_(message)(Vg_UserMsg,
287 "Warning: set address range perms: "
288 "large range %u, a %d",
289 len, example_a_bit );
290 }
291
292 VGP_PUSHCC(VgpSetMem);
293
294 /* Requests to change permissions of huge address ranges may
295 indicate bugs in our machinery. 30,000,000 is arbitrary, but so
296 far all legitimate requests have fallen beneath that size. */
297 /* 4 Mar 02: this is just stupid; get rid of it. */
njnca82cc02004-11-22 17:18:48 +0000298 /* tl_assert(len < 30000000); */
njn25e49d8e72002-09-23 09:36:25 +0000299
300 /* Check the permissions make sense. */
njnca82cc02004-11-22 17:18:48 +0000301 tl_assert(example_a_bit == VGM_BIT_VALID
njn25e49d8e72002-09-23 09:36:25 +0000302 || example_a_bit == VGM_BIT_INVALID);
303
304 /* In order that we can charge through the address space at 8
305 bytes/main-loop iteration, make up some perms. */
sewardjb5f6f512005-03-10 23:59:00 +0000306 abyte8 = BIT_EXPAND(example_a_bit);
njn25e49d8e72002-09-23 09:36:25 +0000307
308# ifdef VG_DEBUG_MEMORY
309 /* Do it ... */
310 while (True) {
njn0da7ac62005-07-19 21:11:54 +0000311 PROF_EVENT(31, "");
njn25e49d8e72002-09-23 09:36:25 +0000312 if (len == 0) break;
313 set_abit ( a, example_a_bit );
314 set_vbyte ( a, vbyte );
315 a++;
316 len--;
317 }
318
319# else
320 /* Slowly do parts preceding 8-byte alignment. */
321 while (True) {
njn0da7ac62005-07-19 21:11:54 +0000322 PROF_EVENT(31, "");
njn25e49d8e72002-09-23 09:36:25 +0000323 if (len == 0) break;
324 if ((a % 8) == 0) break;
325 set_abit ( a, example_a_bit );
326 a++;
327 len--;
328 }
329
330 if (len == 0) {
331 VGP_POPCC(VgpSetMem);
332 return;
333 }
njnca82cc02004-11-22 17:18:48 +0000334 tl_assert((a % 8) == 0 && len > 0);
njn25e49d8e72002-09-23 09:36:25 +0000335
sewardjb5f6f512005-03-10 23:59:00 +0000336 /* Once aligned, go fast up to primary boundary. */
337 for (; (a & SECONDARY_MASK) && len >= 8; a += 8, len -= 8) {
njn0da7ac62005-07-19 21:11:54 +0000338 PROF_EVENT(32, "");
sewardjb5f6f512005-03-10 23:59:00 +0000339
340 /* If the primary is already pointing to a distinguished map
341 with the same properties as we're trying to set, then leave
342 it that way. */
343 if (primary_map[PM_IDX(a)] == DSM(example_a_bit))
344 continue;
njn25e49d8e72002-09-23 09:36:25 +0000345 ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
sewardjb5f6f512005-03-10 23:59:00 +0000346 sm = primary_map[PM_IDX(a)];
347 sm_off = SM_OFF(a);
njn25e49d8e72002-09-23 09:36:25 +0000348 sm->abits[sm_off >> 3] = abyte8;
njn25e49d8e72002-09-23 09:36:25 +0000349 }
350
sewardjb5f6f512005-03-10 23:59:00 +0000351 /* Now set whole secondary maps to the right distinguished value.
352
353 Note that if the primary already points to a non-distinguished
354 secondary, then don't replace the reference. That would just
355 leak memory.
356 */
357 for(; len >= SECONDARY_SIZE; a += SECONDARY_SIZE, len -= SECONDARY_SIZE) {
358 sm = primary_map[PM_IDX(a)];
359
360 if (IS_DISTINGUISHED_SM(sm))
361 primary_map[PM_IDX(a)] = DSM(example_a_bit);
362 else
363 VG_(memset)(sm->abits, abyte8, sizeof(sm->abits));
njn25e49d8e72002-09-23 09:36:25 +0000364 }
sewardjb5f6f512005-03-10 23:59:00 +0000365
366 /* Now finished the remains. */
367 for (; len >= 8; a += 8, len -= 8) {
njn0da7ac62005-07-19 21:11:54 +0000368 PROF_EVENT(32, "");
sewardjb5f6f512005-03-10 23:59:00 +0000369
370 /* If the primary is already pointing to a distinguished map
371 with the same properties as we're trying to set, then leave
372 it that way. */
373 if (primary_map[PM_IDX(a)] == DSM(example_a_bit))
374 continue;
375 ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
376 sm = primary_map[PM_IDX(a)];
377 sm_off = SM_OFF(a);
378 sm->abits[sm_off >> 3] = abyte8;
379 }
380
njn25e49d8e72002-09-23 09:36:25 +0000381
382 /* Finish the upper fragment. */
383 while (True) {
njn0da7ac62005-07-19 21:11:54 +0000384 PROF_EVENT(33, "");
njn25e49d8e72002-09-23 09:36:25 +0000385 if (len == 0) break;
386 set_abit ( a, example_a_bit );
387 a++;
388 len--;
389 }
390# endif
391
njn25e49d8e72002-09-23 09:36:25 +0000392 VGP_POPCC(VgpSetMem);
393}
394
395/* Set permissions for address ranges ... */
396
nethercote451eae92004-11-02 13:06:32 +0000397static void ac_make_noaccess ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000398{
njn0da7ac62005-07-19 21:11:54 +0000399 PROF_EVENT(35, "");
njn5c004e42002-11-18 11:04:50 +0000400 DEBUG("ac_make_noaccess(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000401 set_address_range_perms ( a, len, VGM_BIT_INVALID );
402}
403
nethercote451eae92004-11-02 13:06:32 +0000404static void ac_make_accessible ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000405{
njn0da7ac62005-07-19 21:11:54 +0000406 PROF_EVENT(38, "");
njn5c004e42002-11-18 11:04:50 +0000407 DEBUG("ac_make_accessible(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000408 set_address_range_perms ( a, len, VGM_BIT_VALID );
409}
410
njn9b007f62003-04-07 14:40:25 +0000411static __inline__
412void make_aligned_word_noaccess(Addr a)
413{
414 AcSecMap* sm;
415 UInt sm_off;
416 UChar mask;
417
418 VGP_PUSHCC(VgpESPAdj);
419 ENSURE_MAPPABLE(a, "make_aligned_word_noaccess");
sewardjb5f6f512005-03-10 23:59:00 +0000420 sm = primary_map[PM_IDX(a)];
421 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000422 mask = 0x0F;
423 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
424 /* mask now contains 1s where we wish to make address bits invalid (1s). */
425 sm->abits[sm_off >> 3] |= mask;
426 VGP_POPCC(VgpESPAdj);
427}
428
429static __inline__
430void make_aligned_word_accessible(Addr a)
431{
432 AcSecMap* sm;
433 UInt sm_off;
434 UChar mask;
435
436 VGP_PUSHCC(VgpESPAdj);
437 ENSURE_MAPPABLE(a, "make_aligned_word_accessible");
sewardjb5f6f512005-03-10 23:59:00 +0000438 sm = primary_map[PM_IDX(a)];
439 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000440 mask = 0x0F;
441 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
442 /* mask now contains 1s where we wish to make address bits
443 invalid (0s). */
444 sm->abits[sm_off >> 3] &= ~mask;
445 VGP_POPCC(VgpESPAdj);
446}
447
448/* Nb: by "aligned" here we mean 8-byte aligned */
449static __inline__
450void make_aligned_doubleword_accessible(Addr a)
451{
452 AcSecMap* sm;
453 UInt sm_off;
454
455 VGP_PUSHCC(VgpESPAdj);
456 ENSURE_MAPPABLE(a, "make_aligned_doubleword_accessible");
sewardjb5f6f512005-03-10 23:59:00 +0000457 sm = primary_map[PM_IDX(a)];
458 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000459 sm->abits[sm_off >> 3] = VGM_BYTE_VALID;
460 VGP_POPCC(VgpESPAdj);
461}
462
463static __inline__
464void make_aligned_doubleword_noaccess(Addr a)
465{
466 AcSecMap* sm;
467 UInt sm_off;
468
469 VGP_PUSHCC(VgpESPAdj);
470 ENSURE_MAPPABLE(a, "make_aligned_doubleword_noaccess");
sewardjb5f6f512005-03-10 23:59:00 +0000471 sm = primary_map[PM_IDX(a)];
472 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000473 sm->abits[sm_off >> 3] = VGM_BYTE_INVALID;
474 VGP_POPCC(VgpESPAdj);
475}
476
477/* The %esp update handling functions */
478ESP_UPDATE_HANDLERS ( make_aligned_word_accessible,
479 make_aligned_word_noaccess,
480 make_aligned_doubleword_accessible,
481 make_aligned_doubleword_noaccess,
482 ac_make_accessible,
483 ac_make_noaccess
484 );
485
486
njn25e49d8e72002-09-23 09:36:25 +0000487/* Block-copy permissions (needed for implementing realloc()). */
488
nethercote451eae92004-11-02 13:06:32 +0000489static void ac_copy_address_range_state ( Addr src, Addr dst, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000490{
491 UInt i;
492
njn5c004e42002-11-18 11:04:50 +0000493 DEBUG("ac_copy_address_range_state\n");
njn25e49d8e72002-09-23 09:36:25 +0000494
njn0da7ac62005-07-19 21:11:54 +0000495 PROF_EVENT(40, "");
njn25e49d8e72002-09-23 09:36:25 +0000496 for (i = 0; i < len; i++) {
497 UChar abit = get_abit ( src+i );
njn0da7ac62005-07-19 21:11:54 +0000498 PROF_EVENT(41, "");
njn25e49d8e72002-09-23 09:36:25 +0000499 set_abit ( dst+i, abit );
500 }
501}
502
503
504/* Check permissions for address range. If inadequate permissions
505 exist, *bad_addr is set to the offending address, so the caller can
506 know what it is. */
507
njn5c004e42002-11-18 11:04:50 +0000508static __inline__
nethercote451eae92004-11-02 13:06:32 +0000509Bool ac_check_accessible ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000510{
511 UInt i;
512 UChar abit;
njn0da7ac62005-07-19 21:11:54 +0000513 PROF_EVENT(48, "");
njn25e49d8e72002-09-23 09:36:25 +0000514 for (i = 0; i < len; i++) {
njn0da7ac62005-07-19 21:11:54 +0000515 PROF_EVENT(49, "");
njn25e49d8e72002-09-23 09:36:25 +0000516 abit = get_abit(a);
517 if (abit == VGM_BIT_INVALID) {
518 if (bad_addr != NULL) *bad_addr = a;
519 return False;
520 }
521 a++;
522 }
523 return True;
524}
525
sewardjecf8e102003-07-12 12:11:39 +0000526/* The opposite; check that an address range is inaccessible. */
527static
nethercote451eae92004-11-02 13:06:32 +0000528Bool ac_check_noaccess ( Addr a, SizeT len, Addr* bad_addr )
sewardjecf8e102003-07-12 12:11:39 +0000529{
530 UInt i;
531 UChar abit;
njn0da7ac62005-07-19 21:11:54 +0000532 PROF_EVENT(48, "");
sewardjecf8e102003-07-12 12:11:39 +0000533 for (i = 0; i < len; i++) {
njn0da7ac62005-07-19 21:11:54 +0000534 PROF_EVENT(49, "");
sewardjecf8e102003-07-12 12:11:39 +0000535 abit = get_abit(a);
536 if (abit == VGM_BIT_VALID) {
537 if (bad_addr != NULL) *bad_addr = a;
538 return False;
539 }
540 a++;
541 }
542 return True;
543}
544
njn25e49d8e72002-09-23 09:36:25 +0000545/* Check a zero-terminated ascii string. Tricky -- don't want to
546 examine the actual bytes, to find the end, until we're sure it is
547 safe to do so. */
548
njn5c004e42002-11-18 11:04:50 +0000549static __inline__
550Bool ac_check_readable_asciiz ( Addr a, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000551{
552 UChar abit;
njn0da7ac62005-07-19 21:11:54 +0000553 PROF_EVENT(46, "");
njn5c004e42002-11-18 11:04:50 +0000554 DEBUG("ac_check_readable_asciiz\n");
njn25e49d8e72002-09-23 09:36:25 +0000555 while (True) {
njn0da7ac62005-07-19 21:11:54 +0000556 PROF_EVENT(47, "");
njn25e49d8e72002-09-23 09:36:25 +0000557 abit = get_abit(a);
558 if (abit != VGM_BIT_VALID) {
559 if (bad_addr != NULL) *bad_addr = a;
560 return False;
561 }
562 /* Ok, a is safe to read. */
563 if (* ((UChar*)a) == 0) return True;
564 a++;
565 }
566}
567
568
569/*------------------------------------------------------------*/
570/*--- Memory event handlers ---*/
571/*------------------------------------------------------------*/
572
njn5c004e42002-11-18 11:04:50 +0000573static __inline__
njn72718642003-07-24 08:45:32 +0000574void ac_check_is_accessible ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000575 Char* s, Addr base, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000576{
577 Bool ok;
njn86f12dc2005-03-14 01:16:05 +0000578 Addr bad_addr = 0; // Initialise to shut gcc up
njn25e49d8e72002-09-23 09:36:25 +0000579
580 VGP_PUSHCC(VgpCheckMem);
581
njn5c004e42002-11-18 11:04:50 +0000582 ok = ac_check_accessible ( base, size, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000583 if (!ok) {
584 switch (part) {
585 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +0000586 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
587 /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000588 break;
589
njn25e49d8e72002-09-23 09:36:25 +0000590 case Vg_CoreSignal:
njnca82cc02004-11-22 17:18:48 +0000591 tl_assert(isWrite); /* Should only happen with isWrite case */
njn5c004e42002-11-18 11:04:50 +0000592 /* fall through */
njn25e49d8e72002-09-23 09:36:25 +0000593 case Vg_CorePThread:
nethercote8b76fe52004-11-08 19:20:09 +0000594 MAC_(record_core_mem_error)( tid, /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000595 break;
596
597 /* If we're being asked to jump to a silly address, record an error
598 message before potentially crashing the entire system. */
599 case Vg_CoreTranslate:
njnca82cc02004-11-22 17:18:48 +0000600 tl_assert(!isWrite); /* Should only happen with !isWrite case */
njn72718642003-07-24 08:45:32 +0000601 MAC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000602 break;
603
604 default:
njn67993252004-11-22 18:02:32 +0000605 VG_(tool_panic)("ac_check_is_accessible: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +0000606 }
607 }
njn5c004e42002-11-18 11:04:50 +0000608
njn25e49d8e72002-09-23 09:36:25 +0000609 VGP_POPCC(VgpCheckMem);
610}
611
612static
njn72718642003-07-24 08:45:32 +0000613void ac_check_is_writable ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000614 Char* s, Addr base, SizeT size )
njn5c004e42002-11-18 11:04:50 +0000615{
njn72718642003-07-24 08:45:32 +0000616 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/True );
njn5c004e42002-11-18 11:04:50 +0000617}
618
619static
njn72718642003-07-24 08:45:32 +0000620void ac_check_is_readable ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000621 Char* s, Addr base, SizeT size )
njn5c004e42002-11-18 11:04:50 +0000622{
njn72718642003-07-24 08:45:32 +0000623 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/False );
njn5c004e42002-11-18 11:04:50 +0000624}
625
626static
njn72718642003-07-24 08:45:32 +0000627void ac_check_is_readable_asciiz ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000628 Char* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +0000629{
630 Bool ok = True;
njn86f12dc2005-03-14 01:16:05 +0000631 Addr bad_addr = 0; // Initialise to shut gcc up
njn25e49d8e72002-09-23 09:36:25 +0000632
633 VGP_PUSHCC(VgpCheckMem);
634
njnca82cc02004-11-22 17:18:48 +0000635 tl_assert(part == Vg_CoreSysCall);
njn5c004e42002-11-18 11:04:50 +0000636 ok = ac_check_readable_asciiz ( (Addr)str, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000637 if (!ok) {
nethercote8b76fe52004-11-08 19:20:09 +0000638 MAC_(record_param_error) ( tid, bad_addr, /*IsReg*/False,
639 /*IsUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000640 }
641
642 VGP_POPCC(VgpCheckMem);
643}
644
645static
nethercote451eae92004-11-02 13:06:32 +0000646void ac_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +0000647{
njn1f3a9092002-10-04 09:22:30 +0000648 /* Ignore the permissions, just make it readable. Seems to work... */
njn25e49d8e72002-09-23 09:36:25 +0000649 DEBUG("new_mem_startup(%p, %u, rr=%u, ww=%u, xx=%u)\n", a,len,rr,ww,xx);
njn5c004e42002-11-18 11:04:50 +0000650 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000651}
652
653static
nethercote451eae92004-11-02 13:06:32 +0000654void ac_new_mem_heap ( Addr a, SizeT len, Bool is_inited )
njn25e49d8e72002-09-23 09:36:25 +0000655{
njn5c004e42002-11-18 11:04:50 +0000656 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000657}
658
659static
sewardjb5f6f512005-03-10 23:59:00 +0000660void ac_new_mem_mmap (Addr a, SizeT len, Bool rr, Bool ww, Bool xx)
njn25e49d8e72002-09-23 09:36:25 +0000661{
njn5c004e42002-11-18 11:04:50 +0000662 DEBUG("ac_set_perms(%p, %u, rr=%u ww=%u, xx=%u)\n",
sewardj40f8ebe2002-10-23 21:46:13 +0000663 a, len, rr, ww, xx);
sewardjb5f6f512005-03-10 23:59:00 +0000664 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000665}
666
njncf45fd42004-11-24 16:30:22 +0000667static
668void ac_post_mem_write(CorePart part, ThreadId tid, Addr a, SizeT len)
669{
670 ac_make_accessible(a, len);
671}
672
njn25e49d8e72002-09-23 09:36:25 +0000673
674/*------------------------------------------------------------*/
675/*--- Functions called directly from generated code. ---*/
676/*------------------------------------------------------------*/
677
678static __inline__ UInt rotateRight16 ( UInt x )
679{
680 /* Amazingly, gcc turns this into a single rotate insn. */
681 return (x >> 16) | (x << 16);
682}
683
njn25e49d8e72002-09-23 09:36:25 +0000684static __inline__ UInt shiftRight16 ( UInt x )
685{
686 return x >> 16;
687}
688
689
690/* Read/write 1/2/4 sized V bytes, and emit an address error if
691 needed. */
692
njn5c004e42002-11-18 11:04:50 +0000693/* ac_helperc_ACCESS{1,2,4} handle the common case fast.
njn25e49d8e72002-09-23 09:36:25 +0000694 Under all other circumstances, it defers to the relevant _SLOWLY
695 function, which can handle all situations.
696*/
njnc2699f62003-09-05 23:29:33 +0000697static __inline__ void ac_helperc_ACCESS4 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000698{
699# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000700 return ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000701# else
702 UInt sec_no = rotateRight16(a) & 0x3FFFF;
njnda2e36d2003-09-30 13:33:24 +0000703 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000704 UInt a_off = (SM_OFF(a)) >> 3;
njn25e49d8e72002-09-23 09:36:25 +0000705 UChar abits = sm->abits[a_off];
706 abits >>= (a & 4);
707 abits &= 15;
njn0da7ac62005-07-19 21:11:54 +0000708 PROF_EVENT(66, "");
njn25e49d8e72002-09-23 09:36:25 +0000709 if (abits == VGM_NIBBLE_VALID) {
710 /* Handle common case quickly: a is suitably aligned, is mapped,
711 and is addressible. So just return. */
712 return;
713 } else {
714 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000715 ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000716 }
717# endif
718}
719
njnc2699f62003-09-05 23:29:33 +0000720static __inline__ void ac_helperc_ACCESS2 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000721{
722# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000723 return ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000724# else
725 UInt sec_no = rotateRight16(a) & 0x1FFFF;
726 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000727 UInt a_off = (SM_OFF(a)) >> 3;
njn0da7ac62005-07-19 21:11:54 +0000728 PROF_EVENT(67, "");
njn25e49d8e72002-09-23 09:36:25 +0000729 if (sm->abits[a_off] == VGM_BYTE_VALID) {
730 /* Handle common case quickly. */
731 return;
732 } else {
733 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000734 ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000735 }
736# endif
737}
738
njnc2699f62003-09-05 23:29:33 +0000739static __inline__ void ac_helperc_ACCESS1 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000740{
741# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000742 return ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000743# else
744 UInt sec_no = shiftRight16(a);
745 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000746 UInt a_off = (SM_OFF(a)) >> 3;
njn0da7ac62005-07-19 21:11:54 +0000747 PROF_EVENT(68, "");
njn25e49d8e72002-09-23 09:36:25 +0000748 if (sm->abits[a_off] == VGM_BYTE_VALID) {
749 /* Handle common case quickly. */
750 return;
751 } else {
752 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000753 ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000754 }
755# endif
756}
757
njnaf839f52005-06-23 03:27:57 +0000758VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000759static void ach_LOAD4 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000760{
761 ac_helperc_ACCESS4 ( a, /*isWrite*/False );
762}
njnaf839f52005-06-23 03:27:57 +0000763VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000764static void ach_STORE4 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000765{
766 ac_helperc_ACCESS4 ( a, /*isWrite*/True );
767}
768
njnaf839f52005-06-23 03:27:57 +0000769VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000770static void ach_LOAD2 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000771{
772 ac_helperc_ACCESS2 ( a, /*isWrite*/False );
773}
njnaf839f52005-06-23 03:27:57 +0000774VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000775static void ach_STORE2 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000776{
777 ac_helperc_ACCESS2 ( a, /*isWrite*/True );
778}
779
njnaf839f52005-06-23 03:27:57 +0000780VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000781static void ach_LOAD1 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000782{
783 ac_helperc_ACCESS1 ( a, /*isWrite*/False );
784}
njnaf839f52005-06-23 03:27:57 +0000785VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000786static void ach_STORE1 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000787{
788 ac_helperc_ACCESS1 ( a, /*isWrite*/True );
789}
790
njn25e49d8e72002-09-23 09:36:25 +0000791
792/*------------------------------------------------------------*/
793/*--- Fallback functions to handle cases that the above ---*/
njnc2699f62003-09-05 23:29:33 +0000794/*--- ac_helperc_ACCESS{1,2,4} can't manage. ---*/
njn25e49d8e72002-09-23 09:36:25 +0000795/*------------------------------------------------------------*/
796
njnc2699f62003-09-05 23:29:33 +0000797static void ac_ACCESS4_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000798{
799 Bool a0ok, a1ok, a2ok, a3ok;
800
njn0da7ac62005-07-19 21:11:54 +0000801 PROF_EVENT(76, "");
njn25e49d8e72002-09-23 09:36:25 +0000802
803 /* First establish independently the addressibility of the 4 bytes
804 involved. */
805 a0ok = get_abit(a+0) == VGM_BIT_VALID;
806 a1ok = get_abit(a+1) == VGM_BIT_VALID;
807 a2ok = get_abit(a+2) == VGM_BIT_VALID;
808 a3ok = get_abit(a+3) == VGM_BIT_VALID;
809
810 /* Now distinguish 3 cases */
811
812 /* Case 1: the address is completely valid, so:
813 - no addressing error
814 */
815 if (a0ok && a1ok && a2ok && a3ok) {
816 return;
817 }
818
819 /* Case 2: the address is completely invalid.
820 - emit addressing error
821 */
822 /* VG_(printf)("%p (%d %d %d %d)\n", a, a0ok, a1ok, a2ok, a3ok); */
njn43c799e2003-04-08 00:08:52 +0000823 if (!MAC_(clo_partial_loads_ok)
njn25e49d8e72002-09-23 09:36:25 +0000824 || ((a & 3) != 0)
825 || (!a0ok && !a1ok && !a2ok && !a3ok)) {
sewardj76754cf2005-03-14 00:14:04 +0000826 MAC_(record_address_error)( VG_(get_running_tid)(), a, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000827 return;
828 }
829
830 /* Case 3: the address is partially valid.
831 - no addressing error
njn43c799e2003-04-08 00:08:52 +0000832 Case 3 is only allowed if MAC_(clo_partial_loads_ok) is True
njn25e49d8e72002-09-23 09:36:25 +0000833 (which is the default), and the address is 4-aligned.
834 If not, Case 2 will have applied.
835 */
njnca82cc02004-11-22 17:18:48 +0000836 tl_assert(MAC_(clo_partial_loads_ok));
njn25e49d8e72002-09-23 09:36:25 +0000837 {
838 return;
839 }
840}
841
njnc2699f62003-09-05 23:29:33 +0000842static void ac_ACCESS2_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000843{
844 /* Check the address for validity. */
845 Bool aerr = False;
njn0da7ac62005-07-19 21:11:54 +0000846 PROF_EVENT(77, "");
njn25e49d8e72002-09-23 09:36:25 +0000847
848 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
849 if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
850
851 /* If an address error has happened, report it. */
852 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000853 MAC_(record_address_error)( VG_(get_running_tid)(), a, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000854 }
855}
856
njnc2699f62003-09-05 23:29:33 +0000857static void ac_ACCESS1_SLOWLY ( Addr a, Bool isWrite)
njn25e49d8e72002-09-23 09:36:25 +0000858{
859 /* Check the address for validity. */
860 Bool aerr = False;
njn0da7ac62005-07-19 21:11:54 +0000861 PROF_EVENT(78, "");
njn25e49d8e72002-09-23 09:36:25 +0000862
863 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
864
865 /* If an address error has happened, report it. */
866 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000867 MAC_(record_address_error)( VG_(get_running_tid)(), a, 1, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000868 }
869}
870
871
872/* ---------------------------------------------------------------------
873 FPU load and store checks, called from generated code.
874 ------------------------------------------------------------------ */
875
sewardj56867352003-10-12 10:27:06 +0000876static
nethercote928a5f72004-11-03 18:10:37 +0000877void ac_fpu_ACCESS_check ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000878{
879 /* Ensure the read area is both addressible and valid (ie,
880 readable). If there's an address error, don't report a value
881 error too; but if there isn't an address error, check for a
882 value error.
883
884 Try to be reasonably fast on the common case; wimp out and defer
njn5c004e42002-11-18 11:04:50 +0000885 to ac_fpu_ACCESS_check_SLOWLY for everything else. */
njn25e49d8e72002-09-23 09:36:25 +0000886
887 AcSecMap* sm;
888 UInt sm_off, a_off;
889 Addr addr4;
890
njn0da7ac62005-07-19 21:11:54 +0000891 PROF_EVENT(90, "");
njn25e49d8e72002-09-23 09:36:25 +0000892
893# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000894 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000895# else
896
897 if (size == 4) {
njnbe91aae2005-03-27 01:42:41 +0000898 if (!VG_IS_4_ALIGNED(addr)) goto slow4;
njn0da7ac62005-07-19 21:11:54 +0000899 PROF_EVENT(91, "");
njn25e49d8e72002-09-23 09:36:25 +0000900 /* Properly aligned. */
sewardjb5f6f512005-03-10 23:59:00 +0000901 sm = primary_map[PM_IDX(addr)];
902 sm_off = SM_OFF(addr);
njn25e49d8e72002-09-23 09:36:25 +0000903 a_off = sm_off >> 3;
904 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow4;
905 /* Properly aligned and addressible. */
906 return;
907 slow4:
njnc2699f62003-09-05 23:29:33 +0000908 ac_fpu_ACCESS_check_SLOWLY ( addr, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000909 return;
910 }
911
912 if (size == 8) {
njnbe91aae2005-03-27 01:42:41 +0000913 if (!VG_IS_4_ALIGNED(addr)) goto slow8;
njn0da7ac62005-07-19 21:11:54 +0000914 PROF_EVENT(92, "");
njn25e49d8e72002-09-23 09:36:25 +0000915 /* Properly aligned. Do it in two halves. */
916 addr4 = addr + 4;
917 /* First half. */
sewardjb5f6f512005-03-10 23:59:00 +0000918 sm = primary_map[PM_IDX(addr)];
919 sm_off = SM_OFF(addr);
njn25e49d8e72002-09-23 09:36:25 +0000920 a_off = sm_off >> 3;
921 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
922 /* First half properly aligned and addressible. */
923 /* Second half. */
sewardjb5f6f512005-03-10 23:59:00 +0000924 sm = primary_map[PM_IDX(addr4)];
925 sm_off = SM_OFF(addr4);
njn25e49d8e72002-09-23 09:36:25 +0000926 a_off = sm_off >> 3;
927 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
928 /* Second half properly aligned and addressible. */
929 /* Both halves properly aligned and addressible. */
930 return;
931 slow8:
njnc2699f62003-09-05 23:29:33 +0000932 ac_fpu_ACCESS_check_SLOWLY ( addr, 8, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000933 return;
934 }
935
936 /* Can't be bothered to huff'n'puff to make these (allegedly) rare
937 cases go quickly. */
938 if (size == 2) {
njn0da7ac62005-07-19 21:11:54 +0000939 PROF_EVENT(93, "");
njnc2699f62003-09-05 23:29:33 +0000940 ac_fpu_ACCESS_check_SLOWLY ( addr, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000941 return;
942 }
943
jsewardfca60182004-01-04 23:30:55 +0000944 if (size == 16 || size == 10 || size == 28 || size == 108 || size == 512) {
njn0da7ac62005-07-19 21:11:54 +0000945 PROF_EVENT(94, "");
njnc2699f62003-09-05 23:29:33 +0000946 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000947 return;
948 }
949
950 VG_(printf)("size is %d\n", size);
njn67993252004-11-22 18:02:32 +0000951 VG_(tool_panic)("fpu_ACCESS_check: unhandled size");
njn25e49d8e72002-09-23 09:36:25 +0000952# endif
953}
954
njnaf839f52005-06-23 03:27:57 +0000955VG_REGPARM(2)
sewardj9f649aa2004-11-22 20:38:40 +0000956static void ach_LOADN ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000957{
958 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/False );
959}
960
njnaf839f52005-06-23 03:27:57 +0000961VG_REGPARM(2)
sewardj9f649aa2004-11-22 20:38:40 +0000962static void ach_STOREN ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000963{
964 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/True );
965}
njn25e49d8e72002-09-23 09:36:25 +0000966
sewardjd62e03b2004-12-10 12:01:14 +0000967
njn25e49d8e72002-09-23 09:36:25 +0000968/* ---------------------------------------------------------------------
969 Slow, general cases for FPU access checks.
970 ------------------------------------------------------------------ */
971
nethercote928a5f72004-11-03 18:10:37 +0000972void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000973{
974 Int i;
975 Bool aerr = False;
njn0da7ac62005-07-19 21:11:54 +0000976 PROF_EVENT(100, "");
njn25e49d8e72002-09-23 09:36:25 +0000977 for (i = 0; i < size; i++) {
njn0da7ac62005-07-19 21:11:54 +0000978 PROF_EVENT(101, "");
njn25e49d8e72002-09-23 09:36:25 +0000979 if (get_abit(addr+i) != VGM_BIT_VALID)
980 aerr = True;
981 }
982
983 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000984 MAC_(record_address_error)( VG_(get_running_tid)(), addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000985 }
986}
987
988
989/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000990/*--- Our instrumenter ---*/
991/*------------------------------------------------------------*/
992
njn51d827b2005-05-09 01:02:08 +0000993static IRBB* ac_instrument(IRBB* bb_in, VexGuestLayout* layout,
994 IRType gWordTy, IRType hWordTy )
njn25e49d8e72002-09-23 09:36:25 +0000995{
sewardj9f649aa2004-11-22 20:38:40 +0000996 Int i, hsz;
997 IRStmt* st;
998 IRExpr* data;
999 IRExpr* aexpr;
1000 IRExpr* guard;
1001 IRDirty* di;
1002 Bool isLoad;
sewardjd54babf2005-03-21 00:55:49 +00001003 IRBB* bb;
1004
1005 if (gWordTy != hWordTy) {
1006 /* We don't currently support this case. */
1007 VG_(tool_panic)("host/guest word size mismatch");
1008 }
njn25e49d8e72002-09-23 09:36:25 +00001009
sewardj9f649aa2004-11-22 20:38:40 +00001010 /* Set up BB */
sewardjd54babf2005-03-21 00:55:49 +00001011 bb = emptyIRBB();
sewardj9f649aa2004-11-22 20:38:40 +00001012 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
1013 bb->next = dopyIRExpr(bb_in->next);
1014 bb->jumpkind = bb_in->jumpkind;
njn25e49d8e72002-09-23 09:36:25 +00001015
sewardj9f649aa2004-11-22 20:38:40 +00001016 /* No loads to consider in ->next. */
sewardj710d6c22005-03-20 18:55:15 +00001017 tl_assert(isIRAtom(bb_in->next));
njn25e49d8e72002-09-23 09:36:25 +00001018
sewardj9f649aa2004-11-22 20:38:40 +00001019 for (i = 0; i < bb_in->stmts_used; i++) {
1020 st = bb_in->stmts[i];
sewardj21dc3452005-03-21 00:27:41 +00001021 tl_assert(st);
njn25e49d8e72002-09-23 09:36:25 +00001022
sewardj9f649aa2004-11-22 20:38:40 +00001023 /* Examine each stmt in turn to figure out if it needs to be
1024 preceded by a memory access check. If so, collect up the
1025 relevant pieces of information. */
1026 hsz = 0;
1027 aexpr = NULL;
1028 guard = NULL;
1029 isLoad = True;
njn25e49d8e72002-09-23 09:36:25 +00001030
sewardj9f649aa2004-11-22 20:38:40 +00001031 switch (st->tag) {
1032
1033 case Ist_Tmp:
1034 data = st->Ist.Tmp.data;
1035 if (data->tag == Iex_LDle) {
1036 aexpr = data->Iex.LDle.addr;
1037 hsz = sizeofIRType(data->Iex.LDle.ty);
1038 isLoad = True;
1039 }
1040 break;
1041
1042 case Ist_STle:
1043 data = st->Ist.STle.data;
1044 aexpr = st->Ist.STle.addr;
sewardj710d6c22005-03-20 18:55:15 +00001045 tl_assert(isIRAtom(data));
1046 tl_assert(isIRAtom(aexpr));
sewardj9f649aa2004-11-22 20:38:40 +00001047 hsz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
1048 isLoad = False;
sewardj08ccc5c2005-03-17 03:17:54 +00001049 break;
sewardj9f649aa2004-11-22 20:38:40 +00001050
1051 case Ist_Put:
sewardj710d6c22005-03-20 18:55:15 +00001052 tl_assert(isIRAtom(st->Ist.Put.data));
njn25e49d8e72002-09-23 09:36:25 +00001053 break;
1054
sewardj9f649aa2004-11-22 20:38:40 +00001055 case Ist_PutI:
sewardj710d6c22005-03-20 18:55:15 +00001056 tl_assert(isIRAtom(st->Ist.PutI.ix));
1057 tl_assert(isIRAtom(st->Ist.PutI.data));
njnc2699f62003-09-05 23:29:33 +00001058 break;
1059
sewardj9f649aa2004-11-22 20:38:40 +00001060 case Ist_Exit:
sewardj710d6c22005-03-20 18:55:15 +00001061 tl_assert(isIRAtom(st->Ist.Exit.guard));
njn25e49d8e72002-09-23 09:36:25 +00001062 break;
1063
sewardj9f649aa2004-11-22 20:38:40 +00001064 case Ist_Dirty:
1065 if (st->Ist.Dirty.details->mFx != Ifx_None) {
1066 /* We classify Ifx_Modify as a load. */
1067 isLoad = st->Ist.Dirty.details->mFx != Ifx_Write;
1068 hsz = st->Ist.Dirty.details->mSize;
1069 aexpr = st->Ist.Dirty.details->mAddr;
1070 guard = st->Ist.Dirty.details->guard;
sewardj710d6c22005-03-20 18:55:15 +00001071 tl_assert(isIRAtom(aexpr));
sewardj9f649aa2004-11-22 20:38:40 +00001072 }
1073 break;
sewardje3891fa2003-06-15 03:13:48 +00001074
sewardj21dc3452005-03-21 00:27:41 +00001075 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00001076 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00001077 case Ist_MFence:
1078 break;
1079
njn25e49d8e72002-09-23 09:36:25 +00001080 default:
sewardj9f649aa2004-11-22 20:38:40 +00001081 VG_(printf)("\n");
1082 ppIRStmt(st);
1083 VG_(printf)("\n");
1084 VG_(tool_panic)("addrcheck: unhandled IRStmt");
njn25e49d8e72002-09-23 09:36:25 +00001085 }
sewardj9f649aa2004-11-22 20:38:40 +00001086
1087 /* If needed, add a helper call. */
1088 if (aexpr) {
1089 tl_assert(hsz > 0);
1090 switch (hsz) {
1091 case 4:
1092 if (isLoad)
1093 di = unsafeIRDirty_0_N( 1, "ach_LOAD4", &ach_LOAD4,
1094 mkIRExprVec_1(aexpr));
1095 else
1096 di = unsafeIRDirty_0_N( 1, "ach_STORE4", &ach_STORE4,
1097 mkIRExprVec_1(aexpr));
1098 break;
1099 case 2:
1100 if (isLoad)
1101 di = unsafeIRDirty_0_N( 1, "ach_LOAD2", &ach_LOAD2,
1102 mkIRExprVec_1(aexpr));
1103 else
1104 di = unsafeIRDirty_0_N( 1, "ach_STORE2", &ach_STORE2,
1105 mkIRExprVec_1(aexpr));
1106 break;
1107 case 1:
1108 if (isLoad)
1109 di = unsafeIRDirty_0_N( 1, "ach_LOAD1", &ach_LOAD1,
1110 mkIRExprVec_1(aexpr));
1111 else
1112 di = unsafeIRDirty_0_N( 1, "ach_STORE1", &ach_STORE1,
1113 mkIRExprVec_1(aexpr));
1114 break;
1115 default:
1116 if (isLoad)
1117 di = unsafeIRDirty_0_N(
1118 2, "ach_LOADN", &ach_LOADN,
1119 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1120 else
1121 di = unsafeIRDirty_0_N(
1122 2, "ach_STOREN", &ach_STOREN,
1123 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1124 break;
1125 }
1126
1127 /* If the call has arisen as a result of a dirty helper which
1128 references memory, we need to inherit the guard from the
1129 dirty helper. */
1130 if (guard)
1131 di->guard = dopyIRExpr(guard);
1132
1133 /* emit the helper call */
1134 addStmtToIRBB( bb, IRStmt_Dirty(di) );
1135
1136 }
1137
1138 /* And finally, copy the expr itself to the output. */
sewardjbd598e12005-01-07 12:10:21 +00001139 addStmtToIRBB( bb, st );
njn25e49d8e72002-09-23 09:36:25 +00001140 }
1141
sewardj9f649aa2004-11-22 20:38:40 +00001142 return bb;
njn25e49d8e72002-09-23 09:36:25 +00001143}
1144
1145
njn25e49d8e72002-09-23 09:36:25 +00001146/*------------------------------------------------------------*/
1147/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
1148/*------------------------------------------------------------*/
1149
sewardja4495682002-10-21 07:29:59 +00001150/* For the memory leak detector, say whether an entire 64k chunk of
1151 address space is possibly in use, or not. If in doubt return
1152 True.
njn25e49d8e72002-09-23 09:36:25 +00001153*/
sewardja4495682002-10-21 07:29:59 +00001154static
1155Bool ac_is_valid_64k_chunk ( UInt chunk_number )
njn25e49d8e72002-09-23 09:36:25 +00001156{
sewardjb5f6f512005-03-10 23:59:00 +00001157 tl_assert(chunk_number >= 0 && chunk_number < PRIMARY_SIZE);
1158 if (primary_map[chunk_number] == DSM_NOTADDR) {
sewardja4495682002-10-21 07:29:59 +00001159 /* Definitely not in use. */
1160 return False;
1161 } else {
1162 return True;
njn25e49d8e72002-09-23 09:36:25 +00001163 }
1164}
1165
1166
sewardja4495682002-10-21 07:29:59 +00001167/* For the memory leak detector, say whether or not a given word
1168 address is to be regarded as valid. */
1169static
1170Bool ac_is_valid_address ( Addr a )
1171{
1172 UChar abits;
njnbe91aae2005-03-27 01:42:41 +00001173 tl_assert(VG_IS_4_ALIGNED(a));
sewardja4495682002-10-21 07:29:59 +00001174 abits = get_abits4_ALIGNED(a);
1175 if (abits == VGM_NIBBLE_VALID) {
1176 return True;
1177 } else {
1178 return False;
1179 }
1180}
1181
1182
nethercote996901a2004-08-03 13:29:09 +00001183/* Leak detector for this tool. We don't actually do anything, merely
sewardja4495682002-10-21 07:29:59 +00001184 run the generic leak detector with suitable parameters for this
nethercote996901a2004-08-03 13:29:09 +00001185 tool. */
njnb8dca862005-03-14 02:42:44 +00001186static void ac_detect_memory_leaks ( ThreadId tid, LeakCheckMode mode )
njn25e49d8e72002-09-23 09:36:25 +00001187{
njnb8dca862005-03-14 02:42:44 +00001188 MAC_(do_detect_memory_leaks) ( tid, mode, ac_is_valid_64k_chunk, ac_is_valid_address );
njn25e49d8e72002-09-23 09:36:25 +00001189}
1190
1191
1192/* ---------------------------------------------------------------------
1193 Sanity check machinery (permanently engaged).
1194 ------------------------------------------------------------------ */
1195
njn51d827b2005-05-09 01:02:08 +00001196static Bool ac_cheap_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00001197{
jseward9800fd32004-01-04 23:08:04 +00001198 /* nothing useful we can rapidly check */
1199 return True;
njn25e49d8e72002-09-23 09:36:25 +00001200}
1201
njn51d827b2005-05-09 01:02:08 +00001202static Bool ac_expensive_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00001203{
1204 Int i;
1205
sewardjb5f6f512005-03-10 23:59:00 +00001206#if 0
njn25e49d8e72002-09-23 09:36:25 +00001207 /* Make sure nobody changed the distinguished secondary. */
1208 for (i = 0; i < 8192; i++)
1209 if (distinguished_secondary_map.abits[i] != VGM_BYTE_INVALID)
1210 return False;
sewardjb5f6f512005-03-10 23:59:00 +00001211#endif
njn25e49d8e72002-09-23 09:36:25 +00001212
1213 /* Make sure that the upper 3/4 of the primary map hasn't
1214 been messed with. */
sewardjb5f6f512005-03-10 23:59:00 +00001215 for (i = PRIMARY_SIZE; i < PRIMARY_SIZE*4; i++)
1216 if (primary_map[i] != DSM_NOTADDR)
njn25e49d8e72002-09-23 09:36:25 +00001217 return False;
1218
1219 return True;
1220}
1221
njn47363ab2003-04-21 13:24:40 +00001222/*------------------------------------------------------------*/
1223/*--- Client requests ---*/
1224/*------------------------------------------------------------*/
1225
njn51d827b2005-05-09 01:02:08 +00001226static Bool ac_handle_client_request ( ThreadId tid, UWord* arg, UWord *ret )
sewardjd8033d92002-12-08 22:16:58 +00001227{
sewardjbf310d92002-12-28 13:09:57 +00001228#define IGNORE(what) \
1229 do { \
1230 if (moans-- > 0) { \
1231 VG_(message)(Vg_UserMsg, \
njn02bc4b82005-05-15 17:28:26 +00001232 "Warning: Addrcheck: ignoring '%s' request.", what); \
sewardjbf310d92002-12-28 13:09:57 +00001233 VG_(message)(Vg_UserMsg, \
nethercote137bc552003-11-14 17:47:54 +00001234 " To honour this request, rerun with --tool=memcheck."); \
sewardjbf310d92002-12-28 13:09:57 +00001235 } \
1236 } while (0)
1237
sewardjbf310d92002-12-28 13:09:57 +00001238 static Int moans = 3;
sewardjd8033d92002-12-08 22:16:58 +00001239
1240 /* Overload memcheck client reqs */
njnfc26ff92004-11-22 19:12:49 +00001241 if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
sewardjd62e03b2004-12-10 12:01:14 +00001242 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
1243 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
1244 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
1245 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
1246 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
1247 && VG_USERREQ__MEMPOOL_FREE != arg[0])
sewardjd8033d92002-12-08 22:16:58 +00001248 return False;
1249
1250 switch (arg[0]) {
1251 case VG_USERREQ__DO_LEAK_CHECK:
njnb8dca862005-03-14 02:42:44 +00001252 ac_detect_memory_leaks(tid, arg[1] ? LC_Summary : LC_Full);
sewardjd8033d92002-12-08 22:16:58 +00001253 *ret = 0; /* return value is meaningless */
1254 break;
1255
sewardjbf310d92002-12-28 13:09:57 +00001256 /* Ignore these */
sewardjd8033d92002-12-08 22:16:58 +00001257 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
sewardjbf310d92002-12-28 13:09:57 +00001258 IGNORE("VALGRIND_CHECK_WRITABLE");
1259 return False;
sewardjd8033d92002-12-08 22:16:58 +00001260 case VG_USERREQ__CHECK_READABLE: /* check readable */
sewardjbf310d92002-12-28 13:09:57 +00001261 IGNORE("VALGRIND_CHECK_READABLE");
1262 return False;
sewardjd8033d92002-12-08 22:16:58 +00001263 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
sewardjbf310d92002-12-28 13:09:57 +00001264 IGNORE("VALGRIND_MAKE_NOACCESS");
1265 return False;
sewardjd8033d92002-12-08 22:16:58 +00001266 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
sewardjbf310d92002-12-28 13:09:57 +00001267 IGNORE("VALGRIND_MAKE_WRITABLE");
1268 return False;
sewardjd8033d92002-12-08 22:16:58 +00001269 case VG_USERREQ__MAKE_READABLE: /* make readable */
sewardjbf310d92002-12-28 13:09:57 +00001270 IGNORE("VALGRIND_MAKE_READABLE");
1271 return False;
sewardjd8033d92002-12-08 22:16:58 +00001272 case VG_USERREQ__DISCARD: /* discard */
sewardjbf310d92002-12-28 13:09:57 +00001273 IGNORE("VALGRIND_CHECK_DISCARD");
1274 return False;
sewardjd8033d92002-12-08 22:16:58 +00001275
1276 default:
nethercoted1b64b22004-11-04 18:22:28 +00001277 if (MAC_(handle_common_client_requests)(tid, arg, ret )) {
njn47363ab2003-04-21 13:24:40 +00001278 return True;
1279 } else {
1280 VG_(message)(Vg_UserMsg,
nethercoted1b64b22004-11-04 18:22:28 +00001281 "Warning: unknown addrcheck client request code %llx",
1282 (ULong)arg[0]);
njn47363ab2003-04-21 13:24:40 +00001283 return False;
1284 }
sewardjd8033d92002-12-08 22:16:58 +00001285 }
1286 return True;
sewardjbf310d92002-12-28 13:09:57 +00001287
1288#undef IGNORE
sewardjd8033d92002-12-08 22:16:58 +00001289}
1290
njn25e49d8e72002-09-23 09:36:25 +00001291/*------------------------------------------------------------*/
1292/*--- Setup ---*/
1293/*------------------------------------------------------------*/
1294
njn51d827b2005-05-09 01:02:08 +00001295static Bool ac_process_cmd_line_option(Char* arg)
njn25e49d8e72002-09-23 09:36:25 +00001296{
njn43c799e2003-04-08 00:08:52 +00001297 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001298}
1299
njn51d827b2005-05-09 01:02:08 +00001300static void ac_print_usage(void)
njn25e49d8e72002-09-23 09:36:25 +00001301{
njn3e884182003-04-15 13:03:23 +00001302 MAC_(print_common_usage)();
1303}
1304
njn51d827b2005-05-09 01:02:08 +00001305static void ac_print_debug_usage(void)
njn3e884182003-04-15 13:03:23 +00001306{
1307 MAC_(print_common_debug_usage)();
njn25e49d8e72002-09-23 09:36:25 +00001308}
1309
1310
1311/*------------------------------------------------------------*/
njn51d827b2005-05-09 01:02:08 +00001312/*--- Setup and finalisation ---*/
njn25e49d8e72002-09-23 09:36:25 +00001313/*------------------------------------------------------------*/
1314
njn51d827b2005-05-09 01:02:08 +00001315static void ac_post_clo_init ( void )
1316{
1317}
1318
1319static void ac_fini ( Int exitcode )
1320{
1321 MAC_(common_fini)( ac_detect_memory_leaks );
1322}
1323
1324static void ac_pre_clo_init(void)
njn25e49d8e72002-09-23 09:36:25 +00001325{
njn810086f2002-11-14 12:42:47 +00001326 VG_(details_name) ("Addrcheck");
1327 VG_(details_version) (NULL);
1328 VG_(details_description) ("a fine-grained address checker");
1329 VG_(details_copyright_author)(
njn53612422005-03-12 16:22:54 +00001330 "Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.");
nethercote421281e2003-11-20 16:20:55 +00001331 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardj78210aa2002-12-01 02:55:46 +00001332 VG_(details_avg_translation_sizeB) ( 135 );
njn25e49d8e72002-09-23 09:36:25 +00001333
njn51d827b2005-05-09 01:02:08 +00001334 VG_(basic_tool_funcs) (ac_post_clo_init,
1335 ac_instrument,
1336 ac_fini);
njn8a97c6d2005-03-31 04:37:24 +00001337
njn810086f2002-11-14 12:42:47 +00001338 VG_(needs_core_errors) ();
njn51d827b2005-05-09 01:02:08 +00001339 VG_(needs_tool_errors) (MAC_(eq_Error),
1340 ac_pp_Error,
1341 MAC_(update_extra),
1342 MAC_(shared_recognised_suppression),
1343 MAC_(read_extra_suppression_info),
1344 MAC_(error_matches_suppression),
1345 MAC_(get_error_name),
1346 MAC_(print_extra_suppression_info));
njn810086f2002-11-14 12:42:47 +00001347 VG_(needs_libc_freeres) ();
njn51d827b2005-05-09 01:02:08 +00001348 VG_(needs_command_line_options)(MAC_(process_common_cmd_line_option),
1349 MAC_(print_common_usage),
1350 MAC_(print_common_debug_usage));
1351 VG_(needs_client_requests) (ac_handle_client_request);
1352 VG_(needs_sanity_checks) (ac_cheap_sanity_check,
1353 ac_expensive_sanity_check);
fitzhardinge98abfc72003-12-16 02:05:15 +00001354 VG_(needs_shadow_memory) ();
njn25e49d8e72002-09-23 09:36:25 +00001355
njnfc51f8d2005-06-21 03:20:17 +00001356 VG_(needs_malloc_replacement) (MAC_(malloc),
njn51d827b2005-05-09 01:02:08 +00001357 MAC_(__builtin_new),
1358 MAC_(__builtin_vec_new),
1359 MAC_(memalign),
1360 MAC_(calloc),
1361 MAC_(free),
1362 MAC_(__builtin_delete),
1363 MAC_(__builtin_vec_delete),
1364 MAC_(realloc),
1365 MAC_MALLOC_REDZONE_SZB );
njn8a97c6d2005-03-31 04:37:24 +00001366
njn3e884182003-04-15 13:03:23 +00001367 MAC_( new_mem_heap) = & ac_new_mem_heap;
1368 MAC_( ban_mem_heap) = & ac_make_noaccess;
1369 MAC_(copy_mem_heap) = & ac_copy_address_range_state;
1370 MAC_( die_mem_heap) = & ac_make_noaccess;
sewardjecf8e102003-07-12 12:11:39 +00001371 MAC_(check_noaccess) = & ac_check_noaccess;
njn3e884182003-04-15 13:03:23 +00001372
njn51d827b2005-05-09 01:02:08 +00001373 VG_(track_new_mem_startup) ( & ac_new_mem_startup );
1374 VG_(track_new_mem_stack_signal)( & ac_make_accessible );
1375 VG_(track_new_mem_brk) ( & ac_make_accessible );
1376 VG_(track_new_mem_mmap) ( & ac_new_mem_mmap );
njn25e49d8e72002-09-23 09:36:25 +00001377
njn51d827b2005-05-09 01:02:08 +00001378 VG_(track_copy_mem_remap) ( & ac_copy_address_range_state );
njn3e884182003-04-15 13:03:23 +00001379
njn51d827b2005-05-09 01:02:08 +00001380 VG_(track_die_mem_stack_signal)( & ac_make_noaccess );
1381 VG_(track_die_mem_brk) ( & ac_make_noaccess );
1382 VG_(track_die_mem_munmap) ( & ac_make_noaccess );
njn3e884182003-04-15 13:03:23 +00001383
njn51d827b2005-05-09 01:02:08 +00001384 VG_(track_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
1385 VG_(track_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
1386 VG_(track_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
1387 VG_(track_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
1388 VG_(track_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
1389 VG_(track_new_mem_stack) ( & MAC_(new_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001390
njn51d827b2005-05-09 01:02:08 +00001391 VG_(track_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
1392 VG_(track_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
1393 VG_(track_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
1394 VG_(track_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
1395 VG_(track_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
1396 VG_(track_die_mem_stack) ( & MAC_(die_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001397
njn51d827b2005-05-09 01:02:08 +00001398 VG_(track_ban_mem_stack) ( & ac_make_noaccess );
njn25e49d8e72002-09-23 09:36:25 +00001399
njn51d827b2005-05-09 01:02:08 +00001400 VG_(track_pre_mem_read) ( & ac_check_is_readable );
1401 VG_(track_pre_mem_read_asciiz) ( & ac_check_is_readable_asciiz );
1402 VG_(track_pre_mem_write) ( & ac_check_is_writable );
1403 VG_(track_post_mem_write) ( & ac_post_mem_write );
njn25e49d8e72002-09-23 09:36:25 +00001404
njn31066fd2005-03-26 00:42:02 +00001405 VG_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
1406 VG_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
1407 VG_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
njnd04b7c62002-10-03 14:05:52 +00001408
1409 init_shadow_memory();
njn3e884182003-04-15 13:03:23 +00001410 MAC_(common_pre_clo_init)();
njn5c004e42002-11-18 11:04:50 +00001411}
1412
njn51d827b2005-05-09 01:02:08 +00001413VG_DETERMINE_INTERFACE_VERSION(ac_pre_clo_init, 1./8)
fitzhardinge98abfc72003-12-16 02:05:15 +00001414
1415
njn25e49d8e72002-09-23 09:36:25 +00001416/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00001417/*--- end ac_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00001418/*--------------------------------------------------------------------*/