blob: db05274b7525c4b280893dc8be2fe654993bee2c [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
njn5db32122005-08-12 15:23:57 +000045#if 0
njn9b007f62003-04-07 14:40:25 +000046
njn25e49d8e72002-09-23 09:36:25 +000047/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000048/*--- Comparing and printing errors ---*/
49/*------------------------------------------------------------*/
50
njn51d827b2005-05-09 01:02:08 +000051static void ac_pp_Error ( Error* err )
njn25e49d8e72002-09-23 09:36:25 +000052{
njn43c799e2003-04-08 00:08:52 +000053 MAC_Error* err_extra = VG_(get_error_extra)(err);
njn25e49d8e72002-09-23 09:36:25 +000054
njn810086f2002-11-14 12:42:47 +000055 switch (VG_(get_error_kind)(err)) {
njn25e49d8e72002-09-23 09:36:25 +000056 case CoreMemErr:
njn43c799e2003-04-08 00:08:52 +000057 VG_(message)(Vg_UserMsg, "%s contains unaddressable byte(s)",
58 VG_(get_error_string)(err));
59 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
njn25e49d8e72002-09-23 09:36:25 +000060 break;
61
njn25e49d8e72002-09-23 09:36:25 +000062 case ParamErr:
njn43c799e2003-04-08 00:08:52 +000063 VG_(message)(Vg_UserMsg,
64 "Syscall param %s contains unaddressable byte(s)",
65 VG_(get_error_string)(err) );
66 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
67 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
njn25e49d8e72002-09-23 09:36:25 +000068 break;
69
70 case UserErr:
njn43c799e2003-04-08 00:08:52 +000071 VG_(message)(Vg_UserMsg,
72 "Unaddressable byte(s) found during client check request");
73 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
74 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
njn25e49d8e72002-09-23 09:36:25 +000075 break;
76
77 default:
njnb126f732004-11-22 17:57:07 +000078 MAC_(pp_shared_Error)(err);
njn43c799e2003-04-08 00:08:52 +000079 break;
njn25e49d8e72002-09-23 09:36:25 +000080 }
81}
82
83/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000084/*--- Suppressions ---*/
85/*------------------------------------------------------------*/
86
njn51d827b2005-05-09 01:02:08 +000087static Bool ac_recognised_suppression ( Char* name, Supp* su )
njn25e49d8e72002-09-23 09:36:25 +000088{
njn43c799e2003-04-08 00:08:52 +000089 return MAC_(shared_recognised_suppression)(name, su);
njn25e49d8e72002-09-23 09:36:25 +000090}
91
njn5c004e42002-11-18 11:04:50 +000092#define DEBUG(fmt, args...) //VG_(printf)(fmt, ## args)
93
njn25e49d8e72002-09-23 09:36:25 +000094/*------------------------------------------------------------*/
95/*--- Low-level support for memory checking. ---*/
96/*------------------------------------------------------------*/
97
98/* All reads and writes are checked against a memory map, which
99 records the state of all memory in the process. The memory map is
100 organised like this:
101
102 The top 16 bits of an address are used to index into a top-level
103 map table, containing 65536 entries. Each entry is a pointer to a
104 second-level map, which records the accesibililty and validity
105 permissions for the 65536 bytes indexed by the lower 16 bits of the
106 address. Each byte is represented by one bit, indicating
107 accessibility. So each second-level map contains 8192 bytes. This
108 two-level arrangement conveniently divides the 4G address space
109 into 64k lumps, each size 64k bytes.
110
111 All entries in the primary (top-level) map must point to a valid
112 secondary (second-level) map. Since most of the 4G of address
113 space will not be in use -- ie, not mapped at all -- there is a
njn02bc4b82005-05-15 17:28:26 +0000114 distinguished secondary map, which indicates 'not addressible and
njn25e49d8e72002-09-23 09:36:25 +0000115 not valid' writeable for all bytes. Entries in the primary map for
116 which the entire 64k is not in use at all point at this
117 distinguished map.
118
119 [...] lots of stuff deleted due to out of date-ness
120
121 As a final optimisation, the alignment and address checks for
122 4-byte loads and stores are combined in a neat way. The primary
123 map is extended to have 262144 entries (2^18), rather than 2^16.
124 The top 3/4 of these entries are permanently set to the
125 distinguished secondary map. For a 4-byte load/store, the
126 top-level map is indexed not with (addr >> 16) but instead f(addr),
127 where
128
129 f( XXXX XXXX XXXX XXXX ____ ____ ____ __YZ )
130 = ____ ____ ____ __YZ XXXX XXXX XXXX XXXX or
131 = ____ ____ ____ __ZY XXXX XXXX XXXX XXXX
132
133 ie the lowest two bits are placed above the 16 high address bits.
134 If either of these two bits are nonzero, the address is misaligned;
135 this will select a secondary map from the upper 3/4 of the primary
136 map. Because this is always the distinguished secondary map, a
137 (bogus) address check failure will result. The failure handling
138 code can then figure out whether this is a genuine addr check
139 failure or whether it is a possibly-legitimate access at a
140 misaligned address. */
141
142
143/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000144/*--- Function declarations. ---*/
145/*------------------------------------------------------------*/
146
njnc2699f62003-09-05 23:29:33 +0000147static void ac_ACCESS4_SLOWLY ( Addr a, Bool isWrite );
148static void ac_ACCESS2_SLOWLY ( Addr a, Bool isWrite );
149static void ac_ACCESS1_SLOWLY ( Addr a, Bool isWrite );
nethercote928a5f72004-11-03 18:10:37 +0000150static void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, SizeT size, Bool isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000151
152/*------------------------------------------------------------*/
153/*--- Data defns. ---*/
154/*------------------------------------------------------------*/
155
156typedef
157 struct {
sewardjb5f6f512005-03-10 23:59:00 +0000158 UChar abits[SECONDARY_SIZE / 8];
njn25e49d8e72002-09-23 09:36:25 +0000159 }
160 AcSecMap;
161
sewardjb5f6f512005-03-10 23:59:00 +0000162static AcSecMap* primary_map[ /*PRIMARY_SIZE*/ PRIMARY_SIZE*4 ];
163static const AcSecMap distinguished_secondary_maps[2] = {
164 [ VGM_BIT_INVALID ] = { { [0 ... (SECONDARY_SIZE/8) - 1] = VGM_BYTE_INVALID } },
165 [ VGM_BIT_VALID ] = { { [0 ... (SECONDARY_SIZE/8) - 1] = VGM_BYTE_VALID } },
166};
167#define N_SECONDARY_MAPS (sizeof(distinguished_secondary_maps)/sizeof(*distinguished_secondary_maps))
168
169#define DSM_IDX(a) ((a) & 1)
170
171#define DSM(a) ((AcSecMap *)&distinguished_secondary_maps[DSM_IDX(a)])
172
173#define DSM_NOTADDR DSM(VGM_BIT_INVALID)
174#define DSM_ADDR DSM(VGM_BIT_VALID)
njn25e49d8e72002-09-23 09:36:25 +0000175
njn25e49d8e72002-09-23 09:36:25 +0000176static void init_shadow_memory ( void )
177{
sewardjb5f6f512005-03-10 23:59:00 +0000178 Int i, a;
njn25e49d8e72002-09-23 09:36:25 +0000179
sewardjb5f6f512005-03-10 23:59:00 +0000180 /* check construction of the distinguished secondaries */
sewardj76754cf2005-03-14 00:14:04 +0000181 tl_assert(VGM_BIT_INVALID == 1);
182 tl_assert(VGM_BIT_VALID == 0);
sewardjb5f6f512005-03-10 23:59:00 +0000183
184 for(a = 0; a <= 1; a++)
sewardj76754cf2005-03-14 00:14:04 +0000185 tl_assert(distinguished_secondary_maps[DSM_IDX(a)].abits[0] == BIT_EXPAND(a));
njn25e49d8e72002-09-23 09:36:25 +0000186
187 /* These entries gradually get overwritten as the used address
188 space expands. */
sewardjb5f6f512005-03-10 23:59:00 +0000189 for (i = 0; i < PRIMARY_SIZE; i++)
190 primary_map[i] = DSM_NOTADDR;
njn25e49d8e72002-09-23 09:36:25 +0000191
192 /* These ones should never change; it's a bug in Valgrind if they do. */
sewardjb5f6f512005-03-10 23:59:00 +0000193 for (i = PRIMARY_SIZE; i < PRIMARY_SIZE*4; i++)
194 primary_map[i] = DSM_NOTADDR;
njn25e49d8e72002-09-23 09:36:25 +0000195}
196
njn25e49d8e72002-09-23 09:36:25 +0000197/*------------------------------------------------------------*/
198/*--- Basic bitmap management, reading and writing. ---*/
199/*------------------------------------------------------------*/
200
201/* Allocate and initialise a secondary map. */
202
203static AcSecMap* alloc_secondary_map ( __attribute__ ((unused))
sewardjb5f6f512005-03-10 23:59:00 +0000204 Char* caller,
205 const AcSecMap *prototype)
njn25e49d8e72002-09-23 09:36:25 +0000206{
207 AcSecMap* map;
njn0da7ac62005-07-19 21:11:54 +0000208 PROF_EVENT(10, "");
njn25e49d8e72002-09-23 09:36:25 +0000209
fitzhardinge98abfc72003-12-16 02:05:15 +0000210 map = (AcSecMap *)VG_(shadow_alloc)(sizeof(AcSecMap));
sewardjb5f6f512005-03-10 23:59:00 +0000211 VG_(memcpy)(map, prototype, sizeof(*map));
njn25e49d8e72002-09-23 09:36:25 +0000212
213 /* VG_(printf)("ALLOC_2MAP(%s)\n", caller ); */
214 return map;
215}
216
217
218/* Basic reading/writing of the bitmaps, for byte-sized accesses. */
219
220static __inline__ UChar get_abit ( Addr a )
221{
sewardjb5f6f512005-03-10 23:59:00 +0000222 AcSecMap* sm = primary_map[PM_IDX(a)];
223 UInt sm_off = SM_OFF(a);
njn0da7ac62005-07-19 21:11:54 +0000224 PROF_EVENT(20, "");
njn25e49d8e72002-09-23 09:36:25 +0000225# if 0
226 if (IS_DISTINGUISHED_SM(sm))
227 VG_(message)(Vg_DebugMsg,
228 "accessed distinguished 2ndary (A)map! 0x%x\n", a);
229# endif
230 return BITARR_TEST(sm->abits, sm_off)
231 ? VGM_BIT_INVALID : VGM_BIT_VALID;
232}
233
sewardj56867352003-10-12 10:27:06 +0000234static /* __inline__ */ void set_abit ( Addr a, UChar abit )
njn25e49d8e72002-09-23 09:36:25 +0000235{
236 AcSecMap* sm;
237 UInt sm_off;
njn0da7ac62005-07-19 21:11:54 +0000238 PROF_EVENT(22, "");
njn25e49d8e72002-09-23 09:36:25 +0000239 ENSURE_MAPPABLE(a, "set_abit");
sewardjb5f6f512005-03-10 23:59:00 +0000240 sm = primary_map[PM_IDX(a)];
241 sm_off = SM_OFF(a);
njn25e49d8e72002-09-23 09:36:25 +0000242 if (abit)
243 BITARR_SET(sm->abits, sm_off);
244 else
245 BITARR_CLEAR(sm->abits, sm_off);
246}
247
248
249/* Reading/writing of the bitmaps, for aligned word-sized accesses. */
250
251static __inline__ UChar get_abits4_ALIGNED ( Addr a )
252{
253 AcSecMap* sm;
254 UInt sm_off;
255 UChar abits8;
njn0da7ac62005-07-19 21:11:54 +0000256 PROF_EVENT(24, "");
njn25e49d8e72002-09-23 09:36:25 +0000257# ifdef VG_DEBUG_MEMORY
njnbe91aae2005-03-27 01:42:41 +0000258 tl_assert(VG_IS_4_ALIGNED(a));
njn25e49d8e72002-09-23 09:36:25 +0000259# endif
sewardjb5f6f512005-03-10 23:59:00 +0000260 sm = primary_map[PM_IDX(a)];
261 sm_off = SM_OFF(a);
njn25e49d8e72002-09-23 09:36:25 +0000262 abits8 = sm->abits[sm_off >> 3];
263 abits8 >>= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
264 abits8 &= 0x0F;
265 return abits8;
266}
267
268
269
270/*------------------------------------------------------------*/
271/*--- Setting permissions over address ranges. ---*/
272/*------------------------------------------------------------*/
273
sewardj56867352003-10-12 10:27:06 +0000274static /* __inline__ */
nethercote451eae92004-11-02 13:06:32 +0000275void set_address_range_perms ( Addr a, SizeT len, UInt example_a_bit )
njn25e49d8e72002-09-23 09:36:25 +0000276{
277 UChar abyte8;
278 UInt sm_off;
279 AcSecMap* sm;
280
njn0da7ac62005-07-19 21:11:54 +0000281 PROF_EVENT(30, "");
njn25e49d8e72002-09-23 09:36:25 +0000282
283 if (len == 0)
284 return;
285
286 if (len > 100 * 1000 * 1000) {
287 VG_(message)(Vg_UserMsg,
288 "Warning: set address range perms: "
289 "large range %u, a %d",
290 len, example_a_bit );
291 }
292
293 VGP_PUSHCC(VgpSetMem);
294
295 /* Requests to change permissions of huge address ranges may
296 indicate bugs in our machinery. 30,000,000 is arbitrary, but so
297 far all legitimate requests have fallen beneath that size. */
298 /* 4 Mar 02: this is just stupid; get rid of it. */
njnca82cc02004-11-22 17:18:48 +0000299 /* tl_assert(len < 30000000); */
njn25e49d8e72002-09-23 09:36:25 +0000300
301 /* Check the permissions make sense. */
njnca82cc02004-11-22 17:18:48 +0000302 tl_assert(example_a_bit == VGM_BIT_VALID
njn25e49d8e72002-09-23 09:36:25 +0000303 || example_a_bit == VGM_BIT_INVALID);
304
305 /* In order that we can charge through the address space at 8
306 bytes/main-loop iteration, make up some perms. */
sewardjb5f6f512005-03-10 23:59:00 +0000307 abyte8 = BIT_EXPAND(example_a_bit);
njn25e49d8e72002-09-23 09:36:25 +0000308
309# ifdef VG_DEBUG_MEMORY
310 /* Do it ... */
311 while (True) {
njn0da7ac62005-07-19 21:11:54 +0000312 PROF_EVENT(31, "");
njn25e49d8e72002-09-23 09:36:25 +0000313 if (len == 0) break;
314 set_abit ( a, example_a_bit );
315 set_vbyte ( a, vbyte );
316 a++;
317 len--;
318 }
319
320# else
321 /* Slowly do parts preceding 8-byte alignment. */
322 while (True) {
njn0da7ac62005-07-19 21:11:54 +0000323 PROF_EVENT(31, "");
njn25e49d8e72002-09-23 09:36:25 +0000324 if (len == 0) break;
325 if ((a % 8) == 0) break;
326 set_abit ( a, example_a_bit );
327 a++;
328 len--;
329 }
330
331 if (len == 0) {
332 VGP_POPCC(VgpSetMem);
333 return;
334 }
njnca82cc02004-11-22 17:18:48 +0000335 tl_assert((a % 8) == 0 && len > 0);
njn25e49d8e72002-09-23 09:36:25 +0000336
sewardjb5f6f512005-03-10 23:59:00 +0000337 /* Once aligned, go fast up to primary boundary. */
338 for (; (a & SECONDARY_MASK) && len >= 8; a += 8, len -= 8) {
njn0da7ac62005-07-19 21:11:54 +0000339 PROF_EVENT(32, "");
sewardjb5f6f512005-03-10 23:59:00 +0000340
341 /* If the primary is already pointing to a distinguished map
342 with the same properties as we're trying to set, then leave
343 it that way. */
344 if (primary_map[PM_IDX(a)] == DSM(example_a_bit))
345 continue;
njn25e49d8e72002-09-23 09:36:25 +0000346 ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
sewardjb5f6f512005-03-10 23:59:00 +0000347 sm = primary_map[PM_IDX(a)];
348 sm_off = SM_OFF(a);
njn25e49d8e72002-09-23 09:36:25 +0000349 sm->abits[sm_off >> 3] = abyte8;
njn25e49d8e72002-09-23 09:36:25 +0000350 }
351
sewardjb5f6f512005-03-10 23:59:00 +0000352 /* Now set whole secondary maps to the right distinguished value.
353
354 Note that if the primary already points to a non-distinguished
355 secondary, then don't replace the reference. That would just
356 leak memory.
357 */
358 for(; len >= SECONDARY_SIZE; a += SECONDARY_SIZE, len -= SECONDARY_SIZE) {
359 sm = primary_map[PM_IDX(a)];
360
361 if (IS_DISTINGUISHED_SM(sm))
362 primary_map[PM_IDX(a)] = DSM(example_a_bit);
363 else
364 VG_(memset)(sm->abits, abyte8, sizeof(sm->abits));
njn25e49d8e72002-09-23 09:36:25 +0000365 }
sewardjb5f6f512005-03-10 23:59:00 +0000366
367 /* Now finished the remains. */
368 for (; len >= 8; a += 8, len -= 8) {
njn0da7ac62005-07-19 21:11:54 +0000369 PROF_EVENT(32, "");
sewardjb5f6f512005-03-10 23:59:00 +0000370
371 /* If the primary is already pointing to a distinguished map
372 with the same properties as we're trying to set, then leave
373 it that way. */
374 if (primary_map[PM_IDX(a)] == DSM(example_a_bit))
375 continue;
376 ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
377 sm = primary_map[PM_IDX(a)];
378 sm_off = SM_OFF(a);
379 sm->abits[sm_off >> 3] = abyte8;
380 }
381
njn25e49d8e72002-09-23 09:36:25 +0000382
383 /* Finish the upper fragment. */
384 while (True) {
njn0da7ac62005-07-19 21:11:54 +0000385 PROF_EVENT(33, "");
njn25e49d8e72002-09-23 09:36:25 +0000386 if (len == 0) break;
387 set_abit ( a, example_a_bit );
388 a++;
389 len--;
390 }
391# endif
392
njn25e49d8e72002-09-23 09:36:25 +0000393 VGP_POPCC(VgpSetMem);
394}
395
396/* Set permissions for address ranges ... */
397
nethercote451eae92004-11-02 13:06:32 +0000398static void ac_make_noaccess ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000399{
njn0da7ac62005-07-19 21:11:54 +0000400 PROF_EVENT(35, "");
njn5c004e42002-11-18 11:04:50 +0000401 DEBUG("ac_make_noaccess(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000402 set_address_range_perms ( a, len, VGM_BIT_INVALID );
403}
404
nethercote451eae92004-11-02 13:06:32 +0000405static void ac_make_accessible ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000406{
njn0da7ac62005-07-19 21:11:54 +0000407 PROF_EVENT(38, "");
njn5c004e42002-11-18 11:04:50 +0000408 DEBUG("ac_make_accessible(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000409 set_address_range_perms ( a, len, VGM_BIT_VALID );
410}
411
njn9b007f62003-04-07 14:40:25 +0000412static __inline__
413void make_aligned_word_noaccess(Addr a)
414{
415 AcSecMap* sm;
416 UInt sm_off;
417 UChar mask;
418
419 VGP_PUSHCC(VgpESPAdj);
420 ENSURE_MAPPABLE(a, "make_aligned_word_noaccess");
sewardjb5f6f512005-03-10 23:59:00 +0000421 sm = primary_map[PM_IDX(a)];
422 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000423 mask = 0x0F;
424 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
425 /* mask now contains 1s where we wish to make address bits invalid (1s). */
426 sm->abits[sm_off >> 3] |= mask;
427 VGP_POPCC(VgpESPAdj);
428}
429
430static __inline__
431void make_aligned_word_accessible(Addr a)
432{
433 AcSecMap* sm;
434 UInt sm_off;
435 UChar mask;
436
437 VGP_PUSHCC(VgpESPAdj);
438 ENSURE_MAPPABLE(a, "make_aligned_word_accessible");
sewardjb5f6f512005-03-10 23:59:00 +0000439 sm = primary_map[PM_IDX(a)];
440 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000441 mask = 0x0F;
442 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
443 /* mask now contains 1s where we wish to make address bits
444 invalid (0s). */
445 sm->abits[sm_off >> 3] &= ~mask;
446 VGP_POPCC(VgpESPAdj);
447}
448
449/* Nb: by "aligned" here we mean 8-byte aligned */
450static __inline__
451void make_aligned_doubleword_accessible(Addr a)
452{
453 AcSecMap* sm;
454 UInt sm_off;
455
456 VGP_PUSHCC(VgpESPAdj);
457 ENSURE_MAPPABLE(a, "make_aligned_doubleword_accessible");
sewardjb5f6f512005-03-10 23:59:00 +0000458 sm = primary_map[PM_IDX(a)];
459 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000460 sm->abits[sm_off >> 3] = VGM_BYTE_VALID;
461 VGP_POPCC(VgpESPAdj);
462}
463
464static __inline__
465void make_aligned_doubleword_noaccess(Addr a)
466{
467 AcSecMap* sm;
468 UInt sm_off;
469
470 VGP_PUSHCC(VgpESPAdj);
471 ENSURE_MAPPABLE(a, "make_aligned_doubleword_noaccess");
sewardjb5f6f512005-03-10 23:59:00 +0000472 sm = primary_map[PM_IDX(a)];
473 sm_off = SM_OFF(a);
njn9b007f62003-04-07 14:40:25 +0000474 sm->abits[sm_off >> 3] = VGM_BYTE_INVALID;
475 VGP_POPCC(VgpESPAdj);
476}
477
478/* The %esp update handling functions */
479ESP_UPDATE_HANDLERS ( make_aligned_word_accessible,
480 make_aligned_word_noaccess,
481 make_aligned_doubleword_accessible,
482 make_aligned_doubleword_noaccess,
483 ac_make_accessible,
484 ac_make_noaccess
485 );
486
487
njn25e49d8e72002-09-23 09:36:25 +0000488/* Block-copy permissions (needed for implementing realloc()). */
489
nethercote451eae92004-11-02 13:06:32 +0000490static void ac_copy_address_range_state ( Addr src, Addr dst, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000491{
492 UInt i;
493
njn5c004e42002-11-18 11:04:50 +0000494 DEBUG("ac_copy_address_range_state\n");
njn25e49d8e72002-09-23 09:36:25 +0000495
njn0da7ac62005-07-19 21:11:54 +0000496 PROF_EVENT(40, "");
njn25e49d8e72002-09-23 09:36:25 +0000497 for (i = 0; i < len; i++) {
498 UChar abit = get_abit ( src+i );
njn0da7ac62005-07-19 21:11:54 +0000499 PROF_EVENT(41, "");
njn25e49d8e72002-09-23 09:36:25 +0000500 set_abit ( dst+i, abit );
501 }
502}
503
504
505/* Check permissions for address range. If inadequate permissions
506 exist, *bad_addr is set to the offending address, so the caller can
507 know what it is. */
508
njn5c004e42002-11-18 11:04:50 +0000509static __inline__
nethercote451eae92004-11-02 13:06:32 +0000510Bool ac_check_accessible ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000511{
512 UInt i;
513 UChar abit;
njn0da7ac62005-07-19 21:11:54 +0000514 PROF_EVENT(48, "");
njn25e49d8e72002-09-23 09:36:25 +0000515 for (i = 0; i < len; i++) {
njn0da7ac62005-07-19 21:11:54 +0000516 PROF_EVENT(49, "");
njn25e49d8e72002-09-23 09:36:25 +0000517 abit = get_abit(a);
518 if (abit == VGM_BIT_INVALID) {
519 if (bad_addr != NULL) *bad_addr = a;
520 return False;
521 }
522 a++;
523 }
524 return True;
525}
526
sewardjecf8e102003-07-12 12:11:39 +0000527/* The opposite; check that an address range is inaccessible. */
528static
nethercote451eae92004-11-02 13:06:32 +0000529Bool ac_check_noaccess ( Addr a, SizeT len, Addr* bad_addr )
sewardjecf8e102003-07-12 12:11:39 +0000530{
531 UInt i;
532 UChar abit;
njn0da7ac62005-07-19 21:11:54 +0000533 PROF_EVENT(48, "");
sewardjecf8e102003-07-12 12:11:39 +0000534 for (i = 0; i < len; i++) {
njn0da7ac62005-07-19 21:11:54 +0000535 PROF_EVENT(49, "");
sewardjecf8e102003-07-12 12:11:39 +0000536 abit = get_abit(a);
537 if (abit == VGM_BIT_VALID) {
538 if (bad_addr != NULL) *bad_addr = a;
539 return False;
540 }
541 a++;
542 }
543 return True;
544}
545
njn25e49d8e72002-09-23 09:36:25 +0000546/* Check a zero-terminated ascii string. Tricky -- don't want to
547 examine the actual bytes, to find the end, until we're sure it is
548 safe to do so. */
549
njn5c004e42002-11-18 11:04:50 +0000550static __inline__
551Bool ac_check_readable_asciiz ( Addr a, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000552{
553 UChar abit;
njn0da7ac62005-07-19 21:11:54 +0000554 PROF_EVENT(46, "");
njn5c004e42002-11-18 11:04:50 +0000555 DEBUG("ac_check_readable_asciiz\n");
njn25e49d8e72002-09-23 09:36:25 +0000556 while (True) {
njn0da7ac62005-07-19 21:11:54 +0000557 PROF_EVENT(47, "");
njn25e49d8e72002-09-23 09:36:25 +0000558 abit = get_abit(a);
559 if (abit != VGM_BIT_VALID) {
560 if (bad_addr != NULL) *bad_addr = a;
561 return False;
562 }
563 /* Ok, a is safe to read. */
564 if (* ((UChar*)a) == 0) return True;
565 a++;
566 }
567}
568
569
570/*------------------------------------------------------------*/
571/*--- Memory event handlers ---*/
572/*------------------------------------------------------------*/
573
njn5c004e42002-11-18 11:04:50 +0000574static __inline__
njn72718642003-07-24 08:45:32 +0000575void ac_check_is_accessible ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000576 Char* s, Addr base, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000577{
578 Bool ok;
njn86f12dc2005-03-14 01:16:05 +0000579 Addr bad_addr = 0; // Initialise to shut gcc up
njn25e49d8e72002-09-23 09:36:25 +0000580
581 VGP_PUSHCC(VgpCheckMem);
582
njn5c004e42002-11-18 11:04:50 +0000583 ok = ac_check_accessible ( base, size, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000584 if (!ok) {
585 switch (part) {
586 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +0000587 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
588 /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000589 break;
590
njn25e49d8e72002-09-23 09:36:25 +0000591 case Vg_CoreSignal:
njnca82cc02004-11-22 17:18:48 +0000592 tl_assert(isWrite); /* Should only happen with isWrite case */
njn5c004e42002-11-18 11:04:50 +0000593 /* fall through */
njn25e49d8e72002-09-23 09:36:25 +0000594 case Vg_CorePThread:
nethercote8b76fe52004-11-08 19:20:09 +0000595 MAC_(record_core_mem_error)( tid, /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000596 break;
597
598 /* If we're being asked to jump to a silly address, record an error
599 message before potentially crashing the entire system. */
600 case Vg_CoreTranslate:
njnca82cc02004-11-22 17:18:48 +0000601 tl_assert(!isWrite); /* Should only happen with !isWrite case */
njn72718642003-07-24 08:45:32 +0000602 MAC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000603 break;
604
605 default:
njn67993252004-11-22 18:02:32 +0000606 VG_(tool_panic)("ac_check_is_accessible: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +0000607 }
608 }
njn5c004e42002-11-18 11:04:50 +0000609
njn25e49d8e72002-09-23 09:36:25 +0000610 VGP_POPCC(VgpCheckMem);
611}
612
613static
njn72718642003-07-24 08:45:32 +0000614void ac_check_is_writable ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000615 Char* s, Addr base, SizeT size )
njn5c004e42002-11-18 11:04:50 +0000616{
njn72718642003-07-24 08:45:32 +0000617 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/True );
njn5c004e42002-11-18 11:04:50 +0000618}
619
620static
njn72718642003-07-24 08:45:32 +0000621void ac_check_is_readable ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000622 Char* s, Addr base, SizeT size )
njn5c004e42002-11-18 11:04:50 +0000623{
njn72718642003-07-24 08:45:32 +0000624 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/False );
njn5c004e42002-11-18 11:04:50 +0000625}
626
627static
njn72718642003-07-24 08:45:32 +0000628void ac_check_is_readable_asciiz ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000629 Char* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +0000630{
631 Bool ok = True;
njn86f12dc2005-03-14 01:16:05 +0000632 Addr bad_addr = 0; // Initialise to shut gcc up
njn25e49d8e72002-09-23 09:36:25 +0000633
634 VGP_PUSHCC(VgpCheckMem);
635
njnca82cc02004-11-22 17:18:48 +0000636 tl_assert(part == Vg_CoreSysCall);
njn5c004e42002-11-18 11:04:50 +0000637 ok = ac_check_readable_asciiz ( (Addr)str, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000638 if (!ok) {
nethercote8b76fe52004-11-08 19:20:09 +0000639 MAC_(record_param_error) ( tid, bad_addr, /*IsReg*/False,
640 /*IsUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000641 }
642
643 VGP_POPCC(VgpCheckMem);
644}
645
646static
nethercote451eae92004-11-02 13:06:32 +0000647void ac_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +0000648{
njn1f3a9092002-10-04 09:22:30 +0000649 /* Ignore the permissions, just make it readable. Seems to work... */
njn25e49d8e72002-09-23 09:36:25 +0000650 DEBUG("new_mem_startup(%p, %u, rr=%u, ww=%u, xx=%u)\n", a,len,rr,ww,xx);
njn5c004e42002-11-18 11:04:50 +0000651 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000652}
653
654static
nethercote451eae92004-11-02 13:06:32 +0000655void ac_new_mem_heap ( Addr a, SizeT len, Bool is_inited )
njn25e49d8e72002-09-23 09:36:25 +0000656{
njn5c004e42002-11-18 11:04:50 +0000657 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000658}
659
660static
sewardjb5f6f512005-03-10 23:59:00 +0000661void ac_new_mem_mmap (Addr a, SizeT len, Bool rr, Bool ww, Bool xx)
njn25e49d8e72002-09-23 09:36:25 +0000662{
njn5c004e42002-11-18 11:04:50 +0000663 DEBUG("ac_set_perms(%p, %u, rr=%u ww=%u, xx=%u)\n",
sewardj40f8ebe2002-10-23 21:46:13 +0000664 a, len, rr, ww, xx);
sewardjb5f6f512005-03-10 23:59:00 +0000665 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000666}
667
njncf45fd42004-11-24 16:30:22 +0000668static
669void ac_post_mem_write(CorePart part, ThreadId tid, Addr a, SizeT len)
670{
671 ac_make_accessible(a, len);
672}
673
njn25e49d8e72002-09-23 09:36:25 +0000674
675/*------------------------------------------------------------*/
676/*--- Functions called directly from generated code. ---*/
677/*------------------------------------------------------------*/
678
679static __inline__ UInt rotateRight16 ( UInt x )
680{
681 /* Amazingly, gcc turns this into a single rotate insn. */
682 return (x >> 16) | (x << 16);
683}
684
njn25e49d8e72002-09-23 09:36:25 +0000685static __inline__ UInt shiftRight16 ( UInt x )
686{
687 return x >> 16;
688}
689
690
691/* Read/write 1/2/4 sized V bytes, and emit an address error if
692 needed. */
693
njn5c004e42002-11-18 11:04:50 +0000694/* ac_helperc_ACCESS{1,2,4} handle the common case fast.
njn25e49d8e72002-09-23 09:36:25 +0000695 Under all other circumstances, it defers to the relevant _SLOWLY
696 function, which can handle all situations.
697*/
njnc2699f62003-09-05 23:29:33 +0000698static __inline__ void ac_helperc_ACCESS4 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000699{
700# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000701 return ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000702# else
703 UInt sec_no = rotateRight16(a) & 0x3FFFF;
njnda2e36d2003-09-30 13:33:24 +0000704 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000705 UInt a_off = (SM_OFF(a)) >> 3;
njn25e49d8e72002-09-23 09:36:25 +0000706 UChar abits = sm->abits[a_off];
707 abits >>= (a & 4);
708 abits &= 15;
njn0da7ac62005-07-19 21:11:54 +0000709 PROF_EVENT(66, "");
njn25e49d8e72002-09-23 09:36:25 +0000710 if (abits == VGM_NIBBLE_VALID) {
711 /* Handle common case quickly: a is suitably aligned, is mapped,
712 and is addressible. So just return. */
713 return;
714 } else {
715 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000716 ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000717 }
718# endif
719}
720
njnc2699f62003-09-05 23:29:33 +0000721static __inline__ void ac_helperc_ACCESS2 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000722{
723# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000724 return ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000725# else
726 UInt sec_no = rotateRight16(a) & 0x1FFFF;
727 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000728 UInt a_off = (SM_OFF(a)) >> 3;
njn0da7ac62005-07-19 21:11:54 +0000729 PROF_EVENT(67, "");
njn25e49d8e72002-09-23 09:36:25 +0000730 if (sm->abits[a_off] == VGM_BYTE_VALID) {
731 /* Handle common case quickly. */
732 return;
733 } else {
734 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000735 ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000736 }
737# endif
738}
739
njnc2699f62003-09-05 23:29:33 +0000740static __inline__ void ac_helperc_ACCESS1 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000741{
742# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000743 return ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000744# else
745 UInt sec_no = shiftRight16(a);
746 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000747 UInt a_off = (SM_OFF(a)) >> 3;
njn0da7ac62005-07-19 21:11:54 +0000748 PROF_EVENT(68, "");
njn25e49d8e72002-09-23 09:36:25 +0000749 if (sm->abits[a_off] == VGM_BYTE_VALID) {
750 /* Handle common case quickly. */
751 return;
752 } else {
753 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000754 ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000755 }
756# endif
757}
758
njnaf839f52005-06-23 03:27:57 +0000759VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000760static void ach_LOAD4 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000761{
762 ac_helperc_ACCESS4 ( a, /*isWrite*/False );
763}
njnaf839f52005-06-23 03:27:57 +0000764VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000765static void ach_STORE4 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000766{
767 ac_helperc_ACCESS4 ( a, /*isWrite*/True );
768}
769
njnaf839f52005-06-23 03:27:57 +0000770VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000771static void ach_LOAD2 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000772{
773 ac_helperc_ACCESS2 ( a, /*isWrite*/False );
774}
njnaf839f52005-06-23 03:27:57 +0000775VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000776static void ach_STORE2 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000777{
778 ac_helperc_ACCESS2 ( a, /*isWrite*/True );
779}
780
njnaf839f52005-06-23 03:27:57 +0000781VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000782static void ach_LOAD1 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000783{
784 ac_helperc_ACCESS1 ( a, /*isWrite*/False );
785}
njnaf839f52005-06-23 03:27:57 +0000786VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000787static void ach_STORE1 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000788{
789 ac_helperc_ACCESS1 ( a, /*isWrite*/True );
790}
791
njn25e49d8e72002-09-23 09:36:25 +0000792
793/*------------------------------------------------------------*/
794/*--- Fallback functions to handle cases that the above ---*/
njnc2699f62003-09-05 23:29:33 +0000795/*--- ac_helperc_ACCESS{1,2,4} can't manage. ---*/
njn25e49d8e72002-09-23 09:36:25 +0000796/*------------------------------------------------------------*/
797
njnc2699f62003-09-05 23:29:33 +0000798static void ac_ACCESS4_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000799{
800 Bool a0ok, a1ok, a2ok, a3ok;
801
njn0da7ac62005-07-19 21:11:54 +0000802 PROF_EVENT(76, "");
njn25e49d8e72002-09-23 09:36:25 +0000803
804 /* First establish independently the addressibility of the 4 bytes
805 involved. */
806 a0ok = get_abit(a+0) == VGM_BIT_VALID;
807 a1ok = get_abit(a+1) == VGM_BIT_VALID;
808 a2ok = get_abit(a+2) == VGM_BIT_VALID;
809 a3ok = get_abit(a+3) == VGM_BIT_VALID;
810
811 /* Now distinguish 3 cases */
812
813 /* Case 1: the address is completely valid, so:
814 - no addressing error
815 */
816 if (a0ok && a1ok && a2ok && a3ok) {
817 return;
818 }
819
820 /* Case 2: the address is completely invalid.
821 - emit addressing error
822 */
823 /* VG_(printf)("%p (%d %d %d %d)\n", a, a0ok, a1ok, a2ok, a3ok); */
njn43c799e2003-04-08 00:08:52 +0000824 if (!MAC_(clo_partial_loads_ok)
njn25e49d8e72002-09-23 09:36:25 +0000825 || ((a & 3) != 0)
826 || (!a0ok && !a1ok && !a2ok && !a3ok)) {
sewardj76754cf2005-03-14 00:14:04 +0000827 MAC_(record_address_error)( VG_(get_running_tid)(), a, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000828 return;
829 }
830
831 /* Case 3: the address is partially valid.
832 - no addressing error
njn43c799e2003-04-08 00:08:52 +0000833 Case 3 is only allowed if MAC_(clo_partial_loads_ok) is True
njn25e49d8e72002-09-23 09:36:25 +0000834 (which is the default), and the address is 4-aligned.
835 If not, Case 2 will have applied.
836 */
njnca82cc02004-11-22 17:18:48 +0000837 tl_assert(MAC_(clo_partial_loads_ok));
njn25e49d8e72002-09-23 09:36:25 +0000838 {
839 return;
840 }
841}
842
njnc2699f62003-09-05 23:29:33 +0000843static void ac_ACCESS2_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000844{
845 /* Check the address for validity. */
846 Bool aerr = False;
njn0da7ac62005-07-19 21:11:54 +0000847 PROF_EVENT(77, "");
njn25e49d8e72002-09-23 09:36:25 +0000848
849 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
850 if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
851
852 /* If an address error has happened, report it. */
853 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000854 MAC_(record_address_error)( VG_(get_running_tid)(), a, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000855 }
856}
857
njnc2699f62003-09-05 23:29:33 +0000858static void ac_ACCESS1_SLOWLY ( Addr a, Bool isWrite)
njn25e49d8e72002-09-23 09:36:25 +0000859{
860 /* Check the address for validity. */
861 Bool aerr = False;
njn0da7ac62005-07-19 21:11:54 +0000862 PROF_EVENT(78, "");
njn25e49d8e72002-09-23 09:36:25 +0000863
864 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
865
866 /* If an address error has happened, report it. */
867 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000868 MAC_(record_address_error)( VG_(get_running_tid)(), a, 1, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000869 }
870}
871
872
873/* ---------------------------------------------------------------------
874 FPU load and store checks, called from generated code.
875 ------------------------------------------------------------------ */
876
sewardj56867352003-10-12 10:27:06 +0000877static
nethercote928a5f72004-11-03 18:10:37 +0000878void ac_fpu_ACCESS_check ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000879{
880 /* Ensure the read area is both addressible and valid (ie,
881 readable). If there's an address error, don't report a value
882 error too; but if there isn't an address error, check for a
883 value error.
884
885 Try to be reasonably fast on the common case; wimp out and defer
njn5c004e42002-11-18 11:04:50 +0000886 to ac_fpu_ACCESS_check_SLOWLY for everything else. */
njn25e49d8e72002-09-23 09:36:25 +0000887
888 AcSecMap* sm;
889 UInt sm_off, a_off;
890 Addr addr4;
891
njn0da7ac62005-07-19 21:11:54 +0000892 PROF_EVENT(90, "");
njn25e49d8e72002-09-23 09:36:25 +0000893
894# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000895 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000896# else
897
898 if (size == 4) {
njnbe91aae2005-03-27 01:42:41 +0000899 if (!VG_IS_4_ALIGNED(addr)) goto slow4;
njn0da7ac62005-07-19 21:11:54 +0000900 PROF_EVENT(91, "");
njn25e49d8e72002-09-23 09:36:25 +0000901 /* Properly aligned. */
sewardjb5f6f512005-03-10 23:59:00 +0000902 sm = primary_map[PM_IDX(addr)];
903 sm_off = SM_OFF(addr);
njn25e49d8e72002-09-23 09:36:25 +0000904 a_off = sm_off >> 3;
905 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow4;
906 /* Properly aligned and addressible. */
907 return;
908 slow4:
njnc2699f62003-09-05 23:29:33 +0000909 ac_fpu_ACCESS_check_SLOWLY ( addr, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000910 return;
911 }
912
913 if (size == 8) {
njnbe91aae2005-03-27 01:42:41 +0000914 if (!VG_IS_4_ALIGNED(addr)) goto slow8;
njn0da7ac62005-07-19 21:11:54 +0000915 PROF_EVENT(92, "");
njn25e49d8e72002-09-23 09:36:25 +0000916 /* Properly aligned. Do it in two halves. */
917 addr4 = addr + 4;
918 /* First half. */
sewardjb5f6f512005-03-10 23:59:00 +0000919 sm = primary_map[PM_IDX(addr)];
920 sm_off = SM_OFF(addr);
njn25e49d8e72002-09-23 09:36:25 +0000921 a_off = sm_off >> 3;
922 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
923 /* First half properly aligned and addressible. */
924 /* Second half. */
sewardjb5f6f512005-03-10 23:59:00 +0000925 sm = primary_map[PM_IDX(addr4)];
926 sm_off = SM_OFF(addr4);
njn25e49d8e72002-09-23 09:36:25 +0000927 a_off = sm_off >> 3;
928 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
929 /* Second half properly aligned and addressible. */
930 /* Both halves properly aligned and addressible. */
931 return;
932 slow8:
njnc2699f62003-09-05 23:29:33 +0000933 ac_fpu_ACCESS_check_SLOWLY ( addr, 8, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000934 return;
935 }
936
937 /* Can't be bothered to huff'n'puff to make these (allegedly) rare
938 cases go quickly. */
939 if (size == 2) {
njn0da7ac62005-07-19 21:11:54 +0000940 PROF_EVENT(93, "");
njnc2699f62003-09-05 23:29:33 +0000941 ac_fpu_ACCESS_check_SLOWLY ( addr, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000942 return;
943 }
944
jsewardfca60182004-01-04 23:30:55 +0000945 if (size == 16 || size == 10 || size == 28 || size == 108 || size == 512) {
njn0da7ac62005-07-19 21:11:54 +0000946 PROF_EVENT(94, "");
njnc2699f62003-09-05 23:29:33 +0000947 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000948 return;
949 }
950
951 VG_(printf)("size is %d\n", size);
njn67993252004-11-22 18:02:32 +0000952 VG_(tool_panic)("fpu_ACCESS_check: unhandled size");
njn25e49d8e72002-09-23 09:36:25 +0000953# endif
954}
955
njnaf839f52005-06-23 03:27:57 +0000956VG_REGPARM(2)
sewardj9f649aa2004-11-22 20:38:40 +0000957static void ach_LOADN ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000958{
959 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/False );
960}
961
njnaf839f52005-06-23 03:27:57 +0000962VG_REGPARM(2)
sewardj9f649aa2004-11-22 20:38:40 +0000963static void ach_STOREN ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000964{
965 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/True );
966}
njn25e49d8e72002-09-23 09:36:25 +0000967
sewardjd62e03b2004-12-10 12:01:14 +0000968
njn25e49d8e72002-09-23 09:36:25 +0000969/* ---------------------------------------------------------------------
970 Slow, general cases for FPU access checks.
971 ------------------------------------------------------------------ */
972
nethercote928a5f72004-11-03 18:10:37 +0000973void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000974{
975 Int i;
976 Bool aerr = False;
njn0da7ac62005-07-19 21:11:54 +0000977 PROF_EVENT(100, "");
njn25e49d8e72002-09-23 09:36:25 +0000978 for (i = 0; i < size; i++) {
njn0da7ac62005-07-19 21:11:54 +0000979 PROF_EVENT(101, "");
njn25e49d8e72002-09-23 09:36:25 +0000980 if (get_abit(addr+i) != VGM_BIT_VALID)
981 aerr = True;
982 }
983
984 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000985 MAC_(record_address_error)( VG_(get_running_tid)(), addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000986 }
987}
988
989
990/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000991/*--- Our instrumenter ---*/
992/*------------------------------------------------------------*/
993
njn51d827b2005-05-09 01:02:08 +0000994static IRBB* ac_instrument(IRBB* bb_in, VexGuestLayout* layout,
995 IRType gWordTy, IRType hWordTy )
njn25e49d8e72002-09-23 09:36:25 +0000996{
sewardj9f649aa2004-11-22 20:38:40 +0000997 Int i, hsz;
998 IRStmt* st;
999 IRExpr* data;
1000 IRExpr* aexpr;
1001 IRExpr* guard;
1002 IRDirty* di;
1003 Bool isLoad;
sewardjd54babf2005-03-21 00:55:49 +00001004 IRBB* bb;
1005
1006 if (gWordTy != hWordTy) {
1007 /* We don't currently support this case. */
1008 VG_(tool_panic)("host/guest word size mismatch");
1009 }
njn25e49d8e72002-09-23 09:36:25 +00001010
sewardj9f649aa2004-11-22 20:38:40 +00001011 /* Set up BB */
sewardjd54babf2005-03-21 00:55:49 +00001012 bb = emptyIRBB();
sewardj9f649aa2004-11-22 20:38:40 +00001013 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
1014 bb->next = dopyIRExpr(bb_in->next);
1015 bb->jumpkind = bb_in->jumpkind;
njn25e49d8e72002-09-23 09:36:25 +00001016
sewardj9f649aa2004-11-22 20:38:40 +00001017 /* No loads to consider in ->next. */
sewardj710d6c22005-03-20 18:55:15 +00001018 tl_assert(isIRAtom(bb_in->next));
njn25e49d8e72002-09-23 09:36:25 +00001019
sewardj9f649aa2004-11-22 20:38:40 +00001020 for (i = 0; i < bb_in->stmts_used; i++) {
1021 st = bb_in->stmts[i];
sewardj21dc3452005-03-21 00:27:41 +00001022 tl_assert(st);
njn25e49d8e72002-09-23 09:36:25 +00001023
sewardj9f649aa2004-11-22 20:38:40 +00001024 /* Examine each stmt in turn to figure out if it needs to be
1025 preceded by a memory access check. If so, collect up the
1026 relevant pieces of information. */
1027 hsz = 0;
1028 aexpr = NULL;
1029 guard = NULL;
1030 isLoad = True;
njn25e49d8e72002-09-23 09:36:25 +00001031
sewardj9f649aa2004-11-22 20:38:40 +00001032 switch (st->tag) {
1033
1034 case Ist_Tmp:
1035 data = st->Ist.Tmp.data;
1036 if (data->tag == Iex_LDle) {
1037 aexpr = data->Iex.LDle.addr;
1038 hsz = sizeofIRType(data->Iex.LDle.ty);
1039 isLoad = True;
1040 }
1041 break;
1042
1043 case Ist_STle:
1044 data = st->Ist.STle.data;
1045 aexpr = st->Ist.STle.addr;
sewardj710d6c22005-03-20 18:55:15 +00001046 tl_assert(isIRAtom(data));
1047 tl_assert(isIRAtom(aexpr));
sewardj9f649aa2004-11-22 20:38:40 +00001048 hsz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
1049 isLoad = False;
sewardj08ccc5c2005-03-17 03:17:54 +00001050 break;
sewardj9f649aa2004-11-22 20:38:40 +00001051
1052 case Ist_Put:
sewardj710d6c22005-03-20 18:55:15 +00001053 tl_assert(isIRAtom(st->Ist.Put.data));
njn25e49d8e72002-09-23 09:36:25 +00001054 break;
1055
sewardj9f649aa2004-11-22 20:38:40 +00001056 case Ist_PutI:
sewardj710d6c22005-03-20 18:55:15 +00001057 tl_assert(isIRAtom(st->Ist.PutI.ix));
1058 tl_assert(isIRAtom(st->Ist.PutI.data));
njnc2699f62003-09-05 23:29:33 +00001059 break;
1060
sewardj9f649aa2004-11-22 20:38:40 +00001061 case Ist_Exit:
sewardj710d6c22005-03-20 18:55:15 +00001062 tl_assert(isIRAtom(st->Ist.Exit.guard));
njn25e49d8e72002-09-23 09:36:25 +00001063 break;
1064
sewardj9f649aa2004-11-22 20:38:40 +00001065 case Ist_Dirty:
1066 if (st->Ist.Dirty.details->mFx != Ifx_None) {
1067 /* We classify Ifx_Modify as a load. */
1068 isLoad = st->Ist.Dirty.details->mFx != Ifx_Write;
1069 hsz = st->Ist.Dirty.details->mSize;
1070 aexpr = st->Ist.Dirty.details->mAddr;
1071 guard = st->Ist.Dirty.details->guard;
sewardj710d6c22005-03-20 18:55:15 +00001072 tl_assert(isIRAtom(aexpr));
sewardj9f649aa2004-11-22 20:38:40 +00001073 }
1074 break;
sewardje3891fa2003-06-15 03:13:48 +00001075
sewardj21dc3452005-03-21 00:27:41 +00001076 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00001077 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00001078 case Ist_MFence:
1079 break;
1080
njn25e49d8e72002-09-23 09:36:25 +00001081 default:
sewardj9f649aa2004-11-22 20:38:40 +00001082 VG_(printf)("\n");
1083 ppIRStmt(st);
1084 VG_(printf)("\n");
1085 VG_(tool_panic)("addrcheck: unhandled IRStmt");
njn25e49d8e72002-09-23 09:36:25 +00001086 }
sewardj9f649aa2004-11-22 20:38:40 +00001087
1088 /* If needed, add a helper call. */
1089 if (aexpr) {
1090 tl_assert(hsz > 0);
1091 switch (hsz) {
1092 case 4:
1093 if (isLoad)
1094 di = unsafeIRDirty_0_N( 1, "ach_LOAD4", &ach_LOAD4,
1095 mkIRExprVec_1(aexpr));
1096 else
1097 di = unsafeIRDirty_0_N( 1, "ach_STORE4", &ach_STORE4,
1098 mkIRExprVec_1(aexpr));
1099 break;
1100 case 2:
1101 if (isLoad)
1102 di = unsafeIRDirty_0_N( 1, "ach_LOAD2", &ach_LOAD2,
1103 mkIRExprVec_1(aexpr));
1104 else
1105 di = unsafeIRDirty_0_N( 1, "ach_STORE2", &ach_STORE2,
1106 mkIRExprVec_1(aexpr));
1107 break;
1108 case 1:
1109 if (isLoad)
1110 di = unsafeIRDirty_0_N( 1, "ach_LOAD1", &ach_LOAD1,
1111 mkIRExprVec_1(aexpr));
1112 else
1113 di = unsafeIRDirty_0_N( 1, "ach_STORE1", &ach_STORE1,
1114 mkIRExprVec_1(aexpr));
1115 break;
1116 default:
1117 if (isLoad)
1118 di = unsafeIRDirty_0_N(
1119 2, "ach_LOADN", &ach_LOADN,
1120 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1121 else
1122 di = unsafeIRDirty_0_N(
1123 2, "ach_STOREN", &ach_STOREN,
1124 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1125 break;
1126 }
1127
1128 /* If the call has arisen as a result of a dirty helper which
1129 references memory, we need to inherit the guard from the
1130 dirty helper. */
1131 if (guard)
1132 di->guard = dopyIRExpr(guard);
1133
1134 /* emit the helper call */
1135 addStmtToIRBB( bb, IRStmt_Dirty(di) );
1136
1137 }
1138
1139 /* And finally, copy the expr itself to the output. */
sewardjbd598e12005-01-07 12:10:21 +00001140 addStmtToIRBB( bb, st );
njn25e49d8e72002-09-23 09:36:25 +00001141 }
1142
sewardj9f649aa2004-11-22 20:38:40 +00001143 return bb;
njn25e49d8e72002-09-23 09:36:25 +00001144}
1145
1146
njn25e49d8e72002-09-23 09:36:25 +00001147/*------------------------------------------------------------*/
1148/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
1149/*------------------------------------------------------------*/
1150
sewardja4495682002-10-21 07:29:59 +00001151/* For the memory leak detector, say whether an entire 64k chunk of
1152 address space is possibly in use, or not. If in doubt return
1153 True.
njn25e49d8e72002-09-23 09:36:25 +00001154*/
sewardja4495682002-10-21 07:29:59 +00001155static
1156Bool ac_is_valid_64k_chunk ( UInt chunk_number )
njn25e49d8e72002-09-23 09:36:25 +00001157{
sewardjb5f6f512005-03-10 23:59:00 +00001158 tl_assert(chunk_number >= 0 && chunk_number < PRIMARY_SIZE);
1159 if (primary_map[chunk_number] == DSM_NOTADDR) {
sewardja4495682002-10-21 07:29:59 +00001160 /* Definitely not in use. */
1161 return False;
1162 } else {
1163 return True;
njn25e49d8e72002-09-23 09:36:25 +00001164 }
1165}
1166
1167
sewardja4495682002-10-21 07:29:59 +00001168/* For the memory leak detector, say whether or not a given word
1169 address is to be regarded as valid. */
1170static
1171Bool ac_is_valid_address ( Addr a )
1172{
1173 UChar abits;
njnbe91aae2005-03-27 01:42:41 +00001174 tl_assert(VG_IS_4_ALIGNED(a));
sewardja4495682002-10-21 07:29:59 +00001175 abits = get_abits4_ALIGNED(a);
1176 if (abits == VGM_NIBBLE_VALID) {
1177 return True;
1178 } else {
1179 return False;
1180 }
1181}
1182
1183
nethercote996901a2004-08-03 13:29:09 +00001184/* Leak detector for this tool. We don't actually do anything, merely
sewardja4495682002-10-21 07:29:59 +00001185 run the generic leak detector with suitable parameters for this
nethercote996901a2004-08-03 13:29:09 +00001186 tool. */
njnb8dca862005-03-14 02:42:44 +00001187static void ac_detect_memory_leaks ( ThreadId tid, LeakCheckMode mode )
njn25e49d8e72002-09-23 09:36:25 +00001188{
njnb8dca862005-03-14 02:42:44 +00001189 MAC_(do_detect_memory_leaks) ( tid, mode, ac_is_valid_64k_chunk, ac_is_valid_address );
njn25e49d8e72002-09-23 09:36:25 +00001190}
1191
1192
1193/* ---------------------------------------------------------------------
1194 Sanity check machinery (permanently engaged).
1195 ------------------------------------------------------------------ */
1196
njn51d827b2005-05-09 01:02:08 +00001197static Bool ac_cheap_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00001198{
jseward9800fd32004-01-04 23:08:04 +00001199 /* nothing useful we can rapidly check */
1200 return True;
njn25e49d8e72002-09-23 09:36:25 +00001201}
1202
njn51d827b2005-05-09 01:02:08 +00001203static Bool ac_expensive_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00001204{
1205 Int i;
1206
sewardjb5f6f512005-03-10 23:59:00 +00001207#if 0
njn25e49d8e72002-09-23 09:36:25 +00001208 /* Make sure nobody changed the distinguished secondary. */
1209 for (i = 0; i < 8192; i++)
1210 if (distinguished_secondary_map.abits[i] != VGM_BYTE_INVALID)
1211 return False;
sewardjb5f6f512005-03-10 23:59:00 +00001212#endif
njn25e49d8e72002-09-23 09:36:25 +00001213
1214 /* Make sure that the upper 3/4 of the primary map hasn't
1215 been messed with. */
sewardjb5f6f512005-03-10 23:59:00 +00001216 for (i = PRIMARY_SIZE; i < PRIMARY_SIZE*4; i++)
1217 if (primary_map[i] != DSM_NOTADDR)
njn25e49d8e72002-09-23 09:36:25 +00001218 return False;
1219
1220 return True;
1221}
1222
njn47363ab2003-04-21 13:24:40 +00001223/*------------------------------------------------------------*/
1224/*--- Client requests ---*/
1225/*------------------------------------------------------------*/
1226
njn51d827b2005-05-09 01:02:08 +00001227static Bool ac_handle_client_request ( ThreadId tid, UWord* arg, UWord *ret )
sewardjd8033d92002-12-08 22:16:58 +00001228{
sewardjbf310d92002-12-28 13:09:57 +00001229#define IGNORE(what) \
1230 do { \
1231 if (moans-- > 0) { \
1232 VG_(message)(Vg_UserMsg, \
njn02bc4b82005-05-15 17:28:26 +00001233 "Warning: Addrcheck: ignoring '%s' request.", what); \
sewardjbf310d92002-12-28 13:09:57 +00001234 VG_(message)(Vg_UserMsg, \
nethercote137bc552003-11-14 17:47:54 +00001235 " To honour this request, rerun with --tool=memcheck."); \
sewardjbf310d92002-12-28 13:09:57 +00001236 } \
1237 } while (0)
1238
sewardjbf310d92002-12-28 13:09:57 +00001239 static Int moans = 3;
sewardjd8033d92002-12-08 22:16:58 +00001240
1241 /* Overload memcheck client reqs */
njnfc26ff92004-11-22 19:12:49 +00001242 if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
sewardjd62e03b2004-12-10 12:01:14 +00001243 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
1244 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
1245 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
1246 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
1247 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
1248 && VG_USERREQ__MEMPOOL_FREE != arg[0])
sewardjd8033d92002-12-08 22:16:58 +00001249 return False;
1250
1251 switch (arg[0]) {
1252 case VG_USERREQ__DO_LEAK_CHECK:
njnb8dca862005-03-14 02:42:44 +00001253 ac_detect_memory_leaks(tid, arg[1] ? LC_Summary : LC_Full);
sewardjd8033d92002-12-08 22:16:58 +00001254 *ret = 0; /* return value is meaningless */
1255 break;
1256
sewardjbf310d92002-12-28 13:09:57 +00001257 /* Ignore these */
sewardjd8033d92002-12-08 22:16:58 +00001258 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
sewardjbf310d92002-12-28 13:09:57 +00001259 IGNORE("VALGRIND_CHECK_WRITABLE");
1260 return False;
sewardjd8033d92002-12-08 22:16:58 +00001261 case VG_USERREQ__CHECK_READABLE: /* check readable */
sewardjbf310d92002-12-28 13:09:57 +00001262 IGNORE("VALGRIND_CHECK_READABLE");
1263 return False;
sewardjd8033d92002-12-08 22:16:58 +00001264 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
sewardjbf310d92002-12-28 13:09:57 +00001265 IGNORE("VALGRIND_MAKE_NOACCESS");
1266 return False;
sewardjd8033d92002-12-08 22:16:58 +00001267 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
sewardjbf310d92002-12-28 13:09:57 +00001268 IGNORE("VALGRIND_MAKE_WRITABLE");
1269 return False;
sewardjd8033d92002-12-08 22:16:58 +00001270 case VG_USERREQ__MAKE_READABLE: /* make readable */
sewardjbf310d92002-12-28 13:09:57 +00001271 IGNORE("VALGRIND_MAKE_READABLE");
1272 return False;
sewardjd8033d92002-12-08 22:16:58 +00001273 case VG_USERREQ__DISCARD: /* discard */
sewardjbf310d92002-12-28 13:09:57 +00001274 IGNORE("VALGRIND_CHECK_DISCARD");
1275 return False;
sewardjd8033d92002-12-08 22:16:58 +00001276
1277 default:
nethercoted1b64b22004-11-04 18:22:28 +00001278 if (MAC_(handle_common_client_requests)(tid, arg, ret )) {
njn47363ab2003-04-21 13:24:40 +00001279 return True;
1280 } else {
1281 VG_(message)(Vg_UserMsg,
nethercoted1b64b22004-11-04 18:22:28 +00001282 "Warning: unknown addrcheck client request code %llx",
1283 (ULong)arg[0]);
njn47363ab2003-04-21 13:24:40 +00001284 return False;
1285 }
sewardjd8033d92002-12-08 22:16:58 +00001286 }
1287 return True;
sewardjbf310d92002-12-28 13:09:57 +00001288
1289#undef IGNORE
sewardjd8033d92002-12-08 22:16:58 +00001290}
1291
njn25e49d8e72002-09-23 09:36:25 +00001292/*------------------------------------------------------------*/
1293/*--- Setup ---*/
1294/*------------------------------------------------------------*/
1295
njn51d827b2005-05-09 01:02:08 +00001296static Bool ac_process_cmd_line_option(Char* arg)
njn25e49d8e72002-09-23 09:36:25 +00001297{
njn43c799e2003-04-08 00:08:52 +00001298 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001299}
1300
njn51d827b2005-05-09 01:02:08 +00001301static void ac_print_usage(void)
njn25e49d8e72002-09-23 09:36:25 +00001302{
njn3e884182003-04-15 13:03:23 +00001303 MAC_(print_common_usage)();
1304}
1305
njn51d827b2005-05-09 01:02:08 +00001306static void ac_print_debug_usage(void)
njn3e884182003-04-15 13:03:23 +00001307{
1308 MAC_(print_common_debug_usage)();
njn25e49d8e72002-09-23 09:36:25 +00001309}
njn5db32122005-08-12 15:23:57 +00001310#endif
njn25e49d8e72002-09-23 09:36:25 +00001311
1312/*------------------------------------------------------------*/
njn51d827b2005-05-09 01:02:08 +00001313/*--- Setup and finalisation ---*/
njn25e49d8e72002-09-23 09:36:25 +00001314/*------------------------------------------------------------*/
1315
njn5db32122005-08-12 15:23:57 +00001316// dummy instrument() function
1317static IRBB* ac_instrument(IRBB* bb_in, VexGuestLayout* layout,
1318 IRType gWordTy, IRType hWordTy )
1319{
1320 tl_assert(0);
1321}
1322
njn51d827b2005-05-09 01:02:08 +00001323static void ac_post_clo_init ( void )
1324{
1325}
1326
1327static void ac_fini ( Int exitcode )
1328{
njn5db32122005-08-12 15:23:57 +00001329 tl_assert(0); // turn leak checking back on
1330#if 0
njn51d827b2005-05-09 01:02:08 +00001331 MAC_(common_fini)( ac_detect_memory_leaks );
njn5db32122005-08-12 15:23:57 +00001332#endif
njn51d827b2005-05-09 01:02:08 +00001333}
1334
1335static void ac_pre_clo_init(void)
njn25e49d8e72002-09-23 09:36:25 +00001336{
njn810086f2002-11-14 12:42:47 +00001337 VG_(details_name) ("Addrcheck");
1338 VG_(details_version) (NULL);
1339 VG_(details_description) ("a fine-grained address checker");
1340 VG_(details_copyright_author)(
njn53612422005-03-12 16:22:54 +00001341 "Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.");
nethercote421281e2003-11-20 16:20:55 +00001342 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardj78210aa2002-12-01 02:55:46 +00001343 VG_(details_avg_translation_sizeB) ( 135 );
njn25e49d8e72002-09-23 09:36:25 +00001344
njn51d827b2005-05-09 01:02:08 +00001345 VG_(basic_tool_funcs) (ac_post_clo_init,
1346 ac_instrument,
1347 ac_fini);
njn8a97c6d2005-03-31 04:37:24 +00001348
njn5db32122005-08-12 15:23:57 +00001349
1350 VG_(printf)(
1351"\n"
1352"Addrcheck is currently not working, because:\n"
1353" (a) it is not yet ready to handle the Vex IR and the use with 64-bit\n"
1354" platforms introduced in Valgrind 3.0.0\n"
1355"\n"
1356"Sorry for the inconvenience. Let us know if this is a problem for you.\n");
1357 VG_(exit)(1);
1358
1359
1360#if 0
njn810086f2002-11-14 12:42:47 +00001361 VG_(needs_core_errors) ();
njn51d827b2005-05-09 01:02:08 +00001362 VG_(needs_tool_errors) (MAC_(eq_Error),
1363 ac_pp_Error,
1364 MAC_(update_extra),
1365 MAC_(shared_recognised_suppression),
1366 MAC_(read_extra_suppression_info),
1367 MAC_(error_matches_suppression),
1368 MAC_(get_error_name),
1369 MAC_(print_extra_suppression_info));
njn810086f2002-11-14 12:42:47 +00001370 VG_(needs_libc_freeres) ();
njn51d827b2005-05-09 01:02:08 +00001371 VG_(needs_command_line_options)(MAC_(process_common_cmd_line_option),
1372 MAC_(print_common_usage),
1373 MAC_(print_common_debug_usage));
1374 VG_(needs_client_requests) (ac_handle_client_request);
1375 VG_(needs_sanity_checks) (ac_cheap_sanity_check,
1376 ac_expensive_sanity_check);
fitzhardinge98abfc72003-12-16 02:05:15 +00001377 VG_(needs_shadow_memory) ();
njn25e49d8e72002-09-23 09:36:25 +00001378
njnfc51f8d2005-06-21 03:20:17 +00001379 VG_(needs_malloc_replacement) (MAC_(malloc),
njn51d827b2005-05-09 01:02:08 +00001380 MAC_(__builtin_new),
1381 MAC_(__builtin_vec_new),
1382 MAC_(memalign),
1383 MAC_(calloc),
1384 MAC_(free),
1385 MAC_(__builtin_delete),
1386 MAC_(__builtin_vec_delete),
1387 MAC_(realloc),
1388 MAC_MALLOC_REDZONE_SZB );
njn8a97c6d2005-03-31 04:37:24 +00001389
njn3e884182003-04-15 13:03:23 +00001390 MAC_( new_mem_heap) = & ac_new_mem_heap;
1391 MAC_( ban_mem_heap) = & ac_make_noaccess;
1392 MAC_(copy_mem_heap) = & ac_copy_address_range_state;
1393 MAC_( die_mem_heap) = & ac_make_noaccess;
sewardjecf8e102003-07-12 12:11:39 +00001394 MAC_(check_noaccess) = & ac_check_noaccess;
njn3e884182003-04-15 13:03:23 +00001395
njn51d827b2005-05-09 01:02:08 +00001396 VG_(track_new_mem_startup) ( & ac_new_mem_startup );
1397 VG_(track_new_mem_stack_signal)( & ac_make_accessible );
1398 VG_(track_new_mem_brk) ( & ac_make_accessible );
1399 VG_(track_new_mem_mmap) ( & ac_new_mem_mmap );
njn25e49d8e72002-09-23 09:36:25 +00001400
njn51d827b2005-05-09 01:02:08 +00001401 VG_(track_copy_mem_remap) ( & ac_copy_address_range_state );
njn3e884182003-04-15 13:03:23 +00001402
njn51d827b2005-05-09 01:02:08 +00001403 VG_(track_die_mem_stack_signal)( & ac_make_noaccess );
1404 VG_(track_die_mem_brk) ( & ac_make_noaccess );
1405 VG_(track_die_mem_munmap) ( & ac_make_noaccess );
njn3e884182003-04-15 13:03:23 +00001406
njn51d827b2005-05-09 01:02:08 +00001407 VG_(track_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
1408 VG_(track_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
1409 VG_(track_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
1410 VG_(track_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
1411 VG_(track_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
1412 VG_(track_new_mem_stack) ( & MAC_(new_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001413
njn51d827b2005-05-09 01:02:08 +00001414 VG_(track_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
1415 VG_(track_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
1416 VG_(track_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
1417 VG_(track_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
1418 VG_(track_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
1419 VG_(track_die_mem_stack) ( & MAC_(die_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001420
njn51d827b2005-05-09 01:02:08 +00001421 VG_(track_ban_mem_stack) ( & ac_make_noaccess );
njn25e49d8e72002-09-23 09:36:25 +00001422
njn51d827b2005-05-09 01:02:08 +00001423 VG_(track_pre_mem_read) ( & ac_check_is_readable );
1424 VG_(track_pre_mem_read_asciiz) ( & ac_check_is_readable_asciiz );
1425 VG_(track_pre_mem_write) ( & ac_check_is_writable );
1426 VG_(track_post_mem_write) ( & ac_post_mem_write );
njn25e49d8e72002-09-23 09:36:25 +00001427
njn31066fd2005-03-26 00:42:02 +00001428 VG_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
1429 VG_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
1430 VG_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
njnd04b7c62002-10-03 14:05:52 +00001431
1432 init_shadow_memory();
njn3e884182003-04-15 13:03:23 +00001433 MAC_(common_pre_clo_init)();
njn5db32122005-08-12 15:23:57 +00001434#endif
njn5c004e42002-11-18 11:04:50 +00001435}
1436
njn51d827b2005-05-09 01:02:08 +00001437VG_DETERMINE_INTERFACE_VERSION(ac_pre_clo_init, 1./8)
fitzhardinge98abfc72003-12-16 02:05:15 +00001438
1439
njn25e49d8e72002-09-23 09:36:25 +00001440/*--------------------------------------------------------------------*/
njn5db32122005-08-12 15:23:57 +00001441/*--- end ---*/
njn25e49d8e72002-09-23 09:36:25 +00001442/*--------------------------------------------------------------------*/