blob: 296679a9d1c0d733a981d872a624c936f87d99f0 [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
njn43c799e2003-04-08 00:08:52 +000042void SK_(pp_SkinError) ( 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:
njn43c799e2003-04-08 00:08:52 +000069 MAC_(pp_shared_SkinError)(err);
70 break;
njn25e49d8e72002-09-23 09:36:25 +000071 }
72}
73
74/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000075/*--- Suppressions ---*/
76/*------------------------------------------------------------*/
77
njn810086f2002-11-14 12:42:47 +000078Bool SK_(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
njne427a662002-10-02 11:08:25 +0000236 sk_assert(IS_ALIGNED4_ADDR(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. */
njne427a662002-10-02 11:08:25 +0000277 /* sk_assert(len < 30000000); */
njn25e49d8e72002-09-23 09:36:25 +0000278
279 /* Check the permissions make sense. */
njne427a662002-10-02 11:08:25 +0000280 sk_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 }
njne427a662002-10-02 11:08:25 +0000320 sk_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 }
njne427a662002-10-02 11:08:25 +0000338 sk_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. */
njne427a662002-10-02 11:08:25 +0000353 sk_assert(SK_(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:
njn72718642003-07-24 08:45:32 +0000548 MAC_(record_param_error) ( tid, bad_addr, isWrite, s );
njn25e49d8e72002-09-23 09:36:25 +0000549 break;
550
njn25e49d8e72002-09-23 09:36:25 +0000551 case Vg_CoreSignal:
njn5c004e42002-11-18 11:04:50 +0000552 sk_assert(isWrite); /* Should only happen with isWrite case */
553 /* fall through */
njn25e49d8e72002-09-23 09:36:25 +0000554 case Vg_CorePThread:
njn72718642003-07-24 08:45:32 +0000555 MAC_(record_core_mem_error)( tid, isWrite, s );
njn25e49d8e72002-09-23 09:36:25 +0000556 break;
557
558 /* If we're being asked to jump to a silly address, record an error
559 message before potentially crashing the entire system. */
560 case Vg_CoreTranslate:
njn5c004e42002-11-18 11:04:50 +0000561 sk_assert(!isWrite); /* Should only happen with !isWrite case */
njn72718642003-07-24 08:45:32 +0000562 MAC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000563 break;
564
565 default:
njn5c004e42002-11-18 11:04:50 +0000566 VG_(skin_panic)("ac_check_is_accessible: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +0000567 }
568 }
njn5c004e42002-11-18 11:04:50 +0000569
njn25e49d8e72002-09-23 09:36:25 +0000570 VGP_POPCC(VgpCheckMem);
571}
572
573static
njn72718642003-07-24 08:45:32 +0000574void ac_check_is_writable ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000575 Char* s, Addr base, SizeT size )
njn5c004e42002-11-18 11:04:50 +0000576{
njn72718642003-07-24 08:45:32 +0000577 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/True );
njn5c004e42002-11-18 11:04:50 +0000578}
579
580static
njn72718642003-07-24 08:45:32 +0000581void ac_check_is_readable ( CorePart part, ThreadId tid,
nethercote451eae92004-11-02 13:06:32 +0000582 Char* s, Addr base, SizeT size )
njn5c004e42002-11-18 11:04:50 +0000583{
njn72718642003-07-24 08:45:32 +0000584 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/False );
njn5c004e42002-11-18 11:04:50 +0000585}
586
587static
njn72718642003-07-24 08:45:32 +0000588void ac_check_is_readable_asciiz ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000589 Char* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +0000590{
591 Bool ok = True;
592 Addr bad_addr;
593 /* VG_(message)(Vg_DebugMsg,"check is readable asciiz: 0x%x",str); */
594
595 VGP_PUSHCC(VgpCheckMem);
596
njne427a662002-10-02 11:08:25 +0000597 sk_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) {
njn72718642003-07-24 08:45:32 +0000600 MAC_(record_param_error) ( tid, bad_addr, /*is_writable =*/False, s );
njn25e49d8e72002-09-23 09:36:25 +0000601 }
602
603 VGP_POPCC(VgpCheckMem);
604}
605
606static
nethercote451eae92004-11-02 13:06:32 +0000607void ac_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +0000608{
njn1f3a9092002-10-04 09:22:30 +0000609 /* Ignore the permissions, just make it readable. Seems to work... */
njn25e49d8e72002-09-23 09:36:25 +0000610 DEBUG("new_mem_startup(%p, %u, rr=%u, ww=%u, xx=%u)\n", a,len,rr,ww,xx);
njn5c004e42002-11-18 11:04:50 +0000611 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000612}
613
614static
nethercote451eae92004-11-02 13:06:32 +0000615void ac_new_mem_heap ( Addr a, SizeT len, Bool is_inited )
njn25e49d8e72002-09-23 09:36:25 +0000616{
njn5c004e42002-11-18 11:04:50 +0000617 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000618}
619
620static
nethercote451eae92004-11-02 13:06:32 +0000621void ac_set_perms (Addr a, SizeT len, Bool rr, Bool ww, Bool xx)
njn25e49d8e72002-09-23 09:36:25 +0000622{
njn5c004e42002-11-18 11:04:50 +0000623 DEBUG("ac_set_perms(%p, %u, rr=%u ww=%u, xx=%u)\n",
sewardj40f8ebe2002-10-23 21:46:13 +0000624 a, len, rr, ww, xx);
njn25e49d8e72002-09-23 09:36:25 +0000625 if (rr || ww || xx) {
njn5c004e42002-11-18 11:04:50 +0000626 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000627 } else {
njn5c004e42002-11-18 11:04:50 +0000628 ac_make_noaccess(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000629 }
630}
631
632
633/*------------------------------------------------------------*/
634/*--- Functions called directly from generated code. ---*/
635/*------------------------------------------------------------*/
636
637static __inline__ UInt rotateRight16 ( UInt x )
638{
639 /* Amazingly, gcc turns this into a single rotate insn. */
640 return (x >> 16) | (x << 16);
641}
642
njn25e49d8e72002-09-23 09:36:25 +0000643static __inline__ UInt shiftRight16 ( UInt x )
644{
645 return x >> 16;
646}
647
648
649/* Read/write 1/2/4 sized V bytes, and emit an address error if
650 needed. */
651
njn5c004e42002-11-18 11:04:50 +0000652/* ac_helperc_ACCESS{1,2,4} handle the common case fast.
njn25e49d8e72002-09-23 09:36:25 +0000653 Under all other circumstances, it defers to the relevant _SLOWLY
654 function, which can handle all situations.
655*/
njnc2699f62003-09-05 23:29:33 +0000656static __inline__ void ac_helperc_ACCESS4 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000657{
658# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000659 return ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000660# else
661 UInt sec_no = rotateRight16(a) & 0x3FFFF;
njnda2e36d2003-09-30 13:33:24 +0000662 AcSecMap* sm = primary_map[sec_no];
njn25e49d8e72002-09-23 09:36:25 +0000663 UInt a_off = (a & 0xFFFF) >> 3;
664 UChar abits = sm->abits[a_off];
665 abits >>= (a & 4);
666 abits &= 15;
njn5c004e42002-11-18 11:04:50 +0000667 PROF_EVENT(66);
njn25e49d8e72002-09-23 09:36:25 +0000668 if (abits == VGM_NIBBLE_VALID) {
669 /* Handle common case quickly: a is suitably aligned, is mapped,
670 and is addressible. So just return. */
671 return;
672 } else {
673 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000674 ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000675 }
676# endif
677}
678
njnc2699f62003-09-05 23:29:33 +0000679static __inline__ void ac_helperc_ACCESS2 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000680{
681# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000682 return ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000683# else
684 UInt sec_no = rotateRight16(a) & 0x1FFFF;
685 AcSecMap* sm = primary_map[sec_no];
686 UInt a_off = (a & 0xFFFF) >> 3;
njn5c004e42002-11-18 11:04:50 +0000687 PROF_EVENT(67);
njn25e49d8e72002-09-23 09:36:25 +0000688 if (sm->abits[a_off] == VGM_BYTE_VALID) {
689 /* Handle common case quickly. */
690 return;
691 } else {
692 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000693 ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000694 }
695# endif
696}
697
njnc2699f62003-09-05 23:29:33 +0000698static __inline__ void ac_helperc_ACCESS1 ( 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_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000702# else
703 UInt sec_no = shiftRight16(a);
704 AcSecMap* sm = primary_map[sec_no];
705 UInt a_off = (a & 0xFFFF) >> 3;
njn5c004e42002-11-18 11:04:50 +0000706 PROF_EVENT(68);
njn25e49d8e72002-09-23 09:36:25 +0000707 if (sm->abits[a_off] == VGM_BYTE_VALID) {
708 /* Handle common case quickly. */
709 return;
710 } else {
711 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000712 ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000713 }
714# endif
715}
716
nethercoteeec46302004-08-23 15:06:23 +0000717REGPARM(1)
njnc2699f62003-09-05 23:29:33 +0000718static void ac_helperc_LOAD4 ( Addr a )
719{
720 ac_helperc_ACCESS4 ( a, /*isWrite*/False );
721}
nethercoteeec46302004-08-23 15:06:23 +0000722REGPARM(1)
njnc2699f62003-09-05 23:29:33 +0000723static void ac_helperc_STORE4 ( Addr a )
724{
725 ac_helperc_ACCESS4 ( a, /*isWrite*/True );
726}
727
nethercoteeec46302004-08-23 15:06:23 +0000728REGPARM(1)
njnc2699f62003-09-05 23:29:33 +0000729static void ac_helperc_LOAD2 ( Addr a )
730{
731 ac_helperc_ACCESS2 ( a, /*isWrite*/False );
732}
nethercoteeec46302004-08-23 15:06:23 +0000733REGPARM(1)
njnc2699f62003-09-05 23:29:33 +0000734static void ac_helperc_STORE2 ( Addr a )
735{
736 ac_helperc_ACCESS2 ( a, /*isWrite*/True );
737}
738
nethercoteeec46302004-08-23 15:06:23 +0000739REGPARM(1)
njnc2699f62003-09-05 23:29:33 +0000740static void ac_helperc_LOAD1 ( Addr a )
741{
742 ac_helperc_ACCESS1 ( a, /*isWrite*/False );
743}
nethercoteeec46302004-08-23 15:06:23 +0000744REGPARM(1)
njnc2699f62003-09-05 23:29:33 +0000745static void ac_helperc_STORE1 ( Addr a )
746{
747 ac_helperc_ACCESS1 ( a, /*isWrite*/True );
748}
749
njn25e49d8e72002-09-23 09:36:25 +0000750
751/*------------------------------------------------------------*/
752/*--- Fallback functions to handle cases that the above ---*/
njnc2699f62003-09-05 23:29:33 +0000753/*--- ac_helperc_ACCESS{1,2,4} can't manage. ---*/
njn25e49d8e72002-09-23 09:36:25 +0000754/*------------------------------------------------------------*/
755
njnc2699f62003-09-05 23:29:33 +0000756static void ac_ACCESS4_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000757{
758 Bool a0ok, a1ok, a2ok, a3ok;
759
njn5c004e42002-11-18 11:04:50 +0000760 PROF_EVENT(76);
njn25e49d8e72002-09-23 09:36:25 +0000761
762 /* First establish independently the addressibility of the 4 bytes
763 involved. */
764 a0ok = get_abit(a+0) == VGM_BIT_VALID;
765 a1ok = get_abit(a+1) == VGM_BIT_VALID;
766 a2ok = get_abit(a+2) == VGM_BIT_VALID;
767 a3ok = get_abit(a+3) == VGM_BIT_VALID;
768
769 /* Now distinguish 3 cases */
770
771 /* Case 1: the address is completely valid, so:
772 - no addressing error
773 */
774 if (a0ok && a1ok && a2ok && a3ok) {
775 return;
776 }
777
778 /* Case 2: the address is completely invalid.
779 - emit addressing error
780 */
781 /* VG_(printf)("%p (%d %d %d %d)\n", a, a0ok, a1ok, a2ok, a3ok); */
njn43c799e2003-04-08 00:08:52 +0000782 if (!MAC_(clo_partial_loads_ok)
njn25e49d8e72002-09-23 09:36:25 +0000783 || ((a & 3) != 0)
784 || (!a0ok && !a1ok && !a2ok && !a3ok)) {
njnc2699f62003-09-05 23:29:33 +0000785 MAC_(record_address_error)( VG_(get_current_tid)(), a, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000786 return;
787 }
788
789 /* Case 3: the address is partially valid.
790 - no addressing error
njn43c799e2003-04-08 00:08:52 +0000791 Case 3 is only allowed if MAC_(clo_partial_loads_ok) is True
njn25e49d8e72002-09-23 09:36:25 +0000792 (which is the default), and the address is 4-aligned.
793 If not, Case 2 will have applied.
794 */
njn43c799e2003-04-08 00:08:52 +0000795 sk_assert(MAC_(clo_partial_loads_ok));
njn25e49d8e72002-09-23 09:36:25 +0000796 {
797 return;
798 }
799}
800
njnc2699f62003-09-05 23:29:33 +0000801static void ac_ACCESS2_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000802{
803 /* Check the address for validity. */
804 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000805 PROF_EVENT(77);
njn25e49d8e72002-09-23 09:36:25 +0000806
807 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
808 if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
809
810 /* If an address error has happened, report it. */
811 if (aerr) {
njnc2699f62003-09-05 23:29:33 +0000812 MAC_(record_address_error)( VG_(get_current_tid)(), a, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000813 }
814}
815
njnc2699f62003-09-05 23:29:33 +0000816static void ac_ACCESS1_SLOWLY ( Addr a, Bool isWrite)
njn25e49d8e72002-09-23 09:36:25 +0000817{
818 /* Check the address for validity. */
819 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000820 PROF_EVENT(78);
njn25e49d8e72002-09-23 09:36:25 +0000821
822 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
823
824 /* If an address error has happened, report it. */
825 if (aerr) {
njnc2699f62003-09-05 23:29:33 +0000826 MAC_(record_address_error)( VG_(get_current_tid)(), a, 1, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000827 }
828}
829
830
831/* ---------------------------------------------------------------------
832 FPU load and store checks, called from generated code.
833 ------------------------------------------------------------------ */
834
sewardj56867352003-10-12 10:27:06 +0000835static
nethercote928a5f72004-11-03 18:10:37 +0000836void ac_fpu_ACCESS_check ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000837{
838 /* Ensure the read area is both addressible and valid (ie,
839 readable). If there's an address error, don't report a value
840 error too; but if there isn't an address error, check for a
841 value error.
842
843 Try to be reasonably fast on the common case; wimp out and defer
njn5c004e42002-11-18 11:04:50 +0000844 to ac_fpu_ACCESS_check_SLOWLY for everything else. */
njn25e49d8e72002-09-23 09:36:25 +0000845
846 AcSecMap* sm;
847 UInt sm_off, a_off;
848 Addr addr4;
849
njn5c004e42002-11-18 11:04:50 +0000850 PROF_EVENT(90);
njn25e49d8e72002-09-23 09:36:25 +0000851
852# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000853 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000854# else
855
856 if (size == 4) {
857 if (!IS_ALIGNED4_ADDR(addr)) goto slow4;
njn5c004e42002-11-18 11:04:50 +0000858 PROF_EVENT(91);
njn25e49d8e72002-09-23 09:36:25 +0000859 /* Properly aligned. */
860 sm = primary_map[addr >> 16];
861 sm_off = addr & 0xFFFF;
862 a_off = sm_off >> 3;
863 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow4;
864 /* Properly aligned and addressible. */
865 return;
866 slow4:
njnc2699f62003-09-05 23:29:33 +0000867 ac_fpu_ACCESS_check_SLOWLY ( addr, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000868 return;
869 }
870
871 if (size == 8) {
872 if (!IS_ALIGNED4_ADDR(addr)) goto slow8;
njn5c004e42002-11-18 11:04:50 +0000873 PROF_EVENT(92);
njn25e49d8e72002-09-23 09:36:25 +0000874 /* Properly aligned. Do it in two halves. */
875 addr4 = addr + 4;
876 /* First half. */
877 sm = primary_map[addr >> 16];
878 sm_off = addr & 0xFFFF;
879 a_off = sm_off >> 3;
880 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
881 /* First half properly aligned and addressible. */
882 /* Second half. */
883 sm = primary_map[addr4 >> 16];
884 sm_off = addr4 & 0xFFFF;
885 a_off = sm_off >> 3;
886 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
887 /* Second half properly aligned and addressible. */
888 /* Both halves properly aligned and addressible. */
889 return;
890 slow8:
njnc2699f62003-09-05 23:29:33 +0000891 ac_fpu_ACCESS_check_SLOWLY ( addr, 8, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000892 return;
893 }
894
895 /* Can't be bothered to huff'n'puff to make these (allegedly) rare
896 cases go quickly. */
897 if (size == 2) {
njn5c004e42002-11-18 11:04:50 +0000898 PROF_EVENT(93);
njnc2699f62003-09-05 23:29:33 +0000899 ac_fpu_ACCESS_check_SLOWLY ( addr, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000900 return;
901 }
902
jsewardfca60182004-01-04 23:30:55 +0000903 if (size == 16 || size == 10 || size == 28 || size == 108 || size == 512) {
njn5c004e42002-11-18 11:04:50 +0000904 PROF_EVENT(94);
njnc2699f62003-09-05 23:29:33 +0000905 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000906 return;
907 }
908
909 VG_(printf)("size is %d\n", size);
njne427a662002-10-02 11:08:25 +0000910 VG_(skin_panic)("fpu_ACCESS_check: unhandled size");
njn25e49d8e72002-09-23 09:36:25 +0000911# endif
912}
913
nethercoteeec46302004-08-23 15:06:23 +0000914REGPARM(2)
nethercote928a5f72004-11-03 18:10:37 +0000915static void ac_fpu_READ_check ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000916{
917 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/False );
918}
919
nethercoteeec46302004-08-23 15:06:23 +0000920REGPARM(2)
nethercote928a5f72004-11-03 18:10:37 +0000921static void ac_fpu_WRITE_check ( Addr addr, SizeT size )
njnc2699f62003-09-05 23:29:33 +0000922{
923 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/True );
924}
njn25e49d8e72002-09-23 09:36:25 +0000925
926/* ---------------------------------------------------------------------
927 Slow, general cases for FPU access checks.
928 ------------------------------------------------------------------ */
929
nethercote928a5f72004-11-03 18:10:37 +0000930void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, SizeT size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000931{
932 Int i;
933 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000934 PROF_EVENT(100);
njn25e49d8e72002-09-23 09:36:25 +0000935 for (i = 0; i < size; i++) {
njn5c004e42002-11-18 11:04:50 +0000936 PROF_EVENT(101);
njn25e49d8e72002-09-23 09:36:25 +0000937 if (get_abit(addr+i) != VGM_BIT_VALID)
938 aerr = True;
939 }
940
941 if (aerr) {
njnc2699f62003-09-05 23:29:33 +0000942 MAC_(record_address_error)( VG_(get_current_tid)(), addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000943 }
944}
945
946
947/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000948/*--- Our instrumenter ---*/
949/*------------------------------------------------------------*/
950
njn25e49d8e72002-09-23 09:36:25 +0000951UCodeBlock* SK_(instrument)(UCodeBlock* cb_in, Addr orig_addr)
952{
953/* Use this rather than eg. -1 because it's a UInt. */
954#define INVALID_DATA_SIZE 999999
955
956 UCodeBlock* cb;
957 Int i;
958 UInstr* u_in;
959 Int t_addr, t_size;
njnc2699f62003-09-05 23:29:33 +0000960 Addr helper;
njn25e49d8e72002-09-23 09:36:25 +0000961
njn810086f2002-11-14 12:42:47 +0000962 cb = VG_(setup_UCodeBlock)(cb_in);
njn25e49d8e72002-09-23 09:36:25 +0000963
njn810086f2002-11-14 12:42:47 +0000964 for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
njn25e49d8e72002-09-23 09:36:25 +0000965
966 t_addr = t_size = INVALID_TEMPREG;
njn810086f2002-11-14 12:42:47 +0000967 u_in = VG_(get_instr)(cb_in, i);
njn25e49d8e72002-09-23 09:36:25 +0000968
969 switch (u_in->opcode) {
sewardj7a5ebcf2002-11-13 22:42:13 +0000970 case NOP: case LOCK: case CALLM_E: case CALLM_S:
njn25e49d8e72002-09-23 09:36:25 +0000971 break;
972
sewardj77d30a22003-10-19 08:18:52 +0000973 /* For memory-ref instrs, copy the data_addr into a temporary
974 * to be passed to the helper at the end of the instruction.
njn25e49d8e72002-09-23 09:36:25 +0000975 */
njnc2699f62003-09-05 23:29:33 +0000976 case LOAD:
njn25e49d8e72002-09-23 09:36:25 +0000977 switch (u_in->size) {
njnc2699f62003-09-05 23:29:33 +0000978 case 4: helper = (Addr)ac_helperc_LOAD4; break;
979 case 2: helper = (Addr)ac_helperc_LOAD2; break;
980 case 1: helper = (Addr)ac_helperc_LOAD1; break;
sewardj77d30a22003-10-19 08:18:52 +0000981 default: VG_(skin_panic)
982 ("addrcheck::SK_(instrument):LOAD");
njn25e49d8e72002-09-23 09:36:25 +0000983 }
njnc2699f62003-09-05 23:29:33 +0000984 uInstr1(cb, CCALL, 0, TempReg, u_in->val1);
985 uCCall (cb, helper, 1, 1, False );
986 VG_(copy_UInstr)(cb, u_in);
987 break;
988
989 case STORE:
990 switch (u_in->size) {
991 case 4: helper = (Addr)ac_helperc_STORE4; break;
992 case 2: helper = (Addr)ac_helperc_STORE2; break;
993 case 1: helper = (Addr)ac_helperc_STORE1; break;
sewardj77d30a22003-10-19 08:18:52 +0000994 default: VG_(skin_panic)
995 ("addrcheck::SK_(instrument):STORE");
njnc2699f62003-09-05 23:29:33 +0000996 }
997 uInstr1(cb, CCALL, 0, TempReg, u_in->val2);
998 uCCall (cb, helper, 1, 1, False );
njn4ba5a792002-09-30 10:23:54 +0000999 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001000 break;
1001
sewardje3891fa2003-06-15 03:13:48 +00001002 case SSE3ag_MemRd_RegWr:
1003 sk_assert(u_in->size == 4 || u_in->size == 8);
njnc2699f62003-09-05 23:29:33 +00001004 helper = (Addr)ac_fpu_READ_check;
sewardje3891fa2003-06-15 03:13:48 +00001005 goto do_Access_ARG1;
1006 do_Access_ARG1:
1007 sk_assert(u_in->tag1 == TempReg);
1008 t_addr = u_in->val1;
1009 t_size = newTemp(cb);
1010 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
1011 uLiteral(cb, u_in->size);
1012 uInstr2(cb, CCALL, 0, TempReg, t_addr, TempReg, t_size);
njnc2699f62003-09-05 23:29:33 +00001013 uCCall(cb, helper, 2, 2, False );
sewardje3891fa2003-06-15 03:13:48 +00001014 VG_(copy_UInstr)(cb, u_in);
1015 break;
1016
sewardj3d7c9c82003-03-26 21:08:13 +00001017 case MMX2_MemRd:
njnc2699f62003-09-05 23:29:33 +00001018 sk_assert(u_in->size == 4 || u_in->size == 8);
1019 helper = (Addr)ac_fpu_READ_check;
1020 goto do_Access_ARG2;
sewardj3d7c9c82003-03-26 21:08:13 +00001021 case MMX2_MemWr:
sewardjd7971012003-04-04 00:21:58 +00001022 sk_assert(u_in->size == 4 || u_in->size == 8);
njnc2699f62003-09-05 23:29:33 +00001023 helper = (Addr)ac_fpu_WRITE_check;
sewardj1863abc2003-06-14 16:01:32 +00001024 goto do_Access_ARG2;
1025 case FPU_R:
njnc2699f62003-09-05 23:29:33 +00001026 helper = (Addr)ac_fpu_READ_check;
1027 goto do_Access_ARG2;
sewardj1863abc2003-06-14 16:01:32 +00001028 case FPU_W:
njnc2699f62003-09-05 23:29:33 +00001029 helper = (Addr)ac_fpu_WRITE_check;
sewardj1863abc2003-06-14 16:01:32 +00001030 goto do_Access_ARG2;
1031 do_Access_ARG2:
1032 sk_assert(u_in->tag2 == TempReg);
sewardj3d7c9c82003-03-26 21:08:13 +00001033 t_addr = u_in->val2;
1034 t_size = newTemp(cb);
1035 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
sewardjd7971012003-04-04 00:21:58 +00001036 uLiteral(cb, u_in->size);
sewardj3d7c9c82003-03-26 21:08:13 +00001037 uInstr2(cb, CCALL, 0, TempReg, t_addr, TempReg, t_size);
njnc2699f62003-09-05 23:29:33 +00001038 uCCall(cb, helper, 2, 2, False );
sewardj3d7c9c82003-03-26 21:08:13 +00001039 VG_(copy_UInstr)(cb, u_in);
1040 break;
1041
nethercote42d9cd12004-04-20 10:07:44 +00001042 case MMX2a1_MemRd:
sewardj77d30a22003-10-19 08:18:52 +00001043 case SSE3a_MemRd:
sewardj1863abc2003-06-14 16:01:32 +00001044 case SSE2a_MemRd:
nethercoteb1affa82004-01-19 19:14:18 +00001045 case SSE3a1_MemRd:
1046 case SSE2a1_MemRd:
njnc2699f62003-09-05 23:29:33 +00001047 helper = (Addr)ac_fpu_READ_check;
1048 goto do_Access_ARG3;
sewardj1863abc2003-06-14 16:01:32 +00001049 case SSE2a_MemWr:
1050 case SSE3a_MemWr:
njnc2699f62003-09-05 23:29:33 +00001051 helper = (Addr)ac_fpu_WRITE_check;
sewardj1863abc2003-06-14 16:01:32 +00001052 goto do_Access_ARG3;
1053 do_Access_ARG3:
jsewardfca60182004-01-04 23:30:55 +00001054 sk_assert(u_in->size == 4 || u_in->size == 8
1055 || u_in->size == 16 || u_in->size == 512);
sewardj1863abc2003-06-14 16:01:32 +00001056 sk_assert(u_in->tag3 == TempReg);
1057 t_addr = u_in->val3;
1058 t_size = newTemp(cb);
1059 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
1060 uLiteral(cb, u_in->size);
1061 uInstr2(cb, CCALL, 0, TempReg, t_addr, TempReg, t_size);
njnc2699f62003-09-05 23:29:33 +00001062 uCCall(cb, helper, 2, 2, False );
sewardj1863abc2003-06-14 16:01:32 +00001063 VG_(copy_UInstr)(cb, u_in);
1064 break;
1065
sewardj095c3bc2003-06-15 23:26:04 +00001066 case SSE3e1_RegRd:
sewardjabf8bf82003-06-15 22:28:05 +00001067 case SSE3e_RegWr:
sewardje3891fa2003-06-15 03:13:48 +00001068 case SSE3g1_RegWr:
sewardj6bc40552003-06-15 01:40:58 +00001069 case SSE5:
sewardj1863abc2003-06-14 16:01:32 +00001070 case SSE3g_RegWr:
sewardj4fbe6e92003-06-15 21:54:34 +00001071 case SSE3e_RegRd:
sewardj1863abc2003-06-14 16:01:32 +00001072 case SSE4:
sewardj77d30a22003-10-19 08:18:52 +00001073 case SSE3:
njn25e49d8e72002-09-23 09:36:25 +00001074 default:
njn4ba5a792002-09-30 10:23:54 +00001075 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001076 break;
1077 }
1078 }
1079
njn4ba5a792002-09-30 10:23:54 +00001080 VG_(free_UCodeBlock)(cb_in);
njn25e49d8e72002-09-23 09:36:25 +00001081 return cb;
1082}
1083
1084
njn25e49d8e72002-09-23 09:36:25 +00001085/*------------------------------------------------------------*/
1086/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
1087/*------------------------------------------------------------*/
1088
sewardja4495682002-10-21 07:29:59 +00001089/* For the memory leak detector, say whether an entire 64k chunk of
1090 address space is possibly in use, or not. If in doubt return
1091 True.
njn25e49d8e72002-09-23 09:36:25 +00001092*/
sewardja4495682002-10-21 07:29:59 +00001093static
1094Bool ac_is_valid_64k_chunk ( UInt chunk_number )
njn25e49d8e72002-09-23 09:36:25 +00001095{
sewardja4495682002-10-21 07:29:59 +00001096 sk_assert(chunk_number >= 0 && chunk_number < 65536);
1097 if (IS_DISTINGUISHED_SM(primary_map[chunk_number])) {
1098 /* Definitely not in use. */
1099 return False;
1100 } else {
1101 return True;
njn25e49d8e72002-09-23 09:36:25 +00001102 }
1103}
1104
1105
sewardja4495682002-10-21 07:29:59 +00001106/* For the memory leak detector, say whether or not a given word
1107 address is to be regarded as valid. */
1108static
1109Bool ac_is_valid_address ( Addr a )
1110{
1111 UChar abits;
1112 sk_assert(IS_ALIGNED4_ADDR(a));
1113 abits = get_abits4_ALIGNED(a);
1114 if (abits == VGM_NIBBLE_VALID) {
1115 return True;
1116 } else {
1117 return False;
1118 }
1119}
1120
1121
nethercote996901a2004-08-03 13:29:09 +00001122/* Leak detector for this tool. We don't actually do anything, merely
sewardja4495682002-10-21 07:29:59 +00001123 run the generic leak detector with suitable parameters for this
nethercote996901a2004-08-03 13:29:09 +00001124 tool. */
njn5c004e42002-11-18 11:04:50 +00001125static void ac_detect_memory_leaks ( void )
njn25e49d8e72002-09-23 09:36:25 +00001126{
njn43c799e2003-04-08 00:08:52 +00001127 MAC_(do_detect_memory_leaks) ( ac_is_valid_64k_chunk, ac_is_valid_address );
njn25e49d8e72002-09-23 09:36:25 +00001128}
1129
1130
1131/* ---------------------------------------------------------------------
1132 Sanity check machinery (permanently engaged).
1133 ------------------------------------------------------------------ */
1134
njn25e49d8e72002-09-23 09:36:25 +00001135Bool SK_(cheap_sanity_check) ( void )
1136{
jseward9800fd32004-01-04 23:08:04 +00001137 /* nothing useful we can rapidly check */
1138 return True;
njn25e49d8e72002-09-23 09:36:25 +00001139}
1140
1141Bool SK_(expensive_sanity_check) ( void )
1142{
1143 Int i;
1144
1145 /* Make sure nobody changed the distinguished secondary. */
1146 for (i = 0; i < 8192; i++)
1147 if (distinguished_secondary_map.abits[i] != VGM_BYTE_INVALID)
1148 return False;
1149
1150 /* Make sure that the upper 3/4 of the primary map hasn't
1151 been messed with. */
1152 for (i = 65536; i < 262144; i++)
1153 if (primary_map[i] != & distinguished_secondary_map)
1154 return False;
1155
1156 return True;
1157}
1158
njn47363ab2003-04-21 13:24:40 +00001159/*------------------------------------------------------------*/
1160/*--- Client requests ---*/
1161/*------------------------------------------------------------*/
1162
njn72718642003-07-24 08:45:32 +00001163Bool SK_(handle_client_request) ( ThreadId tid, UInt* arg_block, UInt *ret )
sewardjd8033d92002-12-08 22:16:58 +00001164{
sewardjbf310d92002-12-28 13:09:57 +00001165#define IGNORE(what) \
1166 do { \
1167 if (moans-- > 0) { \
1168 VG_(message)(Vg_UserMsg, \
1169 "Warning: Addrcheck: ignoring `%s' request.", what); \
1170 VG_(message)(Vg_UserMsg, \
nethercote137bc552003-11-14 17:47:54 +00001171 " To honour this request, rerun with --tool=memcheck."); \
sewardjbf310d92002-12-28 13:09:57 +00001172 } \
1173 } while (0)
1174
sewardjd8033d92002-12-08 22:16:58 +00001175 UInt* arg = arg_block;
sewardjbf310d92002-12-28 13:09:57 +00001176 static Int moans = 3;
sewardjd8033d92002-12-08 22:16:58 +00001177
1178 /* Overload memcheck client reqs */
njnd7994182003-10-02 13:44:04 +00001179 if (!VG_IS_SKIN_USERREQ('M','C',arg[0])
1180 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
rjwalshbc0bb832004-06-19 18:12:36 +00001181 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
1182 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
1183 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
1184 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
1185 && VG_USERREQ__MEMPOOL_FREE != arg[0])
sewardjd8033d92002-12-08 22:16:58 +00001186 return False;
1187
1188 switch (arg[0]) {
1189 case VG_USERREQ__DO_LEAK_CHECK:
1190 ac_detect_memory_leaks();
1191 *ret = 0; /* return value is meaningless */
1192 break;
1193
sewardjbf310d92002-12-28 13:09:57 +00001194 /* Ignore these */
sewardjd8033d92002-12-08 22:16:58 +00001195 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
sewardjbf310d92002-12-28 13:09:57 +00001196 IGNORE("VALGRIND_CHECK_WRITABLE");
1197 return False;
sewardjd8033d92002-12-08 22:16:58 +00001198 case VG_USERREQ__CHECK_READABLE: /* check readable */
sewardjbf310d92002-12-28 13:09:57 +00001199 IGNORE("VALGRIND_CHECK_READABLE");
1200 return False;
sewardjd8033d92002-12-08 22:16:58 +00001201 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
sewardjbf310d92002-12-28 13:09:57 +00001202 IGNORE("VALGRIND_MAKE_NOACCESS");
1203 return False;
sewardjd8033d92002-12-08 22:16:58 +00001204 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
sewardjbf310d92002-12-28 13:09:57 +00001205 IGNORE("VALGRIND_MAKE_WRITABLE");
1206 return False;
sewardjd8033d92002-12-08 22:16:58 +00001207 case VG_USERREQ__MAKE_READABLE: /* make readable */
sewardjbf310d92002-12-28 13:09:57 +00001208 IGNORE("VALGRIND_MAKE_READABLE");
1209 return False;
sewardjd8033d92002-12-08 22:16:58 +00001210 case VG_USERREQ__DISCARD: /* discard */
sewardjbf310d92002-12-28 13:09:57 +00001211 IGNORE("VALGRIND_CHECK_DISCARD");
1212 return False;
sewardjd8033d92002-12-08 22:16:58 +00001213
1214 default:
njn72718642003-07-24 08:45:32 +00001215 if (MAC_(handle_common_client_requests)(tid, arg_block, ret )) {
njn47363ab2003-04-21 13:24:40 +00001216 return True;
1217 } else {
1218 VG_(message)(Vg_UserMsg,
1219 "Warning: unknown addrcheck client request code %d",
1220 arg[0]);
1221 return False;
1222 }
sewardjd8033d92002-12-08 22:16:58 +00001223 }
1224 return True;
sewardjbf310d92002-12-28 13:09:57 +00001225
1226#undef IGNORE
sewardjd8033d92002-12-08 22:16:58 +00001227}
1228
njn25e49d8e72002-09-23 09:36:25 +00001229/*------------------------------------------------------------*/
1230/*--- Setup ---*/
1231/*------------------------------------------------------------*/
1232
njn25e49d8e72002-09-23 09:36:25 +00001233Bool SK_(process_cmd_line_option)(Char* arg)
1234{
njn43c799e2003-04-08 00:08:52 +00001235 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001236}
1237
njn3e884182003-04-15 13:03:23 +00001238void SK_(print_usage)(void)
njn25e49d8e72002-09-23 09:36:25 +00001239{
njn3e884182003-04-15 13:03:23 +00001240 MAC_(print_common_usage)();
1241}
1242
1243void SK_(print_debug_usage)(void)
1244{
1245 MAC_(print_common_debug_usage)();
njn25e49d8e72002-09-23 09:36:25 +00001246}
1247
1248
1249/*------------------------------------------------------------*/
1250/*--- Setup ---*/
1251/*------------------------------------------------------------*/
1252
njn810086f2002-11-14 12:42:47 +00001253void SK_(pre_clo_init)(void)
njn25e49d8e72002-09-23 09:36:25 +00001254{
njn810086f2002-11-14 12:42:47 +00001255 VG_(details_name) ("Addrcheck");
1256 VG_(details_version) (NULL);
1257 VG_(details_description) ("a fine-grained address checker");
1258 VG_(details_copyright_author)(
nethercote08fa9a72004-07-16 17:44:00 +00001259 "Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al.");
nethercote421281e2003-11-20 16:20:55 +00001260 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardj78210aa2002-12-01 02:55:46 +00001261 VG_(details_avg_translation_sizeB) ( 135 );
njn25e49d8e72002-09-23 09:36:25 +00001262
njn810086f2002-11-14 12:42:47 +00001263 VG_(needs_core_errors) ();
1264 VG_(needs_skin_errors) ();
1265 VG_(needs_libc_freeres) ();
njn810086f2002-11-14 12:42:47 +00001266 VG_(needs_command_line_options)();
1267 VG_(needs_client_requests) ();
1268 VG_(needs_syscall_wrapper) ();
njn810086f2002-11-14 12:42:47 +00001269 VG_(needs_sanity_checks) ();
fitzhardinge98abfc72003-12-16 02:05:15 +00001270 VG_(needs_shadow_memory) ();
njn25e49d8e72002-09-23 09:36:25 +00001271
njn3e884182003-04-15 13:03:23 +00001272 MAC_( new_mem_heap) = & ac_new_mem_heap;
1273 MAC_( ban_mem_heap) = & ac_make_noaccess;
1274 MAC_(copy_mem_heap) = & ac_copy_address_range_state;
1275 MAC_( die_mem_heap) = & ac_make_noaccess;
sewardjecf8e102003-07-12 12:11:39 +00001276 MAC_(check_noaccess) = & ac_check_noaccess;
njn3e884182003-04-15 13:03:23 +00001277
fitzhardinge98abfc72003-12-16 02:05:15 +00001278 VG_(init_new_mem_startup) ( & ac_new_mem_startup );
1279 VG_(init_new_mem_stack_signal) ( & ac_make_accessible );
1280 VG_(init_new_mem_brk) ( & ac_make_accessible );
1281 VG_(init_new_mem_mmap) ( & ac_set_perms );
njn25e49d8e72002-09-23 09:36:25 +00001282
fitzhardinge98abfc72003-12-16 02:05:15 +00001283 VG_(init_copy_mem_remap) ( & ac_copy_address_range_state );
1284 VG_(init_change_mem_mprotect) ( & ac_set_perms );
njn3e884182003-04-15 13:03:23 +00001285
fitzhardinge98abfc72003-12-16 02:05:15 +00001286 VG_(init_die_mem_stack_signal) ( & ac_make_noaccess );
1287 VG_(init_die_mem_brk) ( & ac_make_noaccess );
1288 VG_(init_die_mem_munmap) ( & ac_make_noaccess );
njn3e884182003-04-15 13:03:23 +00001289
fitzhardinge98abfc72003-12-16 02:05:15 +00001290 VG_(init_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
1291 VG_(init_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
1292 VG_(init_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
1293 VG_(init_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
1294 VG_(init_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
1295 VG_(init_new_mem_stack) ( & MAC_(new_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001296
fitzhardinge98abfc72003-12-16 02:05:15 +00001297 VG_(init_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
1298 VG_(init_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
1299 VG_(init_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
1300 VG_(init_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
1301 VG_(init_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
1302 VG_(init_die_mem_stack) ( & MAC_(die_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001303
fitzhardinge98abfc72003-12-16 02:05:15 +00001304 VG_(init_ban_mem_stack) ( & ac_make_noaccess );
njn25e49d8e72002-09-23 09:36:25 +00001305
fitzhardinge98abfc72003-12-16 02:05:15 +00001306 VG_(init_pre_mem_read) ( & ac_check_is_readable );
1307 VG_(init_pre_mem_read_asciiz) ( & ac_check_is_readable_asciiz );
1308 VG_(init_pre_mem_write) ( & ac_check_is_writable );
1309 VG_(init_post_mem_write) ( & ac_make_accessible );
njn25e49d8e72002-09-23 09:36:25 +00001310
njnc2699f62003-09-05 23:29:33 +00001311 VG_(register_compact_helper)((Addr) & ac_helperc_LOAD4);
1312 VG_(register_compact_helper)((Addr) & ac_helperc_LOAD2);
1313 VG_(register_compact_helper)((Addr) & ac_helperc_LOAD1);
1314 VG_(register_compact_helper)((Addr) & ac_helperc_STORE4);
1315 VG_(register_compact_helper)((Addr) & ac_helperc_STORE2);
1316 VG_(register_compact_helper)((Addr) & ac_helperc_STORE1);
1317 VG_(register_noncompact_helper)((Addr) & ac_fpu_READ_check);
1318 VG_(register_noncompact_helper)((Addr) & ac_fpu_WRITE_check);
njn25e49d8e72002-09-23 09:36:25 +00001319
1320 VGP_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
1321 VGP_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
njn9b007f62003-04-07 14:40:25 +00001322 VGP_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
njnd04b7c62002-10-03 14:05:52 +00001323
1324 init_shadow_memory();
njn3e884182003-04-15 13:03:23 +00001325 MAC_(common_pre_clo_init)();
njn5c004e42002-11-18 11:04:50 +00001326}
1327
1328void SK_(post_clo_init) ( void )
1329{
1330}
1331
njn7d9f94d2003-04-22 21:41:40 +00001332void SK_(fini) ( Int exitcode )
njn5c004e42002-11-18 11:04:50 +00001333{
njn3e884182003-04-15 13:03:23 +00001334 MAC_(common_fini)( ac_detect_memory_leaks );
njn25e49d8e72002-09-23 09:36:25 +00001335}
1336
fitzhardinge98abfc72003-12-16 02:05:15 +00001337VG_DETERMINE_INTERFACE_VERSION(SK_(pre_clo_init), 1./8)
1338
1339
njn25e49d8e72002-09-23 09:36:25 +00001340/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00001341/*--- end ac_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00001342/*--------------------------------------------------------------------*/