blob: 152bbdabf487e90c85c92821bd7d80007ad4ec60 [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
137/* Just handle the first 16G fast and the rest via auxiliary
138 primaries. */
139# define N_PRIMARY_BITS 18
140
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
sewardj45d94cc2005-04-20 14:44:11 +0000193 new_sm = VG_(shadow_alloc)(sizeof(SecMap));
194 VG_(memcpy)(new_sm, dist_sm, sizeof(SecMap));
sewardj23eb2fd2005-04-22 16:29:19 +0000195 n_secmaps_issued++;
sewardj45d94cc2005-04-20 14:44:11 +0000196 return new_sm;
197}
njnb8dca862005-03-14 02:42:44 +0000198
sewardj45d94cc2005-04-20 14:44:11 +0000199
200/* --------------- Primary maps --------------- */
201
202/* The main primary map. This covers some initial part of the address
sewardj23eb2fd2005-04-22 16:29:19 +0000203 space, addresses 0 .. (N_PRIMARY_MAP << 16)-1. The rest of it is
sewardj45d94cc2005-04-20 14:44:11 +0000204 handled using the auxiliary primary map.
205*/
sewardj23eb2fd2005-04-22 16:29:19 +0000206static SecMap* primary_map[N_PRIMARY_MAP];
sewardj45d94cc2005-04-20 14:44:11 +0000207
208
209/* An entry in the auxiliary primary map. base must be a 64k-aligned
210 value, and sm points at the relevant secondary map. As with the
211 main primary map, the secondary may be either a real secondary, or
212 one of the three distinguished secondaries.
213*/
214typedef
215 struct {
sewardj23eb2fd2005-04-22 16:29:19 +0000216 Addr base;
sewardj45d94cc2005-04-20 14:44:11 +0000217 SecMap* sm;
218 }
219 AuxMapEnt;
220
221/* An expanding array of AuxMapEnts. */
sewardjaba741d2005-06-09 13:56:07 +0000222#define N_AUXMAPS 20000 /* HACK */
sewardj45d94cc2005-04-20 14:44:11 +0000223static AuxMapEnt hacky_auxmaps[N_AUXMAPS];
224static Int auxmap_size = N_AUXMAPS;
225static Int auxmap_used = 0;
226static AuxMapEnt* auxmap = &hacky_auxmaps[0];
227
sewardj45d94cc2005-04-20 14:44:11 +0000228
229/* Find an entry in the auxiliary map. If an entry is found, move it
230 one step closer to the front of the array, then return its address.
sewardj05fe85e2005-04-27 22:46:36 +0000231 If an entry is not found, return NULL. Note carefully that
sewardj45d94cc2005-04-20 14:44:11 +0000232 because a each call potentially rearranges the entries, each call
233 to this function invalidates ALL AuxMapEnt*s previously obtained by
234 calling this fn.
235*/
sewardj05fe85e2005-04-27 22:46:36 +0000236static AuxMapEnt* maybe_find_in_auxmap ( Addr a )
sewardj45d94cc2005-04-20 14:44:11 +0000237{
238 UWord i;
239 tl_assert(a > MAX_PRIMARY_ADDRESS);
240
241 a &= ~(Addr)0xFFFF;
242
243 /* Search .. */
244 n_auxmap_searches++;
245 for (i = 0; i < auxmap_used; i++) {
246 if (auxmap[i].base == a)
247 break;
248 }
249 n_auxmap_cmps += (ULong)(i+1);
250
251 if (i < auxmap_used) {
252 /* Found it. Nudge it a bit closer to the front. */
253 if (i > 0) {
254 AuxMapEnt tmp = auxmap[i-1];
255 auxmap[i-1] = auxmap[i];
256 auxmap[i] = tmp;
257 i--;
258 }
259 return &auxmap[i];
260 }
261
sewardj05fe85e2005-04-27 22:46:36 +0000262 return NULL;
263}
264
265
266/* Find an entry in the auxiliary map. If an entry is found, move it
267 one step closer to the front of the array, then return its address.
268 If an entry is not found, allocate one. Note carefully that
269 because a each call potentially rearranges the entries, each call
270 to this function invalidates ALL AuxMapEnt*s previously obtained by
271 calling this fn.
272*/
273static AuxMapEnt* find_or_alloc_in_auxmap ( Addr a )
274{
275 AuxMapEnt* am = maybe_find_in_auxmap(a);
276 if (am)
277 return am;
278
sewardj45d94cc2005-04-20 14:44:11 +0000279 /* We didn't find it. Hmm. This is a new piece of address space.
280 We'll need to allocate a new AuxMap entry for it. */
281 if (auxmap_used >= auxmap_size) {
282 tl_assert(auxmap_used == auxmap_size);
283 /* Out of auxmap entries. */
284 tl_assert2(0, "failed to expand the auxmap table");
285 }
286
287 tl_assert(auxmap_used < auxmap_size);
288
289 auxmap[auxmap_used].base = a & ~(Addr)0xFFFF;
290 auxmap[auxmap_used].sm = &sm_distinguished[SM_DIST_NOACCESS];
291
292 if (0)
293 VG_(printf)("new auxmap, base = 0x%llx\n",
294 (ULong)auxmap[auxmap_used].base );
295
296 auxmap_used++;
297 return &auxmap[auxmap_used-1];
298}
299
300
301/* --------------- SecMap fundamentals --------------- */
302
303/* Produce the secmap for 'a', either from the primary map or by
304 ensuring there is an entry for it in the aux primary map. The
305 secmap may be a distinguished one as the caller will only want to
306 be able to read it.
307*/
308static SecMap* get_secmap_readable ( Addr a )
309{
310 if (a <= MAX_PRIMARY_ADDRESS) {
311 UWord pm_off = a >> 16;
312 return primary_map[ pm_off ];
313 } else {
314 AuxMapEnt* am = find_or_alloc_in_auxmap(a);
315 return am->sm;
316 }
317}
318
sewardj05fe85e2005-04-27 22:46:36 +0000319/* If 'a' has a SecMap, produce it. Else produce NULL. But don't
320 allocate one if one doesn't already exist. This is used by the
321 leak checker.
322*/
323static SecMap* maybe_get_secmap_for ( Addr a )
324{
325 if (a <= MAX_PRIMARY_ADDRESS) {
326 UWord pm_off = a >> 16;
327 return primary_map[ pm_off ];
328 } else {
329 AuxMapEnt* am = maybe_find_in_auxmap(a);
330 return am ? am->sm : NULL;
331 }
332}
333
334
335
sewardj45d94cc2005-04-20 14:44:11 +0000336/* Produce the secmap for 'a', either from the primary map or by
337 ensuring there is an entry for it in the aux primary map. The
338 secmap may not be a distinguished one, since the caller will want
339 to be able to write it. If it is a distinguished secondary, make a
340 writable copy of it, install it, and return the copy instead. (COW
341 semantics).
342*/
343static SecMap* get_secmap_writable ( Addr a )
344{
345 if (a <= MAX_PRIMARY_ADDRESS) {
346 UWord pm_off = a >> 16;
347 if (is_distinguished_sm(primary_map[ pm_off ]))
348 primary_map[pm_off] = copy_for_writing(primary_map[pm_off]);
349 return primary_map[pm_off];
350 } else {
351 AuxMapEnt* am = find_or_alloc_in_auxmap(a);
352 if (is_distinguished_sm(am->sm))
353 am->sm = copy_for_writing(am->sm);
354 return am->sm;
355 }
356}
357
358
359/* --------------- Endianness helpers --------------- */
360
361/* Returns the offset in memory of the byteno-th most significant byte
362 in a wordszB-sized word, given the specified endianness. */
363static inline UWord byte_offset_w ( UWord wordszB, Bool bigendian,
364 UWord byteno ) {
365 return bigendian ? (wordszB-1-byteno) : byteno;
366}
367
368
369/* --------------- Fundamental functions --------------- */
370
371static
372void get_abit_and_vbyte ( /*OUT*/UWord* abit,
373 /*OUT*/UWord* vbyte,
374 Addr a )
375{
376 SecMap* sm = get_secmap_readable(a);
377 *vbyte = 0xFF & sm->vbyte[a & 0xFFFF];
378 *abit = read_bit_array(sm->abits, a & 0xFFFF);
379}
380
381static
382UWord get_abit ( Addr a )
383{
384 SecMap* sm = get_secmap_readable(a);
385 return read_bit_array(sm->abits, a & 0xFFFF);
386}
387
388static
389void set_abit_and_vbyte ( Addr a, UWord abit, UWord vbyte )
390{
391 SecMap* sm = get_secmap_writable(a);
392 sm->vbyte[a & 0xFFFF] = 0xFF & vbyte;
393 write_bit_array(sm->abits, a & 0xFFFF, abit);
394}
395
396static
397void set_vbyte ( Addr a, UWord vbyte )
398{
399 SecMap* sm = get_secmap_writable(a);
400 sm->vbyte[a & 0xFFFF] = 0xFF & vbyte;
401}
402
403
404/* --------------- Load/store slow cases. --------------- */
405
406static
407ULong mc_LOADVn_slow ( Addr a, SizeT szB, Bool bigendian )
408{
409 /* Make up a result V word, which contains the loaded data for
sewardjf3d57dd2005-04-22 20:23:27 +0000410 valid addresses and Defined for invalid addresses. Iterate over
411 the bytes in the word, from the most significant down to the
412 least. */
sewardj45d94cc2005-04-20 14:44:11 +0000413 ULong vw = VGM_WORD64_INVALID;
414 SizeT i = szB-1;
415 SizeT n_addrs_bad = 0;
416 Addr ai;
417 Bool aok;
418 UWord abit, vbyte;
419
sewardjc1a2cda2005-04-21 17:34:00 +0000420 PROF_EVENT(30, "mc_LOADVn_slow");
sewardj45d94cc2005-04-20 14:44:11 +0000421 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
422
423 while (True) {
sewardjc1a2cda2005-04-21 17:34:00 +0000424 PROF_EVENT(31, "mc_LOADVn_slow(loop)");
sewardj45d94cc2005-04-20 14:44:11 +0000425 ai = a+byte_offset_w(szB,bigendian,i);
426 get_abit_and_vbyte(&abit, &vbyte, ai);
427 aok = abit == VGM_BIT_VALID;
428 if (!aok)
429 n_addrs_bad++;
430 vw <<= 8;
sewardjf3d57dd2005-04-22 20:23:27 +0000431 vw |= 0xFF & (aok ? vbyte : VGM_BYTE_VALID);
sewardj45d94cc2005-04-20 14:44:11 +0000432 if (i == 0) break;
433 i--;
434 }
435
436 if (n_addrs_bad > 0)
437 MAC_(record_address_error)( VG_(get_running_tid)(), a, szB, False );
438
sewardj45d94cc2005-04-20 14:44:11 +0000439 return vw;
440}
441
442
443static
444void mc_STOREVn_slow ( Addr a, SizeT szB, UWord vbytes, Bool bigendian )
445{
446 SizeT i;
447 SizeT n_addrs_bad = 0;
448 UWord abit;
449 Bool aok;
450 Addr ai;
451
sewardjc1a2cda2005-04-21 17:34:00 +0000452 PROF_EVENT(35, "mc_STOREVn_slow");
sewardj45d94cc2005-04-20 14:44:11 +0000453 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
454
455 /* Dump vbytes in memory, iterating from least to most significant
456 byte. At the same time establish addressibility of the
457 location. */
458 for (i = 0; i < szB; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +0000459 PROF_EVENT(36, "mc_STOREVn_slow(loop)");
sewardj45d94cc2005-04-20 14:44:11 +0000460 ai = a+byte_offset_w(szB,bigendian,i);
461 abit = get_abit(ai);
462 aok = abit == VGM_BIT_VALID;
463 if (!aok)
464 n_addrs_bad++;
465 set_vbyte(ai, vbytes & 0xFF );
466 vbytes >>= 8;
467 }
468
469 /* If an address error has happened, report it. */
470 if (n_addrs_bad > 0)
471 MAC_(record_address_error)( VG_(get_running_tid)(), a, szB, True );
472}
473
474
sewardj45d94cc2005-04-20 14:44:11 +0000475//zz /* Reading/writing of the bitmaps, for aligned word-sized accesses. */
476//zz
477//zz static __inline__ UChar get_abits4_ALIGNED ( Addr a )
478//zz {
479//zz SecMap* sm;
480//zz UInt sm_off;
481//zz UChar abits8;
482//zz PROF_EVENT(24);
483//zz # ifdef VG_DEBUG_MEMORY
484//zz tl_assert(VG_IS_4_ALIGNED(a));
485//zz # endif
486//zz sm = primary_map[PM_IDX(a)];
487//zz sm_off = SM_OFF(a);
488//zz abits8 = sm->abits[sm_off >> 3];
489//zz abits8 >>= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
490//zz abits8 &= 0x0F;
491//zz return abits8;
492//zz }
493//zz
494//zz static UInt __inline__ get_vbytes4_ALIGNED ( Addr a )
495//zz {
496//zz SecMap* sm = primary_map[PM_IDX(a)];
497//zz UInt sm_off = SM_OFF(a);
498//zz PROF_EVENT(25);
499//zz # ifdef VG_DEBUG_MEMORY
500//zz tl_assert(VG_IS_4_ALIGNED(a));
501//zz # endif
502//zz return ((UInt*)(sm->vbyte))[sm_off >> 2];
503//zz }
504//zz
505//zz
506//zz static void __inline__ set_vbytes4_ALIGNED ( Addr a, UInt vbytes )
507//zz {
508//zz SecMap* sm;
509//zz UInt sm_off;
510//zz ENSURE_MAPPABLE(a, "set_vbytes4_ALIGNED");
511//zz sm = primary_map[PM_IDX(a)];
512//zz sm_off = SM_OFF(a);
513//zz PROF_EVENT(23);
514//zz # ifdef VG_DEBUG_MEMORY
515//zz tl_assert(VG_IS_4_ALIGNED(a));
516//zz # endif
517//zz ((UInt*)(sm->vbyte))[sm_off >> 2] = vbytes;
518//zz }
sewardjee070842003-07-05 17:53:55 +0000519
520
njn25e49d8e72002-09-23 09:36:25 +0000521/*------------------------------------------------------------*/
522/*--- Setting permissions over address ranges. ---*/
523/*------------------------------------------------------------*/
524
sewardj23eb2fd2005-04-22 16:29:19 +0000525/* Given address 'a', find the place where the pointer to a's
526 secondary map lives. If a falls into the primary map, the returned
527 value points to one of the entries in primary_map[]. Otherwise,
528 the auxiliary primary map is searched for 'a', or an entry is
529 created for it; either way, the returned value points to the
530 relevant AuxMapEnt's .sm field.
531
532 The point of this is to enable set_address_range_perms to assign
533 secondary maps in a uniform way, without worrying about whether a
534 given secondary map is pointed to from the main or auxiliary
535 primary map.
536*/
537
538static SecMap** find_secmap_binder_for_addr ( Addr aA )
539{
540 if (aA > MAX_PRIMARY_ADDRESS) {
541 AuxMapEnt* am = find_or_alloc_in_auxmap(aA);
542 return &am->sm;
543 } else {
544 UWord a = (UWord)aA;
545 UWord sec_no = (UWord)(a >> 16);
546# if VG_DEBUG_MEMORY >= 1
547 tl_assert(sec_no < N_PRIMARY_MAP);
548# endif
549 return &primary_map[sec_no];
550 }
551}
552
553
554static void set_address_range_perms ( Addr aA, SizeT len,
sewardj45d94cc2005-04-20 14:44:11 +0000555 UWord example_a_bit,
556 UWord example_v_bit )
njn25e49d8e72002-09-23 09:36:25 +0000557{
sewardj23eb2fd2005-04-22 16:29:19 +0000558 PROF_EVENT(150, "set_address_range_perms");
559
560 /* Check the permissions make sense. */
561 tl_assert(example_a_bit == VGM_BIT_VALID
562 || example_a_bit == VGM_BIT_INVALID);
563 tl_assert(example_v_bit == VGM_BIT_VALID
564 || example_v_bit == VGM_BIT_INVALID);
565 if (example_a_bit == VGM_BIT_INVALID)
566 tl_assert(example_v_bit == VGM_BIT_INVALID);
567
568 if (len == 0)
569 return;
570
sewardj1fa7d2c2005-06-13 18:22:17 +0000571 if (VG_(clo_verbosity) > 0 && !VG_(clo_xml)) {
sewardj23eb2fd2005-04-22 16:29:19 +0000572 if (len > 100 * 1000 * 1000) {
573 VG_(message)(Vg_UserMsg,
574 "Warning: set address range perms: "
575 "large range %u, a %d, v %d",
576 len, example_a_bit, example_v_bit );
577 }
578 }
579
580 UWord a = (UWord)aA;
581
582# if VG_DEBUG_MEMORY >= 2
583
584 /*------------------ debug-only case ------------------ */
sewardj45d94cc2005-04-20 14:44:11 +0000585 SizeT i;
njn25e49d8e72002-09-23 09:36:25 +0000586
sewardj23eb2fd2005-04-22 16:29:19 +0000587 UWord example_vbyte = BIT_TO_BYTE(example_v_bit);
sewardj45d94cc2005-04-20 14:44:11 +0000588
589 tl_assert(sizeof(SizeT) == sizeof(Addr));
590
591 if (0 && len >= 4096)
592 VG_(printf)("s_a_r_p(0x%llx, %d, %d,%d)\n",
593 (ULong)a, len, example_a_bit, example_v_bit);
njn25e49d8e72002-09-23 09:36:25 +0000594
595 if (len == 0)
596 return;
597
sewardj45d94cc2005-04-20 14:44:11 +0000598 for (i = 0; i < len; i++) {
599 set_abit_and_vbyte(a+i, example_a_bit, example_vbyte);
njn25e49d8e72002-09-23 09:36:25 +0000600 }
njn25e49d8e72002-09-23 09:36:25 +0000601
sewardj23eb2fd2005-04-22 16:29:19 +0000602# else
603
604 /*------------------ standard handling ------------------ */
605 UWord vbits8, abits8, vbits32, v_off, a_off;
606 SecMap* sm;
607 SecMap** binder;
608 SecMap* example_dsm;
609
610 /* Decide on the distinguished secondary that we might want
611 to use (part of the space-compression scheme). */
612 if (example_a_bit == VGM_BIT_INVALID) {
613 example_dsm = &sm_distinguished[SM_DIST_NOACCESS];
614 } else {
615 if (example_v_bit == VGM_BIT_VALID) {
616 example_dsm = &sm_distinguished[SM_DIST_ACCESS_DEFINED];
617 } else {
618 example_dsm = &sm_distinguished[SM_DIST_ACCESS_UNDEFINED];
619 }
620 }
621
622 /* Make various wider versions of the A/V values to use. */
623 vbits8 = BIT_TO_BYTE(example_v_bit);
624 abits8 = BIT_TO_BYTE(example_a_bit);
625 vbits32 = (vbits8 << 24) | (vbits8 << 16) | (vbits8 << 8) | vbits8;
626
627 /* Slowly do parts preceding 8-byte alignment. */
628 while (True) {
629 if (len == 0) break;
630 PROF_EVENT(151, "set_address_range_perms-loop1-pre");
631 if (VG_IS_8_ALIGNED(a)) break;
632 set_abit_and_vbyte( a, example_a_bit, vbits8 );
633 a++;
634 len--;
635 }
636
637 if (len == 0)
638 return;
639
640 tl_assert(VG_IS_8_ALIGNED(a) && len > 0);
641
642 /* Now go in steps of 8 bytes. */
643 binder = find_secmap_binder_for_addr(a);
644
645 while (True) {
646
647 if (len < 8) break;
648
649 PROF_EVENT(152, "set_address_range_perms-loop8");
650
651 if ((a & SECONDARY_MASK) == 0) {
652 /* we just traversed a primary map boundary, so update the
653 binder. */
654 binder = find_secmap_binder_for_addr(a);
655 PROF_EVENT(153, "set_address_range_perms-update-binder");
656
657 /* Space-optimisation. If we are setting the entire
658 secondary map, just point this entry at one of our
659 distinguished secondaries. However, only do that if it
660 already points at a distinguished secondary, since doing
661 otherwise would leak the existing secondary. We could do
662 better and free up any pre-existing non-distinguished
663 secondary at this point, since we are guaranteed that each
664 non-dist secondary only has one pointer to it, and we have
665 that pointer right here. */
666 if (len >= SECONDARY_SIZE && is_distinguished_sm(*binder)) {
667 PROF_EVENT(154, "set_address_range_perms-entire-secmap");
668 *binder = example_dsm;
669 len -= SECONDARY_SIZE;
670 a += SECONDARY_SIZE;
671 continue;
672 }
673 }
674
675 /* If the primary is already pointing to a distinguished map
676 with the same properties as we're trying to set, then leave
677 it that way. */
678 if (*binder == example_dsm) {
679 a += 8;
680 len -= 8;
681 continue;
682 }
683
684 /* Make sure it's OK to write the secondary. */
685 if (is_distinguished_sm(*binder))
686 *binder = copy_for_writing(*binder);
687
688 sm = *binder;
689 v_off = a & 0xFFFF;
690 a_off = v_off >> 3;
691 sm->abits[a_off] = (UChar)abits8;
692 ((UInt*)(sm->vbyte))[(v_off >> 2) + 0] = (UInt)vbits32;
693 ((UInt*)(sm->vbyte))[(v_off >> 2) + 1] = (UInt)vbits32;
694
695 a += 8;
696 len -= 8;
697 }
698
699 if (len == 0)
700 return;
701
702 tl_assert(VG_IS_8_ALIGNED(a) && len > 0 && len < 8);
703
704 /* Finish the upper fragment. */
705 while (True) {
706 if (len == 0) break;
707 PROF_EVENT(155, "set_address_range_perms-loop1-post");
708 set_abit_and_vbyte ( a, example_a_bit, vbits8 );
709 a++;
710 len--;
711 }
712
713# endif
714}
sewardj45d94cc2005-04-20 14:44:11 +0000715
sewardjc859fbf2005-04-22 21:10:28 +0000716
717/* --- Set permissions for arbitrary address ranges --- */
njn25e49d8e72002-09-23 09:36:25 +0000718
nethercote8b76fe52004-11-08 19:20:09 +0000719static void mc_make_noaccess ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000720{
sewardjc1a2cda2005-04-21 17:34:00 +0000721 PROF_EVENT(40, "mc_make_noaccess");
nethercote8b76fe52004-11-08 19:20:09 +0000722 DEBUG("mc_make_noaccess(%p, %llu)\n", a, (ULong)len);
njn25e49d8e72002-09-23 09:36:25 +0000723 set_address_range_perms ( a, len, VGM_BIT_INVALID, VGM_BIT_INVALID );
724}
725
nethercote8b76fe52004-11-08 19:20:09 +0000726static void mc_make_writable ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000727{
sewardjc1a2cda2005-04-21 17:34:00 +0000728 PROF_EVENT(41, "mc_make_writable");
nethercote8b76fe52004-11-08 19:20:09 +0000729 DEBUG("mc_make_writable(%p, %llu)\n", a, (ULong)len);
njn25e49d8e72002-09-23 09:36:25 +0000730 set_address_range_perms ( a, len, VGM_BIT_VALID, VGM_BIT_INVALID );
731}
732
nethercote8b76fe52004-11-08 19:20:09 +0000733static void mc_make_readable ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000734{
sewardjc1a2cda2005-04-21 17:34:00 +0000735 PROF_EVENT(42, "mc_make_readable");
nethercote8b76fe52004-11-08 19:20:09 +0000736 DEBUG("mc_make_readable(%p, %llu)\n", a, (ULong)len);
njn25e49d8e72002-09-23 09:36:25 +0000737 set_address_range_perms ( a, len, VGM_BIT_VALID, VGM_BIT_VALID );
738}
739
njn9b007f62003-04-07 14:40:25 +0000740
sewardjc859fbf2005-04-22 21:10:28 +0000741/* --- Block-copy permissions (needed for implementing realloc()). --- */
742
743static void mc_copy_address_range_state ( Addr src, Addr dst, SizeT len )
744{
745 SizeT i;
746 UWord abit, vbyte;
747
748 DEBUG("mc_copy_address_range_state\n");
749
750 PROF_EVENT(50, "mc_copy_address_range_state");
751 for (i = 0; i < len; i++) {
752 PROF_EVENT(51, "mc_copy_address_range_state(loop)");
753 get_abit_and_vbyte( &abit, &vbyte, src+i );
754 set_abit_and_vbyte( dst+i, abit, vbyte );
755 }
756}
757
758
759/* --- Fast case permission setters, for dealing with stacks. --- */
760
njn9b007f62003-04-07 14:40:25 +0000761static __inline__
sewardj5d28efc2005-04-21 22:16:29 +0000762void make_aligned_word32_writable ( Addr aA )
njn9b007f62003-04-07 14:40:25 +0000763{
sewardj5d28efc2005-04-21 22:16:29 +0000764 PROF_EVENT(300, "make_aligned_word32_writable");
765
766# if VG_DEBUG_MEMORY >= 2
767 mc_make_writable(aA, 4);
768# else
769
770 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
sewardj23eb2fd2005-04-22 16:29:19 +0000771 PROF_EVENT(301, "make_aligned_word32_writable-slow1");
sewardj5d28efc2005-04-21 22:16:29 +0000772 mc_make_writable(aA, 4);
773 return;
774 }
775
776 UWord a = (UWord)aA;
777 UWord sec_no = (UWord)(a >> 16);
778# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +0000779 tl_assert(sec_no < N_PRIMARY_MAP);
sewardj5d28efc2005-04-21 22:16:29 +0000780# endif
781
782 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
783 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
784
785 SecMap* sm = primary_map[sec_no];
786 UWord v_off = a & 0xFFFF;
787 UWord a_off = v_off >> 3;
788
789 /* Paint the new area as uninitialised. */
790 ((UInt*)(sm->vbyte))[v_off >> 2] = VGM_WORD32_INVALID;
791
792 UWord mask = 0x0F;
793 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
794 /* mask now contains 1s where we wish to make address bits valid
795 (0s). */
796 sm->abits[a_off] &= ~mask;
797# endif
njn9b007f62003-04-07 14:40:25 +0000798}
799
sewardj5d28efc2005-04-21 22:16:29 +0000800
801static __inline__
802void make_aligned_word32_noaccess ( Addr aA )
803{
804 PROF_EVENT(310, "make_aligned_word32_noaccess");
805
806# if VG_DEBUG_MEMORY >= 2
807 mc_make_noaccess(aA, 4);
808# else
809
810 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
811 PROF_EVENT(311, "make_aligned_word32_noaccess-slow1");
812 mc_make_noaccess(aA, 4);
813 return;
814 }
815
816 UWord a = (UWord)aA;
817 UWord sec_no = (UWord)(a >> 16);
818# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +0000819 tl_assert(sec_no < N_PRIMARY_MAP);
sewardj5d28efc2005-04-21 22:16:29 +0000820# endif
821
822 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
823 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
824
825 SecMap* sm = primary_map[sec_no];
826 UWord v_off = a & 0xFFFF;
827 UWord a_off = v_off >> 3;
828
829 /* Paint the abandoned data as uninitialised. Probably not
830 necessary, but still .. */
831 ((UInt*)(sm->vbyte))[v_off >> 2] = VGM_WORD32_INVALID;
832
833 UWord mask = 0x0F;
834 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
835 /* mask now contains 1s where we wish to make address bits invalid
836 (1s). */
837 sm->abits[a_off] |= mask;
838# endif
839}
840
841
njn9b007f62003-04-07 14:40:25 +0000842/* Nb: by "aligned" here we mean 8-byte aligned */
843static __inline__
sewardj23eb2fd2005-04-22 16:29:19 +0000844void make_aligned_word64_writable ( Addr aA )
njn9b007f62003-04-07 14:40:25 +0000845{
sewardj23eb2fd2005-04-22 16:29:19 +0000846 PROF_EVENT(320, "make_aligned_word64_writable");
847
848# if VG_DEBUG_MEMORY >= 2
849 mc_make_writable(aA, 8);
850# else
851
852 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
853 PROF_EVENT(321, "make_aligned_word64_writable-slow1");
854 mc_make_writable(aA, 8);
855 return;
856 }
857
858 UWord a = (UWord)aA;
859 UWord sec_no = (UWord)(a >> 16);
860# if VG_DEBUG_MEMORY >= 1
861 tl_assert(sec_no < N_PRIMARY_MAP);
862# endif
863
864 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
865 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
866
867 SecMap* sm = primary_map[sec_no];
868 UWord v_off = a & 0xFFFF;
869 UWord a_off = v_off >> 3;
870
871 /* Paint the new area as uninitialised. */
872 ((ULong*)(sm->vbyte))[v_off >> 3] = VGM_WORD64_INVALID;
873
874 /* Make the relevant area accessible. */
875 sm->abits[a_off] = VGM_BYTE_VALID;
876# endif
njn9b007f62003-04-07 14:40:25 +0000877}
878
sewardj23eb2fd2005-04-22 16:29:19 +0000879
njn9b007f62003-04-07 14:40:25 +0000880static __inline__
sewardj23eb2fd2005-04-22 16:29:19 +0000881void make_aligned_word64_noaccess ( Addr aA )
njn9b007f62003-04-07 14:40:25 +0000882{
sewardj23eb2fd2005-04-22 16:29:19 +0000883 PROF_EVENT(330, "make_aligned_word64_noaccess");
884
885# if VG_DEBUG_MEMORY >= 2
886 mc_make_noaccess(aA, 8);
887# else
888
889 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
890 PROF_EVENT(331, "make_aligned_word64_noaccess-slow1");
891 mc_make_noaccess(aA, 8);
892 return;
893 }
894
895 UWord a = (UWord)aA;
896 UWord sec_no = (UWord)(a >> 16);
897# if VG_DEBUG_MEMORY >= 1
898 tl_assert(sec_no < N_PRIMARY_MAP);
899# endif
900
901 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
902 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
903
904 SecMap* sm = primary_map[sec_no];
905 UWord v_off = a & 0xFFFF;
906 UWord a_off = v_off >> 3;
907
908 /* Paint the abandoned data as uninitialised. Probably not
909 necessary, but still .. */
910 ((ULong*)(sm->vbyte))[v_off >> 3] = VGM_WORD64_INVALID;
911
912 /* Make the abandoned area inaccessible. */
913 sm->abits[a_off] = VGM_BYTE_INVALID;
914# endif
njn9b007f62003-04-07 14:40:25 +0000915}
916
sewardj23eb2fd2005-04-22 16:29:19 +0000917
sewardj45d94cc2005-04-20 14:44:11 +0000918/* The stack-pointer update handling functions */
919SP_UPDATE_HANDLERS ( make_aligned_word32_writable,
920 make_aligned_word32_noaccess,
921 make_aligned_word64_writable,
922 make_aligned_word64_noaccess,
923 mc_make_writable,
924 mc_make_noaccess
925 );
njn9b007f62003-04-07 14:40:25 +0000926
sewardj45d94cc2005-04-20 14:44:11 +0000927
sewardj826ec492005-05-12 18:05:00 +0000928void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len )
929{
930 tl_assert(sizeof(UWord) == sizeof(SizeT));
sewardj2a3a1a72005-05-12 23:25:43 +0000931 if (0)
932 VG_(printf)("helperc_MAKE_STACK_UNINIT %p %d\n", base, len );
933
934# if 0
935 /* Really slow version */
936 mc_make_writable(base, len);
937# endif
938
939# if 0
940 /* Slow(ish) version, which is fairly easily seen to be correct.
941 */
942 if (EXPECTED_TAKEN( VG_IS_8_ALIGNED(base) && len==128 )) {
943 make_aligned_word64_writable(base + 0);
944 make_aligned_word64_writable(base + 8);
945 make_aligned_word64_writable(base + 16);
946 make_aligned_word64_writable(base + 24);
947
948 make_aligned_word64_writable(base + 32);
949 make_aligned_word64_writable(base + 40);
950 make_aligned_word64_writable(base + 48);
951 make_aligned_word64_writable(base + 56);
952
953 make_aligned_word64_writable(base + 64);
954 make_aligned_word64_writable(base + 72);
955 make_aligned_word64_writable(base + 80);
956 make_aligned_word64_writable(base + 88);
957
958 make_aligned_word64_writable(base + 96);
959 make_aligned_word64_writable(base + 104);
960 make_aligned_word64_writable(base + 112);
961 make_aligned_word64_writable(base + 120);
962 } else {
963 mc_make_writable(base, len);
964 }
965# endif
966
967 /* Idea is: go fast when
968 * 8-aligned and length is 128
969 * the sm is available in the main primary map
970 * the address range falls entirely with a single
971 secondary map
972 * the SM is modifiable
973 If all those conditions hold, just update the V bits
974 by writing directly on the v-bit array. We don't care
975 about A bits; if the address range is marked invalid,
976 any attempt to access it will elicit an addressing error,
977 and that's good enough.
978 */
979 if (EXPECTED_TAKEN( len == 128
980 && VG_IS_8_ALIGNED(base)
981 )) {
982 /* Now we know the address range is suitably sized and
983 aligned. */
984 UWord a_lo = (UWord)base;
985 UWord a_hi = (UWord)(base + 127);
986 UWord sec_lo = a_lo >> 16;
987 UWord sec_hi = a_hi >> 16;
988
989 if (EXPECTED_TAKEN( sec_lo == sec_hi
990 && sec_lo <= N_PRIMARY_MAP
991 )) {
992 /* Now we know that the entire address range falls within a
993 single secondary map, and that that secondary 'lives' in
994 the main primary map. */
995 SecMap* sm = primary_map[sec_lo];
996
997 if (EXPECTED_TAKEN( !is_distinguished_sm(sm) )) {
998 /* And finally, now we know that the secondary in question
999 is modifiable. */
1000 UWord v_off = a_lo & 0xFFFF;
1001 ULong* p = (ULong*)(&sm->vbyte[v_off]);
1002 p[ 0] = VGM_WORD64_INVALID;
1003 p[ 1] = VGM_WORD64_INVALID;
1004 p[ 2] = VGM_WORD64_INVALID;
1005 p[ 3] = VGM_WORD64_INVALID;
1006 p[ 4] = VGM_WORD64_INVALID;
1007 p[ 5] = VGM_WORD64_INVALID;
1008 p[ 6] = VGM_WORD64_INVALID;
1009 p[ 7] = VGM_WORD64_INVALID;
1010 p[ 8] = VGM_WORD64_INVALID;
1011 p[ 9] = VGM_WORD64_INVALID;
1012 p[10] = VGM_WORD64_INVALID;
1013 p[11] = VGM_WORD64_INVALID;
1014 p[12] = VGM_WORD64_INVALID;
1015 p[13] = VGM_WORD64_INVALID;
1016 p[14] = VGM_WORD64_INVALID;
1017 p[15] = VGM_WORD64_INVALID;
1018 return;
1019 }
1020 }
1021 }
1022
1023 /* else fall into slow case */
sewardj826ec492005-05-12 18:05:00 +00001024 mc_make_writable(base, len);
1025}
1026
1027
nethercote8b76fe52004-11-08 19:20:09 +00001028/*------------------------------------------------------------*/
1029/*--- Checking memory ---*/
1030/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00001031
sewardje4ccc012005-05-02 12:53:38 +00001032typedef
1033 enum {
1034 MC_Ok = 5,
1035 MC_AddrErr = 6,
1036 MC_ValueErr = 7
1037 }
1038 MC_ReadResult;
1039
1040
njn25e49d8e72002-09-23 09:36:25 +00001041/* Check permissions for address range. If inadequate permissions
1042 exist, *bad_addr is set to the offending address, so the caller can
1043 know what it is. */
1044
sewardjecf8e102003-07-12 12:11:39 +00001045/* Returns True if [a .. a+len) is not addressible. Otherwise,
1046 returns False, and if bad_addr is non-NULL, sets *bad_addr to
1047 indicate the lowest failing address. Functions below are
1048 similar. */
nethercote8b76fe52004-11-08 19:20:09 +00001049static Bool mc_check_noaccess ( Addr a, SizeT len, Addr* bad_addr )
sewardjecf8e102003-07-12 12:11:39 +00001050{
nethercote451eae92004-11-02 13:06:32 +00001051 SizeT i;
sewardj45d94cc2005-04-20 14:44:11 +00001052 UWord abit;
sewardjc1a2cda2005-04-21 17:34:00 +00001053 PROF_EVENT(60, "mc_check_noaccess");
sewardjecf8e102003-07-12 12:11:39 +00001054 for (i = 0; i < len; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +00001055 PROF_EVENT(61, "mc_check_noaccess(loop)");
sewardjecf8e102003-07-12 12:11:39 +00001056 abit = get_abit(a);
1057 if (abit == VGM_BIT_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001058 if (bad_addr != NULL)
1059 *bad_addr = a;
sewardjecf8e102003-07-12 12:11:39 +00001060 return False;
1061 }
1062 a++;
1063 }
1064 return True;
1065}
1066
nethercote8b76fe52004-11-08 19:20:09 +00001067static Bool mc_check_writable ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +00001068{
nethercote451eae92004-11-02 13:06:32 +00001069 SizeT i;
sewardj45d94cc2005-04-20 14:44:11 +00001070 UWord abit;
sewardjc1a2cda2005-04-21 17:34:00 +00001071 PROF_EVENT(62, "mc_check_writable");
njn25e49d8e72002-09-23 09:36:25 +00001072 for (i = 0; i < len; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +00001073 PROF_EVENT(63, "mc_check_writable(loop)");
njn25e49d8e72002-09-23 09:36:25 +00001074 abit = get_abit(a);
1075 if (abit == VGM_BIT_INVALID) {
1076 if (bad_addr != NULL) *bad_addr = a;
1077 return False;
1078 }
1079 a++;
1080 }
1081 return True;
1082}
1083
nethercote8b76fe52004-11-08 19:20:09 +00001084static MC_ReadResult mc_check_readable ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +00001085{
nethercote451eae92004-11-02 13:06:32 +00001086 SizeT i;
sewardj45d94cc2005-04-20 14:44:11 +00001087 UWord abit;
1088 UWord vbyte;
njn25e49d8e72002-09-23 09:36:25 +00001089
sewardjc1a2cda2005-04-21 17:34:00 +00001090 PROF_EVENT(64, "mc_check_readable");
nethercote8b76fe52004-11-08 19:20:09 +00001091 DEBUG("mc_check_readable\n");
njn25e49d8e72002-09-23 09:36:25 +00001092 for (i = 0; i < len; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +00001093 PROF_EVENT(65, "mc_check_readable(loop)");
sewardj45d94cc2005-04-20 14:44:11 +00001094 get_abit_and_vbyte(&abit, &vbyte, a);
nethercote8b76fe52004-11-08 19:20:09 +00001095 // Report addressability errors in preference to definedness errors
1096 // by checking the A bits first.
1097 if (abit != VGM_BIT_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001098 if (bad_addr != NULL)
1099 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +00001100 return MC_AddrErr;
1101 }
1102 if (vbyte != VGM_BYTE_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001103 if (bad_addr != NULL)
1104 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +00001105 return MC_ValueErr;
njn25e49d8e72002-09-23 09:36:25 +00001106 }
1107 a++;
1108 }
nethercote8b76fe52004-11-08 19:20:09 +00001109 return MC_Ok;
njn25e49d8e72002-09-23 09:36:25 +00001110}
1111
1112
1113/* Check a zero-terminated ascii string. Tricky -- don't want to
1114 examine the actual bytes, to find the end, until we're sure it is
1115 safe to do so. */
1116
njn9b007f62003-04-07 14:40:25 +00001117static Bool mc_check_readable_asciiz ( Addr a, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +00001118{
sewardj45d94cc2005-04-20 14:44:11 +00001119 UWord abit;
1120 UWord vbyte;
sewardjc1a2cda2005-04-21 17:34:00 +00001121 PROF_EVENT(66, "mc_check_readable_asciiz");
njn5c004e42002-11-18 11:04:50 +00001122 DEBUG("mc_check_readable_asciiz\n");
njn25e49d8e72002-09-23 09:36:25 +00001123 while (True) {
sewardjc1a2cda2005-04-21 17:34:00 +00001124 PROF_EVENT(67, "mc_check_readable_asciiz(loop)");
sewardj45d94cc2005-04-20 14:44:11 +00001125 get_abit_and_vbyte(&abit, &vbyte, a);
nethercote8b76fe52004-11-08 19:20:09 +00001126 // As in mc_check_readable(), check A bits first
1127 if (abit != VGM_BIT_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001128 if (bad_addr != NULL)
1129 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +00001130 return MC_AddrErr;
1131 }
1132 if (vbyte != VGM_BYTE_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001133 if (bad_addr != NULL)
1134 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +00001135 return MC_ValueErr;
njn25e49d8e72002-09-23 09:36:25 +00001136 }
1137 /* Ok, a is safe to read. */
sewardj45d94cc2005-04-20 14:44:11 +00001138 if (* ((UChar*)a) == 0)
1139 return MC_Ok;
njn25e49d8e72002-09-23 09:36:25 +00001140 a++;
1141 }
1142}
1143
1144
1145/*------------------------------------------------------------*/
1146/*--- Memory event handlers ---*/
1147/*------------------------------------------------------------*/
1148
njn25e49d8e72002-09-23 09:36:25 +00001149static
njn72718642003-07-24 08:45:32 +00001150void mc_check_is_writable ( CorePart part, ThreadId tid, Char* s,
nethercote451eae92004-11-02 13:06:32 +00001151 Addr base, SizeT size )
njn25e49d8e72002-09-23 09:36:25 +00001152{
1153 Bool ok;
1154 Addr bad_addr;
1155
1156 VGP_PUSHCC(VgpCheckMem);
1157
1158 /* VG_(message)(Vg_DebugMsg,"check is writable: %x .. %x",
1159 base,base+size-1); */
nethercote8b76fe52004-11-08 19:20:09 +00001160 ok = mc_check_writable ( base, size, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +00001161 if (!ok) {
1162 switch (part) {
1163 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +00001164 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
1165 /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +00001166 break;
1167
1168 case Vg_CorePThread:
1169 case Vg_CoreSignal:
nethercote8b76fe52004-11-08 19:20:09 +00001170 MAC_(record_core_mem_error)( tid, /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +00001171 break;
1172
1173 default:
njn67993252004-11-22 18:02:32 +00001174 VG_(tool_panic)("mc_check_is_writable: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +00001175 }
1176 }
1177
1178 VGP_POPCC(VgpCheckMem);
1179}
1180
1181static
njn72718642003-07-24 08:45:32 +00001182void mc_check_is_readable ( CorePart part, ThreadId tid, Char* s,
nethercote451eae92004-11-02 13:06:32 +00001183 Addr base, SizeT size )
njn25e49d8e72002-09-23 09:36:25 +00001184{
njn25e49d8e72002-09-23 09:36:25 +00001185 Addr bad_addr;
nethercote8b76fe52004-11-08 19:20:09 +00001186 MC_ReadResult res;
njn25e49d8e72002-09-23 09:36:25 +00001187
1188 VGP_PUSHCC(VgpCheckMem);
1189
1190 /* VG_(message)(Vg_DebugMsg,"check is readable: %x .. %x",
1191 base,base+size-1); */
nethercote8b76fe52004-11-08 19:20:09 +00001192 res = mc_check_readable ( base, size, &bad_addr );
1193 if (MC_Ok != res) {
1194 Bool isUnaddr = ( MC_AddrErr == res ? True : False );
1195
njn25e49d8e72002-09-23 09:36:25 +00001196 switch (part) {
1197 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +00001198 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
1199 isUnaddr, s );
njn25e49d8e72002-09-23 09:36:25 +00001200 break;
1201
1202 case Vg_CorePThread:
nethercote8b76fe52004-11-08 19:20:09 +00001203 MAC_(record_core_mem_error)( tid, isUnaddr, s );
njn25e49d8e72002-09-23 09:36:25 +00001204 break;
1205
1206 /* If we're being asked to jump to a silly address, record an error
1207 message before potentially crashing the entire system. */
1208 case Vg_CoreTranslate:
njn72718642003-07-24 08:45:32 +00001209 MAC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +00001210 break;
1211
1212 default:
njn67993252004-11-22 18:02:32 +00001213 VG_(tool_panic)("mc_check_is_readable: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +00001214 }
1215 }
1216 VGP_POPCC(VgpCheckMem);
1217}
1218
1219static
njn72718642003-07-24 08:45:32 +00001220void mc_check_is_readable_asciiz ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +00001221 Char* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +00001222{
nethercote8b76fe52004-11-08 19:20:09 +00001223 MC_ReadResult res;
njn5ab96ac2005-05-08 02:59:50 +00001224 Addr bad_addr = 0; // shut GCC up
njn25e49d8e72002-09-23 09:36:25 +00001225 /* VG_(message)(Vg_DebugMsg,"check is readable asciiz: 0x%x",str); */
1226
1227 VGP_PUSHCC(VgpCheckMem);
1228
njnca82cc02004-11-22 17:18:48 +00001229 tl_assert(part == Vg_CoreSysCall);
nethercote8b76fe52004-11-08 19:20:09 +00001230 res = mc_check_readable_asciiz ( (Addr)str, &bad_addr );
1231 if (MC_Ok != res) {
1232 Bool isUnaddr = ( MC_AddrErr == res ? True : False );
1233 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False, isUnaddr, s );
njn25e49d8e72002-09-23 09:36:25 +00001234 }
1235
1236 VGP_POPCC(VgpCheckMem);
1237}
1238
njn25e49d8e72002-09-23 09:36:25 +00001239static
nethercote451eae92004-11-02 13:06:32 +00001240void mc_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +00001241{
njn1f3a9092002-10-04 09:22:30 +00001242 /* Ignore the permissions, just make it readable. Seems to work... */
nethercote451eae92004-11-02 13:06:32 +00001243 DEBUG("mc_new_mem_startup(%p, %llu, rr=%u, ww=%u, xx=%u)\n",
1244 a,(ULong)len,rr,ww,xx);
nethercote8b76fe52004-11-08 19:20:09 +00001245 mc_make_readable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001246}
1247
1248static
nethercote451eae92004-11-02 13:06:32 +00001249void mc_new_mem_heap ( Addr a, SizeT len, Bool is_inited )
njn25e49d8e72002-09-23 09:36:25 +00001250{
1251 if (is_inited) {
nethercote8b76fe52004-11-08 19:20:09 +00001252 mc_make_readable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001253 } else {
nethercote8b76fe52004-11-08 19:20:09 +00001254 mc_make_writable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001255 }
1256}
1257
1258static
njnb8dca862005-03-14 02:42:44 +00001259void mc_new_mem_mmap ( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +00001260{
njnb8dca862005-03-14 02:42:44 +00001261 mc_make_readable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001262}
1263
njncf45fd42004-11-24 16:30:22 +00001264static
1265void mc_post_mem_write(CorePart part, ThreadId tid, Addr a, SizeT len)
1266{
1267 mc_make_readable(a, len);
1268}
njn25e49d8e72002-09-23 09:36:25 +00001269
sewardj45d94cc2005-04-20 14:44:11 +00001270
njn25e49d8e72002-09-23 09:36:25 +00001271/*------------------------------------------------------------*/
njnd3040452003-05-19 15:04:06 +00001272/*--- Register event handlers ---*/
1273/*------------------------------------------------------------*/
1274
sewardj45d94cc2005-04-20 14:44:11 +00001275/* When some chunk of guest state is written, mark the corresponding
1276 shadow area as valid. This is used to initialise arbitrarily large
sewardj2c27f702005-05-03 18:19:05 +00001277 chunks of guest state, hence the (somewhat arbitrary) 1024 limit.
sewardj45d94cc2005-04-20 14:44:11 +00001278*/
1279static void mc_post_reg_write ( CorePart part, ThreadId tid,
1280 OffT offset, SizeT size)
njnd3040452003-05-19 15:04:06 +00001281{
sewardj6cf40ff2005-04-20 22:31:26 +00001282 UChar area[1024];
1283 tl_assert(size <= 1024);
njncf45fd42004-11-24 16:30:22 +00001284 VG_(memset)(area, VGM_BYTE_VALID, size);
1285 VG_(set_shadow_regs_area)( tid, offset, size, area );
njnd3040452003-05-19 15:04:06 +00001286}
1287
sewardj45d94cc2005-04-20 14:44:11 +00001288static
1289void mc_post_reg_write_clientcall ( ThreadId tid,
1290 OffT offset, SizeT size,
1291 Addr f)
njnd3040452003-05-19 15:04:06 +00001292{
njncf45fd42004-11-24 16:30:22 +00001293 mc_post_reg_write(/*dummy*/0, tid, offset, size);
njnd3040452003-05-19 15:04:06 +00001294}
1295
sewardj45d94cc2005-04-20 14:44:11 +00001296/* Look at the definedness of the guest's shadow state for
1297 [offset, offset+len). If any part of that is undefined, record
1298 a parameter error.
1299*/
1300static void mc_pre_reg_read ( CorePart part, ThreadId tid, Char* s,
1301 OffT offset, SizeT size)
nethercote8b76fe52004-11-08 19:20:09 +00001302{
sewardj45d94cc2005-04-20 14:44:11 +00001303 Int i;
1304 Bool bad;
1305
1306 UChar area[16];
1307 tl_assert(size <= 16);
1308
1309 VG_(get_shadow_regs_area)( tid, offset, size, area );
1310
1311 bad = False;
1312 for (i = 0; i < size; i++) {
1313 if (area[i] != VGM_BYTE_VALID) {
sewardj2c27f702005-05-03 18:19:05 +00001314 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00001315 break;
1316 }
nethercote8b76fe52004-11-08 19:20:09 +00001317 }
1318
sewardj45d94cc2005-04-20 14:44:11 +00001319 if (bad)
nethercote8b76fe52004-11-08 19:20:09 +00001320 MAC_(record_param_error) ( tid, 0, /*isReg*/True, /*isUnaddr*/False, s );
1321}
njnd3040452003-05-19 15:04:06 +00001322
njn25e49d8e72002-09-23 09:36:25 +00001323
sewardj6cf40ff2005-04-20 22:31:26 +00001324/*------------------------------------------------------------*/
njn9e63cb62005-05-08 18:34:59 +00001325/*--- Printing errors ---*/
1326/*------------------------------------------------------------*/
1327
njn51d827b2005-05-09 01:02:08 +00001328static void mc_pp_Error ( Error* err )
njn9e63cb62005-05-08 18:34:59 +00001329{
1330 MAC_Error* err_extra = VG_(get_error_extra)(err);
1331
sewardj71bc3cb2005-05-19 00:25:45 +00001332 HChar* xpre = VG_(clo_xml) ? " <what>" : "";
1333 HChar* xpost = VG_(clo_xml) ? "</what>" : "";
1334
njn9e63cb62005-05-08 18:34:59 +00001335 switch (VG_(get_error_kind)(err)) {
1336 case CoreMemErr: {
1337 Char* s = ( err_extra->isUnaddr ? "unaddressable" : "uninitialised" );
sewardj71bc3cb2005-05-19 00:25:45 +00001338 if (VG_(clo_xml))
1339 VG_(message)(Vg_UserMsg, " <kind>CoreMemError</kind>");
1340 /* What the hell *is* a CoreMemError? jrs 2005-May-18 */
1341 VG_(message)(Vg_UserMsg, "%s%s contains %s byte(s)%s",
1342 xpre, VG_(get_error_string)(err), s, xpost);
1343
njn9e63cb62005-05-08 18:34:59 +00001344 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1345 break;
1346
1347 }
1348
1349 case ValueErr:
1350 if (err_extra->size == 0) {
sewardj71bc3cb2005-05-19 00:25:45 +00001351 if (VG_(clo_xml))
1352 VG_(message)(Vg_UserMsg, " <kind>UninitCondition</kind>");
1353 VG_(message)(Vg_UserMsg, "%sConditional jump or move depends"
1354 " on uninitialised value(s)%s",
1355 xpre, xpost);
njn9e63cb62005-05-08 18:34:59 +00001356 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001357 if (VG_(clo_xml))
1358 VG_(message)(Vg_UserMsg, " <kind>UninitValue</kind>");
1359 VG_(message)(Vg_UserMsg,
1360 "%sUse of uninitialised value of size %d%s",
1361 xpre, err_extra->size, xpost);
njn9e63cb62005-05-08 18:34:59 +00001362 }
1363 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1364 break;
1365
1366 case ParamErr: {
1367 Bool isReg = ( Register == err_extra->addrinfo.akind );
1368 Char* s1 = ( isReg ? "contains" : "points to" );
1369 Char* s2 = ( err_extra->isUnaddr ? "unaddressable" : "uninitialised" );
1370 if (isReg) tl_assert(!err_extra->isUnaddr);
1371
sewardj71bc3cb2005-05-19 00:25:45 +00001372 if (VG_(clo_xml))
1373 VG_(message)(Vg_UserMsg, " <kind>SyscallParam</kind>");
1374 VG_(message)(Vg_UserMsg, "%sSyscall param %s %s %s byte(s)%s",
1375 xpre, VG_(get_error_string)(err), s1, s2, xpost);
njn9e63cb62005-05-08 18:34:59 +00001376
1377 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1378 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
1379 break;
1380 }
1381 case UserErr: {
1382 Char* s = ( err_extra->isUnaddr ? "Unaddressable" : "Uninitialised" );
1383
sewardj71bc3cb2005-05-19 00:25:45 +00001384 if (VG_(clo_xml))
1385 VG_(message)(Vg_UserMsg, " <kind>ClientCheck</kind>");
njn9e63cb62005-05-08 18:34:59 +00001386 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001387 "%s%s byte(s) found during client check request%s",
1388 xpre, s, xpost);
njn9e63cb62005-05-08 18:34:59 +00001389
1390 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1391 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
1392 break;
1393 }
1394 default:
1395 MAC_(pp_shared_Error)(err);
1396 break;
1397 }
1398}
1399
1400/*------------------------------------------------------------*/
1401/*--- Recording errors ---*/
1402/*------------------------------------------------------------*/
1403
njn02bc4b82005-05-15 17:28:26 +00001404/* Creates a copy of the 'extra' part, updates the copy with address info if
njn9e63cb62005-05-08 18:34:59 +00001405 necessary, and returns the copy. */
1406/* This one called from generated code and non-generated code. */
njn96364822005-05-08 19:04:53 +00001407static void mc_record_value_error ( ThreadId tid, Int size )
njn9e63cb62005-05-08 18:34:59 +00001408{
1409 MAC_Error err_extra;
1410
1411 MAC_(clear_MAC_Error)( &err_extra );
1412 err_extra.size = size;
1413 err_extra.isUnaddr = False;
1414 VG_(maybe_record_error)( tid, ValueErr, /*addr*/0, /*s*/NULL, &err_extra );
1415}
1416
1417/* This called from non-generated code */
1418
njn96364822005-05-08 19:04:53 +00001419static void mc_record_user_error ( ThreadId tid, Addr a, Bool isWrite,
1420 Bool isUnaddr )
njn9e63cb62005-05-08 18:34:59 +00001421{
1422 MAC_Error err_extra;
1423
1424 tl_assert(VG_INVALID_THREADID != tid);
1425 MAC_(clear_MAC_Error)( &err_extra );
1426 err_extra.addrinfo.akind = Undescribed;
1427 err_extra.isUnaddr = isUnaddr;
1428 VG_(maybe_record_error)( tid, UserErr, a, /*s*/NULL, &err_extra );
1429}
1430
1431/*------------------------------------------------------------*/
1432/*--- Suppressions ---*/
1433/*------------------------------------------------------------*/
1434
njn51d827b2005-05-09 01:02:08 +00001435static Bool mc_recognised_suppression ( Char* name, Supp* su )
njn9e63cb62005-05-08 18:34:59 +00001436{
1437 SuppKind skind;
1438
1439 if (MAC_(shared_recognised_suppression)(name, su))
1440 return True;
1441
1442 /* Extra suppressions not used by Addrcheck */
1443 else if (VG_STREQ(name, "Cond")) skind = Value0Supp;
1444 else if (VG_STREQ(name, "Value0")) skind = Value0Supp;/* backwards compat */
1445 else if (VG_STREQ(name, "Value1")) skind = Value1Supp;
1446 else if (VG_STREQ(name, "Value2")) skind = Value2Supp;
1447 else if (VG_STREQ(name, "Value4")) skind = Value4Supp;
1448 else if (VG_STREQ(name, "Value8")) skind = Value8Supp;
1449 else if (VG_STREQ(name, "Value16")) skind = Value16Supp;
1450 else
1451 return False;
1452
1453 VG_(set_supp_kind)(su, skind);
1454 return True;
1455}
1456
1457/*------------------------------------------------------------*/
sewardjc859fbf2005-04-22 21:10:28 +00001458/*--- Functions called directly from generated code: ---*/
1459/*--- Load/store handlers. ---*/
sewardj6cf40ff2005-04-20 22:31:26 +00001460/*------------------------------------------------------------*/
1461
1462/* Types: LOADV4, LOADV2, LOADV1 are:
1463 UWord fn ( Addr a )
1464 so they return 32-bits on 32-bit machines and 64-bits on
1465 64-bit machines. Addr has the same size as a host word.
1466
1467 LOADV8 is always ULong fn ( Addr a )
1468
1469 Similarly for STOREV1, STOREV2, STOREV4, the supplied vbits
1470 are a UWord, and for STOREV8 they are a ULong.
1471*/
1472
sewardj95448072004-11-22 20:19:51 +00001473/* ------------------------ Size = 8 ------------------------ */
1474
sewardj8cf88b72005-07-08 01:29:33 +00001475#define MAKE_LOADV8(nAME,iS_BIGENDIAN) \
1476 \
1477 VG_REGPARM(1) \
1478 ULong nAME ( Addr aA ) \
1479 { \
1480 PROF_EVENT(200, #nAME); \
1481 \
1482 if (VG_DEBUG_MEMORY >= 2) \
1483 return mc_LOADVn_slow( aA, 8, iS_BIGENDIAN ); \
1484 \
1485 const UWord mask = ~((0x10000-8) | ((N_PRIMARY_MAP-1) << 16)); \
1486 UWord a = (UWord)aA; \
1487 \
1488 /* If any part of 'a' indicated by the mask is 1, either */ \
1489 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1490 /* covered by the primary map. Either way we defer to the */ \
1491 /* slow-path case. */ \
1492 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1493 PROF_EVENT(201, #nAME"-slow1"); \
1494 return (UWord)mc_LOADVn_slow( aA, 8, iS_BIGENDIAN ); \
1495 } \
1496 \
1497 UWord sec_no = (UWord)(a >> 16); \
1498 \
1499 if (VG_DEBUG_MEMORY >= 1) \
1500 tl_assert(sec_no < N_PRIMARY_MAP); \
1501 \
1502 SecMap* sm = primary_map[sec_no]; \
1503 UWord v_off = a & 0xFFFF; \
1504 UWord a_off = v_off >> 3; \
1505 UWord abits = (UWord)(sm->abits[a_off]); \
1506 \
1507 if (EXPECTED_TAKEN(abits == VGM_BYTE_VALID)) { \
1508 /* Handle common case quickly: a is suitably aligned, */ \
1509 /* is mapped, and is addressible. */ \
1510 return ((ULong*)(sm->vbyte))[ v_off >> 3 ]; \
1511 } else { \
1512 /* Slow but general case. */ \
1513 PROF_EVENT(202, #nAME"-slow2"); \
1514 return mc_LOADVn_slow( a, 8, iS_BIGENDIAN ); \
1515 } \
sewardjf9d81612005-04-23 23:25:49 +00001516 }
1517
sewardj8cf88b72005-07-08 01:29:33 +00001518MAKE_LOADV8( MC_(helperc_LOADV8be), True /*bigendian*/ );
1519MAKE_LOADV8( MC_(helperc_LOADV8le), False/*littleendian*/ );
sewardjf9d81612005-04-23 23:25:49 +00001520
sewardjf9d81612005-04-23 23:25:49 +00001521
sewardj8cf88b72005-07-08 01:29:33 +00001522#define MAKE_STOREV8(nAME,iS_BIGENDIAN) \
1523 \
1524 VG_REGPARM(1) \
1525 void nAME ( Addr aA, ULong vbytes ) \
1526 { \
1527 PROF_EVENT(210, #nAME); \
1528 \
1529 if (VG_DEBUG_MEMORY >= 2) \
1530 mc_STOREVn_slow( aA, 8, vbytes, iS_BIGENDIAN ); \
1531 \
1532 const UWord mask = ~((0x10000-8) | ((N_PRIMARY_MAP-1) << 16)); \
1533 UWord a = (UWord)aA; \
1534 \
1535 /* If any part of 'a' indicated by the mask is 1, either */ \
1536 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1537 /* covered by the primary map. Either way we defer to the */ \
1538 /* slow-path case. */ \
1539 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1540 PROF_EVENT(211, #nAME"-slow1"); \
1541 mc_STOREVn_slow( aA, 8, vbytes, iS_BIGENDIAN ); \
1542 return; \
1543 } \
1544 \
1545 UWord sec_no = (UWord)(a >> 16); \
1546 \
1547 if (VG_DEBUG_MEMORY >= 1) \
1548 tl_assert(sec_no < N_PRIMARY_MAP); \
1549 \
1550 SecMap* sm = primary_map[sec_no]; \
1551 UWord v_off = a & 0xFFFF; \
1552 UWord a_off = v_off >> 3; \
1553 UWord abits = (UWord)(sm->abits[a_off]); \
1554 \
1555 if (EXPECTED_TAKEN(!is_distinguished_sm(sm) \
1556 && abits == VGM_BYTE_VALID)) { \
1557 /* Handle common case quickly: a is suitably aligned, */ \
1558 /* is mapped, and is addressible. */ \
1559 ((ULong*)(sm->vbyte))[ v_off >> 3 ] = vbytes; \
1560 } else { \
1561 /* Slow but general case. */ \
1562 PROF_EVENT(212, #nAME"-slow2"); \
1563 mc_STOREVn_slow( aA, 8, vbytes, iS_BIGENDIAN ); \
1564 } \
sewardjf9d81612005-04-23 23:25:49 +00001565 }
1566
sewardj8cf88b72005-07-08 01:29:33 +00001567MAKE_STOREV8( MC_(helperc_STOREV8be), True /*bigendian*/ );
1568MAKE_STOREV8( MC_(helperc_STOREV8le), False/*littleendian*/ );
sewardj95448072004-11-22 20:19:51 +00001569
sewardj95448072004-11-22 20:19:51 +00001570
1571/* ------------------------ Size = 4 ------------------------ */
1572
sewardj8cf88b72005-07-08 01:29:33 +00001573#define MAKE_LOADV4(nAME,iS_BIGENDIAN) \
1574 \
1575 VG_REGPARM(1) \
1576 UWord nAME ( Addr aA ) \
1577 { \
1578 PROF_EVENT(220, #nAME); \
1579 \
1580 if (VG_DEBUG_MEMORY >= 2) \
1581 return (UWord)mc_LOADVn_slow( aA, 4, iS_BIGENDIAN ); \
1582 \
1583 const UWord mask = ~((0x10000-4) | ((N_PRIMARY_MAP-1) << 16)); \
1584 UWord a = (UWord)aA; \
1585 \
1586 /* If any part of 'a' indicated by the mask is 1, either */ \
1587 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1588 /* covered by the primary map. Either way we defer to the */ \
1589 /* slow-path case. */ \
1590 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1591 PROF_EVENT(221, #nAME"-slow1"); \
1592 return (UWord)mc_LOADVn_slow( aA, 4, iS_BIGENDIAN ); \
1593 } \
1594 \
1595 UWord sec_no = (UWord)(a >> 16); \
1596 \
1597 if (VG_DEBUG_MEMORY >= 1) \
1598 tl_assert(sec_no < N_PRIMARY_MAP); \
1599 \
1600 SecMap* sm = primary_map[sec_no]; \
1601 UWord v_off = a & 0xFFFF; \
1602 UWord a_off = v_off >> 3; \
1603 UWord abits = (UWord)(sm->abits[a_off]); \
1604 abits >>= (a & 4); \
1605 abits &= 15; \
1606 if (EXPECTED_TAKEN(abits == VGM_NIBBLE_VALID)) { \
1607 /* Handle common case quickly: a is suitably aligned, */ \
1608 /* is mapped, and is addressible. */ \
1609 /* On a 32-bit platform, simply hoick the required 32 */ \
1610 /* bits out of the vbyte array. On a 64-bit platform, */ \
1611 /* also set the upper 32 bits to 1 ("undefined"), just */ \
1612 /* in case. This almost certainly isn't necessary, */ \
1613 /* but be paranoid. */ \
1614 UWord ret = (UWord)0xFFFFFFFF00000000ULL; \
1615 ret |= (UWord)( ((UInt*)(sm->vbyte))[ v_off >> 2 ] ); \
1616 return ret; \
1617 } else { \
1618 /* Slow but general case. */ \
1619 PROF_EVENT(222, #nAME"-slow2"); \
1620 return (UWord)mc_LOADVn_slow( a, 4, iS_BIGENDIAN ); \
1621 } \
sewardjc1a2cda2005-04-21 17:34:00 +00001622 }
1623
sewardj8cf88b72005-07-08 01:29:33 +00001624MAKE_LOADV4( MC_(helperc_LOADV4be), True /*bigendian*/ );
1625MAKE_LOADV4( MC_(helperc_LOADV4le), False/*littleendian*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001626
sewardjc1a2cda2005-04-21 17:34:00 +00001627
sewardj8cf88b72005-07-08 01:29:33 +00001628#define MAKE_STOREV4(nAME,iS_BIGENDIAN) \
1629 \
1630 VG_REGPARM(2) \
1631 void nAME ( Addr aA, UWord vbytes ) \
1632 { \
1633 PROF_EVENT(230, #nAME); \
1634 \
1635 if (VG_DEBUG_MEMORY >= 2) \
1636 mc_STOREVn_slow( aA, 4, (ULong)vbytes, iS_BIGENDIAN ); \
1637 \
1638 const UWord mask = ~((0x10000-4) | ((N_PRIMARY_MAP-1) << 16)); \
1639 UWord a = (UWord)aA; \
1640 \
1641 /* If any part of 'a' indicated by the mask is 1, either */ \
1642 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1643 /* covered by the primary map. Either way we defer to the */ \
1644 /* slow-path case. */ \
1645 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1646 PROF_EVENT(231, #nAME"-slow1"); \
1647 mc_STOREVn_slow( aA, 4, (ULong)vbytes, iS_BIGENDIAN ); \
1648 return; \
1649 } \
1650 \
1651 UWord sec_no = (UWord)(a >> 16); \
1652 \
1653 if (VG_DEBUG_MEMORY >= 1) \
1654 tl_assert(sec_no < N_PRIMARY_MAP); \
1655 \
1656 SecMap* sm = primary_map[sec_no]; \
1657 UWord v_off = a & 0xFFFF; \
1658 UWord a_off = v_off >> 3; \
1659 UWord abits = (UWord)(sm->abits[a_off]); \
1660 abits >>= (a & 4); \
1661 abits &= 15; \
1662 if (EXPECTED_TAKEN(!is_distinguished_sm(sm) \
1663 && abits == VGM_NIBBLE_VALID)) { \
1664 /* Handle common case quickly: a is suitably aligned, */ \
1665 /* is mapped, and is addressible. */ \
1666 ((UInt*)(sm->vbyte))[ v_off >> 2 ] = (UInt)vbytes; \
1667 } else { \
1668 /* Slow but general case. */ \
1669 PROF_EVENT(232, #nAME"-slow2"); \
1670 mc_STOREVn_slow( aA, 4, (ULong)vbytes, iS_BIGENDIAN ); \
1671 } \
sewardjc1a2cda2005-04-21 17:34:00 +00001672 }
1673
sewardj8cf88b72005-07-08 01:29:33 +00001674MAKE_STOREV4( MC_(helperc_STOREV4be), True /*bigendian*/ );
1675MAKE_STOREV4( MC_(helperc_STOREV4le), False/*littleendian*/ );
njn25e49d8e72002-09-23 09:36:25 +00001676
njn25e49d8e72002-09-23 09:36:25 +00001677
sewardj95448072004-11-22 20:19:51 +00001678/* ------------------------ Size = 2 ------------------------ */
1679
sewardj8cf88b72005-07-08 01:29:33 +00001680#define MAKE_LOADV2(nAME,iS_BIGENDIAN) \
1681 \
1682 VG_REGPARM(1) \
1683 UWord nAME ( Addr aA ) \
1684 { \
1685 PROF_EVENT(240, #nAME); \
1686 \
1687 if (VG_DEBUG_MEMORY >= 2) \
1688 return (UWord)mc_LOADVn_slow( aA, 2, iS_BIGENDIAN ); \
1689 \
1690 const UWord mask = ~((0x10000-2) | ((N_PRIMARY_MAP-1) << 16)); \
1691 UWord a = (UWord)aA; \
1692 \
1693 /* If any part of 'a' indicated by the mask is 1, either */ \
1694 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1695 /* covered by the primary map. Either way we defer to the */ \
1696 /* slow-path case. */ \
1697 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1698 PROF_EVENT(241, #nAME"-slow1"); \
1699 return (UWord)mc_LOADVn_slow( aA, 2, iS_BIGENDIAN ); \
1700 } \
1701 \
1702 UWord sec_no = (UWord)(a >> 16); \
1703 \
1704 if (VG_DEBUG_MEMORY >= 1) \
1705 tl_assert(sec_no < N_PRIMARY_MAP); \
1706 \
1707 SecMap* sm = primary_map[sec_no]; \
1708 UWord v_off = a & 0xFFFF; \
1709 UWord a_off = v_off >> 3; \
1710 UWord abits = (UWord)(sm->abits[a_off]); \
1711 if (EXPECTED_TAKEN(abits == VGM_BYTE_VALID)) { \
1712 /* Handle common case quickly: a is mapped, and the */ \
1713 /* entire word32 it lives in is addressible. */ \
1714 /* Set the upper 16/48 bits of the result to 1 */ \
1715 /* ("undefined"), just in case. This almost certainly */ \
1716 /* isn't necessary, but be paranoid. */ \
1717 return (~(UWord)0xFFFF) \
1718 | \
1719 (UWord)( ((UShort*)(sm->vbyte))[ v_off >> 1 ] ); \
1720 } else { \
1721 /* Slow but general case. */ \
1722 PROF_EVENT(242, #nAME"-slow2"); \
1723 return (UWord)mc_LOADVn_slow( aA, 2, iS_BIGENDIAN ); \
1724 } \
sewardjc1a2cda2005-04-21 17:34:00 +00001725 }
1726
sewardj8cf88b72005-07-08 01:29:33 +00001727MAKE_LOADV2( MC_(helperc_LOADV2be), True /*bigendian*/ );
1728MAKE_LOADV2( MC_(helperc_LOADV2le), False/*littleendian*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001729
sewardjc1a2cda2005-04-21 17:34:00 +00001730
sewardj8cf88b72005-07-08 01:29:33 +00001731#define MAKE_STOREV2(nAME,iS_BIGENDIAN) \
1732 \
1733 VG_REGPARM(2) \
1734 void nAME ( Addr aA, UWord vbytes ) \
1735 { \
1736 PROF_EVENT(250, #nAME); \
1737 \
1738 if (VG_DEBUG_MEMORY >= 2) \
1739 mc_STOREVn_slow( aA, 2, (ULong)vbytes, iS_BIGENDIAN ); \
1740 \
1741 const UWord mask = ~((0x10000-2) | ((N_PRIMARY_MAP-1) << 16)); \
1742 UWord a = (UWord)aA; \
1743 \
1744 /* If any part of 'a' indicated by the mask is 1, either */ \
1745 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1746 /* covered by the primary map. Either way we defer to the */ \
1747 /* slow-path case. */ \
1748 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1749 PROF_EVENT(251, #nAME"-slow1"); \
1750 mc_STOREVn_slow( aA, 2, (ULong)vbytes, iS_BIGENDIAN ); \
1751 return; \
1752 } \
1753 \
1754 UWord sec_no = (UWord)(a >> 16); \
1755 \
1756 if (VG_DEBUG_MEMORY >= 1) \
1757 tl_assert(sec_no < N_PRIMARY_MAP); \
1758 \
1759 SecMap* sm = primary_map[sec_no]; \
1760 UWord v_off = a & 0xFFFF; \
1761 UWord a_off = v_off >> 3; \
1762 UWord abits = (UWord)(sm->abits[a_off]); \
1763 if (EXPECTED_TAKEN(!is_distinguished_sm(sm) \
1764 && abits == VGM_BYTE_VALID)) { \
1765 /* Handle common case quickly. */ \
1766 ((UShort*)(sm->vbyte))[ v_off >> 1 ] = (UShort)vbytes; \
1767 } else { \
1768 /* Slow but general case. */ \
1769 PROF_EVENT(252, #nAME"-slow2"); \
1770 mc_STOREVn_slow( aA, 2, (ULong)vbytes, iS_BIGENDIAN ); \
1771 } \
sewardjc1a2cda2005-04-21 17:34:00 +00001772 }
1773
njn25e49d8e72002-09-23 09:36:25 +00001774
sewardj8cf88b72005-07-08 01:29:33 +00001775MAKE_STOREV2( MC_(helperc_STOREV2be), True /*bigendian*/ );
1776MAKE_STOREV2( MC_(helperc_STOREV2le), False/*littleendian*/ );
sewardj5d28efc2005-04-21 22:16:29 +00001777
njn25e49d8e72002-09-23 09:36:25 +00001778
sewardj95448072004-11-22 20:19:51 +00001779/* ------------------------ Size = 1 ------------------------ */
sewardj8cf88b72005-07-08 01:29:33 +00001780/* Note: endianness is irrelevant for size == 1 */
sewardj95448072004-11-22 20:19:51 +00001781
njnaf839f52005-06-23 03:27:57 +00001782VG_REGPARM(1)
sewardj8cf88b72005-07-08 01:29:33 +00001783UWord MC_(helperc_LOADV1) ( Addr aA )
njn25e49d8e72002-09-23 09:36:25 +00001784{
sewardj8cf88b72005-07-08 01:29:33 +00001785 PROF_EVENT(260, "helperc_LOADV1");
sewardjc1a2cda2005-04-21 17:34:00 +00001786
1787# if VG_DEBUG_MEMORY >= 2
sewardj8cf88b72005-07-08 01:29:33 +00001788 return (UWord)mc_LOADVn_slow( aA, 1, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001789# else
1790
sewardj23eb2fd2005-04-22 16:29:19 +00001791 const UWord mask = ~((0x10000-1) | ((N_PRIMARY_MAP-1) << 16));
sewardjc1a2cda2005-04-21 17:34:00 +00001792 UWord a = (UWord)aA;
1793
1794 /* If any part of 'a' indicated by the mask is 1, it means 'a'
1795 exceeds the range covered by the primary map. In which case we
1796 defer to the slow-path case. */
1797 if (EXPECTED_NOT_TAKEN(a & mask)) {
sewardj8cf88b72005-07-08 01:29:33 +00001798 PROF_EVENT(261, "helperc_LOADV1-slow1");
1799 return (UWord)mc_LOADVn_slow( aA, 1, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001800 }
1801
1802 UWord sec_no = (UWord)(a >> 16);
1803
1804# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +00001805 tl_assert(sec_no < N_PRIMARY_MAP);
sewardjc1a2cda2005-04-21 17:34:00 +00001806# endif
1807
1808 SecMap* sm = primary_map[sec_no];
1809 UWord v_off = a & 0xFFFF;
1810 UWord a_off = v_off >> 3;
sewardj5d28efc2005-04-21 22:16:29 +00001811 UWord abits = (UWord)(sm->abits[a_off]);
sewardjc1a2cda2005-04-21 17:34:00 +00001812 if (EXPECTED_TAKEN(abits == VGM_BYTE_VALID)) {
1813 /* Handle common case quickly: a is mapped, and the entire
1814 word32 it lives in is addressible. */
sewardj5d28efc2005-04-21 22:16:29 +00001815 /* Set the upper 24/56 bits of the result to 1 ("undefined"),
1816 just in case. This almost certainly isn't necessary, but be
1817 paranoid. */
sewardjc1a2cda2005-04-21 17:34:00 +00001818 return (~(UWord)0xFF)
1819 |
1820 (UWord)( ((UChar*)(sm->vbyte))[ v_off ] );
1821 } else {
1822 /* Slow but general case. */
sewardj8cf88b72005-07-08 01:29:33 +00001823 PROF_EVENT(262, "helperc_LOADV1-slow2");
1824 return (UWord)mc_LOADVn_slow( aA, 1, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001825 }
1826# endif
njn25e49d8e72002-09-23 09:36:25 +00001827}
1828
sewardjc1a2cda2005-04-21 17:34:00 +00001829
njnaf839f52005-06-23 03:27:57 +00001830VG_REGPARM(2)
sewardj8cf88b72005-07-08 01:29:33 +00001831void MC_(helperc_STOREV1) ( Addr aA, UWord vbyte )
njn25e49d8e72002-09-23 09:36:25 +00001832{
sewardj8cf88b72005-07-08 01:29:33 +00001833 PROF_EVENT(270, "helperc_STOREV1");
sewardjc1a2cda2005-04-21 17:34:00 +00001834
1835# if VG_DEBUG_MEMORY >= 2
sewardj8cf88b72005-07-08 01:29:33 +00001836 mc_STOREVn_slow( aA, 1, (ULong)vbyte, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001837# else
1838
sewardj23eb2fd2005-04-22 16:29:19 +00001839 const UWord mask = ~((0x10000-1) | ((N_PRIMARY_MAP-1) << 16));
sewardjc1a2cda2005-04-21 17:34:00 +00001840 UWord a = (UWord)aA;
1841 /* If any part of 'a' indicated by the mask is 1, it means 'a'
1842 exceeds the range covered by the primary map. In which case we
1843 defer to the slow-path case. */
1844 if (EXPECTED_NOT_TAKEN(a & mask)) {
sewardj8cf88b72005-07-08 01:29:33 +00001845 PROF_EVENT(271, "helperc_STOREV1-slow1");
1846 mc_STOREVn_slow( aA, 1, (ULong)vbyte, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001847 return;
1848 }
1849
1850 UWord sec_no = (UWord)(a >> 16);
1851
1852# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +00001853 tl_assert(sec_no < N_PRIMARY_MAP);
sewardjc1a2cda2005-04-21 17:34:00 +00001854# endif
1855
1856 SecMap* sm = primary_map[sec_no];
1857 UWord v_off = a & 0xFFFF;
1858 UWord a_off = v_off >> 3;
sewardj5d28efc2005-04-21 22:16:29 +00001859 UWord abits = (UWord)(sm->abits[a_off]);
sewardjc1a2cda2005-04-21 17:34:00 +00001860 if (EXPECTED_TAKEN(!is_distinguished_sm(sm)
1861 && abits == VGM_BYTE_VALID)) {
1862 /* Handle common case quickly: a is mapped, the entire word32 it
1863 lives in is addressible. */
1864 ((UChar*)(sm->vbyte))[ v_off ] = (UChar)vbyte;
1865 } else {
sewardj8cf88b72005-07-08 01:29:33 +00001866 PROF_EVENT(272, "helperc_STOREV1-slow2");
1867 mc_STOREVn_slow( aA, 1, (ULong)vbyte, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001868 }
1869
1870# endif
njn25e49d8e72002-09-23 09:36:25 +00001871}
1872
1873
sewardjc859fbf2005-04-22 21:10:28 +00001874/*------------------------------------------------------------*/
1875/*--- Functions called directly from generated code: ---*/
1876/*--- Value-check failure handlers. ---*/
1877/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00001878
njn5c004e42002-11-18 11:04:50 +00001879void MC_(helperc_value_check0_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001880{
njn9e63cb62005-05-08 18:34:59 +00001881 mc_record_value_error ( VG_(get_running_tid)(), 0 );
njn25e49d8e72002-09-23 09:36:25 +00001882}
1883
njn5c004e42002-11-18 11:04:50 +00001884void MC_(helperc_value_check1_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001885{
njn9e63cb62005-05-08 18:34:59 +00001886 mc_record_value_error ( VG_(get_running_tid)(), 1 );
njn25e49d8e72002-09-23 09:36:25 +00001887}
1888
njn5c004e42002-11-18 11:04:50 +00001889void MC_(helperc_value_check4_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001890{
njn9e63cb62005-05-08 18:34:59 +00001891 mc_record_value_error ( VG_(get_running_tid)(), 4 );
njn25e49d8e72002-09-23 09:36:25 +00001892}
1893
sewardj11bcc4e2005-04-23 22:38:38 +00001894void MC_(helperc_value_check8_fail) ( void )
1895{
njn9e63cb62005-05-08 18:34:59 +00001896 mc_record_value_error ( VG_(get_running_tid)(), 8 );
sewardj11bcc4e2005-04-23 22:38:38 +00001897}
1898
njnaf839f52005-06-23 03:27:57 +00001899VG_REGPARM(1) void MC_(helperc_complain_undef) ( HWord sz )
sewardj95448072004-11-22 20:19:51 +00001900{
njn9e63cb62005-05-08 18:34:59 +00001901 mc_record_value_error ( VG_(get_running_tid)(), (Int)sz );
sewardj95448072004-11-22 20:19:51 +00001902}
1903
njn25e49d8e72002-09-23 09:36:25 +00001904
sewardj45d94cc2005-04-20 14:44:11 +00001905//zz /*------------------------------------------------------------*/
1906//zz /*--- Metadata get/set functions, for client requests. ---*/
1907//zz /*------------------------------------------------------------*/
1908//zz
1909//zz /* Copy Vbits for src into vbits. Returns: 1 == OK, 2 == alignment
1910//zz error, 3 == addressing error. */
1911//zz static Int mc_get_or_set_vbits_for_client (
1912//zz ThreadId tid,
1913//zz Addr dataV,
1914//zz Addr vbitsV,
1915//zz SizeT size,
1916//zz Bool setting /* True <=> set vbits, False <=> get vbits */
1917//zz )
1918//zz {
1919//zz Bool addressibleD = True;
1920//zz Bool addressibleV = True;
1921//zz UInt* data = (UInt*)dataV;
1922//zz UInt* vbits = (UInt*)vbitsV;
1923//zz SizeT szW = size / 4; /* sigh */
1924//zz SizeT i;
1925//zz UInt* dataP = NULL; /* bogus init to keep gcc happy */
1926//zz UInt* vbitsP = NULL; /* ditto */
1927//zz
1928//zz /* Check alignment of args. */
1929//zz if (!(VG_IS_4_ALIGNED(data) && VG_IS_4_ALIGNED(vbits)))
1930//zz return 2;
1931//zz if ((size & 3) != 0)
1932//zz return 2;
1933//zz
1934//zz /* Check that arrays are addressible. */
1935//zz for (i = 0; i < szW; i++) {
1936//zz dataP = &data[i];
1937//zz vbitsP = &vbits[i];
1938//zz if (get_abits4_ALIGNED((Addr)dataP) != VGM_NIBBLE_VALID) {
1939//zz addressibleD = False;
1940//zz break;
1941//zz }
1942//zz if (get_abits4_ALIGNED((Addr)vbitsP) != VGM_NIBBLE_VALID) {
1943//zz addressibleV = False;
1944//zz break;
1945//zz }
1946//zz }
1947//zz if (!addressibleD) {
1948//zz MAC_(record_address_error)( tid, (Addr)dataP, 4,
1949//zz setting ? True : False );
1950//zz return 3;
1951//zz }
1952//zz if (!addressibleV) {
1953//zz MAC_(record_address_error)( tid, (Addr)vbitsP, 4,
1954//zz setting ? False : True );
1955//zz return 3;
1956//zz }
1957//zz
1958//zz /* Do the copy */
1959//zz if (setting) {
1960//zz /* setting */
1961//zz for (i = 0; i < szW; i++) {
1962//zz if (get_vbytes4_ALIGNED( (Addr)&vbits[i] ) != VGM_WORD_VALID)
njn9e63cb62005-05-08 18:34:59 +00001963//zz mc_record_value_error(tid, 4);
sewardj45d94cc2005-04-20 14:44:11 +00001964//zz set_vbytes4_ALIGNED( (Addr)&data[i], vbits[i] );
1965//zz }
1966//zz } else {
1967//zz /* getting */
1968//zz for (i = 0; i < szW; i++) {
1969//zz vbits[i] = get_vbytes4_ALIGNED( (Addr)&data[i] );
1970//zz set_vbytes4_ALIGNED( (Addr)&vbits[i], VGM_WORD_VALID );
1971//zz }
1972//zz }
1973//zz
1974//zz return 1;
1975//zz }
sewardj05fe85e2005-04-27 22:46:36 +00001976
1977
1978/*------------------------------------------------------------*/
1979/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
1980/*------------------------------------------------------------*/
1981
1982/* For the memory leak detector, say whether an entire 64k chunk of
1983 address space is possibly in use, or not. If in doubt return
1984 True.
1985*/
1986static
1987Bool mc_is_within_valid_secondary ( Addr a )
1988{
1989 SecMap* sm = maybe_get_secmap_for ( a );
1990 if (sm == NULL || sm == &sm_distinguished[SM_DIST_NOACCESS]) {
1991 /* Definitely not in use. */
1992 return False;
1993 } else {
1994 return True;
1995 }
1996}
1997
1998
1999/* For the memory leak detector, say whether or not a given word
2000 address is to be regarded as valid. */
2001static
2002Bool mc_is_valid_aligned_word ( Addr a )
2003{
2004 tl_assert(sizeof(UWord) == 4 || sizeof(UWord) == 8);
2005 if (sizeof(UWord) == 4) {
2006 tl_assert(VG_IS_4_ALIGNED(a));
2007 } else {
2008 tl_assert(VG_IS_8_ALIGNED(a));
2009 }
2010 if (mc_check_readable( a, sizeof(UWord), NULL ) == MC_Ok) {
2011 return True;
2012 } else {
2013 return False;
2014 }
2015}
sewardja4495682002-10-21 07:29:59 +00002016
2017
nethercote996901a2004-08-03 13:29:09 +00002018/* Leak detector for this tool. We don't actually do anything, merely
sewardja4495682002-10-21 07:29:59 +00002019 run the generic leak detector with suitable parameters for this
nethercote996901a2004-08-03 13:29:09 +00002020 tool. */
njnb8dca862005-03-14 02:42:44 +00002021static void mc_detect_memory_leaks ( ThreadId tid, LeakCheckMode mode )
njn25e49d8e72002-09-23 09:36:25 +00002022{
sewardj05fe85e2005-04-27 22:46:36 +00002023 MAC_(do_detect_memory_leaks) (
2024 tid,
2025 mode,
2026 mc_is_within_valid_secondary,
2027 mc_is_valid_aligned_word
2028 );
njn25e49d8e72002-09-23 09:36:25 +00002029}
2030
2031
sewardjc859fbf2005-04-22 21:10:28 +00002032/*------------------------------------------------------------*/
2033/*--- Initialisation ---*/
2034/*------------------------------------------------------------*/
2035
2036static void init_shadow_memory ( void )
2037{
2038 Int i;
2039 SecMap* sm;
2040
2041 /* Build the 3 distinguished secondaries */
2042 tl_assert(VGM_BIT_INVALID == 1);
2043 tl_assert(VGM_BIT_VALID == 0);
2044 tl_assert(VGM_BYTE_INVALID == 0xFF);
2045 tl_assert(VGM_BYTE_VALID == 0);
2046
2047 /* Set A invalid, V invalid. */
2048 sm = &sm_distinguished[SM_DIST_NOACCESS];
2049 for (i = 0; i < 65536; i++)
2050 sm->vbyte[i] = VGM_BYTE_INVALID;
2051 for (i = 0; i < 8192; i++)
2052 sm->abits[i] = VGM_BYTE_INVALID;
2053
2054 /* Set A valid, V invalid. */
2055 sm = &sm_distinguished[SM_DIST_ACCESS_UNDEFINED];
2056 for (i = 0; i < 65536; i++)
2057 sm->vbyte[i] = VGM_BYTE_INVALID;
2058 for (i = 0; i < 8192; i++)
2059 sm->abits[i] = VGM_BYTE_VALID;
2060
2061 /* Set A valid, V valid. */
2062 sm = &sm_distinguished[SM_DIST_ACCESS_DEFINED];
2063 for (i = 0; i < 65536; i++)
2064 sm->vbyte[i] = VGM_BYTE_VALID;
2065 for (i = 0; i < 8192; i++)
2066 sm->abits[i] = VGM_BYTE_VALID;
2067
2068 /* Set up the primary map. */
2069 /* These entries gradually get overwritten as the used address
2070 space expands. */
2071 for (i = 0; i < N_PRIMARY_MAP; i++)
2072 primary_map[i] = &sm_distinguished[SM_DIST_NOACCESS];
2073
2074 /* auxmap_size = auxmap_used = 0;
2075 no ... these are statically initialised */
2076}
2077
2078
2079/*------------------------------------------------------------*/
2080/*--- Sanity check machinery (permanently engaged) ---*/
2081/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00002082
njn51d827b2005-05-09 01:02:08 +00002083static Bool mc_cheap_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00002084{
jseward9800fd32004-01-04 23:08:04 +00002085 /* nothing useful we can rapidly check */
sewardj23eb2fd2005-04-22 16:29:19 +00002086 n_sanity_cheap++;
sewardjc1a2cda2005-04-21 17:34:00 +00002087 PROF_EVENT(490, "cheap_sanity_check");
jseward9800fd32004-01-04 23:08:04 +00002088 return True;
njn25e49d8e72002-09-23 09:36:25 +00002089}
2090
njn51d827b2005-05-09 01:02:08 +00002091static Bool mc_expensive_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00002092{
sewardj23eb2fd2005-04-22 16:29:19 +00002093 Int i, n_secmaps_found;
sewardj45d94cc2005-04-20 14:44:11 +00002094 SecMap* sm;
sewardj23eb2fd2005-04-22 16:29:19 +00002095 Bool bad = False;
njn25e49d8e72002-09-23 09:36:25 +00002096
sewardj23eb2fd2005-04-22 16:29:19 +00002097 n_sanity_expensive++;
sewardjc1a2cda2005-04-21 17:34:00 +00002098 PROF_EVENT(491, "expensive_sanity_check");
2099
sewardj23eb2fd2005-04-22 16:29:19 +00002100 /* Check that the 3 distinguished SMs are still as they should
2101 be. */
njn25e49d8e72002-09-23 09:36:25 +00002102
sewardj45d94cc2005-04-20 14:44:11 +00002103 /* Check A invalid, V invalid. */
2104 sm = &sm_distinguished[SM_DIST_NOACCESS];
njn25e49d8e72002-09-23 09:36:25 +00002105 for (i = 0; i < 65536; i++)
sewardj45d94cc2005-04-20 14:44:11 +00002106 if (!(sm->vbyte[i] == VGM_BYTE_INVALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002107 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00002108 for (i = 0; i < 8192; i++)
2109 if (!(sm->abits[i] == VGM_BYTE_INVALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002110 bad = True;
njn25e49d8e72002-09-23 09:36:25 +00002111
sewardj45d94cc2005-04-20 14:44:11 +00002112 /* Check A valid, V invalid. */
2113 sm = &sm_distinguished[SM_DIST_ACCESS_UNDEFINED];
2114 for (i = 0; i < 65536; i++)
2115 if (!(sm->vbyte[i] == VGM_BYTE_INVALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002116 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00002117 for (i = 0; i < 8192; i++)
2118 if (!(sm->abits[i] == VGM_BYTE_VALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002119 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00002120
2121 /* Check A valid, V valid. */
2122 sm = &sm_distinguished[SM_DIST_ACCESS_DEFINED];
2123 for (i = 0; i < 65536; i++)
2124 if (!(sm->vbyte[i] == VGM_BYTE_VALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002125 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00002126 for (i = 0; i < 8192; i++)
2127 if (!(sm->abits[i] == VGM_BYTE_VALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002128 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00002129
sewardj23eb2fd2005-04-22 16:29:19 +00002130 if (bad) {
2131 VG_(printf)("memcheck expensive sanity: "
2132 "distinguished_secondaries have changed\n");
2133 return False;
2134 }
2135
2136 /* check nonsensical auxmap sizing */
sewardj45d94cc2005-04-20 14:44:11 +00002137 if (auxmap_used > auxmap_size)
sewardj23eb2fd2005-04-22 16:29:19 +00002138 bad = True;
2139
2140 if (bad) {
2141 VG_(printf)("memcheck expensive sanity: "
2142 "nonsensical auxmap sizing\n");
2143 return False;
2144 }
2145
2146 /* check that the number of secmaps issued matches the number that
2147 are reachable (iow, no secmap leaks) */
2148 n_secmaps_found = 0;
2149 for (i = 0; i < N_PRIMARY_MAP; i++) {
2150 if (primary_map[i] == NULL) {
2151 bad = True;
2152 } else {
2153 if (!is_distinguished_sm(primary_map[i]))
2154 n_secmaps_found++;
2155 }
2156 }
2157
2158 for (i = 0; i < auxmap_used; i++) {
2159 if (auxmap[i].sm == NULL) {
2160 bad = True;
2161 } else {
2162 if (!is_distinguished_sm(auxmap[i].sm))
2163 n_secmaps_found++;
2164 }
2165 }
2166
2167 if (n_secmaps_found != n_secmaps_issued)
2168 bad = True;
2169
2170 if (bad) {
2171 VG_(printf)("memcheck expensive sanity: "
2172 "apparent secmap leakage\n");
2173 return False;
2174 }
2175
2176 /* check that auxmap only covers address space that the primary
2177 doesn't */
2178
2179 for (i = 0; i < auxmap_used; i++)
2180 if (auxmap[i].base <= MAX_PRIMARY_ADDRESS)
2181 bad = True;
2182
2183 if (bad) {
2184 VG_(printf)("memcheck expensive sanity: "
2185 "auxmap covers wrong address space\n");
2186 return False;
2187 }
2188
2189 /* there is only one pointer to each secmap (expensive) */
njn25e49d8e72002-09-23 09:36:25 +00002190
2191 return True;
2192}
sewardj45d94cc2005-04-20 14:44:11 +00002193
njn25e49d8e72002-09-23 09:36:25 +00002194
njn25e49d8e72002-09-23 09:36:25 +00002195/*------------------------------------------------------------*/
njnd3040452003-05-19 15:04:06 +00002196/*--- Command line args ---*/
njn25e49d8e72002-09-23 09:36:25 +00002197/*------------------------------------------------------------*/
2198
njn51d827b2005-05-09 01:02:08 +00002199Bool MC_(clo_avoid_strlen_errors) = True;
njn43c799e2003-04-08 00:08:52 +00002200
njn51d827b2005-05-09 01:02:08 +00002201static Bool mc_process_cmd_line_option(Char* arg)
njn25e49d8e72002-09-23 09:36:25 +00002202{
njn45270a22005-03-27 01:00:11 +00002203 VG_BOOL_CLO(arg, "--avoid-strlen-errors", MC_(clo_avoid_strlen_errors))
njn25e49d8e72002-09-23 09:36:25 +00002204 else
njn43c799e2003-04-08 00:08:52 +00002205 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00002206
2207 return True;
njn25e49d8e72002-09-23 09:36:25 +00002208}
2209
njn51d827b2005-05-09 01:02:08 +00002210static void mc_print_usage(void)
njn25e49d8e72002-09-23 09:36:25 +00002211{
njn3e884182003-04-15 13:03:23 +00002212 MAC_(print_common_usage)();
2213 VG_(printf)(
2214" --avoid-strlen-errors=no|yes suppress errs from inlined strlen [yes]\n"
2215 );
2216}
2217
njn51d827b2005-05-09 01:02:08 +00002218static void mc_print_debug_usage(void)
njn3e884182003-04-15 13:03:23 +00002219{
2220 MAC_(print_common_debug_usage)();
2221 VG_(printf)(
sewardj8ec2cfc2002-10-13 00:57:26 +00002222" --cleanup=no|yes improve after instrumentation? [yes]\n"
njn3e884182003-04-15 13:03:23 +00002223 );
njn25e49d8e72002-09-23 09:36:25 +00002224}
2225
nethercote8b76fe52004-11-08 19:20:09 +00002226/*------------------------------------------------------------*/
2227/*--- Client requests ---*/
2228/*------------------------------------------------------------*/
2229
2230/* Client block management:
2231
2232 This is managed as an expanding array of client block descriptors.
2233 Indices of live descriptors are issued to the client, so it can ask
2234 to free them later. Therefore we cannot slide live entries down
2235 over dead ones. Instead we must use free/inuse flags and scan for
2236 an empty slot at allocation time. This in turn means allocation is
2237 relatively expensive, so we hope this does not happen too often.
nethercote8b76fe52004-11-08 19:20:09 +00002238
sewardjedc75ab2005-03-15 23:30:32 +00002239 An unused block has start == size == 0
2240*/
nethercote8b76fe52004-11-08 19:20:09 +00002241
2242typedef
2243 struct {
2244 Addr start;
2245 SizeT size;
2246 ExeContext* where;
sewardj8cf88b72005-07-08 01:29:33 +00002247 Char* desc;
nethercote8b76fe52004-11-08 19:20:09 +00002248 }
2249 CGenBlock;
2250
2251/* This subsystem is self-initialising. */
njn695c16e2005-03-27 03:40:28 +00002252static UInt cgb_size = 0;
2253static UInt cgb_used = 0;
2254static CGenBlock* cgbs = NULL;
nethercote8b76fe52004-11-08 19:20:09 +00002255
2256/* Stats for this subsystem. */
njn695c16e2005-03-27 03:40:28 +00002257static UInt cgb_used_MAX = 0; /* Max in use. */
2258static UInt cgb_allocs = 0; /* Number of allocs. */
2259static UInt cgb_discards = 0; /* Number of discards. */
2260static UInt cgb_search = 0; /* Number of searches. */
nethercote8b76fe52004-11-08 19:20:09 +00002261
2262
2263static
njn695c16e2005-03-27 03:40:28 +00002264Int alloc_client_block ( void )
nethercote8b76fe52004-11-08 19:20:09 +00002265{
2266 UInt i, sz_new;
2267 CGenBlock* cgbs_new;
2268
njn695c16e2005-03-27 03:40:28 +00002269 cgb_allocs++;
nethercote8b76fe52004-11-08 19:20:09 +00002270
njn695c16e2005-03-27 03:40:28 +00002271 for (i = 0; i < cgb_used; i++) {
2272 cgb_search++;
2273 if (cgbs[i].start == 0 && cgbs[i].size == 0)
nethercote8b76fe52004-11-08 19:20:09 +00002274 return i;
2275 }
2276
2277 /* Not found. Try to allocate one at the end. */
njn695c16e2005-03-27 03:40:28 +00002278 if (cgb_used < cgb_size) {
2279 cgb_used++;
2280 return cgb_used-1;
nethercote8b76fe52004-11-08 19:20:09 +00002281 }
2282
2283 /* Ok, we have to allocate a new one. */
njn695c16e2005-03-27 03:40:28 +00002284 tl_assert(cgb_used == cgb_size);
2285 sz_new = (cgbs == NULL) ? 10 : (2 * cgb_size);
nethercote8b76fe52004-11-08 19:20:09 +00002286
2287 cgbs_new = VG_(malloc)( sz_new * sizeof(CGenBlock) );
njn695c16e2005-03-27 03:40:28 +00002288 for (i = 0; i < cgb_used; i++)
2289 cgbs_new[i] = cgbs[i];
nethercote8b76fe52004-11-08 19:20:09 +00002290
njn695c16e2005-03-27 03:40:28 +00002291 if (cgbs != NULL)
2292 VG_(free)( cgbs );
2293 cgbs = cgbs_new;
nethercote8b76fe52004-11-08 19:20:09 +00002294
njn695c16e2005-03-27 03:40:28 +00002295 cgb_size = sz_new;
2296 cgb_used++;
2297 if (cgb_used > cgb_used_MAX)
2298 cgb_used_MAX = cgb_used;
2299 return cgb_used-1;
nethercote8b76fe52004-11-08 19:20:09 +00002300}
2301
2302
2303static void show_client_block_stats ( void )
2304{
2305 VG_(message)(Vg_DebugMsg,
2306 "general CBs: %d allocs, %d discards, %d maxinuse, %d search",
njn695c16e2005-03-27 03:40:28 +00002307 cgb_allocs, cgb_discards, cgb_used_MAX, cgb_search
nethercote8b76fe52004-11-08 19:20:09 +00002308 );
2309}
2310
nethercote8b76fe52004-11-08 19:20:09 +00002311static Bool client_perm_maybe_describe( Addr a, AddrInfo* ai )
2312{
2313 UInt i;
2314 /* VG_(printf)("try to identify %d\n", a); */
2315
2316 /* Perhaps it's a general block ? */
njn695c16e2005-03-27 03:40:28 +00002317 for (i = 0; i < cgb_used; i++) {
2318 if (cgbs[i].start == 0 && cgbs[i].size == 0)
nethercote8b76fe52004-11-08 19:20:09 +00002319 continue;
njn717cde52005-05-10 02:47:21 +00002320 // Use zero as the redzone for client blocks.
2321 if (VG_(addr_is_in_block)(a, cgbs[i].start, cgbs[i].size, 0)) {
nethercote8b76fe52004-11-08 19:20:09 +00002322 /* OK - maybe it's a mempool, too? */
njn12627272005-08-14 18:32:16 +00002323 MAC_Mempool* mp = VG_(HT_lookup)(MAC_(mempool_list),
2324 (UWord)cgbs[i].start);
njn1d0cb0d2005-08-15 01:52:02 +00002325 if (mp != NULL) {
2326 if (mp->chunks != NULL) {
2327 MAC_Chunk* mc;
2328 VG_(OSet_ResetIter)(mp->chunks);
2329 while ( (mc = VG_(OSet_Next)(mp->chunks)) ) {
2330 if (VG_(addr_is_in_block)(a, mc->data, mc->size,
2331 MAC_MALLOC_REDZONE_SZB)) {
2332 ai->akind = UserG;
2333 ai->blksize = mc->size;
2334 ai->rwoffset = (Int)(a) - (Int)mc->data;
2335 ai->lastchange = mc->where;
2336 return True;
2337 }
nethercote8b76fe52004-11-08 19:20:09 +00002338 }
2339 }
njn1d0cb0d2005-08-15 01:52:02 +00002340 ai->akind = Mempool;
2341 ai->blksize = cgbs[i].size;
2342 ai->rwoffset = (Int)(a) - (Int)(cgbs[i].start);
njn695c16e2005-03-27 03:40:28 +00002343 ai->lastchange = cgbs[i].where;
nethercote8b76fe52004-11-08 19:20:09 +00002344 return True;
2345 }
njn1d0cb0d2005-08-15 01:52:02 +00002346 ai->akind = UserG;
2347 ai->blksize = cgbs[i].size;
2348 ai->rwoffset = (Int)(a) - (Int)(cgbs[i].start);
njn695c16e2005-03-27 03:40:28 +00002349 ai->lastchange = cgbs[i].where;
njn1d0cb0d2005-08-15 01:52:02 +00002350 ai->desc = cgbs[i].desc;
nethercote8b76fe52004-11-08 19:20:09 +00002351 return True;
2352 }
2353 }
2354 return False;
2355}
2356
njn51d827b2005-05-09 01:02:08 +00002357static Bool mc_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret )
nethercote8b76fe52004-11-08 19:20:09 +00002358{
2359 Int i;
2360 Bool ok;
2361 Addr bad_addr;
2362
njnfc26ff92004-11-22 19:12:49 +00002363 if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
nethercote8b76fe52004-11-08 19:20:09 +00002364 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
2365 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
2366 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
2367 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
2368 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
2369 && VG_USERREQ__MEMPOOL_FREE != arg[0])
2370 return False;
2371
2372 switch (arg[0]) {
2373 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
2374 ok = mc_check_writable ( arg[1], arg[2], &bad_addr );
2375 if (!ok)
njn9e63cb62005-05-08 18:34:59 +00002376 mc_record_user_error ( tid, bad_addr, /*isWrite*/True,
2377 /*isUnaddr*/True );
nethercote8b76fe52004-11-08 19:20:09 +00002378 *ret = ok ? (UWord)NULL : bad_addr;
sewardj8cf88b72005-07-08 01:29:33 +00002379 break;
nethercote8b76fe52004-11-08 19:20:09 +00002380
2381 case VG_USERREQ__CHECK_READABLE: { /* check readable */
2382 MC_ReadResult res;
2383 res = mc_check_readable ( arg[1], arg[2], &bad_addr );
2384 if (MC_AddrErr == res)
njn9e63cb62005-05-08 18:34:59 +00002385 mc_record_user_error ( tid, bad_addr, /*isWrite*/False,
2386 /*isUnaddr*/True );
nethercote8b76fe52004-11-08 19:20:09 +00002387 else if (MC_ValueErr == res)
njn9e63cb62005-05-08 18:34:59 +00002388 mc_record_user_error ( tid, bad_addr, /*isWrite*/False,
2389 /*isUnaddr*/False );
nethercote8b76fe52004-11-08 19:20:09 +00002390 *ret = ( res==MC_Ok ? (UWord)NULL : bad_addr );
sewardj8cf88b72005-07-08 01:29:33 +00002391 break;
nethercote8b76fe52004-11-08 19:20:09 +00002392 }
2393
2394 case VG_USERREQ__DO_LEAK_CHECK:
njnb8dca862005-03-14 02:42:44 +00002395 mc_detect_memory_leaks(tid, arg[1] ? LC_Summary : LC_Full);
sewardj8cf88b72005-07-08 01:29:33 +00002396 *ret = 0; /* return value is meaningless */
2397 break;
nethercote8b76fe52004-11-08 19:20:09 +00002398
2399 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
nethercote8b76fe52004-11-08 19:20:09 +00002400 mc_make_noaccess ( arg[1], arg[2] );
sewardj8cf88b72005-07-08 01:29:33 +00002401 *ret = -1;
2402 break;
nethercote8b76fe52004-11-08 19:20:09 +00002403
2404 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
nethercote8b76fe52004-11-08 19:20:09 +00002405 mc_make_writable ( arg[1], arg[2] );
sewardjedc75ab2005-03-15 23:30:32 +00002406 *ret = -1;
sewardj8cf88b72005-07-08 01:29:33 +00002407 break;
nethercote8b76fe52004-11-08 19:20:09 +00002408
2409 case VG_USERREQ__MAKE_READABLE: /* make readable */
nethercote8b76fe52004-11-08 19:20:09 +00002410 mc_make_readable ( arg[1], arg[2] );
sewardj8cf88b72005-07-08 01:29:33 +00002411 *ret = -1;
nethercote8b76fe52004-11-08 19:20:09 +00002412 break;
2413
sewardjedc75ab2005-03-15 23:30:32 +00002414 case VG_USERREQ__CREATE_BLOCK: /* describe a block */
sewardj8cf88b72005-07-08 01:29:33 +00002415 if (arg[1] != 0 && arg[2] != 0) {
2416 i = alloc_client_block();
2417 /* VG_(printf)("allocated %d %p\n", i, cgbs); */
2418 cgbs[i].start = arg[1];
2419 cgbs[i].size = arg[2];
2420 cgbs[i].desc = VG_(strdup)((Char *)arg[3]);
2421 cgbs[i].where = VG_(record_ExeContext) ( tid );
sewardjedc75ab2005-03-15 23:30:32 +00002422
sewardj8cf88b72005-07-08 01:29:33 +00002423 *ret = i;
2424 } else
2425 *ret = -1;
2426 break;
sewardjedc75ab2005-03-15 23:30:32 +00002427
nethercote8b76fe52004-11-08 19:20:09 +00002428 case VG_USERREQ__DISCARD: /* discard */
njn695c16e2005-03-27 03:40:28 +00002429 if (cgbs == NULL
2430 || arg[2] >= cgb_used ||
sewardj8cf88b72005-07-08 01:29:33 +00002431 (cgbs[arg[2]].start == 0 && cgbs[arg[2]].size == 0)) {
sewardjedc75ab2005-03-15 23:30:32 +00002432 *ret = 1;
sewardj8cf88b72005-07-08 01:29:33 +00002433 } else {
2434 tl_assert(arg[2] >= 0 && arg[2] < cgb_used);
2435 cgbs[arg[2]].start = cgbs[arg[2]].size = 0;
2436 VG_(free)(cgbs[arg[2]].desc);
2437 cgb_discards++;
2438 *ret = 0;
2439 }
2440 break;
nethercote8b76fe52004-11-08 19:20:09 +00002441
sewardj45d94cc2005-04-20 14:44:11 +00002442//zz case VG_USERREQ__GET_VBITS:
2443//zz /* Returns: 1 == OK, 2 == alignment error, 3 == addressing
2444//zz error. */
2445//zz /* VG_(printf)("get_vbits %p %p %d\n", arg[1], arg[2], arg[3] ); */
2446//zz *ret = mc_get_or_set_vbits_for_client
2447//zz ( tid, arg[1], arg[2], arg[3], False /* get them */ );
2448//zz break;
2449//zz
2450//zz case VG_USERREQ__SET_VBITS:
2451//zz /* Returns: 1 == OK, 2 == alignment error, 3 == addressing
2452//zz error. */
2453//zz /* VG_(printf)("set_vbits %p %p %d\n", arg[1], arg[2], arg[3] ); */
2454//zz *ret = mc_get_or_set_vbits_for_client
2455//zz ( tid, arg[1], arg[2], arg[3], True /* set them */ );
2456//zz break;
nethercote8b76fe52004-11-08 19:20:09 +00002457
2458 default:
2459 if (MAC_(handle_common_client_requests)(tid, arg, ret )) {
2460 return True;
2461 } else {
2462 VG_(message)(Vg_UserMsg,
2463 "Warning: unknown memcheck client request code %llx",
2464 (ULong)arg[0]);
2465 return False;
2466 }
2467 }
2468 return True;
2469}
njn25e49d8e72002-09-23 09:36:25 +00002470
2471/*------------------------------------------------------------*/
njn51d827b2005-05-09 01:02:08 +00002472/*--- Setup and finalisation ---*/
njn25e49d8e72002-09-23 09:36:25 +00002473/*------------------------------------------------------------*/
2474
njn51d827b2005-05-09 01:02:08 +00002475static void mc_post_clo_init ( void )
njn5c004e42002-11-18 11:04:50 +00002476{
sewardj71bc3cb2005-05-19 00:25:45 +00002477 /* If we've been asked to emit XML, mash around various other
2478 options so as to constrain the output somewhat. */
2479 if (VG_(clo_xml)) {
2480 /* Extract as much info as possible from the leak checker. */
sewardj09890d82005-05-20 02:45:15 +00002481 /* MAC_(clo_show_reachable) = True; */
sewardj71bc3cb2005-05-19 00:25:45 +00002482 MAC_(clo_leak_check) = LC_Full;
2483 }
njn5c004e42002-11-18 11:04:50 +00002484}
2485
njn51d827b2005-05-09 01:02:08 +00002486static void mc_fini ( Int exitcode )
njn5c004e42002-11-18 11:04:50 +00002487{
nethercote8b76fe52004-11-08 19:20:09 +00002488 MAC_(common_fini)( mc_detect_memory_leaks );
sewardj45d94cc2005-04-20 14:44:11 +00002489
sewardj23eb2fd2005-04-22 16:29:19 +00002490 Int i, n_accessible_dist;
2491 SecMap* sm;
2492
sewardj45d94cc2005-04-20 14:44:11 +00002493 if (VG_(clo_verbosity) > 1) {
2494 VG_(message)(Vg_DebugMsg,
sewardj23eb2fd2005-04-22 16:29:19 +00002495 " memcheck: sanity checks: %d cheap, %d expensive",
2496 n_sanity_cheap, n_sanity_expensive );
sewardj45d94cc2005-04-20 14:44:11 +00002497 VG_(message)(Vg_DebugMsg,
sewardj23eb2fd2005-04-22 16:29:19 +00002498 " memcheck: auxmaps: %d auxmap entries (%dk, %dM) in use",
2499 auxmap_used,
2500 auxmap_used * 64,
2501 auxmap_used / 16 );
2502 VG_(message)(Vg_DebugMsg,
2503 " memcheck: auxmaps: %lld searches, %lld comparisons",
sewardj45d94cc2005-04-20 14:44:11 +00002504 n_auxmap_searches, n_auxmap_cmps );
sewardj23eb2fd2005-04-22 16:29:19 +00002505 VG_(message)(Vg_DebugMsg,
2506 " memcheck: secondaries: %d issued (%dk, %dM)",
2507 n_secmaps_issued,
2508 n_secmaps_issued * 64,
2509 n_secmaps_issued / 16 );
2510
2511 n_accessible_dist = 0;
2512 for (i = 0; i < N_PRIMARY_MAP; i++) {
2513 sm = primary_map[i];
2514 if (is_distinguished_sm(sm)
2515 && sm != &sm_distinguished[SM_DIST_NOACCESS])
2516 n_accessible_dist ++;
2517 }
2518 for (i = 0; i < auxmap_used; i++) {
2519 sm = auxmap[i].sm;
2520 if (is_distinguished_sm(sm)
2521 && sm != &sm_distinguished[SM_DIST_NOACCESS])
2522 n_accessible_dist ++;
2523 }
2524
2525 VG_(message)(Vg_DebugMsg,
2526 " memcheck: secondaries: %d accessible and distinguished (%dk, %dM)",
2527 n_accessible_dist,
2528 n_accessible_dist * 64,
2529 n_accessible_dist / 16 );
2530
sewardj45d94cc2005-04-20 14:44:11 +00002531 }
2532
njn5c004e42002-11-18 11:04:50 +00002533 if (0) {
2534 VG_(message)(Vg_DebugMsg,
2535 "------ Valgrind's client block stats follow ---------------" );
nethercote8b76fe52004-11-08 19:20:09 +00002536 show_client_block_stats();
njn5c004e42002-11-18 11:04:50 +00002537 }
njn25e49d8e72002-09-23 09:36:25 +00002538}
2539
njn51d827b2005-05-09 01:02:08 +00002540static void mc_pre_clo_init(void)
2541{
2542 VG_(details_name) ("Memcheck");
2543 VG_(details_version) (NULL);
2544 VG_(details_description) ("a memory error detector");
2545 VG_(details_copyright_author)(
2546 "Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.");
2547 VG_(details_bug_reports_to) (VG_BUGS_TO);
2548 VG_(details_avg_translation_sizeB) ( 370 );
2549
2550 VG_(basic_tool_funcs) (mc_post_clo_init,
2551 MC_(instrument),
2552 mc_fini);
2553
2554 VG_(needs_core_errors) ();
2555 VG_(needs_tool_errors) (MAC_(eq_Error),
2556 mc_pp_Error,
2557 MAC_(update_extra),
2558 mc_recognised_suppression,
2559 MAC_(read_extra_suppression_info),
2560 MAC_(error_matches_suppression),
2561 MAC_(get_error_name),
2562 MAC_(print_extra_suppression_info));
2563 VG_(needs_libc_freeres) ();
2564 VG_(needs_command_line_options)(mc_process_cmd_line_option,
2565 mc_print_usage,
2566 mc_print_debug_usage);
2567 VG_(needs_client_requests) (mc_handle_client_request);
2568 VG_(needs_sanity_checks) (mc_cheap_sanity_check,
2569 mc_expensive_sanity_check);
2570 VG_(needs_shadow_memory) ();
2571
njnfc51f8d2005-06-21 03:20:17 +00002572 VG_(needs_malloc_replacement) (MAC_(malloc),
njn51d827b2005-05-09 01:02:08 +00002573 MAC_(__builtin_new),
2574 MAC_(__builtin_vec_new),
2575 MAC_(memalign),
2576 MAC_(calloc),
2577 MAC_(free),
2578 MAC_(__builtin_delete),
2579 MAC_(__builtin_vec_delete),
2580 MAC_(realloc),
2581 MAC_MALLOC_REDZONE_SZB );
2582
2583 MAC_( new_mem_heap) = & mc_new_mem_heap;
2584 MAC_( ban_mem_heap) = & mc_make_noaccess;
2585 MAC_(copy_mem_heap) = & mc_copy_address_range_state;
2586 MAC_( die_mem_heap) = & mc_make_noaccess;
2587 MAC_(check_noaccess) = & mc_check_noaccess;
2588
2589 VG_(track_new_mem_startup) ( & mc_new_mem_startup );
2590 VG_(track_new_mem_stack_signal)( & mc_make_writable );
2591 VG_(track_new_mem_brk) ( & mc_make_writable );
2592 VG_(track_new_mem_mmap) ( & mc_new_mem_mmap );
2593
2594 VG_(track_copy_mem_remap) ( & mc_copy_address_range_state );
2595
2596 VG_(track_die_mem_stack_signal)( & mc_make_noaccess );
2597 VG_(track_die_mem_brk) ( & mc_make_noaccess );
2598 VG_(track_die_mem_munmap) ( & mc_make_noaccess );
2599
2600 VG_(track_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
2601 VG_(track_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
2602 VG_(track_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
2603 VG_(track_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
2604 VG_(track_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
2605 VG_(track_new_mem_stack) ( & MAC_(new_mem_stack) );
2606
2607 VG_(track_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
2608 VG_(track_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
2609 VG_(track_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
2610 VG_(track_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
2611 VG_(track_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
2612 VG_(track_die_mem_stack) ( & MAC_(die_mem_stack) );
2613
2614 VG_(track_ban_mem_stack) ( & mc_make_noaccess );
2615
2616 VG_(track_pre_mem_read) ( & mc_check_is_readable );
2617 VG_(track_pre_mem_read_asciiz) ( & mc_check_is_readable_asciiz );
2618 VG_(track_pre_mem_write) ( & mc_check_is_writable );
2619 VG_(track_post_mem_write) ( & mc_post_mem_write );
2620
2621 VG_(track_pre_reg_read) ( & mc_pre_reg_read );
2622
2623 VG_(track_post_reg_write) ( & mc_post_reg_write );
2624 VG_(track_post_reg_write_clientcall_return)( & mc_post_reg_write_clientcall );
2625
2626 VG_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
2627 VG_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
2628 VG_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
2629
2630 /* Additional block description for VG_(describe_addr)() */
2631 MAC_(describe_addr_supp) = client_perm_maybe_describe;
2632
2633 init_shadow_memory();
2634 MAC_(common_pre_clo_init)();
2635
2636 tl_assert( mc_expensive_sanity_check() );
2637}
2638
2639VG_DETERMINE_INTERFACE_VERSION(mc_pre_clo_init, 9./8)
fitzhardinge98abfc72003-12-16 02:05:15 +00002640
njn25e49d8e72002-09-23 09:36:25 +00002641/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00002642/*--- end mc_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00002643/*--------------------------------------------------------------------*/