blob: 73e0de41c85e71db4821edb98dd01474cd2b8e48 [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
nethercotebb1c9912004-01-04 16:43:23 +000012 Copyright (C) 2000-2004 Julian Seward
njn25e49d8e72002-09-23 09:36:25 +000013 jseward@acm.org
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file COPYING.
31*/
32
njn43c799e2003-04-08 00:08:52 +000033#include "mac_shared.h"
sewardjd8033d92002-12-08 22:16:58 +000034#include "memcheck.h"
njn25e49d8e72002-09-23 09:36:25 +000035//#include "vg_profile.c"
36
njn9b007f62003-04-07 14:40:25 +000037
njn25e49d8e72002-09-23 09:36:25 +000038/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000039/*--- Comparing and printing errors ---*/
40/*------------------------------------------------------------*/
41
njn26f02512004-11-22 18:33:15 +000042void TL_(pp_Error) ( Error* err )
njn25e49d8e72002-09-23 09:36:25 +000043{
njn43c799e2003-04-08 00:08:52 +000044 MAC_Error* err_extra = VG_(get_error_extra)(err);
njn25e49d8e72002-09-23 09:36:25 +000045
njn810086f2002-11-14 12:42:47 +000046 switch (VG_(get_error_kind)(err)) {
njn25e49d8e72002-09-23 09:36:25 +000047 case CoreMemErr:
njn43c799e2003-04-08 00:08:52 +000048 VG_(message)(Vg_UserMsg, "%s contains unaddressable byte(s)",
49 VG_(get_error_string)(err));
50 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
njn25e49d8e72002-09-23 09:36:25 +000051 break;
52
njn25e49d8e72002-09-23 09:36:25 +000053 case ParamErr:
njn43c799e2003-04-08 00:08:52 +000054 VG_(message)(Vg_UserMsg,
55 "Syscall param %s contains unaddressable byte(s)",
56 VG_(get_error_string)(err) );
57 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
58 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
njn25e49d8e72002-09-23 09:36:25 +000059 break;
60
61 case UserErr:
njn43c799e2003-04-08 00:08:52 +000062 VG_(message)(Vg_UserMsg,
63 "Unaddressable byte(s) found during client check request");
64 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
65 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
njn25e49d8e72002-09-23 09:36:25 +000066 break;
67
68 default:
njnb126f732004-11-22 17:57:07 +000069 MAC_(pp_shared_Error)(err);
njn43c799e2003-04-08 00:08:52 +000070 break;
njn25e49d8e72002-09-23 09:36:25 +000071 }
72}
73
74/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000075/*--- Suppressions ---*/
76/*------------------------------------------------------------*/
77
njn26f02512004-11-22 18:33:15 +000078Bool TL_(recognised_suppression) ( Char* name, Supp* su )
njn25e49d8e72002-09-23 09:36:25 +000079{
njn43c799e2003-04-08 00:08:52 +000080 return MAC_(shared_recognised_suppression)(name, su);
njn25e49d8e72002-09-23 09:36:25 +000081}
82
njn5c004e42002-11-18 11:04:50 +000083#define DEBUG(fmt, args...) //VG_(printf)(fmt, ## args)
84
njn25e49d8e72002-09-23 09:36:25 +000085/*------------------------------------------------------------*/
86/*--- Low-level support for memory checking. ---*/
87/*------------------------------------------------------------*/
88
89/* All reads and writes are checked against a memory map, which
90 records the state of all memory in the process. The memory map is
91 organised like this:
92
93 The top 16 bits of an address are used to index into a top-level
94 map table, containing 65536 entries. Each entry is a pointer to a
95 second-level map, which records the accesibililty and validity
96 permissions for the 65536 bytes indexed by the lower 16 bits of the
97 address. Each byte is represented by one bit, indicating
98 accessibility. So each second-level map contains 8192 bytes. This
99 two-level arrangement conveniently divides the 4G address space
100 into 64k lumps, each size 64k bytes.
101
102 All entries in the primary (top-level) map must point to a valid
103 secondary (second-level) map. Since most of the 4G of address
104 space will not be in use -- ie, not mapped at all -- there is a
105 distinguished secondary map, which indicates `not addressible and
106 not valid' writeable for all bytes. Entries in the primary map for
107 which the entire 64k is not in use at all point at this
108 distinguished map.
109
110 [...] lots of stuff deleted due to out of date-ness
111
112 As a final optimisation, the alignment and address checks for
113 4-byte loads and stores are combined in a neat way. The primary
114 map is extended to have 262144 entries (2^18), rather than 2^16.
115 The top 3/4 of these entries are permanently set to the
116 distinguished secondary map. For a 4-byte load/store, the
117 top-level map is indexed not with (addr >> 16) but instead f(addr),
118 where
119
120 f( XXXX XXXX XXXX XXXX ____ ____ ____ __YZ )
121 = ____ ____ ____ __YZ XXXX XXXX XXXX XXXX or
122 = ____ ____ ____ __ZY XXXX XXXX XXXX XXXX
123
124 ie the lowest two bits are placed above the 16 high address bits.
125 If either of these two bits are nonzero, the address is misaligned;
126 this will select a secondary map from the upper 3/4 of the primary
127 map. Because this is always the distinguished secondary map, a
128 (bogus) address check failure will result. The failure handling
129 code can then figure out whether this is a genuine addr check
130 failure or whether it is a possibly-legitimate access at a
131 misaligned address. */
132
133
134/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000135/*--- Function declarations. ---*/
136/*------------------------------------------------------------*/
137
njnc2699f62003-09-05 23:29:33 +0000138static void ac_ACCESS4_SLOWLY ( Addr a, Bool isWrite );
139static void ac_ACCESS2_SLOWLY ( Addr a, Bool isWrite );
140static void ac_ACCESS1_SLOWLY ( Addr a, Bool isWrite );
nethercote928a5f72004-11-03 18:10:37 +0000141static void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, SizeT size, Bool isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000142
143/*------------------------------------------------------------*/
144/*--- Data defns. ---*/
145/*------------------------------------------------------------*/
146
147typedef
148 struct {
149 UChar abits[8192];
150 }
151 AcSecMap;
152
153static AcSecMap* primary_map[ /*65536*/ 262144 ];
154static AcSecMap distinguished_secondary_map;
155
njn25e49d8e72002-09-23 09:36:25 +0000156static void init_shadow_memory ( void )
157{
158 Int i;
159
160 for (i = 0; i < 8192; i++) /* Invalid address */
161 distinguished_secondary_map.abits[i] = VGM_BYTE_INVALID;
162
163 /* These entries gradually get overwritten as the used address
164 space expands. */
165 for (i = 0; i < 65536; i++)
166 primary_map[i] = &distinguished_secondary_map;
167
168 /* These ones should never change; it's a bug in Valgrind if they do. */
169 for (i = 65536; i < 262144; i++)
170 primary_map[i] = &distinguished_secondary_map;
171}
172
njn25e49d8e72002-09-23 09:36:25 +0000173/*------------------------------------------------------------*/
174/*--- Basic bitmap management, reading and writing. ---*/
175/*------------------------------------------------------------*/
176
177/* Allocate and initialise a secondary map. */
178
179static AcSecMap* alloc_secondary_map ( __attribute__ ((unused))
180 Char* caller )
181{
182 AcSecMap* map;
183 UInt i;
184 PROF_EVENT(10);
185
186 /* Mark all bytes as invalid access and invalid value. */
fitzhardinge98abfc72003-12-16 02:05:15 +0000187 map = (AcSecMap *)VG_(shadow_alloc)(sizeof(AcSecMap));
njn25e49d8e72002-09-23 09:36:25 +0000188 for (i = 0; i < 8192; i++)
189 map->abits[i] = VGM_BYTE_INVALID; /* Invalid address */
190
191 /* VG_(printf)("ALLOC_2MAP(%s)\n", caller ); */
192 return map;
193}
194
195
196/* Basic reading/writing of the bitmaps, for byte-sized accesses. */
197
198static __inline__ UChar get_abit ( Addr a )
199{
200 AcSecMap* sm = primary_map[a >> 16];
201 UInt sm_off = a & 0xFFFF;
202 PROF_EVENT(20);
203# if 0
204 if (IS_DISTINGUISHED_SM(sm))
205 VG_(message)(Vg_DebugMsg,
206 "accessed distinguished 2ndary (A)map! 0x%x\n", a);
207# endif
208 return BITARR_TEST(sm->abits, sm_off)
209 ? VGM_BIT_INVALID : VGM_BIT_VALID;
210}
211
sewardj56867352003-10-12 10:27:06 +0000212static /* __inline__ */ void set_abit ( Addr a, UChar abit )
njn25e49d8e72002-09-23 09:36:25 +0000213{
214 AcSecMap* sm;
215 UInt sm_off;
216 PROF_EVENT(22);
217 ENSURE_MAPPABLE(a, "set_abit");
218 sm = primary_map[a >> 16];
219 sm_off = a & 0xFFFF;
220 if (abit)
221 BITARR_SET(sm->abits, sm_off);
222 else
223 BITARR_CLEAR(sm->abits, sm_off);
224}
225
226
227/* Reading/writing of the bitmaps, for aligned word-sized accesses. */
228
229static __inline__ UChar get_abits4_ALIGNED ( Addr a )
230{
231 AcSecMap* sm;
232 UInt sm_off;
233 UChar abits8;
234 PROF_EVENT(24);
235# ifdef VG_DEBUG_MEMORY
njnedfa0f62004-11-30 18:08:05 +0000236 tl_assert(IS_4_ALIGNED(a));
njn25e49d8e72002-09-23 09:36:25 +0000237# endif
238 sm = primary_map[a >> 16];
239 sm_off = a & 0xFFFF;
240 abits8 = sm->abits[sm_off >> 3];
241 abits8 >>= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
242 abits8 &= 0x0F;
243 return abits8;
244}
245
246
247
248/*------------------------------------------------------------*/
249/*--- Setting permissions over address ranges. ---*/
250/*------------------------------------------------------------*/
251
sewardj56867352003-10-12 10:27:06 +0000252static /* __inline__ */
nethercote451eae92004-11-02 13:06:32 +0000253void set_address_range_perms ( Addr a, SizeT len, UInt example_a_bit )
njn25e49d8e72002-09-23 09:36:25 +0000254{
255 UChar abyte8;
256 UInt sm_off;
257 AcSecMap* sm;
258
259 PROF_EVENT(30);
260
261 if (len == 0)
262 return;
263
264 if (len > 100 * 1000 * 1000) {
265 VG_(message)(Vg_UserMsg,
266 "Warning: set address range perms: "
267 "large range %u, a %d",
268 len, example_a_bit );
269 }
270
271 VGP_PUSHCC(VgpSetMem);
272
273 /* Requests to change permissions of huge address ranges may
274 indicate bugs in our machinery. 30,000,000 is arbitrary, but so
275 far all legitimate requests have fallen beneath that size. */
276 /* 4 Mar 02: this is just stupid; get rid of it. */
njnca82cc02004-11-22 17:18:48 +0000277 /* tl_assert(len < 30000000); */
njn25e49d8e72002-09-23 09:36:25 +0000278
279 /* Check the permissions make sense. */
njnca82cc02004-11-22 17:18:48 +0000280 tl_assert(example_a_bit == VGM_BIT_VALID
njn25e49d8e72002-09-23 09:36:25 +0000281 || example_a_bit == VGM_BIT_INVALID);
282
283 /* In order that we can charge through the address space at 8
284 bytes/main-loop iteration, make up some perms. */
285 abyte8 = (example_a_bit << 7)
286 | (example_a_bit << 6)
287 | (example_a_bit << 5)
288 | (example_a_bit << 4)
289 | (example_a_bit << 3)
290 | (example_a_bit << 2)
291 | (example_a_bit << 1)
292 | (example_a_bit << 0);
293
294# ifdef VG_DEBUG_MEMORY
295 /* Do it ... */
296 while (True) {
297 PROF_EVENT(31);
298 if (len == 0) break;
299 set_abit ( a, example_a_bit );
300 set_vbyte ( a, vbyte );
301 a++;
302 len--;
303 }
304
305# else
306 /* Slowly do parts preceding 8-byte alignment. */
307 while (True) {
308 PROF_EVENT(31);
309 if (len == 0) break;
310 if ((a % 8) == 0) break;
311 set_abit ( a, example_a_bit );
312 a++;
313 len--;
314 }
315
316 if (len == 0) {
317 VGP_POPCC(VgpSetMem);
318 return;
319 }
njnca82cc02004-11-22 17:18:48 +0000320 tl_assert((a % 8) == 0 && len > 0);
njn25e49d8e72002-09-23 09:36:25 +0000321
322 /* Once aligned, go fast. */
323 while (True) {
324 PROF_EVENT(32);
325 if (len < 8) break;
326 ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
327 sm = primary_map[a >> 16];
328 sm_off = a & 0xFFFF;
329 sm->abits[sm_off >> 3] = abyte8;
330 a += 8;
331 len -= 8;
332 }
333
334 if (len == 0) {
335 VGP_POPCC(VgpSetMem);
336 return;
337 }
njnca82cc02004-11-22 17:18:48 +0000338 tl_assert((a % 8) == 0 && len > 0 && len < 8);
njn25e49d8e72002-09-23 09:36:25 +0000339
340 /* Finish the upper fragment. */
341 while (True) {
342 PROF_EVENT(33);
343 if (len == 0) break;
344 set_abit ( a, example_a_bit );
345 a++;
346 len--;
347 }
348# endif
349
350 /* Check that zero page and highest page have not been written to
351 -- this could happen with buggy syscall wrappers. Today
352 (2001-04-26) had precisely such a problem with __NR_setitimer. */
njn26f02512004-11-22 18:33:15 +0000353 tl_assert(TL_(cheap_sanity_check)());
njn25e49d8e72002-09-23 09:36:25 +0000354 VGP_POPCC(VgpSetMem);
355}
356
357/* Set permissions for address ranges ... */
358
nethercote451eae92004-11-02 13:06:32 +0000359static void ac_make_noaccess ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000360{
361 PROF_EVENT(35);
njn5c004e42002-11-18 11:04:50 +0000362 DEBUG("ac_make_noaccess(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000363 set_address_range_perms ( a, len, VGM_BIT_INVALID );
364}
365
nethercote451eae92004-11-02 13:06:32 +0000366static void ac_make_accessible ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000367{
njn5c004e42002-11-18 11:04:50 +0000368 PROF_EVENT(38);
369 DEBUG("ac_make_accessible(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000370 set_address_range_perms ( a, len, VGM_BIT_VALID );
371}
372
njn9b007f62003-04-07 14:40:25 +0000373static __inline__
374void make_aligned_word_noaccess(Addr a)
375{
376 AcSecMap* sm;
377 UInt sm_off;
378 UChar mask;
379
380 VGP_PUSHCC(VgpESPAdj);
381 ENSURE_MAPPABLE(a, "make_aligned_word_noaccess");
382 sm = primary_map[a >> 16];
383 sm_off = a & 0xFFFF;
384 mask = 0x0F;
385 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
386 /* mask now contains 1s where we wish to make address bits invalid (1s). */
387 sm->abits[sm_off >> 3] |= mask;
388 VGP_POPCC(VgpESPAdj);
389}
390
391static __inline__
392void make_aligned_word_accessible(Addr a)
393{
394 AcSecMap* sm;
395 UInt sm_off;
396 UChar mask;
397
398 VGP_PUSHCC(VgpESPAdj);
399 ENSURE_MAPPABLE(a, "make_aligned_word_accessible");
400 sm = primary_map[a >> 16];
401 sm_off = a & 0xFFFF;
402 mask = 0x0F;
403 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
404 /* mask now contains 1s where we wish to make address bits
405 invalid (0s). */
406 sm->abits[sm_off >> 3] &= ~mask;
407 VGP_POPCC(VgpESPAdj);
408}
409
410/* Nb: by "aligned" here we mean 8-byte aligned */
411static __inline__
412void make_aligned_doubleword_accessible(Addr a)
413{
414 AcSecMap* sm;
415 UInt sm_off;
416
417 VGP_PUSHCC(VgpESPAdj);
418 ENSURE_MAPPABLE(a, "make_aligned_doubleword_accessible");
419 sm = primary_map[a >> 16];
420 sm_off = a & 0xFFFF;
421 sm->abits[sm_off >> 3] = VGM_BYTE_VALID;
422 VGP_POPCC(VgpESPAdj);
423}
424
425static __inline__
426void make_aligned_doubleword_noaccess(Addr a)
427{
428 AcSecMap* sm;
429 UInt sm_off;
430
431 VGP_PUSHCC(VgpESPAdj);
432 ENSURE_MAPPABLE(a, "make_aligned_doubleword_noaccess");
433 sm = primary_map[a >> 16];
434 sm_off = a & 0xFFFF;
435 sm->abits[sm_off >> 3] = VGM_BYTE_INVALID;
436 VGP_POPCC(VgpESPAdj);
437}
438
439/* The %esp update handling functions */
440ESP_UPDATE_HANDLERS ( make_aligned_word_accessible,
441 make_aligned_word_noaccess,
442 make_aligned_doubleword_accessible,
443 make_aligned_doubleword_noaccess,
444 ac_make_accessible,
445 ac_make_noaccess
446 );
447
448
njn25e49d8e72002-09-23 09:36:25 +0000449/* Block-copy permissions (needed for implementing realloc()). */
450
nethercote451eae92004-11-02 13:06:32 +0000451static void ac_copy_address_range_state ( Addr src, Addr dst, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000452{
453 UInt i;
454
njn5c004e42002-11-18 11:04:50 +0000455 DEBUG("ac_copy_address_range_state\n");
njn25e49d8e72002-09-23 09:36:25 +0000456
457 PROF_EVENT(40);
458 for (i = 0; i < len; i++) {
459 UChar abit = get_abit ( src+i );
460 PROF_EVENT(41);
461 set_abit ( dst+i, abit );
462 }
463}
464
465
466/* Check permissions for address range. If inadequate permissions
467 exist, *bad_addr is set to the offending address, so the caller can
468 know what it is. */
469
njn5c004e42002-11-18 11:04:50 +0000470static __inline__
nethercote451eae92004-11-02 13:06:32 +0000471Bool ac_check_accessible ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000472{
473 UInt i;
474 UChar abit;
njn5c004e42002-11-18 11:04:50 +0000475 PROF_EVENT(48);
njn25e49d8e72002-09-23 09:36:25 +0000476 for (i = 0; i < len; i++) {
njn5c004e42002-11-18 11:04:50 +0000477 PROF_EVENT(49);
njn25e49d8e72002-09-23 09:36:25 +0000478 abit = get_abit(a);
479 if (abit == VGM_BIT_INVALID) {
480 if (bad_addr != NULL) *bad_addr = a;
481 return False;
482 }
483 a++;
484 }
485 return True;
486}
487
sewardjecf8e102003-07-12 12:11:39 +0000488/* The opposite; check that an address range is inaccessible. */
489static
nethercote451eae92004-11-02 13:06:32 +0000490Bool ac_check_noaccess ( Addr a, SizeT len, Addr* bad_addr )
sewardjecf8e102003-07-12 12:11:39 +0000491{
492 UInt i;
493 UChar abit;
494 PROF_EVENT(48);
495 for (i = 0; i < len; i++) {
496 PROF_EVENT(49);
497 abit = get_abit(a);
498 if (abit == VGM_BIT_VALID) {
499 if (bad_addr != NULL) *bad_addr = a;
500 return False;
501 }
502 a++;
503 }
504 return True;
505}
506
njn25e49d8e72002-09-23 09:36:25 +0000507/* Check a zero-terminated ascii string. Tricky -- don't want to
508 examine the actual bytes, to find the end, until we're sure it is
509 safe to do so. */
510
njn5c004e42002-11-18 11:04:50 +0000511static __inline__
512Bool ac_check_readable_asciiz ( Addr a, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000513{
514 UChar abit;
515 PROF_EVENT(46);
njn5c004e42002-11-18 11:04:50 +0000516 DEBUG("ac_check_readable_asciiz\n");
njn25e49d8e72002-09-23 09:36:25 +0000517 while (True) {
518 PROF_EVENT(47);
519 abit = get_abit(a);
520 if (abit != VGM_BIT_VALID) {
521 if (bad_addr != NULL) *bad_addr = a;
522 return False;
523 }
524 /* Ok, a is safe to read. */
525 if (* ((UChar*)a) == 0) return True;
526 a++;
527 }
528}
529
530
531/*------------------------------------------------------------*/
532/*--- Memory event handlers ---*/
533/*------------------------------------------------------------*/
534
njn5c004e42002-11-18 11:04:50 +0000535static __inline__
njn72718642003-07-24 08:45:32 +0000536void ac_check_is_accessible ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000537 Char* s, Addr base, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000538{
539 Bool ok;
540 Addr bad_addr;
541
542 VGP_PUSHCC(VgpCheckMem);
543
njn5c004e42002-11-18 11:04:50 +0000544 ok = ac_check_accessible ( base, size, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000545 if (!ok) {
546 switch (part) {
547 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +0000548 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
549 /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000550 break;
551
njn25e49d8e72002-09-23 09:36:25 +0000552 case Vg_CoreSignal:
njnca82cc02004-11-22 17:18:48 +0000553 tl_assert(isWrite); /* Should only happen with isWrite case */
njn5c004e42002-11-18 11:04:50 +0000554 /* fall through */
njn25e49d8e72002-09-23 09:36:25 +0000555 case Vg_CorePThread:
nethercote8b76fe52004-11-08 19:20:09 +0000556 MAC_(record_core_mem_error)( tid, /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000557 break;
558
559 /* If we're being asked to jump to a silly address, record an error
560 message before potentially crashing the entire system. */
561 case Vg_CoreTranslate:
njnca82cc02004-11-22 17:18:48 +0000562 tl_assert(!isWrite); /* Should only happen with !isWrite case */
njn72718642003-07-24 08:45:32 +0000563 MAC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000564 break;
565
566 default:
njn67993252004-11-22 18:02:32 +0000567 VG_(tool_panic)("ac_check_is_accessible: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +0000568 }
569 }
njn5c004e42002-11-18 11:04:50 +0000570
njn25e49d8e72002-09-23 09:36:25 +0000571 VGP_POPCC(VgpCheckMem);
572}
573
574static
njn72718642003-07-24 08:45:32 +0000575void ac_check_is_writable ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000576 Char* s, Addr base, SizeT size )
njn5c004e42002-11-18 11:04:50 +0000577{
njn72718642003-07-24 08:45:32 +0000578 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/True );
njn5c004e42002-11-18 11:04:50 +0000579}
580
581static
njn72718642003-07-24 08:45:32 +0000582void ac_check_is_readable ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000583 Char* s, Addr base, SizeT size )
njn5c004e42002-11-18 11:04:50 +0000584{
njn72718642003-07-24 08:45:32 +0000585 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/False );
njn5c004e42002-11-18 11:04:50 +0000586}
587
588static
njn72718642003-07-24 08:45:32 +0000589void ac_check_is_readable_asciiz ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000590 Char* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +0000591{
592 Bool ok = True;
593 Addr bad_addr;
njn25e49d8e72002-09-23 09:36:25 +0000594
595 VGP_PUSHCC(VgpCheckMem);
596
njnca82cc02004-11-22 17:18:48 +0000597 tl_assert(part == Vg_CoreSysCall);
njn5c004e42002-11-18 11:04:50 +0000598 ok = ac_check_readable_asciiz ( (Addr)str, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000599 if (!ok) {
nethercote8b76fe52004-11-08 19:20:09 +0000600 MAC_(record_param_error) ( tid, bad_addr, /*IsReg*/False,
601 /*IsUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +0000602 }
603
604 VGP_POPCC(VgpCheckMem);
605}
606
607static
nethercote451eae92004-11-02 13:06:32 +0000608void ac_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +0000609{
njn1f3a9092002-10-04 09:22:30 +0000610 /* Ignore the permissions, just make it readable. Seems to work... */
njn25e49d8e72002-09-23 09:36:25 +0000611 DEBUG("new_mem_startup(%p, %u, rr=%u, ww=%u, xx=%u)\n", a,len,rr,ww,xx);
njn5c004e42002-11-18 11:04:50 +0000612 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000613}
614
615static
nethercote451eae92004-11-02 13:06:32 +0000616void ac_new_mem_heap ( Addr a, SizeT len, Bool is_inited )
njn25e49d8e72002-09-23 09:36:25 +0000617{
njn5c004e42002-11-18 11:04:50 +0000618 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000619}
620
621static
nethercote451eae92004-11-02 13:06:32 +0000622void ac_set_perms (Addr a, SizeT len, Bool rr, Bool ww, Bool xx)
njn25e49d8e72002-09-23 09:36:25 +0000623{
njn5c004e42002-11-18 11:04:50 +0000624 DEBUG("ac_set_perms(%p, %u, rr=%u ww=%u, xx=%u)\n",
sewardj40f8ebe2002-10-23 21:46:13 +0000625 a, len, rr, ww, xx);
njn25e49d8e72002-09-23 09:36:25 +0000626 if (rr || ww || xx) {
njn5c004e42002-11-18 11:04:50 +0000627 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000628 } else {
njn5c004e42002-11-18 11:04:50 +0000629 ac_make_noaccess(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000630 }
631}
632
njncf45fd42004-11-24 16:30:22 +0000633static
634void ac_post_mem_write(CorePart part, ThreadId tid, Addr a, SizeT len)
635{
636 ac_make_accessible(a, len);
637}
638
njn25e49d8e72002-09-23 09:36:25 +0000639
640/*------------------------------------------------------------*/
641/*--- Functions called directly from generated code. ---*/
642/*------------------------------------------------------------*/
643
644static __inline__ UInt rotateRight16 ( UInt x )
645{
646 /* Amazingly, gcc turns this into a single rotate insn. */
647 return (x >> 16) | (x << 16);
648}
649
njn25e49d8e72002-09-23 09:36:25 +0000650static __inline__ UInt shiftRight16 ( UInt x )
651{
652 return x >> 16;
653}
654
655
656/* Read/write 1/2/4 sized V bytes, and emit an address error if
657 needed. */
658
njn5c004e42002-11-18 11:04:50 +0000659/* ac_helperc_ACCESS{1,2,4} handle the common case fast.
njn25e49d8e72002-09-23 09:36:25 +0000660 Under all other circumstances, it defers to the relevant _SLOWLY
661 function, which can handle all situations.
662*/
njnc2699f62003-09-05 23:29:33 +0000663static __inline__ void ac_helperc_ACCESS4 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000664{
665# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000666 return ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000667# else
668 UInt sec_no = rotateRight16(a) & 0x3FFFF;
njnda2e36d2003-09-30 13:33:24 +0000669 AcSecMap* sm = primary_map[sec_no];
njn25e49d8e72002-09-23 09:36:25 +0000670 UInt a_off = (a & 0xFFFF) >> 3;
671 UChar abits = sm->abits[a_off];
672 abits >>= (a & 4);
673 abits &= 15;
njn5c004e42002-11-18 11:04:50 +0000674 PROF_EVENT(66);
njn25e49d8e72002-09-23 09:36:25 +0000675 if (abits == VGM_NIBBLE_VALID) {
676 /* Handle common case quickly: a is suitably aligned, is mapped,
677 and is addressible. So just return. */
678 return;
679 } else {
680 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000681 ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000682 }
683# endif
684}
685
njnc2699f62003-09-05 23:29:33 +0000686static __inline__ void ac_helperc_ACCESS2 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000687{
688# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000689 return ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000690# else
691 UInt sec_no = rotateRight16(a) & 0x1FFFF;
692 AcSecMap* sm = primary_map[sec_no];
693 UInt a_off = (a & 0xFFFF) >> 3;
njn5c004e42002-11-18 11:04:50 +0000694 PROF_EVENT(67);
njn25e49d8e72002-09-23 09:36:25 +0000695 if (sm->abits[a_off] == VGM_BYTE_VALID) {
696 /* Handle common case quickly. */
697 return;
698 } else {
699 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000700 ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000701 }
702# endif
703}
704
njnc2699f62003-09-05 23:29:33 +0000705static __inline__ void ac_helperc_ACCESS1 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000706{
707# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000708 return ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000709# else
710 UInt sec_no = shiftRight16(a);
711 AcSecMap* sm = primary_map[sec_no];
712 UInt a_off = (a & 0xFFFF) >> 3;
njn5c004e42002-11-18 11:04:50 +0000713 PROF_EVENT(68);
njn25e49d8e72002-09-23 09:36:25 +0000714 if (sm->abits[a_off] == VGM_BYTE_VALID) {
715 /* Handle common case quickly. */
716 return;
717 } else {
718 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000719 ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000720 }
721# endif
722}
723
nethercoteeec46302004-08-23 15:06:23 +0000724REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000725static void ach_LOAD4 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000726{
727 ac_helperc_ACCESS4 ( a, /*isWrite*/False );
728}
nethercoteeec46302004-08-23 15:06:23 +0000729REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000730static void ach_STORE4 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000731{
732 ac_helperc_ACCESS4 ( a, /*isWrite*/True );
733}
734
nethercoteeec46302004-08-23 15:06:23 +0000735REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000736static void ach_LOAD2 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000737{
738 ac_helperc_ACCESS2 ( a, /*isWrite*/False );
739}
nethercoteeec46302004-08-23 15:06:23 +0000740REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000741static void ach_STORE2 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000742{
743 ac_helperc_ACCESS2 ( a, /*isWrite*/True );
744}
745
nethercoteeec46302004-08-23 15:06:23 +0000746REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000747static void ach_LOAD1 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000748{
749 ac_helperc_ACCESS1 ( a, /*isWrite*/False );
750}
nethercoteeec46302004-08-23 15:06:23 +0000751REGPARM(1)
sewardj9f649aa2004-11-22 20:38:40 +0000752static void ach_STORE1 ( Addr a )
njnc2699f62003-09-05 23:29:33 +0000753{
754 ac_helperc_ACCESS1 ( a, /*isWrite*/True );
755}
756
njn25e49d8e72002-09-23 09:36:25 +0000757
758/*------------------------------------------------------------*/
759/*--- Fallback functions to handle cases that the above ---*/
njnc2699f62003-09-05 23:29:33 +0000760/*--- ac_helperc_ACCESS{1,2,4} can't manage. ---*/
njn25e49d8e72002-09-23 09:36:25 +0000761/*------------------------------------------------------------*/
762
njnc2699f62003-09-05 23:29:33 +0000763static void ac_ACCESS4_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000764{
765 Bool a0ok, a1ok, a2ok, a3ok;
766
njn5c004e42002-11-18 11:04:50 +0000767 PROF_EVENT(76);
njn25e49d8e72002-09-23 09:36:25 +0000768
769 /* First establish independently the addressibility of the 4 bytes
770 involved. */
771 a0ok = get_abit(a+0) == VGM_BIT_VALID;
772 a1ok = get_abit(a+1) == VGM_BIT_VALID;
773 a2ok = get_abit(a+2) == VGM_BIT_VALID;
774 a3ok = get_abit(a+3) == VGM_BIT_VALID;
775
776 /* Now distinguish 3 cases */
777
778 /* Case 1: the address is completely valid, so:
779 - no addressing error
780 */
781 if (a0ok && a1ok && a2ok && a3ok) {
782 return;
783 }
784
785 /* Case 2: the address is completely invalid.
786 - emit addressing error
787 */
788 /* VG_(printf)("%p (%d %d %d %d)\n", a, a0ok, a1ok, a2ok, a3ok); */
njn43c799e2003-04-08 00:08:52 +0000789 if (!MAC_(clo_partial_loads_ok)
njn25e49d8e72002-09-23 09:36:25 +0000790 || ((a & 3) != 0)
791 || (!a0ok && !a1ok && !a2ok && !a3ok)) {
njnc2699f62003-09-05 23:29:33 +0000792 MAC_(record_address_error)( VG_(get_current_tid)(), a, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000793 return;
794 }
795
796 /* Case 3: the address is partially valid.
797 - no addressing error
njn43c799e2003-04-08 00:08:52 +0000798 Case 3 is only allowed if MAC_(clo_partial_loads_ok) is True
njn25e49d8e72002-09-23 09:36:25 +0000799 (which is the default), and the address is 4-aligned.
800 If not, Case 2 will have applied.
801 */
njnca82cc02004-11-22 17:18:48 +0000802 tl_assert(MAC_(clo_partial_loads_ok));
njn25e49d8e72002-09-23 09:36:25 +0000803 {
804 return;
805 }
806}
807
njnc2699f62003-09-05 23:29:33 +0000808static void ac_ACCESS2_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000809{
810 /* Check the address for validity. */
811 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000812 PROF_EVENT(77);
njn25e49d8e72002-09-23 09:36:25 +0000813
814 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
815 if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
816
817 /* If an address error has happened, report it. */
818 if (aerr) {
njnc2699f62003-09-05 23:29:33 +0000819 MAC_(record_address_error)( VG_(get_current_tid)(), a, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000820 }
821}
822
njnc2699f62003-09-05 23:29:33 +0000823static void ac_ACCESS1_SLOWLY ( Addr a, Bool isWrite)
njn25e49d8e72002-09-23 09:36:25 +0000824{
825 /* Check the address for validity. */
826 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000827 PROF_EVENT(78);
njn25e49d8e72002-09-23 09:36:25 +0000828
829 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
830
831 /* If an address error has happened, report it. */
832 if (aerr) {
njnc2699f62003-09-05 23:29:33 +0000833 MAC_(record_address_error)( VG_(get_current_tid)(), a, 1, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000834 }
835}
836
837
838/* ---------------------------------------------------------------------
839 FPU load and store checks, called from generated code.
840 ------------------------------------------------------------------ */
841
sewardj56867352003-10-12 10:27:06 +0000842static
nethercote928a5f72004-11-03 18:10:37 +0000843void ac_fpu_ACCESS_check ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000844{
845 /* Ensure the read area is both addressible and valid (ie,
846 readable). If there's an address error, don't report a value
847 error too; but if there isn't an address error, check for a
848 value error.
849
850 Try to be reasonably fast on the common case; wimp out and defer
njn5c004e42002-11-18 11:04:50 +0000851 to ac_fpu_ACCESS_check_SLOWLY for everything else. */
njn25e49d8e72002-09-23 09:36:25 +0000852
853 AcSecMap* sm;
854 UInt sm_off, a_off;
855 Addr addr4;
856
njn5c004e42002-11-18 11:04:50 +0000857 PROF_EVENT(90);
njn25e49d8e72002-09-23 09:36:25 +0000858
859# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000860 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000861# else
862
863 if (size == 4) {
njnedfa0f62004-11-30 18:08:05 +0000864 if (!IS_4_ALIGNED(addr)) goto slow4;
njn5c004e42002-11-18 11:04:50 +0000865 PROF_EVENT(91);
njn25e49d8e72002-09-23 09:36:25 +0000866 /* Properly aligned. */
867 sm = primary_map[addr >> 16];
868 sm_off = addr & 0xFFFF;
869 a_off = sm_off >> 3;
870 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow4;
871 /* Properly aligned and addressible. */
872 return;
873 slow4:
njnc2699f62003-09-05 23:29:33 +0000874 ac_fpu_ACCESS_check_SLOWLY ( addr, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000875 return;
876 }
877
878 if (size == 8) {
njnedfa0f62004-11-30 18:08:05 +0000879 if (!IS_4_ALIGNED(addr)) goto slow8;
njn5c004e42002-11-18 11:04:50 +0000880 PROF_EVENT(92);
njn25e49d8e72002-09-23 09:36:25 +0000881 /* Properly aligned. Do it in two halves. */
882 addr4 = addr + 4;
883 /* First half. */
884 sm = primary_map[addr >> 16];
885 sm_off = addr & 0xFFFF;
886 a_off = sm_off >> 3;
887 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
888 /* First half properly aligned and addressible. */
889 /* Second half. */
890 sm = primary_map[addr4 >> 16];
891 sm_off = addr4 & 0xFFFF;
892 a_off = sm_off >> 3;
893 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
894 /* Second half properly aligned and addressible. */
895 /* Both halves properly aligned and addressible. */
896 return;
897 slow8:
njnc2699f62003-09-05 23:29:33 +0000898 ac_fpu_ACCESS_check_SLOWLY ( addr, 8, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000899 return;
900 }
901
902 /* Can't be bothered to huff'n'puff to make these (allegedly) rare
903 cases go quickly. */
904 if (size == 2) {
njn5c004e42002-11-18 11:04:50 +0000905 PROF_EVENT(93);
njnc2699f62003-09-05 23:29:33 +0000906 ac_fpu_ACCESS_check_SLOWLY ( addr, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000907 return;
908 }
909
jsewardfca60182004-01-04 23:30:55 +0000910 if (size == 16 || size == 10 || size == 28 || size == 108 || size == 512) {
njn5c004e42002-11-18 11:04:50 +0000911 PROF_EVENT(94);
njnc2699f62003-09-05 23:29:33 +0000912 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000913 return;
914 }
915
916 VG_(printf)("size is %d\n", size);
njn67993252004-11-22 18:02:32 +0000917 VG_(tool_panic)("fpu_ACCESS_check: unhandled size");
njn25e49d8e72002-09-23 09:36:25 +0000918# endif
919}
920
nethercoteeec46302004-08-23 15:06:23 +0000921REGPARM(2)
sewardj9f649aa2004-11-22 20:38:40 +0000922static void ach_LOADN ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000923{
924 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/False );
925}
926
nethercoteeec46302004-08-23 15:06:23 +0000927REGPARM(2)
sewardj9f649aa2004-11-22 20:38:40 +0000928static void ach_STOREN ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000929{
930 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/True );
931}
njn25e49d8e72002-09-23 09:36:25 +0000932
sewardjd62e03b2004-12-10 12:01:14 +0000933
njn25e49d8e72002-09-23 09:36:25 +0000934/* ---------------------------------------------------------------------
935 Slow, general cases for FPU access checks.
936 ------------------------------------------------------------------ */
937
nethercote928a5f72004-11-03 18:10:37 +0000938void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000939{
940 Int i;
941 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000942 PROF_EVENT(100);
njn25e49d8e72002-09-23 09:36:25 +0000943 for (i = 0; i < size; i++) {
njn5c004e42002-11-18 11:04:50 +0000944 PROF_EVENT(101);
njn25e49d8e72002-09-23 09:36:25 +0000945 if (get_abit(addr+i) != VGM_BIT_VALID)
946 aerr = True;
947 }
948
949 if (aerr) {
njnc2699f62003-09-05 23:29:33 +0000950 MAC_(record_address_error)( VG_(get_current_tid)(), addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000951 }
952}
953
954
955/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000956/*--- Our instrumenter ---*/
957/*------------------------------------------------------------*/
958
sewardj9f649aa2004-11-22 20:38:40 +0000959IRBB* TL_(instrument)(IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
njn25e49d8e72002-09-23 09:36:25 +0000960{
sewardj9f649aa2004-11-22 20:38:40 +0000961 Int i, hsz;
962 IRStmt* st;
963 IRExpr* data;
964 IRExpr* aexpr;
965 IRExpr* guard;
966 IRDirty* di;
967 Bool isLoad;
njn25e49d8e72002-09-23 09:36:25 +0000968
sewardj9f649aa2004-11-22 20:38:40 +0000969 /* Set up BB */
970 IRBB* bb = emptyIRBB();
971 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
972 bb->next = dopyIRExpr(bb_in->next);
973 bb->jumpkind = bb_in->jumpkind;
njn25e49d8e72002-09-23 09:36:25 +0000974
sewardj9f649aa2004-11-22 20:38:40 +0000975 /* No loads to consider in ->next. */
976 tl_assert(isAtom(bb_in->next));
njn25e49d8e72002-09-23 09:36:25 +0000977
sewardj9f649aa2004-11-22 20:38:40 +0000978 for (i = 0; i < bb_in->stmts_used; i++) {
979 st = bb_in->stmts[i];
980 if (!st) continue;
njn25e49d8e72002-09-23 09:36:25 +0000981
sewardj9f649aa2004-11-22 20:38:40 +0000982 /* Examine each stmt in turn to figure out if it needs to be
983 preceded by a memory access check. If so, collect up the
984 relevant pieces of information. */
985 hsz = 0;
986 aexpr = NULL;
987 guard = NULL;
988 isLoad = True;
njn25e49d8e72002-09-23 09:36:25 +0000989
sewardj9f649aa2004-11-22 20:38:40 +0000990 switch (st->tag) {
991
992 case Ist_Tmp:
993 data = st->Ist.Tmp.data;
994 if (data->tag == Iex_LDle) {
995 aexpr = data->Iex.LDle.addr;
996 hsz = sizeofIRType(data->Iex.LDle.ty);
997 isLoad = True;
998 }
999 break;
1000
1001 case Ist_STle:
1002 data = st->Ist.STle.data;
1003 aexpr = st->Ist.STle.addr;
1004 tl_assert(isAtom(data));
1005 tl_assert(isAtom(aexpr));
1006 hsz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
1007 isLoad = False;
1008
1009 case Ist_Put:
1010 tl_assert(isAtom(st->Ist.Put.data));
njn25e49d8e72002-09-23 09:36:25 +00001011 break;
1012
sewardj9f649aa2004-11-22 20:38:40 +00001013 case Ist_PutI:
1014 tl_assert(isAtom(st->Ist.PutI.ix));
1015 tl_assert(isAtom(st->Ist.PutI.data));
njnc2699f62003-09-05 23:29:33 +00001016 break;
1017
sewardj9f649aa2004-11-22 20:38:40 +00001018 case Ist_Exit:
1019 tl_assert(isAtom(st->Ist.Exit.guard));
njn25e49d8e72002-09-23 09:36:25 +00001020 break;
1021
sewardj9f649aa2004-11-22 20:38:40 +00001022 case Ist_Dirty:
1023 if (st->Ist.Dirty.details->mFx != Ifx_None) {
1024 /* We classify Ifx_Modify as a load. */
1025 isLoad = st->Ist.Dirty.details->mFx != Ifx_Write;
1026 hsz = st->Ist.Dirty.details->mSize;
1027 aexpr = st->Ist.Dirty.details->mAddr;
1028 guard = st->Ist.Dirty.details->guard;
1029 tl_assert(isAtom(aexpr));
1030 }
1031 break;
sewardje3891fa2003-06-15 03:13:48 +00001032
sewardjbd598e12005-01-07 12:10:21 +00001033 case Ist_MFence:
1034 break;
1035
njn25e49d8e72002-09-23 09:36:25 +00001036 default:
sewardj9f649aa2004-11-22 20:38:40 +00001037 VG_(printf)("\n");
1038 ppIRStmt(st);
1039 VG_(printf)("\n");
1040 VG_(tool_panic)("addrcheck: unhandled IRStmt");
njn25e49d8e72002-09-23 09:36:25 +00001041 }
sewardj9f649aa2004-11-22 20:38:40 +00001042
1043 /* If needed, add a helper call. */
1044 if (aexpr) {
1045 tl_assert(hsz > 0);
1046 switch (hsz) {
1047 case 4:
1048 if (isLoad)
1049 di = unsafeIRDirty_0_N( 1, "ach_LOAD4", &ach_LOAD4,
1050 mkIRExprVec_1(aexpr));
1051 else
1052 di = unsafeIRDirty_0_N( 1, "ach_STORE4", &ach_STORE4,
1053 mkIRExprVec_1(aexpr));
1054 break;
1055 case 2:
1056 if (isLoad)
1057 di = unsafeIRDirty_0_N( 1, "ach_LOAD2", &ach_LOAD2,
1058 mkIRExprVec_1(aexpr));
1059 else
1060 di = unsafeIRDirty_0_N( 1, "ach_STORE2", &ach_STORE2,
1061 mkIRExprVec_1(aexpr));
1062 break;
1063 case 1:
1064 if (isLoad)
1065 di = unsafeIRDirty_0_N( 1, "ach_LOAD1", &ach_LOAD1,
1066 mkIRExprVec_1(aexpr));
1067 else
1068 di = unsafeIRDirty_0_N( 1, "ach_STORE1", &ach_STORE1,
1069 mkIRExprVec_1(aexpr));
1070 break;
1071 default:
1072 if (isLoad)
1073 di = unsafeIRDirty_0_N(
1074 2, "ach_LOADN", &ach_LOADN,
1075 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1076 else
1077 di = unsafeIRDirty_0_N(
1078 2, "ach_STOREN", &ach_STOREN,
1079 mkIRExprVec_2(aexpr,mkIRExpr_HWord(hsz)));
1080 break;
1081 }
1082
1083 /* If the call has arisen as a result of a dirty helper which
1084 references memory, we need to inherit the guard from the
1085 dirty helper. */
1086 if (guard)
1087 di->guard = dopyIRExpr(guard);
1088
1089 /* emit the helper call */
1090 addStmtToIRBB( bb, IRStmt_Dirty(di) );
1091
1092 }
1093
1094 /* And finally, copy the expr itself to the output. */
sewardjbd598e12005-01-07 12:10:21 +00001095 addStmtToIRBB( bb, st );
njn25e49d8e72002-09-23 09:36:25 +00001096 }
1097
sewardj9f649aa2004-11-22 20:38:40 +00001098 return bb;
njn25e49d8e72002-09-23 09:36:25 +00001099}
1100
1101
njn25e49d8e72002-09-23 09:36:25 +00001102/*------------------------------------------------------------*/
1103/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
1104/*------------------------------------------------------------*/
1105
sewardja4495682002-10-21 07:29:59 +00001106/* For the memory leak detector, say whether an entire 64k chunk of
1107 address space is possibly in use, or not. If in doubt return
1108 True.
njn25e49d8e72002-09-23 09:36:25 +00001109*/
sewardja4495682002-10-21 07:29:59 +00001110static
1111Bool ac_is_valid_64k_chunk ( UInt chunk_number )
njn25e49d8e72002-09-23 09:36:25 +00001112{
njnca82cc02004-11-22 17:18:48 +00001113 tl_assert(chunk_number >= 0 && chunk_number < 65536);
sewardja4495682002-10-21 07:29:59 +00001114 if (IS_DISTINGUISHED_SM(primary_map[chunk_number])) {
1115 /* Definitely not in use. */
1116 return False;
1117 } else {
1118 return True;
njn25e49d8e72002-09-23 09:36:25 +00001119 }
1120}
1121
1122
sewardja4495682002-10-21 07:29:59 +00001123/* For the memory leak detector, say whether or not a given word
1124 address is to be regarded as valid. */
1125static
1126Bool ac_is_valid_address ( Addr a )
1127{
1128 UChar abits;
njnedfa0f62004-11-30 18:08:05 +00001129 tl_assert(IS_4_ALIGNED(a));
sewardja4495682002-10-21 07:29:59 +00001130 abits = get_abits4_ALIGNED(a);
1131 if (abits == VGM_NIBBLE_VALID) {
1132 return True;
1133 } else {
1134 return False;
1135 }
1136}
1137
1138
nethercote996901a2004-08-03 13:29:09 +00001139/* Leak detector for this tool. We don't actually do anything, merely
sewardja4495682002-10-21 07:29:59 +00001140 run the generic leak detector with suitable parameters for this
nethercote996901a2004-08-03 13:29:09 +00001141 tool. */
sewardj2a99cf62004-11-24 10:44:19 +00001142static void ac_detect_memory_leaks ( ThreadId tid )
njn25e49d8e72002-09-23 09:36:25 +00001143{
sewardj2a99cf62004-11-24 10:44:19 +00001144 MAC_(do_detect_memory_leaks) (
1145 tid, ac_is_valid_64k_chunk, ac_is_valid_address );
njn25e49d8e72002-09-23 09:36:25 +00001146}
1147
1148
1149/* ---------------------------------------------------------------------
1150 Sanity check machinery (permanently engaged).
1151 ------------------------------------------------------------------ */
1152
njn26f02512004-11-22 18:33:15 +00001153Bool TL_(cheap_sanity_check) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001154{
jseward9800fd32004-01-04 23:08:04 +00001155 /* nothing useful we can rapidly check */
1156 return True;
njn25e49d8e72002-09-23 09:36:25 +00001157}
1158
njn26f02512004-11-22 18:33:15 +00001159Bool TL_(expensive_sanity_check) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001160{
1161 Int i;
1162
1163 /* Make sure nobody changed the distinguished secondary. */
1164 for (i = 0; i < 8192; i++)
1165 if (distinguished_secondary_map.abits[i] != VGM_BYTE_INVALID)
1166 return False;
1167
1168 /* Make sure that the upper 3/4 of the primary map hasn't
1169 been messed with. */
1170 for (i = 65536; i < 262144; i++)
1171 if (primary_map[i] != & distinguished_secondary_map)
1172 return False;
1173
1174 return True;
1175}
1176
njn47363ab2003-04-21 13:24:40 +00001177/*------------------------------------------------------------*/
1178/*--- Client requests ---*/
1179/*------------------------------------------------------------*/
1180
njn26f02512004-11-22 18:33:15 +00001181Bool TL_(handle_client_request) ( ThreadId tid, UWord* arg, UWord *ret )
sewardjd8033d92002-12-08 22:16:58 +00001182{
sewardjbf310d92002-12-28 13:09:57 +00001183#define IGNORE(what) \
1184 do { \
1185 if (moans-- > 0) { \
1186 VG_(message)(Vg_UserMsg, \
1187 "Warning: Addrcheck: ignoring `%s' request.", what); \
1188 VG_(message)(Vg_UserMsg, \
nethercote137bc552003-11-14 17:47:54 +00001189 " To honour this request, rerun with --tool=memcheck."); \
sewardjbf310d92002-12-28 13:09:57 +00001190 } \
1191 } while (0)
1192
sewardjbf310d92002-12-28 13:09:57 +00001193 static Int moans = 3;
sewardjd8033d92002-12-08 22:16:58 +00001194
1195 /* Overload memcheck client reqs */
njnfc26ff92004-11-22 19:12:49 +00001196 if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
sewardjd62e03b2004-12-10 12:01:14 +00001197 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
1198 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
1199 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
1200 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
1201 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
1202 && VG_USERREQ__MEMPOOL_FREE != arg[0])
sewardjd8033d92002-12-08 22:16:58 +00001203 return False;
1204
1205 switch (arg[0]) {
1206 case VG_USERREQ__DO_LEAK_CHECK:
sewardj2a99cf62004-11-24 10:44:19 +00001207 ac_detect_memory_leaks(tid);
sewardjd8033d92002-12-08 22:16:58 +00001208 *ret = 0; /* return value is meaningless */
1209 break;
1210
sewardjbf310d92002-12-28 13:09:57 +00001211 /* Ignore these */
sewardjd8033d92002-12-08 22:16:58 +00001212 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
sewardjbf310d92002-12-28 13:09:57 +00001213 IGNORE("VALGRIND_CHECK_WRITABLE");
1214 return False;
sewardjd8033d92002-12-08 22:16:58 +00001215 case VG_USERREQ__CHECK_READABLE: /* check readable */
sewardjbf310d92002-12-28 13:09:57 +00001216 IGNORE("VALGRIND_CHECK_READABLE");
1217 return False;
sewardjd8033d92002-12-08 22:16:58 +00001218 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
sewardjbf310d92002-12-28 13:09:57 +00001219 IGNORE("VALGRIND_MAKE_NOACCESS");
1220 return False;
sewardjd8033d92002-12-08 22:16:58 +00001221 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
sewardjbf310d92002-12-28 13:09:57 +00001222 IGNORE("VALGRIND_MAKE_WRITABLE");
1223 return False;
sewardjd8033d92002-12-08 22:16:58 +00001224 case VG_USERREQ__MAKE_READABLE: /* make readable */
sewardjbf310d92002-12-28 13:09:57 +00001225 IGNORE("VALGRIND_MAKE_READABLE");
1226 return False;
sewardjd8033d92002-12-08 22:16:58 +00001227 case VG_USERREQ__DISCARD: /* discard */
sewardjbf310d92002-12-28 13:09:57 +00001228 IGNORE("VALGRIND_CHECK_DISCARD");
1229 return False;
sewardjd8033d92002-12-08 22:16:58 +00001230
1231 default:
nethercoted1b64b22004-11-04 18:22:28 +00001232 if (MAC_(handle_common_client_requests)(tid, arg, ret )) {
njn47363ab2003-04-21 13:24:40 +00001233 return True;
1234 } else {
1235 VG_(message)(Vg_UserMsg,
nethercoted1b64b22004-11-04 18:22:28 +00001236 "Warning: unknown addrcheck client request code %llx",
1237 (ULong)arg[0]);
njn47363ab2003-04-21 13:24:40 +00001238 return False;
1239 }
sewardjd8033d92002-12-08 22:16:58 +00001240 }
1241 return True;
sewardjbf310d92002-12-28 13:09:57 +00001242
1243#undef IGNORE
sewardjd8033d92002-12-08 22:16:58 +00001244}
1245
njn25e49d8e72002-09-23 09:36:25 +00001246/*------------------------------------------------------------*/
1247/*--- Setup ---*/
1248/*------------------------------------------------------------*/
1249
njn26f02512004-11-22 18:33:15 +00001250Bool TL_(process_cmd_line_option)(Char* arg)
njn25e49d8e72002-09-23 09:36:25 +00001251{
njn43c799e2003-04-08 00:08:52 +00001252 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001253}
1254
njn26f02512004-11-22 18:33:15 +00001255void TL_(print_usage)(void)
njn25e49d8e72002-09-23 09:36:25 +00001256{
njn3e884182003-04-15 13:03:23 +00001257 MAC_(print_common_usage)();
1258}
1259
njn26f02512004-11-22 18:33:15 +00001260void TL_(print_debug_usage)(void)
njn3e884182003-04-15 13:03:23 +00001261{
1262 MAC_(print_common_debug_usage)();
njn25e49d8e72002-09-23 09:36:25 +00001263}
1264
1265
1266/*------------------------------------------------------------*/
1267/*--- Setup ---*/
1268/*------------------------------------------------------------*/
1269
njn26f02512004-11-22 18:33:15 +00001270void TL_(pre_clo_init)(void)
njn25e49d8e72002-09-23 09:36:25 +00001271{
njn810086f2002-11-14 12:42:47 +00001272 VG_(details_name) ("Addrcheck");
1273 VG_(details_version) (NULL);
1274 VG_(details_description) ("a fine-grained address checker");
1275 VG_(details_copyright_author)(
nethercote08fa9a72004-07-16 17:44:00 +00001276 "Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al.");
nethercote421281e2003-11-20 16:20:55 +00001277 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardj78210aa2002-12-01 02:55:46 +00001278 VG_(details_avg_translation_sizeB) ( 135 );
njn25e49d8e72002-09-23 09:36:25 +00001279
njn810086f2002-11-14 12:42:47 +00001280 VG_(needs_core_errors) ();
njn95ec8702004-11-22 16:46:13 +00001281 VG_(needs_tool_errors) ();
njn810086f2002-11-14 12:42:47 +00001282 VG_(needs_libc_freeres) ();
njn810086f2002-11-14 12:42:47 +00001283 VG_(needs_command_line_options)();
1284 VG_(needs_client_requests) ();
njn810086f2002-11-14 12:42:47 +00001285 VG_(needs_sanity_checks) ();
fitzhardinge98abfc72003-12-16 02:05:15 +00001286 VG_(needs_shadow_memory) ();
njn25e49d8e72002-09-23 09:36:25 +00001287
njn3e884182003-04-15 13:03:23 +00001288 MAC_( new_mem_heap) = & ac_new_mem_heap;
1289 MAC_( ban_mem_heap) = & ac_make_noaccess;
1290 MAC_(copy_mem_heap) = & ac_copy_address_range_state;
1291 MAC_( die_mem_heap) = & ac_make_noaccess;
sewardjecf8e102003-07-12 12:11:39 +00001292 MAC_(check_noaccess) = & ac_check_noaccess;
njn3e884182003-04-15 13:03:23 +00001293
fitzhardinge98abfc72003-12-16 02:05:15 +00001294 VG_(init_new_mem_startup) ( & ac_new_mem_startup );
1295 VG_(init_new_mem_stack_signal) ( & ac_make_accessible );
1296 VG_(init_new_mem_brk) ( & ac_make_accessible );
1297 VG_(init_new_mem_mmap) ( & ac_set_perms );
njn25e49d8e72002-09-23 09:36:25 +00001298
fitzhardinge98abfc72003-12-16 02:05:15 +00001299 VG_(init_copy_mem_remap) ( & ac_copy_address_range_state );
1300 VG_(init_change_mem_mprotect) ( & ac_set_perms );
njn3e884182003-04-15 13:03:23 +00001301
fitzhardinge98abfc72003-12-16 02:05:15 +00001302 VG_(init_die_mem_stack_signal) ( & ac_make_noaccess );
1303 VG_(init_die_mem_brk) ( & ac_make_noaccess );
1304 VG_(init_die_mem_munmap) ( & ac_make_noaccess );
njn3e884182003-04-15 13:03:23 +00001305
fitzhardinge98abfc72003-12-16 02:05:15 +00001306 VG_(init_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
1307 VG_(init_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
1308 VG_(init_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
1309 VG_(init_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
1310 VG_(init_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
1311 VG_(init_new_mem_stack) ( & MAC_(new_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001312
fitzhardinge98abfc72003-12-16 02:05:15 +00001313 VG_(init_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
1314 VG_(init_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
1315 VG_(init_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
1316 VG_(init_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
1317 VG_(init_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
1318 VG_(init_die_mem_stack) ( & MAC_(die_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001319
fitzhardinge98abfc72003-12-16 02:05:15 +00001320 VG_(init_ban_mem_stack) ( & ac_make_noaccess );
njn25e49d8e72002-09-23 09:36:25 +00001321
fitzhardinge98abfc72003-12-16 02:05:15 +00001322 VG_(init_pre_mem_read) ( & ac_check_is_readable );
1323 VG_(init_pre_mem_read_asciiz) ( & ac_check_is_readable_asciiz );
1324 VG_(init_pre_mem_write) ( & ac_check_is_writable );
njnabb14ad2004-11-24 16:57:16 +00001325 VG_(init_post_mem_write) ( & ac_post_mem_write );
njn25e49d8e72002-09-23 09:36:25 +00001326
njn25e49d8e72002-09-23 09:36:25 +00001327 VGP_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
1328 VGP_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
njn9b007f62003-04-07 14:40:25 +00001329 VGP_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
njnd04b7c62002-10-03 14:05:52 +00001330
1331 init_shadow_memory();
njn3e884182003-04-15 13:03:23 +00001332 MAC_(common_pre_clo_init)();
njn5c004e42002-11-18 11:04:50 +00001333}
1334
njn26f02512004-11-22 18:33:15 +00001335void TL_(post_clo_init) ( void )
njn5c004e42002-11-18 11:04:50 +00001336{
1337}
1338
njn26f02512004-11-22 18:33:15 +00001339void TL_(fini) ( Int exitcode )
njn5c004e42002-11-18 11:04:50 +00001340{
njn3e884182003-04-15 13:03:23 +00001341 MAC_(common_fini)( ac_detect_memory_leaks );
njn25e49d8e72002-09-23 09:36:25 +00001342}
1343
njn26f02512004-11-22 18:33:15 +00001344VG_DETERMINE_INTERFACE_VERSION(TL_(pre_clo_init), 1./8)
fitzhardinge98abfc72003-12-16 02:05:15 +00001345
1346
njn25e49d8e72002-09-23 09:36:25 +00001347/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00001348/*--- end ac_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00001349/*--------------------------------------------------------------------*/