blob: bfc79e3c6072ff07e812aa8d6acab9b9819a2080 [file] [log] [blame]
njnc9539842002-10-02 13:26:35 +00001
njn25e49d8e72002-09-23 09:36:25 +00002/*--------------------------------------------------------------------*/
njnc9539842002-10-02 13:26:35 +00003/*--- MemCheck: Maintain bitmaps of memory, tracking the ---*/
4/*--- accessibility (A) and validity (V) status of each byte. ---*/
njn25cac76cb2002-09-23 11:21:57 +00005/*--- mc_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00006/*--------------------------------------------------------------------*/
7
8/*
nethercote137bc552003-11-14 17:47:54 +00009 This file is part of MemCheck, a heavyweight Valgrind tool for
njnc9539842002-10-02 13:26:35 +000010 detecting memory errors.
njn25e49d8e72002-09-23 09:36:25 +000011
njn53612422005-03-12 16:22:54 +000012 Copyright (C) 2000-2005 Julian Seward
njn25e49d8e72002-09-23 09:36:25 +000013 jseward@acm.org
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file COPYING.
31*/
32
sewardjc859fbf2005-04-22 21:10:28 +000033/* TODO 22 Apr 05
sewardj45d94cc2005-04-20 14:44:11 +000034
sewardjc859fbf2005-04-22 21:10:28 +000035 test whether it would be faster, for LOADV4, to check
36 only for 8-byte validity on the fast path
sewardj45d94cc2005-04-20 14:44:11 +000037*/
38
njnc7561b92005-06-19 01:24:32 +000039#include "pub_tool_basics.h"
njn4802b382005-06-11 04:58:29 +000040#include "pub_tool_aspacemgr.h"
njnc7561b92005-06-19 01:24:32 +000041#include "pub_tool_errormgr.h" // For mac_shared.h
42#include "pub_tool_execontext.h" // For mac_shared.h
43#include "pub_tool_hashtable.h" // For mac_shared.h
njn97405b22005-06-02 03:39:33 +000044#include "pub_tool_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000045#include "pub_tool_libcassert.h"
njn36a20fa2005-06-03 03:08:39 +000046#include "pub_tool_libcprint.h"
njnf536bbb2005-06-13 04:21:38 +000047#include "pub_tool_machine.h"
njnc7561b92005-06-19 01:24:32 +000048#include "pub_tool_mallocfree.h"
49#include "pub_tool_options.h"
50#include "pub_tool_profile.h" // For mac_shared.h
51#include "pub_tool_replacemalloc.h"
52#include "pub_tool_tooliface.h"
53#include "pub_tool_threadstate.h"
54
55#include "mc_include.h"
56#include "memcheck.h" /* for client requests */
njn25e49d8e72002-09-23 09:36:25 +000057
sewardj45d94cc2005-04-20 14:44:11 +000058
sewardjc1a2cda2005-04-21 17:34:00 +000059#define EXPECTED_TAKEN(cond) __builtin_expect((cond),1)
60#define EXPECTED_NOT_TAKEN(cond) __builtin_expect((cond),0)
61
62/* Define to debug the mem audit system. Set to:
63 0 no debugging, fast cases are used
64 1 some sanity checking, fast cases are used
65 2 max sanity checking, only slow cases are used
66*/
sewardj23eb2fd2005-04-22 16:29:19 +000067#define VG_DEBUG_MEMORY 0
sewardjc1a2cda2005-04-21 17:34:00 +000068
njn25e49d8e72002-09-23 09:36:25 +000069#define DEBUG(fmt, args...) //VG_(printf)(fmt, ## args)
70
njn25e49d8e72002-09-23 09:36:25 +000071
njn25e49d8e72002-09-23 09:36:25 +000072/*------------------------------------------------------------*/
sewardj45d94cc2005-04-20 14:44:11 +000073/*--- Basic A/V bitmap representation. ---*/
njn25e49d8e72002-09-23 09:36:25 +000074/*------------------------------------------------------------*/
75
sewardjc859fbf2005-04-22 21:10:28 +000076/* TODO: fix this comment */
77//zz /* All reads and writes are checked against a memory map, which
78//zz records the state of all memory in the process. The memory map is
79//zz organised like this:
80//zz
81//zz The top 16 bits of an address are used to index into a top-level
82//zz map table, containing 65536 entries. Each entry is a pointer to a
83//zz second-level map, which records the accesibililty and validity
84//zz permissions for the 65536 bytes indexed by the lower 16 bits of the
85//zz address. Each byte is represented by nine bits, one indicating
86//zz accessibility, the other eight validity. So each second-level map
87//zz contains 73728 bytes. This two-level arrangement conveniently
88//zz divides the 4G address space into 64k lumps, each size 64k bytes.
89//zz
90//zz All entries in the primary (top-level) map must point to a valid
91//zz secondary (second-level) map. Since most of the 4G of address
92//zz space will not be in use -- ie, not mapped at all -- there is a
njn02bc4b82005-05-15 17:28:26 +000093//zz distinguished secondary map, which indicates 'not addressible and
sewardjc859fbf2005-04-22 21:10:28 +000094//zz not valid' writeable for all bytes. Entries in the primary map for
95//zz which the entire 64k is not in use at all point at this
96//zz distinguished map.
97//zz
98//zz There are actually 4 distinguished secondaries. These are used to
99//zz represent a memory range which is either not addressable (validity
100//zz doesn't matter), addressable+not valid, addressable+valid.
101//zz
102//zz [...] lots of stuff deleted due to out of date-ness
103//zz
104//zz As a final optimisation, the alignment and address checks for
105//zz 4-byte loads and stores are combined in a neat way. The primary
106//zz map is extended to have 262144 entries (2^18), rather than 2^16.
107//zz The top 3/4 of these entries are permanently set to the
108//zz distinguished secondary map. For a 4-byte load/store, the
109//zz top-level map is indexed not with (addr >> 16) but instead f(addr),
110//zz where
111//zz
112//zz f( XXXX XXXX XXXX XXXX ____ ____ ____ __YZ )
113//zz = ____ ____ ____ __YZ XXXX XXXX XXXX XXXX or
114//zz = ____ ____ ____ __ZY XXXX XXXX XXXX XXXX
115//zz
116//zz ie the lowest two bits are placed above the 16 high address bits.
117//zz If either of these two bits are nonzero, the address is misaligned;
118//zz this will select a secondary map from the upper 3/4 of the primary
119//zz map. Because this is always the distinguished secondary map, a
120//zz (bogus) address check failure will result. The failure handling
121//zz code can then figure out whether this is a genuine addr check
122//zz failure or whether it is a possibly-legitimate access at a
123//zz misaligned address.
124//zz */
125
sewardj45d94cc2005-04-20 14:44:11 +0000126/* --------------- Basic configuration --------------- */
sewardj95448072004-11-22 20:19:51 +0000127
sewardj23eb2fd2005-04-22 16:29:19 +0000128/* Only change this. N_PRIMARY_MAP *must* be a power of 2. */
sewardj21f7ff42005-04-28 10:32:02 +0000129
sewardje4ccc012005-05-02 12:53:38 +0000130#if VG_WORDSIZE == 4
sewardj21f7ff42005-04-28 10:32:02 +0000131
132/* cover the entire address space */
133# define N_PRIMARY_BITS 16
134
135#else
136
sewardj34483bc2005-09-28 11:50:20 +0000137/* Just handle the first 32G fast and the rest via auxiliary
sewardj21f7ff42005-04-28 10:32:02 +0000138 primaries. */
sewardj34483bc2005-09-28 11:50:20 +0000139# define N_PRIMARY_BITS 19
sewardj21f7ff42005-04-28 10:32:02 +0000140
141#endif
142
sewardj45d94cc2005-04-20 14:44:11 +0000143
sewardjc1a2cda2005-04-21 17:34:00 +0000144/* Do not change this. */
sewardje4ccc012005-05-02 12:53:38 +0000145#define N_PRIMARY_MAP ( ((UWord)1) << N_PRIMARY_BITS)
sewardjc1a2cda2005-04-21 17:34:00 +0000146
147/* Do not change this. */
sewardj23eb2fd2005-04-22 16:29:19 +0000148#define MAX_PRIMARY_ADDRESS (Addr)((((Addr)65536) * N_PRIMARY_MAP)-1)
149
150
151/* --------------- Stats maps --------------- */
152
153static Int n_secmaps_issued = 0;
154static ULong n_auxmap_searches = 0;
155static ULong n_auxmap_cmps = 0;
156static Int n_sanity_cheap = 0;
157static Int n_sanity_expensive = 0;
sewardj45d94cc2005-04-20 14:44:11 +0000158
159
160/* --------------- Secondary maps --------------- */
njn25e49d8e72002-09-23 09:36:25 +0000161
162typedef
163 struct {
sewardj45d94cc2005-04-20 14:44:11 +0000164 UChar abits[8192];
165 UChar vbyte[65536];
njn25e49d8e72002-09-23 09:36:25 +0000166 }
167 SecMap;
168
sewardj45d94cc2005-04-20 14:44:11 +0000169/* 3 distinguished secondary maps, one for no-access, one for
170 accessible but undefined, and one for accessible and defined.
171 Distinguished secondaries may never be modified.
172*/
173#define SM_DIST_NOACCESS 0
174#define SM_DIST_ACCESS_UNDEFINED 1
175#define SM_DIST_ACCESS_DEFINED 2
njnb8dca862005-03-14 02:42:44 +0000176
sewardj45d94cc2005-04-20 14:44:11 +0000177static SecMap sm_distinguished[3];
njnb8dca862005-03-14 02:42:44 +0000178
sewardj45d94cc2005-04-20 14:44:11 +0000179static inline Bool is_distinguished_sm ( SecMap* sm ) {
180 return sm >= &sm_distinguished[0] && sm <= &sm_distinguished[2];
181}
njnb8dca862005-03-14 02:42:44 +0000182
sewardj45d94cc2005-04-20 14:44:11 +0000183/* dist_sm points to one of our three distinguished secondaries. Make
184 a copy of it so that we can write to it.
185*/
186static SecMap* copy_for_writing ( SecMap* dist_sm )
187{
188 SecMap* new_sm;
189 tl_assert(dist_sm == &sm_distinguished[0]
190 || dist_sm == &sm_distinguished[1]
191 || dist_sm == &sm_distinguished[2]);
njnb8dca862005-03-14 02:42:44 +0000192
sewardj45f4e7c2005-09-27 19:20:21 +0000193 new_sm = VG_(am_shadow_alloc)(sizeof(SecMap));
194 if (new_sm == NULL)
195 VG_(out_of_memory_NORETURN)( "memcheck:allocate new SecMap",
196 sizeof(SecMap) );
sewardj45d94cc2005-04-20 14:44:11 +0000197 VG_(memcpy)(new_sm, dist_sm, sizeof(SecMap));
sewardj23eb2fd2005-04-22 16:29:19 +0000198 n_secmaps_issued++;
sewardj45d94cc2005-04-20 14:44:11 +0000199 return new_sm;
200}
njnb8dca862005-03-14 02:42:44 +0000201
sewardj45d94cc2005-04-20 14:44:11 +0000202
203/* --------------- Primary maps --------------- */
204
205/* The main primary map. This covers some initial part of the address
sewardj23eb2fd2005-04-22 16:29:19 +0000206 space, addresses 0 .. (N_PRIMARY_MAP << 16)-1. The rest of it is
sewardj45d94cc2005-04-20 14:44:11 +0000207 handled using the auxiliary primary map.
208*/
sewardj23eb2fd2005-04-22 16:29:19 +0000209static SecMap* primary_map[N_PRIMARY_MAP];
sewardj45d94cc2005-04-20 14:44:11 +0000210
211
212/* An entry in the auxiliary primary map. base must be a 64k-aligned
213 value, and sm points at the relevant secondary map. As with the
214 main primary map, the secondary may be either a real secondary, or
215 one of the three distinguished secondaries.
216*/
217typedef
218 struct {
sewardj23eb2fd2005-04-22 16:29:19 +0000219 Addr base;
sewardj45d94cc2005-04-20 14:44:11 +0000220 SecMap* sm;
221 }
222 AuxMapEnt;
223
224/* An expanding array of AuxMapEnts. */
sewardjaba741d2005-06-09 13:56:07 +0000225#define N_AUXMAPS 20000 /* HACK */
sewardj45d94cc2005-04-20 14:44:11 +0000226static AuxMapEnt hacky_auxmaps[N_AUXMAPS];
227static Int auxmap_size = N_AUXMAPS;
228static Int auxmap_used = 0;
229static AuxMapEnt* auxmap = &hacky_auxmaps[0];
230
sewardj45d94cc2005-04-20 14:44:11 +0000231
232/* Find an entry in the auxiliary map. If an entry is found, move it
233 one step closer to the front of the array, then return its address.
sewardj05fe85e2005-04-27 22:46:36 +0000234 If an entry is not found, return NULL. Note carefully that
sewardj45d94cc2005-04-20 14:44:11 +0000235 because a each call potentially rearranges the entries, each call
236 to this function invalidates ALL AuxMapEnt*s previously obtained by
237 calling this fn.
238*/
sewardj05fe85e2005-04-27 22:46:36 +0000239static AuxMapEnt* maybe_find_in_auxmap ( Addr a )
sewardj45d94cc2005-04-20 14:44:11 +0000240{
241 UWord i;
242 tl_assert(a > MAX_PRIMARY_ADDRESS);
243
244 a &= ~(Addr)0xFFFF;
245
246 /* Search .. */
247 n_auxmap_searches++;
248 for (i = 0; i < auxmap_used; i++) {
249 if (auxmap[i].base == a)
250 break;
251 }
252 n_auxmap_cmps += (ULong)(i+1);
253
254 if (i < auxmap_used) {
255 /* Found it. Nudge it a bit closer to the front. */
256 if (i > 0) {
257 AuxMapEnt tmp = auxmap[i-1];
258 auxmap[i-1] = auxmap[i];
259 auxmap[i] = tmp;
260 i--;
261 }
262 return &auxmap[i];
263 }
264
sewardj05fe85e2005-04-27 22:46:36 +0000265 return NULL;
266}
267
268
269/* Find an entry in the auxiliary map. If an entry is found, move it
270 one step closer to the front of the array, then return its address.
271 If an entry is not found, allocate one. Note carefully that
272 because a each call potentially rearranges the entries, each call
273 to this function invalidates ALL AuxMapEnt*s previously obtained by
274 calling this fn.
275*/
276static AuxMapEnt* find_or_alloc_in_auxmap ( Addr a )
277{
278 AuxMapEnt* am = maybe_find_in_auxmap(a);
279 if (am)
280 return am;
281
sewardj45d94cc2005-04-20 14:44:11 +0000282 /* We didn't find it. Hmm. This is a new piece of address space.
283 We'll need to allocate a new AuxMap entry for it. */
284 if (auxmap_used >= auxmap_size) {
285 tl_assert(auxmap_used == auxmap_size);
286 /* Out of auxmap entries. */
287 tl_assert2(0, "failed to expand the auxmap table");
288 }
289
290 tl_assert(auxmap_used < auxmap_size);
291
292 auxmap[auxmap_used].base = a & ~(Addr)0xFFFF;
293 auxmap[auxmap_used].sm = &sm_distinguished[SM_DIST_NOACCESS];
294
295 if (0)
296 VG_(printf)("new auxmap, base = 0x%llx\n",
297 (ULong)auxmap[auxmap_used].base );
298
299 auxmap_used++;
300 return &auxmap[auxmap_used-1];
301}
302
303
304/* --------------- SecMap fundamentals --------------- */
305
306/* Produce the secmap for 'a', either from the primary map or by
307 ensuring there is an entry for it in the aux primary map. The
308 secmap may be a distinguished one as the caller will only want to
309 be able to read it.
310*/
311static SecMap* get_secmap_readable ( Addr a )
312{
313 if (a <= MAX_PRIMARY_ADDRESS) {
314 UWord pm_off = a >> 16;
315 return primary_map[ pm_off ];
316 } else {
317 AuxMapEnt* am = find_or_alloc_in_auxmap(a);
318 return am->sm;
319 }
320}
321
sewardj05fe85e2005-04-27 22:46:36 +0000322/* If 'a' has a SecMap, produce it. Else produce NULL. But don't
323 allocate one if one doesn't already exist. This is used by the
324 leak checker.
325*/
326static SecMap* maybe_get_secmap_for ( Addr a )
327{
328 if (a <= MAX_PRIMARY_ADDRESS) {
329 UWord pm_off = a >> 16;
330 return primary_map[ pm_off ];
331 } else {
332 AuxMapEnt* am = maybe_find_in_auxmap(a);
333 return am ? am->sm : NULL;
334 }
335}
336
337
338
sewardj45d94cc2005-04-20 14:44:11 +0000339/* Produce the secmap for 'a', either from the primary map or by
340 ensuring there is an entry for it in the aux primary map. The
341 secmap may not be a distinguished one, since the caller will want
342 to be able to write it. If it is a distinguished secondary, make a
343 writable copy of it, install it, and return the copy instead. (COW
344 semantics).
345*/
346static SecMap* get_secmap_writable ( Addr a )
347{
348 if (a <= MAX_PRIMARY_ADDRESS) {
349 UWord pm_off = a >> 16;
350 if (is_distinguished_sm(primary_map[ pm_off ]))
351 primary_map[pm_off] = copy_for_writing(primary_map[pm_off]);
352 return primary_map[pm_off];
353 } else {
354 AuxMapEnt* am = find_or_alloc_in_auxmap(a);
355 if (is_distinguished_sm(am->sm))
356 am->sm = copy_for_writing(am->sm);
357 return am->sm;
358 }
359}
360
361
362/* --------------- Endianness helpers --------------- */
363
364/* Returns the offset in memory of the byteno-th most significant byte
365 in a wordszB-sized word, given the specified endianness. */
366static inline UWord byte_offset_w ( UWord wordszB, Bool bigendian,
367 UWord byteno ) {
368 return bigendian ? (wordszB-1-byteno) : byteno;
369}
370
371
372/* --------------- Fundamental functions --------------- */
373
374static
375void get_abit_and_vbyte ( /*OUT*/UWord* abit,
376 /*OUT*/UWord* vbyte,
377 Addr a )
378{
379 SecMap* sm = get_secmap_readable(a);
380 *vbyte = 0xFF & sm->vbyte[a & 0xFFFF];
381 *abit = read_bit_array(sm->abits, a & 0xFFFF);
382}
383
384static
385UWord get_abit ( Addr a )
386{
387 SecMap* sm = get_secmap_readable(a);
388 return read_bit_array(sm->abits, a & 0xFFFF);
389}
390
391static
392void set_abit_and_vbyte ( Addr a, UWord abit, UWord vbyte )
393{
394 SecMap* sm = get_secmap_writable(a);
395 sm->vbyte[a & 0xFFFF] = 0xFF & vbyte;
396 write_bit_array(sm->abits, a & 0xFFFF, abit);
397}
398
399static
400void set_vbyte ( Addr a, UWord vbyte )
401{
402 SecMap* sm = get_secmap_writable(a);
403 sm->vbyte[a & 0xFFFF] = 0xFF & vbyte;
404}
405
406
407/* --------------- Load/store slow cases. --------------- */
408
409static
410ULong mc_LOADVn_slow ( Addr a, SizeT szB, Bool bigendian )
411{
412 /* Make up a result V word, which contains the loaded data for
sewardjf3d57dd2005-04-22 20:23:27 +0000413 valid addresses and Defined for invalid addresses. Iterate over
414 the bytes in the word, from the most significant down to the
415 least. */
sewardj45d94cc2005-04-20 14:44:11 +0000416 ULong vw = VGM_WORD64_INVALID;
417 SizeT i = szB-1;
418 SizeT n_addrs_bad = 0;
419 Addr ai;
420 Bool aok;
421 UWord abit, vbyte;
422
sewardjc1a2cda2005-04-21 17:34:00 +0000423 PROF_EVENT(30, "mc_LOADVn_slow");
sewardj45d94cc2005-04-20 14:44:11 +0000424 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
425
426 while (True) {
sewardjc1a2cda2005-04-21 17:34:00 +0000427 PROF_EVENT(31, "mc_LOADVn_slow(loop)");
sewardj45d94cc2005-04-20 14:44:11 +0000428 ai = a+byte_offset_w(szB,bigendian,i);
429 get_abit_and_vbyte(&abit, &vbyte, ai);
430 aok = abit == VGM_BIT_VALID;
431 if (!aok)
432 n_addrs_bad++;
433 vw <<= 8;
sewardjf3d57dd2005-04-22 20:23:27 +0000434 vw |= 0xFF & (aok ? vbyte : VGM_BYTE_VALID);
sewardj45d94cc2005-04-20 14:44:11 +0000435 if (i == 0) break;
436 i--;
437 }
438
439 if (n_addrs_bad > 0)
440 MAC_(record_address_error)( VG_(get_running_tid)(), a, szB, False );
441
sewardj45d94cc2005-04-20 14:44:11 +0000442 return vw;
443}
444
445
446static
447void mc_STOREVn_slow ( Addr a, SizeT szB, UWord vbytes, Bool bigendian )
448{
449 SizeT i;
450 SizeT n_addrs_bad = 0;
451 UWord abit;
452 Bool aok;
453 Addr ai;
454
sewardjc1a2cda2005-04-21 17:34:00 +0000455 PROF_EVENT(35, "mc_STOREVn_slow");
sewardj45d94cc2005-04-20 14:44:11 +0000456 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
457
458 /* Dump vbytes in memory, iterating from least to most significant
459 byte. At the same time establish addressibility of the
460 location. */
461 for (i = 0; i < szB; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +0000462 PROF_EVENT(36, "mc_STOREVn_slow(loop)");
sewardj45d94cc2005-04-20 14:44:11 +0000463 ai = a+byte_offset_w(szB,bigendian,i);
464 abit = get_abit(ai);
465 aok = abit == VGM_BIT_VALID;
466 if (!aok)
467 n_addrs_bad++;
468 set_vbyte(ai, vbytes & 0xFF );
469 vbytes >>= 8;
470 }
471
472 /* If an address error has happened, report it. */
473 if (n_addrs_bad > 0)
474 MAC_(record_address_error)( VG_(get_running_tid)(), a, szB, True );
475}
476
477
sewardj45d94cc2005-04-20 14:44:11 +0000478//zz /* Reading/writing of the bitmaps, for aligned word-sized accesses. */
479//zz
480//zz static __inline__ UChar get_abits4_ALIGNED ( Addr a )
481//zz {
482//zz SecMap* sm;
483//zz UInt sm_off;
484//zz UChar abits8;
485//zz PROF_EVENT(24);
486//zz # ifdef VG_DEBUG_MEMORY
487//zz tl_assert(VG_IS_4_ALIGNED(a));
488//zz # endif
489//zz sm = primary_map[PM_IDX(a)];
490//zz sm_off = SM_OFF(a);
491//zz abits8 = sm->abits[sm_off >> 3];
492//zz abits8 >>= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
493//zz abits8 &= 0x0F;
494//zz return abits8;
495//zz }
496//zz
497//zz static UInt __inline__ get_vbytes4_ALIGNED ( Addr a )
498//zz {
499//zz SecMap* sm = primary_map[PM_IDX(a)];
500//zz UInt sm_off = SM_OFF(a);
501//zz PROF_EVENT(25);
502//zz # ifdef VG_DEBUG_MEMORY
503//zz tl_assert(VG_IS_4_ALIGNED(a));
504//zz # endif
505//zz return ((UInt*)(sm->vbyte))[sm_off >> 2];
506//zz }
507//zz
508//zz
509//zz static void __inline__ set_vbytes4_ALIGNED ( Addr a, UInt vbytes )
510//zz {
511//zz SecMap* sm;
512//zz UInt sm_off;
513//zz ENSURE_MAPPABLE(a, "set_vbytes4_ALIGNED");
514//zz sm = primary_map[PM_IDX(a)];
515//zz sm_off = SM_OFF(a);
516//zz PROF_EVENT(23);
517//zz # ifdef VG_DEBUG_MEMORY
518//zz tl_assert(VG_IS_4_ALIGNED(a));
519//zz # endif
520//zz ((UInt*)(sm->vbyte))[sm_off >> 2] = vbytes;
521//zz }
sewardjee070842003-07-05 17:53:55 +0000522
523
njn25e49d8e72002-09-23 09:36:25 +0000524/*------------------------------------------------------------*/
525/*--- Setting permissions over address ranges. ---*/
526/*------------------------------------------------------------*/
527
sewardj23eb2fd2005-04-22 16:29:19 +0000528/* Given address 'a', find the place where the pointer to a's
529 secondary map lives. If a falls into the primary map, the returned
530 value points to one of the entries in primary_map[]. Otherwise,
531 the auxiliary primary map is searched for 'a', or an entry is
532 created for it; either way, the returned value points to the
533 relevant AuxMapEnt's .sm field.
534
535 The point of this is to enable set_address_range_perms to assign
536 secondary maps in a uniform way, without worrying about whether a
537 given secondary map is pointed to from the main or auxiliary
538 primary map.
539*/
540
541static SecMap** find_secmap_binder_for_addr ( Addr aA )
542{
543 if (aA > MAX_PRIMARY_ADDRESS) {
544 AuxMapEnt* am = find_or_alloc_in_auxmap(aA);
545 return &am->sm;
546 } else {
547 UWord a = (UWord)aA;
548 UWord sec_no = (UWord)(a >> 16);
549# if VG_DEBUG_MEMORY >= 1
550 tl_assert(sec_no < N_PRIMARY_MAP);
551# endif
552 return &primary_map[sec_no];
553 }
554}
555
556
557static void set_address_range_perms ( Addr aA, SizeT len,
sewardj45d94cc2005-04-20 14:44:11 +0000558 UWord example_a_bit,
559 UWord example_v_bit )
njn25e49d8e72002-09-23 09:36:25 +0000560{
sewardjae986ca2005-10-12 12:53:20 +0000561 UWord a, vbits8, abits8, vbits32, v_off, a_off;
562 SecMap* sm;
563 SecMap** binder;
564 SecMap* example_dsm;
565
sewardj23eb2fd2005-04-22 16:29:19 +0000566 PROF_EVENT(150, "set_address_range_perms");
567
568 /* Check the permissions make sense. */
569 tl_assert(example_a_bit == VGM_BIT_VALID
570 || example_a_bit == VGM_BIT_INVALID);
571 tl_assert(example_v_bit == VGM_BIT_VALID
572 || example_v_bit == VGM_BIT_INVALID);
573 if (example_a_bit == VGM_BIT_INVALID)
574 tl_assert(example_v_bit == VGM_BIT_INVALID);
575
576 if (len == 0)
577 return;
578
sewardj1fa7d2c2005-06-13 18:22:17 +0000579 if (VG_(clo_verbosity) > 0 && !VG_(clo_xml)) {
sewardj23eb2fd2005-04-22 16:29:19 +0000580 if (len > 100 * 1000 * 1000) {
581 VG_(message)(Vg_UserMsg,
582 "Warning: set address range perms: "
sewardj9273eb92005-09-28 20:00:30 +0000583 "large range %lu, a %d, v %d",
sewardj23eb2fd2005-04-22 16:29:19 +0000584 len, example_a_bit, example_v_bit );
585 }
586 }
587
sewardjae986ca2005-10-12 12:53:20 +0000588 a = (UWord)aA;
sewardj23eb2fd2005-04-22 16:29:19 +0000589
590# if VG_DEBUG_MEMORY >= 2
591
592 /*------------------ debug-only case ------------------ */
sewardjae986ca2005-10-12 12:53:20 +0000593 { SizeT i;
njn25e49d8e72002-09-23 09:36:25 +0000594
sewardjae986ca2005-10-12 12:53:20 +0000595 UWord example_vbyte = BIT_TO_BYTE(example_v_bit);
sewardj45d94cc2005-04-20 14:44:11 +0000596
sewardjae986ca2005-10-12 12:53:20 +0000597 tl_assert(sizeof(SizeT) == sizeof(Addr));
sewardj45d94cc2005-04-20 14:44:11 +0000598
sewardjae986ca2005-10-12 12:53:20 +0000599 if (0 && len >= 4096)
600 VG_(printf)("s_a_r_p(0x%llx, %d, %d,%d)\n",
601 (ULong)a, len, example_a_bit, example_v_bit);
njn25e49d8e72002-09-23 09:36:25 +0000602
sewardjae986ca2005-10-12 12:53:20 +0000603 if (len == 0)
604 return;
njn25e49d8e72002-09-23 09:36:25 +0000605
sewardjae986ca2005-10-12 12:53:20 +0000606 for (i = 0; i < len; i++) {
607 set_abit_and_vbyte(a+i, example_a_bit, example_vbyte);
608 }
njn25e49d8e72002-09-23 09:36:25 +0000609 }
njn25e49d8e72002-09-23 09:36:25 +0000610
sewardj23eb2fd2005-04-22 16:29:19 +0000611# else
612
613 /*------------------ standard handling ------------------ */
sewardj23eb2fd2005-04-22 16:29:19 +0000614
615 /* Decide on the distinguished secondary that we might want
616 to use (part of the space-compression scheme). */
617 if (example_a_bit == VGM_BIT_INVALID) {
618 example_dsm = &sm_distinguished[SM_DIST_NOACCESS];
619 } else {
620 if (example_v_bit == VGM_BIT_VALID) {
621 example_dsm = &sm_distinguished[SM_DIST_ACCESS_DEFINED];
622 } else {
623 example_dsm = &sm_distinguished[SM_DIST_ACCESS_UNDEFINED];
624 }
625 }
626
627 /* Make various wider versions of the A/V values to use. */
628 vbits8 = BIT_TO_BYTE(example_v_bit);
629 abits8 = BIT_TO_BYTE(example_a_bit);
630 vbits32 = (vbits8 << 24) | (vbits8 << 16) | (vbits8 << 8) | vbits8;
631
632 /* Slowly do parts preceding 8-byte alignment. */
633 while (True) {
634 if (len == 0) break;
635 PROF_EVENT(151, "set_address_range_perms-loop1-pre");
636 if (VG_IS_8_ALIGNED(a)) break;
637 set_abit_and_vbyte( a, example_a_bit, vbits8 );
638 a++;
639 len--;
640 }
641
642 if (len == 0)
643 return;
644
645 tl_assert(VG_IS_8_ALIGNED(a) && len > 0);
646
647 /* Now go in steps of 8 bytes. */
648 binder = find_secmap_binder_for_addr(a);
649
650 while (True) {
651
652 if (len < 8) break;
653
654 PROF_EVENT(152, "set_address_range_perms-loop8");
655
656 if ((a & SECONDARY_MASK) == 0) {
657 /* we just traversed a primary map boundary, so update the
658 binder. */
659 binder = find_secmap_binder_for_addr(a);
660 PROF_EVENT(153, "set_address_range_perms-update-binder");
661
662 /* Space-optimisation. If we are setting the entire
663 secondary map, just point this entry at one of our
664 distinguished secondaries. However, only do that if it
665 already points at a distinguished secondary, since doing
666 otherwise would leak the existing secondary. We could do
667 better and free up any pre-existing non-distinguished
668 secondary at this point, since we are guaranteed that each
669 non-dist secondary only has one pointer to it, and we have
670 that pointer right here. */
671 if (len >= SECONDARY_SIZE && is_distinguished_sm(*binder)) {
672 PROF_EVENT(154, "set_address_range_perms-entire-secmap");
673 *binder = example_dsm;
674 len -= SECONDARY_SIZE;
675 a += SECONDARY_SIZE;
676 continue;
677 }
678 }
679
680 /* If the primary is already pointing to a distinguished map
681 with the same properties as we're trying to set, then leave
682 it that way. */
683 if (*binder == example_dsm) {
684 a += 8;
685 len -= 8;
686 continue;
687 }
688
689 /* Make sure it's OK to write the secondary. */
690 if (is_distinguished_sm(*binder))
691 *binder = copy_for_writing(*binder);
692
693 sm = *binder;
694 v_off = a & 0xFFFF;
695 a_off = v_off >> 3;
696 sm->abits[a_off] = (UChar)abits8;
697 ((UInt*)(sm->vbyte))[(v_off >> 2) + 0] = (UInt)vbits32;
698 ((UInt*)(sm->vbyte))[(v_off >> 2) + 1] = (UInt)vbits32;
699
700 a += 8;
701 len -= 8;
702 }
703
704 if (len == 0)
705 return;
706
707 tl_assert(VG_IS_8_ALIGNED(a) && len > 0 && len < 8);
708
709 /* Finish the upper fragment. */
710 while (True) {
711 if (len == 0) break;
712 PROF_EVENT(155, "set_address_range_perms-loop1-post");
713 set_abit_and_vbyte ( a, example_a_bit, vbits8 );
714 a++;
715 len--;
716 }
717
718# endif
719}
sewardj45d94cc2005-04-20 14:44:11 +0000720
sewardjc859fbf2005-04-22 21:10:28 +0000721
722/* --- Set permissions for arbitrary address ranges --- */
njn25e49d8e72002-09-23 09:36:25 +0000723
nethercote8b76fe52004-11-08 19:20:09 +0000724static void mc_make_noaccess ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000725{
sewardjc1a2cda2005-04-21 17:34:00 +0000726 PROF_EVENT(40, "mc_make_noaccess");
nethercote8b76fe52004-11-08 19:20:09 +0000727 DEBUG("mc_make_noaccess(%p, %llu)\n", a, (ULong)len);
njn25e49d8e72002-09-23 09:36:25 +0000728 set_address_range_perms ( a, len, VGM_BIT_INVALID, VGM_BIT_INVALID );
729}
730
nethercote8b76fe52004-11-08 19:20:09 +0000731static void mc_make_writable ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000732{
sewardjc1a2cda2005-04-21 17:34:00 +0000733 PROF_EVENT(41, "mc_make_writable");
nethercote8b76fe52004-11-08 19:20:09 +0000734 DEBUG("mc_make_writable(%p, %llu)\n", a, (ULong)len);
njn25e49d8e72002-09-23 09:36:25 +0000735 set_address_range_perms ( a, len, VGM_BIT_VALID, VGM_BIT_INVALID );
736}
737
nethercote8b76fe52004-11-08 19:20:09 +0000738static void mc_make_readable ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000739{
sewardjc1a2cda2005-04-21 17:34:00 +0000740 PROF_EVENT(42, "mc_make_readable");
nethercote8b76fe52004-11-08 19:20:09 +0000741 DEBUG("mc_make_readable(%p, %llu)\n", a, (ULong)len);
njn25e49d8e72002-09-23 09:36:25 +0000742 set_address_range_perms ( a, len, VGM_BIT_VALID, VGM_BIT_VALID );
743}
744
njn9b007f62003-04-07 14:40:25 +0000745
sewardj45f4e7c2005-09-27 19:20:21 +0000746/* --- Block-copy permissions (needed for implementing realloc() and
747 sys_mremap). --- */
sewardjc859fbf2005-04-22 21:10:28 +0000748
749static void mc_copy_address_range_state ( Addr src, Addr dst, SizeT len )
750{
sewardj45f4e7c2005-09-27 19:20:21 +0000751 SizeT i, j;
sewardjc859fbf2005-04-22 21:10:28 +0000752 UWord abit, vbyte;
753
754 DEBUG("mc_copy_address_range_state\n");
sewardjc859fbf2005-04-22 21:10:28 +0000755 PROF_EVENT(50, "mc_copy_address_range_state");
sewardj45f4e7c2005-09-27 19:20:21 +0000756
757 if (len == 0)
758 return;
759
760 if (src < dst) {
761 for (i = 0, j = len-1; i < len; i++, j--) {
762 PROF_EVENT(51, "mc_copy_address_range_state(loop)");
763 get_abit_and_vbyte( &abit, &vbyte, src+j );
764 set_abit_and_vbyte( dst+j, abit, vbyte );
765 }
766 }
767
768 if (src > dst) {
769 for (i = 0; i < len; i++) {
770 PROF_EVENT(51, "mc_copy_address_range_state(loop)");
771 get_abit_and_vbyte( &abit, &vbyte, src+i );
772 set_abit_and_vbyte( dst+i, abit, vbyte );
773 }
sewardjc859fbf2005-04-22 21:10:28 +0000774 }
775}
776
777
778/* --- Fast case permission setters, for dealing with stacks. --- */
779
njn9b007f62003-04-07 14:40:25 +0000780static __inline__
sewardj5d28efc2005-04-21 22:16:29 +0000781void make_aligned_word32_writable ( Addr aA )
njn9b007f62003-04-07 14:40:25 +0000782{
sewardjae986ca2005-10-12 12:53:20 +0000783 UWord a, sec_no, v_off, a_off, mask;
784 SecMap* sm;
785
sewardj5d28efc2005-04-21 22:16:29 +0000786 PROF_EVENT(300, "make_aligned_word32_writable");
787
788# if VG_DEBUG_MEMORY >= 2
789 mc_make_writable(aA, 4);
790# else
791
792 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
sewardj23eb2fd2005-04-22 16:29:19 +0000793 PROF_EVENT(301, "make_aligned_word32_writable-slow1");
sewardj5d28efc2005-04-21 22:16:29 +0000794 mc_make_writable(aA, 4);
795 return;
796 }
797
sewardjae986ca2005-10-12 12:53:20 +0000798 a = (UWord)aA;
799 sec_no = (UWord)(a >> 16);
sewardj5d28efc2005-04-21 22:16:29 +0000800# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +0000801 tl_assert(sec_no < N_PRIMARY_MAP);
sewardj5d28efc2005-04-21 22:16:29 +0000802# endif
803
804 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
805 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
806
sewardjae986ca2005-10-12 12:53:20 +0000807 sm = primary_map[sec_no];
808 v_off = a & 0xFFFF;
809 a_off = v_off >> 3;
sewardj5d28efc2005-04-21 22:16:29 +0000810
811 /* Paint the new area as uninitialised. */
812 ((UInt*)(sm->vbyte))[v_off >> 2] = VGM_WORD32_INVALID;
813
sewardjae986ca2005-10-12 12:53:20 +0000814 mask = 0x0F;
sewardj5d28efc2005-04-21 22:16:29 +0000815 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
816 /* mask now contains 1s where we wish to make address bits valid
817 (0s). */
818 sm->abits[a_off] &= ~mask;
819# endif
njn9b007f62003-04-07 14:40:25 +0000820}
821
sewardj5d28efc2005-04-21 22:16:29 +0000822
823static __inline__
824void make_aligned_word32_noaccess ( Addr aA )
825{
sewardjae986ca2005-10-12 12:53:20 +0000826 UWord a, sec_no, v_off, a_off, mask;
827 SecMap* sm;
828
sewardj5d28efc2005-04-21 22:16:29 +0000829 PROF_EVENT(310, "make_aligned_word32_noaccess");
830
831# if VG_DEBUG_MEMORY >= 2
832 mc_make_noaccess(aA, 4);
833# else
834
835 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
836 PROF_EVENT(311, "make_aligned_word32_noaccess-slow1");
837 mc_make_noaccess(aA, 4);
838 return;
839 }
840
sewardjae986ca2005-10-12 12:53:20 +0000841 a = (UWord)aA;
842 sec_no = (UWord)(a >> 16);
sewardj5d28efc2005-04-21 22:16:29 +0000843# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +0000844 tl_assert(sec_no < N_PRIMARY_MAP);
sewardj5d28efc2005-04-21 22:16:29 +0000845# endif
846
847 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
848 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
849
sewardjae986ca2005-10-12 12:53:20 +0000850 sm = primary_map[sec_no];
851 v_off = a & 0xFFFF;
852 a_off = v_off >> 3;
sewardj5d28efc2005-04-21 22:16:29 +0000853
854 /* Paint the abandoned data as uninitialised. Probably not
855 necessary, but still .. */
856 ((UInt*)(sm->vbyte))[v_off >> 2] = VGM_WORD32_INVALID;
857
sewardjae986ca2005-10-12 12:53:20 +0000858 mask = 0x0F;
sewardj5d28efc2005-04-21 22:16:29 +0000859 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
860 /* mask now contains 1s where we wish to make address bits invalid
861 (1s). */
862 sm->abits[a_off] |= mask;
863# endif
864}
865
866
njn9b007f62003-04-07 14:40:25 +0000867/* Nb: by "aligned" here we mean 8-byte aligned */
868static __inline__
sewardj23eb2fd2005-04-22 16:29:19 +0000869void make_aligned_word64_writable ( Addr aA )
njn9b007f62003-04-07 14:40:25 +0000870{
sewardjae986ca2005-10-12 12:53:20 +0000871 UWord a, sec_no, v_off, a_off;
872 SecMap* sm;
873
sewardj23eb2fd2005-04-22 16:29:19 +0000874 PROF_EVENT(320, "make_aligned_word64_writable");
875
876# if VG_DEBUG_MEMORY >= 2
877 mc_make_writable(aA, 8);
878# else
879
880 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
881 PROF_EVENT(321, "make_aligned_word64_writable-slow1");
882 mc_make_writable(aA, 8);
883 return;
884 }
885
sewardjae986ca2005-10-12 12:53:20 +0000886 a = (UWord)aA;
887 sec_no = (UWord)(a >> 16);
sewardj23eb2fd2005-04-22 16:29:19 +0000888# if VG_DEBUG_MEMORY >= 1
889 tl_assert(sec_no < N_PRIMARY_MAP);
890# endif
891
892 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
893 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
894
sewardjae986ca2005-10-12 12:53:20 +0000895 sm = primary_map[sec_no];
896 v_off = a & 0xFFFF;
897 a_off = v_off >> 3;
sewardj23eb2fd2005-04-22 16:29:19 +0000898
899 /* Paint the new area as uninitialised. */
900 ((ULong*)(sm->vbyte))[v_off >> 3] = VGM_WORD64_INVALID;
901
902 /* Make the relevant area accessible. */
903 sm->abits[a_off] = VGM_BYTE_VALID;
904# endif
njn9b007f62003-04-07 14:40:25 +0000905}
906
sewardj23eb2fd2005-04-22 16:29:19 +0000907
njn9b007f62003-04-07 14:40:25 +0000908static __inline__
sewardj23eb2fd2005-04-22 16:29:19 +0000909void make_aligned_word64_noaccess ( Addr aA )
njn9b007f62003-04-07 14:40:25 +0000910{
sewardjae986ca2005-10-12 12:53:20 +0000911 UWord a, sec_no, v_off, a_off;
912 SecMap* sm;
913
sewardj23eb2fd2005-04-22 16:29:19 +0000914 PROF_EVENT(330, "make_aligned_word64_noaccess");
915
916# if VG_DEBUG_MEMORY >= 2
917 mc_make_noaccess(aA, 8);
918# else
919
920 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
921 PROF_EVENT(331, "make_aligned_word64_noaccess-slow1");
922 mc_make_noaccess(aA, 8);
923 return;
924 }
925
sewardjae986ca2005-10-12 12:53:20 +0000926 a = (UWord)aA;
927 sec_no = (UWord)(a >> 16);
sewardj23eb2fd2005-04-22 16:29:19 +0000928# if VG_DEBUG_MEMORY >= 1
929 tl_assert(sec_no < N_PRIMARY_MAP);
930# endif
931
932 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
933 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
934
sewardjae986ca2005-10-12 12:53:20 +0000935 sm = primary_map[sec_no];
936 v_off = a & 0xFFFF;
937 a_off = v_off >> 3;
sewardj23eb2fd2005-04-22 16:29:19 +0000938
939 /* Paint the abandoned data as uninitialised. Probably not
940 necessary, but still .. */
941 ((ULong*)(sm->vbyte))[v_off >> 3] = VGM_WORD64_INVALID;
942
943 /* Make the abandoned area inaccessible. */
944 sm->abits[a_off] = VGM_BYTE_INVALID;
945# endif
njn9b007f62003-04-07 14:40:25 +0000946}
947
sewardj23eb2fd2005-04-22 16:29:19 +0000948
sewardj45d94cc2005-04-20 14:44:11 +0000949/* The stack-pointer update handling functions */
950SP_UPDATE_HANDLERS ( make_aligned_word32_writable,
951 make_aligned_word32_noaccess,
952 make_aligned_word64_writable,
953 make_aligned_word64_noaccess,
954 mc_make_writable,
955 mc_make_noaccess
956 );
njn9b007f62003-04-07 14:40:25 +0000957
sewardj45d94cc2005-04-20 14:44:11 +0000958
sewardj826ec492005-05-12 18:05:00 +0000959void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len )
960{
961 tl_assert(sizeof(UWord) == sizeof(SizeT));
sewardj2a3a1a72005-05-12 23:25:43 +0000962 if (0)
963 VG_(printf)("helperc_MAKE_STACK_UNINIT %p %d\n", base, len );
964
965# if 0
966 /* Really slow version */
967 mc_make_writable(base, len);
968# endif
969
970# if 0
971 /* Slow(ish) version, which is fairly easily seen to be correct.
972 */
973 if (EXPECTED_TAKEN( VG_IS_8_ALIGNED(base) && len==128 )) {
974 make_aligned_word64_writable(base + 0);
975 make_aligned_word64_writable(base + 8);
976 make_aligned_word64_writable(base + 16);
977 make_aligned_word64_writable(base + 24);
978
979 make_aligned_word64_writable(base + 32);
980 make_aligned_word64_writable(base + 40);
981 make_aligned_word64_writable(base + 48);
982 make_aligned_word64_writable(base + 56);
983
984 make_aligned_word64_writable(base + 64);
985 make_aligned_word64_writable(base + 72);
986 make_aligned_word64_writable(base + 80);
987 make_aligned_word64_writable(base + 88);
988
989 make_aligned_word64_writable(base + 96);
990 make_aligned_word64_writable(base + 104);
991 make_aligned_word64_writable(base + 112);
992 make_aligned_word64_writable(base + 120);
993 } else {
994 mc_make_writable(base, len);
995 }
996# endif
997
998 /* Idea is: go fast when
999 * 8-aligned and length is 128
1000 * the sm is available in the main primary map
1001 * the address range falls entirely with a single
1002 secondary map
1003 * the SM is modifiable
1004 If all those conditions hold, just update the V bits
1005 by writing directly on the v-bit array. We don't care
1006 about A bits; if the address range is marked invalid,
1007 any attempt to access it will elicit an addressing error,
1008 and that's good enough.
1009 */
1010 if (EXPECTED_TAKEN( len == 128
1011 && VG_IS_8_ALIGNED(base)
1012 )) {
1013 /* Now we know the address range is suitably sized and
1014 aligned. */
1015 UWord a_lo = (UWord)base;
1016 UWord a_hi = (UWord)(base + 127);
1017 UWord sec_lo = a_lo >> 16;
1018 UWord sec_hi = a_hi >> 16;
1019
1020 if (EXPECTED_TAKEN( sec_lo == sec_hi
1021 && sec_lo <= N_PRIMARY_MAP
1022 )) {
1023 /* Now we know that the entire address range falls within a
1024 single secondary map, and that that secondary 'lives' in
1025 the main primary map. */
1026 SecMap* sm = primary_map[sec_lo];
1027
1028 if (EXPECTED_TAKEN( !is_distinguished_sm(sm) )) {
1029 /* And finally, now we know that the secondary in question
1030 is modifiable. */
1031 UWord v_off = a_lo & 0xFFFF;
1032 ULong* p = (ULong*)(&sm->vbyte[v_off]);
1033 p[ 0] = VGM_WORD64_INVALID;
1034 p[ 1] = VGM_WORD64_INVALID;
1035 p[ 2] = VGM_WORD64_INVALID;
1036 p[ 3] = VGM_WORD64_INVALID;
1037 p[ 4] = VGM_WORD64_INVALID;
1038 p[ 5] = VGM_WORD64_INVALID;
1039 p[ 6] = VGM_WORD64_INVALID;
1040 p[ 7] = VGM_WORD64_INVALID;
1041 p[ 8] = VGM_WORD64_INVALID;
1042 p[ 9] = VGM_WORD64_INVALID;
1043 p[10] = VGM_WORD64_INVALID;
1044 p[11] = VGM_WORD64_INVALID;
1045 p[12] = VGM_WORD64_INVALID;
1046 p[13] = VGM_WORD64_INVALID;
1047 p[14] = VGM_WORD64_INVALID;
1048 p[15] = VGM_WORD64_INVALID;
1049 return;
1050 }
1051 }
1052 }
1053
1054 /* else fall into slow case */
sewardj826ec492005-05-12 18:05:00 +00001055 mc_make_writable(base, len);
1056}
1057
1058
nethercote8b76fe52004-11-08 19:20:09 +00001059/*------------------------------------------------------------*/
1060/*--- Checking memory ---*/
1061/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00001062
sewardje4ccc012005-05-02 12:53:38 +00001063typedef
1064 enum {
1065 MC_Ok = 5,
1066 MC_AddrErr = 6,
1067 MC_ValueErr = 7
1068 }
1069 MC_ReadResult;
1070
1071
njn25e49d8e72002-09-23 09:36:25 +00001072/* Check permissions for address range. If inadequate permissions
1073 exist, *bad_addr is set to the offending address, so the caller can
1074 know what it is. */
1075
sewardjecf8e102003-07-12 12:11:39 +00001076/* Returns True if [a .. a+len) is not addressible. Otherwise,
1077 returns False, and if bad_addr is non-NULL, sets *bad_addr to
1078 indicate the lowest failing address. Functions below are
1079 similar. */
nethercote8b76fe52004-11-08 19:20:09 +00001080static Bool mc_check_noaccess ( Addr a, SizeT len, Addr* bad_addr )
sewardjecf8e102003-07-12 12:11:39 +00001081{
nethercote451eae92004-11-02 13:06:32 +00001082 SizeT i;
sewardj45d94cc2005-04-20 14:44:11 +00001083 UWord abit;
sewardjc1a2cda2005-04-21 17:34:00 +00001084 PROF_EVENT(60, "mc_check_noaccess");
sewardjecf8e102003-07-12 12:11:39 +00001085 for (i = 0; i < len; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +00001086 PROF_EVENT(61, "mc_check_noaccess(loop)");
sewardjecf8e102003-07-12 12:11:39 +00001087 abit = get_abit(a);
1088 if (abit == VGM_BIT_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001089 if (bad_addr != NULL)
1090 *bad_addr = a;
sewardjecf8e102003-07-12 12:11:39 +00001091 return False;
1092 }
1093 a++;
1094 }
1095 return True;
1096}
1097
nethercote8b76fe52004-11-08 19:20:09 +00001098static Bool mc_check_writable ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +00001099{
nethercote451eae92004-11-02 13:06:32 +00001100 SizeT i;
sewardj45d94cc2005-04-20 14:44:11 +00001101 UWord abit;
sewardjc1a2cda2005-04-21 17:34:00 +00001102 PROF_EVENT(62, "mc_check_writable");
njn25e49d8e72002-09-23 09:36:25 +00001103 for (i = 0; i < len; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +00001104 PROF_EVENT(63, "mc_check_writable(loop)");
njn25e49d8e72002-09-23 09:36:25 +00001105 abit = get_abit(a);
1106 if (abit == VGM_BIT_INVALID) {
1107 if (bad_addr != NULL) *bad_addr = a;
1108 return False;
1109 }
1110 a++;
1111 }
1112 return True;
1113}
1114
nethercote8b76fe52004-11-08 19:20:09 +00001115static MC_ReadResult mc_check_readable ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +00001116{
nethercote451eae92004-11-02 13:06:32 +00001117 SizeT i;
sewardj45d94cc2005-04-20 14:44:11 +00001118 UWord abit;
1119 UWord vbyte;
njn25e49d8e72002-09-23 09:36:25 +00001120
sewardjc1a2cda2005-04-21 17:34:00 +00001121 PROF_EVENT(64, "mc_check_readable");
nethercote8b76fe52004-11-08 19:20:09 +00001122 DEBUG("mc_check_readable\n");
njn25e49d8e72002-09-23 09:36:25 +00001123 for (i = 0; i < len; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +00001124 PROF_EVENT(65, "mc_check_readable(loop)");
sewardj45d94cc2005-04-20 14:44:11 +00001125 get_abit_and_vbyte(&abit, &vbyte, a);
nethercote8b76fe52004-11-08 19:20:09 +00001126 // Report addressability errors in preference to definedness errors
1127 // by checking the A bits first.
1128 if (abit != VGM_BIT_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001129 if (bad_addr != NULL)
1130 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +00001131 return MC_AddrErr;
1132 }
1133 if (vbyte != VGM_BYTE_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001134 if (bad_addr != NULL)
1135 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +00001136 return MC_ValueErr;
njn25e49d8e72002-09-23 09:36:25 +00001137 }
1138 a++;
1139 }
nethercote8b76fe52004-11-08 19:20:09 +00001140 return MC_Ok;
njn25e49d8e72002-09-23 09:36:25 +00001141}
1142
1143
1144/* Check a zero-terminated ascii string. Tricky -- don't want to
1145 examine the actual bytes, to find the end, until we're sure it is
1146 safe to do so. */
1147
njn9b007f62003-04-07 14:40:25 +00001148static Bool mc_check_readable_asciiz ( Addr a, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +00001149{
sewardj45d94cc2005-04-20 14:44:11 +00001150 UWord abit;
1151 UWord vbyte;
sewardjc1a2cda2005-04-21 17:34:00 +00001152 PROF_EVENT(66, "mc_check_readable_asciiz");
njn5c004e42002-11-18 11:04:50 +00001153 DEBUG("mc_check_readable_asciiz\n");
njn25e49d8e72002-09-23 09:36:25 +00001154 while (True) {
sewardjc1a2cda2005-04-21 17:34:00 +00001155 PROF_EVENT(67, "mc_check_readable_asciiz(loop)");
sewardj45d94cc2005-04-20 14:44:11 +00001156 get_abit_and_vbyte(&abit, &vbyte, a);
nethercote8b76fe52004-11-08 19:20:09 +00001157 // As in mc_check_readable(), check A bits first
1158 if (abit != VGM_BIT_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001159 if (bad_addr != NULL)
1160 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +00001161 return MC_AddrErr;
1162 }
1163 if (vbyte != VGM_BYTE_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001164 if (bad_addr != NULL)
1165 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +00001166 return MC_ValueErr;
njn25e49d8e72002-09-23 09:36:25 +00001167 }
1168 /* Ok, a is safe to read. */
sewardj45d94cc2005-04-20 14:44:11 +00001169 if (* ((UChar*)a) == 0)
1170 return MC_Ok;
njn25e49d8e72002-09-23 09:36:25 +00001171 a++;
1172 }
1173}
1174
1175
1176/*------------------------------------------------------------*/
1177/*--- Memory event handlers ---*/
1178/*------------------------------------------------------------*/
1179
njn25e49d8e72002-09-23 09:36:25 +00001180static
njn72718642003-07-24 08:45:32 +00001181void mc_check_is_writable ( CorePart part, ThreadId tid, Char* s,
nethercote451eae92004-11-02 13:06:32 +00001182 Addr base, SizeT size )
njn25e49d8e72002-09-23 09:36:25 +00001183{
1184 Bool ok;
1185 Addr bad_addr;
1186
1187 VGP_PUSHCC(VgpCheckMem);
1188
1189 /* VG_(message)(Vg_DebugMsg,"check is writable: %x .. %x",
1190 base,base+size-1); */
nethercote8b76fe52004-11-08 19:20:09 +00001191 ok = mc_check_writable ( base, size, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +00001192 if (!ok) {
1193 switch (part) {
1194 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +00001195 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
1196 /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +00001197 break;
1198
1199 case Vg_CorePThread:
1200 case Vg_CoreSignal:
nethercote8b76fe52004-11-08 19:20:09 +00001201 MAC_(record_core_mem_error)( tid, /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +00001202 break;
1203
1204 default:
njn67993252004-11-22 18:02:32 +00001205 VG_(tool_panic)("mc_check_is_writable: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +00001206 }
1207 }
1208
1209 VGP_POPCC(VgpCheckMem);
1210}
1211
1212static
njn72718642003-07-24 08:45:32 +00001213void mc_check_is_readable ( CorePart part, ThreadId tid, Char* s,
nethercote451eae92004-11-02 13:06:32 +00001214 Addr base, SizeT size )
njn25e49d8e72002-09-23 09:36:25 +00001215{
njn25e49d8e72002-09-23 09:36:25 +00001216 Addr bad_addr;
nethercote8b76fe52004-11-08 19:20:09 +00001217 MC_ReadResult res;
njn25e49d8e72002-09-23 09:36:25 +00001218
1219 VGP_PUSHCC(VgpCheckMem);
1220
nethercote8b76fe52004-11-08 19:20:09 +00001221 res = mc_check_readable ( base, size, &bad_addr );
sewardj45f4e7c2005-09-27 19:20:21 +00001222
1223 if (0)
1224 VG_(printf)("mc_check_is_readable(0x%x, %d, %s) -> %s\n",
1225 (UInt)base, (Int)size, s, res==MC_Ok ? "yes" : "no" );
1226
nethercote8b76fe52004-11-08 19:20:09 +00001227 if (MC_Ok != res) {
1228 Bool isUnaddr = ( MC_AddrErr == res ? True : False );
sewardj45f4e7c2005-09-27 19:20:21 +00001229
njn25e49d8e72002-09-23 09:36:25 +00001230 switch (part) {
1231 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +00001232 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
1233 isUnaddr, s );
njn25e49d8e72002-09-23 09:36:25 +00001234 break;
1235
1236 case Vg_CorePThread:
nethercote8b76fe52004-11-08 19:20:09 +00001237 MAC_(record_core_mem_error)( tid, isUnaddr, s );
njn25e49d8e72002-09-23 09:36:25 +00001238 break;
1239
1240 /* If we're being asked to jump to a silly address, record an error
1241 message before potentially crashing the entire system. */
1242 case Vg_CoreTranslate:
njn72718642003-07-24 08:45:32 +00001243 MAC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +00001244 break;
1245
1246 default:
njn67993252004-11-22 18:02:32 +00001247 VG_(tool_panic)("mc_check_is_readable: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +00001248 }
1249 }
1250 VGP_POPCC(VgpCheckMem);
1251}
1252
1253static
njn72718642003-07-24 08:45:32 +00001254void mc_check_is_readable_asciiz ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +00001255 Char* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +00001256{
nethercote8b76fe52004-11-08 19:20:09 +00001257 MC_ReadResult res;
njn5ab96ac2005-05-08 02:59:50 +00001258 Addr bad_addr = 0; // shut GCC up
njn25e49d8e72002-09-23 09:36:25 +00001259 /* VG_(message)(Vg_DebugMsg,"check is readable asciiz: 0x%x",str); */
1260
1261 VGP_PUSHCC(VgpCheckMem);
1262
njnca82cc02004-11-22 17:18:48 +00001263 tl_assert(part == Vg_CoreSysCall);
nethercote8b76fe52004-11-08 19:20:09 +00001264 res = mc_check_readable_asciiz ( (Addr)str, &bad_addr );
1265 if (MC_Ok != res) {
1266 Bool isUnaddr = ( MC_AddrErr == res ? True : False );
1267 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False, isUnaddr, s );
njn25e49d8e72002-09-23 09:36:25 +00001268 }
1269
1270 VGP_POPCC(VgpCheckMem);
1271}
1272
njn25e49d8e72002-09-23 09:36:25 +00001273static
nethercote451eae92004-11-02 13:06:32 +00001274void mc_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +00001275{
njn1f3a9092002-10-04 09:22:30 +00001276 /* Ignore the permissions, just make it readable. Seems to work... */
nethercote451eae92004-11-02 13:06:32 +00001277 DEBUG("mc_new_mem_startup(%p, %llu, rr=%u, ww=%u, xx=%u)\n",
1278 a,(ULong)len,rr,ww,xx);
nethercote8b76fe52004-11-08 19:20:09 +00001279 mc_make_readable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001280}
1281
1282static
nethercote451eae92004-11-02 13:06:32 +00001283void mc_new_mem_heap ( Addr a, SizeT len, Bool is_inited )
njn25e49d8e72002-09-23 09:36:25 +00001284{
1285 if (is_inited) {
nethercote8b76fe52004-11-08 19:20:09 +00001286 mc_make_readable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001287 } else {
nethercote8b76fe52004-11-08 19:20:09 +00001288 mc_make_writable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001289 }
1290}
1291
1292static
njnb8dca862005-03-14 02:42:44 +00001293void mc_new_mem_mmap ( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +00001294{
njnb8dca862005-03-14 02:42:44 +00001295 mc_make_readable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001296}
1297
njncf45fd42004-11-24 16:30:22 +00001298static
1299void mc_post_mem_write(CorePart part, ThreadId tid, Addr a, SizeT len)
1300{
1301 mc_make_readable(a, len);
1302}
njn25e49d8e72002-09-23 09:36:25 +00001303
sewardj45d94cc2005-04-20 14:44:11 +00001304
njn25e49d8e72002-09-23 09:36:25 +00001305/*------------------------------------------------------------*/
njnd3040452003-05-19 15:04:06 +00001306/*--- Register event handlers ---*/
1307/*------------------------------------------------------------*/
1308
sewardj45d94cc2005-04-20 14:44:11 +00001309/* When some chunk of guest state is written, mark the corresponding
1310 shadow area as valid. This is used to initialise arbitrarily large
sewardj2c27f702005-05-03 18:19:05 +00001311 chunks of guest state, hence the (somewhat arbitrary) 1024 limit.
sewardj45d94cc2005-04-20 14:44:11 +00001312*/
1313static void mc_post_reg_write ( CorePart part, ThreadId tid,
1314 OffT offset, SizeT size)
njnd3040452003-05-19 15:04:06 +00001315{
sewardj6cf40ff2005-04-20 22:31:26 +00001316 UChar area[1024];
1317 tl_assert(size <= 1024);
njncf45fd42004-11-24 16:30:22 +00001318 VG_(memset)(area, VGM_BYTE_VALID, size);
1319 VG_(set_shadow_regs_area)( tid, offset, size, area );
njnd3040452003-05-19 15:04:06 +00001320}
1321
sewardj45d94cc2005-04-20 14:44:11 +00001322static
1323void mc_post_reg_write_clientcall ( ThreadId tid,
1324 OffT offset, SizeT size,
1325 Addr f)
njnd3040452003-05-19 15:04:06 +00001326{
njncf45fd42004-11-24 16:30:22 +00001327 mc_post_reg_write(/*dummy*/0, tid, offset, size);
njnd3040452003-05-19 15:04:06 +00001328}
1329
sewardj45d94cc2005-04-20 14:44:11 +00001330/* Look at the definedness of the guest's shadow state for
1331 [offset, offset+len). If any part of that is undefined, record
1332 a parameter error.
1333*/
1334static void mc_pre_reg_read ( CorePart part, ThreadId tid, Char* s,
1335 OffT offset, SizeT size)
nethercote8b76fe52004-11-08 19:20:09 +00001336{
sewardj45d94cc2005-04-20 14:44:11 +00001337 Int i;
1338 Bool bad;
1339
1340 UChar area[16];
1341 tl_assert(size <= 16);
1342
1343 VG_(get_shadow_regs_area)( tid, offset, size, area );
1344
1345 bad = False;
1346 for (i = 0; i < size; i++) {
1347 if (area[i] != VGM_BYTE_VALID) {
sewardj2c27f702005-05-03 18:19:05 +00001348 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00001349 break;
1350 }
nethercote8b76fe52004-11-08 19:20:09 +00001351 }
1352
sewardj45d94cc2005-04-20 14:44:11 +00001353 if (bad)
nethercote8b76fe52004-11-08 19:20:09 +00001354 MAC_(record_param_error) ( tid, 0, /*isReg*/True, /*isUnaddr*/False, s );
1355}
njnd3040452003-05-19 15:04:06 +00001356
njn25e49d8e72002-09-23 09:36:25 +00001357
sewardj6cf40ff2005-04-20 22:31:26 +00001358/*------------------------------------------------------------*/
njn9e63cb62005-05-08 18:34:59 +00001359/*--- Printing errors ---*/
1360/*------------------------------------------------------------*/
1361
njn51d827b2005-05-09 01:02:08 +00001362static void mc_pp_Error ( Error* err )
njn9e63cb62005-05-08 18:34:59 +00001363{
1364 MAC_Error* err_extra = VG_(get_error_extra)(err);
1365
sewardj71bc3cb2005-05-19 00:25:45 +00001366 HChar* xpre = VG_(clo_xml) ? " <what>" : "";
1367 HChar* xpost = VG_(clo_xml) ? "</what>" : "";
1368
njn9e63cb62005-05-08 18:34:59 +00001369 switch (VG_(get_error_kind)(err)) {
1370 case CoreMemErr: {
1371 Char* s = ( err_extra->isUnaddr ? "unaddressable" : "uninitialised" );
sewardj71bc3cb2005-05-19 00:25:45 +00001372 if (VG_(clo_xml))
1373 VG_(message)(Vg_UserMsg, " <kind>CoreMemError</kind>");
1374 /* What the hell *is* a CoreMemError? jrs 2005-May-18 */
1375 VG_(message)(Vg_UserMsg, "%s%s contains %s byte(s)%s",
1376 xpre, VG_(get_error_string)(err), s, xpost);
1377
njn9e63cb62005-05-08 18:34:59 +00001378 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1379 break;
1380
1381 }
1382
1383 case ValueErr:
1384 if (err_extra->size == 0) {
sewardj71bc3cb2005-05-19 00:25:45 +00001385 if (VG_(clo_xml))
1386 VG_(message)(Vg_UserMsg, " <kind>UninitCondition</kind>");
1387 VG_(message)(Vg_UserMsg, "%sConditional jump or move depends"
1388 " on uninitialised value(s)%s",
1389 xpre, xpost);
njn9e63cb62005-05-08 18:34:59 +00001390 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001391 if (VG_(clo_xml))
1392 VG_(message)(Vg_UserMsg, " <kind>UninitValue</kind>");
1393 VG_(message)(Vg_UserMsg,
1394 "%sUse of uninitialised value of size %d%s",
1395 xpre, err_extra->size, xpost);
njn9e63cb62005-05-08 18:34:59 +00001396 }
1397 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1398 break;
1399
1400 case ParamErr: {
1401 Bool isReg = ( Register == err_extra->addrinfo.akind );
1402 Char* s1 = ( isReg ? "contains" : "points to" );
1403 Char* s2 = ( err_extra->isUnaddr ? "unaddressable" : "uninitialised" );
1404 if (isReg) tl_assert(!err_extra->isUnaddr);
1405
sewardj71bc3cb2005-05-19 00:25:45 +00001406 if (VG_(clo_xml))
1407 VG_(message)(Vg_UserMsg, " <kind>SyscallParam</kind>");
1408 VG_(message)(Vg_UserMsg, "%sSyscall param %s %s %s byte(s)%s",
1409 xpre, VG_(get_error_string)(err), s1, s2, xpost);
njn9e63cb62005-05-08 18:34:59 +00001410
1411 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1412 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
1413 break;
1414 }
1415 case UserErr: {
1416 Char* s = ( err_extra->isUnaddr ? "Unaddressable" : "Uninitialised" );
1417
sewardj71bc3cb2005-05-19 00:25:45 +00001418 if (VG_(clo_xml))
1419 VG_(message)(Vg_UserMsg, " <kind>ClientCheck</kind>");
njn9e63cb62005-05-08 18:34:59 +00001420 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001421 "%s%s byte(s) found during client check request%s",
1422 xpre, s, xpost);
njn9e63cb62005-05-08 18:34:59 +00001423
1424 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1425 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
1426 break;
1427 }
1428 default:
1429 MAC_(pp_shared_Error)(err);
1430 break;
1431 }
1432}
1433
1434/*------------------------------------------------------------*/
1435/*--- Recording errors ---*/
1436/*------------------------------------------------------------*/
1437
njn02bc4b82005-05-15 17:28:26 +00001438/* Creates a copy of the 'extra' part, updates the copy with address info if
njn9e63cb62005-05-08 18:34:59 +00001439 necessary, and returns the copy. */
1440/* This one called from generated code and non-generated code. */
njn96364822005-05-08 19:04:53 +00001441static void mc_record_value_error ( ThreadId tid, Int size )
njn9e63cb62005-05-08 18:34:59 +00001442{
1443 MAC_Error err_extra;
1444
1445 MAC_(clear_MAC_Error)( &err_extra );
1446 err_extra.size = size;
1447 err_extra.isUnaddr = False;
1448 VG_(maybe_record_error)( tid, ValueErr, /*addr*/0, /*s*/NULL, &err_extra );
1449}
1450
1451/* This called from non-generated code */
1452
njn96364822005-05-08 19:04:53 +00001453static void mc_record_user_error ( ThreadId tid, Addr a, Bool isWrite,
1454 Bool isUnaddr )
njn9e63cb62005-05-08 18:34:59 +00001455{
1456 MAC_Error err_extra;
1457
1458 tl_assert(VG_INVALID_THREADID != tid);
1459 MAC_(clear_MAC_Error)( &err_extra );
1460 err_extra.addrinfo.akind = Undescribed;
1461 err_extra.isUnaddr = isUnaddr;
1462 VG_(maybe_record_error)( tid, UserErr, a, /*s*/NULL, &err_extra );
1463}
1464
1465/*------------------------------------------------------------*/
1466/*--- Suppressions ---*/
1467/*------------------------------------------------------------*/
1468
njn51d827b2005-05-09 01:02:08 +00001469static Bool mc_recognised_suppression ( Char* name, Supp* su )
njn9e63cb62005-05-08 18:34:59 +00001470{
1471 SuppKind skind;
1472
1473 if (MAC_(shared_recognised_suppression)(name, su))
1474 return True;
1475
1476 /* Extra suppressions not used by Addrcheck */
1477 else if (VG_STREQ(name, "Cond")) skind = Value0Supp;
1478 else if (VG_STREQ(name, "Value0")) skind = Value0Supp;/* backwards compat */
1479 else if (VG_STREQ(name, "Value1")) skind = Value1Supp;
1480 else if (VG_STREQ(name, "Value2")) skind = Value2Supp;
1481 else if (VG_STREQ(name, "Value4")) skind = Value4Supp;
1482 else if (VG_STREQ(name, "Value8")) skind = Value8Supp;
1483 else if (VG_STREQ(name, "Value16")) skind = Value16Supp;
1484 else
1485 return False;
1486
1487 VG_(set_supp_kind)(su, skind);
1488 return True;
1489}
1490
1491/*------------------------------------------------------------*/
sewardjc859fbf2005-04-22 21:10:28 +00001492/*--- Functions called directly from generated code: ---*/
1493/*--- Load/store handlers. ---*/
sewardj6cf40ff2005-04-20 22:31:26 +00001494/*------------------------------------------------------------*/
1495
1496/* Types: LOADV4, LOADV2, LOADV1 are:
1497 UWord fn ( Addr a )
1498 so they return 32-bits on 32-bit machines and 64-bits on
1499 64-bit machines. Addr has the same size as a host word.
1500
1501 LOADV8 is always ULong fn ( Addr a )
1502
1503 Similarly for STOREV1, STOREV2, STOREV4, the supplied vbits
1504 are a UWord, and for STOREV8 they are a ULong.
1505*/
1506
sewardj95448072004-11-22 20:19:51 +00001507/* ------------------------ Size = 8 ------------------------ */
1508
sewardj8cf88b72005-07-08 01:29:33 +00001509#define MAKE_LOADV8(nAME,iS_BIGENDIAN) \
1510 \
1511 VG_REGPARM(1) \
1512 ULong nAME ( Addr aA ) \
1513 { \
sewardjae986ca2005-10-12 12:53:20 +00001514 UWord mask, a, sec_no, v_off, a_off, abits; \
1515 SecMap* sm; \
1516 \
sewardj8cf88b72005-07-08 01:29:33 +00001517 PROF_EVENT(200, #nAME); \
1518 \
1519 if (VG_DEBUG_MEMORY >= 2) \
1520 return mc_LOADVn_slow( aA, 8, iS_BIGENDIAN ); \
1521 \
sewardjae986ca2005-10-12 12:53:20 +00001522 mask = ~((0x10000-8) | ((N_PRIMARY_MAP-1) << 16)); \
1523 a = (UWord)aA; \
sewardj8cf88b72005-07-08 01:29:33 +00001524 \
1525 /* If any part of 'a' indicated by the mask is 1, either */ \
1526 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1527 /* covered by the primary map. Either way we defer to the */ \
1528 /* slow-path case. */ \
1529 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1530 PROF_EVENT(201, #nAME"-slow1"); \
1531 return (UWord)mc_LOADVn_slow( aA, 8, iS_BIGENDIAN ); \
1532 } \
1533 \
sewardjae986ca2005-10-12 12:53:20 +00001534 sec_no = (UWord)(a >> 16); \
sewardj8cf88b72005-07-08 01:29:33 +00001535 \
1536 if (VG_DEBUG_MEMORY >= 1) \
1537 tl_assert(sec_no < N_PRIMARY_MAP); \
1538 \
sewardjae986ca2005-10-12 12:53:20 +00001539 sm = primary_map[sec_no]; \
1540 v_off = a & 0xFFFF; \
1541 a_off = v_off >> 3; \
1542 abits = (UWord)(sm->abits[a_off]); \
sewardj8cf88b72005-07-08 01:29:33 +00001543 \
1544 if (EXPECTED_TAKEN(abits == VGM_BYTE_VALID)) { \
1545 /* Handle common case quickly: a is suitably aligned, */ \
1546 /* is mapped, and is addressible. */ \
1547 return ((ULong*)(sm->vbyte))[ v_off >> 3 ]; \
1548 } else { \
1549 /* Slow but general case. */ \
1550 PROF_EVENT(202, #nAME"-slow2"); \
1551 return mc_LOADVn_slow( a, 8, iS_BIGENDIAN ); \
1552 } \
sewardjf9d81612005-04-23 23:25:49 +00001553 }
1554
sewardj8cf88b72005-07-08 01:29:33 +00001555MAKE_LOADV8( MC_(helperc_LOADV8be), True /*bigendian*/ );
1556MAKE_LOADV8( MC_(helperc_LOADV8le), False/*littleendian*/ );
sewardjf9d81612005-04-23 23:25:49 +00001557
sewardjf9d81612005-04-23 23:25:49 +00001558
sewardj8cf88b72005-07-08 01:29:33 +00001559#define MAKE_STOREV8(nAME,iS_BIGENDIAN) \
1560 \
1561 VG_REGPARM(1) \
1562 void nAME ( Addr aA, ULong vbytes ) \
1563 { \
sewardjae986ca2005-10-12 12:53:20 +00001564 UWord mask, a, sec_no, v_off, a_off, abits; \
1565 SecMap* sm; \
1566 \
sewardj8cf88b72005-07-08 01:29:33 +00001567 PROF_EVENT(210, #nAME); \
1568 \
1569 if (VG_DEBUG_MEMORY >= 2) \
1570 mc_STOREVn_slow( aA, 8, vbytes, iS_BIGENDIAN ); \
1571 \
sewardjae986ca2005-10-12 12:53:20 +00001572 mask = ~((0x10000-8) | ((N_PRIMARY_MAP-1) << 16)); \
1573 a = (UWord)aA; \
sewardj8cf88b72005-07-08 01:29:33 +00001574 \
1575 /* If any part of 'a' indicated by the mask is 1, either */ \
1576 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1577 /* covered by the primary map. Either way we defer to the */ \
1578 /* slow-path case. */ \
1579 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1580 PROF_EVENT(211, #nAME"-slow1"); \
1581 mc_STOREVn_slow( aA, 8, vbytes, iS_BIGENDIAN ); \
1582 return; \
1583 } \
1584 \
sewardjae986ca2005-10-12 12:53:20 +00001585 sec_no = (UWord)(a >> 16); \
sewardj8cf88b72005-07-08 01:29:33 +00001586 \
1587 if (VG_DEBUG_MEMORY >= 1) \
1588 tl_assert(sec_no < N_PRIMARY_MAP); \
1589 \
sewardjae986ca2005-10-12 12:53:20 +00001590 sm = primary_map[sec_no]; \
1591 v_off = a & 0xFFFF; \
1592 a_off = v_off >> 3; \
1593 abits = (UWord)(sm->abits[a_off]); \
sewardj8cf88b72005-07-08 01:29:33 +00001594 \
1595 if (EXPECTED_TAKEN(!is_distinguished_sm(sm) \
1596 && abits == VGM_BYTE_VALID)) { \
1597 /* Handle common case quickly: a is suitably aligned, */ \
1598 /* is mapped, and is addressible. */ \
1599 ((ULong*)(sm->vbyte))[ v_off >> 3 ] = vbytes; \
1600 } else { \
1601 /* Slow but general case. */ \
1602 PROF_EVENT(212, #nAME"-slow2"); \
1603 mc_STOREVn_slow( aA, 8, vbytes, iS_BIGENDIAN ); \
1604 } \
sewardjf9d81612005-04-23 23:25:49 +00001605 }
1606
sewardj8cf88b72005-07-08 01:29:33 +00001607MAKE_STOREV8( MC_(helperc_STOREV8be), True /*bigendian*/ );
1608MAKE_STOREV8( MC_(helperc_STOREV8le), False/*littleendian*/ );
sewardj95448072004-11-22 20:19:51 +00001609
sewardj95448072004-11-22 20:19:51 +00001610
1611/* ------------------------ Size = 4 ------------------------ */
1612
sewardj8cf88b72005-07-08 01:29:33 +00001613#define MAKE_LOADV4(nAME,iS_BIGENDIAN) \
1614 \
1615 VG_REGPARM(1) \
1616 UWord nAME ( Addr aA ) \
1617 { \
sewardjae986ca2005-10-12 12:53:20 +00001618 UWord mask, a, sec_no, v_off, a_off, abits; \
1619 SecMap* sm; \
1620 \
sewardj8cf88b72005-07-08 01:29:33 +00001621 PROF_EVENT(220, #nAME); \
1622 \
1623 if (VG_DEBUG_MEMORY >= 2) \
1624 return (UWord)mc_LOADVn_slow( aA, 4, iS_BIGENDIAN ); \
1625 \
sewardjae986ca2005-10-12 12:53:20 +00001626 mask = ~((0x10000-4) | ((N_PRIMARY_MAP-1) << 16)); \
1627 a = (UWord)aA; \
sewardj8cf88b72005-07-08 01:29:33 +00001628 \
1629 /* If any part of 'a' indicated by the mask is 1, either */ \
1630 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1631 /* covered by the primary map. Either way we defer to the */ \
1632 /* slow-path case. */ \
1633 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1634 PROF_EVENT(221, #nAME"-slow1"); \
1635 return (UWord)mc_LOADVn_slow( aA, 4, iS_BIGENDIAN ); \
1636 } \
1637 \
sewardjae986ca2005-10-12 12:53:20 +00001638 sec_no = (UWord)(a >> 16); \
sewardj8cf88b72005-07-08 01:29:33 +00001639 \
1640 if (VG_DEBUG_MEMORY >= 1) \
1641 tl_assert(sec_no < N_PRIMARY_MAP); \
1642 \
sewardjae986ca2005-10-12 12:53:20 +00001643 sm = primary_map[sec_no]; \
1644 v_off = a & 0xFFFF; \
1645 a_off = v_off >> 3; \
1646 abits = (UWord)(sm->abits[a_off]); \
sewardj8cf88b72005-07-08 01:29:33 +00001647 abits >>= (a & 4); \
1648 abits &= 15; \
1649 if (EXPECTED_TAKEN(abits == VGM_NIBBLE_VALID)) { \
1650 /* Handle common case quickly: a is suitably aligned, */ \
1651 /* is mapped, and is addressible. */ \
1652 /* On a 32-bit platform, simply hoick the required 32 */ \
1653 /* bits out of the vbyte array. On a 64-bit platform, */ \
1654 /* also set the upper 32 bits to 1 ("undefined"), just */ \
1655 /* in case. This almost certainly isn't necessary, */ \
1656 /* but be paranoid. */ \
1657 UWord ret = (UWord)0xFFFFFFFF00000000ULL; \
1658 ret |= (UWord)( ((UInt*)(sm->vbyte))[ v_off >> 2 ] ); \
1659 return ret; \
1660 } else { \
1661 /* Slow but general case. */ \
1662 PROF_EVENT(222, #nAME"-slow2"); \
1663 return (UWord)mc_LOADVn_slow( a, 4, iS_BIGENDIAN ); \
1664 } \
sewardjc1a2cda2005-04-21 17:34:00 +00001665 }
1666
sewardj8cf88b72005-07-08 01:29:33 +00001667MAKE_LOADV4( MC_(helperc_LOADV4be), True /*bigendian*/ );
1668MAKE_LOADV4( MC_(helperc_LOADV4le), False/*littleendian*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001669
sewardjc1a2cda2005-04-21 17:34:00 +00001670
sewardj8cf88b72005-07-08 01:29:33 +00001671#define MAKE_STOREV4(nAME,iS_BIGENDIAN) \
1672 \
1673 VG_REGPARM(2) \
1674 void nAME ( Addr aA, UWord vbytes ) \
1675 { \
sewardjae986ca2005-10-12 12:53:20 +00001676 UWord mask, a, sec_no, v_off, a_off, abits; \
1677 SecMap* sm; \
1678 \
sewardj8cf88b72005-07-08 01:29:33 +00001679 PROF_EVENT(230, #nAME); \
1680 \
1681 if (VG_DEBUG_MEMORY >= 2) \
1682 mc_STOREVn_slow( aA, 4, (ULong)vbytes, iS_BIGENDIAN ); \
1683 \
sewardjae986ca2005-10-12 12:53:20 +00001684 mask = ~((0x10000-4) | ((N_PRIMARY_MAP-1) << 16)); \
1685 a = (UWord)aA; \
sewardj8cf88b72005-07-08 01:29:33 +00001686 \
1687 /* If any part of 'a' indicated by the mask is 1, either */ \
1688 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1689 /* covered by the primary map. Either way we defer to the */ \
1690 /* slow-path case. */ \
1691 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1692 PROF_EVENT(231, #nAME"-slow1"); \
1693 mc_STOREVn_slow( aA, 4, (ULong)vbytes, iS_BIGENDIAN ); \
1694 return; \
1695 } \
1696 \
sewardjae986ca2005-10-12 12:53:20 +00001697 sec_no = (UWord)(a >> 16); \
sewardj8cf88b72005-07-08 01:29:33 +00001698 \
1699 if (VG_DEBUG_MEMORY >= 1) \
1700 tl_assert(sec_no < N_PRIMARY_MAP); \
1701 \
sewardjae986ca2005-10-12 12:53:20 +00001702 sm = primary_map[sec_no]; \
1703 v_off = a & 0xFFFF; \
1704 a_off = v_off >> 3; \
1705 abits = (UWord)(sm->abits[a_off]); \
sewardj8cf88b72005-07-08 01:29:33 +00001706 abits >>= (a & 4); \
1707 abits &= 15; \
1708 if (EXPECTED_TAKEN(!is_distinguished_sm(sm) \
1709 && abits == VGM_NIBBLE_VALID)) { \
1710 /* Handle common case quickly: a is suitably aligned, */ \
1711 /* is mapped, and is addressible. */ \
1712 ((UInt*)(sm->vbyte))[ v_off >> 2 ] = (UInt)vbytes; \
1713 } else { \
1714 /* Slow but general case. */ \
1715 PROF_EVENT(232, #nAME"-slow2"); \
1716 mc_STOREVn_slow( aA, 4, (ULong)vbytes, iS_BIGENDIAN ); \
1717 } \
sewardjc1a2cda2005-04-21 17:34:00 +00001718 }
1719
sewardj8cf88b72005-07-08 01:29:33 +00001720MAKE_STOREV4( MC_(helperc_STOREV4be), True /*bigendian*/ );
1721MAKE_STOREV4( MC_(helperc_STOREV4le), False/*littleendian*/ );
njn25e49d8e72002-09-23 09:36:25 +00001722
njn25e49d8e72002-09-23 09:36:25 +00001723
sewardj95448072004-11-22 20:19:51 +00001724/* ------------------------ Size = 2 ------------------------ */
1725
sewardj8cf88b72005-07-08 01:29:33 +00001726#define MAKE_LOADV2(nAME,iS_BIGENDIAN) \
1727 \
1728 VG_REGPARM(1) \
1729 UWord nAME ( Addr aA ) \
1730 { \
sewardjae986ca2005-10-12 12:53:20 +00001731 UWord mask, a, sec_no, v_off, a_off, abits; \
1732 SecMap* sm; \
1733 \
sewardj8cf88b72005-07-08 01:29:33 +00001734 PROF_EVENT(240, #nAME); \
1735 \
1736 if (VG_DEBUG_MEMORY >= 2) \
1737 return (UWord)mc_LOADVn_slow( aA, 2, iS_BIGENDIAN ); \
1738 \
sewardjae986ca2005-10-12 12:53:20 +00001739 mask = ~((0x10000-2) | ((N_PRIMARY_MAP-1) << 16)); \
1740 a = (UWord)aA; \
sewardj8cf88b72005-07-08 01:29:33 +00001741 \
1742 /* If any part of 'a' indicated by the mask is 1, either */ \
1743 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1744 /* covered by the primary map. Either way we defer to the */ \
1745 /* slow-path case. */ \
1746 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1747 PROF_EVENT(241, #nAME"-slow1"); \
1748 return (UWord)mc_LOADVn_slow( aA, 2, iS_BIGENDIAN ); \
1749 } \
1750 \
sewardjae986ca2005-10-12 12:53:20 +00001751 sec_no = (UWord)(a >> 16); \
sewardj8cf88b72005-07-08 01:29:33 +00001752 \
1753 if (VG_DEBUG_MEMORY >= 1) \
1754 tl_assert(sec_no < N_PRIMARY_MAP); \
1755 \
sewardjae986ca2005-10-12 12:53:20 +00001756 sm = primary_map[sec_no]; \
1757 v_off = a & 0xFFFF; \
1758 a_off = v_off >> 3; \
1759 abits = (UWord)(sm->abits[a_off]); \
sewardj8cf88b72005-07-08 01:29:33 +00001760 if (EXPECTED_TAKEN(abits == VGM_BYTE_VALID)) { \
1761 /* Handle common case quickly: a is mapped, and the */ \
1762 /* entire word32 it lives in is addressible. */ \
1763 /* Set the upper 16/48 bits of the result to 1 */ \
1764 /* ("undefined"), just in case. This almost certainly */ \
1765 /* isn't necessary, but be paranoid. */ \
1766 return (~(UWord)0xFFFF) \
1767 | \
1768 (UWord)( ((UShort*)(sm->vbyte))[ v_off >> 1 ] ); \
1769 } else { \
1770 /* Slow but general case. */ \
1771 PROF_EVENT(242, #nAME"-slow2"); \
1772 return (UWord)mc_LOADVn_slow( aA, 2, iS_BIGENDIAN ); \
1773 } \
sewardjc1a2cda2005-04-21 17:34:00 +00001774 }
1775
sewardj8cf88b72005-07-08 01:29:33 +00001776MAKE_LOADV2( MC_(helperc_LOADV2be), True /*bigendian*/ );
1777MAKE_LOADV2( MC_(helperc_LOADV2le), False/*littleendian*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001778
sewardjc1a2cda2005-04-21 17:34:00 +00001779
sewardj8cf88b72005-07-08 01:29:33 +00001780#define MAKE_STOREV2(nAME,iS_BIGENDIAN) \
1781 \
1782 VG_REGPARM(2) \
1783 void nAME ( Addr aA, UWord vbytes ) \
1784 { \
sewardjae986ca2005-10-12 12:53:20 +00001785 UWord mask, a, sec_no, v_off, a_off, abits; \
1786 SecMap* sm; \
1787 \
sewardj8cf88b72005-07-08 01:29:33 +00001788 PROF_EVENT(250, #nAME); \
1789 \
1790 if (VG_DEBUG_MEMORY >= 2) \
1791 mc_STOREVn_slow( aA, 2, (ULong)vbytes, iS_BIGENDIAN ); \
1792 \
sewardjae986ca2005-10-12 12:53:20 +00001793 mask = ~((0x10000-2) | ((N_PRIMARY_MAP-1) << 16)); \
1794 a = (UWord)aA; \
sewardj8cf88b72005-07-08 01:29:33 +00001795 \
1796 /* If any part of 'a' indicated by the mask is 1, either */ \
1797 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1798 /* covered by the primary map. Either way we defer to the */ \
1799 /* slow-path case. */ \
1800 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1801 PROF_EVENT(251, #nAME"-slow1"); \
1802 mc_STOREVn_slow( aA, 2, (ULong)vbytes, iS_BIGENDIAN ); \
1803 return; \
1804 } \
1805 \
sewardjae986ca2005-10-12 12:53:20 +00001806 sec_no = (UWord)(a >> 16); \
sewardj8cf88b72005-07-08 01:29:33 +00001807 \
1808 if (VG_DEBUG_MEMORY >= 1) \
1809 tl_assert(sec_no < N_PRIMARY_MAP); \
1810 \
sewardjae986ca2005-10-12 12:53:20 +00001811 sm = primary_map[sec_no]; \
1812 v_off = a & 0xFFFF; \
1813 a_off = v_off >> 3; \
1814 abits = (UWord)(sm->abits[a_off]); \
sewardj8cf88b72005-07-08 01:29:33 +00001815 if (EXPECTED_TAKEN(!is_distinguished_sm(sm) \
1816 && abits == VGM_BYTE_VALID)) { \
1817 /* Handle common case quickly. */ \
1818 ((UShort*)(sm->vbyte))[ v_off >> 1 ] = (UShort)vbytes; \
1819 } else { \
1820 /* Slow but general case. */ \
1821 PROF_EVENT(252, #nAME"-slow2"); \
1822 mc_STOREVn_slow( aA, 2, (ULong)vbytes, iS_BIGENDIAN ); \
1823 } \
sewardjc1a2cda2005-04-21 17:34:00 +00001824 }
1825
njn25e49d8e72002-09-23 09:36:25 +00001826
sewardj8cf88b72005-07-08 01:29:33 +00001827MAKE_STOREV2( MC_(helperc_STOREV2be), True /*bigendian*/ );
1828MAKE_STOREV2( MC_(helperc_STOREV2le), False/*littleendian*/ );
sewardj5d28efc2005-04-21 22:16:29 +00001829
njn25e49d8e72002-09-23 09:36:25 +00001830
sewardj95448072004-11-22 20:19:51 +00001831/* ------------------------ Size = 1 ------------------------ */
sewardj8cf88b72005-07-08 01:29:33 +00001832/* Note: endianness is irrelevant for size == 1 */
sewardj95448072004-11-22 20:19:51 +00001833
njnaf839f52005-06-23 03:27:57 +00001834VG_REGPARM(1)
sewardj8cf88b72005-07-08 01:29:33 +00001835UWord MC_(helperc_LOADV1) ( Addr aA )
njn25e49d8e72002-09-23 09:36:25 +00001836{
sewardjae986ca2005-10-12 12:53:20 +00001837 UWord mask, a, sec_no, v_off, a_off, abits;
1838 SecMap* sm;
1839
sewardj8cf88b72005-07-08 01:29:33 +00001840 PROF_EVENT(260, "helperc_LOADV1");
sewardjc1a2cda2005-04-21 17:34:00 +00001841
1842# if VG_DEBUG_MEMORY >= 2
sewardj8cf88b72005-07-08 01:29:33 +00001843 return (UWord)mc_LOADVn_slow( aA, 1, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001844# else
1845
sewardjae986ca2005-10-12 12:53:20 +00001846 mask = ~((0x10000-1) | ((N_PRIMARY_MAP-1) << 16));
1847 a = (UWord)aA;
sewardjc1a2cda2005-04-21 17:34:00 +00001848
1849 /* If any part of 'a' indicated by the mask is 1, it means 'a'
1850 exceeds the range covered by the primary map. In which case we
1851 defer to the slow-path case. */
1852 if (EXPECTED_NOT_TAKEN(a & mask)) {
sewardj8cf88b72005-07-08 01:29:33 +00001853 PROF_EVENT(261, "helperc_LOADV1-slow1");
1854 return (UWord)mc_LOADVn_slow( aA, 1, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001855 }
1856
sewardjae986ca2005-10-12 12:53:20 +00001857 sec_no = (UWord)(a >> 16);
sewardjc1a2cda2005-04-21 17:34:00 +00001858
1859# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +00001860 tl_assert(sec_no < N_PRIMARY_MAP);
sewardjc1a2cda2005-04-21 17:34:00 +00001861# endif
1862
sewardjae986ca2005-10-12 12:53:20 +00001863 sm = primary_map[sec_no];
1864 v_off = a & 0xFFFF;
1865 a_off = v_off >> 3;
1866 abits = (UWord)(sm->abits[a_off]);
sewardjc1a2cda2005-04-21 17:34:00 +00001867 if (EXPECTED_TAKEN(abits == VGM_BYTE_VALID)) {
1868 /* Handle common case quickly: a is mapped, and the entire
1869 word32 it lives in is addressible. */
sewardj5d28efc2005-04-21 22:16:29 +00001870 /* Set the upper 24/56 bits of the result to 1 ("undefined"),
1871 just in case. This almost certainly isn't necessary, but be
1872 paranoid. */
sewardjc1a2cda2005-04-21 17:34:00 +00001873 return (~(UWord)0xFF)
1874 |
1875 (UWord)( ((UChar*)(sm->vbyte))[ v_off ] );
1876 } else {
1877 /* Slow but general case. */
sewardj8cf88b72005-07-08 01:29:33 +00001878 PROF_EVENT(262, "helperc_LOADV1-slow2");
1879 return (UWord)mc_LOADVn_slow( aA, 1, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001880 }
1881# endif
njn25e49d8e72002-09-23 09:36:25 +00001882}
1883
sewardjc1a2cda2005-04-21 17:34:00 +00001884
njnaf839f52005-06-23 03:27:57 +00001885VG_REGPARM(2)
sewardj8cf88b72005-07-08 01:29:33 +00001886void MC_(helperc_STOREV1) ( Addr aA, UWord vbyte )
njn25e49d8e72002-09-23 09:36:25 +00001887{
sewardjae986ca2005-10-12 12:53:20 +00001888 UWord mask, a, sec_no, v_off, a_off, abits;
1889 SecMap* sm;
1890
sewardj8cf88b72005-07-08 01:29:33 +00001891 PROF_EVENT(270, "helperc_STOREV1");
sewardjc1a2cda2005-04-21 17:34:00 +00001892
1893# if VG_DEBUG_MEMORY >= 2
sewardj8cf88b72005-07-08 01:29:33 +00001894 mc_STOREVn_slow( aA, 1, (ULong)vbyte, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001895# else
1896
sewardjae986ca2005-10-12 12:53:20 +00001897 mask = ~((0x10000-1) | ((N_PRIMARY_MAP-1) << 16));
1898 a = (UWord)aA;
sewardjc1a2cda2005-04-21 17:34:00 +00001899 /* If any part of 'a' indicated by the mask is 1, it means 'a'
1900 exceeds the range covered by the primary map. In which case we
1901 defer to the slow-path case. */
1902 if (EXPECTED_NOT_TAKEN(a & mask)) {
sewardj8cf88b72005-07-08 01:29:33 +00001903 PROF_EVENT(271, "helperc_STOREV1-slow1");
1904 mc_STOREVn_slow( aA, 1, (ULong)vbyte, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001905 return;
1906 }
1907
sewardjae986ca2005-10-12 12:53:20 +00001908 sec_no = (UWord)(a >> 16);
sewardjc1a2cda2005-04-21 17:34:00 +00001909
1910# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +00001911 tl_assert(sec_no < N_PRIMARY_MAP);
sewardjc1a2cda2005-04-21 17:34:00 +00001912# endif
1913
sewardjae986ca2005-10-12 12:53:20 +00001914 sm = primary_map[sec_no];
1915 v_off = a & 0xFFFF;
1916 a_off = v_off >> 3;
1917 abits = (UWord)(sm->abits[a_off]);
sewardjc1a2cda2005-04-21 17:34:00 +00001918 if (EXPECTED_TAKEN(!is_distinguished_sm(sm)
1919 && abits == VGM_BYTE_VALID)) {
1920 /* Handle common case quickly: a is mapped, the entire word32 it
1921 lives in is addressible. */
1922 ((UChar*)(sm->vbyte))[ v_off ] = (UChar)vbyte;
1923 } else {
sewardj8cf88b72005-07-08 01:29:33 +00001924 PROF_EVENT(272, "helperc_STOREV1-slow2");
1925 mc_STOREVn_slow( aA, 1, (ULong)vbyte, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001926 }
1927
1928# endif
njn25e49d8e72002-09-23 09:36:25 +00001929}
1930
1931
sewardjc859fbf2005-04-22 21:10:28 +00001932/*------------------------------------------------------------*/
1933/*--- Functions called directly from generated code: ---*/
1934/*--- Value-check failure handlers. ---*/
1935/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00001936
njn5c004e42002-11-18 11:04:50 +00001937void MC_(helperc_value_check0_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001938{
njn9e63cb62005-05-08 18:34:59 +00001939 mc_record_value_error ( VG_(get_running_tid)(), 0 );
njn25e49d8e72002-09-23 09:36:25 +00001940}
1941
njn5c004e42002-11-18 11:04:50 +00001942void MC_(helperc_value_check1_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001943{
njn9e63cb62005-05-08 18:34:59 +00001944 mc_record_value_error ( VG_(get_running_tid)(), 1 );
njn25e49d8e72002-09-23 09:36:25 +00001945}
1946
njn5c004e42002-11-18 11:04:50 +00001947void MC_(helperc_value_check4_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001948{
njn9e63cb62005-05-08 18:34:59 +00001949 mc_record_value_error ( VG_(get_running_tid)(), 4 );
njn25e49d8e72002-09-23 09:36:25 +00001950}
1951
sewardj11bcc4e2005-04-23 22:38:38 +00001952void MC_(helperc_value_check8_fail) ( void )
1953{
njn9e63cb62005-05-08 18:34:59 +00001954 mc_record_value_error ( VG_(get_running_tid)(), 8 );
sewardj11bcc4e2005-04-23 22:38:38 +00001955}
1956
njnaf839f52005-06-23 03:27:57 +00001957VG_REGPARM(1) void MC_(helperc_complain_undef) ( HWord sz )
sewardj95448072004-11-22 20:19:51 +00001958{
njn9e63cb62005-05-08 18:34:59 +00001959 mc_record_value_error ( VG_(get_running_tid)(), (Int)sz );
sewardj95448072004-11-22 20:19:51 +00001960}
1961
njn25e49d8e72002-09-23 09:36:25 +00001962
sewardj45d94cc2005-04-20 14:44:11 +00001963//zz /*------------------------------------------------------------*/
1964//zz /*--- Metadata get/set functions, for client requests. ---*/
1965//zz /*------------------------------------------------------------*/
1966//zz
1967//zz /* Copy Vbits for src into vbits. Returns: 1 == OK, 2 == alignment
1968//zz error, 3 == addressing error. */
1969//zz static Int mc_get_or_set_vbits_for_client (
1970//zz ThreadId tid,
1971//zz Addr dataV,
1972//zz Addr vbitsV,
1973//zz SizeT size,
1974//zz Bool setting /* True <=> set vbits, False <=> get vbits */
1975//zz )
1976//zz {
1977//zz Bool addressibleD = True;
1978//zz Bool addressibleV = True;
1979//zz UInt* data = (UInt*)dataV;
1980//zz UInt* vbits = (UInt*)vbitsV;
1981//zz SizeT szW = size / 4; /* sigh */
1982//zz SizeT i;
1983//zz UInt* dataP = NULL; /* bogus init to keep gcc happy */
1984//zz UInt* vbitsP = NULL; /* ditto */
1985//zz
1986//zz /* Check alignment of args. */
1987//zz if (!(VG_IS_4_ALIGNED(data) && VG_IS_4_ALIGNED(vbits)))
1988//zz return 2;
1989//zz if ((size & 3) != 0)
1990//zz return 2;
1991//zz
1992//zz /* Check that arrays are addressible. */
1993//zz for (i = 0; i < szW; i++) {
1994//zz dataP = &data[i];
1995//zz vbitsP = &vbits[i];
1996//zz if (get_abits4_ALIGNED((Addr)dataP) != VGM_NIBBLE_VALID) {
1997//zz addressibleD = False;
1998//zz break;
1999//zz }
2000//zz if (get_abits4_ALIGNED((Addr)vbitsP) != VGM_NIBBLE_VALID) {
2001//zz addressibleV = False;
2002//zz break;
2003//zz }
2004//zz }
2005//zz if (!addressibleD) {
2006//zz MAC_(record_address_error)( tid, (Addr)dataP, 4,
2007//zz setting ? True : False );
2008//zz return 3;
2009//zz }
2010//zz if (!addressibleV) {
2011//zz MAC_(record_address_error)( tid, (Addr)vbitsP, 4,
2012//zz setting ? False : True );
2013//zz return 3;
2014//zz }
2015//zz
2016//zz /* Do the copy */
2017//zz if (setting) {
2018//zz /* setting */
2019//zz for (i = 0; i < szW; i++) {
2020//zz if (get_vbytes4_ALIGNED( (Addr)&vbits[i] ) != VGM_WORD_VALID)
njn9e63cb62005-05-08 18:34:59 +00002021//zz mc_record_value_error(tid, 4);
sewardj45d94cc2005-04-20 14:44:11 +00002022//zz set_vbytes4_ALIGNED( (Addr)&data[i], vbits[i] );
2023//zz }
2024//zz } else {
2025//zz /* getting */
2026//zz for (i = 0; i < szW; i++) {
2027//zz vbits[i] = get_vbytes4_ALIGNED( (Addr)&data[i] );
2028//zz set_vbytes4_ALIGNED( (Addr)&vbits[i], VGM_WORD_VALID );
2029//zz }
2030//zz }
2031//zz
2032//zz return 1;
2033//zz }
sewardj05fe85e2005-04-27 22:46:36 +00002034
2035
2036/*------------------------------------------------------------*/
2037/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
2038/*------------------------------------------------------------*/
2039
2040/* For the memory leak detector, say whether an entire 64k chunk of
2041 address space is possibly in use, or not. If in doubt return
2042 True.
2043*/
2044static
2045Bool mc_is_within_valid_secondary ( Addr a )
2046{
2047 SecMap* sm = maybe_get_secmap_for ( a );
2048 if (sm == NULL || sm == &sm_distinguished[SM_DIST_NOACCESS]) {
2049 /* Definitely not in use. */
2050 return False;
2051 } else {
2052 return True;
2053 }
2054}
2055
2056
2057/* For the memory leak detector, say whether or not a given word
2058 address is to be regarded as valid. */
2059static
2060Bool mc_is_valid_aligned_word ( Addr a )
2061{
2062 tl_assert(sizeof(UWord) == 4 || sizeof(UWord) == 8);
2063 if (sizeof(UWord) == 4) {
2064 tl_assert(VG_IS_4_ALIGNED(a));
2065 } else {
2066 tl_assert(VG_IS_8_ALIGNED(a));
2067 }
2068 if (mc_check_readable( a, sizeof(UWord), NULL ) == MC_Ok) {
2069 return True;
2070 } else {
2071 return False;
2072 }
2073}
sewardja4495682002-10-21 07:29:59 +00002074
2075
nethercote996901a2004-08-03 13:29:09 +00002076/* Leak detector for this tool. We don't actually do anything, merely
sewardja4495682002-10-21 07:29:59 +00002077 run the generic leak detector with suitable parameters for this
nethercote996901a2004-08-03 13:29:09 +00002078 tool. */
njnb8dca862005-03-14 02:42:44 +00002079static void mc_detect_memory_leaks ( ThreadId tid, LeakCheckMode mode )
njn25e49d8e72002-09-23 09:36:25 +00002080{
sewardj05fe85e2005-04-27 22:46:36 +00002081 MAC_(do_detect_memory_leaks) (
2082 tid,
2083 mode,
2084 mc_is_within_valid_secondary,
2085 mc_is_valid_aligned_word
2086 );
njn25e49d8e72002-09-23 09:36:25 +00002087}
2088
2089
sewardjc859fbf2005-04-22 21:10:28 +00002090/*------------------------------------------------------------*/
2091/*--- Initialisation ---*/
2092/*------------------------------------------------------------*/
2093
2094static void init_shadow_memory ( void )
2095{
2096 Int i;
2097 SecMap* sm;
2098
2099 /* Build the 3 distinguished secondaries */
2100 tl_assert(VGM_BIT_INVALID == 1);
2101 tl_assert(VGM_BIT_VALID == 0);
2102 tl_assert(VGM_BYTE_INVALID == 0xFF);
2103 tl_assert(VGM_BYTE_VALID == 0);
2104
2105 /* Set A invalid, V invalid. */
2106 sm = &sm_distinguished[SM_DIST_NOACCESS];
2107 for (i = 0; i < 65536; i++)
2108 sm->vbyte[i] = VGM_BYTE_INVALID;
2109 for (i = 0; i < 8192; i++)
2110 sm->abits[i] = VGM_BYTE_INVALID;
2111
2112 /* Set A valid, V invalid. */
2113 sm = &sm_distinguished[SM_DIST_ACCESS_UNDEFINED];
2114 for (i = 0; i < 65536; i++)
2115 sm->vbyte[i] = VGM_BYTE_INVALID;
2116 for (i = 0; i < 8192; i++)
2117 sm->abits[i] = VGM_BYTE_VALID;
2118
2119 /* Set A valid, V valid. */
2120 sm = &sm_distinguished[SM_DIST_ACCESS_DEFINED];
2121 for (i = 0; i < 65536; i++)
2122 sm->vbyte[i] = VGM_BYTE_VALID;
2123 for (i = 0; i < 8192; i++)
2124 sm->abits[i] = VGM_BYTE_VALID;
2125
2126 /* Set up the primary map. */
2127 /* These entries gradually get overwritten as the used address
2128 space expands. */
2129 for (i = 0; i < N_PRIMARY_MAP; i++)
2130 primary_map[i] = &sm_distinguished[SM_DIST_NOACCESS];
2131
2132 /* auxmap_size = auxmap_used = 0;
2133 no ... these are statically initialised */
2134}
2135
2136
2137/*------------------------------------------------------------*/
2138/*--- Sanity check machinery (permanently engaged) ---*/
2139/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00002140
njn51d827b2005-05-09 01:02:08 +00002141static Bool mc_cheap_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00002142{
jseward9800fd32004-01-04 23:08:04 +00002143 /* nothing useful we can rapidly check */
sewardj23eb2fd2005-04-22 16:29:19 +00002144 n_sanity_cheap++;
sewardjc1a2cda2005-04-21 17:34:00 +00002145 PROF_EVENT(490, "cheap_sanity_check");
jseward9800fd32004-01-04 23:08:04 +00002146 return True;
njn25e49d8e72002-09-23 09:36:25 +00002147}
2148
njn51d827b2005-05-09 01:02:08 +00002149static Bool mc_expensive_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00002150{
sewardj23eb2fd2005-04-22 16:29:19 +00002151 Int i, n_secmaps_found;
sewardj45d94cc2005-04-20 14:44:11 +00002152 SecMap* sm;
sewardj23eb2fd2005-04-22 16:29:19 +00002153 Bool bad = False;
njn25e49d8e72002-09-23 09:36:25 +00002154
sewardj23eb2fd2005-04-22 16:29:19 +00002155 n_sanity_expensive++;
sewardjc1a2cda2005-04-21 17:34:00 +00002156 PROF_EVENT(491, "expensive_sanity_check");
2157
sewardj23eb2fd2005-04-22 16:29:19 +00002158 /* Check that the 3 distinguished SMs are still as they should
2159 be. */
njn25e49d8e72002-09-23 09:36:25 +00002160
sewardj45d94cc2005-04-20 14:44:11 +00002161 /* Check A invalid, V invalid. */
2162 sm = &sm_distinguished[SM_DIST_NOACCESS];
njn25e49d8e72002-09-23 09:36:25 +00002163 for (i = 0; i < 65536; i++)
sewardj45d94cc2005-04-20 14:44:11 +00002164 if (!(sm->vbyte[i] == VGM_BYTE_INVALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002165 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00002166 for (i = 0; i < 8192; i++)
2167 if (!(sm->abits[i] == VGM_BYTE_INVALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002168 bad = True;
njn25e49d8e72002-09-23 09:36:25 +00002169
sewardj45d94cc2005-04-20 14:44:11 +00002170 /* Check A valid, V invalid. */
2171 sm = &sm_distinguished[SM_DIST_ACCESS_UNDEFINED];
2172 for (i = 0; i < 65536; i++)
2173 if (!(sm->vbyte[i] == VGM_BYTE_INVALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002174 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00002175 for (i = 0; i < 8192; i++)
2176 if (!(sm->abits[i] == VGM_BYTE_VALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002177 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00002178
2179 /* Check A valid, V valid. */
2180 sm = &sm_distinguished[SM_DIST_ACCESS_DEFINED];
2181 for (i = 0; i < 65536; i++)
2182 if (!(sm->vbyte[i] == VGM_BYTE_VALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002183 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00002184 for (i = 0; i < 8192; i++)
2185 if (!(sm->abits[i] == VGM_BYTE_VALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002186 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00002187
sewardj23eb2fd2005-04-22 16:29:19 +00002188 if (bad) {
2189 VG_(printf)("memcheck expensive sanity: "
2190 "distinguished_secondaries have changed\n");
2191 return False;
2192 }
2193
2194 /* check nonsensical auxmap sizing */
sewardj45d94cc2005-04-20 14:44:11 +00002195 if (auxmap_used > auxmap_size)
sewardj23eb2fd2005-04-22 16:29:19 +00002196 bad = True;
2197
2198 if (bad) {
2199 VG_(printf)("memcheck expensive sanity: "
2200 "nonsensical auxmap sizing\n");
2201 return False;
2202 }
2203
2204 /* check that the number of secmaps issued matches the number that
2205 are reachable (iow, no secmap leaks) */
2206 n_secmaps_found = 0;
2207 for (i = 0; i < N_PRIMARY_MAP; i++) {
2208 if (primary_map[i] == NULL) {
2209 bad = True;
2210 } else {
2211 if (!is_distinguished_sm(primary_map[i]))
2212 n_secmaps_found++;
2213 }
2214 }
2215
2216 for (i = 0; i < auxmap_used; i++) {
2217 if (auxmap[i].sm == NULL) {
2218 bad = True;
2219 } else {
2220 if (!is_distinguished_sm(auxmap[i].sm))
2221 n_secmaps_found++;
2222 }
2223 }
2224
2225 if (n_secmaps_found != n_secmaps_issued)
2226 bad = True;
2227
2228 if (bad) {
2229 VG_(printf)("memcheck expensive sanity: "
2230 "apparent secmap leakage\n");
2231 return False;
2232 }
2233
2234 /* check that auxmap only covers address space that the primary
2235 doesn't */
2236
2237 for (i = 0; i < auxmap_used; i++)
2238 if (auxmap[i].base <= MAX_PRIMARY_ADDRESS)
2239 bad = True;
2240
2241 if (bad) {
2242 VG_(printf)("memcheck expensive sanity: "
2243 "auxmap covers wrong address space\n");
2244 return False;
2245 }
2246
2247 /* there is only one pointer to each secmap (expensive) */
njn25e49d8e72002-09-23 09:36:25 +00002248
2249 return True;
2250}
sewardj45d94cc2005-04-20 14:44:11 +00002251
njn25e49d8e72002-09-23 09:36:25 +00002252
njn25e49d8e72002-09-23 09:36:25 +00002253/*------------------------------------------------------------*/
njnd3040452003-05-19 15:04:06 +00002254/*--- Command line args ---*/
njn25e49d8e72002-09-23 09:36:25 +00002255/*------------------------------------------------------------*/
2256
njn51d827b2005-05-09 01:02:08 +00002257Bool MC_(clo_avoid_strlen_errors) = True;
njn43c799e2003-04-08 00:08:52 +00002258
njn51d827b2005-05-09 01:02:08 +00002259static Bool mc_process_cmd_line_option(Char* arg)
njn25e49d8e72002-09-23 09:36:25 +00002260{
njn45270a22005-03-27 01:00:11 +00002261 VG_BOOL_CLO(arg, "--avoid-strlen-errors", MC_(clo_avoid_strlen_errors))
njn25e49d8e72002-09-23 09:36:25 +00002262 else
njn43c799e2003-04-08 00:08:52 +00002263 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00002264
2265 return True;
njn25e49d8e72002-09-23 09:36:25 +00002266}
2267
njn51d827b2005-05-09 01:02:08 +00002268static void mc_print_usage(void)
njn25e49d8e72002-09-23 09:36:25 +00002269{
njn3e884182003-04-15 13:03:23 +00002270 MAC_(print_common_usage)();
2271 VG_(printf)(
2272" --avoid-strlen-errors=no|yes suppress errs from inlined strlen [yes]\n"
2273 );
2274}
2275
njn51d827b2005-05-09 01:02:08 +00002276static void mc_print_debug_usage(void)
njn3e884182003-04-15 13:03:23 +00002277{
2278 MAC_(print_common_debug_usage)();
2279 VG_(printf)(
sewardj8ec2cfc2002-10-13 00:57:26 +00002280" --cleanup=no|yes improve after instrumentation? [yes]\n"
njn3e884182003-04-15 13:03:23 +00002281 );
njn25e49d8e72002-09-23 09:36:25 +00002282}
2283
nethercote8b76fe52004-11-08 19:20:09 +00002284/*------------------------------------------------------------*/
2285/*--- Client requests ---*/
2286/*------------------------------------------------------------*/
2287
2288/* Client block management:
2289
2290 This is managed as an expanding array of client block descriptors.
2291 Indices of live descriptors are issued to the client, so it can ask
2292 to free them later. Therefore we cannot slide live entries down
2293 over dead ones. Instead we must use free/inuse flags and scan for
2294 an empty slot at allocation time. This in turn means allocation is
2295 relatively expensive, so we hope this does not happen too often.
nethercote8b76fe52004-11-08 19:20:09 +00002296
sewardjedc75ab2005-03-15 23:30:32 +00002297 An unused block has start == size == 0
2298*/
nethercote8b76fe52004-11-08 19:20:09 +00002299
2300typedef
2301 struct {
2302 Addr start;
2303 SizeT size;
2304 ExeContext* where;
sewardj8cf88b72005-07-08 01:29:33 +00002305 Char* desc;
nethercote8b76fe52004-11-08 19:20:09 +00002306 }
2307 CGenBlock;
2308
2309/* This subsystem is self-initialising. */
njn695c16e2005-03-27 03:40:28 +00002310static UInt cgb_size = 0;
2311static UInt cgb_used = 0;
2312static CGenBlock* cgbs = NULL;
nethercote8b76fe52004-11-08 19:20:09 +00002313
2314/* Stats for this subsystem. */
njn695c16e2005-03-27 03:40:28 +00002315static UInt cgb_used_MAX = 0; /* Max in use. */
2316static UInt cgb_allocs = 0; /* Number of allocs. */
2317static UInt cgb_discards = 0; /* Number of discards. */
2318static UInt cgb_search = 0; /* Number of searches. */
nethercote8b76fe52004-11-08 19:20:09 +00002319
2320
2321static
njn695c16e2005-03-27 03:40:28 +00002322Int alloc_client_block ( void )
nethercote8b76fe52004-11-08 19:20:09 +00002323{
2324 UInt i, sz_new;
2325 CGenBlock* cgbs_new;
2326
njn695c16e2005-03-27 03:40:28 +00002327 cgb_allocs++;
nethercote8b76fe52004-11-08 19:20:09 +00002328
njn695c16e2005-03-27 03:40:28 +00002329 for (i = 0; i < cgb_used; i++) {
2330 cgb_search++;
2331 if (cgbs[i].start == 0 && cgbs[i].size == 0)
nethercote8b76fe52004-11-08 19:20:09 +00002332 return i;
2333 }
2334
2335 /* Not found. Try to allocate one at the end. */
njn695c16e2005-03-27 03:40:28 +00002336 if (cgb_used < cgb_size) {
2337 cgb_used++;
2338 return cgb_used-1;
nethercote8b76fe52004-11-08 19:20:09 +00002339 }
2340
2341 /* Ok, we have to allocate a new one. */
njn695c16e2005-03-27 03:40:28 +00002342 tl_assert(cgb_used == cgb_size);
2343 sz_new = (cgbs == NULL) ? 10 : (2 * cgb_size);
nethercote8b76fe52004-11-08 19:20:09 +00002344
2345 cgbs_new = VG_(malloc)( sz_new * sizeof(CGenBlock) );
njn695c16e2005-03-27 03:40:28 +00002346 for (i = 0; i < cgb_used; i++)
2347 cgbs_new[i] = cgbs[i];
nethercote8b76fe52004-11-08 19:20:09 +00002348
njn695c16e2005-03-27 03:40:28 +00002349 if (cgbs != NULL)
2350 VG_(free)( cgbs );
2351 cgbs = cgbs_new;
nethercote8b76fe52004-11-08 19:20:09 +00002352
njn695c16e2005-03-27 03:40:28 +00002353 cgb_size = sz_new;
2354 cgb_used++;
2355 if (cgb_used > cgb_used_MAX)
2356 cgb_used_MAX = cgb_used;
2357 return cgb_used-1;
nethercote8b76fe52004-11-08 19:20:09 +00002358}
2359
2360
2361static void show_client_block_stats ( void )
2362{
2363 VG_(message)(Vg_DebugMsg,
2364 "general CBs: %d allocs, %d discards, %d maxinuse, %d search",
njn695c16e2005-03-27 03:40:28 +00002365 cgb_allocs, cgb_discards, cgb_used_MAX, cgb_search
nethercote8b76fe52004-11-08 19:20:09 +00002366 );
2367}
2368
nethercote8b76fe52004-11-08 19:20:09 +00002369static Bool client_perm_maybe_describe( Addr a, AddrInfo* ai )
2370{
2371 UInt i;
2372 /* VG_(printf)("try to identify %d\n", a); */
2373
2374 /* Perhaps it's a general block ? */
njn695c16e2005-03-27 03:40:28 +00002375 for (i = 0; i < cgb_used; i++) {
2376 if (cgbs[i].start == 0 && cgbs[i].size == 0)
nethercote8b76fe52004-11-08 19:20:09 +00002377 continue;
njn717cde52005-05-10 02:47:21 +00002378 // Use zero as the redzone for client blocks.
2379 if (VG_(addr_is_in_block)(a, cgbs[i].start, cgbs[i].size, 0)) {
nethercote8b76fe52004-11-08 19:20:09 +00002380 /* OK - maybe it's a mempool, too? */
njn12627272005-08-14 18:32:16 +00002381 MAC_Mempool* mp = VG_(HT_lookup)(MAC_(mempool_list),
2382 (UWord)cgbs[i].start);
njn1d0cb0d2005-08-15 01:52:02 +00002383 if (mp != NULL) {
2384 if (mp->chunks != NULL) {
2385 MAC_Chunk* mc;
njnf66dbfc2005-08-15 01:54:05 +00002386 VG_(HT_ResetIter)(mp->chunks);
2387 while ( (mc = VG_(HT_Next)(mp->chunks)) ) {
njn1d0cb0d2005-08-15 01:52:02 +00002388 if (VG_(addr_is_in_block)(a, mc->data, mc->size,
2389 MAC_MALLOC_REDZONE_SZB)) {
2390 ai->akind = UserG;
2391 ai->blksize = mc->size;
2392 ai->rwoffset = (Int)(a) - (Int)mc->data;
2393 ai->lastchange = mc->where;
2394 return True;
2395 }
nethercote8b76fe52004-11-08 19:20:09 +00002396 }
2397 }
njn1d0cb0d2005-08-15 01:52:02 +00002398 ai->akind = Mempool;
2399 ai->blksize = cgbs[i].size;
2400 ai->rwoffset = (Int)(a) - (Int)(cgbs[i].start);
njn695c16e2005-03-27 03:40:28 +00002401 ai->lastchange = cgbs[i].where;
nethercote8b76fe52004-11-08 19:20:09 +00002402 return True;
2403 }
njn1d0cb0d2005-08-15 01:52:02 +00002404 ai->akind = UserG;
2405 ai->blksize = cgbs[i].size;
2406 ai->rwoffset = (Int)(a) - (Int)(cgbs[i].start);
njn695c16e2005-03-27 03:40:28 +00002407 ai->lastchange = cgbs[i].where;
njn1d0cb0d2005-08-15 01:52:02 +00002408 ai->desc = cgbs[i].desc;
nethercote8b76fe52004-11-08 19:20:09 +00002409 return True;
2410 }
2411 }
2412 return False;
2413}
2414
njn51d827b2005-05-09 01:02:08 +00002415static Bool mc_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret )
nethercote8b76fe52004-11-08 19:20:09 +00002416{
2417 Int i;
2418 Bool ok;
2419 Addr bad_addr;
2420
njnfc26ff92004-11-22 19:12:49 +00002421 if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
nethercote8b76fe52004-11-08 19:20:09 +00002422 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
2423 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
2424 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
2425 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
2426 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
2427 && VG_USERREQ__MEMPOOL_FREE != arg[0])
2428 return False;
2429
2430 switch (arg[0]) {
2431 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
2432 ok = mc_check_writable ( arg[1], arg[2], &bad_addr );
2433 if (!ok)
njn9e63cb62005-05-08 18:34:59 +00002434 mc_record_user_error ( tid, bad_addr, /*isWrite*/True,
2435 /*isUnaddr*/True );
nethercote8b76fe52004-11-08 19:20:09 +00002436 *ret = ok ? (UWord)NULL : bad_addr;
sewardj8cf88b72005-07-08 01:29:33 +00002437 break;
nethercote8b76fe52004-11-08 19:20:09 +00002438
2439 case VG_USERREQ__CHECK_READABLE: { /* check readable */
2440 MC_ReadResult res;
2441 res = mc_check_readable ( arg[1], arg[2], &bad_addr );
2442 if (MC_AddrErr == res)
njn9e63cb62005-05-08 18:34:59 +00002443 mc_record_user_error ( tid, bad_addr, /*isWrite*/False,
2444 /*isUnaddr*/True );
nethercote8b76fe52004-11-08 19:20:09 +00002445 else if (MC_ValueErr == res)
njn9e63cb62005-05-08 18:34:59 +00002446 mc_record_user_error ( tid, bad_addr, /*isWrite*/False,
2447 /*isUnaddr*/False );
nethercote8b76fe52004-11-08 19:20:09 +00002448 *ret = ( res==MC_Ok ? (UWord)NULL : bad_addr );
sewardj8cf88b72005-07-08 01:29:33 +00002449 break;
nethercote8b76fe52004-11-08 19:20:09 +00002450 }
2451
2452 case VG_USERREQ__DO_LEAK_CHECK:
njnb8dca862005-03-14 02:42:44 +00002453 mc_detect_memory_leaks(tid, arg[1] ? LC_Summary : LC_Full);
sewardj8cf88b72005-07-08 01:29:33 +00002454 *ret = 0; /* return value is meaningless */
2455 break;
nethercote8b76fe52004-11-08 19:20:09 +00002456
2457 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
nethercote8b76fe52004-11-08 19:20:09 +00002458 mc_make_noaccess ( arg[1], arg[2] );
sewardj8cf88b72005-07-08 01:29:33 +00002459 *ret = -1;
2460 break;
nethercote8b76fe52004-11-08 19:20:09 +00002461
2462 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
nethercote8b76fe52004-11-08 19:20:09 +00002463 mc_make_writable ( arg[1], arg[2] );
sewardjedc75ab2005-03-15 23:30:32 +00002464 *ret = -1;
sewardj8cf88b72005-07-08 01:29:33 +00002465 break;
nethercote8b76fe52004-11-08 19:20:09 +00002466
2467 case VG_USERREQ__MAKE_READABLE: /* make readable */
nethercote8b76fe52004-11-08 19:20:09 +00002468 mc_make_readable ( arg[1], arg[2] );
sewardj8cf88b72005-07-08 01:29:33 +00002469 *ret = -1;
nethercote8b76fe52004-11-08 19:20:09 +00002470 break;
2471
sewardjedc75ab2005-03-15 23:30:32 +00002472 case VG_USERREQ__CREATE_BLOCK: /* describe a block */
sewardj8cf88b72005-07-08 01:29:33 +00002473 if (arg[1] != 0 && arg[2] != 0) {
2474 i = alloc_client_block();
2475 /* VG_(printf)("allocated %d %p\n", i, cgbs); */
2476 cgbs[i].start = arg[1];
2477 cgbs[i].size = arg[2];
2478 cgbs[i].desc = VG_(strdup)((Char *)arg[3]);
2479 cgbs[i].where = VG_(record_ExeContext) ( tid );
sewardjedc75ab2005-03-15 23:30:32 +00002480
sewardj8cf88b72005-07-08 01:29:33 +00002481 *ret = i;
2482 } else
2483 *ret = -1;
2484 break;
sewardjedc75ab2005-03-15 23:30:32 +00002485
nethercote8b76fe52004-11-08 19:20:09 +00002486 case VG_USERREQ__DISCARD: /* discard */
njn695c16e2005-03-27 03:40:28 +00002487 if (cgbs == NULL
2488 || arg[2] >= cgb_used ||
sewardj8cf88b72005-07-08 01:29:33 +00002489 (cgbs[arg[2]].start == 0 && cgbs[arg[2]].size == 0)) {
sewardjedc75ab2005-03-15 23:30:32 +00002490 *ret = 1;
sewardj8cf88b72005-07-08 01:29:33 +00002491 } else {
2492 tl_assert(arg[2] >= 0 && arg[2] < cgb_used);
2493 cgbs[arg[2]].start = cgbs[arg[2]].size = 0;
2494 VG_(free)(cgbs[arg[2]].desc);
2495 cgb_discards++;
2496 *ret = 0;
2497 }
2498 break;
nethercote8b76fe52004-11-08 19:20:09 +00002499
sewardj45d94cc2005-04-20 14:44:11 +00002500//zz case VG_USERREQ__GET_VBITS:
2501//zz /* Returns: 1 == OK, 2 == alignment error, 3 == addressing
2502//zz error. */
2503//zz /* VG_(printf)("get_vbits %p %p %d\n", arg[1], arg[2], arg[3] ); */
2504//zz *ret = mc_get_or_set_vbits_for_client
2505//zz ( tid, arg[1], arg[2], arg[3], False /* get them */ );
2506//zz break;
2507//zz
2508//zz case VG_USERREQ__SET_VBITS:
2509//zz /* Returns: 1 == OK, 2 == alignment error, 3 == addressing
2510//zz error. */
2511//zz /* VG_(printf)("set_vbits %p %p %d\n", arg[1], arg[2], arg[3] ); */
2512//zz *ret = mc_get_or_set_vbits_for_client
2513//zz ( tid, arg[1], arg[2], arg[3], True /* set them */ );
2514//zz break;
nethercote8b76fe52004-11-08 19:20:09 +00002515
2516 default:
2517 if (MAC_(handle_common_client_requests)(tid, arg, ret )) {
2518 return True;
2519 } else {
2520 VG_(message)(Vg_UserMsg,
2521 "Warning: unknown memcheck client request code %llx",
2522 (ULong)arg[0]);
2523 return False;
2524 }
2525 }
2526 return True;
2527}
njn25e49d8e72002-09-23 09:36:25 +00002528
2529/*------------------------------------------------------------*/
njn51d827b2005-05-09 01:02:08 +00002530/*--- Setup and finalisation ---*/
njn25e49d8e72002-09-23 09:36:25 +00002531/*------------------------------------------------------------*/
2532
njn51d827b2005-05-09 01:02:08 +00002533static void mc_post_clo_init ( void )
njn5c004e42002-11-18 11:04:50 +00002534{
sewardj71bc3cb2005-05-19 00:25:45 +00002535 /* If we've been asked to emit XML, mash around various other
2536 options so as to constrain the output somewhat. */
2537 if (VG_(clo_xml)) {
2538 /* Extract as much info as possible from the leak checker. */
sewardj09890d82005-05-20 02:45:15 +00002539 /* MAC_(clo_show_reachable) = True; */
sewardj71bc3cb2005-05-19 00:25:45 +00002540 MAC_(clo_leak_check) = LC_Full;
2541 }
njn5c004e42002-11-18 11:04:50 +00002542}
2543
njn51d827b2005-05-09 01:02:08 +00002544static void mc_fini ( Int exitcode )
njn5c004e42002-11-18 11:04:50 +00002545{
sewardj23eb2fd2005-04-22 16:29:19 +00002546 Int i, n_accessible_dist;
2547 SecMap* sm;
2548
sewardjae986ca2005-10-12 12:53:20 +00002549 MAC_(common_fini)( mc_detect_memory_leaks );
2550
sewardj45d94cc2005-04-20 14:44:11 +00002551 if (VG_(clo_verbosity) > 1) {
2552 VG_(message)(Vg_DebugMsg,
sewardj23eb2fd2005-04-22 16:29:19 +00002553 " memcheck: sanity checks: %d cheap, %d expensive",
2554 n_sanity_cheap, n_sanity_expensive );
sewardj45d94cc2005-04-20 14:44:11 +00002555 VG_(message)(Vg_DebugMsg,
sewardj23eb2fd2005-04-22 16:29:19 +00002556 " memcheck: auxmaps: %d auxmap entries (%dk, %dM) in use",
2557 auxmap_used,
2558 auxmap_used * 64,
2559 auxmap_used / 16 );
2560 VG_(message)(Vg_DebugMsg,
2561 " memcheck: auxmaps: %lld searches, %lld comparisons",
sewardj45d94cc2005-04-20 14:44:11 +00002562 n_auxmap_searches, n_auxmap_cmps );
sewardj23eb2fd2005-04-22 16:29:19 +00002563 VG_(message)(Vg_DebugMsg,
2564 " memcheck: secondaries: %d issued (%dk, %dM)",
2565 n_secmaps_issued,
2566 n_secmaps_issued * 64,
2567 n_secmaps_issued / 16 );
2568
2569 n_accessible_dist = 0;
2570 for (i = 0; i < N_PRIMARY_MAP; i++) {
2571 sm = primary_map[i];
2572 if (is_distinguished_sm(sm)
2573 && sm != &sm_distinguished[SM_DIST_NOACCESS])
2574 n_accessible_dist ++;
2575 }
2576 for (i = 0; i < auxmap_used; i++) {
2577 sm = auxmap[i].sm;
2578 if (is_distinguished_sm(sm)
2579 && sm != &sm_distinguished[SM_DIST_NOACCESS])
2580 n_accessible_dist ++;
2581 }
2582
2583 VG_(message)(Vg_DebugMsg,
2584 " memcheck: secondaries: %d accessible and distinguished (%dk, %dM)",
2585 n_accessible_dist,
2586 n_accessible_dist * 64,
2587 n_accessible_dist / 16 );
2588
sewardj45d94cc2005-04-20 14:44:11 +00002589 }
2590
njn5c004e42002-11-18 11:04:50 +00002591 if (0) {
2592 VG_(message)(Vg_DebugMsg,
2593 "------ Valgrind's client block stats follow ---------------" );
nethercote8b76fe52004-11-08 19:20:09 +00002594 show_client_block_stats();
njn5c004e42002-11-18 11:04:50 +00002595 }
njn25e49d8e72002-09-23 09:36:25 +00002596}
2597
njn51d827b2005-05-09 01:02:08 +00002598static void mc_pre_clo_init(void)
2599{
2600 VG_(details_name) ("Memcheck");
2601 VG_(details_version) (NULL);
2602 VG_(details_description) ("a memory error detector");
2603 VG_(details_copyright_author)(
2604 "Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.");
2605 VG_(details_bug_reports_to) (VG_BUGS_TO);
2606 VG_(details_avg_translation_sizeB) ( 370 );
2607
2608 VG_(basic_tool_funcs) (mc_post_clo_init,
2609 MC_(instrument),
2610 mc_fini);
2611
2612 VG_(needs_core_errors) ();
2613 VG_(needs_tool_errors) (MAC_(eq_Error),
2614 mc_pp_Error,
2615 MAC_(update_extra),
2616 mc_recognised_suppression,
2617 MAC_(read_extra_suppression_info),
2618 MAC_(error_matches_suppression),
2619 MAC_(get_error_name),
2620 MAC_(print_extra_suppression_info));
2621 VG_(needs_libc_freeres) ();
2622 VG_(needs_command_line_options)(mc_process_cmd_line_option,
2623 mc_print_usage,
2624 mc_print_debug_usage);
2625 VG_(needs_client_requests) (mc_handle_client_request);
2626 VG_(needs_sanity_checks) (mc_cheap_sanity_check,
2627 mc_expensive_sanity_check);
njn51d827b2005-05-09 01:02:08 +00002628
njnfc51f8d2005-06-21 03:20:17 +00002629 VG_(needs_malloc_replacement) (MAC_(malloc),
njn51d827b2005-05-09 01:02:08 +00002630 MAC_(__builtin_new),
2631 MAC_(__builtin_vec_new),
2632 MAC_(memalign),
2633 MAC_(calloc),
2634 MAC_(free),
2635 MAC_(__builtin_delete),
2636 MAC_(__builtin_vec_delete),
2637 MAC_(realloc),
2638 MAC_MALLOC_REDZONE_SZB );
2639
2640 MAC_( new_mem_heap) = & mc_new_mem_heap;
2641 MAC_( ban_mem_heap) = & mc_make_noaccess;
2642 MAC_(copy_mem_heap) = & mc_copy_address_range_state;
2643 MAC_( die_mem_heap) = & mc_make_noaccess;
2644 MAC_(check_noaccess) = & mc_check_noaccess;
2645
2646 VG_(track_new_mem_startup) ( & mc_new_mem_startup );
2647 VG_(track_new_mem_stack_signal)( & mc_make_writable );
2648 VG_(track_new_mem_brk) ( & mc_make_writable );
2649 VG_(track_new_mem_mmap) ( & mc_new_mem_mmap );
2650
2651 VG_(track_copy_mem_remap) ( & mc_copy_address_range_state );
njn81623712005-10-07 04:48:37 +00002652
2653 // Nb: we don't do anything with mprotect. This means that V bits are
2654 // preserved if a program, for example, marks some memory as inaccessible
2655 // and then later marks it as accessible again.
2656 //
2657 // If an access violation occurs (eg. writing to read-only memory) we let
2658 // it fault and print an informative termination message. This doesn't
2659 // happen if the program catches the signal, though, which is bad. If we
2660 // had two A bits (for readability and writability) that were completely
2661 // distinct from V bits, then we could handle all this properly.
2662 VG_(track_change_mem_mprotect) ( NULL );
njn51d827b2005-05-09 01:02:08 +00002663
2664 VG_(track_die_mem_stack_signal)( & mc_make_noaccess );
2665 VG_(track_die_mem_brk) ( & mc_make_noaccess );
2666 VG_(track_die_mem_munmap) ( & mc_make_noaccess );
2667
2668 VG_(track_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
2669 VG_(track_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
2670 VG_(track_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
2671 VG_(track_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
2672 VG_(track_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
2673 VG_(track_new_mem_stack) ( & MAC_(new_mem_stack) );
2674
2675 VG_(track_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
2676 VG_(track_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
2677 VG_(track_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
2678 VG_(track_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
2679 VG_(track_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
2680 VG_(track_die_mem_stack) ( & MAC_(die_mem_stack) );
2681
2682 VG_(track_ban_mem_stack) ( & mc_make_noaccess );
2683
2684 VG_(track_pre_mem_read) ( & mc_check_is_readable );
2685 VG_(track_pre_mem_read_asciiz) ( & mc_check_is_readable_asciiz );
2686 VG_(track_pre_mem_write) ( & mc_check_is_writable );
2687 VG_(track_post_mem_write) ( & mc_post_mem_write );
2688
2689 VG_(track_pre_reg_read) ( & mc_pre_reg_read );
2690
2691 VG_(track_post_reg_write) ( & mc_post_reg_write );
2692 VG_(track_post_reg_write_clientcall_return)( & mc_post_reg_write_clientcall );
2693
2694 VG_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
2695 VG_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
2696 VG_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
2697
2698 /* Additional block description for VG_(describe_addr)() */
2699 MAC_(describe_addr_supp) = client_perm_maybe_describe;
2700
2701 init_shadow_memory();
2702 MAC_(common_pre_clo_init)();
2703
2704 tl_assert( mc_expensive_sanity_check() );
2705}
2706
sewardj45f4e7c2005-09-27 19:20:21 +00002707VG_DETERMINE_INTERFACE_VERSION(mc_pre_clo_init)
fitzhardinge98abfc72003-12-16 02:05:15 +00002708
njn25e49d8e72002-09-23 09:36:25 +00002709/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00002710/*--- end mc_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00002711/*--------------------------------------------------------------------*/