blob: bcd255f72b0e094857644ec8b67d3e1c9cd5ade5 [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 );
141static void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, Int 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. */
187
188 /* It just happens that a AcSecMap occupies exactly 18 pages --
189 although this isn't important, so the following assert is
190 spurious. */
njne427a662002-10-02 11:08:25 +0000191 sk_assert(0 == (sizeof(AcSecMap) % VKI_BYTES_PER_PAGE));
fitzhardinge98abfc72003-12-16 02:05:15 +0000192 map = (AcSecMap *)VG_(shadow_alloc)(sizeof(AcSecMap));
njn25e49d8e72002-09-23 09:36:25 +0000193
194 for (i = 0; i < 8192; i++)
195 map->abits[i] = VGM_BYTE_INVALID; /* Invalid address */
196
197 /* VG_(printf)("ALLOC_2MAP(%s)\n", caller ); */
198 return map;
199}
200
201
202/* Basic reading/writing of the bitmaps, for byte-sized accesses. */
203
204static __inline__ UChar get_abit ( Addr a )
205{
206 AcSecMap* sm = primary_map[a >> 16];
207 UInt sm_off = a & 0xFFFF;
208 PROF_EVENT(20);
209# if 0
210 if (IS_DISTINGUISHED_SM(sm))
211 VG_(message)(Vg_DebugMsg,
212 "accessed distinguished 2ndary (A)map! 0x%x\n", a);
213# endif
214 return BITARR_TEST(sm->abits, sm_off)
215 ? VGM_BIT_INVALID : VGM_BIT_VALID;
216}
217
sewardj56867352003-10-12 10:27:06 +0000218static /* __inline__ */ void set_abit ( Addr a, UChar abit )
njn25e49d8e72002-09-23 09:36:25 +0000219{
220 AcSecMap* sm;
221 UInt sm_off;
222 PROF_EVENT(22);
223 ENSURE_MAPPABLE(a, "set_abit");
224 sm = primary_map[a >> 16];
225 sm_off = a & 0xFFFF;
226 if (abit)
227 BITARR_SET(sm->abits, sm_off);
228 else
229 BITARR_CLEAR(sm->abits, sm_off);
230}
231
232
233/* Reading/writing of the bitmaps, for aligned word-sized accesses. */
234
235static __inline__ UChar get_abits4_ALIGNED ( Addr a )
236{
237 AcSecMap* sm;
238 UInt sm_off;
239 UChar abits8;
240 PROF_EVENT(24);
241# ifdef VG_DEBUG_MEMORY
njne427a662002-10-02 11:08:25 +0000242 sk_assert(IS_ALIGNED4_ADDR(a));
njn25e49d8e72002-09-23 09:36:25 +0000243# endif
244 sm = primary_map[a >> 16];
245 sm_off = a & 0xFFFF;
246 abits8 = sm->abits[sm_off >> 3];
247 abits8 >>= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
248 abits8 &= 0x0F;
249 return abits8;
250}
251
252
253
254/*------------------------------------------------------------*/
255/*--- Setting permissions over address ranges. ---*/
256/*------------------------------------------------------------*/
257
sewardj56867352003-10-12 10:27:06 +0000258static /* __inline__ */
sewardj5de6ee02002-12-14 23:11:35 +0000259void set_address_range_perms ( Addr a, UInt len,
260 UInt example_a_bit )
njn25e49d8e72002-09-23 09:36:25 +0000261{
262 UChar abyte8;
263 UInt sm_off;
264 AcSecMap* sm;
265
266 PROF_EVENT(30);
267
268 if (len == 0)
269 return;
270
271 if (len > 100 * 1000 * 1000) {
272 VG_(message)(Vg_UserMsg,
273 "Warning: set address range perms: "
274 "large range %u, a %d",
275 len, example_a_bit );
276 }
277
278 VGP_PUSHCC(VgpSetMem);
279
280 /* Requests to change permissions of huge address ranges may
281 indicate bugs in our machinery. 30,000,000 is arbitrary, but so
282 far all legitimate requests have fallen beneath that size. */
283 /* 4 Mar 02: this is just stupid; get rid of it. */
njne427a662002-10-02 11:08:25 +0000284 /* sk_assert(len < 30000000); */
njn25e49d8e72002-09-23 09:36:25 +0000285
286 /* Check the permissions make sense. */
njne427a662002-10-02 11:08:25 +0000287 sk_assert(example_a_bit == VGM_BIT_VALID
njn25e49d8e72002-09-23 09:36:25 +0000288 || example_a_bit == VGM_BIT_INVALID);
289
290 /* In order that we can charge through the address space at 8
291 bytes/main-loop iteration, make up some perms. */
292 abyte8 = (example_a_bit << 7)
293 | (example_a_bit << 6)
294 | (example_a_bit << 5)
295 | (example_a_bit << 4)
296 | (example_a_bit << 3)
297 | (example_a_bit << 2)
298 | (example_a_bit << 1)
299 | (example_a_bit << 0);
300
301# ifdef VG_DEBUG_MEMORY
302 /* Do it ... */
303 while (True) {
304 PROF_EVENT(31);
305 if (len == 0) break;
306 set_abit ( a, example_a_bit );
307 set_vbyte ( a, vbyte );
308 a++;
309 len--;
310 }
311
312# else
313 /* Slowly do parts preceding 8-byte alignment. */
314 while (True) {
315 PROF_EVENT(31);
316 if (len == 0) break;
317 if ((a % 8) == 0) break;
318 set_abit ( a, example_a_bit );
319 a++;
320 len--;
321 }
322
323 if (len == 0) {
324 VGP_POPCC(VgpSetMem);
325 return;
326 }
njne427a662002-10-02 11:08:25 +0000327 sk_assert((a % 8) == 0 && len > 0);
njn25e49d8e72002-09-23 09:36:25 +0000328
329 /* Once aligned, go fast. */
330 while (True) {
331 PROF_EVENT(32);
332 if (len < 8) break;
333 ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
334 sm = primary_map[a >> 16];
335 sm_off = a & 0xFFFF;
336 sm->abits[sm_off >> 3] = abyte8;
337 a += 8;
338 len -= 8;
339 }
340
341 if (len == 0) {
342 VGP_POPCC(VgpSetMem);
343 return;
344 }
njne427a662002-10-02 11:08:25 +0000345 sk_assert((a % 8) == 0 && len > 0 && len < 8);
njn25e49d8e72002-09-23 09:36:25 +0000346
347 /* Finish the upper fragment. */
348 while (True) {
349 PROF_EVENT(33);
350 if (len == 0) break;
351 set_abit ( a, example_a_bit );
352 a++;
353 len--;
354 }
355# endif
356
357 /* Check that zero page and highest page have not been written to
358 -- this could happen with buggy syscall wrappers. Today
359 (2001-04-26) had precisely such a problem with __NR_setitimer. */
njne427a662002-10-02 11:08:25 +0000360 sk_assert(SK_(cheap_sanity_check)());
njn25e49d8e72002-09-23 09:36:25 +0000361 VGP_POPCC(VgpSetMem);
362}
363
364/* Set permissions for address ranges ... */
365
njn5c004e42002-11-18 11:04:50 +0000366static void ac_make_noaccess ( Addr a, UInt len )
njn25e49d8e72002-09-23 09:36:25 +0000367{
368 PROF_EVENT(35);
njn5c004e42002-11-18 11:04:50 +0000369 DEBUG("ac_make_noaccess(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000370 set_address_range_perms ( a, len, VGM_BIT_INVALID );
371}
372
njn5c004e42002-11-18 11:04:50 +0000373static void ac_make_accessible ( Addr a, UInt len )
njn25e49d8e72002-09-23 09:36:25 +0000374{
njn5c004e42002-11-18 11:04:50 +0000375 PROF_EVENT(38);
376 DEBUG("ac_make_accessible(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000377 set_address_range_perms ( a, len, VGM_BIT_VALID );
378}
379
njn9b007f62003-04-07 14:40:25 +0000380static __inline__
381void make_aligned_word_noaccess(Addr a)
382{
383 AcSecMap* sm;
384 UInt sm_off;
385 UChar mask;
386
387 VGP_PUSHCC(VgpESPAdj);
388 ENSURE_MAPPABLE(a, "make_aligned_word_noaccess");
389 sm = primary_map[a >> 16];
390 sm_off = a & 0xFFFF;
391 mask = 0x0F;
392 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
393 /* mask now contains 1s where we wish to make address bits invalid (1s). */
394 sm->abits[sm_off >> 3] |= mask;
395 VGP_POPCC(VgpESPAdj);
396}
397
398static __inline__
399void make_aligned_word_accessible(Addr a)
400{
401 AcSecMap* sm;
402 UInt sm_off;
403 UChar mask;
404
405 VGP_PUSHCC(VgpESPAdj);
406 ENSURE_MAPPABLE(a, "make_aligned_word_accessible");
407 sm = primary_map[a >> 16];
408 sm_off = a & 0xFFFF;
409 mask = 0x0F;
410 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
411 /* mask now contains 1s where we wish to make address bits
412 invalid (0s). */
413 sm->abits[sm_off >> 3] &= ~mask;
414 VGP_POPCC(VgpESPAdj);
415}
416
417/* Nb: by "aligned" here we mean 8-byte aligned */
418static __inline__
419void make_aligned_doubleword_accessible(Addr a)
420{
421 AcSecMap* sm;
422 UInt sm_off;
423
424 VGP_PUSHCC(VgpESPAdj);
425 ENSURE_MAPPABLE(a, "make_aligned_doubleword_accessible");
426 sm = primary_map[a >> 16];
427 sm_off = a & 0xFFFF;
428 sm->abits[sm_off >> 3] = VGM_BYTE_VALID;
429 VGP_POPCC(VgpESPAdj);
430}
431
432static __inline__
433void make_aligned_doubleword_noaccess(Addr a)
434{
435 AcSecMap* sm;
436 UInt sm_off;
437
438 VGP_PUSHCC(VgpESPAdj);
439 ENSURE_MAPPABLE(a, "make_aligned_doubleword_noaccess");
440 sm = primary_map[a >> 16];
441 sm_off = a & 0xFFFF;
442 sm->abits[sm_off >> 3] = VGM_BYTE_INVALID;
443 VGP_POPCC(VgpESPAdj);
444}
445
446/* The %esp update handling functions */
447ESP_UPDATE_HANDLERS ( make_aligned_word_accessible,
448 make_aligned_word_noaccess,
449 make_aligned_doubleword_accessible,
450 make_aligned_doubleword_noaccess,
451 ac_make_accessible,
452 ac_make_noaccess
453 );
454
455
njn25e49d8e72002-09-23 09:36:25 +0000456/* Block-copy permissions (needed for implementing realloc()). */
457
njn5c004e42002-11-18 11:04:50 +0000458static void ac_copy_address_range_state ( Addr src, Addr dst, UInt len )
njn25e49d8e72002-09-23 09:36:25 +0000459{
460 UInt i;
461
njn5c004e42002-11-18 11:04:50 +0000462 DEBUG("ac_copy_address_range_state\n");
njn25e49d8e72002-09-23 09:36:25 +0000463
464 PROF_EVENT(40);
465 for (i = 0; i < len; i++) {
466 UChar abit = get_abit ( src+i );
467 PROF_EVENT(41);
468 set_abit ( dst+i, abit );
469 }
470}
471
472
473/* Check permissions for address range. If inadequate permissions
474 exist, *bad_addr is set to the offending address, so the caller can
475 know what it is. */
476
njn5c004e42002-11-18 11:04:50 +0000477static __inline__
478Bool ac_check_accessible ( Addr a, UInt len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000479{
480 UInt i;
481 UChar abit;
njn5c004e42002-11-18 11:04:50 +0000482 PROF_EVENT(48);
njn25e49d8e72002-09-23 09:36:25 +0000483 for (i = 0; i < len; i++) {
njn5c004e42002-11-18 11:04:50 +0000484 PROF_EVENT(49);
njn25e49d8e72002-09-23 09:36:25 +0000485 abit = get_abit(a);
486 if (abit == VGM_BIT_INVALID) {
487 if (bad_addr != NULL) *bad_addr = a;
488 return False;
489 }
490 a++;
491 }
492 return True;
493}
494
sewardjecf8e102003-07-12 12:11:39 +0000495/* The opposite; check that an address range is inaccessible. */
496static
497Bool ac_check_noaccess ( Addr a, UInt len, Addr* bad_addr )
498{
499 UInt i;
500 UChar abit;
501 PROF_EVENT(48);
502 for (i = 0; i < len; i++) {
503 PROF_EVENT(49);
504 abit = get_abit(a);
505 if (abit == VGM_BIT_VALID) {
506 if (bad_addr != NULL) *bad_addr = a;
507 return False;
508 }
509 a++;
510 }
511 return True;
512}
513
njn25e49d8e72002-09-23 09:36:25 +0000514/* Check a zero-terminated ascii string. Tricky -- don't want to
515 examine the actual bytes, to find the end, until we're sure it is
516 safe to do so. */
517
njn5c004e42002-11-18 11:04:50 +0000518static __inline__
519Bool ac_check_readable_asciiz ( Addr a, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000520{
521 UChar abit;
522 PROF_EVENT(46);
njn5c004e42002-11-18 11:04:50 +0000523 DEBUG("ac_check_readable_asciiz\n");
njn25e49d8e72002-09-23 09:36:25 +0000524 while (True) {
525 PROF_EVENT(47);
526 abit = get_abit(a);
527 if (abit != VGM_BIT_VALID) {
528 if (bad_addr != NULL) *bad_addr = a;
529 return False;
530 }
531 /* Ok, a is safe to read. */
532 if (* ((UChar*)a) == 0) return True;
533 a++;
534 }
535}
536
537
538/*------------------------------------------------------------*/
539/*--- Memory event handlers ---*/
540/*------------------------------------------------------------*/
541
njn5c004e42002-11-18 11:04:50 +0000542static __inline__
njn72718642003-07-24 08:45:32 +0000543void ac_check_is_accessible ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000544 Char* s, Addr base, UInt size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000545{
546 Bool ok;
547 Addr bad_addr;
548
549 VGP_PUSHCC(VgpCheckMem);
550
njn5c004e42002-11-18 11:04:50 +0000551 ok = ac_check_accessible ( base, size, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000552 if (!ok) {
553 switch (part) {
554 case Vg_CoreSysCall:
njn72718642003-07-24 08:45:32 +0000555 MAC_(record_param_error) ( tid, bad_addr, isWrite, s );
njn25e49d8e72002-09-23 09:36:25 +0000556 break;
557
njn25e49d8e72002-09-23 09:36:25 +0000558 case Vg_CoreSignal:
njn5c004e42002-11-18 11:04:50 +0000559 sk_assert(isWrite); /* Should only happen with isWrite case */
560 /* fall through */
njn25e49d8e72002-09-23 09:36:25 +0000561 case Vg_CorePThread:
njn72718642003-07-24 08:45:32 +0000562 MAC_(record_core_mem_error)( tid, isWrite, s );
njn25e49d8e72002-09-23 09:36:25 +0000563 break;
564
565 /* If we're being asked to jump to a silly address, record an error
566 message before potentially crashing the entire system. */
567 case Vg_CoreTranslate:
njn5c004e42002-11-18 11:04:50 +0000568 sk_assert(!isWrite); /* Should only happen with !isWrite case */
njn72718642003-07-24 08:45:32 +0000569 MAC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000570 break;
571
572 default:
njn5c004e42002-11-18 11:04:50 +0000573 VG_(skin_panic)("ac_check_is_accessible: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +0000574 }
575 }
njn5c004e42002-11-18 11:04:50 +0000576
njn25e49d8e72002-09-23 09:36:25 +0000577 VGP_POPCC(VgpCheckMem);
578}
579
580static
njn72718642003-07-24 08:45:32 +0000581void ac_check_is_writable ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000582 Char* s, Addr base, UInt size )
583{
njn72718642003-07-24 08:45:32 +0000584 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/True );
njn5c004e42002-11-18 11:04:50 +0000585}
586
587static
njn72718642003-07-24 08:45:32 +0000588void ac_check_is_readable ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000589 Char* s, Addr base, UInt size )
590{
njn72718642003-07-24 08:45:32 +0000591 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/False );
njn5c004e42002-11-18 11:04:50 +0000592}
593
594static
njn72718642003-07-24 08:45:32 +0000595void ac_check_is_readable_asciiz ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000596 Char* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +0000597{
598 Bool ok = True;
599 Addr bad_addr;
600 /* VG_(message)(Vg_DebugMsg,"check is readable asciiz: 0x%x",str); */
601
602 VGP_PUSHCC(VgpCheckMem);
603
njne427a662002-10-02 11:08:25 +0000604 sk_assert(part == Vg_CoreSysCall);
njn5c004e42002-11-18 11:04:50 +0000605 ok = ac_check_readable_asciiz ( (Addr)str, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000606 if (!ok) {
njn72718642003-07-24 08:45:32 +0000607 MAC_(record_param_error) ( tid, bad_addr, /*is_writable =*/False, s );
njn25e49d8e72002-09-23 09:36:25 +0000608 }
609
610 VGP_POPCC(VgpCheckMem);
611}
612
613static
njn5c004e42002-11-18 11:04:50 +0000614void ac_new_mem_startup( Addr a, UInt len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +0000615{
njn1f3a9092002-10-04 09:22:30 +0000616 /* Ignore the permissions, just make it readable. Seems to work... */
njn25e49d8e72002-09-23 09:36:25 +0000617 DEBUG("new_mem_startup(%p, %u, rr=%u, ww=%u, xx=%u)\n", a,len,rr,ww,xx);
njn5c004e42002-11-18 11:04:50 +0000618 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000619}
620
621static
njn5c004e42002-11-18 11:04:50 +0000622void ac_new_mem_heap ( Addr a, UInt len, Bool is_inited )
njn25e49d8e72002-09-23 09:36:25 +0000623{
njn5c004e42002-11-18 11:04:50 +0000624 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000625}
626
627static
njnda2e36d2003-09-30 13:33:24 +0000628void ac_set_perms (Addr a, UInt len, Bool rr, Bool ww, Bool xx)
njn25e49d8e72002-09-23 09:36:25 +0000629{
njn5c004e42002-11-18 11:04:50 +0000630 DEBUG("ac_set_perms(%p, %u, rr=%u ww=%u, xx=%u)\n",
sewardj40f8ebe2002-10-23 21:46:13 +0000631 a, len, rr, ww, xx);
njn25e49d8e72002-09-23 09:36:25 +0000632 if (rr || ww || xx) {
njn5c004e42002-11-18 11:04:50 +0000633 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000634 } else {
njn5c004e42002-11-18 11:04:50 +0000635 ac_make_noaccess(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000636 }
637}
638
639
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
njnc2699f62003-09-05 23:29:33 +0000724__attribute__ ((regparm(1)))
725static void ac_helperc_LOAD4 ( Addr a )
726{
727 ac_helperc_ACCESS4 ( a, /*isWrite*/False );
728}
729__attribute__ ((regparm(1)))
730static void ac_helperc_STORE4 ( Addr a )
731{
732 ac_helperc_ACCESS4 ( a, /*isWrite*/True );
733}
734
735__attribute__ ((regparm(1)))
736static void ac_helperc_LOAD2 ( Addr a )
737{
738 ac_helperc_ACCESS2 ( a, /*isWrite*/False );
739}
740__attribute__ ((regparm(1)))
741static void ac_helperc_STORE2 ( Addr a )
742{
743 ac_helperc_ACCESS2 ( a, /*isWrite*/True );
744}
745
746__attribute__ ((regparm(1)))
747static void ac_helperc_LOAD1 ( Addr a )
748{
749 ac_helperc_ACCESS1 ( a, /*isWrite*/False );
750}
751__attribute__ ((regparm(1)))
752static void ac_helperc_STORE1 ( Addr a )
753{
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 */
njn43c799e2003-04-08 00:08:52 +0000802 sk_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
njnc2699f62003-09-05 23:29:33 +0000843void ac_fpu_ACCESS_check ( Addr addr, Int 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) {
864 if (!IS_ALIGNED4_ADDR(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) {
879 if (!IS_ALIGNED4_ADDR(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);
njne427a662002-10-02 11:08:25 +0000917 VG_(skin_panic)("fpu_ACCESS_check: unhandled size");
njn25e49d8e72002-09-23 09:36:25 +0000918# endif
919}
920
njnc2699f62003-09-05 23:29:33 +0000921__attribute__ ((regparm(2)))
922static void ac_fpu_READ_check ( Addr addr, Int size )
923{
924 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/False );
925}
926
927__attribute__ ((regparm(2)))
928static void ac_fpu_WRITE_check ( Addr addr, Int size )
929{
930 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/True );
931}
njn25e49d8e72002-09-23 09:36:25 +0000932
933/* ---------------------------------------------------------------------
934 Slow, general cases for FPU access checks.
935 ------------------------------------------------------------------ */
936
njnc2699f62003-09-05 23:29:33 +0000937void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, Int size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000938{
939 Int i;
940 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000941 PROF_EVENT(100);
njn25e49d8e72002-09-23 09:36:25 +0000942 for (i = 0; i < size; i++) {
njn5c004e42002-11-18 11:04:50 +0000943 PROF_EVENT(101);
njn25e49d8e72002-09-23 09:36:25 +0000944 if (get_abit(addr+i) != VGM_BIT_VALID)
945 aerr = True;
946 }
947
948 if (aerr) {
njnc2699f62003-09-05 23:29:33 +0000949 MAC_(record_address_error)( VG_(get_current_tid)(), addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000950 }
951}
952
953
954/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000955/*--- Our instrumenter ---*/
956/*------------------------------------------------------------*/
957
njn25e49d8e72002-09-23 09:36:25 +0000958UCodeBlock* SK_(instrument)(UCodeBlock* cb_in, Addr orig_addr)
959{
960/* Use this rather than eg. -1 because it's a UInt. */
961#define INVALID_DATA_SIZE 999999
962
963 UCodeBlock* cb;
964 Int i;
965 UInstr* u_in;
966 Int t_addr, t_size;
njnc2699f62003-09-05 23:29:33 +0000967 Addr helper;
njn25e49d8e72002-09-23 09:36:25 +0000968
njn810086f2002-11-14 12:42:47 +0000969 cb = VG_(setup_UCodeBlock)(cb_in);
njn25e49d8e72002-09-23 09:36:25 +0000970
njn810086f2002-11-14 12:42:47 +0000971 for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
njn25e49d8e72002-09-23 09:36:25 +0000972
973 t_addr = t_size = INVALID_TEMPREG;
njn810086f2002-11-14 12:42:47 +0000974 u_in = VG_(get_instr)(cb_in, i);
njn25e49d8e72002-09-23 09:36:25 +0000975
976 switch (u_in->opcode) {
sewardj7a5ebcf2002-11-13 22:42:13 +0000977 case NOP: case LOCK: case CALLM_E: case CALLM_S:
njn25e49d8e72002-09-23 09:36:25 +0000978 break;
979
sewardj77d30a22003-10-19 08:18:52 +0000980 /* For memory-ref instrs, copy the data_addr into a temporary
981 * to be passed to the helper at the end of the instruction.
njn25e49d8e72002-09-23 09:36:25 +0000982 */
njnc2699f62003-09-05 23:29:33 +0000983 case LOAD:
njn25e49d8e72002-09-23 09:36:25 +0000984 switch (u_in->size) {
njnc2699f62003-09-05 23:29:33 +0000985 case 4: helper = (Addr)ac_helperc_LOAD4; break;
986 case 2: helper = (Addr)ac_helperc_LOAD2; break;
987 case 1: helper = (Addr)ac_helperc_LOAD1; break;
sewardj77d30a22003-10-19 08:18:52 +0000988 default: VG_(skin_panic)
989 ("addrcheck::SK_(instrument):LOAD");
njn25e49d8e72002-09-23 09:36:25 +0000990 }
njnc2699f62003-09-05 23:29:33 +0000991 uInstr1(cb, CCALL, 0, TempReg, u_in->val1);
992 uCCall (cb, helper, 1, 1, False );
993 VG_(copy_UInstr)(cb, u_in);
994 break;
995
996 case STORE:
997 switch (u_in->size) {
998 case 4: helper = (Addr)ac_helperc_STORE4; break;
999 case 2: helper = (Addr)ac_helperc_STORE2; break;
1000 case 1: helper = (Addr)ac_helperc_STORE1; break;
sewardj77d30a22003-10-19 08:18:52 +00001001 default: VG_(skin_panic)
1002 ("addrcheck::SK_(instrument):STORE");
njnc2699f62003-09-05 23:29:33 +00001003 }
1004 uInstr1(cb, CCALL, 0, TempReg, u_in->val2);
1005 uCCall (cb, helper, 1, 1, False );
njn4ba5a792002-09-30 10:23:54 +00001006 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001007 break;
1008
sewardje3891fa2003-06-15 03:13:48 +00001009 case SSE3ag_MemRd_RegWr:
1010 sk_assert(u_in->size == 4 || u_in->size == 8);
njnc2699f62003-09-05 23:29:33 +00001011 helper = (Addr)ac_fpu_READ_check;
sewardje3891fa2003-06-15 03:13:48 +00001012 goto do_Access_ARG1;
1013 do_Access_ARG1:
1014 sk_assert(u_in->tag1 == TempReg);
1015 t_addr = u_in->val1;
1016 t_size = newTemp(cb);
1017 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
1018 uLiteral(cb, u_in->size);
1019 uInstr2(cb, CCALL, 0, TempReg, t_addr, TempReg, t_size);
njnc2699f62003-09-05 23:29:33 +00001020 uCCall(cb, helper, 2, 2, False );
sewardje3891fa2003-06-15 03:13:48 +00001021 VG_(copy_UInstr)(cb, u_in);
1022 break;
1023
sewardj3d7c9c82003-03-26 21:08:13 +00001024 case MMX2_MemRd:
njnc2699f62003-09-05 23:29:33 +00001025 sk_assert(u_in->size == 4 || u_in->size == 8);
1026 helper = (Addr)ac_fpu_READ_check;
1027 goto do_Access_ARG2;
sewardj3d7c9c82003-03-26 21:08:13 +00001028 case MMX2_MemWr:
sewardjd7971012003-04-04 00:21:58 +00001029 sk_assert(u_in->size == 4 || u_in->size == 8);
njnc2699f62003-09-05 23:29:33 +00001030 helper = (Addr)ac_fpu_WRITE_check;
sewardj1863abc2003-06-14 16:01:32 +00001031 goto do_Access_ARG2;
1032 case FPU_R:
njnc2699f62003-09-05 23:29:33 +00001033 helper = (Addr)ac_fpu_READ_check;
1034 goto do_Access_ARG2;
sewardj1863abc2003-06-14 16:01:32 +00001035 case FPU_W:
njnc2699f62003-09-05 23:29:33 +00001036 helper = (Addr)ac_fpu_WRITE_check;
sewardj1863abc2003-06-14 16:01:32 +00001037 goto do_Access_ARG2;
1038 do_Access_ARG2:
1039 sk_assert(u_in->tag2 == TempReg);
sewardj3d7c9c82003-03-26 21:08:13 +00001040 t_addr = u_in->val2;
1041 t_size = newTemp(cb);
1042 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
sewardjd7971012003-04-04 00:21:58 +00001043 uLiteral(cb, u_in->size);
sewardj3d7c9c82003-03-26 21:08:13 +00001044 uInstr2(cb, CCALL, 0, TempReg, t_addr, TempReg, t_size);
njnc2699f62003-09-05 23:29:33 +00001045 uCCall(cb, helper, 2, 2, False );
sewardj3d7c9c82003-03-26 21:08:13 +00001046 VG_(copy_UInstr)(cb, u_in);
1047 break;
1048
sewardj77d30a22003-10-19 08:18:52 +00001049 case SSE3a_MemRd:
sewardj1863abc2003-06-14 16:01:32 +00001050 case SSE2a_MemRd:
nethercoteb1affa82004-01-19 19:14:18 +00001051 case SSE3a1_MemRd:
1052 case SSE2a1_MemRd:
njnc2699f62003-09-05 23:29:33 +00001053 helper = (Addr)ac_fpu_READ_check;
1054 goto do_Access_ARG3;
sewardj1863abc2003-06-14 16:01:32 +00001055 case SSE2a_MemWr:
1056 case SSE3a_MemWr:
njnc2699f62003-09-05 23:29:33 +00001057 helper = (Addr)ac_fpu_WRITE_check;
sewardj1863abc2003-06-14 16:01:32 +00001058 goto do_Access_ARG3;
1059 do_Access_ARG3:
jsewardfca60182004-01-04 23:30:55 +00001060 sk_assert(u_in->size == 4 || u_in->size == 8
1061 || u_in->size == 16 || u_in->size == 512);
sewardj1863abc2003-06-14 16:01:32 +00001062 sk_assert(u_in->tag3 == TempReg);
1063 t_addr = u_in->val3;
1064 t_size = newTemp(cb);
1065 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
1066 uLiteral(cb, u_in->size);
1067 uInstr2(cb, CCALL, 0, TempReg, t_addr, TempReg, t_size);
njnc2699f62003-09-05 23:29:33 +00001068 uCCall(cb, helper, 2, 2, False );
sewardj1863abc2003-06-14 16:01:32 +00001069 VG_(copy_UInstr)(cb, u_in);
1070 break;
1071
sewardj095c3bc2003-06-15 23:26:04 +00001072 case SSE3e1_RegRd:
sewardjabf8bf82003-06-15 22:28:05 +00001073 case SSE3e_RegWr:
sewardje3891fa2003-06-15 03:13:48 +00001074 case SSE3g1_RegWr:
sewardj6bc40552003-06-15 01:40:58 +00001075 case SSE5:
sewardj1863abc2003-06-14 16:01:32 +00001076 case SSE3g_RegWr:
sewardj4fbe6e92003-06-15 21:54:34 +00001077 case SSE3e_RegRd:
sewardj1863abc2003-06-14 16:01:32 +00001078 case SSE4:
sewardj77d30a22003-10-19 08:18:52 +00001079 case SSE3:
njn25e49d8e72002-09-23 09:36:25 +00001080 default:
njn4ba5a792002-09-30 10:23:54 +00001081 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001082 break;
1083 }
1084 }
1085
njn4ba5a792002-09-30 10:23:54 +00001086 VG_(free_UCodeBlock)(cb_in);
njn25e49d8e72002-09-23 09:36:25 +00001087 return cb;
1088}
1089
1090
njn25e49d8e72002-09-23 09:36:25 +00001091/*------------------------------------------------------------*/
1092/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
1093/*------------------------------------------------------------*/
1094
sewardja4495682002-10-21 07:29:59 +00001095/* For the memory leak detector, say whether an entire 64k chunk of
1096 address space is possibly in use, or not. If in doubt return
1097 True.
njn25e49d8e72002-09-23 09:36:25 +00001098*/
sewardja4495682002-10-21 07:29:59 +00001099static
1100Bool ac_is_valid_64k_chunk ( UInt chunk_number )
njn25e49d8e72002-09-23 09:36:25 +00001101{
sewardja4495682002-10-21 07:29:59 +00001102 sk_assert(chunk_number >= 0 && chunk_number < 65536);
1103 if (IS_DISTINGUISHED_SM(primary_map[chunk_number])) {
1104 /* Definitely not in use. */
1105 return False;
1106 } else {
1107 return True;
njn25e49d8e72002-09-23 09:36:25 +00001108 }
1109}
1110
1111
sewardja4495682002-10-21 07:29:59 +00001112/* For the memory leak detector, say whether or not a given word
1113 address is to be regarded as valid. */
1114static
1115Bool ac_is_valid_address ( Addr a )
1116{
1117 UChar abits;
1118 sk_assert(IS_ALIGNED4_ADDR(a));
1119 abits = get_abits4_ALIGNED(a);
1120 if (abits == VGM_NIBBLE_VALID) {
1121 return True;
1122 } else {
1123 return False;
1124 }
1125}
1126
1127
1128/* Leak detector for this skin. We don't actually do anything, merely
1129 run the generic leak detector with suitable parameters for this
1130 skin. */
njn5c004e42002-11-18 11:04:50 +00001131static void ac_detect_memory_leaks ( void )
njn25e49d8e72002-09-23 09:36:25 +00001132{
njn43c799e2003-04-08 00:08:52 +00001133 MAC_(do_detect_memory_leaks) ( ac_is_valid_64k_chunk, ac_is_valid_address );
njn25e49d8e72002-09-23 09:36:25 +00001134}
1135
1136
1137/* ---------------------------------------------------------------------
1138 Sanity check machinery (permanently engaged).
1139 ------------------------------------------------------------------ */
1140
njn25e49d8e72002-09-23 09:36:25 +00001141Bool SK_(cheap_sanity_check) ( void )
1142{
jseward9800fd32004-01-04 23:08:04 +00001143 /* nothing useful we can rapidly check */
1144 return True;
njn25e49d8e72002-09-23 09:36:25 +00001145}
1146
1147Bool SK_(expensive_sanity_check) ( void )
1148{
1149 Int i;
1150
1151 /* Make sure nobody changed the distinguished secondary. */
1152 for (i = 0; i < 8192; i++)
1153 if (distinguished_secondary_map.abits[i] != VGM_BYTE_INVALID)
1154 return False;
1155
1156 /* Make sure that the upper 3/4 of the primary map hasn't
1157 been messed with. */
1158 for (i = 65536; i < 262144; i++)
1159 if (primary_map[i] != & distinguished_secondary_map)
1160 return False;
1161
1162 return True;
1163}
1164
njn47363ab2003-04-21 13:24:40 +00001165/*------------------------------------------------------------*/
1166/*--- Client requests ---*/
1167/*------------------------------------------------------------*/
1168
njn72718642003-07-24 08:45:32 +00001169Bool SK_(handle_client_request) ( ThreadId tid, UInt* arg_block, UInt *ret )
sewardjd8033d92002-12-08 22:16:58 +00001170{
sewardjbf310d92002-12-28 13:09:57 +00001171#define IGNORE(what) \
1172 do { \
1173 if (moans-- > 0) { \
1174 VG_(message)(Vg_UserMsg, \
1175 "Warning: Addrcheck: ignoring `%s' request.", what); \
1176 VG_(message)(Vg_UserMsg, \
nethercote137bc552003-11-14 17:47:54 +00001177 " To honour this request, rerun with --tool=memcheck."); \
sewardjbf310d92002-12-28 13:09:57 +00001178 } \
1179 } while (0)
1180
sewardjd8033d92002-12-08 22:16:58 +00001181 UInt* arg = arg_block;
sewardjbf310d92002-12-28 13:09:57 +00001182 static Int moans = 3;
sewardjd8033d92002-12-08 22:16:58 +00001183
1184 /* Overload memcheck client reqs */
njnd7994182003-10-02 13:44:04 +00001185 if (!VG_IS_SKIN_USERREQ('M','C',arg[0])
1186 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
1187 && VG_USERREQ__FREELIKE_BLOCK != arg[0])
sewardjd8033d92002-12-08 22:16:58 +00001188 return False;
1189
1190 switch (arg[0]) {
1191 case VG_USERREQ__DO_LEAK_CHECK:
1192 ac_detect_memory_leaks();
1193 *ret = 0; /* return value is meaningless */
1194 break;
1195
sewardjbf310d92002-12-28 13:09:57 +00001196 /* Ignore these */
sewardjd8033d92002-12-08 22:16:58 +00001197 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
sewardjbf310d92002-12-28 13:09:57 +00001198 IGNORE("VALGRIND_CHECK_WRITABLE");
1199 return False;
sewardjd8033d92002-12-08 22:16:58 +00001200 case VG_USERREQ__CHECK_READABLE: /* check readable */
sewardjbf310d92002-12-28 13:09:57 +00001201 IGNORE("VALGRIND_CHECK_READABLE");
1202 return False;
sewardjd8033d92002-12-08 22:16:58 +00001203 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
sewardjbf310d92002-12-28 13:09:57 +00001204 IGNORE("VALGRIND_MAKE_NOACCESS");
1205 return False;
sewardjd8033d92002-12-08 22:16:58 +00001206 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
sewardjbf310d92002-12-28 13:09:57 +00001207 IGNORE("VALGRIND_MAKE_WRITABLE");
1208 return False;
sewardjd8033d92002-12-08 22:16:58 +00001209 case VG_USERREQ__MAKE_READABLE: /* make readable */
sewardjbf310d92002-12-28 13:09:57 +00001210 IGNORE("VALGRIND_MAKE_READABLE");
1211 return False;
sewardjd8033d92002-12-08 22:16:58 +00001212 case VG_USERREQ__DISCARD: /* discard */
sewardjbf310d92002-12-28 13:09:57 +00001213 IGNORE("VALGRIND_CHECK_DISCARD");
1214 return False;
sewardjd8033d92002-12-08 22:16:58 +00001215
1216 default:
njn72718642003-07-24 08:45:32 +00001217 if (MAC_(handle_common_client_requests)(tid, arg_block, ret )) {
njn47363ab2003-04-21 13:24:40 +00001218 return True;
1219 } else {
1220 VG_(message)(Vg_UserMsg,
1221 "Warning: unknown addrcheck client request code %d",
1222 arg[0]);
1223 return False;
1224 }
sewardjd8033d92002-12-08 22:16:58 +00001225 }
1226 return True;
sewardjbf310d92002-12-28 13:09:57 +00001227
1228#undef IGNORE
sewardjd8033d92002-12-08 22:16:58 +00001229}
1230
njn25e49d8e72002-09-23 09:36:25 +00001231/*------------------------------------------------------------*/
1232/*--- Setup ---*/
1233/*------------------------------------------------------------*/
1234
njn25e49d8e72002-09-23 09:36:25 +00001235Bool SK_(process_cmd_line_option)(Char* arg)
1236{
njn43c799e2003-04-08 00:08:52 +00001237 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001238}
1239
njn3e884182003-04-15 13:03:23 +00001240void SK_(print_usage)(void)
njn25e49d8e72002-09-23 09:36:25 +00001241{
njn3e884182003-04-15 13:03:23 +00001242 MAC_(print_common_usage)();
1243}
1244
1245void SK_(print_debug_usage)(void)
1246{
1247 MAC_(print_common_debug_usage)();
njn25e49d8e72002-09-23 09:36:25 +00001248}
1249
1250
1251/*------------------------------------------------------------*/
1252/*--- Setup ---*/
1253/*------------------------------------------------------------*/
1254
njn810086f2002-11-14 12:42:47 +00001255void SK_(pre_clo_init)(void)
njn25e49d8e72002-09-23 09:36:25 +00001256{
njn810086f2002-11-14 12:42:47 +00001257 VG_(details_name) ("Addrcheck");
1258 VG_(details_version) (NULL);
1259 VG_(details_description) ("a fine-grained address checker");
1260 VG_(details_copyright_author)(
nethercotebb1c9912004-01-04 16:43:23 +00001261 "Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward.");
nethercote421281e2003-11-20 16:20:55 +00001262 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardj78210aa2002-12-01 02:55:46 +00001263 VG_(details_avg_translation_sizeB) ( 135 );
njn25e49d8e72002-09-23 09:36:25 +00001264
njn810086f2002-11-14 12:42:47 +00001265 VG_(needs_core_errors) ();
1266 VG_(needs_skin_errors) ();
1267 VG_(needs_libc_freeres) ();
njn810086f2002-11-14 12:42:47 +00001268 VG_(needs_command_line_options)();
1269 VG_(needs_client_requests) ();
1270 VG_(needs_syscall_wrapper) ();
njn810086f2002-11-14 12:42:47 +00001271 VG_(needs_sanity_checks) ();
fitzhardinge98abfc72003-12-16 02:05:15 +00001272 VG_(needs_shadow_memory) ();
njn25e49d8e72002-09-23 09:36:25 +00001273
njn3e884182003-04-15 13:03:23 +00001274 MAC_( new_mem_heap) = & ac_new_mem_heap;
1275 MAC_( ban_mem_heap) = & ac_make_noaccess;
1276 MAC_(copy_mem_heap) = & ac_copy_address_range_state;
1277 MAC_( die_mem_heap) = & ac_make_noaccess;
sewardjecf8e102003-07-12 12:11:39 +00001278 MAC_(check_noaccess) = & ac_check_noaccess;
njn3e884182003-04-15 13:03:23 +00001279
fitzhardinge98abfc72003-12-16 02:05:15 +00001280 VG_(init_new_mem_startup) ( & ac_new_mem_startup );
1281 VG_(init_new_mem_stack_signal) ( & ac_make_accessible );
1282 VG_(init_new_mem_brk) ( & ac_make_accessible );
1283 VG_(init_new_mem_mmap) ( & ac_set_perms );
njn25e49d8e72002-09-23 09:36:25 +00001284
fitzhardinge98abfc72003-12-16 02:05:15 +00001285 VG_(init_copy_mem_remap) ( & ac_copy_address_range_state );
1286 VG_(init_change_mem_mprotect) ( & ac_set_perms );
njn3e884182003-04-15 13:03:23 +00001287
fitzhardinge98abfc72003-12-16 02:05:15 +00001288 VG_(init_die_mem_stack_signal) ( & ac_make_noaccess );
1289 VG_(init_die_mem_brk) ( & ac_make_noaccess );
1290 VG_(init_die_mem_munmap) ( & ac_make_noaccess );
njn3e884182003-04-15 13:03:23 +00001291
fitzhardinge98abfc72003-12-16 02:05:15 +00001292 VG_(init_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
1293 VG_(init_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
1294 VG_(init_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
1295 VG_(init_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
1296 VG_(init_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
1297 VG_(init_new_mem_stack) ( & MAC_(new_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001298
fitzhardinge98abfc72003-12-16 02:05:15 +00001299 VG_(init_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
1300 VG_(init_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
1301 VG_(init_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
1302 VG_(init_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
1303 VG_(init_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
1304 VG_(init_die_mem_stack) ( & MAC_(die_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001305
fitzhardinge98abfc72003-12-16 02:05:15 +00001306 VG_(init_ban_mem_stack) ( & ac_make_noaccess );
njn25e49d8e72002-09-23 09:36:25 +00001307
fitzhardinge98abfc72003-12-16 02:05:15 +00001308 VG_(init_pre_mem_read) ( & ac_check_is_readable );
1309 VG_(init_pre_mem_read_asciiz) ( & ac_check_is_readable_asciiz );
1310 VG_(init_pre_mem_write) ( & ac_check_is_writable );
1311 VG_(init_post_mem_write) ( & ac_make_accessible );
njn25e49d8e72002-09-23 09:36:25 +00001312
njnc2699f62003-09-05 23:29:33 +00001313 VG_(register_compact_helper)((Addr) & ac_helperc_LOAD4);
1314 VG_(register_compact_helper)((Addr) & ac_helperc_LOAD2);
1315 VG_(register_compact_helper)((Addr) & ac_helperc_LOAD1);
1316 VG_(register_compact_helper)((Addr) & ac_helperc_STORE4);
1317 VG_(register_compact_helper)((Addr) & ac_helperc_STORE2);
1318 VG_(register_compact_helper)((Addr) & ac_helperc_STORE1);
1319 VG_(register_noncompact_helper)((Addr) & ac_fpu_READ_check);
1320 VG_(register_noncompact_helper)((Addr) & ac_fpu_WRITE_check);
njn25e49d8e72002-09-23 09:36:25 +00001321
1322 VGP_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
1323 VGP_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
njn9b007f62003-04-07 14:40:25 +00001324 VGP_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
njnd04b7c62002-10-03 14:05:52 +00001325
1326 init_shadow_memory();
njn3e884182003-04-15 13:03:23 +00001327 MAC_(common_pre_clo_init)();
njn5c004e42002-11-18 11:04:50 +00001328}
1329
1330void SK_(post_clo_init) ( void )
1331{
1332}
1333
njn7d9f94d2003-04-22 21:41:40 +00001334void SK_(fini) ( Int exitcode )
njn5c004e42002-11-18 11:04:50 +00001335{
njn3e884182003-04-15 13:03:23 +00001336 MAC_(common_fini)( ac_detect_memory_leaks );
njn25e49d8e72002-09-23 09:36:25 +00001337}
1338
fitzhardinge98abfc72003-12-16 02:05:15 +00001339VG_DETERMINE_INTERFACE_VERSION(SK_(pre_clo_init), 1./8)
1340
1341
njn25e49d8e72002-09-23 09:36:25 +00001342/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00001343/*--- end ac_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00001344/*--------------------------------------------------------------------*/