blob: e47fd0a5f71e8f7bb368e26d73fe671a3f54b3da [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
njn0e1b5142003-04-15 14:58:06 +000012 Copyright (C) 2000-2003 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
njn27f1a382002-11-08 15:48:16 +000038VG_DETERMINE_INTERFACE_VERSION
39
njn25e49d8e72002-09-23 09:36:25 +000040/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000041/*--- Comparing and printing errors ---*/
42/*------------------------------------------------------------*/
43
njn43c799e2003-04-08 00:08:52 +000044void SK_(pp_SkinError) ( Error* err )
njn25e49d8e72002-09-23 09:36:25 +000045{
njn43c799e2003-04-08 00:08:52 +000046 MAC_Error* err_extra = VG_(get_error_extra)(err);
njn25e49d8e72002-09-23 09:36:25 +000047
njn810086f2002-11-14 12:42:47 +000048 switch (VG_(get_error_kind)(err)) {
njn25e49d8e72002-09-23 09:36:25 +000049 case CoreMemErr:
njn43c799e2003-04-08 00:08:52 +000050 VG_(message)(Vg_UserMsg, "%s contains unaddressable byte(s)",
51 VG_(get_error_string)(err));
52 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
njn25e49d8e72002-09-23 09:36:25 +000053 break;
54
njn25e49d8e72002-09-23 09:36:25 +000055 case ParamErr:
njn43c799e2003-04-08 00:08:52 +000056 VG_(message)(Vg_UserMsg,
57 "Syscall param %s contains unaddressable byte(s)",
58 VG_(get_error_string)(err) );
59 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
60 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
njn25e49d8e72002-09-23 09:36:25 +000061 break;
62
63 case UserErr:
njn43c799e2003-04-08 00:08:52 +000064 VG_(message)(Vg_UserMsg,
65 "Unaddressable byte(s) found during client check request");
66 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
67 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
njn25e49d8e72002-09-23 09:36:25 +000068 break;
69
70 default:
njn43c799e2003-04-08 00:08:52 +000071 MAC_(pp_shared_SkinError)(err);
72 break;
njn25e49d8e72002-09-23 09:36:25 +000073 }
74}
75
76/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000077/*--- Suppressions ---*/
78/*------------------------------------------------------------*/
79
njn810086f2002-11-14 12:42:47 +000080Bool SK_(recognised_suppression) ( Char* name, Supp* su )
njn25e49d8e72002-09-23 09:36:25 +000081{
njn43c799e2003-04-08 00:08:52 +000082 return MAC_(shared_recognised_suppression)(name, su);
njn25e49d8e72002-09-23 09:36:25 +000083}
84
njn5c004e42002-11-18 11:04:50 +000085#define DEBUG(fmt, args...) //VG_(printf)(fmt, ## args)
86
njn25e49d8e72002-09-23 09:36:25 +000087/*------------------------------------------------------------*/
88/*--- Low-level support for memory checking. ---*/
89/*------------------------------------------------------------*/
90
91/* All reads and writes are checked against a memory map, which
92 records the state of all memory in the process. The memory map is
93 organised like this:
94
95 The top 16 bits of an address are used to index into a top-level
96 map table, containing 65536 entries. Each entry is a pointer to a
97 second-level map, which records the accesibililty and validity
98 permissions for the 65536 bytes indexed by the lower 16 bits of the
99 address. Each byte is represented by one bit, indicating
100 accessibility. So each second-level map contains 8192 bytes. This
101 two-level arrangement conveniently divides the 4G address space
102 into 64k lumps, each size 64k bytes.
103
104 All entries in the primary (top-level) map must point to a valid
105 secondary (second-level) map. Since most of the 4G of address
106 space will not be in use -- ie, not mapped at all -- there is a
107 distinguished secondary map, which indicates `not addressible and
108 not valid' writeable for all bytes. Entries in the primary map for
109 which the entire 64k is not in use at all point at this
110 distinguished map.
111
112 [...] lots of stuff deleted due to out of date-ness
113
114 As a final optimisation, the alignment and address checks for
115 4-byte loads and stores are combined in a neat way. The primary
116 map is extended to have 262144 entries (2^18), rather than 2^16.
117 The top 3/4 of these entries are permanently set to the
118 distinguished secondary map. For a 4-byte load/store, the
119 top-level map is indexed not with (addr >> 16) but instead f(addr),
120 where
121
122 f( XXXX XXXX XXXX XXXX ____ ____ ____ __YZ )
123 = ____ ____ ____ __YZ XXXX XXXX XXXX XXXX or
124 = ____ ____ ____ __ZY XXXX XXXX XXXX XXXX
125
126 ie the lowest two bits are placed above the 16 high address bits.
127 If either of these two bits are nonzero, the address is misaligned;
128 this will select a secondary map from the upper 3/4 of the primary
129 map. Because this is always the distinguished secondary map, a
130 (bogus) address check failure will result. The failure handling
131 code can then figure out whether this is a genuine addr check
132 failure or whether it is a possibly-legitimate access at a
133 misaligned address. */
134
135
136/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000137/*--- Function declarations. ---*/
138/*------------------------------------------------------------*/
139
njnc2699f62003-09-05 23:29:33 +0000140static void ac_ACCESS4_SLOWLY ( Addr a, Bool isWrite );
141static void ac_ACCESS2_SLOWLY ( Addr a, Bool isWrite );
142static void ac_ACCESS1_SLOWLY ( Addr a, Bool isWrite );
143static void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, Int size, Bool isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000144
145/*------------------------------------------------------------*/
146/*--- Data defns. ---*/
147/*------------------------------------------------------------*/
148
149typedef
150 struct {
151 UChar abits[8192];
152 }
153 AcSecMap;
154
155static AcSecMap* primary_map[ /*65536*/ 262144 ];
156static AcSecMap distinguished_secondary_map;
157
njn25e49d8e72002-09-23 09:36:25 +0000158static void init_shadow_memory ( void )
159{
160 Int i;
161
162 for (i = 0; i < 8192; i++) /* Invalid address */
163 distinguished_secondary_map.abits[i] = VGM_BYTE_INVALID;
164
165 /* These entries gradually get overwritten as the used address
166 space expands. */
167 for (i = 0; i < 65536; i++)
168 primary_map[i] = &distinguished_secondary_map;
169
170 /* These ones should never change; it's a bug in Valgrind if they do. */
171 for (i = 65536; i < 262144; i++)
172 primary_map[i] = &distinguished_secondary_map;
173}
174
njn25e49d8e72002-09-23 09:36:25 +0000175/*------------------------------------------------------------*/
176/*--- Basic bitmap management, reading and writing. ---*/
177/*------------------------------------------------------------*/
178
179/* Allocate and initialise a secondary map. */
180
181static AcSecMap* alloc_secondary_map ( __attribute__ ((unused))
182 Char* caller )
183{
184 AcSecMap* map;
185 UInt i;
186 PROF_EVENT(10);
187
188 /* Mark all bytes as invalid access and invalid value. */
189
190 /* It just happens that a AcSecMap occupies exactly 18 pages --
191 although this isn't important, so the following assert is
192 spurious. */
njne427a662002-10-02 11:08:25 +0000193 sk_assert(0 == (sizeof(AcSecMap) % VKI_BYTES_PER_PAGE));
njn25e49d8e72002-09-23 09:36:25 +0000194 map = VG_(get_memory_from_mmap)( sizeof(AcSecMap), caller );
195
196 for (i = 0; i < 8192; i++)
197 map->abits[i] = VGM_BYTE_INVALID; /* Invalid address */
198
199 /* VG_(printf)("ALLOC_2MAP(%s)\n", caller ); */
200 return map;
201}
202
203
204/* Basic reading/writing of the bitmaps, for byte-sized accesses. */
205
206static __inline__ UChar get_abit ( Addr a )
207{
208 AcSecMap* sm = primary_map[a >> 16];
209 UInt sm_off = a & 0xFFFF;
210 PROF_EVENT(20);
211# if 0
212 if (IS_DISTINGUISHED_SM(sm))
213 VG_(message)(Vg_DebugMsg,
214 "accessed distinguished 2ndary (A)map! 0x%x\n", a);
215# endif
216 return BITARR_TEST(sm->abits, sm_off)
217 ? VGM_BIT_INVALID : VGM_BIT_VALID;
218}
219
sewardj56867352003-10-12 10:27:06 +0000220static /* __inline__ */ void set_abit ( Addr a, UChar abit )
njn25e49d8e72002-09-23 09:36:25 +0000221{
222 AcSecMap* sm;
223 UInt sm_off;
224 PROF_EVENT(22);
225 ENSURE_MAPPABLE(a, "set_abit");
226 sm = primary_map[a >> 16];
227 sm_off = a & 0xFFFF;
228 if (abit)
229 BITARR_SET(sm->abits, sm_off);
230 else
231 BITARR_CLEAR(sm->abits, sm_off);
232}
233
234
235/* Reading/writing of the bitmaps, for aligned word-sized accesses. */
236
237static __inline__ UChar get_abits4_ALIGNED ( Addr a )
238{
239 AcSecMap* sm;
240 UInt sm_off;
241 UChar abits8;
242 PROF_EVENT(24);
243# ifdef VG_DEBUG_MEMORY
njne427a662002-10-02 11:08:25 +0000244 sk_assert(IS_ALIGNED4_ADDR(a));
njn25e49d8e72002-09-23 09:36:25 +0000245# endif
246 sm = primary_map[a >> 16];
247 sm_off = a & 0xFFFF;
248 abits8 = sm->abits[sm_off >> 3];
249 abits8 >>= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
250 abits8 &= 0x0F;
251 return abits8;
252}
253
254
255
256/*------------------------------------------------------------*/
257/*--- Setting permissions over address ranges. ---*/
258/*------------------------------------------------------------*/
259
sewardj56867352003-10-12 10:27:06 +0000260static /* __inline__ */
sewardj5de6ee02002-12-14 23:11:35 +0000261void set_address_range_perms ( Addr a, UInt len,
262 UInt example_a_bit )
njn25e49d8e72002-09-23 09:36:25 +0000263{
264 UChar abyte8;
265 UInt sm_off;
266 AcSecMap* sm;
267
268 PROF_EVENT(30);
269
270 if (len == 0)
271 return;
272
273 if (len > 100 * 1000 * 1000) {
274 VG_(message)(Vg_UserMsg,
275 "Warning: set address range perms: "
276 "large range %u, a %d",
277 len, example_a_bit );
278 }
279
280 VGP_PUSHCC(VgpSetMem);
281
282 /* Requests to change permissions of huge address ranges may
283 indicate bugs in our machinery. 30,000,000 is arbitrary, but so
284 far all legitimate requests have fallen beneath that size. */
285 /* 4 Mar 02: this is just stupid; get rid of it. */
njne427a662002-10-02 11:08:25 +0000286 /* sk_assert(len < 30000000); */
njn25e49d8e72002-09-23 09:36:25 +0000287
288 /* Check the permissions make sense. */
njne427a662002-10-02 11:08:25 +0000289 sk_assert(example_a_bit == VGM_BIT_VALID
njn25e49d8e72002-09-23 09:36:25 +0000290 || example_a_bit == VGM_BIT_INVALID);
291
292 /* In order that we can charge through the address space at 8
293 bytes/main-loop iteration, make up some perms. */
294 abyte8 = (example_a_bit << 7)
295 | (example_a_bit << 6)
296 | (example_a_bit << 5)
297 | (example_a_bit << 4)
298 | (example_a_bit << 3)
299 | (example_a_bit << 2)
300 | (example_a_bit << 1)
301 | (example_a_bit << 0);
302
303# ifdef VG_DEBUG_MEMORY
304 /* Do it ... */
305 while (True) {
306 PROF_EVENT(31);
307 if (len == 0) break;
308 set_abit ( a, example_a_bit );
309 set_vbyte ( a, vbyte );
310 a++;
311 len--;
312 }
313
314# else
315 /* Slowly do parts preceding 8-byte alignment. */
316 while (True) {
317 PROF_EVENT(31);
318 if (len == 0) break;
319 if ((a % 8) == 0) break;
320 set_abit ( a, example_a_bit );
321 a++;
322 len--;
323 }
324
325 if (len == 0) {
326 VGP_POPCC(VgpSetMem);
327 return;
328 }
njne427a662002-10-02 11:08:25 +0000329 sk_assert((a % 8) == 0 && len > 0);
njn25e49d8e72002-09-23 09:36:25 +0000330
331 /* Once aligned, go fast. */
332 while (True) {
333 PROF_EVENT(32);
334 if (len < 8) break;
335 ENSURE_MAPPABLE(a, "set_address_range_perms(fast)");
336 sm = primary_map[a >> 16];
337 sm_off = a & 0xFFFF;
338 sm->abits[sm_off >> 3] = abyte8;
339 a += 8;
340 len -= 8;
341 }
342
343 if (len == 0) {
344 VGP_POPCC(VgpSetMem);
345 return;
346 }
njne427a662002-10-02 11:08:25 +0000347 sk_assert((a % 8) == 0 && len > 0 && len < 8);
njn25e49d8e72002-09-23 09:36:25 +0000348
349 /* Finish the upper fragment. */
350 while (True) {
351 PROF_EVENT(33);
352 if (len == 0) break;
353 set_abit ( a, example_a_bit );
354 a++;
355 len--;
356 }
357# endif
358
359 /* Check that zero page and highest page have not been written to
360 -- this could happen with buggy syscall wrappers. Today
361 (2001-04-26) had precisely such a problem with __NR_setitimer. */
njne427a662002-10-02 11:08:25 +0000362 sk_assert(SK_(cheap_sanity_check)());
njn25e49d8e72002-09-23 09:36:25 +0000363 VGP_POPCC(VgpSetMem);
364}
365
366/* Set permissions for address ranges ... */
367
njn5c004e42002-11-18 11:04:50 +0000368static void ac_make_noaccess ( Addr a, UInt len )
njn25e49d8e72002-09-23 09:36:25 +0000369{
370 PROF_EVENT(35);
njn5c004e42002-11-18 11:04:50 +0000371 DEBUG("ac_make_noaccess(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000372 set_address_range_perms ( a, len, VGM_BIT_INVALID );
373}
374
njn5c004e42002-11-18 11:04:50 +0000375static void ac_make_accessible ( Addr a, UInt len )
njn25e49d8e72002-09-23 09:36:25 +0000376{
njn5c004e42002-11-18 11:04:50 +0000377 PROF_EVENT(38);
378 DEBUG("ac_make_accessible(%p, %x)\n", a, len);
njn25e49d8e72002-09-23 09:36:25 +0000379 set_address_range_perms ( a, len, VGM_BIT_VALID );
380}
381
njn9b007f62003-04-07 14:40:25 +0000382static __inline__
383void make_aligned_word_noaccess(Addr a)
384{
385 AcSecMap* sm;
386 UInt sm_off;
387 UChar mask;
388
389 VGP_PUSHCC(VgpESPAdj);
390 ENSURE_MAPPABLE(a, "make_aligned_word_noaccess");
391 sm = primary_map[a >> 16];
392 sm_off = a & 0xFFFF;
393 mask = 0x0F;
394 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
395 /* mask now contains 1s where we wish to make address bits invalid (1s). */
396 sm->abits[sm_off >> 3] |= mask;
397 VGP_POPCC(VgpESPAdj);
398}
399
400static __inline__
401void make_aligned_word_accessible(Addr a)
402{
403 AcSecMap* sm;
404 UInt sm_off;
405 UChar mask;
406
407 VGP_PUSHCC(VgpESPAdj);
408 ENSURE_MAPPABLE(a, "make_aligned_word_accessible");
409 sm = primary_map[a >> 16];
410 sm_off = a & 0xFFFF;
411 mask = 0x0F;
412 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
413 /* mask now contains 1s where we wish to make address bits
414 invalid (0s). */
415 sm->abits[sm_off >> 3] &= ~mask;
416 VGP_POPCC(VgpESPAdj);
417}
418
419/* Nb: by "aligned" here we mean 8-byte aligned */
420static __inline__
421void make_aligned_doubleword_accessible(Addr a)
422{
423 AcSecMap* sm;
424 UInt sm_off;
425
426 VGP_PUSHCC(VgpESPAdj);
427 ENSURE_MAPPABLE(a, "make_aligned_doubleword_accessible");
428 sm = primary_map[a >> 16];
429 sm_off = a & 0xFFFF;
430 sm->abits[sm_off >> 3] = VGM_BYTE_VALID;
431 VGP_POPCC(VgpESPAdj);
432}
433
434static __inline__
435void make_aligned_doubleword_noaccess(Addr a)
436{
437 AcSecMap* sm;
438 UInt sm_off;
439
440 VGP_PUSHCC(VgpESPAdj);
441 ENSURE_MAPPABLE(a, "make_aligned_doubleword_noaccess");
442 sm = primary_map[a >> 16];
443 sm_off = a & 0xFFFF;
444 sm->abits[sm_off >> 3] = VGM_BYTE_INVALID;
445 VGP_POPCC(VgpESPAdj);
446}
447
448/* The %esp update handling functions */
449ESP_UPDATE_HANDLERS ( make_aligned_word_accessible,
450 make_aligned_word_noaccess,
451 make_aligned_doubleword_accessible,
452 make_aligned_doubleword_noaccess,
453 ac_make_accessible,
454 ac_make_noaccess
455 );
456
457
njn25e49d8e72002-09-23 09:36:25 +0000458/* Block-copy permissions (needed for implementing realloc()). */
459
njn5c004e42002-11-18 11:04:50 +0000460static void ac_copy_address_range_state ( Addr src, Addr dst, UInt len )
njn25e49d8e72002-09-23 09:36:25 +0000461{
462 UInt i;
463
njn5c004e42002-11-18 11:04:50 +0000464 DEBUG("ac_copy_address_range_state\n");
njn25e49d8e72002-09-23 09:36:25 +0000465
466 PROF_EVENT(40);
467 for (i = 0; i < len; i++) {
468 UChar abit = get_abit ( src+i );
469 PROF_EVENT(41);
470 set_abit ( dst+i, abit );
471 }
472}
473
474
475/* Check permissions for address range. If inadequate permissions
476 exist, *bad_addr is set to the offending address, so the caller can
477 know what it is. */
478
njn5c004e42002-11-18 11:04:50 +0000479static __inline__
480Bool ac_check_accessible ( Addr a, UInt len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000481{
482 UInt i;
483 UChar abit;
njn5c004e42002-11-18 11:04:50 +0000484 PROF_EVENT(48);
njn25e49d8e72002-09-23 09:36:25 +0000485 for (i = 0; i < len; i++) {
njn5c004e42002-11-18 11:04:50 +0000486 PROF_EVENT(49);
njn25e49d8e72002-09-23 09:36:25 +0000487 abit = get_abit(a);
488 if (abit == VGM_BIT_INVALID) {
489 if (bad_addr != NULL) *bad_addr = a;
490 return False;
491 }
492 a++;
493 }
494 return True;
495}
496
sewardjecf8e102003-07-12 12:11:39 +0000497/* The opposite; check that an address range is inaccessible. */
498static
499Bool ac_check_noaccess ( Addr a, UInt len, Addr* bad_addr )
500{
501 UInt i;
502 UChar abit;
503 PROF_EVENT(48);
504 for (i = 0; i < len; i++) {
505 PROF_EVENT(49);
506 abit = get_abit(a);
507 if (abit == VGM_BIT_VALID) {
508 if (bad_addr != NULL) *bad_addr = a;
509 return False;
510 }
511 a++;
512 }
513 return True;
514}
515
njn25e49d8e72002-09-23 09:36:25 +0000516/* Check a zero-terminated ascii string. Tricky -- don't want to
517 examine the actual bytes, to find the end, until we're sure it is
518 safe to do so. */
519
njn5c004e42002-11-18 11:04:50 +0000520static __inline__
521Bool ac_check_readable_asciiz ( Addr a, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +0000522{
523 UChar abit;
524 PROF_EVENT(46);
njn5c004e42002-11-18 11:04:50 +0000525 DEBUG("ac_check_readable_asciiz\n");
njn25e49d8e72002-09-23 09:36:25 +0000526 while (True) {
527 PROF_EVENT(47);
528 abit = get_abit(a);
529 if (abit != VGM_BIT_VALID) {
530 if (bad_addr != NULL) *bad_addr = a;
531 return False;
532 }
533 /* Ok, a is safe to read. */
534 if (* ((UChar*)a) == 0) return True;
535 a++;
536 }
537}
538
539
540/*------------------------------------------------------------*/
541/*--- Memory event handlers ---*/
542/*------------------------------------------------------------*/
543
njn5c004e42002-11-18 11:04:50 +0000544static __inline__
njn72718642003-07-24 08:45:32 +0000545void ac_check_is_accessible ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000546 Char* s, Addr base, UInt size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000547{
548 Bool ok;
549 Addr bad_addr;
550
551 VGP_PUSHCC(VgpCheckMem);
552
njn5c004e42002-11-18 11:04:50 +0000553 ok = ac_check_accessible ( base, size, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000554 if (!ok) {
555 switch (part) {
556 case Vg_CoreSysCall:
njn72718642003-07-24 08:45:32 +0000557 MAC_(record_param_error) ( tid, bad_addr, isWrite, s );
njn25e49d8e72002-09-23 09:36:25 +0000558 break;
559
njn25e49d8e72002-09-23 09:36:25 +0000560 case Vg_CoreSignal:
njn5c004e42002-11-18 11:04:50 +0000561 sk_assert(isWrite); /* Should only happen with isWrite case */
562 /* fall through */
njn25e49d8e72002-09-23 09:36:25 +0000563 case Vg_CorePThread:
njn72718642003-07-24 08:45:32 +0000564 MAC_(record_core_mem_error)( tid, isWrite, s );
njn25e49d8e72002-09-23 09:36:25 +0000565 break;
566
567 /* If we're being asked to jump to a silly address, record an error
568 message before potentially crashing the entire system. */
569 case Vg_CoreTranslate:
njn5c004e42002-11-18 11:04:50 +0000570 sk_assert(!isWrite); /* Should only happen with !isWrite case */
njn72718642003-07-24 08:45:32 +0000571 MAC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000572 break;
573
574 default:
njn5c004e42002-11-18 11:04:50 +0000575 VG_(skin_panic)("ac_check_is_accessible: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +0000576 }
577 }
njn5c004e42002-11-18 11:04:50 +0000578
njn25e49d8e72002-09-23 09:36:25 +0000579 VGP_POPCC(VgpCheckMem);
580}
581
582static
njn72718642003-07-24 08:45:32 +0000583void ac_check_is_writable ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000584 Char* s, Addr base, UInt size )
585{
njn72718642003-07-24 08:45:32 +0000586 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/True );
njn5c004e42002-11-18 11:04:50 +0000587}
588
589static
njn72718642003-07-24 08:45:32 +0000590void ac_check_is_readable ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000591 Char* s, Addr base, UInt size )
592{
njn72718642003-07-24 08:45:32 +0000593 ac_check_is_accessible ( part, tid, s, base, size, /*isWrite*/False );
njn5c004e42002-11-18 11:04:50 +0000594}
595
596static
njn72718642003-07-24 08:45:32 +0000597void ac_check_is_readable_asciiz ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +0000598 Char* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +0000599{
600 Bool ok = True;
601 Addr bad_addr;
602 /* VG_(message)(Vg_DebugMsg,"check is readable asciiz: 0x%x",str); */
603
604 VGP_PUSHCC(VgpCheckMem);
605
njne427a662002-10-02 11:08:25 +0000606 sk_assert(part == Vg_CoreSysCall);
njn5c004e42002-11-18 11:04:50 +0000607 ok = ac_check_readable_asciiz ( (Addr)str, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +0000608 if (!ok) {
njn72718642003-07-24 08:45:32 +0000609 MAC_(record_param_error) ( tid, bad_addr, /*is_writable =*/False, s );
njn25e49d8e72002-09-23 09:36:25 +0000610 }
611
612 VGP_POPCC(VgpCheckMem);
613}
614
615static
njn5c004e42002-11-18 11:04:50 +0000616void ac_new_mem_startup( Addr a, UInt len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +0000617{
njn1f3a9092002-10-04 09:22:30 +0000618 /* Ignore the permissions, just make it readable. Seems to work... */
njn25e49d8e72002-09-23 09:36:25 +0000619 DEBUG("new_mem_startup(%p, %u, rr=%u, ww=%u, xx=%u)\n", a,len,rr,ww,xx);
njn5c004e42002-11-18 11:04:50 +0000620 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000621}
622
623static
njn5c004e42002-11-18 11:04:50 +0000624void ac_new_mem_heap ( Addr a, UInt len, Bool is_inited )
njn25e49d8e72002-09-23 09:36:25 +0000625{
njn5c004e42002-11-18 11:04:50 +0000626 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000627}
628
629static
njnda2e36d2003-09-30 13:33:24 +0000630void ac_set_perms (Addr a, UInt len, Bool rr, Bool ww, Bool xx)
njn25e49d8e72002-09-23 09:36:25 +0000631{
njn5c004e42002-11-18 11:04:50 +0000632 DEBUG("ac_set_perms(%p, %u, rr=%u ww=%u, xx=%u)\n",
sewardj40f8ebe2002-10-23 21:46:13 +0000633 a, len, rr, ww, xx);
njn25e49d8e72002-09-23 09:36:25 +0000634 if (rr || ww || xx) {
njn5c004e42002-11-18 11:04:50 +0000635 ac_make_accessible(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000636 } else {
njn5c004e42002-11-18 11:04:50 +0000637 ac_make_noaccess(a, len);
njn25e49d8e72002-09-23 09:36:25 +0000638 }
639}
640
641
642/*------------------------------------------------------------*/
643/*--- Functions called directly from generated code. ---*/
644/*------------------------------------------------------------*/
645
646static __inline__ UInt rotateRight16 ( UInt x )
647{
648 /* Amazingly, gcc turns this into a single rotate insn. */
649 return (x >> 16) | (x << 16);
650}
651
njn25e49d8e72002-09-23 09:36:25 +0000652static __inline__ UInt shiftRight16 ( UInt x )
653{
654 return x >> 16;
655}
656
657
658/* Read/write 1/2/4 sized V bytes, and emit an address error if
659 needed. */
660
njn5c004e42002-11-18 11:04:50 +0000661/* ac_helperc_ACCESS{1,2,4} handle the common case fast.
njn25e49d8e72002-09-23 09:36:25 +0000662 Under all other circumstances, it defers to the relevant _SLOWLY
663 function, which can handle all situations.
664*/
njnc2699f62003-09-05 23:29:33 +0000665static __inline__ void ac_helperc_ACCESS4 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000666{
667# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000668 return ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000669# else
670 UInt sec_no = rotateRight16(a) & 0x3FFFF;
njnda2e36d2003-09-30 13:33:24 +0000671 AcSecMap* sm = primary_map[sec_no];
njn25e49d8e72002-09-23 09:36:25 +0000672 UInt a_off = (a & 0xFFFF) >> 3;
673 UChar abits = sm->abits[a_off];
674 abits >>= (a & 4);
675 abits &= 15;
njn5c004e42002-11-18 11:04:50 +0000676 PROF_EVENT(66);
njn25e49d8e72002-09-23 09:36:25 +0000677 if (abits == VGM_NIBBLE_VALID) {
678 /* Handle common case quickly: a is suitably aligned, is mapped,
679 and is addressible. So just return. */
680 return;
681 } else {
682 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000683 ac_ACCESS4_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000684 }
685# endif
686}
687
njnc2699f62003-09-05 23:29:33 +0000688static __inline__ void ac_helperc_ACCESS2 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000689{
690# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000691 return ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000692# else
693 UInt sec_no = rotateRight16(a) & 0x1FFFF;
694 AcSecMap* sm = primary_map[sec_no];
695 UInt a_off = (a & 0xFFFF) >> 3;
njn5c004e42002-11-18 11:04:50 +0000696 PROF_EVENT(67);
njn25e49d8e72002-09-23 09:36:25 +0000697 if (sm->abits[a_off] == VGM_BYTE_VALID) {
698 /* Handle common case quickly. */
699 return;
700 } else {
701 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000702 ac_ACCESS2_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000703 }
704# endif
705}
706
njnc2699f62003-09-05 23:29:33 +0000707static __inline__ void ac_helperc_ACCESS1 ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000708{
709# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000710 return ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000711# else
712 UInt sec_no = shiftRight16(a);
713 AcSecMap* sm = primary_map[sec_no];
714 UInt a_off = (a & 0xFFFF) >> 3;
njn5c004e42002-11-18 11:04:50 +0000715 PROF_EVENT(68);
njn25e49d8e72002-09-23 09:36:25 +0000716 if (sm->abits[a_off] == VGM_BYTE_VALID) {
717 /* Handle common case quickly. */
718 return;
719 } else {
720 /* Slow but general case. */
njnc2699f62003-09-05 23:29:33 +0000721 ac_ACCESS1_SLOWLY(a, isWrite);
njn25e49d8e72002-09-23 09:36:25 +0000722 }
723# endif
724}
725
njnc2699f62003-09-05 23:29:33 +0000726__attribute__ ((regparm(1)))
727static void ac_helperc_LOAD4 ( Addr a )
728{
729 ac_helperc_ACCESS4 ( a, /*isWrite*/False );
730}
731__attribute__ ((regparm(1)))
732static void ac_helperc_STORE4 ( Addr a )
733{
734 ac_helperc_ACCESS4 ( a, /*isWrite*/True );
735}
736
737__attribute__ ((regparm(1)))
738static void ac_helperc_LOAD2 ( Addr a )
739{
740 ac_helperc_ACCESS2 ( a, /*isWrite*/False );
741}
742__attribute__ ((regparm(1)))
743static void ac_helperc_STORE2 ( Addr a )
744{
745 ac_helperc_ACCESS2 ( a, /*isWrite*/True );
746}
747
748__attribute__ ((regparm(1)))
749static void ac_helperc_LOAD1 ( Addr a )
750{
751 ac_helperc_ACCESS1 ( a, /*isWrite*/False );
752}
753__attribute__ ((regparm(1)))
754static void ac_helperc_STORE1 ( Addr a )
755{
756 ac_helperc_ACCESS1 ( a, /*isWrite*/True );
757}
758
njn25e49d8e72002-09-23 09:36:25 +0000759
760/*------------------------------------------------------------*/
761/*--- Fallback functions to handle cases that the above ---*/
njnc2699f62003-09-05 23:29:33 +0000762/*--- ac_helperc_ACCESS{1,2,4} can't manage. ---*/
njn25e49d8e72002-09-23 09:36:25 +0000763/*------------------------------------------------------------*/
764
njnc2699f62003-09-05 23:29:33 +0000765static void ac_ACCESS4_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000766{
767 Bool a0ok, a1ok, a2ok, a3ok;
768
njn5c004e42002-11-18 11:04:50 +0000769 PROF_EVENT(76);
njn25e49d8e72002-09-23 09:36:25 +0000770
771 /* First establish independently the addressibility of the 4 bytes
772 involved. */
773 a0ok = get_abit(a+0) == VGM_BIT_VALID;
774 a1ok = get_abit(a+1) == VGM_BIT_VALID;
775 a2ok = get_abit(a+2) == VGM_BIT_VALID;
776 a3ok = get_abit(a+3) == VGM_BIT_VALID;
777
778 /* Now distinguish 3 cases */
779
780 /* Case 1: the address is completely valid, so:
781 - no addressing error
782 */
783 if (a0ok && a1ok && a2ok && a3ok) {
784 return;
785 }
786
787 /* Case 2: the address is completely invalid.
788 - emit addressing error
789 */
790 /* VG_(printf)("%p (%d %d %d %d)\n", a, a0ok, a1ok, a2ok, a3ok); */
njn43c799e2003-04-08 00:08:52 +0000791 if (!MAC_(clo_partial_loads_ok)
njn25e49d8e72002-09-23 09:36:25 +0000792 || ((a & 3) != 0)
793 || (!a0ok && !a1ok && !a2ok && !a3ok)) {
njnc2699f62003-09-05 23:29:33 +0000794 MAC_(record_address_error)( VG_(get_current_tid)(), a, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000795 return;
796 }
797
798 /* Case 3: the address is partially valid.
799 - no addressing error
njn43c799e2003-04-08 00:08:52 +0000800 Case 3 is only allowed if MAC_(clo_partial_loads_ok) is True
njn25e49d8e72002-09-23 09:36:25 +0000801 (which is the default), and the address is 4-aligned.
802 If not, Case 2 will have applied.
803 */
njn43c799e2003-04-08 00:08:52 +0000804 sk_assert(MAC_(clo_partial_loads_ok));
njn25e49d8e72002-09-23 09:36:25 +0000805 {
806 return;
807 }
808}
809
njnc2699f62003-09-05 23:29:33 +0000810static void ac_ACCESS2_SLOWLY ( Addr a, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000811{
812 /* Check the address for validity. */
813 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000814 PROF_EVENT(77);
njn25e49d8e72002-09-23 09:36:25 +0000815
816 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
817 if (get_abit(a+1) != VGM_BIT_VALID) aerr = True;
818
819 /* If an address error has happened, report it. */
820 if (aerr) {
njnc2699f62003-09-05 23:29:33 +0000821 MAC_(record_address_error)( VG_(get_current_tid)(), a, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000822 }
823}
824
njnc2699f62003-09-05 23:29:33 +0000825static void ac_ACCESS1_SLOWLY ( Addr a, Bool isWrite)
njn25e49d8e72002-09-23 09:36:25 +0000826{
827 /* Check the address for validity. */
828 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000829 PROF_EVENT(78);
njn25e49d8e72002-09-23 09:36:25 +0000830
831 if (get_abit(a+0) != VGM_BIT_VALID) aerr = True;
832
833 /* If an address error has happened, report it. */
834 if (aerr) {
njnc2699f62003-09-05 23:29:33 +0000835 MAC_(record_address_error)( VG_(get_current_tid)(), a, 1, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000836 }
837}
838
839
840/* ---------------------------------------------------------------------
841 FPU load and store checks, called from generated code.
842 ------------------------------------------------------------------ */
843
sewardj56867352003-10-12 10:27:06 +0000844static
njnc2699f62003-09-05 23:29:33 +0000845void ac_fpu_ACCESS_check ( Addr addr, Int size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000846{
847 /* Ensure the read area is both addressible and valid (ie,
848 readable). If there's an address error, don't report a value
849 error too; but if there isn't an address error, check for a
850 value error.
851
852 Try to be reasonably fast on the common case; wimp out and defer
njn5c004e42002-11-18 11:04:50 +0000853 to ac_fpu_ACCESS_check_SLOWLY for everything else. */
njn25e49d8e72002-09-23 09:36:25 +0000854
855 AcSecMap* sm;
856 UInt sm_off, a_off;
857 Addr addr4;
858
njn5c004e42002-11-18 11:04:50 +0000859 PROF_EVENT(90);
njn25e49d8e72002-09-23 09:36:25 +0000860
861# ifdef VG_DEBUG_MEMORY
njnc2699f62003-09-05 23:29:33 +0000862 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000863# else
864
865 if (size == 4) {
866 if (!IS_ALIGNED4_ADDR(addr)) goto slow4;
njn5c004e42002-11-18 11:04:50 +0000867 PROF_EVENT(91);
njn25e49d8e72002-09-23 09:36:25 +0000868 /* Properly aligned. */
869 sm = primary_map[addr >> 16];
870 sm_off = addr & 0xFFFF;
871 a_off = sm_off >> 3;
872 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow4;
873 /* Properly aligned and addressible. */
874 return;
875 slow4:
njnc2699f62003-09-05 23:29:33 +0000876 ac_fpu_ACCESS_check_SLOWLY ( addr, 4, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000877 return;
878 }
879
880 if (size == 8) {
881 if (!IS_ALIGNED4_ADDR(addr)) goto slow8;
njn5c004e42002-11-18 11:04:50 +0000882 PROF_EVENT(92);
njn25e49d8e72002-09-23 09:36:25 +0000883 /* Properly aligned. Do it in two halves. */
884 addr4 = addr + 4;
885 /* First half. */
886 sm = primary_map[addr >> 16];
887 sm_off = addr & 0xFFFF;
888 a_off = sm_off >> 3;
889 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
890 /* First half properly aligned and addressible. */
891 /* Second half. */
892 sm = primary_map[addr4 >> 16];
893 sm_off = addr4 & 0xFFFF;
894 a_off = sm_off >> 3;
895 if (sm->abits[a_off] != VGM_BYTE_VALID) goto slow8;
896 /* Second half properly aligned and addressible. */
897 /* Both halves properly aligned and addressible. */
898 return;
899 slow8:
njnc2699f62003-09-05 23:29:33 +0000900 ac_fpu_ACCESS_check_SLOWLY ( addr, 8, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000901 return;
902 }
903
904 /* Can't be bothered to huff'n'puff to make these (allegedly) rare
905 cases go quickly. */
906 if (size == 2) {
njn5c004e42002-11-18 11:04:50 +0000907 PROF_EVENT(93);
njnc2699f62003-09-05 23:29:33 +0000908 ac_fpu_ACCESS_check_SLOWLY ( addr, 2, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000909 return;
910 }
911
sewardj1863abc2003-06-14 16:01:32 +0000912 if (size == 16 || size == 10 || size == 28 || size == 108) {
njn5c004e42002-11-18 11:04:50 +0000913 PROF_EVENT(94);
njnc2699f62003-09-05 23:29:33 +0000914 ac_fpu_ACCESS_check_SLOWLY ( addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000915 return;
916 }
917
918 VG_(printf)("size is %d\n", size);
njne427a662002-10-02 11:08:25 +0000919 VG_(skin_panic)("fpu_ACCESS_check: unhandled size");
njn25e49d8e72002-09-23 09:36:25 +0000920# endif
921}
922
njnc2699f62003-09-05 23:29:33 +0000923__attribute__ ((regparm(2)))
924static void ac_fpu_READ_check ( Addr addr, Int size )
925{
926 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/False );
927}
928
929__attribute__ ((regparm(2)))
930static void ac_fpu_WRITE_check ( Addr addr, Int size )
931{
932 ac_fpu_ACCESS_check ( addr, size, /*isWrite*/True );
933}
njn25e49d8e72002-09-23 09:36:25 +0000934
935/* ---------------------------------------------------------------------
936 Slow, general cases for FPU access checks.
937 ------------------------------------------------------------------ */
938
njnc2699f62003-09-05 23:29:33 +0000939void ac_fpu_ACCESS_check_SLOWLY ( Addr addr, Int size, Bool isWrite )
njn25e49d8e72002-09-23 09:36:25 +0000940{
941 Int i;
942 Bool aerr = False;
njn5c004e42002-11-18 11:04:50 +0000943 PROF_EVENT(100);
njn25e49d8e72002-09-23 09:36:25 +0000944 for (i = 0; i < size; i++) {
njn5c004e42002-11-18 11:04:50 +0000945 PROF_EVENT(101);
njn25e49d8e72002-09-23 09:36:25 +0000946 if (get_abit(addr+i) != VGM_BIT_VALID)
947 aerr = True;
948 }
949
950 if (aerr) {
njnc2699f62003-09-05 23:29:33 +0000951 MAC_(record_address_error)( VG_(get_current_tid)(), addr, size, isWrite );
njn25e49d8e72002-09-23 09:36:25 +0000952 }
953}
954
955
956/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +0000957/*--- Our instrumenter ---*/
958/*------------------------------------------------------------*/
959
njn25e49d8e72002-09-23 09:36:25 +0000960UCodeBlock* SK_(instrument)(UCodeBlock* cb_in, Addr orig_addr)
961{
962/* Use this rather than eg. -1 because it's a UInt. */
963#define INVALID_DATA_SIZE 999999
964
965 UCodeBlock* cb;
966 Int i;
967 UInstr* u_in;
968 Int t_addr, t_size;
njnc2699f62003-09-05 23:29:33 +0000969 Addr helper;
njn25e49d8e72002-09-23 09:36:25 +0000970
njn810086f2002-11-14 12:42:47 +0000971 cb = VG_(setup_UCodeBlock)(cb_in);
njn25e49d8e72002-09-23 09:36:25 +0000972
njn810086f2002-11-14 12:42:47 +0000973 for (i = 0; i < VG_(get_num_instrs)(cb_in); i++) {
njn25e49d8e72002-09-23 09:36:25 +0000974
975 t_addr = t_size = INVALID_TEMPREG;
njn810086f2002-11-14 12:42:47 +0000976 u_in = VG_(get_instr)(cb_in, i);
njn25e49d8e72002-09-23 09:36:25 +0000977
978 switch (u_in->opcode) {
sewardj7a5ebcf2002-11-13 22:42:13 +0000979 case NOP: case LOCK: case CALLM_E: case CALLM_S:
njn25e49d8e72002-09-23 09:36:25 +0000980 break;
981
sewardj77d30a22003-10-19 08:18:52 +0000982 /* For memory-ref instrs, copy the data_addr into a temporary
983 * to be passed to the helper at the end of the instruction.
njn25e49d8e72002-09-23 09:36:25 +0000984 */
njnc2699f62003-09-05 23:29:33 +0000985 case LOAD:
njn25e49d8e72002-09-23 09:36:25 +0000986 switch (u_in->size) {
njnc2699f62003-09-05 23:29:33 +0000987 case 4: helper = (Addr)ac_helperc_LOAD4; break;
988 case 2: helper = (Addr)ac_helperc_LOAD2; break;
989 case 1: helper = (Addr)ac_helperc_LOAD1; break;
sewardj77d30a22003-10-19 08:18:52 +0000990 default: VG_(skin_panic)
991 ("addrcheck::SK_(instrument):LOAD");
njn25e49d8e72002-09-23 09:36:25 +0000992 }
njnc2699f62003-09-05 23:29:33 +0000993 uInstr1(cb, CCALL, 0, TempReg, u_in->val1);
994 uCCall (cb, helper, 1, 1, False );
995 VG_(copy_UInstr)(cb, u_in);
996 break;
997
998 case STORE:
999 switch (u_in->size) {
1000 case 4: helper = (Addr)ac_helperc_STORE4; break;
1001 case 2: helper = (Addr)ac_helperc_STORE2; break;
1002 case 1: helper = (Addr)ac_helperc_STORE1; break;
sewardj77d30a22003-10-19 08:18:52 +00001003 default: VG_(skin_panic)
1004 ("addrcheck::SK_(instrument):STORE");
njnc2699f62003-09-05 23:29:33 +00001005 }
1006 uInstr1(cb, CCALL, 0, TempReg, u_in->val2);
1007 uCCall (cb, helper, 1, 1, False );
njn4ba5a792002-09-30 10:23:54 +00001008 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001009 break;
1010
sewardje3891fa2003-06-15 03:13:48 +00001011 case SSE3ag_MemRd_RegWr:
1012 sk_assert(u_in->size == 4 || u_in->size == 8);
njnc2699f62003-09-05 23:29:33 +00001013 helper = (Addr)ac_fpu_READ_check;
sewardje3891fa2003-06-15 03:13:48 +00001014 goto do_Access_ARG1;
1015 do_Access_ARG1:
1016 sk_assert(u_in->tag1 == TempReg);
1017 t_addr = u_in->val1;
1018 t_size = newTemp(cb);
1019 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
1020 uLiteral(cb, u_in->size);
1021 uInstr2(cb, CCALL, 0, TempReg, t_addr, TempReg, t_size);
njnc2699f62003-09-05 23:29:33 +00001022 uCCall(cb, helper, 2, 2, False );
sewardje3891fa2003-06-15 03:13:48 +00001023 VG_(copy_UInstr)(cb, u_in);
1024 break;
1025
sewardj3d7c9c82003-03-26 21:08:13 +00001026 case MMX2_MemRd:
njnc2699f62003-09-05 23:29:33 +00001027 sk_assert(u_in->size == 4 || u_in->size == 8);
1028 helper = (Addr)ac_fpu_READ_check;
1029 goto do_Access_ARG2;
sewardj3d7c9c82003-03-26 21:08:13 +00001030 case MMX2_MemWr:
sewardjd7971012003-04-04 00:21:58 +00001031 sk_assert(u_in->size == 4 || u_in->size == 8);
njnc2699f62003-09-05 23:29:33 +00001032 helper = (Addr)ac_fpu_WRITE_check;
sewardj1863abc2003-06-14 16:01:32 +00001033 goto do_Access_ARG2;
1034 case FPU_R:
njnc2699f62003-09-05 23:29:33 +00001035 helper = (Addr)ac_fpu_READ_check;
1036 goto do_Access_ARG2;
sewardj1863abc2003-06-14 16:01:32 +00001037 case FPU_W:
njnc2699f62003-09-05 23:29:33 +00001038 helper = (Addr)ac_fpu_WRITE_check;
sewardj1863abc2003-06-14 16:01:32 +00001039 goto do_Access_ARG2;
1040 do_Access_ARG2:
1041 sk_assert(u_in->tag2 == TempReg);
sewardj3d7c9c82003-03-26 21:08:13 +00001042 t_addr = u_in->val2;
1043 t_size = newTemp(cb);
1044 uInstr2(cb, MOV, 4, Literal, 0, TempReg, t_size);
sewardjd7971012003-04-04 00:21:58 +00001045 uLiteral(cb, u_in->size);
sewardj3d7c9c82003-03-26 21:08:13 +00001046 uInstr2(cb, CCALL, 0, TempReg, t_addr, TempReg, t_size);
njnc2699f62003-09-05 23:29:33 +00001047 uCCall(cb, helper, 2, 2, False );
sewardj3d7c9c82003-03-26 21:08:13 +00001048 VG_(copy_UInstr)(cb, u_in);
1049 break;
1050
sewardj77d30a22003-10-19 08:18:52 +00001051 case SSE3a_MemRd:
sewardj1863abc2003-06-14 16:01:32 +00001052 case SSE2a_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:
sewardj77d30a22003-10-19 08:18:52 +00001060 sk_assert(u_in->size == 4
1061 || u_in->size == 8 || u_in->size == 16);
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
sewardj77d30a22003-10-19 08:18:52 +00001072 case SSE2a1_MemRd:
1073 case SSE3a1_MemRd:
sewardj1863abc2003-06-14 16:01:32 +00001074 VG_(pp_UInstr)(0,u_in);
1075 VG_(skin_panic)("AddrCheck: unhandled SSE uinstr");
1076 break;
1077
sewardj095c3bc2003-06-15 23:26:04 +00001078 case SSE3e1_RegRd:
sewardjabf8bf82003-06-15 22:28:05 +00001079 case SSE3e_RegWr:
sewardje3891fa2003-06-15 03:13:48 +00001080 case SSE3g1_RegWr:
sewardj6bc40552003-06-15 01:40:58 +00001081 case SSE5:
sewardj1863abc2003-06-14 16:01:32 +00001082 case SSE3g_RegWr:
sewardj4fbe6e92003-06-15 21:54:34 +00001083 case SSE3e_RegRd:
sewardj1863abc2003-06-14 16:01:32 +00001084 case SSE4:
sewardj77d30a22003-10-19 08:18:52 +00001085 case SSE3:
njn25e49d8e72002-09-23 09:36:25 +00001086 default:
njn4ba5a792002-09-30 10:23:54 +00001087 VG_(copy_UInstr)(cb, u_in);
njn25e49d8e72002-09-23 09:36:25 +00001088 break;
1089 }
1090 }
1091
njn4ba5a792002-09-30 10:23:54 +00001092 VG_(free_UCodeBlock)(cb_in);
njn25e49d8e72002-09-23 09:36:25 +00001093 return cb;
1094}
1095
1096
njn25e49d8e72002-09-23 09:36:25 +00001097/*------------------------------------------------------------*/
1098/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
1099/*------------------------------------------------------------*/
1100
sewardja4495682002-10-21 07:29:59 +00001101/* For the memory leak detector, say whether an entire 64k chunk of
1102 address space is possibly in use, or not. If in doubt return
1103 True.
njn25e49d8e72002-09-23 09:36:25 +00001104*/
sewardja4495682002-10-21 07:29:59 +00001105static
1106Bool ac_is_valid_64k_chunk ( UInt chunk_number )
njn25e49d8e72002-09-23 09:36:25 +00001107{
sewardja4495682002-10-21 07:29:59 +00001108 sk_assert(chunk_number >= 0 && chunk_number < 65536);
1109 if (IS_DISTINGUISHED_SM(primary_map[chunk_number])) {
1110 /* Definitely not in use. */
1111 return False;
1112 } else {
1113 return True;
njn25e49d8e72002-09-23 09:36:25 +00001114 }
1115}
1116
1117
sewardja4495682002-10-21 07:29:59 +00001118/* For the memory leak detector, say whether or not a given word
1119 address is to be regarded as valid. */
1120static
1121Bool ac_is_valid_address ( Addr a )
1122{
1123 UChar abits;
1124 sk_assert(IS_ALIGNED4_ADDR(a));
1125 abits = get_abits4_ALIGNED(a);
1126 if (abits == VGM_NIBBLE_VALID) {
1127 return True;
1128 } else {
1129 return False;
1130 }
1131}
1132
1133
1134/* Leak detector for this skin. We don't actually do anything, merely
1135 run the generic leak detector with suitable parameters for this
1136 skin. */
njn5c004e42002-11-18 11:04:50 +00001137static void ac_detect_memory_leaks ( void )
njn25e49d8e72002-09-23 09:36:25 +00001138{
njn43c799e2003-04-08 00:08:52 +00001139 MAC_(do_detect_memory_leaks) ( ac_is_valid_64k_chunk, ac_is_valid_address );
njn25e49d8e72002-09-23 09:36:25 +00001140}
1141
1142
1143/* ---------------------------------------------------------------------
1144 Sanity check machinery (permanently engaged).
1145 ------------------------------------------------------------------ */
1146
1147/* Check that nobody has spuriously claimed that the first or last 16
1148 pages (64 KB) of address space have become accessible. Failure of
1149 the following do not per se indicate an internal consistency
1150 problem, but they are so likely to that we really want to know
1151 about it if so. */
1152
1153Bool SK_(cheap_sanity_check) ( void )
1154{
sewardjd5815ec2003-04-06 12:23:27 +00001155 if (IS_DISTINGUISHED_SM(primary_map[0])
1156 /* kludge: kernel drops a page up at top of address range for
1157 magic "optimized syscalls", so we can no longer check the
1158 highest page */
1159 /* && IS_DISTINGUISHED_SM(primary_map[65535]) */
1160 )
njn25e49d8e72002-09-23 09:36:25 +00001161 return True;
1162 else
1163 return False;
1164}
1165
1166Bool SK_(expensive_sanity_check) ( void )
1167{
1168 Int i;
1169
1170 /* Make sure nobody changed the distinguished secondary. */
1171 for (i = 0; i < 8192; i++)
1172 if (distinguished_secondary_map.abits[i] != VGM_BYTE_INVALID)
1173 return False;
1174
1175 /* Make sure that the upper 3/4 of the primary map hasn't
1176 been messed with. */
1177 for (i = 65536; i < 262144; i++)
1178 if (primary_map[i] != & distinguished_secondary_map)
1179 return False;
1180
1181 return True;
1182}
1183
njn47363ab2003-04-21 13:24:40 +00001184/*------------------------------------------------------------*/
1185/*--- Client requests ---*/
1186/*------------------------------------------------------------*/
1187
njn72718642003-07-24 08:45:32 +00001188Bool SK_(handle_client_request) ( ThreadId tid, UInt* arg_block, UInt *ret )
sewardjd8033d92002-12-08 22:16:58 +00001189{
sewardjbf310d92002-12-28 13:09:57 +00001190#define IGNORE(what) \
1191 do { \
1192 if (moans-- > 0) { \
1193 VG_(message)(Vg_UserMsg, \
1194 "Warning: Addrcheck: ignoring `%s' request.", what); \
1195 VG_(message)(Vg_UserMsg, \
nethercote137bc552003-11-14 17:47:54 +00001196 " To honour this request, rerun with --tool=memcheck."); \
sewardjbf310d92002-12-28 13:09:57 +00001197 } \
1198 } while (0)
1199
sewardjd8033d92002-12-08 22:16:58 +00001200 UInt* arg = arg_block;
sewardjbf310d92002-12-28 13:09:57 +00001201 static Int moans = 3;
sewardjd8033d92002-12-08 22:16:58 +00001202
1203 /* Overload memcheck client reqs */
njnd7994182003-10-02 13:44:04 +00001204 if (!VG_IS_SKIN_USERREQ('M','C',arg[0])
1205 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
1206 && VG_USERREQ__FREELIKE_BLOCK != arg[0])
sewardjd8033d92002-12-08 22:16:58 +00001207 return False;
1208
1209 switch (arg[0]) {
1210 case VG_USERREQ__DO_LEAK_CHECK:
1211 ac_detect_memory_leaks();
1212 *ret = 0; /* return value is meaningless */
1213 break;
1214
sewardjbf310d92002-12-28 13:09:57 +00001215 /* Ignore these */
sewardjd8033d92002-12-08 22:16:58 +00001216 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
sewardjbf310d92002-12-28 13:09:57 +00001217 IGNORE("VALGRIND_CHECK_WRITABLE");
1218 return False;
sewardjd8033d92002-12-08 22:16:58 +00001219 case VG_USERREQ__CHECK_READABLE: /* check readable */
sewardjbf310d92002-12-28 13:09:57 +00001220 IGNORE("VALGRIND_CHECK_READABLE");
1221 return False;
sewardjd8033d92002-12-08 22:16:58 +00001222 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
sewardjbf310d92002-12-28 13:09:57 +00001223 IGNORE("VALGRIND_MAKE_NOACCESS");
1224 return False;
sewardjd8033d92002-12-08 22:16:58 +00001225 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
sewardjbf310d92002-12-28 13:09:57 +00001226 IGNORE("VALGRIND_MAKE_WRITABLE");
1227 return False;
sewardjd8033d92002-12-08 22:16:58 +00001228 case VG_USERREQ__MAKE_READABLE: /* make readable */
sewardjbf310d92002-12-28 13:09:57 +00001229 IGNORE("VALGRIND_MAKE_READABLE");
1230 return False;
sewardjd8033d92002-12-08 22:16:58 +00001231 case VG_USERREQ__DISCARD: /* discard */
sewardjbf310d92002-12-28 13:09:57 +00001232 IGNORE("VALGRIND_CHECK_DISCARD");
1233 return False;
sewardjd8033d92002-12-08 22:16:58 +00001234
1235 default:
njn72718642003-07-24 08:45:32 +00001236 if (MAC_(handle_common_client_requests)(tid, arg_block, ret )) {
njn47363ab2003-04-21 13:24:40 +00001237 return True;
1238 } else {
1239 VG_(message)(Vg_UserMsg,
1240 "Warning: unknown addrcheck client request code %d",
1241 arg[0]);
1242 return False;
1243 }
sewardjd8033d92002-12-08 22:16:58 +00001244 }
1245 return True;
sewardjbf310d92002-12-28 13:09:57 +00001246
1247#undef IGNORE
sewardjd8033d92002-12-08 22:16:58 +00001248}
1249
njn25e49d8e72002-09-23 09:36:25 +00001250/*------------------------------------------------------------*/
1251/*--- Setup ---*/
1252/*------------------------------------------------------------*/
1253
njn25e49d8e72002-09-23 09:36:25 +00001254Bool SK_(process_cmd_line_option)(Char* arg)
1255{
njn43c799e2003-04-08 00:08:52 +00001256 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00001257}
1258
njn3e884182003-04-15 13:03:23 +00001259void SK_(print_usage)(void)
njn25e49d8e72002-09-23 09:36:25 +00001260{
njn3e884182003-04-15 13:03:23 +00001261 MAC_(print_common_usage)();
1262}
1263
1264void SK_(print_debug_usage)(void)
1265{
1266 MAC_(print_common_debug_usage)();
njn25e49d8e72002-09-23 09:36:25 +00001267}
1268
1269
1270/*------------------------------------------------------------*/
1271/*--- Setup ---*/
1272/*------------------------------------------------------------*/
1273
njn810086f2002-11-14 12:42:47 +00001274void SK_(pre_clo_init)(void)
njn25e49d8e72002-09-23 09:36:25 +00001275{
njn810086f2002-11-14 12:42:47 +00001276 VG_(details_name) ("Addrcheck");
1277 VG_(details_version) (NULL);
1278 VG_(details_description) ("a fine-grained address checker");
1279 VG_(details_copyright_author)(
njn0e1b5142003-04-15 14:58:06 +00001280 "Copyright (C) 2002-2003, and GNU GPL'd, by Julian Seward.");
nethercote421281e2003-11-20 16:20:55 +00001281 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardj78210aa2002-12-01 02:55:46 +00001282 VG_(details_avg_translation_sizeB) ( 135 );
njn25e49d8e72002-09-23 09:36:25 +00001283
njn810086f2002-11-14 12:42:47 +00001284 VG_(needs_core_errors) ();
1285 VG_(needs_skin_errors) ();
1286 VG_(needs_libc_freeres) ();
njn810086f2002-11-14 12:42:47 +00001287 VG_(needs_command_line_options)();
1288 VG_(needs_client_requests) ();
1289 VG_(needs_syscall_wrapper) ();
njn810086f2002-11-14 12:42:47 +00001290 VG_(needs_sanity_checks) ();
njn25e49d8e72002-09-23 09:36:25 +00001291
njn3e884182003-04-15 13:03:23 +00001292 MAC_( new_mem_heap) = & ac_new_mem_heap;
1293 MAC_( ban_mem_heap) = & ac_make_noaccess;
1294 MAC_(copy_mem_heap) = & ac_copy_address_range_state;
1295 MAC_( die_mem_heap) = & ac_make_noaccess;
sewardjecf8e102003-07-12 12:11:39 +00001296 MAC_(check_noaccess) = & ac_check_noaccess;
njn3e884182003-04-15 13:03:23 +00001297
njn5c004e42002-11-18 11:04:50 +00001298 VG_(track_new_mem_startup) ( & ac_new_mem_startup );
njn5c004e42002-11-18 11:04:50 +00001299 VG_(track_new_mem_stack_signal) ( & ac_make_accessible );
1300 VG_(track_new_mem_brk) ( & ac_make_accessible );
1301 VG_(track_new_mem_mmap) ( & ac_set_perms );
njn25e49d8e72002-09-23 09:36:25 +00001302
njn3e884182003-04-15 13:03:23 +00001303 VG_(track_copy_mem_remap) ( & ac_copy_address_range_state );
1304 VG_(track_change_mem_mprotect) ( & ac_set_perms );
1305
1306 VG_(track_die_mem_stack_signal) ( & ac_make_noaccess );
1307 VG_(track_die_mem_brk) ( & ac_make_noaccess );
1308 VG_(track_die_mem_munmap) ( & ac_make_noaccess );
1309
njn43c799e2003-04-08 00:08:52 +00001310 VG_(track_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
1311 VG_(track_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
1312 VG_(track_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
1313 VG_(track_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
1314 VG_(track_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
1315 VG_(track_new_mem_stack) ( & MAC_(new_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001316
njn43c799e2003-04-08 00:08:52 +00001317 VG_(track_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
1318 VG_(track_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
1319 VG_(track_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
1320 VG_(track_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
1321 VG_(track_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
1322 VG_(track_die_mem_stack) ( & MAC_(die_mem_stack) );
njn9b007f62003-04-07 14:40:25 +00001323
njn3e884182003-04-15 13:03:23 +00001324 VG_(track_ban_mem_stack) ( & ac_make_noaccess );
njn25e49d8e72002-09-23 09:36:25 +00001325
njn5c004e42002-11-18 11:04:50 +00001326 VG_(track_pre_mem_read) ( & ac_check_is_readable );
1327 VG_(track_pre_mem_read_asciiz) ( & ac_check_is_readable_asciiz );
1328 VG_(track_pre_mem_write) ( & ac_check_is_writable );
1329 VG_(track_post_mem_write) ( & ac_make_accessible );
njn25e49d8e72002-09-23 09:36:25 +00001330
njnc2699f62003-09-05 23:29:33 +00001331 VG_(register_compact_helper)((Addr) & ac_helperc_LOAD4);
1332 VG_(register_compact_helper)((Addr) & ac_helperc_LOAD2);
1333 VG_(register_compact_helper)((Addr) & ac_helperc_LOAD1);
1334 VG_(register_compact_helper)((Addr) & ac_helperc_STORE4);
1335 VG_(register_compact_helper)((Addr) & ac_helperc_STORE2);
1336 VG_(register_compact_helper)((Addr) & ac_helperc_STORE1);
1337 VG_(register_noncompact_helper)((Addr) & ac_fpu_READ_check);
1338 VG_(register_noncompact_helper)((Addr) & ac_fpu_WRITE_check);
njn25e49d8e72002-09-23 09:36:25 +00001339
1340 VGP_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
1341 VGP_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
njn9b007f62003-04-07 14:40:25 +00001342 VGP_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
njnd04b7c62002-10-03 14:05:52 +00001343
1344 init_shadow_memory();
njn3e884182003-04-15 13:03:23 +00001345 MAC_(common_pre_clo_init)();
njn5c004e42002-11-18 11:04:50 +00001346}
1347
1348void SK_(post_clo_init) ( void )
1349{
1350}
1351
njn7d9f94d2003-04-22 21:41:40 +00001352void SK_(fini) ( Int exitcode )
njn5c004e42002-11-18 11:04:50 +00001353{
njn3e884182003-04-15 13:03:23 +00001354 MAC_(common_fini)( ac_detect_memory_leaks );
njn25e49d8e72002-09-23 09:36:25 +00001355}
1356
1357/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00001358/*--- end ac_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00001359/*--------------------------------------------------------------------*/