blob: 0b2fbb891ca797719162d068482eef5cae4c8761 [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, "");
njn62a31902005-08-28 05:21:17 +0000710 // XXX: Should this be "if (!is_distinguished_sm(sm) && abits == VGM_NIBBLE_VALID)"?
njn25e49d8e72002-09-23 09:36:25 +0000711 if (abits == VGM_NIBBLE_VALID) {
712 /* Handle common case quickly: a is suitably aligned, is mapped,
713 and is addressible. So just return. */
714 return;
715 } else {
716 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000717 ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000718 }
719# endif
720}
721
njnc2699f62003-09-05 23:29:33 +0000722static __inline__ void ac_helperc_ACCESS2 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000723{
724# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000725 return ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000726# else
727 UInt sec_no = rotateRight16(a) & 0x1FFFF;
728 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000729 UInt a_off = (SM_OFF(a)) >> 3;
njn0da7ac62005-07-19 21:11:54 +0000730 PROF_EVENT(67, "");
njn62a31902005-08-28 05:21:17 +0000731 // XXX: Should this be "if (!is_distinguished_sm(sm) && sm->abits[a_off] == VGM_BYTE_VALID)"?
njn25e49d8e72002-09-23 09:36:25 +0000732 if (sm->abits[a_off] == VGM_BYTE_VALID) {
733 /* Handle common case quickly. */
734 return;
735 } else {
736 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000737 ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000738 }
739# endif
740}
741
njnc2699f62003-09-05 23:29:33 +0000742static __inline__ void ac_helperc_ACCESS1 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000743{
744# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000745 return ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000746# else
747 UInt sec_no = shiftRight16(a);
748 AcSecMap* sm = primary_map[sec_no];
sewardjb5f6f512005-03-10 23:59:00 +0000749 UInt a_off = (SM_OFF(a)) >> 3;
njn0da7ac62005-07-19 21:11:54 +0000750 PROF_EVENT(68, "");
njn62a31902005-08-28 05:21:17 +0000751 // XXX: Should this be "if (!is_distinguished_sm(sm) && sm->abits[a_off] == VGM_BYTE_VALID)"?
njn25e49d8e72002-09-23 09:36:25 +0000752 if (sm->abits[a_off] == VGM_BYTE_VALID) {
753 /* Handle common case quickly. */
754 return;
755 } else {
756 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000757 ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000758 }
759# endif
760}
761
njnaf839f52005-06-23 03:27:57 +0000762VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000763static void ach_LOAD4 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000764{
765 ac_helperc_ACCESS4 ( a, /*isWrite*/False );
766}
njnaf839f52005-06-23 03:27:57 +0000767VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000768static void ach_STORE4 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000769{
770 ac_helperc_ACCESS4 ( a, /*isWrite*/True );
771}
772
njnaf839f52005-06-23 03:27:57 +0000773VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000774static void ach_LOAD2 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000775{
776 ac_helperc_ACCESS2 ( a, /*isWrite*/False );
777}
njnaf839f52005-06-23 03:27:57 +0000778VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000779static void ach_STORE2 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000780{
781 ac_helperc_ACCESS2 ( a, /*isWrite*/True );
782}
783
njnaf839f52005-06-23 03:27:57 +0000784VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000785static void ach_LOAD1 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000786{
787 ac_helperc_ACCESS1 ( a, /*isWrite*/False );
788}
njnaf839f52005-06-23 03:27:57 +0000789VG_REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000790static void ach_STORE1 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000791{
792 ac_helperc_ACCESS1 ( a, /*isWrite*/True );
793}
794
njn25e49d8e72002-09-23 09:36:25 +0000795
796/*------------------------------------------------------------*/
797/*--- Fallback functions to handle cases that the above ---*/
njnc2699f62003-09-05 23:29:33 +0000798/*--- ac_helperc_ACCESS{1,2,4} can't manage. ---*/
njn25e49d8e72002-09-23 09:36:25 +0000799/*------------------------------------------------------------*/
800
njnc2699f62003-09-05 23:29:33 +0000801static void ac_ACCESS4_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000802{
803 Bool a0ok, a1ok, a2ok, a3ok;
804
njn0da7ac62005-07-19 21:11:54 +0000805 PROF_EVENT(76, "");
njn25e49d8e72002-09-23 09:36:25 +0000806
807 /* First establish independently the addressibility of the 4 bytes
808 involved. */
809 a0ok = get_abit(a+0) == VGM_BIT_VALID;
810 a1ok = get_abit(a+1) == VGM_BIT_VALID;
811 a2ok = get_abit(a+2) == VGM_BIT_VALID;
812 a3ok = get_abit(a+3) == VGM_BIT_VALID;
813
814 /* Now distinguish 3 cases */
815
816 /* Case 1: the address is completely valid, so:
817 - no addressing error
818 */
819 if (a0ok && a1ok && a2ok && a3ok) {
820 return;
821 }
822
823 /* Case 2: the address is completely invalid.
824 - emit addressing error
825 */
826 /* VG_(printf)("%p (%d %d %d %d)\n", a, a0ok, a1ok, a2ok, a3ok); */
njn43c799e2003-04-08 00:08:52 +0000827 if (!MAC_(clo_partial_loads_ok)
njn25e49d8e72002-09-23 09:36:25 +0000828 || ((a & 3) != 0)
829 || (!a0ok && !a1ok && !a2ok && !a3ok)) {
sewardj76754cf2005-03-14 00:14:04 +0000830 MAC_(record_address_error)( VG_(get_running_tid)(), a, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000831 return;
832 }
833
834 /* Case 3: the address is partially valid.
835 - no addressing error
njn43c799e2003-04-08 00:08:52 +0000836 Case 3 is only allowed if MAC_(clo_partial_loads_ok) is True
njn25e49d8e72002-09-23 09:36:25 +0000837 (which is the default), and the address is 4-aligned.
838 If not, Case 2 will have applied.
839 */
njnca82cc02004-11-22 17:18:48 +0000840 tl_assert(MAC_(clo_partial_loads_ok));
njn25e49d8e72002-09-23 09:36:25 +0000841 {
842 return;
843 }
844}
845
njnc2699f62003-09-05 23:29:33 +0000846static void ac_ACCESS2_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000847{
848 /* Check the address for validity. */
849 Bool aerr = False;
njn0da7ac62005-07-19 21:11:54 +0000850 PROF_EVENT(77, "");
njn25e49d8e72002-09-23 09:36:25 +0000851
852 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
853 if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
854
855 /* If an address error has happened, report it. */
856 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000857 MAC_(record_address_error)( VG_(get_running_tid)(), a, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000858 }
859}
860
njnc2699f62003-09-05 23:29:33 +0000861static void ac_ACCESS1_SLOWLY ( Addr a, Bool isWrite)
njn25e49d8e72002-09-23 09:36:25 +0000862{
863 /* Check the address for validity. */
864 Bool aerr = False;
njn0da7ac62005-07-19 21:11:54 +0000865 PROF_EVENT(78, "");
njn25e49d8e72002-09-23 09:36:25 +0000866
867 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
868
869 /* If an address error has happened, report it. */
870 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000871 MAC_(record_address_error)( VG_(get_running_tid)(), a, 1, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000872 }
873}
874
875
876/* ---------------------------------------------------------------------
877 FPU load and store checks, called from generated code.
878 ------------------------------------------------------------------ */
879
sewardj56867352003-10-12 10:27:06 +0000880static
nethercote928a5f72004-11-03 18:10:37 +0000881void ac_fpu_ACCESS_check ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000882{
883 /* Ensure the read area is both addressible and valid (ie,
884 readable). If there's an address error, don't report a value
885 error too; but if there isn't an address error, check for a
886 value error.
887
888 Try to be reasonably fast on the common case; wimp out and defer
njn5c004e42002-11-18 11:04:50 +0000889 to ac_fpu_ACCESS_check_SLOWLY for everything else. */
njn25e49d8e72002-09-23 09:36:25 +0000890
891 AcSecMap* sm;
892 UInt sm_off, a_off;
893 Addr addr4;
894
njn0da7ac62005-07-19 21:11:54 +0000895 PROF_EVENT(90, "");
njn25e49d8e72002-09-23 09:36:25 +0000896
897# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000898 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000899# else
900
901 if (size == 4) {
njnbe91aae2005-03-27 01:42:41 +0000902 if (!VG_IS_4_ALIGNED(addr)) goto slow4;
njn0da7ac62005-07-19 21:11:54 +0000903 PROF_EVENT(91, "");
njn25e49d8e72002-09-23 09:36:25 +0000904 /* Properly aligned. */
sewardjb5f6f512005-03-10 23:59:00 +0000905 sm = primary_map[PM_IDX(addr)];
906 sm_off = SM_OFF(addr);
njn25e49d8e72002-09-23 09:36:25 +0000907 a_off = sm_off >> 3;
908 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow4;
909 /* Properly aligned and addressible. */
910 return;
911 slow4:
njnc2699f62003-09-05 23:29:33 +0000912 ac_fpu_ACCESS_check_SLOWLY ( addr, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000913 return;
914 }
915
916 if (size == 8) {
njnbe91aae2005-03-27 01:42:41 +0000917 if (!VG_IS_4_ALIGNED(addr)) goto slow8;
njn0da7ac62005-07-19 21:11:54 +0000918 PROF_EVENT(92, "");
njn25e49d8e72002-09-23 09:36:25 +0000919 /* Properly aligned. Do it in two halves. */
920 addr4 = addr + 4;
921 /* First half. */
sewardjb5f6f512005-03-10 23:59:00 +0000922 sm = primary_map[PM_IDX(addr)];
923 sm_off = SM_OFF(addr);
njn25e49d8e72002-09-23 09:36:25 +0000924 a_off = sm_off >> 3;
925 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
926 /* First half properly aligned and addressible. */
927 /* Second half. */
sewardjb5f6f512005-03-10 23:59:00 +0000928 sm = primary_map[PM_IDX(addr4)];
929 sm_off = SM_OFF(addr4);
njn25e49d8e72002-09-23 09:36:25 +0000930 a_off = sm_off >> 3;
931 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
932 /* Second half properly aligned and addressible. */
933 /* Both halves properly aligned and addressible. */
934 return;
935 slow8:
njnc2699f62003-09-05 23:29:33 +0000936 ac_fpu_ACCESS_check_SLOWLY ( addr, 8, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000937 return;
938 }
939
940 /* Can't be bothered to huff'n'puff to make these (allegedly) rare
941 cases go quickly. */
942 if (size == 2) {
njn0da7ac62005-07-19 21:11:54 +0000943 PROF_EVENT(93, "");
njnc2699f62003-09-05 23:29:33 +0000944 ac_fpu_ACCESS_check_SLOWLY ( addr, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000945 return;
946 }
947
jsewardfca60182004-01-04 23:30:55 +0000948 if (size == 16 || size == 10 || size == 28 || size == 108 || size == 512) {
njn0da7ac62005-07-19 21:11:54 +0000949 PROF_EVENT(94, "");
njnc2699f62003-09-05 23:29:33 +0000950 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000951 return;
952 }
953
954 VG_(printf)("size is %d\n", size);
njn67993252004-11-22 18:02:32 +0000955 VG_(tool_panic)("fpu_ACCESS_check: unhandled size");
njn25e49d8e72002-09-23 09:36:25 +0000956# endif
957}
958
njnaf839f52005-06-23 03:27:57 +0000959VG_REGPARM(2)
sewardj9f649aa2004-11-22 20:38:40 +0000960static void ach_LOADN ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000961{
962 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/False );
963}
964
njnaf839f52005-06-23 03:27:57 +0000965VG_REGPARM(2)
sewardj9f649aa2004-11-22 20:38:40 +0000966static void ach_STOREN ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000967{
968 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/True );
969}
njn25e49d8e72002-09-23 09:36:25 +0000970
sewardjd62e03b2004-12-10 12:01:14 +0000971
njn25e49d8e72002-09-23 09:36:25 +0000972/* ---------------------------------------------------------------------
973 Slow, general cases for FPU access checks.
974 ------------------------------------------------------------------ */
975
nethercote928a5f72004-11-03 18:10:37 +0000976void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000977{
978 Int i;
979 Bool aerr = False;
njn0da7ac62005-07-19 21:11:54 +0000980 PROF_EVENT(100, "");
njn25e49d8e72002-09-23 09:36:25 +0000981 for (i = 0; i < size; i++) {
njn0da7ac62005-07-19 21:11:54 +0000982 PROF_EVENT(101, "");
njn25e49d8e72002-09-23 09:36:25 +0000983 if (get_abit(addr+i) != VGM_BIT_VALID)
984 aerr = True;
985 }
986
987 if (aerr) {
sewardj76754cf2005-03-14 00:14:04 +0000988 MAC_(record_address_error)( VG_(get_running_tid)(), addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000989 }
990}
991
992
993/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000994/*--- Our instrumenter ---*/
995/*------------------------------------------------------------*/
996
njn51d827b2005-05-09 01:02:08 +0000997static IRBB* ac_instrument(IRBB* bb_in, VexGuestLayout* layout,
998 IRType gWordTy, IRType hWordTy )
njn25e49d8e72002-09-23 09:36:25 +0000999{
sewardj9f649aa2004-11-22 20:38:40 +00001000 Int i, hsz;
1001 IRStmt* st;
1002 IRExpr* data;
1003 IRExpr* aexpr;
1004 IRExpr* guard;
1005 IRDirty* di;
1006 Bool isLoad;
sewardjd54babf2005-03-21 00:55:49 +00001007 IRBB* bb;
1008
1009 if (gWordTy != hWordTy) {
1010 /* We don't currently support this case. */
1011 VG_(tool_panic)("host/guest word size mismatch");
1012 }
njn25e49d8e72002-09-23 09:36:25 +00001013
sewardj9f649aa2004-11-22 20:38:40 +00001014 /* Set up BB */
sewardjd54babf2005-03-21 00:55:49 +00001015 bb = emptyIRBB();
sewardj9f649aa2004-11-22 20:38:40 +00001016 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
1017 bb->next = dopyIRExpr(bb_in->next);
1018 bb->jumpkind = bb_in->jumpkind;
njn25e49d8e72002-09-23 09:36:25 +00001019
sewardj9f649aa2004-11-22 20:38:40 +00001020 /* No loads to consider in ->next. */
sewardj710d6c22005-03-20 18:55:15 +00001021 tl_assert(isIRAtom(bb_in->next));
njn25e49d8e72002-09-23 09:36:25 +00001022
sewardj9f649aa2004-11-22 20:38:40 +00001023 for (i = 0; i < bb_in->stmts_used; i++) {
1024 st = bb_in->stmts[i];
sewardj21dc3452005-03-21 00:27:41 +00001025 tl_assert(st);
njn25e49d8e72002-09-23 09:36:25 +00001026
sewardj9f649aa2004-11-22 20:38:40 +00001027 /* Examine each stmt in turn to figure out if it needs to be
1028 preceded by a memory access check. If so, collect up the
1029 relevant pieces of information. */
1030 hsz = 0;
1031 aexpr = NULL;
1032 guard = NULL;
1033 isLoad = True;
njn25e49d8e72002-09-23 09:36:25 +00001034
sewardj9f649aa2004-11-22 20:38:40 +00001035 switch (st->tag) {
1036
1037 case Ist_Tmp:
1038 data = st->Ist.Tmp.data;
1039 if (data->tag == Iex_LDle) {
1040 aexpr = data->Iex.LDle.addr;
1041 hsz = sizeofIRType(data->Iex.LDle.ty);
1042 isLoad = True;
1043 }
1044 break;
1045
1046 case Ist_STle:
1047 data = st->Ist.STle.data;
1048 aexpr = st->Ist.STle.addr;
sewardj710d6c22005-03-20 18:55:15 +00001049 tl_assert(isIRAtom(data));
1050 tl_assert(isIRAtom(aexpr));
sewardj9f649aa2004-11-22 20:38:40 +00001051 hsz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
1052 isLoad = False;
sewardj08ccc5c2005-03-17 03:17:54 +00001053 break;
sewardj9f649aa2004-11-22 20:38:40 +00001054
1055 case Ist_Put:
sewardj710d6c22005-03-20 18:55:15 +00001056 tl_assert(isIRAtom(st->Ist.Put.data));
njn25e49d8e72002-09-23 09:36:25 +00001057 break;
1058
sewardj9f649aa2004-11-22 20:38:40 +00001059 case Ist_PutI:
sewardj710d6c22005-03-20 18:55:15 +00001060 tl_assert(isIRAtom(st->Ist.PutI.ix));
1061 tl_assert(isIRAtom(st->Ist.PutI.data));
njnc2699f62003-09-05 23:29:33 +00001062 break;
1063
sewardj9f649aa2004-11-22 20:38:40 +00001064 case Ist_Exit:
sewardj710d6c22005-03-20 18:55:15 +00001065 tl_assert(isIRAtom(st->Ist.Exit.guard));
njn25e49d8e72002-09-23 09:36:25 +00001066 break;
1067
sewardj9f649aa2004-11-22 20:38:40 +00001068 case Ist_Dirty:
1069 if (st->Ist.Dirty.details->mFx != Ifx_None) {
1070 /* We classify Ifx_Modify as a load. */
1071 isLoad = st->Ist.Dirty.details->mFx != Ifx_Write;
1072 hsz = st->Ist.Dirty.details->mSize;
1073 aexpr = st->Ist.Dirty.details->mAddr;
1074 guard = st->Ist.Dirty.details->guard;
sewardj710d6c22005-03-20 18:55:15 +00001075 tl_assert(isIRAtom(aexpr));
sewardj9f649aa2004-11-22 20:38:40 +00001076 }
1077 break;
sewardje3891fa2003-06-15 03:13:48 +00001078
sewardj21dc3452005-03-21 00:27:41 +00001079 case Ist_NoOp:
sewardj29faa502005-03-16 18:20:21 +00001080 case Ist_IMark:
sewardjbd598e12005-01-07 12:10:21 +00001081 case Ist_MFence:
1082 break;
1083
njn25e49d8e72002-09-23 09:36:25 +00001084 default:
sewardj9f649aa2004-11-22 20:38:40 +00001085 VG_(printf)("\n");
1086 ppIRStmt(st);
1087 VG_(printf)("\n");
1088 VG_(tool_panic)("addrcheck: unhandled IRStmt");
njn25e49d8e72002-09-23 09:36:25 +00001089 }
sewardj9f649aa2004-11-22 20:38:40 +00001090
1091 /* If needed, add a helper call. */
1092 if (aexpr) {
1093 tl_assert(hsz > 0);
1094 switch (hsz) {
1095 case 4:
1096 if (isLoad)
1097 di = unsafeIRDirty_0_N( 1, "ach_LOAD4", &ach_LOAD4,
1098 mkIRExprVec_1(aexpr));
1099 else
1100 di = unsafeIRDirty_0_N( 1, "ach_STORE4", &ach_STORE4,
1101 mkIRExprVec_1(aexpr));
1102 break;
1103 case 2:
1104 if (isLoad)
1105 di = unsafeIRDirty_0_N( 1, "ach_LOAD2", &ach_LOAD2,
1106 mkIRExprVec_1(aexpr));
1107 else
1108 di = unsafeIRDirty_0_N( 1, "ach_STORE2", &ach_STORE2,
1109 mkIRExprVec_1(aexpr));
1110 break;
1111 case 1:
1112 if (isLoad)
1113 di = unsafeIRDirty_0_N( 1, "ach_LOAD1", &ach_LOAD1,
1114 mkIRExprVec_1(aexpr));
1115 else
1116 di = unsafeIRDirty_0_N( 1, "ach_STORE1", &ach_STORE1,
1117 mkIRExprVec_1(aexpr));
1118 break;
1119 default:
1120 if (isLoad)
1121 di = unsafeIRDirty_0_N(
1122 2, "ach_LOADN", &ach_LOADN,
1123 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1124 else
1125 di = unsafeIRDirty_0_N(
1126 2, "ach_STOREN", &ach_STOREN,
1127 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1128 break;
1129 }
1130
1131 /* If the call has arisen as a result of a dirty helper which
1132 references memory, we need to inherit the guard from the
1133 dirty helper. */
1134 if (guard)
1135 di->guard = dopyIRExpr(guard);
1136
1137 /* emit the helper call */
1138 addStmtToIRBB( bb, IRStmt_Dirty(di) );
1139
1140 }
1141
1142 /* And finally, copy the expr itself to the output. */
sewardjbd598e12005-01-07 12:10:21 +00001143 addStmtToIRBB( bb, st );
njn25e49d8e72002-09-23 09:36:25 +00001144 }
1145
sewardj9f649aa2004-11-22 20:38:40 +00001146 return bb;
njn25e49d8e72002-09-23 09:36:25 +00001147}
1148
1149
njn25e49d8e72002-09-23 09:36:25 +00001150/*------------------------------------------------------------*/
1151/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
1152/*------------------------------------------------------------*/
1153
sewardja4495682002-10-21 07:29:59 +00001154/* For the memory leak detector, say whether an entire 64k chunk of
1155 address space is possibly in use, or not. If in doubt return
1156 True.
njn25e49d8e72002-09-23 09:36:25 +00001157*/
sewardja4495682002-10-21 07:29:59 +00001158static
1159Bool ac_is_valid_64k_chunk ( UInt chunk_number )
njn25e49d8e72002-09-23 09:36:25 +00001160{
sewardjb5f6f512005-03-10 23:59:00 +00001161 tl_assert(chunk_number >= 0 && chunk_number < PRIMARY_SIZE);
1162 if (primary_map[chunk_number] == DSM_NOTADDR) {
sewardja4495682002-10-21 07:29:59 +00001163 /* Definitely not in use. */
1164 return False;
1165 } else {
1166 return True;
njn25e49d8e72002-09-23 09:36:25 +00001167 }
1168}
1169
1170
sewardja4495682002-10-21 07:29:59 +00001171/* For the memory leak detector, say whether or not a given word
1172 address is to be regarded as valid. */
1173static
1174Bool ac_is_valid_address ( Addr a )
1175{
1176 UChar abits;
njnbe91aae2005-03-27 01:42:41 +00001177 tl_assert(VG_IS_4_ALIGNED(a));
sewardja4495682002-10-21 07:29:59 +00001178 abits = get_abits4_ALIGNED(a);
1179 if (abits == VGM_NIBBLE_VALID) {
1180 return True;
1181 } else {
1182 return False;
1183 }
1184}
1185
1186
nethercote996901a2004-08-03 13:29:09 +00001187/* Leak detector for this tool. We don't actually do anything, merely
sewardja4495682002-10-21 07:29:59 +00001188 run the generic leak detector with suitable parameters for this
nethercote996901a2004-08-03 13:29:09 +00001189 tool. */
njnb8dca862005-03-14 02:42:44 +00001190static void ac_detect_memory_leaks ( ThreadId tid, LeakCheckMode mode )
njn25e49d8e72002-09-23 09:36:25 +00001191{
njnb8dca862005-03-14 02:42:44 +00001192 MAC_(do_detect_memory_leaks) ( tid, mode, ac_is_valid_64k_chunk, ac_is_valid_address );
njn25e49d8e72002-09-23 09:36:25 +00001193}
1194
1195
1196/* ---------------------------------------------------------------------
1197 Sanity check machinery (permanently engaged).
1198 ------------------------------------------------------------------ */
1199
njn51d827b2005-05-09 01:02:08 +00001200static Bool ac_cheap_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00001201{
jseward9800fd32004-01-04 23:08:04 +00001202 /* nothing useful we can rapidly check */
1203 return True;
njn25e49d8e72002-09-23 09:36:25 +00001204}
1205
njn51d827b2005-05-09 01:02:08 +00001206static Bool ac_expensive_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00001207{
1208 Int i;
1209
sewardjb5f6f512005-03-10 23:59:00 +00001210#if 0
njn25e49d8e72002-09-23 09:36:25 +00001211 /* Make sure nobody changed the distinguished secondary. */
1212 for (i = 0; i < 8192; i++)
1213 if (distinguished_secondary_map.abits[i] != VGM_BYTE_INVALID)
1214 return False;
sewardjb5f6f512005-03-10 23:59:00 +00001215#endif
njn25e49d8e72002-09-23 09:36:25 +00001216
1217 /* Make sure that the upper 3/4 of the primary map hasn't
1218 been messed with. */
sewardjb5f6f512005-03-10 23:59:00 +00001219 for (i = PRIMARY_SIZE; i < PRIMARY_SIZE*4; i++)
1220 if (primary_map[i] != DSM_NOTADDR)
njn25e49d8e72002-09-23 09:36:25 +00001221 return False;
1222
1223 return True;
1224}
1225
njn47363ab2003-04-21 13:24:40 +00001226/*------------------------------------------------------------*/
1227/*--- Client requests ---*/
1228/*------------------------------------------------------------*/
1229
njn51d827b2005-05-09 01:02:08 +00001230static Bool ac_handle_client_request ( ThreadId tid, UWord* arg, UWord *ret )
sewardjd8033d92002-12-08 22:16:58 +00001231{
sewardjbf310d92002-12-28 13:09:57 +00001232#define IGNORE(what) \
1233 do { \
1234 if (moans-- > 0) { \
1235 VG_(message)(Vg_UserMsg, \
njn02bc4b82005-05-15 17:28:26 +00001236 "Warning: Addrcheck: ignoring '%s' request.", what); \
sewardjbf310d92002-12-28 13:09:57 +00001237 VG_(message)(Vg_UserMsg, \
nethercote137bc552003-11-14 17:47:54 +00001238 " To honour this request, rerun with --tool=memcheck."); \
sewardjbf310d92002-12-28 13:09:57 +00001239 } \
1240 } while (0)
1241
sewardjbf310d92002-12-28 13:09:57 +00001242 static Int moans = 3;
sewardjd8033d92002-12-08 22:16:58 +00001243
1244 /* Overload memcheck client reqs */
njnfc26ff92004-11-22 19:12:49 +00001245 if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
sewardjd62e03b2004-12-10 12:01:14 +00001246 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
1247 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
1248 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
1249 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
1250 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
1251 && VG_USERREQ__MEMPOOL_FREE != arg[0])
sewardjd8033d92002-12-08 22:16:58 +00001252 return False;
1253
1254 switch (arg[0]) {
1255 case VG_USERREQ__DO_LEAK_CHECK:
njnb8dca862005-03-14 02:42:44 +00001256 ac_detect_memory_leaks(tid, arg[1] ? LC_Summary : LC_Full);
sewardjd8033d92002-12-08 22:16:58 +00001257 *ret = 0; /* return value is meaningless */
1258 break;
1259
sewardjbf310d92002-12-28 13:09:57 +00001260 /* Ignore these */
sewardjd8033d92002-12-08 22:16:58 +00001261 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
sewardjbf310d92002-12-28 13:09:57 +00001262 IGNORE("VALGRIND_CHECK_WRITABLE");
1263 return False;
sewardjd8033d92002-12-08 22:16:58 +00001264 case VG_USERREQ__CHECK_READABLE: /* check readable */
sewardjbf310d92002-12-28 13:09:57 +00001265 IGNORE("VALGRIND_CHECK_READABLE");
1266 return False;
sewardjd8033d92002-12-08 22:16:58 +00001267 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
sewardjbf310d92002-12-28 13:09:57 +00001268 IGNORE("VALGRIND_MAKE_NOACCESS");
1269 return False;
sewardjd8033d92002-12-08 22:16:58 +00001270 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
sewardjbf310d92002-12-28 13:09:57 +00001271 IGNORE("VALGRIND_MAKE_WRITABLE");
1272 return False;
sewardjd8033d92002-12-08 22:16:58 +00001273 case VG_USERREQ__MAKE_READABLE: /* make readable */
sewardjbf310d92002-12-28 13:09:57 +00001274 IGNORE("VALGRIND_MAKE_READABLE");
1275 return False;
sewardjd8033d92002-12-08 22:16:58 +00001276 case VG_USERREQ__DISCARD: /* discard */
sewardjbf310d92002-12-28 13:09:57 +00001277 IGNORE("VALGRIND_CHECK_DISCARD");
1278 return False;
sewardjd8033d92002-12-08 22:16:58 +00001279
1280 default:
nethercoted1b64b22004-11-04 18:22:28 +00001281 if (MAC_(handle_common_client_requests)(tid, arg, ret )) {
njn47363ab2003-04-21 13:24:40 +00001282 return True;
1283 } else {
1284 VG_(message)(Vg_UserMsg,
nethercoted1b64b22004-11-04 18:22:28 +00001285 "Warning: unknown addrcheck client request code %llx",
1286 (ULong)arg[0]);
njn47363ab2003-04-21 13:24:40 +00001287 return False;
1288 }
sewardjd8033d92002-12-08 22:16:58 +00001289 }
1290 return True;
sewardjbf310d92002-12-28 13:09:57 +00001291
1292#undef IGNORE
sewardjd8033d92002-12-08 22:16:58 +00001293}
1294
njn25e49d8e72002-09-23 09:36:25 +00001295/*------------------------------------------------------------*/
1296/*--- Setup ---*/
1297/*------------------------------------------------------------*/
1298
njn51d827b2005-05-09 01:02:08 +00001299static Bool ac_process_cmd_line_option(Char* arg)
njn25e49d8e72002-09-23 09:36:25 +00001300{
njn43c799e2003-04-08 00:08:52 +00001301 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001302}
1303
njn51d827b2005-05-09 01:02:08 +00001304static void ac_print_usage(void)
njn25e49d8e72002-09-23 09:36:25 +00001305{
njn3e884182003-04-15 13:03:23 +00001306 MAC_(print_common_usage)();
1307}
1308
njn51d827b2005-05-09 01:02:08 +00001309static void ac_print_debug_usage(void)
njn3e884182003-04-15 13:03:23 +00001310{
1311 MAC_(print_common_debug_usage)();
njn25e49d8e72002-09-23 09:36:25 +00001312}
njn5db32122005-08-12 15:23:57 +00001313#endif
njn25e49d8e72002-09-23 09:36:25 +00001314
1315/*------------------------------------------------------------*/
njn51d827b2005-05-09 01:02:08 +00001316/*--- Setup and finalisation ---*/
njn25e49d8e72002-09-23 09:36:25 +00001317/*------------------------------------------------------------*/
1318
njn5db32122005-08-12 15:23:57 +00001319// dummy instrument() function
1320static IRBB* ac_instrument(IRBB* bb_in, VexGuestLayout* layout,
1321 IRType gWordTy, IRType hWordTy )
1322{
1323 tl_assert(0);
1324}
1325
njn51d827b2005-05-09 01:02:08 +00001326static void ac_post_clo_init ( void )
1327{
1328}
1329
1330static void ac_fini ( Int exitcode )
1331{
njn5db32122005-08-12 15:23:57 +00001332 tl_assert(0); // turn leak checking back on
1333#if 0
njn51d827b2005-05-09 01:02:08 +00001334 MAC_(common_fini)( ac_detect_memory_leaks );
njn5db32122005-08-12 15:23:57 +00001335#endif
njn51d827b2005-05-09 01:02:08 +00001336}
1337
1338static void ac_pre_clo_init(void)
njn25e49d8e72002-09-23 09:36:25 +00001339{
njn810086f2002-11-14 12:42:47 +00001340 VG_(details_name) ("Addrcheck");
1341 VG_(details_version) (NULL);
1342 VG_(details_description) ("a fine-grained address checker");
1343 VG_(details_copyright_author)(
njn53612422005-03-12 16:22:54 +00001344 "Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.");
nethercote421281e2003-11-20 16:20:55 +00001345 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardj78210aa2002-12-01 02:55:46 +00001346 VG_(details_avg_translation_sizeB) ( 135 );
njn25e49d8e72002-09-23 09:36:25 +00001347
njn51d827b2005-05-09 01:02:08 +00001348 VG_(basic_tool_funcs) (ac_post_clo_init,
1349 ac_instrument,
1350 ac_fini);
njn8a97c6d2005-03-31 04:37:24 +00001351
njn5db32122005-08-12 15:23:57 +00001352
1353 VG_(printf)(
1354"\n"
1355"Addrcheck is currently not working, because:\n"
1356" (a) it is not yet ready to handle the Vex IR and the use with 64-bit\n"
1357" platforms introduced in Valgrind 3.0.0\n"
1358"\n"
1359"Sorry for the inconvenience. Let us know if this is a problem for you.\n");
1360 VG_(exit)(1);
1361
1362
1363#if 0
njn810086f2002-11-14 12:42:47 +00001364 VG_(needs_core_errors) ();
njn51d827b2005-05-09 01:02:08 +00001365 VG_(needs_tool_errors) (MAC_(eq_Error),
1366 ac_pp_Error,
1367 MAC_(update_extra),
1368 MAC_(shared_recognised_suppression),
1369 MAC_(read_extra_suppression_info),
1370 MAC_(error_matches_suppression),
1371 MAC_(get_error_name),
1372 MAC_(print_extra_suppression_info));
njn810086f2002-11-14 12:42:47 +00001373 VG_(needs_libc_freeres) ();
njn51d827b2005-05-09 01:02:08 +00001374 VG_(needs_command_line_options)(MAC_(process_common_cmd_line_option),
1375 MAC_(print_common_usage),
1376 MAC_(print_common_debug_usage));
1377 VG_(needs_client_requests) (ac_handle_client_request);
1378 VG_(needs_sanity_checks) (ac_cheap_sanity_check,
1379 ac_expensive_sanity_check);
njn25e49d8e72002-09-23 09:36:25 +00001380
njnfc51f8d2005-06-21 03:20:17 +00001381 VG_(needs_malloc_replacement) (MAC_(malloc),
njn51d827b2005-05-09 01:02:08 +00001382 MAC_(__builtin_new),
1383 MAC_(__builtin_vec_new),
1384 MAC_(memalign),
1385 MAC_(calloc),
1386 MAC_(free),
1387 MAC_(__builtin_delete),
1388 MAC_(__builtin_vec_delete),
1389 MAC_(realloc),
1390 MAC_MALLOC_REDZONE_SZB );
njn8a97c6d2005-03-31 04:37:24 +00001391
njn3e884182003-04-15 13:03:23 +00001392 MAC_( new_mem_heap) = & ac_new_mem_heap;
1393 MAC_( ban_mem_heap) = & ac_make_noaccess;
1394 MAC_(copy_mem_heap) = & ac_copy_address_range_state;
1395 MAC_( die_mem_heap) = & ac_make_noaccess;
sewardjecf8e102003-07-12 12:11:39 +00001396 MAC_(check_noaccess) = & ac_check_noaccess;
njn3e884182003-04-15 13:03:23 +00001397
njn51d827b2005-05-09 01:02:08 +00001398 VG_(track_new_mem_startup) ( & ac_new_mem_startup );
1399 VG_(track_new_mem_stack_signal)( & ac_make_accessible );
1400 VG_(track_new_mem_brk) ( & ac_make_accessible );
1401 VG_(track_new_mem_mmap) ( & ac_new_mem_mmap );
njn25e49d8e72002-09-23 09:36:25 +00001402
njn51d827b2005-05-09 01:02:08 +00001403 VG_(track_copy_mem_remap) ( & ac_copy_address_range_state );
njn3e884182003-04-15 13:03:23 +00001404
njn51d827b2005-05-09 01:02:08 +00001405 VG_(track_die_mem_stack_signal)( & ac_make_noaccess );
1406 VG_(track_die_mem_brk) ( & ac_make_noaccess );
1407 VG_(track_die_mem_munmap) ( & ac_make_noaccess );
njn3e884182003-04-15 13:03:23 +00001408
njn51d827b2005-05-09 01:02:08 +00001409 VG_(track_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
1410 VG_(track_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
1411 VG_(track_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
1412 VG_(track_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
1413 VG_(track_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
1414 VG_(track_new_mem_stack) ( & MAC_(new_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001415
njn51d827b2005-05-09 01:02:08 +00001416 VG_(track_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
1417 VG_(track_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
1418 VG_(track_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
1419 VG_(track_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
1420 VG_(track_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
1421 VG_(track_die_mem_stack) ( & MAC_(die_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001422
njn51d827b2005-05-09 01:02:08 +00001423 VG_(track_ban_mem_stack) ( & ac_make_noaccess );
njn25e49d8e72002-09-23 09:36:25 +00001424
njn51d827b2005-05-09 01:02:08 +00001425 VG_(track_pre_mem_read) ( & ac_check_is_readable );
1426 VG_(track_pre_mem_read_asciiz) ( & ac_check_is_readable_asciiz );
1427 VG_(track_pre_mem_write) ( & ac_check_is_writable );
1428 VG_(track_post_mem_write) ( & ac_post_mem_write );
njn25e49d8e72002-09-23 09:36:25 +00001429
njn31066fd2005-03-26 00:42:02 +00001430 VG_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
1431 VG_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
1432 VG_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
njnd04b7c62002-10-03 14:05:52 +00001433
1434 init_shadow_memory();
njn3e884182003-04-15 13:03:23 +00001435 MAC_(common_pre_clo_init)();
njn5db32122005-08-12 15:23:57 +00001436#endif
njn5c004e42002-11-18 11:04:50 +00001437}
1438
njn51d827b2005-05-09 01:02:08 +00001439VG_DETERMINE_INTERFACE_VERSION(ac_pre_clo_init, 1./8)
fitzhardinge98abfc72003-12-16 02:05:15 +00001440
1441
njn25e49d8e72002-09-23 09:36:25 +00001442/*--------------------------------------------------------------------*/
njn5db32122005-08-12 15:23:57 +00001443/*--- end ---*/
njn25e49d8e72002-09-23 09:36:25 +00001444/*--------------------------------------------------------------------*/