blob: 2e14d86cf500f4416c3d70a88860090e564c9894 [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
tomd55121e2005-12-19 12:40:13 +000059#ifdef HAVE_BUILTIN_EXPECT
sewardjc1a2cda2005-04-21 17:34:00 +000060#define EXPECTED_TAKEN(cond) __builtin_expect((cond),1)
61#define EXPECTED_NOT_TAKEN(cond) __builtin_expect((cond),0)
tomd55121e2005-12-19 12:40:13 +000062#else
63#define EXPECTED_TAKEN(cond) (cond)
64#define EXPECTED_NOT_TAKEN(cond) (cond)
65#endif
sewardjc1a2cda2005-04-21 17:34:00 +000066
67/* Define to debug the mem audit system. Set to:
68 0 no debugging, fast cases are used
69 1 some sanity checking, fast cases are used
70 2 max sanity checking, only slow cases are used
71*/
sewardj23eb2fd2005-04-22 16:29:19 +000072#define VG_DEBUG_MEMORY 0
sewardjc1a2cda2005-04-21 17:34:00 +000073
njn25e49d8e72002-09-23 09:36:25 +000074#define DEBUG(fmt, args...) //VG_(printf)(fmt, ## args)
75
njn25e49d8e72002-09-23 09:36:25 +000076
njn25e49d8e72002-09-23 09:36:25 +000077/*------------------------------------------------------------*/
sewardj45d94cc2005-04-20 14:44:11 +000078/*--- Basic A/V bitmap representation. ---*/
njn25e49d8e72002-09-23 09:36:25 +000079/*------------------------------------------------------------*/
80
sewardjc859fbf2005-04-22 21:10:28 +000081/* TODO: fix this comment */
82//zz /* All reads and writes are checked against a memory map, which
83//zz records the state of all memory in the process. The memory map is
84//zz organised like this:
85//zz
86//zz The top 16 bits of an address are used to index into a top-level
87//zz map table, containing 65536 entries. Each entry is a pointer to a
88//zz second-level map, which records the accesibililty and validity
89//zz permissions for the 65536 bytes indexed by the lower 16 bits of the
90//zz address. Each byte is represented by nine bits, one indicating
91//zz accessibility, the other eight validity. So each second-level map
92//zz contains 73728 bytes. This two-level arrangement conveniently
93//zz divides the 4G address space into 64k lumps, each size 64k bytes.
94//zz
95//zz All entries in the primary (top-level) map must point to a valid
96//zz secondary (second-level) map. Since most of the 4G of address
97//zz space will not be in use -- ie, not mapped at all -- there is a
njn02bc4b82005-05-15 17:28:26 +000098//zz distinguished secondary map, which indicates 'not addressible and
sewardjc859fbf2005-04-22 21:10:28 +000099//zz not valid' writeable for all bytes. Entries in the primary map for
100//zz which the entire 64k is not in use at all point at this
101//zz distinguished map.
102//zz
103//zz There are actually 4 distinguished secondaries. These are used to
104//zz represent a memory range which is either not addressable (validity
105//zz doesn't matter), addressable+not valid, addressable+valid.
sewardjc859fbf2005-04-22 21:10:28 +0000106//zz */
107
sewardj45d94cc2005-04-20 14:44:11 +0000108/* --------------- Basic configuration --------------- */
sewardj95448072004-11-22 20:19:51 +0000109
sewardj23eb2fd2005-04-22 16:29:19 +0000110/* Only change this. N_PRIMARY_MAP *must* be a power of 2. */
sewardj21f7ff42005-04-28 10:32:02 +0000111
sewardje4ccc012005-05-02 12:53:38 +0000112#if VG_WORDSIZE == 4
sewardj21f7ff42005-04-28 10:32:02 +0000113
114/* cover the entire address space */
115# define N_PRIMARY_BITS 16
116
117#else
118
sewardj34483bc2005-09-28 11:50:20 +0000119/* Just handle the first 32G fast and the rest via auxiliary
sewardj21f7ff42005-04-28 10:32:02 +0000120 primaries. */
sewardj34483bc2005-09-28 11:50:20 +0000121# define N_PRIMARY_BITS 19
sewardj21f7ff42005-04-28 10:32:02 +0000122
123#endif
124
sewardj45d94cc2005-04-20 14:44:11 +0000125
sewardjc1a2cda2005-04-21 17:34:00 +0000126/* Do not change this. */
sewardje4ccc012005-05-02 12:53:38 +0000127#define N_PRIMARY_MAP ( ((UWord)1) << N_PRIMARY_BITS)
sewardjc1a2cda2005-04-21 17:34:00 +0000128
129/* Do not change this. */
sewardj23eb2fd2005-04-22 16:29:19 +0000130#define MAX_PRIMARY_ADDRESS (Addr)((((Addr)65536) * N_PRIMARY_MAP)-1)
131
132
133/* --------------- Stats maps --------------- */
134
135static Int n_secmaps_issued = 0;
136static ULong n_auxmap_searches = 0;
137static ULong n_auxmap_cmps = 0;
138static Int n_sanity_cheap = 0;
139static Int n_sanity_expensive = 0;
sewardj45d94cc2005-04-20 14:44:11 +0000140
141
142/* --------------- Secondary maps --------------- */
njn25e49d8e72002-09-23 09:36:25 +0000143
144typedef
145 struct {
sewardj45d94cc2005-04-20 14:44:11 +0000146 UChar abits[8192];
147 UChar vbyte[65536];
njn25e49d8e72002-09-23 09:36:25 +0000148 }
149 SecMap;
150
sewardj45d94cc2005-04-20 14:44:11 +0000151/* 3 distinguished secondary maps, one for no-access, one for
152 accessible but undefined, and one for accessible and defined.
153 Distinguished secondaries may never be modified.
154*/
155#define SM_DIST_NOACCESS 0
156#define SM_DIST_ACCESS_UNDEFINED 1
157#define SM_DIST_ACCESS_DEFINED 2
njnb8dca862005-03-14 02:42:44 +0000158
sewardj45d94cc2005-04-20 14:44:11 +0000159static SecMap sm_distinguished[3];
njnb8dca862005-03-14 02:42:44 +0000160
sewardj45d94cc2005-04-20 14:44:11 +0000161static inline Bool is_distinguished_sm ( SecMap* sm ) {
162 return sm >= &sm_distinguished[0] && sm <= &sm_distinguished[2];
163}
njnb8dca862005-03-14 02:42:44 +0000164
sewardj45d94cc2005-04-20 14:44:11 +0000165/* dist_sm points to one of our three distinguished secondaries. Make
166 a copy of it so that we can write to it.
167*/
168static SecMap* copy_for_writing ( SecMap* dist_sm )
169{
170 SecMap* new_sm;
171 tl_assert(dist_sm == &sm_distinguished[0]
172 || dist_sm == &sm_distinguished[1]
173 || dist_sm == &sm_distinguished[2]);
njnb8dca862005-03-14 02:42:44 +0000174
sewardj45f4e7c2005-09-27 19:20:21 +0000175 new_sm = VG_(am_shadow_alloc)(sizeof(SecMap));
176 if (new_sm == NULL)
177 VG_(out_of_memory_NORETURN)( "memcheck:allocate new SecMap",
178 sizeof(SecMap) );
sewardj45d94cc2005-04-20 14:44:11 +0000179 VG_(memcpy)(new_sm, dist_sm, sizeof(SecMap));
sewardj23eb2fd2005-04-22 16:29:19 +0000180 n_secmaps_issued++;
sewardj45d94cc2005-04-20 14:44:11 +0000181 return new_sm;
182}
njnb8dca862005-03-14 02:42:44 +0000183
sewardj45d94cc2005-04-20 14:44:11 +0000184
185/* --------------- Primary maps --------------- */
186
187/* The main primary map. This covers some initial part of the address
sewardj23eb2fd2005-04-22 16:29:19 +0000188 space, addresses 0 .. (N_PRIMARY_MAP << 16)-1. The rest of it is
sewardj45d94cc2005-04-20 14:44:11 +0000189 handled using the auxiliary primary map.
190*/
sewardj23eb2fd2005-04-22 16:29:19 +0000191static SecMap* primary_map[N_PRIMARY_MAP];
sewardj45d94cc2005-04-20 14:44:11 +0000192
193
194/* An entry in the auxiliary primary map. base must be a 64k-aligned
195 value, and sm points at the relevant secondary map. As with the
196 main primary map, the secondary may be either a real secondary, or
197 one of the three distinguished secondaries.
198*/
199typedef
200 struct {
sewardj23eb2fd2005-04-22 16:29:19 +0000201 Addr base;
sewardj45d94cc2005-04-20 14:44:11 +0000202 SecMap* sm;
203 }
204 AuxMapEnt;
205
206/* An expanding array of AuxMapEnts. */
sewardjaba741d2005-06-09 13:56:07 +0000207#define N_AUXMAPS 20000 /* HACK */
sewardj45d94cc2005-04-20 14:44:11 +0000208static AuxMapEnt hacky_auxmaps[N_AUXMAPS];
209static Int auxmap_size = N_AUXMAPS;
210static Int auxmap_used = 0;
211static AuxMapEnt* auxmap = &hacky_auxmaps[0];
212
sewardj45d94cc2005-04-20 14:44:11 +0000213
214/* Find an entry in the auxiliary map. If an entry is found, move it
215 one step closer to the front of the array, then return its address.
sewardj05fe85e2005-04-27 22:46:36 +0000216 If an entry is not found, return NULL. Note carefully that
sewardj45d94cc2005-04-20 14:44:11 +0000217 because a each call potentially rearranges the entries, each call
218 to this function invalidates ALL AuxMapEnt*s previously obtained by
219 calling this fn.
220*/
sewardj05fe85e2005-04-27 22:46:36 +0000221static AuxMapEnt* maybe_find_in_auxmap ( Addr a )
sewardj45d94cc2005-04-20 14:44:11 +0000222{
223 UWord i;
224 tl_assert(a > MAX_PRIMARY_ADDRESS);
225
226 a &= ~(Addr)0xFFFF;
227
228 /* Search .. */
229 n_auxmap_searches++;
230 for (i = 0; i < auxmap_used; i++) {
231 if (auxmap[i].base == a)
232 break;
233 }
234 n_auxmap_cmps += (ULong)(i+1);
235
236 if (i < auxmap_used) {
237 /* Found it. Nudge it a bit closer to the front. */
238 if (i > 0) {
239 AuxMapEnt tmp = auxmap[i-1];
240 auxmap[i-1] = auxmap[i];
241 auxmap[i] = tmp;
242 i--;
243 }
244 return &auxmap[i];
245 }
246
sewardj05fe85e2005-04-27 22:46:36 +0000247 return NULL;
248}
249
250
251/* Find an entry in the auxiliary map. If an entry is found, move it
252 one step closer to the front of the array, then return its address.
253 If an entry is not found, allocate one. Note carefully that
254 because a each call potentially rearranges the entries, each call
255 to this function invalidates ALL AuxMapEnt*s previously obtained by
256 calling this fn.
257*/
258static AuxMapEnt* find_or_alloc_in_auxmap ( Addr a )
259{
260 AuxMapEnt* am = maybe_find_in_auxmap(a);
261 if (am)
262 return am;
263
sewardj45d94cc2005-04-20 14:44:11 +0000264 /* We didn't find it. Hmm. This is a new piece of address space.
265 We'll need to allocate a new AuxMap entry for it. */
266 if (auxmap_used >= auxmap_size) {
267 tl_assert(auxmap_used == auxmap_size);
268 /* Out of auxmap entries. */
269 tl_assert2(0, "failed to expand the auxmap table");
270 }
271
272 tl_assert(auxmap_used < auxmap_size);
273
274 auxmap[auxmap_used].base = a & ~(Addr)0xFFFF;
275 auxmap[auxmap_used].sm = &sm_distinguished[SM_DIST_NOACCESS];
276
277 if (0)
278 VG_(printf)("new auxmap, base = 0x%llx\n",
279 (ULong)auxmap[auxmap_used].base );
280
281 auxmap_used++;
282 return &auxmap[auxmap_used-1];
283}
284
285
286/* --------------- SecMap fundamentals --------------- */
287
288/* Produce the secmap for 'a', either from the primary map or by
289 ensuring there is an entry for it in the aux primary map. The
290 secmap may be a distinguished one as the caller will only want to
291 be able to read it.
292*/
293static SecMap* get_secmap_readable ( Addr a )
294{
295 if (a <= MAX_PRIMARY_ADDRESS) {
296 UWord pm_off = a >> 16;
297 return primary_map[ pm_off ];
298 } else {
299 AuxMapEnt* am = find_or_alloc_in_auxmap(a);
300 return am->sm;
301 }
302}
303
sewardj05fe85e2005-04-27 22:46:36 +0000304/* If 'a' has a SecMap, produce it. Else produce NULL. But don't
305 allocate one if one doesn't already exist. This is used by the
306 leak checker.
307*/
308static SecMap* maybe_get_secmap_for ( 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 = maybe_find_in_auxmap(a);
315 return am ? am->sm : NULL;
316 }
317}
318
319
320
sewardj45d94cc2005-04-20 14:44:11 +0000321/* Produce the secmap for 'a', either from the primary map or by
322 ensuring there is an entry for it in the aux primary map. The
323 secmap may not be a distinguished one, since the caller will want
324 to be able to write it. If it is a distinguished secondary, make a
325 writable copy of it, install it, and return the copy instead. (COW
326 semantics).
327*/
328static SecMap* get_secmap_writable ( Addr a )
329{
330 if (a <= MAX_PRIMARY_ADDRESS) {
331 UWord pm_off = a >> 16;
332 if (is_distinguished_sm(primary_map[ pm_off ]))
333 primary_map[pm_off] = copy_for_writing(primary_map[pm_off]);
334 return primary_map[pm_off];
335 } else {
336 AuxMapEnt* am = find_or_alloc_in_auxmap(a);
337 if (is_distinguished_sm(am->sm))
338 am->sm = copy_for_writing(am->sm);
339 return am->sm;
340 }
341}
342
343
344/* --------------- Endianness helpers --------------- */
345
346/* Returns the offset in memory of the byteno-th most significant byte
347 in a wordszB-sized word, given the specified endianness. */
348static inline UWord byte_offset_w ( UWord wordszB, Bool bigendian,
349 UWord byteno ) {
350 return bigendian ? (wordszB-1-byteno) : byteno;
351}
352
353
354/* --------------- Fundamental functions --------------- */
355
356static
357void get_abit_and_vbyte ( /*OUT*/UWord* abit,
358 /*OUT*/UWord* vbyte,
359 Addr a )
360{
361 SecMap* sm = get_secmap_readable(a);
362 *vbyte = 0xFF & sm->vbyte[a & 0xFFFF];
363 *abit = read_bit_array(sm->abits, a & 0xFFFF);
364}
365
366static
367UWord get_abit ( Addr a )
368{
369 SecMap* sm = get_secmap_readable(a);
370 return read_bit_array(sm->abits, a & 0xFFFF);
371}
372
373static
374void set_abit_and_vbyte ( Addr a, UWord abit, UWord vbyte )
375{
376 SecMap* sm = get_secmap_writable(a);
377 sm->vbyte[a & 0xFFFF] = 0xFF & vbyte;
378 write_bit_array(sm->abits, a & 0xFFFF, abit);
379}
380
381static
382void set_vbyte ( Addr a, UWord vbyte )
383{
384 SecMap* sm = get_secmap_writable(a);
385 sm->vbyte[a & 0xFFFF] = 0xFF & vbyte;
386}
387
388
389/* --------------- Load/store slow cases. --------------- */
390
391static
392ULong mc_LOADVn_slow ( Addr a, SizeT szB, Bool bigendian )
393{
394 /* Make up a result V word, which contains the loaded data for
sewardjf3d57dd2005-04-22 20:23:27 +0000395 valid addresses and Defined for invalid addresses. Iterate over
396 the bytes in the word, from the most significant down to the
397 least. */
sewardj45d94cc2005-04-20 14:44:11 +0000398 ULong vw = VGM_WORD64_INVALID;
399 SizeT i = szB-1;
400 SizeT n_addrs_bad = 0;
401 Addr ai;
sewardj0ded7a42005-11-08 02:25:37 +0000402 Bool aok, partial_load_exemption_applies;
sewardj45d94cc2005-04-20 14:44:11 +0000403 UWord abit, vbyte;
404
sewardjc1a2cda2005-04-21 17:34:00 +0000405 PROF_EVENT(30, "mc_LOADVn_slow");
sewardj45d94cc2005-04-20 14:44:11 +0000406 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
407
408 while (True) {
sewardjc1a2cda2005-04-21 17:34:00 +0000409 PROF_EVENT(31, "mc_LOADVn_slow(loop)");
sewardj45d94cc2005-04-20 14:44:11 +0000410 ai = a+byte_offset_w(szB,bigendian,i);
411 get_abit_and_vbyte(&abit, &vbyte, ai);
412 aok = abit == VGM_BIT_VALID;
413 if (!aok)
414 n_addrs_bad++;
415 vw <<= 8;
sewardjf3d57dd2005-04-22 20:23:27 +0000416 vw |= 0xFF & (aok ? vbyte : VGM_BYTE_VALID);
sewardj45d94cc2005-04-20 14:44:11 +0000417 if (i == 0) break;
418 i--;
419 }
420
sewardj0ded7a42005-11-08 02:25:37 +0000421 /* This is a hack which avoids producing errors for code which
422 insists in stepping along byte strings in aligned word-sized
423 chunks, and there is a partially defined word at the end. (eg,
424 optimised strlen). Such code is basically broken at least WRT
425 semantics of ANSI C, but sometimes users don't have the option
426 to fix it, and so this option is provided. Note it is now
427 defaulted to not-engaged.
428
429 A load from a partially-addressible place is allowed if:
430 - the command-line flag is set
431 - it's a word-sized, word-aligned load
432 - at least one of the addresses in the word *is* valid
433 */
434 partial_load_exemption_applies
435 = MAC_(clo_partial_loads_ok) && szB == VG_WORDSIZE
436 && VG_IS_WORD_ALIGNED(a)
437 && n_addrs_bad < VG_WORDSIZE;
438
439 if (n_addrs_bad > 0 && !partial_load_exemption_applies)
sewardj45d94cc2005-04-20 14:44:11 +0000440 MAC_(record_address_error)( VG_(get_running_tid)(), a, szB, False );
441
sewardj45d94cc2005-04-20 14:44:11 +0000442 return vw;
443}
444
445
446static
sewardj71ef8e72005-11-20 19:08:08 +0000447void mc_STOREVn_slow ( Addr a, SizeT szB, ULong vbytes, Bool bigendian )
sewardj45d94cc2005-04-20 14:44:11 +0000448{
449 SizeT i;
450 SizeT n_addrs_bad = 0;
451 UWord abit;
452 Bool aok;
453 Addr ai;
454
sewardjc1a2cda2005-04-21 17:34:00 +0000455 PROF_EVENT(35, "mc_STOREVn_slow");
sewardj45d94cc2005-04-20 14:44:11 +0000456 tl_assert(szB == 8 || szB == 4 || szB == 2 || szB == 1);
457
458 /* Dump vbytes in memory, iterating from least to most significant
459 byte. At the same time establish addressibility of the
460 location. */
461 for (i = 0; i < szB; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +0000462 PROF_EVENT(36, "mc_STOREVn_slow(loop)");
sewardj45d94cc2005-04-20 14:44:11 +0000463 ai = a+byte_offset_w(szB,bigendian,i);
464 abit = get_abit(ai);
465 aok = abit == VGM_BIT_VALID;
466 if (!aok)
467 n_addrs_bad++;
468 set_vbyte(ai, vbytes & 0xFF );
469 vbytes >>= 8;
470 }
471
472 /* If an address error has happened, report it. */
473 if (n_addrs_bad > 0)
474 MAC_(record_address_error)( VG_(get_running_tid)(), a, szB, True );
475}
476
477
sewardj45d94cc2005-04-20 14:44:11 +0000478//zz /* Reading/writing of the bitmaps, for aligned word-sized accesses. */
479//zz
480//zz static __inline__ UChar get_abits4_ALIGNED ( Addr a )
481//zz {
482//zz SecMap* sm;
483//zz UInt sm_off;
484//zz UChar abits8;
485//zz PROF_EVENT(24);
486//zz # ifdef VG_DEBUG_MEMORY
487//zz tl_assert(VG_IS_4_ALIGNED(a));
488//zz # endif
489//zz sm = primary_map[PM_IDX(a)];
490//zz sm_off = SM_OFF(a);
491//zz abits8 = sm->abits[sm_off >> 3];
492//zz abits8 >>= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
493//zz abits8 &= 0x0F;
494//zz return abits8;
495//zz }
496//zz
497//zz static UInt __inline__ get_vbytes4_ALIGNED ( Addr a )
498//zz {
499//zz SecMap* sm = primary_map[PM_IDX(a)];
500//zz UInt sm_off = SM_OFF(a);
501//zz PROF_EVENT(25);
502//zz # ifdef VG_DEBUG_MEMORY
503//zz tl_assert(VG_IS_4_ALIGNED(a));
504//zz # endif
505//zz return ((UInt*)(sm->vbyte))[sm_off >> 2];
506//zz }
507//zz
508//zz
509//zz static void __inline__ set_vbytes4_ALIGNED ( Addr a, UInt vbytes )
510//zz {
511//zz SecMap* sm;
512//zz UInt sm_off;
513//zz ENSURE_MAPPABLE(a, "set_vbytes4_ALIGNED");
514//zz sm = primary_map[PM_IDX(a)];
515//zz sm_off = SM_OFF(a);
516//zz PROF_EVENT(23);
517//zz # ifdef VG_DEBUG_MEMORY
518//zz tl_assert(VG_IS_4_ALIGNED(a));
519//zz # endif
520//zz ((UInt*)(sm->vbyte))[sm_off >> 2] = vbytes;
521//zz }
sewardjee070842003-07-05 17:53:55 +0000522
523
njn25e49d8e72002-09-23 09:36:25 +0000524/*------------------------------------------------------------*/
525/*--- Setting permissions over address ranges. ---*/
526/*------------------------------------------------------------*/
527
sewardj23eb2fd2005-04-22 16:29:19 +0000528/* Given address 'a', find the place where the pointer to a's
529 secondary map lives. If a falls into the primary map, the returned
530 value points to one of the entries in primary_map[]. Otherwise,
531 the auxiliary primary map is searched for 'a', or an entry is
532 created for it; either way, the returned value points to the
533 relevant AuxMapEnt's .sm field.
534
535 The point of this is to enable set_address_range_perms to assign
536 secondary maps in a uniform way, without worrying about whether a
537 given secondary map is pointed to from the main or auxiliary
538 primary map.
539*/
540
541static SecMap** find_secmap_binder_for_addr ( Addr aA )
542{
543 if (aA > MAX_PRIMARY_ADDRESS) {
544 AuxMapEnt* am = find_or_alloc_in_auxmap(aA);
545 return &am->sm;
546 } else {
547 UWord a = (UWord)aA;
548 UWord sec_no = (UWord)(a >> 16);
549# if VG_DEBUG_MEMORY >= 1
550 tl_assert(sec_no < N_PRIMARY_MAP);
551# endif
552 return &primary_map[sec_no];
553 }
554}
555
556
557static void set_address_range_perms ( Addr aA, SizeT len,
sewardj45d94cc2005-04-20 14:44:11 +0000558 UWord example_a_bit,
559 UWord example_v_bit )
njn25e49d8e72002-09-23 09:36:25 +0000560{
sewardjae986ca2005-10-12 12:53:20 +0000561 UWord a, vbits8, abits8, vbits32, v_off, a_off;
562 SecMap* sm;
563 SecMap** binder;
564 SecMap* example_dsm;
565
sewardj23eb2fd2005-04-22 16:29:19 +0000566 PROF_EVENT(150, "set_address_range_perms");
567
568 /* Check the permissions make sense. */
569 tl_assert(example_a_bit == VGM_BIT_VALID
570 || example_a_bit == VGM_BIT_INVALID);
571 tl_assert(example_v_bit == VGM_BIT_VALID
572 || example_v_bit == VGM_BIT_INVALID);
573 if (example_a_bit == VGM_BIT_INVALID)
574 tl_assert(example_v_bit == VGM_BIT_INVALID);
575
576 if (len == 0)
577 return;
578
sewardj1fa7d2c2005-06-13 18:22:17 +0000579 if (VG_(clo_verbosity) > 0 && !VG_(clo_xml)) {
sewardj23eb2fd2005-04-22 16:29:19 +0000580 if (len > 100 * 1000 * 1000) {
581 VG_(message)(Vg_UserMsg,
582 "Warning: set address range perms: "
sewardj9273eb92005-09-28 20:00:30 +0000583 "large range %lu, a %d, v %d",
sewardj23eb2fd2005-04-22 16:29:19 +0000584 len, example_a_bit, example_v_bit );
585 }
586 }
587
sewardjae986ca2005-10-12 12:53:20 +0000588 a = (UWord)aA;
sewardj23eb2fd2005-04-22 16:29:19 +0000589
590# if VG_DEBUG_MEMORY >= 2
591
592 /*------------------ debug-only case ------------------ */
sewardjae986ca2005-10-12 12:53:20 +0000593 { SizeT i;
njn25e49d8e72002-09-23 09:36:25 +0000594
sewardjae986ca2005-10-12 12:53:20 +0000595 UWord example_vbyte = BIT_TO_BYTE(example_v_bit);
sewardj45d94cc2005-04-20 14:44:11 +0000596
sewardjae986ca2005-10-12 12:53:20 +0000597 tl_assert(sizeof(SizeT) == sizeof(Addr));
sewardj45d94cc2005-04-20 14:44:11 +0000598
sewardjae986ca2005-10-12 12:53:20 +0000599 if (0 && len >= 4096)
600 VG_(printf)("s_a_r_p(0x%llx, %d, %d,%d)\n",
601 (ULong)a, len, example_a_bit, example_v_bit);
njn25e49d8e72002-09-23 09:36:25 +0000602
sewardjae986ca2005-10-12 12:53:20 +0000603 if (len == 0)
604 return;
njn25e49d8e72002-09-23 09:36:25 +0000605
sewardjae986ca2005-10-12 12:53:20 +0000606 for (i = 0; i < len; i++) {
607 set_abit_and_vbyte(a+i, example_a_bit, example_vbyte);
608 }
njn25e49d8e72002-09-23 09:36:25 +0000609 }
njn25e49d8e72002-09-23 09:36:25 +0000610
sewardj23eb2fd2005-04-22 16:29:19 +0000611# else
612
613 /*------------------ standard handling ------------------ */
sewardj23eb2fd2005-04-22 16:29:19 +0000614
615 /* Decide on the distinguished secondary that we might want
616 to use (part of the space-compression scheme). */
617 if (example_a_bit == VGM_BIT_INVALID) {
618 example_dsm = &sm_distinguished[SM_DIST_NOACCESS];
619 } else {
620 if (example_v_bit == VGM_BIT_VALID) {
621 example_dsm = &sm_distinguished[SM_DIST_ACCESS_DEFINED];
622 } else {
623 example_dsm = &sm_distinguished[SM_DIST_ACCESS_UNDEFINED];
624 }
625 }
626
627 /* Make various wider versions of the A/V values to use. */
628 vbits8 = BIT_TO_BYTE(example_v_bit);
629 abits8 = BIT_TO_BYTE(example_a_bit);
630 vbits32 = (vbits8 << 24) | (vbits8 << 16) | (vbits8 << 8) | vbits8;
631
632 /* Slowly do parts preceding 8-byte alignment. */
633 while (True) {
634 if (len == 0) break;
635 PROF_EVENT(151, "set_address_range_perms-loop1-pre");
636 if (VG_IS_8_ALIGNED(a)) break;
637 set_abit_and_vbyte( a, example_a_bit, vbits8 );
638 a++;
639 len--;
640 }
641
642 if (len == 0)
643 return;
644
645 tl_assert(VG_IS_8_ALIGNED(a) && len > 0);
646
647 /* Now go in steps of 8 bytes. */
648 binder = find_secmap_binder_for_addr(a);
649
650 while (True) {
651
652 if (len < 8) break;
653
654 PROF_EVENT(152, "set_address_range_perms-loop8");
655
656 if ((a & SECONDARY_MASK) == 0) {
657 /* we just traversed a primary map boundary, so update the
658 binder. */
659 binder = find_secmap_binder_for_addr(a);
660 PROF_EVENT(153, "set_address_range_perms-update-binder");
661
662 /* Space-optimisation. If we are setting the entire
663 secondary map, just point this entry at one of our
664 distinguished secondaries. However, only do that if it
665 already points at a distinguished secondary, since doing
666 otherwise would leak the existing secondary. We could do
667 better and free up any pre-existing non-distinguished
668 secondary at this point, since we are guaranteed that each
669 non-dist secondary only has one pointer to it, and we have
670 that pointer right here. */
671 if (len >= SECONDARY_SIZE && is_distinguished_sm(*binder)) {
672 PROF_EVENT(154, "set_address_range_perms-entire-secmap");
673 *binder = example_dsm;
674 len -= SECONDARY_SIZE;
675 a += SECONDARY_SIZE;
676 continue;
677 }
678 }
679
680 /* If the primary is already pointing to a distinguished map
681 with the same properties as we're trying to set, then leave
682 it that way. */
683 if (*binder == example_dsm) {
684 a += 8;
685 len -= 8;
686 continue;
687 }
688
689 /* Make sure it's OK to write the secondary. */
690 if (is_distinguished_sm(*binder))
691 *binder = copy_for_writing(*binder);
692
693 sm = *binder;
694 v_off = a & 0xFFFF;
695 a_off = v_off >> 3;
696 sm->abits[a_off] = (UChar)abits8;
697 ((UInt*)(sm->vbyte))[(v_off >> 2) + 0] = (UInt)vbits32;
698 ((UInt*)(sm->vbyte))[(v_off >> 2) + 1] = (UInt)vbits32;
699
700 a += 8;
701 len -= 8;
702 }
703
704 if (len == 0)
705 return;
706
707 tl_assert(VG_IS_8_ALIGNED(a) && len > 0 && len < 8);
708
709 /* Finish the upper fragment. */
710 while (True) {
711 if (len == 0) break;
712 PROF_EVENT(155, "set_address_range_perms-loop1-post");
713 set_abit_and_vbyte ( a, example_a_bit, vbits8 );
714 a++;
715 len--;
716 }
717
718# endif
719}
sewardj45d94cc2005-04-20 14:44:11 +0000720
sewardjc859fbf2005-04-22 21:10:28 +0000721
722/* --- Set permissions for arbitrary address ranges --- */
njn25e49d8e72002-09-23 09:36:25 +0000723
nethercote8b76fe52004-11-08 19:20:09 +0000724static void mc_make_noaccess ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000725{
sewardjc1a2cda2005-04-21 17:34:00 +0000726 PROF_EVENT(40, "mc_make_noaccess");
nethercote8b76fe52004-11-08 19:20:09 +0000727 DEBUG("mc_make_noaccess(%p, %llu)\n", a, (ULong)len);
njn25e49d8e72002-09-23 09:36:25 +0000728 set_address_range_perms ( a, len, VGM_BIT_INVALID, VGM_BIT_INVALID );
729}
730
nethercote8b76fe52004-11-08 19:20:09 +0000731static void mc_make_writable ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000732{
sewardjc1a2cda2005-04-21 17:34:00 +0000733 PROF_EVENT(41, "mc_make_writable");
nethercote8b76fe52004-11-08 19:20:09 +0000734 DEBUG("mc_make_writable(%p, %llu)\n", a, (ULong)len);
njn25e49d8e72002-09-23 09:36:25 +0000735 set_address_range_perms ( a, len, VGM_BIT_VALID, VGM_BIT_INVALID );
736}
737
nethercote8b76fe52004-11-08 19:20:09 +0000738static void mc_make_readable ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +0000739{
sewardjc1a2cda2005-04-21 17:34:00 +0000740 PROF_EVENT(42, "mc_make_readable");
nethercote8b76fe52004-11-08 19:20:09 +0000741 DEBUG("mc_make_readable(%p, %llu)\n", a, (ULong)len);
njn25e49d8e72002-09-23 09:36:25 +0000742 set_address_range_perms ( a, len, VGM_BIT_VALID, VGM_BIT_VALID );
743}
744
njn9b007f62003-04-07 14:40:25 +0000745
sewardj45f4e7c2005-09-27 19:20:21 +0000746/* --- Block-copy permissions (needed for implementing realloc() and
747 sys_mremap). --- */
sewardjc859fbf2005-04-22 21:10:28 +0000748
749static void mc_copy_address_range_state ( Addr src, Addr dst, SizeT len )
750{
sewardj45f4e7c2005-09-27 19:20:21 +0000751 SizeT i, j;
sewardjc859fbf2005-04-22 21:10:28 +0000752 UWord abit, vbyte;
753
754 DEBUG("mc_copy_address_range_state\n");
sewardjc859fbf2005-04-22 21:10:28 +0000755 PROF_EVENT(50, "mc_copy_address_range_state");
sewardj45f4e7c2005-09-27 19:20:21 +0000756
757 if (len == 0)
758 return;
759
760 if (src < dst) {
761 for (i = 0, j = len-1; i < len; i++, j--) {
762 PROF_EVENT(51, "mc_copy_address_range_state(loop)");
763 get_abit_and_vbyte( &abit, &vbyte, src+j );
764 set_abit_and_vbyte( dst+j, abit, vbyte );
765 }
766 }
767
768 if (src > dst) {
769 for (i = 0; i < len; i++) {
770 PROF_EVENT(51, "mc_copy_address_range_state(loop)");
771 get_abit_and_vbyte( &abit, &vbyte, src+i );
772 set_abit_and_vbyte( dst+i, abit, vbyte );
773 }
sewardjc859fbf2005-04-22 21:10:28 +0000774 }
775}
776
777
778/* --- Fast case permission setters, for dealing with stacks. --- */
779
njn9b007f62003-04-07 14:40:25 +0000780static __inline__
sewardj5d28efc2005-04-21 22:16:29 +0000781void make_aligned_word32_writable ( Addr aA )
njn9b007f62003-04-07 14:40:25 +0000782{
sewardjae986ca2005-10-12 12:53:20 +0000783 UWord a, sec_no, v_off, a_off, mask;
784 SecMap* sm;
785
sewardj5d28efc2005-04-21 22:16:29 +0000786 PROF_EVENT(300, "make_aligned_word32_writable");
787
788# if VG_DEBUG_MEMORY >= 2
789 mc_make_writable(aA, 4);
790# else
791
792 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
sewardj23eb2fd2005-04-22 16:29:19 +0000793 PROF_EVENT(301, "make_aligned_word32_writable-slow1");
sewardj5d28efc2005-04-21 22:16:29 +0000794 mc_make_writable(aA, 4);
795 return;
796 }
797
sewardjae986ca2005-10-12 12:53:20 +0000798 a = (UWord)aA;
799 sec_no = (UWord)(a >> 16);
sewardj5d28efc2005-04-21 22:16:29 +0000800# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +0000801 tl_assert(sec_no < N_PRIMARY_MAP);
sewardj5d28efc2005-04-21 22:16:29 +0000802# endif
803
804 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
805 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
806
sewardjae986ca2005-10-12 12:53:20 +0000807 sm = primary_map[sec_no];
808 v_off = a & 0xFFFF;
809 a_off = v_off >> 3;
sewardj5d28efc2005-04-21 22:16:29 +0000810
811 /* Paint the new area as uninitialised. */
812 ((UInt*)(sm->vbyte))[v_off >> 2] = VGM_WORD32_INVALID;
813
sewardjae986ca2005-10-12 12:53:20 +0000814 mask = 0x0F;
sewardj5d28efc2005-04-21 22:16:29 +0000815 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
816 /* mask now contains 1s where we wish to make address bits valid
817 (0s). */
818 sm->abits[a_off] &= ~mask;
819# endif
njn9b007f62003-04-07 14:40:25 +0000820}
821
sewardj5d28efc2005-04-21 22:16:29 +0000822
823static __inline__
824void make_aligned_word32_noaccess ( Addr aA )
825{
sewardjae986ca2005-10-12 12:53:20 +0000826 UWord a, sec_no, v_off, a_off, mask;
827 SecMap* sm;
828
sewardj5d28efc2005-04-21 22:16:29 +0000829 PROF_EVENT(310, "make_aligned_word32_noaccess");
830
831# if VG_DEBUG_MEMORY >= 2
832 mc_make_noaccess(aA, 4);
833# else
834
835 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
836 PROF_EVENT(311, "make_aligned_word32_noaccess-slow1");
837 mc_make_noaccess(aA, 4);
838 return;
839 }
840
sewardjae986ca2005-10-12 12:53:20 +0000841 a = (UWord)aA;
842 sec_no = (UWord)(a >> 16);
sewardj5d28efc2005-04-21 22:16:29 +0000843# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +0000844 tl_assert(sec_no < N_PRIMARY_MAP);
sewardj5d28efc2005-04-21 22:16:29 +0000845# endif
846
847 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
848 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
849
sewardjae986ca2005-10-12 12:53:20 +0000850 sm = primary_map[sec_no];
851 v_off = a & 0xFFFF;
852 a_off = v_off >> 3;
sewardj5d28efc2005-04-21 22:16:29 +0000853
854 /* Paint the abandoned data as uninitialised. Probably not
855 necessary, but still .. */
856 ((UInt*)(sm->vbyte))[v_off >> 2] = VGM_WORD32_INVALID;
857
sewardjae986ca2005-10-12 12:53:20 +0000858 mask = 0x0F;
sewardj5d28efc2005-04-21 22:16:29 +0000859 mask <<= (a & 4 /* 100b */); /* a & 4 is either 0 or 4 */
860 /* mask now contains 1s where we wish to make address bits invalid
861 (1s). */
862 sm->abits[a_off] |= mask;
863# endif
864}
865
866
njn9b007f62003-04-07 14:40:25 +0000867/* Nb: by "aligned" here we mean 8-byte aligned */
868static __inline__
sewardj23eb2fd2005-04-22 16:29:19 +0000869void make_aligned_word64_writable ( Addr aA )
njn9b007f62003-04-07 14:40:25 +0000870{
sewardjae986ca2005-10-12 12:53:20 +0000871 UWord a, sec_no, v_off, a_off;
872 SecMap* sm;
873
sewardj23eb2fd2005-04-22 16:29:19 +0000874 PROF_EVENT(320, "make_aligned_word64_writable");
875
876# if VG_DEBUG_MEMORY >= 2
877 mc_make_writable(aA, 8);
878# else
879
880 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
881 PROF_EVENT(321, "make_aligned_word64_writable-slow1");
882 mc_make_writable(aA, 8);
883 return;
884 }
885
sewardjae986ca2005-10-12 12:53:20 +0000886 a = (UWord)aA;
887 sec_no = (UWord)(a >> 16);
sewardj23eb2fd2005-04-22 16:29:19 +0000888# if VG_DEBUG_MEMORY >= 1
889 tl_assert(sec_no < N_PRIMARY_MAP);
890# endif
891
892 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
893 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
894
sewardjae986ca2005-10-12 12:53:20 +0000895 sm = primary_map[sec_no];
896 v_off = a & 0xFFFF;
897 a_off = v_off >> 3;
sewardj23eb2fd2005-04-22 16:29:19 +0000898
899 /* Paint the new area as uninitialised. */
900 ((ULong*)(sm->vbyte))[v_off >> 3] = VGM_WORD64_INVALID;
901
902 /* Make the relevant area accessible. */
903 sm->abits[a_off] = VGM_BYTE_VALID;
904# endif
njn9b007f62003-04-07 14:40:25 +0000905}
906
sewardj23eb2fd2005-04-22 16:29:19 +0000907
njn9b007f62003-04-07 14:40:25 +0000908static __inline__
sewardj23eb2fd2005-04-22 16:29:19 +0000909void make_aligned_word64_noaccess ( Addr aA )
njn9b007f62003-04-07 14:40:25 +0000910{
sewardjae986ca2005-10-12 12:53:20 +0000911 UWord a, sec_no, v_off, a_off;
912 SecMap* sm;
913
sewardj23eb2fd2005-04-22 16:29:19 +0000914 PROF_EVENT(330, "make_aligned_word64_noaccess");
915
916# if VG_DEBUG_MEMORY >= 2
917 mc_make_noaccess(aA, 8);
918# else
919
920 if (EXPECTED_NOT_TAKEN(aA > MAX_PRIMARY_ADDRESS)) {
921 PROF_EVENT(331, "make_aligned_word64_noaccess-slow1");
922 mc_make_noaccess(aA, 8);
923 return;
924 }
925
sewardjae986ca2005-10-12 12:53:20 +0000926 a = (UWord)aA;
927 sec_no = (UWord)(a >> 16);
sewardj23eb2fd2005-04-22 16:29:19 +0000928# if VG_DEBUG_MEMORY >= 1
929 tl_assert(sec_no < N_PRIMARY_MAP);
930# endif
931
932 if (EXPECTED_NOT_TAKEN(is_distinguished_sm(primary_map[sec_no])))
933 primary_map[sec_no] = copy_for_writing(primary_map[sec_no]);
934
sewardjae986ca2005-10-12 12:53:20 +0000935 sm = primary_map[sec_no];
936 v_off = a & 0xFFFF;
937 a_off = v_off >> 3;
sewardj23eb2fd2005-04-22 16:29:19 +0000938
939 /* Paint the abandoned data as uninitialised. Probably not
940 necessary, but still .. */
941 ((ULong*)(sm->vbyte))[v_off >> 3] = VGM_WORD64_INVALID;
942
943 /* Make the abandoned area inaccessible. */
944 sm->abits[a_off] = VGM_BYTE_INVALID;
945# endif
njn9b007f62003-04-07 14:40:25 +0000946}
947
sewardj23eb2fd2005-04-22 16:29:19 +0000948
sewardj45d94cc2005-04-20 14:44:11 +0000949/* The stack-pointer update handling functions */
950SP_UPDATE_HANDLERS ( make_aligned_word32_writable,
951 make_aligned_word32_noaccess,
952 make_aligned_word64_writable,
953 make_aligned_word64_noaccess,
954 mc_make_writable,
955 mc_make_noaccess
956 );
njn9b007f62003-04-07 14:40:25 +0000957
sewardj45d94cc2005-04-20 14:44:11 +0000958
sewardj826ec492005-05-12 18:05:00 +0000959void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len )
960{
961 tl_assert(sizeof(UWord) == sizeof(SizeT));
sewardj2a3a1a72005-05-12 23:25:43 +0000962 if (0)
963 VG_(printf)("helperc_MAKE_STACK_UNINIT %p %d\n", base, len );
964
965# if 0
966 /* Really slow version */
967 mc_make_writable(base, len);
968# endif
969
970# if 0
971 /* Slow(ish) version, which is fairly easily seen to be correct.
972 */
973 if (EXPECTED_TAKEN( VG_IS_8_ALIGNED(base) && len==128 )) {
974 make_aligned_word64_writable(base + 0);
975 make_aligned_word64_writable(base + 8);
976 make_aligned_word64_writable(base + 16);
977 make_aligned_word64_writable(base + 24);
978
979 make_aligned_word64_writable(base + 32);
980 make_aligned_word64_writable(base + 40);
981 make_aligned_word64_writable(base + 48);
982 make_aligned_word64_writable(base + 56);
983
984 make_aligned_word64_writable(base + 64);
985 make_aligned_word64_writable(base + 72);
986 make_aligned_word64_writable(base + 80);
987 make_aligned_word64_writable(base + 88);
988
989 make_aligned_word64_writable(base + 96);
990 make_aligned_word64_writable(base + 104);
991 make_aligned_word64_writable(base + 112);
992 make_aligned_word64_writable(base + 120);
993 } else {
994 mc_make_writable(base, len);
995 }
996# endif
997
998 /* Idea is: go fast when
999 * 8-aligned and length is 128
1000 * the sm is available in the main primary map
1001 * the address range falls entirely with a single
1002 secondary map
1003 * the SM is modifiable
1004 If all those conditions hold, just update the V bits
1005 by writing directly on the v-bit array. We don't care
1006 about A bits; if the address range is marked invalid,
1007 any attempt to access it will elicit an addressing error,
1008 and that's good enough.
1009 */
1010 if (EXPECTED_TAKEN( len == 128
1011 && VG_IS_8_ALIGNED(base)
1012 )) {
1013 /* Now we know the address range is suitably sized and
1014 aligned. */
1015 UWord a_lo = (UWord)base;
1016 UWord a_hi = (UWord)(base + 127);
1017 UWord sec_lo = a_lo >> 16;
1018 UWord sec_hi = a_hi >> 16;
1019
1020 if (EXPECTED_TAKEN( sec_lo == sec_hi
1021 && sec_lo <= N_PRIMARY_MAP
1022 )) {
1023 /* Now we know that the entire address range falls within a
1024 single secondary map, and that that secondary 'lives' in
1025 the main primary map. */
1026 SecMap* sm = primary_map[sec_lo];
1027
1028 if (EXPECTED_TAKEN( !is_distinguished_sm(sm) )) {
1029 /* And finally, now we know that the secondary in question
1030 is modifiable. */
1031 UWord v_off = a_lo & 0xFFFF;
1032 ULong* p = (ULong*)(&sm->vbyte[v_off]);
1033 p[ 0] = VGM_WORD64_INVALID;
1034 p[ 1] = VGM_WORD64_INVALID;
1035 p[ 2] = VGM_WORD64_INVALID;
1036 p[ 3] = VGM_WORD64_INVALID;
1037 p[ 4] = VGM_WORD64_INVALID;
1038 p[ 5] = VGM_WORD64_INVALID;
1039 p[ 6] = VGM_WORD64_INVALID;
1040 p[ 7] = VGM_WORD64_INVALID;
1041 p[ 8] = VGM_WORD64_INVALID;
1042 p[ 9] = VGM_WORD64_INVALID;
1043 p[10] = VGM_WORD64_INVALID;
1044 p[11] = VGM_WORD64_INVALID;
1045 p[12] = VGM_WORD64_INVALID;
1046 p[13] = VGM_WORD64_INVALID;
1047 p[14] = VGM_WORD64_INVALID;
1048 p[15] = VGM_WORD64_INVALID;
1049 return;
1050 }
1051 }
1052 }
1053
1054 /* else fall into slow case */
sewardj826ec492005-05-12 18:05:00 +00001055 mc_make_writable(base, len);
1056}
1057
1058
nethercote8b76fe52004-11-08 19:20:09 +00001059/*------------------------------------------------------------*/
1060/*--- Checking memory ---*/
1061/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00001062
sewardje4ccc012005-05-02 12:53:38 +00001063typedef
1064 enum {
1065 MC_Ok = 5,
1066 MC_AddrErr = 6,
1067 MC_ValueErr = 7
1068 }
1069 MC_ReadResult;
1070
1071
njn25e49d8e72002-09-23 09:36:25 +00001072/* Check permissions for address range. If inadequate permissions
1073 exist, *bad_addr is set to the offending address, so the caller can
1074 know what it is. */
1075
sewardjecf8e102003-07-12 12:11:39 +00001076/* Returns True if [a .. a+len) is not addressible. Otherwise,
1077 returns False, and if bad_addr is non-NULL, sets *bad_addr to
1078 indicate the lowest failing address. Functions below are
1079 similar. */
nethercote8b76fe52004-11-08 19:20:09 +00001080static Bool mc_check_noaccess ( Addr a, SizeT len, Addr* bad_addr )
sewardjecf8e102003-07-12 12:11:39 +00001081{
nethercote451eae92004-11-02 13:06:32 +00001082 SizeT i;
sewardj45d94cc2005-04-20 14:44:11 +00001083 UWord abit;
sewardjc1a2cda2005-04-21 17:34:00 +00001084 PROF_EVENT(60, "mc_check_noaccess");
sewardjecf8e102003-07-12 12:11:39 +00001085 for (i = 0; i < len; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +00001086 PROF_EVENT(61, "mc_check_noaccess(loop)");
sewardjecf8e102003-07-12 12:11:39 +00001087 abit = get_abit(a);
1088 if (abit == VGM_BIT_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001089 if (bad_addr != NULL)
1090 *bad_addr = a;
sewardjecf8e102003-07-12 12:11:39 +00001091 return False;
1092 }
1093 a++;
1094 }
1095 return True;
1096}
1097
nethercote8b76fe52004-11-08 19:20:09 +00001098static Bool mc_check_writable ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +00001099{
nethercote451eae92004-11-02 13:06:32 +00001100 SizeT i;
sewardj45d94cc2005-04-20 14:44:11 +00001101 UWord abit;
sewardjc1a2cda2005-04-21 17:34:00 +00001102 PROF_EVENT(62, "mc_check_writable");
njn25e49d8e72002-09-23 09:36:25 +00001103 for (i = 0; i < len; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +00001104 PROF_EVENT(63, "mc_check_writable(loop)");
njn25e49d8e72002-09-23 09:36:25 +00001105 abit = get_abit(a);
1106 if (abit == VGM_BIT_INVALID) {
1107 if (bad_addr != NULL) *bad_addr = a;
1108 return False;
1109 }
1110 a++;
1111 }
1112 return True;
1113}
1114
nethercote8b76fe52004-11-08 19:20:09 +00001115static MC_ReadResult mc_check_readable ( Addr a, SizeT len, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +00001116{
nethercote451eae92004-11-02 13:06:32 +00001117 SizeT i;
sewardj45d94cc2005-04-20 14:44:11 +00001118 UWord abit;
1119 UWord vbyte;
njn25e49d8e72002-09-23 09:36:25 +00001120
sewardjc1a2cda2005-04-21 17:34:00 +00001121 PROF_EVENT(64, "mc_check_readable");
nethercote8b76fe52004-11-08 19:20:09 +00001122 DEBUG("mc_check_readable\n");
njn25e49d8e72002-09-23 09:36:25 +00001123 for (i = 0; i < len; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +00001124 PROF_EVENT(65, "mc_check_readable(loop)");
sewardj45d94cc2005-04-20 14:44:11 +00001125 get_abit_and_vbyte(&abit, &vbyte, a);
nethercote8b76fe52004-11-08 19:20:09 +00001126 // Report addressability errors in preference to definedness errors
1127 // by checking the A bits first.
1128 if (abit != VGM_BIT_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001129 if (bad_addr != NULL)
1130 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +00001131 return MC_AddrErr;
1132 }
1133 if (vbyte != VGM_BYTE_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001134 if (bad_addr != NULL)
1135 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +00001136 return MC_ValueErr;
njn25e49d8e72002-09-23 09:36:25 +00001137 }
1138 a++;
1139 }
nethercote8b76fe52004-11-08 19:20:09 +00001140 return MC_Ok;
njn25e49d8e72002-09-23 09:36:25 +00001141}
1142
1143
1144/* Check a zero-terminated ascii string. Tricky -- don't want to
1145 examine the actual bytes, to find the end, until we're sure it is
1146 safe to do so. */
1147
njn9b007f62003-04-07 14:40:25 +00001148static Bool mc_check_readable_asciiz ( Addr a, Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +00001149{
sewardj45d94cc2005-04-20 14:44:11 +00001150 UWord abit;
1151 UWord vbyte;
sewardjc1a2cda2005-04-21 17:34:00 +00001152 PROF_EVENT(66, "mc_check_readable_asciiz");
njn5c004e42002-11-18 11:04:50 +00001153 DEBUG("mc_check_readable_asciiz\n");
njn25e49d8e72002-09-23 09:36:25 +00001154 while (True) {
sewardjc1a2cda2005-04-21 17:34:00 +00001155 PROF_EVENT(67, "mc_check_readable_asciiz(loop)");
sewardj45d94cc2005-04-20 14:44:11 +00001156 get_abit_and_vbyte(&abit, &vbyte, a);
nethercote8b76fe52004-11-08 19:20:09 +00001157 // As in mc_check_readable(), check A bits first
1158 if (abit != VGM_BIT_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001159 if (bad_addr != NULL)
1160 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +00001161 return MC_AddrErr;
1162 }
1163 if (vbyte != VGM_BYTE_VALID) {
sewardj45d94cc2005-04-20 14:44:11 +00001164 if (bad_addr != NULL)
1165 *bad_addr = a;
nethercote8b76fe52004-11-08 19:20:09 +00001166 return MC_ValueErr;
njn25e49d8e72002-09-23 09:36:25 +00001167 }
1168 /* Ok, a is safe to read. */
sewardj45d94cc2005-04-20 14:44:11 +00001169 if (* ((UChar*)a) == 0)
1170 return MC_Ok;
njn25e49d8e72002-09-23 09:36:25 +00001171 a++;
1172 }
1173}
1174
1175
1176/*------------------------------------------------------------*/
1177/*--- Memory event handlers ---*/
1178/*------------------------------------------------------------*/
1179
njn25e49d8e72002-09-23 09:36:25 +00001180static
njn72718642003-07-24 08:45:32 +00001181void mc_check_is_writable ( CorePart part, ThreadId tid, Char* s,
nethercote451eae92004-11-02 13:06:32 +00001182 Addr base, SizeT size )
njn25e49d8e72002-09-23 09:36:25 +00001183{
1184 Bool ok;
1185 Addr bad_addr;
1186
1187 VGP_PUSHCC(VgpCheckMem);
1188
1189 /* VG_(message)(Vg_DebugMsg,"check is writable: %x .. %x",
1190 base,base+size-1); */
nethercote8b76fe52004-11-08 19:20:09 +00001191 ok = mc_check_writable ( base, size, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +00001192 if (!ok) {
1193 switch (part) {
1194 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +00001195 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
1196 /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +00001197 break;
1198
1199 case Vg_CorePThread:
1200 case Vg_CoreSignal:
nethercote8b76fe52004-11-08 19:20:09 +00001201 MAC_(record_core_mem_error)( tid, /*isUnaddr*/True, s );
njn25e49d8e72002-09-23 09:36:25 +00001202 break;
1203
1204 default:
njn67993252004-11-22 18:02:32 +00001205 VG_(tool_panic)("mc_check_is_writable: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +00001206 }
1207 }
1208
1209 VGP_POPCC(VgpCheckMem);
1210}
1211
1212static
njn72718642003-07-24 08:45:32 +00001213void mc_check_is_readable ( CorePart part, ThreadId tid, Char* s,
nethercote451eae92004-11-02 13:06:32 +00001214 Addr base, SizeT size )
njn25e49d8e72002-09-23 09:36:25 +00001215{
njn25e49d8e72002-09-23 09:36:25 +00001216 Addr bad_addr;
nethercote8b76fe52004-11-08 19:20:09 +00001217 MC_ReadResult res;
njn25e49d8e72002-09-23 09:36:25 +00001218
1219 VGP_PUSHCC(VgpCheckMem);
1220
nethercote8b76fe52004-11-08 19:20:09 +00001221 res = mc_check_readable ( base, size, &bad_addr );
sewardj45f4e7c2005-09-27 19:20:21 +00001222
1223 if (0)
1224 VG_(printf)("mc_check_is_readable(0x%x, %d, %s) -> %s\n",
1225 (UInt)base, (Int)size, s, res==MC_Ok ? "yes" : "no" );
1226
nethercote8b76fe52004-11-08 19:20:09 +00001227 if (MC_Ok != res) {
1228 Bool isUnaddr = ( MC_AddrErr == res ? True : False );
sewardj45f4e7c2005-09-27 19:20:21 +00001229
njn25e49d8e72002-09-23 09:36:25 +00001230 switch (part) {
1231 case Vg_CoreSysCall:
nethercote8b76fe52004-11-08 19:20:09 +00001232 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False,
1233 isUnaddr, s );
njn25e49d8e72002-09-23 09:36:25 +00001234 break;
1235
1236 case Vg_CorePThread:
nethercote8b76fe52004-11-08 19:20:09 +00001237 MAC_(record_core_mem_error)( tid, isUnaddr, s );
njn25e49d8e72002-09-23 09:36:25 +00001238 break;
1239
1240 /* If we're being asked to jump to a silly address, record an error
1241 message before potentially crashing the entire system. */
1242 case Vg_CoreTranslate:
njn72718642003-07-24 08:45:32 +00001243 MAC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +00001244 break;
1245
1246 default:
njn67993252004-11-22 18:02:32 +00001247 VG_(tool_panic)("mc_check_is_readable: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +00001248 }
1249 }
1250 VGP_POPCC(VgpCheckMem);
1251}
1252
1253static
njn72718642003-07-24 08:45:32 +00001254void mc_check_is_readable_asciiz ( CorePart part, ThreadId tid,
njn5c004e42002-11-18 11:04:50 +00001255 Char* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +00001256{
nethercote8b76fe52004-11-08 19:20:09 +00001257 MC_ReadResult res;
njn5ab96ac2005-05-08 02:59:50 +00001258 Addr bad_addr = 0; // shut GCC up
njn25e49d8e72002-09-23 09:36:25 +00001259 /* VG_(message)(Vg_DebugMsg,"check is readable asciiz: 0x%x",str); */
1260
1261 VGP_PUSHCC(VgpCheckMem);
1262
njnca82cc02004-11-22 17:18:48 +00001263 tl_assert(part == Vg_CoreSysCall);
nethercote8b76fe52004-11-08 19:20:09 +00001264 res = mc_check_readable_asciiz ( (Addr)str, &bad_addr );
1265 if (MC_Ok != res) {
1266 Bool isUnaddr = ( MC_AddrErr == res ? True : False );
1267 MAC_(record_param_error) ( tid, bad_addr, /*isReg*/False, isUnaddr, s );
njn25e49d8e72002-09-23 09:36:25 +00001268 }
1269
1270 VGP_POPCC(VgpCheckMem);
1271}
1272
njn25e49d8e72002-09-23 09:36:25 +00001273static
nethercote451eae92004-11-02 13:06:32 +00001274void mc_new_mem_startup( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +00001275{
njn1f3a9092002-10-04 09:22:30 +00001276 /* Ignore the permissions, just make it readable. Seems to work... */
nethercote451eae92004-11-02 13:06:32 +00001277 DEBUG("mc_new_mem_startup(%p, %llu, rr=%u, ww=%u, xx=%u)\n",
1278 a,(ULong)len,rr,ww,xx);
nethercote8b76fe52004-11-08 19:20:09 +00001279 mc_make_readable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001280}
1281
1282static
nethercote451eae92004-11-02 13:06:32 +00001283void mc_new_mem_heap ( Addr a, SizeT len, Bool is_inited )
njn25e49d8e72002-09-23 09:36:25 +00001284{
1285 if (is_inited) {
nethercote8b76fe52004-11-08 19:20:09 +00001286 mc_make_readable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001287 } else {
nethercote8b76fe52004-11-08 19:20:09 +00001288 mc_make_writable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001289 }
1290}
1291
1292static
njnb8dca862005-03-14 02:42:44 +00001293void mc_new_mem_mmap ( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
njn25e49d8e72002-09-23 09:36:25 +00001294{
njnb8dca862005-03-14 02:42:44 +00001295 mc_make_readable(a, len);
njn25e49d8e72002-09-23 09:36:25 +00001296}
1297
njncf45fd42004-11-24 16:30:22 +00001298static
1299void mc_post_mem_write(CorePart part, ThreadId tid, Addr a, SizeT len)
1300{
1301 mc_make_readable(a, len);
1302}
njn25e49d8e72002-09-23 09:36:25 +00001303
sewardj45d94cc2005-04-20 14:44:11 +00001304
njn25e49d8e72002-09-23 09:36:25 +00001305/*------------------------------------------------------------*/
njnd3040452003-05-19 15:04:06 +00001306/*--- Register event handlers ---*/
1307/*------------------------------------------------------------*/
1308
sewardj45d94cc2005-04-20 14:44:11 +00001309/* When some chunk of guest state is written, mark the corresponding
1310 shadow area as valid. This is used to initialise arbitrarily large
sewardj2c27f702005-05-03 18:19:05 +00001311 chunks of guest state, hence the (somewhat arbitrary) 1024 limit.
sewardj45d94cc2005-04-20 14:44:11 +00001312*/
1313static void mc_post_reg_write ( CorePart part, ThreadId tid,
1314 OffT offset, SizeT size)
njnd3040452003-05-19 15:04:06 +00001315{
cerion21082042005-12-06 19:07:08 +00001316# define MAX_REG_WRITE_SIZE 1120
1317 UChar area[MAX_REG_WRITE_SIZE];
1318 tl_assert(size <= MAX_REG_WRITE_SIZE);
njncf45fd42004-11-24 16:30:22 +00001319 VG_(memset)(area, VGM_BYTE_VALID, size);
1320 VG_(set_shadow_regs_area)( tid, offset, size, area );
cerion21082042005-12-06 19:07:08 +00001321# undef MAX_REG_WRITE_SIZE
njnd3040452003-05-19 15:04:06 +00001322}
1323
sewardj45d94cc2005-04-20 14:44:11 +00001324static
1325void mc_post_reg_write_clientcall ( ThreadId tid,
1326 OffT offset, SizeT size,
1327 Addr f)
njnd3040452003-05-19 15:04:06 +00001328{
njncf45fd42004-11-24 16:30:22 +00001329 mc_post_reg_write(/*dummy*/0, tid, offset, size);
njnd3040452003-05-19 15:04:06 +00001330}
1331
sewardj45d94cc2005-04-20 14:44:11 +00001332/* Look at the definedness of the guest's shadow state for
1333 [offset, offset+len). If any part of that is undefined, record
1334 a parameter error.
1335*/
1336static void mc_pre_reg_read ( CorePart part, ThreadId tid, Char* s,
1337 OffT offset, SizeT size)
nethercote8b76fe52004-11-08 19:20:09 +00001338{
sewardj45d94cc2005-04-20 14:44:11 +00001339 Int i;
1340 Bool bad;
1341
1342 UChar area[16];
1343 tl_assert(size <= 16);
1344
1345 VG_(get_shadow_regs_area)( tid, offset, size, area );
1346
1347 bad = False;
1348 for (i = 0; i < size; i++) {
1349 if (area[i] != VGM_BYTE_VALID) {
sewardj2c27f702005-05-03 18:19:05 +00001350 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00001351 break;
1352 }
nethercote8b76fe52004-11-08 19:20:09 +00001353 }
1354
sewardj45d94cc2005-04-20 14:44:11 +00001355 if (bad)
nethercote8b76fe52004-11-08 19:20:09 +00001356 MAC_(record_param_error) ( tid, 0, /*isReg*/True, /*isUnaddr*/False, s );
1357}
njnd3040452003-05-19 15:04:06 +00001358
njn25e49d8e72002-09-23 09:36:25 +00001359
sewardj6cf40ff2005-04-20 22:31:26 +00001360/*------------------------------------------------------------*/
njn9e63cb62005-05-08 18:34:59 +00001361/*--- Printing errors ---*/
1362/*------------------------------------------------------------*/
1363
njn51d827b2005-05-09 01:02:08 +00001364static void mc_pp_Error ( Error* err )
njn9e63cb62005-05-08 18:34:59 +00001365{
1366 MAC_Error* err_extra = VG_(get_error_extra)(err);
1367
sewardj71bc3cb2005-05-19 00:25:45 +00001368 HChar* xpre = VG_(clo_xml) ? " <what>" : "";
1369 HChar* xpost = VG_(clo_xml) ? "</what>" : "";
1370
njn9e63cb62005-05-08 18:34:59 +00001371 switch (VG_(get_error_kind)(err)) {
1372 case CoreMemErr: {
1373 Char* s = ( err_extra->isUnaddr ? "unaddressable" : "uninitialised" );
sewardj71bc3cb2005-05-19 00:25:45 +00001374 if (VG_(clo_xml))
1375 VG_(message)(Vg_UserMsg, " <kind>CoreMemError</kind>");
1376 /* What the hell *is* a CoreMemError? jrs 2005-May-18 */
1377 VG_(message)(Vg_UserMsg, "%s%s contains %s byte(s)%s",
1378 xpre, VG_(get_error_string)(err), s, xpost);
1379
njn9e63cb62005-05-08 18:34:59 +00001380 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1381 break;
1382
1383 }
1384
1385 case ValueErr:
1386 if (err_extra->size == 0) {
sewardj71bc3cb2005-05-19 00:25:45 +00001387 if (VG_(clo_xml))
1388 VG_(message)(Vg_UserMsg, " <kind>UninitCondition</kind>");
1389 VG_(message)(Vg_UserMsg, "%sConditional jump or move depends"
1390 " on uninitialised value(s)%s",
1391 xpre, xpost);
njn9e63cb62005-05-08 18:34:59 +00001392 } else {
sewardj71bc3cb2005-05-19 00:25:45 +00001393 if (VG_(clo_xml))
1394 VG_(message)(Vg_UserMsg, " <kind>UninitValue</kind>");
1395 VG_(message)(Vg_UserMsg,
1396 "%sUse of uninitialised value of size %d%s",
1397 xpre, err_extra->size, xpost);
njn9e63cb62005-05-08 18:34:59 +00001398 }
1399 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1400 break;
1401
1402 case ParamErr: {
1403 Bool isReg = ( Register == err_extra->addrinfo.akind );
1404 Char* s1 = ( isReg ? "contains" : "points to" );
1405 Char* s2 = ( err_extra->isUnaddr ? "unaddressable" : "uninitialised" );
1406 if (isReg) tl_assert(!err_extra->isUnaddr);
1407
sewardj71bc3cb2005-05-19 00:25:45 +00001408 if (VG_(clo_xml))
1409 VG_(message)(Vg_UserMsg, " <kind>SyscallParam</kind>");
1410 VG_(message)(Vg_UserMsg, "%sSyscall param %s %s %s byte(s)%s",
1411 xpre, VG_(get_error_string)(err), s1, s2, xpost);
njn9e63cb62005-05-08 18:34:59 +00001412
1413 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1414 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
1415 break;
1416 }
1417 case UserErr: {
1418 Char* s = ( err_extra->isUnaddr ? "Unaddressable" : "Uninitialised" );
1419
sewardj71bc3cb2005-05-19 00:25:45 +00001420 if (VG_(clo_xml))
1421 VG_(message)(Vg_UserMsg, " <kind>ClientCheck</kind>");
njn9e63cb62005-05-08 18:34:59 +00001422 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +00001423 "%s%s byte(s) found during client check request%s",
1424 xpre, s, xpost);
njn9e63cb62005-05-08 18:34:59 +00001425
1426 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
1427 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
1428 break;
1429 }
1430 default:
1431 MAC_(pp_shared_Error)(err);
1432 break;
1433 }
1434}
1435
1436/*------------------------------------------------------------*/
1437/*--- Recording errors ---*/
1438/*------------------------------------------------------------*/
1439
njn02bc4b82005-05-15 17:28:26 +00001440/* Creates a copy of the 'extra' part, updates the copy with address info if
njn9e63cb62005-05-08 18:34:59 +00001441 necessary, and returns the copy. */
1442/* This one called from generated code and non-generated code. */
njn96364822005-05-08 19:04:53 +00001443static void mc_record_value_error ( ThreadId tid, Int size )
njn9e63cb62005-05-08 18:34:59 +00001444{
1445 MAC_Error err_extra;
1446
1447 MAC_(clear_MAC_Error)( &err_extra );
1448 err_extra.size = size;
1449 err_extra.isUnaddr = False;
1450 VG_(maybe_record_error)( tid, ValueErr, /*addr*/0, /*s*/NULL, &err_extra );
1451}
1452
1453/* This called from non-generated code */
1454
njn96364822005-05-08 19:04:53 +00001455static void mc_record_user_error ( ThreadId tid, Addr a, Bool isWrite,
1456 Bool isUnaddr )
njn9e63cb62005-05-08 18:34:59 +00001457{
1458 MAC_Error err_extra;
1459
1460 tl_assert(VG_INVALID_THREADID != tid);
1461 MAC_(clear_MAC_Error)( &err_extra );
1462 err_extra.addrinfo.akind = Undescribed;
1463 err_extra.isUnaddr = isUnaddr;
1464 VG_(maybe_record_error)( tid, UserErr, a, /*s*/NULL, &err_extra );
1465}
1466
1467/*------------------------------------------------------------*/
1468/*--- Suppressions ---*/
1469/*------------------------------------------------------------*/
1470
njn51d827b2005-05-09 01:02:08 +00001471static Bool mc_recognised_suppression ( Char* name, Supp* su )
njn9e63cb62005-05-08 18:34:59 +00001472{
1473 SuppKind skind;
1474
1475 if (MAC_(shared_recognised_suppression)(name, su))
1476 return True;
1477
1478 /* Extra suppressions not used by Addrcheck */
1479 else if (VG_STREQ(name, "Cond")) skind = Value0Supp;
1480 else if (VG_STREQ(name, "Value0")) skind = Value0Supp;/* backwards compat */
1481 else if (VG_STREQ(name, "Value1")) skind = Value1Supp;
1482 else if (VG_STREQ(name, "Value2")) skind = Value2Supp;
1483 else if (VG_STREQ(name, "Value4")) skind = Value4Supp;
1484 else if (VG_STREQ(name, "Value8")) skind = Value8Supp;
1485 else if (VG_STREQ(name, "Value16")) skind = Value16Supp;
1486 else
1487 return False;
1488
1489 VG_(set_supp_kind)(su, skind);
1490 return True;
1491}
1492
1493/*------------------------------------------------------------*/
sewardjc859fbf2005-04-22 21:10:28 +00001494/*--- Functions called directly from generated code: ---*/
1495/*--- Load/store handlers. ---*/
sewardj6cf40ff2005-04-20 22:31:26 +00001496/*------------------------------------------------------------*/
1497
1498/* Types: LOADV4, LOADV2, LOADV1 are:
1499 UWord fn ( Addr a )
1500 so they return 32-bits on 32-bit machines and 64-bits on
1501 64-bit machines. Addr has the same size as a host word.
1502
1503 LOADV8 is always ULong fn ( Addr a )
1504
1505 Similarly for STOREV1, STOREV2, STOREV4, the supplied vbits
1506 are a UWord, and for STOREV8 they are a ULong.
1507*/
1508
sewardj95448072004-11-22 20:19:51 +00001509/* ------------------------ Size = 8 ------------------------ */
1510
sewardj8cf88b72005-07-08 01:29:33 +00001511#define MAKE_LOADV8(nAME,iS_BIGENDIAN) \
1512 \
1513 VG_REGPARM(1) \
1514 ULong nAME ( Addr aA ) \
1515 { \
sewardjae986ca2005-10-12 12:53:20 +00001516 UWord mask, a, sec_no, v_off, a_off, abits; \
1517 SecMap* sm; \
1518 \
sewardj8cf88b72005-07-08 01:29:33 +00001519 PROF_EVENT(200, #nAME); \
1520 \
1521 if (VG_DEBUG_MEMORY >= 2) \
1522 return mc_LOADVn_slow( aA, 8, iS_BIGENDIAN ); \
1523 \
sewardjae986ca2005-10-12 12:53:20 +00001524 mask = ~((0x10000-8) | ((N_PRIMARY_MAP-1) << 16)); \
1525 a = (UWord)aA; \
sewardj8cf88b72005-07-08 01:29:33 +00001526 \
1527 /* If any part of 'a' indicated by the mask is 1, either */ \
1528 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1529 /* covered by the primary map. Either way we defer to the */ \
1530 /* slow-path case. */ \
1531 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1532 PROF_EVENT(201, #nAME"-slow1"); \
1533 return (UWord)mc_LOADVn_slow( aA, 8, iS_BIGENDIAN ); \
1534 } \
1535 \
sewardjae986ca2005-10-12 12:53:20 +00001536 sec_no = (UWord)(a >> 16); \
sewardj8cf88b72005-07-08 01:29:33 +00001537 \
1538 if (VG_DEBUG_MEMORY >= 1) \
1539 tl_assert(sec_no < N_PRIMARY_MAP); \
1540 \
sewardjae986ca2005-10-12 12:53:20 +00001541 sm = primary_map[sec_no]; \
1542 v_off = a & 0xFFFF; \
1543 a_off = v_off >> 3; \
1544 abits = (UWord)(sm->abits[a_off]); \
sewardj8cf88b72005-07-08 01:29:33 +00001545 \
1546 if (EXPECTED_TAKEN(abits == VGM_BYTE_VALID)) { \
1547 /* Handle common case quickly: a is suitably aligned, */ \
1548 /* is mapped, and is addressible. */ \
1549 return ((ULong*)(sm->vbyte))[ v_off >> 3 ]; \
1550 } else { \
1551 /* Slow but general case. */ \
1552 PROF_EVENT(202, #nAME"-slow2"); \
1553 return mc_LOADVn_slow( a, 8, iS_BIGENDIAN ); \
1554 } \
sewardjf9d81612005-04-23 23:25:49 +00001555 }
1556
sewardj8cf88b72005-07-08 01:29:33 +00001557MAKE_LOADV8( MC_(helperc_LOADV8be), True /*bigendian*/ );
1558MAKE_LOADV8( MC_(helperc_LOADV8le), False/*littleendian*/ );
sewardjf9d81612005-04-23 23:25:49 +00001559
sewardjf9d81612005-04-23 23:25:49 +00001560
sewardj8cf88b72005-07-08 01:29:33 +00001561#define MAKE_STOREV8(nAME,iS_BIGENDIAN) \
1562 \
1563 VG_REGPARM(1) \
1564 void nAME ( Addr aA, ULong vbytes ) \
1565 { \
sewardjae986ca2005-10-12 12:53:20 +00001566 UWord mask, a, sec_no, v_off, a_off, abits; \
1567 SecMap* sm; \
1568 \
sewardj8cf88b72005-07-08 01:29:33 +00001569 PROF_EVENT(210, #nAME); \
1570 \
1571 if (VG_DEBUG_MEMORY >= 2) \
1572 mc_STOREVn_slow( aA, 8, vbytes, iS_BIGENDIAN ); \
1573 \
sewardjae986ca2005-10-12 12:53:20 +00001574 mask = ~((0x10000-8) | ((N_PRIMARY_MAP-1) << 16)); \
1575 a = (UWord)aA; \
sewardj8cf88b72005-07-08 01:29:33 +00001576 \
1577 /* If any part of 'a' indicated by the mask is 1, either */ \
1578 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1579 /* covered by the primary map. Either way we defer to the */ \
1580 /* slow-path case. */ \
1581 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1582 PROF_EVENT(211, #nAME"-slow1"); \
1583 mc_STOREVn_slow( aA, 8, vbytes, iS_BIGENDIAN ); \
1584 return; \
1585 } \
1586 \
sewardjae986ca2005-10-12 12:53:20 +00001587 sec_no = (UWord)(a >> 16); \
sewardj8cf88b72005-07-08 01:29:33 +00001588 \
1589 if (VG_DEBUG_MEMORY >= 1) \
1590 tl_assert(sec_no < N_PRIMARY_MAP); \
1591 \
sewardjae986ca2005-10-12 12:53:20 +00001592 sm = primary_map[sec_no]; \
1593 v_off = a & 0xFFFF; \
1594 a_off = v_off >> 3; \
1595 abits = (UWord)(sm->abits[a_off]); \
sewardj8cf88b72005-07-08 01:29:33 +00001596 \
1597 if (EXPECTED_TAKEN(!is_distinguished_sm(sm) \
1598 && abits == VGM_BYTE_VALID)) { \
1599 /* Handle common case quickly: a is suitably aligned, */ \
1600 /* is mapped, and is addressible. */ \
1601 ((ULong*)(sm->vbyte))[ v_off >> 3 ] = vbytes; \
1602 } else { \
1603 /* Slow but general case. */ \
1604 PROF_EVENT(212, #nAME"-slow2"); \
1605 mc_STOREVn_slow( aA, 8, vbytes, iS_BIGENDIAN ); \
1606 } \
sewardjf9d81612005-04-23 23:25:49 +00001607 }
1608
sewardj8cf88b72005-07-08 01:29:33 +00001609MAKE_STOREV8( MC_(helperc_STOREV8be), True /*bigendian*/ );
1610MAKE_STOREV8( MC_(helperc_STOREV8le), False/*littleendian*/ );
sewardj95448072004-11-22 20:19:51 +00001611
sewardj95448072004-11-22 20:19:51 +00001612
1613/* ------------------------ Size = 4 ------------------------ */
1614
sewardj8cf88b72005-07-08 01:29:33 +00001615#define MAKE_LOADV4(nAME,iS_BIGENDIAN) \
1616 \
1617 VG_REGPARM(1) \
1618 UWord nAME ( Addr aA ) \
1619 { \
sewardjae986ca2005-10-12 12:53:20 +00001620 UWord mask, a, sec_no, v_off, a_off, abits; \
1621 SecMap* sm; \
1622 \
sewardj8cf88b72005-07-08 01:29:33 +00001623 PROF_EVENT(220, #nAME); \
1624 \
1625 if (VG_DEBUG_MEMORY >= 2) \
1626 return (UWord)mc_LOADVn_slow( aA, 4, iS_BIGENDIAN ); \
1627 \
sewardjae986ca2005-10-12 12:53:20 +00001628 mask = ~((0x10000-4) | ((N_PRIMARY_MAP-1) << 16)); \
1629 a = (UWord)aA; \
sewardj8cf88b72005-07-08 01:29:33 +00001630 \
1631 /* If any part of 'a' indicated by the mask is 1, either */ \
1632 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1633 /* covered by the primary map. Either way we defer to the */ \
1634 /* slow-path case. */ \
1635 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1636 PROF_EVENT(221, #nAME"-slow1"); \
1637 return (UWord)mc_LOADVn_slow( aA, 4, iS_BIGENDIAN ); \
1638 } \
1639 \
sewardjae986ca2005-10-12 12:53:20 +00001640 sec_no = (UWord)(a >> 16); \
sewardj8cf88b72005-07-08 01:29:33 +00001641 \
1642 if (VG_DEBUG_MEMORY >= 1) \
1643 tl_assert(sec_no < N_PRIMARY_MAP); \
1644 \
sewardjae986ca2005-10-12 12:53:20 +00001645 sm = primary_map[sec_no]; \
1646 v_off = a & 0xFFFF; \
1647 a_off = v_off >> 3; \
1648 abits = (UWord)(sm->abits[a_off]); \
sewardj8cf88b72005-07-08 01:29:33 +00001649 abits >>= (a & 4); \
1650 abits &= 15; \
1651 if (EXPECTED_TAKEN(abits == VGM_NIBBLE_VALID)) { \
1652 /* Handle common case quickly: a is suitably aligned, */ \
1653 /* is mapped, and is addressible. */ \
1654 /* On a 32-bit platform, simply hoick the required 32 */ \
1655 /* bits out of the vbyte array. On a 64-bit platform, */ \
1656 /* also set the upper 32 bits to 1 ("undefined"), just */ \
1657 /* in case. This almost certainly isn't necessary, */ \
1658 /* but be paranoid. */ \
1659 UWord ret = (UWord)0xFFFFFFFF00000000ULL; \
1660 ret |= (UWord)( ((UInt*)(sm->vbyte))[ v_off >> 2 ] ); \
1661 return ret; \
1662 } else { \
1663 /* Slow but general case. */ \
1664 PROF_EVENT(222, #nAME"-slow2"); \
1665 return (UWord)mc_LOADVn_slow( a, 4, iS_BIGENDIAN ); \
1666 } \
sewardjc1a2cda2005-04-21 17:34:00 +00001667 }
1668
sewardj8cf88b72005-07-08 01:29:33 +00001669MAKE_LOADV4( MC_(helperc_LOADV4be), True /*bigendian*/ );
1670MAKE_LOADV4( MC_(helperc_LOADV4le), False/*littleendian*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001671
sewardjc1a2cda2005-04-21 17:34:00 +00001672
sewardj8cf88b72005-07-08 01:29:33 +00001673#define MAKE_STOREV4(nAME,iS_BIGENDIAN) \
1674 \
1675 VG_REGPARM(2) \
1676 void nAME ( Addr aA, UWord vbytes ) \
1677 { \
sewardjae986ca2005-10-12 12:53:20 +00001678 UWord mask, a, sec_no, v_off, a_off, abits; \
1679 SecMap* sm; \
1680 \
sewardj8cf88b72005-07-08 01:29:33 +00001681 PROF_EVENT(230, #nAME); \
1682 \
1683 if (VG_DEBUG_MEMORY >= 2) \
1684 mc_STOREVn_slow( aA, 4, (ULong)vbytes, iS_BIGENDIAN ); \
1685 \
sewardjae986ca2005-10-12 12:53:20 +00001686 mask = ~((0x10000-4) | ((N_PRIMARY_MAP-1) << 16)); \
1687 a = (UWord)aA; \
sewardj8cf88b72005-07-08 01:29:33 +00001688 \
1689 /* If any part of 'a' indicated by the mask is 1, either */ \
1690 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1691 /* covered by the primary map. Either way we defer to the */ \
1692 /* slow-path case. */ \
1693 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1694 PROF_EVENT(231, #nAME"-slow1"); \
1695 mc_STOREVn_slow( aA, 4, (ULong)vbytes, iS_BIGENDIAN ); \
1696 return; \
1697 } \
1698 \
sewardjae986ca2005-10-12 12:53:20 +00001699 sec_no = (UWord)(a >> 16); \
sewardj8cf88b72005-07-08 01:29:33 +00001700 \
1701 if (VG_DEBUG_MEMORY >= 1) \
1702 tl_assert(sec_no < N_PRIMARY_MAP); \
1703 \
sewardjae986ca2005-10-12 12:53:20 +00001704 sm = primary_map[sec_no]; \
1705 v_off = a & 0xFFFF; \
1706 a_off = v_off >> 3; \
1707 abits = (UWord)(sm->abits[a_off]); \
sewardj8cf88b72005-07-08 01:29:33 +00001708 abits >>= (a & 4); \
1709 abits &= 15; \
1710 if (EXPECTED_TAKEN(!is_distinguished_sm(sm) \
1711 && abits == VGM_NIBBLE_VALID)) { \
1712 /* Handle common case quickly: a is suitably aligned, */ \
1713 /* is mapped, and is addressible. */ \
1714 ((UInt*)(sm->vbyte))[ v_off >> 2 ] = (UInt)vbytes; \
1715 } else { \
1716 /* Slow but general case. */ \
1717 PROF_EVENT(232, #nAME"-slow2"); \
1718 mc_STOREVn_slow( aA, 4, (ULong)vbytes, iS_BIGENDIAN ); \
1719 } \
sewardjc1a2cda2005-04-21 17:34:00 +00001720 }
1721
sewardj8cf88b72005-07-08 01:29:33 +00001722MAKE_STOREV4( MC_(helperc_STOREV4be), True /*bigendian*/ );
1723MAKE_STOREV4( MC_(helperc_STOREV4le), False/*littleendian*/ );
njn25e49d8e72002-09-23 09:36:25 +00001724
njn25e49d8e72002-09-23 09:36:25 +00001725
sewardj95448072004-11-22 20:19:51 +00001726/* ------------------------ Size = 2 ------------------------ */
1727
sewardj8cf88b72005-07-08 01:29:33 +00001728#define MAKE_LOADV2(nAME,iS_BIGENDIAN) \
1729 \
1730 VG_REGPARM(1) \
1731 UWord nAME ( Addr aA ) \
1732 { \
sewardjae986ca2005-10-12 12:53:20 +00001733 UWord mask, a, sec_no, v_off, a_off, abits; \
1734 SecMap* sm; \
1735 \
sewardj8cf88b72005-07-08 01:29:33 +00001736 PROF_EVENT(240, #nAME); \
1737 \
1738 if (VG_DEBUG_MEMORY >= 2) \
1739 return (UWord)mc_LOADVn_slow( aA, 2, iS_BIGENDIAN ); \
1740 \
sewardjae986ca2005-10-12 12:53:20 +00001741 mask = ~((0x10000-2) | ((N_PRIMARY_MAP-1) << 16)); \
1742 a = (UWord)aA; \
sewardj8cf88b72005-07-08 01:29:33 +00001743 \
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(241, #nAME"-slow1"); \
1750 return (UWord)mc_LOADVn_slow( aA, 2, iS_BIGENDIAN ); \
1751 } \
1752 \
sewardjae986ca2005-10-12 12:53:20 +00001753 sec_no = (UWord)(a >> 16); \
sewardj8cf88b72005-07-08 01:29:33 +00001754 \
1755 if (VG_DEBUG_MEMORY >= 1) \
1756 tl_assert(sec_no < N_PRIMARY_MAP); \
1757 \
sewardjae986ca2005-10-12 12:53:20 +00001758 sm = primary_map[sec_no]; \
1759 v_off = a & 0xFFFF; \
1760 a_off = v_off >> 3; \
1761 abits = (UWord)(sm->abits[a_off]); \
sewardj8cf88b72005-07-08 01:29:33 +00001762 if (EXPECTED_TAKEN(abits == VGM_BYTE_VALID)) { \
1763 /* Handle common case quickly: a is mapped, and the */ \
1764 /* entire word32 it lives in is addressible. */ \
1765 /* Set the upper 16/48 bits of the result to 1 */ \
1766 /* ("undefined"), just in case. This almost certainly */ \
1767 /* isn't necessary, but be paranoid. */ \
1768 return (~(UWord)0xFFFF) \
1769 | \
1770 (UWord)( ((UShort*)(sm->vbyte))[ v_off >> 1 ] ); \
1771 } else { \
1772 /* Slow but general case. */ \
1773 PROF_EVENT(242, #nAME"-slow2"); \
1774 return (UWord)mc_LOADVn_slow( aA, 2, iS_BIGENDIAN ); \
1775 } \
sewardjc1a2cda2005-04-21 17:34:00 +00001776 }
1777
sewardj8cf88b72005-07-08 01:29:33 +00001778MAKE_LOADV2( MC_(helperc_LOADV2be), True /*bigendian*/ );
1779MAKE_LOADV2( MC_(helperc_LOADV2le), False/*littleendian*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001780
sewardjc1a2cda2005-04-21 17:34:00 +00001781
sewardj8cf88b72005-07-08 01:29:33 +00001782#define MAKE_STOREV2(nAME,iS_BIGENDIAN) \
1783 \
1784 VG_REGPARM(2) \
1785 void nAME ( Addr aA, UWord vbytes ) \
1786 { \
sewardjae986ca2005-10-12 12:53:20 +00001787 UWord mask, a, sec_no, v_off, a_off, abits; \
1788 SecMap* sm; \
1789 \
sewardj8cf88b72005-07-08 01:29:33 +00001790 PROF_EVENT(250, #nAME); \
1791 \
1792 if (VG_DEBUG_MEMORY >= 2) \
1793 mc_STOREVn_slow( aA, 2, (ULong)vbytes, iS_BIGENDIAN ); \
1794 \
sewardjae986ca2005-10-12 12:53:20 +00001795 mask = ~((0x10000-2) | ((N_PRIMARY_MAP-1) << 16)); \
1796 a = (UWord)aA; \
sewardj8cf88b72005-07-08 01:29:33 +00001797 \
1798 /* If any part of 'a' indicated by the mask is 1, either */ \
1799 /* 'a' is not naturally aligned, or 'a' exceeds the range */ \
1800 /* covered by the primary map. Either way we defer to the */ \
1801 /* slow-path case. */ \
1802 if (EXPECTED_NOT_TAKEN(a & mask)) { \
1803 PROF_EVENT(251, #nAME"-slow1"); \
1804 mc_STOREVn_slow( aA, 2, (ULong)vbytes, iS_BIGENDIAN ); \
1805 return; \
1806 } \
1807 \
sewardjae986ca2005-10-12 12:53:20 +00001808 sec_no = (UWord)(a >> 16); \
sewardj8cf88b72005-07-08 01:29:33 +00001809 \
1810 if (VG_DEBUG_MEMORY >= 1) \
1811 tl_assert(sec_no < N_PRIMARY_MAP); \
1812 \
sewardjae986ca2005-10-12 12:53:20 +00001813 sm = primary_map[sec_no]; \
1814 v_off = a & 0xFFFF; \
1815 a_off = v_off >> 3; \
1816 abits = (UWord)(sm->abits[a_off]); \
sewardj8cf88b72005-07-08 01:29:33 +00001817 if (EXPECTED_TAKEN(!is_distinguished_sm(sm) \
1818 && abits == VGM_BYTE_VALID)) { \
1819 /* Handle common case quickly. */ \
1820 ((UShort*)(sm->vbyte))[ v_off >> 1 ] = (UShort)vbytes; \
1821 } else { \
1822 /* Slow but general case. */ \
1823 PROF_EVENT(252, #nAME"-slow2"); \
1824 mc_STOREVn_slow( aA, 2, (ULong)vbytes, iS_BIGENDIAN ); \
1825 } \
sewardjc1a2cda2005-04-21 17:34:00 +00001826 }
1827
njn25e49d8e72002-09-23 09:36:25 +00001828
sewardj8cf88b72005-07-08 01:29:33 +00001829MAKE_STOREV2( MC_(helperc_STOREV2be), True /*bigendian*/ );
1830MAKE_STOREV2( MC_(helperc_STOREV2le), False/*littleendian*/ );
sewardj5d28efc2005-04-21 22:16:29 +00001831
njn25e49d8e72002-09-23 09:36:25 +00001832
sewardj95448072004-11-22 20:19:51 +00001833/* ------------------------ Size = 1 ------------------------ */
sewardj8cf88b72005-07-08 01:29:33 +00001834/* Note: endianness is irrelevant for size == 1 */
sewardj95448072004-11-22 20:19:51 +00001835
njnaf839f52005-06-23 03:27:57 +00001836VG_REGPARM(1)
sewardj8cf88b72005-07-08 01:29:33 +00001837UWord MC_(helperc_LOADV1) ( Addr aA )
njn25e49d8e72002-09-23 09:36:25 +00001838{
sewardjae986ca2005-10-12 12:53:20 +00001839 UWord mask, a, sec_no, v_off, a_off, abits;
1840 SecMap* sm;
1841
sewardj8cf88b72005-07-08 01:29:33 +00001842 PROF_EVENT(260, "helperc_LOADV1");
sewardjc1a2cda2005-04-21 17:34:00 +00001843
1844# if VG_DEBUG_MEMORY >= 2
sewardj8cf88b72005-07-08 01:29:33 +00001845 return (UWord)mc_LOADVn_slow( aA, 1, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001846# else
1847
sewardjae986ca2005-10-12 12:53:20 +00001848 mask = ~((0x10000-1) | ((N_PRIMARY_MAP-1) << 16));
1849 a = (UWord)aA;
sewardjc1a2cda2005-04-21 17:34:00 +00001850
1851 /* If any part of 'a' indicated by the mask is 1, it means 'a'
1852 exceeds the range covered by the primary map. In which case we
1853 defer to the slow-path case. */
1854 if (EXPECTED_NOT_TAKEN(a & mask)) {
sewardj8cf88b72005-07-08 01:29:33 +00001855 PROF_EVENT(261, "helperc_LOADV1-slow1");
1856 return (UWord)mc_LOADVn_slow( aA, 1, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001857 }
1858
sewardjae986ca2005-10-12 12:53:20 +00001859 sec_no = (UWord)(a >> 16);
sewardjc1a2cda2005-04-21 17:34:00 +00001860
1861# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +00001862 tl_assert(sec_no < N_PRIMARY_MAP);
sewardjc1a2cda2005-04-21 17:34:00 +00001863# endif
1864
sewardjae986ca2005-10-12 12:53:20 +00001865 sm = primary_map[sec_no];
1866 v_off = a & 0xFFFF;
1867 a_off = v_off >> 3;
1868 abits = (UWord)(sm->abits[a_off]);
sewardjc1a2cda2005-04-21 17:34:00 +00001869 if (EXPECTED_TAKEN(abits == VGM_BYTE_VALID)) {
1870 /* Handle common case quickly: a is mapped, and the entire
1871 word32 it lives in is addressible. */
sewardj5d28efc2005-04-21 22:16:29 +00001872 /* Set the upper 24/56 bits of the result to 1 ("undefined"),
1873 just in case. This almost certainly isn't necessary, but be
1874 paranoid. */
sewardjc1a2cda2005-04-21 17:34:00 +00001875 return (~(UWord)0xFF)
1876 |
1877 (UWord)( ((UChar*)(sm->vbyte))[ v_off ] );
1878 } else {
1879 /* Slow but general case. */
sewardj8cf88b72005-07-08 01:29:33 +00001880 PROF_EVENT(262, "helperc_LOADV1-slow2");
1881 return (UWord)mc_LOADVn_slow( aA, 1, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001882 }
1883# endif
njn25e49d8e72002-09-23 09:36:25 +00001884}
1885
sewardjc1a2cda2005-04-21 17:34:00 +00001886
njnaf839f52005-06-23 03:27:57 +00001887VG_REGPARM(2)
sewardj8cf88b72005-07-08 01:29:33 +00001888void MC_(helperc_STOREV1) ( Addr aA, UWord vbyte )
njn25e49d8e72002-09-23 09:36:25 +00001889{
sewardjae986ca2005-10-12 12:53:20 +00001890 UWord mask, a, sec_no, v_off, a_off, abits;
1891 SecMap* sm;
1892
sewardj8cf88b72005-07-08 01:29:33 +00001893 PROF_EVENT(270, "helperc_STOREV1");
sewardjc1a2cda2005-04-21 17:34:00 +00001894
1895# if VG_DEBUG_MEMORY >= 2
sewardj8cf88b72005-07-08 01:29:33 +00001896 mc_STOREVn_slow( aA, 1, (ULong)vbyte, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001897# else
1898
sewardjae986ca2005-10-12 12:53:20 +00001899 mask = ~((0x10000-1) | ((N_PRIMARY_MAP-1) << 16));
1900 a = (UWord)aA;
sewardjc1a2cda2005-04-21 17:34:00 +00001901 /* If any part of 'a' indicated by the mask is 1, it means 'a'
1902 exceeds the range covered by the primary map. In which case we
1903 defer to the slow-path case. */
1904 if (EXPECTED_NOT_TAKEN(a & mask)) {
sewardj8cf88b72005-07-08 01:29:33 +00001905 PROF_EVENT(271, "helperc_STOREV1-slow1");
1906 mc_STOREVn_slow( aA, 1, (ULong)vbyte, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001907 return;
1908 }
1909
sewardjae986ca2005-10-12 12:53:20 +00001910 sec_no = (UWord)(a >> 16);
sewardjc1a2cda2005-04-21 17:34:00 +00001911
1912# if VG_DEBUG_MEMORY >= 1
sewardj23eb2fd2005-04-22 16:29:19 +00001913 tl_assert(sec_no < N_PRIMARY_MAP);
sewardjc1a2cda2005-04-21 17:34:00 +00001914# endif
1915
sewardjae986ca2005-10-12 12:53:20 +00001916 sm = primary_map[sec_no];
1917 v_off = a & 0xFFFF;
1918 a_off = v_off >> 3;
1919 abits = (UWord)(sm->abits[a_off]);
sewardjc1a2cda2005-04-21 17:34:00 +00001920 if (EXPECTED_TAKEN(!is_distinguished_sm(sm)
1921 && abits == VGM_BYTE_VALID)) {
1922 /* Handle common case quickly: a is mapped, the entire word32 it
1923 lives in is addressible. */
1924 ((UChar*)(sm->vbyte))[ v_off ] = (UChar)vbyte;
1925 } else {
sewardj8cf88b72005-07-08 01:29:33 +00001926 PROF_EVENT(272, "helperc_STOREV1-slow2");
1927 mc_STOREVn_slow( aA, 1, (ULong)vbyte, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00001928 }
1929
1930# endif
njn25e49d8e72002-09-23 09:36:25 +00001931}
1932
1933
sewardjc859fbf2005-04-22 21:10:28 +00001934/*------------------------------------------------------------*/
1935/*--- Functions called directly from generated code: ---*/
1936/*--- Value-check failure handlers. ---*/
1937/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00001938
njn5c004e42002-11-18 11:04:50 +00001939void MC_(helperc_value_check0_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001940{
njn9e63cb62005-05-08 18:34:59 +00001941 mc_record_value_error ( VG_(get_running_tid)(), 0 );
njn25e49d8e72002-09-23 09:36:25 +00001942}
1943
njn5c004e42002-11-18 11:04:50 +00001944void MC_(helperc_value_check1_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001945{
njn9e63cb62005-05-08 18:34:59 +00001946 mc_record_value_error ( VG_(get_running_tid)(), 1 );
njn25e49d8e72002-09-23 09:36:25 +00001947}
1948
njn5c004e42002-11-18 11:04:50 +00001949void MC_(helperc_value_check4_fail) ( void )
njn25e49d8e72002-09-23 09:36:25 +00001950{
njn9e63cb62005-05-08 18:34:59 +00001951 mc_record_value_error ( VG_(get_running_tid)(), 4 );
njn25e49d8e72002-09-23 09:36:25 +00001952}
1953
sewardj11bcc4e2005-04-23 22:38:38 +00001954void MC_(helperc_value_check8_fail) ( void )
1955{
njn9e63cb62005-05-08 18:34:59 +00001956 mc_record_value_error ( VG_(get_running_tid)(), 8 );
sewardj11bcc4e2005-04-23 22:38:38 +00001957}
1958
njnaf839f52005-06-23 03:27:57 +00001959VG_REGPARM(1) void MC_(helperc_complain_undef) ( HWord sz )
sewardj95448072004-11-22 20:19:51 +00001960{
njn9e63cb62005-05-08 18:34:59 +00001961 mc_record_value_error ( VG_(get_running_tid)(), (Int)sz );
sewardj95448072004-11-22 20:19:51 +00001962}
1963
njn25e49d8e72002-09-23 09:36:25 +00001964
sewardj45d94cc2005-04-20 14:44:11 +00001965//zz /*------------------------------------------------------------*/
1966//zz /*--- Metadata get/set functions, for client requests. ---*/
1967//zz /*------------------------------------------------------------*/
1968//zz
1969//zz /* Copy Vbits for src into vbits. Returns: 1 == OK, 2 == alignment
1970//zz error, 3 == addressing error. */
1971//zz static Int mc_get_or_set_vbits_for_client (
1972//zz ThreadId tid,
1973//zz Addr dataV,
1974//zz Addr vbitsV,
1975//zz SizeT size,
1976//zz Bool setting /* True <=> set vbits, False <=> get vbits */
1977//zz )
1978//zz {
1979//zz Bool addressibleD = True;
1980//zz Bool addressibleV = True;
1981//zz UInt* data = (UInt*)dataV;
1982//zz UInt* vbits = (UInt*)vbitsV;
1983//zz SizeT szW = size / 4; /* sigh */
1984//zz SizeT i;
1985//zz UInt* dataP = NULL; /* bogus init to keep gcc happy */
1986//zz UInt* vbitsP = NULL; /* ditto */
1987//zz
1988//zz /* Check alignment of args. */
1989//zz if (!(VG_IS_4_ALIGNED(data) && VG_IS_4_ALIGNED(vbits)))
1990//zz return 2;
1991//zz if ((size & 3) != 0)
1992//zz return 2;
1993//zz
1994//zz /* Check that arrays are addressible. */
1995//zz for (i = 0; i < szW; i++) {
1996//zz dataP = &data[i];
1997//zz vbitsP = &vbits[i];
1998//zz if (get_abits4_ALIGNED((Addr)dataP) != VGM_NIBBLE_VALID) {
1999//zz addressibleD = False;
2000//zz break;
2001//zz }
2002//zz if (get_abits4_ALIGNED((Addr)vbitsP) != VGM_NIBBLE_VALID) {
2003//zz addressibleV = False;
2004//zz break;
2005//zz }
2006//zz }
2007//zz if (!addressibleD) {
2008//zz MAC_(record_address_error)( tid, (Addr)dataP, 4,
2009//zz setting ? True : False );
2010//zz return 3;
2011//zz }
2012//zz if (!addressibleV) {
2013//zz MAC_(record_address_error)( tid, (Addr)vbitsP, 4,
2014//zz setting ? False : True );
2015//zz return 3;
2016//zz }
2017//zz
2018//zz /* Do the copy */
2019//zz if (setting) {
2020//zz /* setting */
2021//zz for (i = 0; i < szW; i++) {
2022//zz if (get_vbytes4_ALIGNED( (Addr)&vbits[i] ) != VGM_WORD_VALID)
njn9e63cb62005-05-08 18:34:59 +00002023//zz mc_record_value_error(tid, 4);
sewardj45d94cc2005-04-20 14:44:11 +00002024//zz set_vbytes4_ALIGNED( (Addr)&data[i], vbits[i] );
2025//zz }
2026//zz } else {
2027//zz /* getting */
2028//zz for (i = 0; i < szW; i++) {
2029//zz vbits[i] = get_vbytes4_ALIGNED( (Addr)&data[i] );
2030//zz set_vbytes4_ALIGNED( (Addr)&vbits[i], VGM_WORD_VALID );
2031//zz }
2032//zz }
2033//zz
2034//zz return 1;
2035//zz }
sewardj05fe85e2005-04-27 22:46:36 +00002036
2037
2038/*------------------------------------------------------------*/
2039/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
2040/*------------------------------------------------------------*/
2041
2042/* For the memory leak detector, say whether an entire 64k chunk of
2043 address space is possibly in use, or not. If in doubt return
2044 True.
2045*/
2046static
2047Bool mc_is_within_valid_secondary ( Addr a )
2048{
2049 SecMap* sm = maybe_get_secmap_for ( a );
2050 if (sm == NULL || sm == &sm_distinguished[SM_DIST_NOACCESS]) {
2051 /* Definitely not in use. */
2052 return False;
2053 } else {
2054 return True;
2055 }
2056}
2057
2058
2059/* For the memory leak detector, say whether or not a given word
2060 address is to be regarded as valid. */
2061static
2062Bool mc_is_valid_aligned_word ( Addr a )
2063{
2064 tl_assert(sizeof(UWord) == 4 || sizeof(UWord) == 8);
2065 if (sizeof(UWord) == 4) {
2066 tl_assert(VG_IS_4_ALIGNED(a));
2067 } else {
2068 tl_assert(VG_IS_8_ALIGNED(a));
2069 }
2070 if (mc_check_readable( a, sizeof(UWord), NULL ) == MC_Ok) {
2071 return True;
2072 } else {
2073 return False;
2074 }
2075}
sewardja4495682002-10-21 07:29:59 +00002076
2077
nethercote996901a2004-08-03 13:29:09 +00002078/* Leak detector for this tool. We don't actually do anything, merely
sewardja4495682002-10-21 07:29:59 +00002079 run the generic leak detector with suitable parameters for this
nethercote996901a2004-08-03 13:29:09 +00002080 tool. */
njnb8dca862005-03-14 02:42:44 +00002081static void mc_detect_memory_leaks ( ThreadId tid, LeakCheckMode mode )
njn25e49d8e72002-09-23 09:36:25 +00002082{
sewardj05fe85e2005-04-27 22:46:36 +00002083 MAC_(do_detect_memory_leaks) (
2084 tid,
2085 mode,
2086 mc_is_within_valid_secondary,
2087 mc_is_valid_aligned_word
2088 );
njn25e49d8e72002-09-23 09:36:25 +00002089}
2090
2091
sewardjc859fbf2005-04-22 21:10:28 +00002092/*------------------------------------------------------------*/
2093/*--- Initialisation ---*/
2094/*------------------------------------------------------------*/
2095
2096static void init_shadow_memory ( void )
2097{
2098 Int i;
2099 SecMap* sm;
2100
2101 /* Build the 3 distinguished secondaries */
2102 tl_assert(VGM_BIT_INVALID == 1);
2103 tl_assert(VGM_BIT_VALID == 0);
2104 tl_assert(VGM_BYTE_INVALID == 0xFF);
2105 tl_assert(VGM_BYTE_VALID == 0);
2106
2107 /* Set A invalid, V invalid. */
2108 sm = &sm_distinguished[SM_DIST_NOACCESS];
2109 for (i = 0; i < 65536; i++)
2110 sm->vbyte[i] = VGM_BYTE_INVALID;
2111 for (i = 0; i < 8192; i++)
2112 sm->abits[i] = VGM_BYTE_INVALID;
2113
2114 /* Set A valid, V invalid. */
2115 sm = &sm_distinguished[SM_DIST_ACCESS_UNDEFINED];
2116 for (i = 0; i < 65536; i++)
2117 sm->vbyte[i] = VGM_BYTE_INVALID;
2118 for (i = 0; i < 8192; i++)
2119 sm->abits[i] = VGM_BYTE_VALID;
2120
2121 /* Set A valid, V valid. */
2122 sm = &sm_distinguished[SM_DIST_ACCESS_DEFINED];
2123 for (i = 0; i < 65536; i++)
2124 sm->vbyte[i] = VGM_BYTE_VALID;
2125 for (i = 0; i < 8192; i++)
2126 sm->abits[i] = VGM_BYTE_VALID;
2127
2128 /* Set up the primary map. */
2129 /* These entries gradually get overwritten as the used address
2130 space expands. */
2131 for (i = 0; i < N_PRIMARY_MAP; i++)
2132 primary_map[i] = &sm_distinguished[SM_DIST_NOACCESS];
2133
2134 /* auxmap_size = auxmap_used = 0;
2135 no ... these are statically initialised */
2136}
2137
2138
2139/*------------------------------------------------------------*/
2140/*--- Sanity check machinery (permanently engaged) ---*/
2141/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00002142
njn51d827b2005-05-09 01:02:08 +00002143static Bool mc_cheap_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00002144{
jseward9800fd32004-01-04 23:08:04 +00002145 /* nothing useful we can rapidly check */
sewardj23eb2fd2005-04-22 16:29:19 +00002146 n_sanity_cheap++;
sewardjc1a2cda2005-04-21 17:34:00 +00002147 PROF_EVENT(490, "cheap_sanity_check");
jseward9800fd32004-01-04 23:08:04 +00002148 return True;
njn25e49d8e72002-09-23 09:36:25 +00002149}
2150
njn51d827b2005-05-09 01:02:08 +00002151static Bool mc_expensive_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00002152{
sewardj23eb2fd2005-04-22 16:29:19 +00002153 Int i, n_secmaps_found;
sewardj45d94cc2005-04-20 14:44:11 +00002154 SecMap* sm;
sewardj23eb2fd2005-04-22 16:29:19 +00002155 Bool bad = False;
njn25e49d8e72002-09-23 09:36:25 +00002156
sewardj23eb2fd2005-04-22 16:29:19 +00002157 n_sanity_expensive++;
sewardjc1a2cda2005-04-21 17:34:00 +00002158 PROF_EVENT(491, "expensive_sanity_check");
2159
sewardj23eb2fd2005-04-22 16:29:19 +00002160 /* Check that the 3 distinguished SMs are still as they should
2161 be. */
njn25e49d8e72002-09-23 09:36:25 +00002162
sewardj45d94cc2005-04-20 14:44:11 +00002163 /* Check A invalid, V invalid. */
2164 sm = &sm_distinguished[SM_DIST_NOACCESS];
njn25e49d8e72002-09-23 09:36:25 +00002165 for (i = 0; i < 65536; i++)
sewardj45d94cc2005-04-20 14:44:11 +00002166 if (!(sm->vbyte[i] == VGM_BYTE_INVALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002167 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00002168 for (i = 0; i < 8192; i++)
2169 if (!(sm->abits[i] == VGM_BYTE_INVALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002170 bad = True;
njn25e49d8e72002-09-23 09:36:25 +00002171
sewardj45d94cc2005-04-20 14:44:11 +00002172 /* Check A valid, V invalid. */
2173 sm = &sm_distinguished[SM_DIST_ACCESS_UNDEFINED];
2174 for (i = 0; i < 65536; i++)
2175 if (!(sm->vbyte[i] == VGM_BYTE_INVALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002176 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00002177 for (i = 0; i < 8192; i++)
2178 if (!(sm->abits[i] == VGM_BYTE_VALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002179 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00002180
2181 /* Check A valid, V valid. */
2182 sm = &sm_distinguished[SM_DIST_ACCESS_DEFINED];
2183 for (i = 0; i < 65536; i++)
2184 if (!(sm->vbyte[i] == VGM_BYTE_VALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002185 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00002186 for (i = 0; i < 8192; i++)
2187 if (!(sm->abits[i] == VGM_BYTE_VALID))
sewardj23eb2fd2005-04-22 16:29:19 +00002188 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00002189
sewardj23eb2fd2005-04-22 16:29:19 +00002190 if (bad) {
2191 VG_(printf)("memcheck expensive sanity: "
2192 "distinguished_secondaries have changed\n");
2193 return False;
2194 }
2195
2196 /* check nonsensical auxmap sizing */
sewardj45d94cc2005-04-20 14:44:11 +00002197 if (auxmap_used > auxmap_size)
sewardj23eb2fd2005-04-22 16:29:19 +00002198 bad = True;
2199
2200 if (bad) {
2201 VG_(printf)("memcheck expensive sanity: "
2202 "nonsensical auxmap sizing\n");
2203 return False;
2204 }
2205
2206 /* check that the number of secmaps issued matches the number that
2207 are reachable (iow, no secmap leaks) */
2208 n_secmaps_found = 0;
2209 for (i = 0; i < N_PRIMARY_MAP; i++) {
2210 if (primary_map[i] == NULL) {
2211 bad = True;
2212 } else {
2213 if (!is_distinguished_sm(primary_map[i]))
2214 n_secmaps_found++;
2215 }
2216 }
2217
2218 for (i = 0; i < auxmap_used; i++) {
2219 if (auxmap[i].sm == NULL) {
2220 bad = True;
2221 } else {
2222 if (!is_distinguished_sm(auxmap[i].sm))
2223 n_secmaps_found++;
2224 }
2225 }
2226
2227 if (n_secmaps_found != n_secmaps_issued)
2228 bad = True;
2229
2230 if (bad) {
2231 VG_(printf)("memcheck expensive sanity: "
2232 "apparent secmap leakage\n");
2233 return False;
2234 }
2235
2236 /* check that auxmap only covers address space that the primary
2237 doesn't */
2238
2239 for (i = 0; i < auxmap_used; i++)
2240 if (auxmap[i].base <= MAX_PRIMARY_ADDRESS)
2241 bad = True;
2242
2243 if (bad) {
2244 VG_(printf)("memcheck expensive sanity: "
2245 "auxmap covers wrong address space\n");
2246 return False;
2247 }
2248
2249 /* there is only one pointer to each secmap (expensive) */
njn25e49d8e72002-09-23 09:36:25 +00002250
2251 return True;
2252}
sewardj45d94cc2005-04-20 14:44:11 +00002253
njn25e49d8e72002-09-23 09:36:25 +00002254
njn25e49d8e72002-09-23 09:36:25 +00002255/*------------------------------------------------------------*/
njnd3040452003-05-19 15:04:06 +00002256/*--- Command line args ---*/
njn25e49d8e72002-09-23 09:36:25 +00002257/*------------------------------------------------------------*/
2258
njn51d827b2005-05-09 01:02:08 +00002259static Bool mc_process_cmd_line_option(Char* arg)
njn25e49d8e72002-09-23 09:36:25 +00002260{
sewardjf3418c02005-11-08 14:10:24 +00002261 return MAC_(process_common_cmd_line_option)(arg);
njn25e49d8e72002-09-23 09:36:25 +00002262}
2263
njn51d827b2005-05-09 01:02:08 +00002264static void mc_print_usage(void)
njn25e49d8e72002-09-23 09:36:25 +00002265{
njn3e884182003-04-15 13:03:23 +00002266 MAC_(print_common_usage)();
njn3e884182003-04-15 13:03:23 +00002267}
2268
njn51d827b2005-05-09 01:02:08 +00002269static void mc_print_debug_usage(void)
njn3e884182003-04-15 13:03:23 +00002270{
2271 MAC_(print_common_debug_usage)();
njn25e49d8e72002-09-23 09:36:25 +00002272}
2273
sewardjf3418c02005-11-08 14:10:24 +00002274
nethercote8b76fe52004-11-08 19:20:09 +00002275/*------------------------------------------------------------*/
2276/*--- Client requests ---*/
2277/*------------------------------------------------------------*/
2278
2279/* Client block management:
2280
2281 This is managed as an expanding array of client block descriptors.
2282 Indices of live descriptors are issued to the client, so it can ask
2283 to free them later. Therefore we cannot slide live entries down
2284 over dead ones. Instead we must use free/inuse flags and scan for
2285 an empty slot at allocation time. This in turn means allocation is
2286 relatively expensive, so we hope this does not happen too often.
nethercote8b76fe52004-11-08 19:20:09 +00002287
sewardjedc75ab2005-03-15 23:30:32 +00002288 An unused block has start == size == 0
2289*/
nethercote8b76fe52004-11-08 19:20:09 +00002290
2291typedef
2292 struct {
2293 Addr start;
2294 SizeT size;
2295 ExeContext* where;
sewardj8cf88b72005-07-08 01:29:33 +00002296 Char* desc;
nethercote8b76fe52004-11-08 19:20:09 +00002297 }
2298 CGenBlock;
2299
2300/* This subsystem is self-initialising. */
njn695c16e2005-03-27 03:40:28 +00002301static UInt cgb_size = 0;
2302static UInt cgb_used = 0;
2303static CGenBlock* cgbs = NULL;
nethercote8b76fe52004-11-08 19:20:09 +00002304
2305/* Stats for this subsystem. */
njn695c16e2005-03-27 03:40:28 +00002306static UInt cgb_used_MAX = 0; /* Max in use. */
2307static UInt cgb_allocs = 0; /* Number of allocs. */
2308static UInt cgb_discards = 0; /* Number of discards. */
2309static UInt cgb_search = 0; /* Number of searches. */
nethercote8b76fe52004-11-08 19:20:09 +00002310
2311
2312static
njn695c16e2005-03-27 03:40:28 +00002313Int alloc_client_block ( void )
nethercote8b76fe52004-11-08 19:20:09 +00002314{
2315 UInt i, sz_new;
2316 CGenBlock* cgbs_new;
2317
njn695c16e2005-03-27 03:40:28 +00002318 cgb_allocs++;
nethercote8b76fe52004-11-08 19:20:09 +00002319
njn695c16e2005-03-27 03:40:28 +00002320 for (i = 0; i < cgb_used; i++) {
2321 cgb_search++;
2322 if (cgbs[i].start == 0 && cgbs[i].size == 0)
nethercote8b76fe52004-11-08 19:20:09 +00002323 return i;
2324 }
2325
2326 /* Not found. Try to allocate one at the end. */
njn695c16e2005-03-27 03:40:28 +00002327 if (cgb_used < cgb_size) {
2328 cgb_used++;
2329 return cgb_used-1;
nethercote8b76fe52004-11-08 19:20:09 +00002330 }
2331
2332 /* Ok, we have to allocate a new one. */
njn695c16e2005-03-27 03:40:28 +00002333 tl_assert(cgb_used == cgb_size);
2334 sz_new = (cgbs == NULL) ? 10 : (2 * cgb_size);
nethercote8b76fe52004-11-08 19:20:09 +00002335
2336 cgbs_new = VG_(malloc)( sz_new * sizeof(CGenBlock) );
njn695c16e2005-03-27 03:40:28 +00002337 for (i = 0; i < cgb_used; i++)
2338 cgbs_new[i] = cgbs[i];
nethercote8b76fe52004-11-08 19:20:09 +00002339
njn695c16e2005-03-27 03:40:28 +00002340 if (cgbs != NULL)
2341 VG_(free)( cgbs );
2342 cgbs = cgbs_new;
nethercote8b76fe52004-11-08 19:20:09 +00002343
njn695c16e2005-03-27 03:40:28 +00002344 cgb_size = sz_new;
2345 cgb_used++;
2346 if (cgb_used > cgb_used_MAX)
2347 cgb_used_MAX = cgb_used;
2348 return cgb_used-1;
nethercote8b76fe52004-11-08 19:20:09 +00002349}
2350
2351
2352static void show_client_block_stats ( void )
2353{
2354 VG_(message)(Vg_DebugMsg,
2355 "general CBs: %d allocs, %d discards, %d maxinuse, %d search",
njn695c16e2005-03-27 03:40:28 +00002356 cgb_allocs, cgb_discards, cgb_used_MAX, cgb_search
nethercote8b76fe52004-11-08 19:20:09 +00002357 );
2358}
2359
nethercote8b76fe52004-11-08 19:20:09 +00002360static Bool client_perm_maybe_describe( Addr a, AddrInfo* ai )
2361{
2362 UInt i;
2363 /* VG_(printf)("try to identify %d\n", a); */
2364
2365 /* Perhaps it's a general block ? */
njn695c16e2005-03-27 03:40:28 +00002366 for (i = 0; i < cgb_used; i++) {
2367 if (cgbs[i].start == 0 && cgbs[i].size == 0)
nethercote8b76fe52004-11-08 19:20:09 +00002368 continue;
njn717cde52005-05-10 02:47:21 +00002369 // Use zero as the redzone for client blocks.
2370 if (VG_(addr_is_in_block)(a, cgbs[i].start, cgbs[i].size, 0)) {
nethercote8b76fe52004-11-08 19:20:09 +00002371 /* OK - maybe it's a mempool, too? */
njn12627272005-08-14 18:32:16 +00002372 MAC_Mempool* mp = VG_(HT_lookup)(MAC_(mempool_list),
2373 (UWord)cgbs[i].start);
njn1d0cb0d2005-08-15 01:52:02 +00002374 if (mp != NULL) {
2375 if (mp->chunks != NULL) {
2376 MAC_Chunk* mc;
njnf66dbfc2005-08-15 01:54:05 +00002377 VG_(HT_ResetIter)(mp->chunks);
2378 while ( (mc = VG_(HT_Next)(mp->chunks)) ) {
njn1d0cb0d2005-08-15 01:52:02 +00002379 if (VG_(addr_is_in_block)(a, mc->data, mc->size,
2380 MAC_MALLOC_REDZONE_SZB)) {
2381 ai->akind = UserG;
2382 ai->blksize = mc->size;
2383 ai->rwoffset = (Int)(a) - (Int)mc->data;
2384 ai->lastchange = mc->where;
2385 return True;
2386 }
nethercote8b76fe52004-11-08 19:20:09 +00002387 }
2388 }
njn1d0cb0d2005-08-15 01:52:02 +00002389 ai->akind = Mempool;
2390 ai->blksize = cgbs[i].size;
2391 ai->rwoffset = (Int)(a) - (Int)(cgbs[i].start);
njn695c16e2005-03-27 03:40:28 +00002392 ai->lastchange = cgbs[i].where;
nethercote8b76fe52004-11-08 19:20:09 +00002393 return True;
2394 }
njn1d0cb0d2005-08-15 01:52:02 +00002395 ai->akind = UserG;
2396 ai->blksize = cgbs[i].size;
2397 ai->rwoffset = (Int)(a) - (Int)(cgbs[i].start);
njn695c16e2005-03-27 03:40:28 +00002398 ai->lastchange = cgbs[i].where;
njn1d0cb0d2005-08-15 01:52:02 +00002399 ai->desc = cgbs[i].desc;
nethercote8b76fe52004-11-08 19:20:09 +00002400 return True;
2401 }
2402 }
2403 return False;
2404}
2405
njn51d827b2005-05-09 01:02:08 +00002406static Bool mc_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret )
nethercote8b76fe52004-11-08 19:20:09 +00002407{
2408 Int i;
2409 Bool ok;
2410 Addr bad_addr;
2411
njnfc26ff92004-11-22 19:12:49 +00002412 if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
nethercote8b76fe52004-11-08 19:20:09 +00002413 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
2414 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
2415 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
2416 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
2417 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
2418 && VG_USERREQ__MEMPOOL_FREE != arg[0])
2419 return False;
2420
2421 switch (arg[0]) {
2422 case VG_USERREQ__CHECK_WRITABLE: /* check writable */
2423 ok = mc_check_writable ( arg[1], arg[2], &bad_addr );
2424 if (!ok)
njn9e63cb62005-05-08 18:34:59 +00002425 mc_record_user_error ( tid, bad_addr, /*isWrite*/True,
2426 /*isUnaddr*/True );
nethercote8b76fe52004-11-08 19:20:09 +00002427 *ret = ok ? (UWord)NULL : bad_addr;
sewardj8cf88b72005-07-08 01:29:33 +00002428 break;
nethercote8b76fe52004-11-08 19:20:09 +00002429
2430 case VG_USERREQ__CHECK_READABLE: { /* check readable */
2431 MC_ReadResult res;
2432 res = mc_check_readable ( arg[1], arg[2], &bad_addr );
2433 if (MC_AddrErr == res)
njn9e63cb62005-05-08 18:34:59 +00002434 mc_record_user_error ( tid, bad_addr, /*isWrite*/False,
2435 /*isUnaddr*/True );
nethercote8b76fe52004-11-08 19:20:09 +00002436 else if (MC_ValueErr == res)
njn9e63cb62005-05-08 18:34:59 +00002437 mc_record_user_error ( tid, bad_addr, /*isWrite*/False,
2438 /*isUnaddr*/False );
nethercote8b76fe52004-11-08 19:20:09 +00002439 *ret = ( res==MC_Ok ? (UWord)NULL : bad_addr );
sewardj8cf88b72005-07-08 01:29:33 +00002440 break;
nethercote8b76fe52004-11-08 19:20:09 +00002441 }
2442
2443 case VG_USERREQ__DO_LEAK_CHECK:
njnb8dca862005-03-14 02:42:44 +00002444 mc_detect_memory_leaks(tid, arg[1] ? LC_Summary : LC_Full);
sewardj8cf88b72005-07-08 01:29:33 +00002445 *ret = 0; /* return value is meaningless */
2446 break;
nethercote8b76fe52004-11-08 19:20:09 +00002447
2448 case VG_USERREQ__MAKE_NOACCESS: /* make no access */
nethercote8b76fe52004-11-08 19:20:09 +00002449 mc_make_noaccess ( arg[1], arg[2] );
sewardj8cf88b72005-07-08 01:29:33 +00002450 *ret = -1;
2451 break;
nethercote8b76fe52004-11-08 19:20:09 +00002452
2453 case VG_USERREQ__MAKE_WRITABLE: /* make writable */
nethercote8b76fe52004-11-08 19:20:09 +00002454 mc_make_writable ( arg[1], arg[2] );
sewardjedc75ab2005-03-15 23:30:32 +00002455 *ret = -1;
sewardj8cf88b72005-07-08 01:29:33 +00002456 break;
nethercote8b76fe52004-11-08 19:20:09 +00002457
2458 case VG_USERREQ__MAKE_READABLE: /* make readable */
nethercote8b76fe52004-11-08 19:20:09 +00002459 mc_make_readable ( arg[1], arg[2] );
sewardj8cf88b72005-07-08 01:29:33 +00002460 *ret = -1;
nethercote8b76fe52004-11-08 19:20:09 +00002461 break;
2462
sewardjedc75ab2005-03-15 23:30:32 +00002463 case VG_USERREQ__CREATE_BLOCK: /* describe a block */
sewardj8cf88b72005-07-08 01:29:33 +00002464 if (arg[1] != 0 && arg[2] != 0) {
2465 i = alloc_client_block();
2466 /* VG_(printf)("allocated %d %p\n", i, cgbs); */
2467 cgbs[i].start = arg[1];
2468 cgbs[i].size = arg[2];
2469 cgbs[i].desc = VG_(strdup)((Char *)arg[3]);
2470 cgbs[i].where = VG_(record_ExeContext) ( tid );
sewardjedc75ab2005-03-15 23:30:32 +00002471
sewardj8cf88b72005-07-08 01:29:33 +00002472 *ret = i;
2473 } else
2474 *ret = -1;
2475 break;
sewardjedc75ab2005-03-15 23:30:32 +00002476
nethercote8b76fe52004-11-08 19:20:09 +00002477 case VG_USERREQ__DISCARD: /* discard */
njn695c16e2005-03-27 03:40:28 +00002478 if (cgbs == NULL
2479 || arg[2] >= cgb_used ||
sewardj8cf88b72005-07-08 01:29:33 +00002480 (cgbs[arg[2]].start == 0 && cgbs[arg[2]].size == 0)) {
sewardjedc75ab2005-03-15 23:30:32 +00002481 *ret = 1;
sewardj8cf88b72005-07-08 01:29:33 +00002482 } else {
2483 tl_assert(arg[2] >= 0 && arg[2] < cgb_used);
2484 cgbs[arg[2]].start = cgbs[arg[2]].size = 0;
2485 VG_(free)(cgbs[arg[2]].desc);
2486 cgb_discards++;
2487 *ret = 0;
2488 }
2489 break;
nethercote8b76fe52004-11-08 19:20:09 +00002490
sewardj45d94cc2005-04-20 14:44:11 +00002491//zz case VG_USERREQ__GET_VBITS:
2492//zz /* Returns: 1 == OK, 2 == alignment error, 3 == addressing
2493//zz error. */
2494//zz /* VG_(printf)("get_vbits %p %p %d\n", arg[1], arg[2], arg[3] ); */
2495//zz *ret = mc_get_or_set_vbits_for_client
2496//zz ( tid, arg[1], arg[2], arg[3], False /* get them */ );
2497//zz break;
2498//zz
2499//zz case VG_USERREQ__SET_VBITS:
2500//zz /* Returns: 1 == OK, 2 == alignment error, 3 == addressing
2501//zz error. */
2502//zz /* VG_(printf)("set_vbits %p %p %d\n", arg[1], arg[2], arg[3] ); */
2503//zz *ret = mc_get_or_set_vbits_for_client
2504//zz ( tid, arg[1], arg[2], arg[3], True /* set them */ );
2505//zz break;
nethercote8b76fe52004-11-08 19:20:09 +00002506
2507 default:
2508 if (MAC_(handle_common_client_requests)(tid, arg, ret )) {
2509 return True;
2510 } else {
2511 VG_(message)(Vg_UserMsg,
2512 "Warning: unknown memcheck client request code %llx",
2513 (ULong)arg[0]);
2514 return False;
2515 }
2516 }
2517 return True;
2518}
njn25e49d8e72002-09-23 09:36:25 +00002519
2520/*------------------------------------------------------------*/
njn51d827b2005-05-09 01:02:08 +00002521/*--- Setup and finalisation ---*/
njn25e49d8e72002-09-23 09:36:25 +00002522/*------------------------------------------------------------*/
2523
njn51d827b2005-05-09 01:02:08 +00002524static void mc_post_clo_init ( void )
njn5c004e42002-11-18 11:04:50 +00002525{
sewardj71bc3cb2005-05-19 00:25:45 +00002526 /* If we've been asked to emit XML, mash around various other
2527 options so as to constrain the output somewhat. */
2528 if (VG_(clo_xml)) {
2529 /* Extract as much info as possible from the leak checker. */
sewardj09890d82005-05-20 02:45:15 +00002530 /* MAC_(clo_show_reachable) = True; */
sewardj71bc3cb2005-05-19 00:25:45 +00002531 MAC_(clo_leak_check) = LC_Full;
2532 }
njn5c004e42002-11-18 11:04:50 +00002533}
2534
njn51d827b2005-05-09 01:02:08 +00002535static void mc_fini ( Int exitcode )
njn5c004e42002-11-18 11:04:50 +00002536{
sewardj23eb2fd2005-04-22 16:29:19 +00002537 Int i, n_accessible_dist;
2538 SecMap* sm;
2539
sewardjae986ca2005-10-12 12:53:20 +00002540 MAC_(common_fini)( mc_detect_memory_leaks );
2541
sewardj45d94cc2005-04-20 14:44:11 +00002542 if (VG_(clo_verbosity) > 1) {
2543 VG_(message)(Vg_DebugMsg,
sewardj23eb2fd2005-04-22 16:29:19 +00002544 " memcheck: sanity checks: %d cheap, %d expensive",
2545 n_sanity_cheap, n_sanity_expensive );
sewardj45d94cc2005-04-20 14:44:11 +00002546 VG_(message)(Vg_DebugMsg,
sewardj23eb2fd2005-04-22 16:29:19 +00002547 " memcheck: auxmaps: %d auxmap entries (%dk, %dM) in use",
2548 auxmap_used,
2549 auxmap_used * 64,
2550 auxmap_used / 16 );
2551 VG_(message)(Vg_DebugMsg,
2552 " memcheck: auxmaps: %lld searches, %lld comparisons",
sewardj45d94cc2005-04-20 14:44:11 +00002553 n_auxmap_searches, n_auxmap_cmps );
sewardj23eb2fd2005-04-22 16:29:19 +00002554 VG_(message)(Vg_DebugMsg,
2555 " memcheck: secondaries: %d issued (%dk, %dM)",
2556 n_secmaps_issued,
2557 n_secmaps_issued * 64,
2558 n_secmaps_issued / 16 );
2559
2560 n_accessible_dist = 0;
2561 for (i = 0; i < N_PRIMARY_MAP; i++) {
2562 sm = primary_map[i];
2563 if (is_distinguished_sm(sm)
2564 && sm != &sm_distinguished[SM_DIST_NOACCESS])
2565 n_accessible_dist ++;
2566 }
2567 for (i = 0; i < auxmap_used; i++) {
2568 sm = auxmap[i].sm;
2569 if (is_distinguished_sm(sm)
2570 && sm != &sm_distinguished[SM_DIST_NOACCESS])
2571 n_accessible_dist ++;
2572 }
2573
2574 VG_(message)(Vg_DebugMsg,
2575 " memcheck: secondaries: %d accessible and distinguished (%dk, %dM)",
2576 n_accessible_dist,
2577 n_accessible_dist * 64,
2578 n_accessible_dist / 16 );
2579
sewardj45d94cc2005-04-20 14:44:11 +00002580 }
2581
njn5c004e42002-11-18 11:04:50 +00002582 if (0) {
2583 VG_(message)(Vg_DebugMsg,
2584 "------ Valgrind's client block stats follow ---------------" );
nethercote8b76fe52004-11-08 19:20:09 +00002585 show_client_block_stats();
njn5c004e42002-11-18 11:04:50 +00002586 }
njn25e49d8e72002-09-23 09:36:25 +00002587}
2588
njn51d827b2005-05-09 01:02:08 +00002589static void mc_pre_clo_init(void)
2590{
2591 VG_(details_name) ("Memcheck");
2592 VG_(details_version) (NULL);
2593 VG_(details_description) ("a memory error detector");
2594 VG_(details_copyright_author)(
2595 "Copyright (C) 2002-2005, and GNU GPL'd, by Julian Seward et al.");
2596 VG_(details_bug_reports_to) (VG_BUGS_TO);
2597 VG_(details_avg_translation_sizeB) ( 370 );
2598
2599 VG_(basic_tool_funcs) (mc_post_clo_init,
2600 MC_(instrument),
2601 mc_fini);
2602
2603 VG_(needs_core_errors) ();
2604 VG_(needs_tool_errors) (MAC_(eq_Error),
2605 mc_pp_Error,
2606 MAC_(update_extra),
2607 mc_recognised_suppression,
2608 MAC_(read_extra_suppression_info),
2609 MAC_(error_matches_suppression),
2610 MAC_(get_error_name),
2611 MAC_(print_extra_suppression_info));
2612 VG_(needs_libc_freeres) ();
2613 VG_(needs_command_line_options)(mc_process_cmd_line_option,
2614 mc_print_usage,
2615 mc_print_debug_usage);
2616 VG_(needs_client_requests) (mc_handle_client_request);
2617 VG_(needs_sanity_checks) (mc_cheap_sanity_check,
2618 mc_expensive_sanity_check);
njn51d827b2005-05-09 01:02:08 +00002619
njnfc51f8d2005-06-21 03:20:17 +00002620 VG_(needs_malloc_replacement) (MAC_(malloc),
njn51d827b2005-05-09 01:02:08 +00002621 MAC_(__builtin_new),
2622 MAC_(__builtin_vec_new),
2623 MAC_(memalign),
2624 MAC_(calloc),
2625 MAC_(free),
2626 MAC_(__builtin_delete),
2627 MAC_(__builtin_vec_delete),
2628 MAC_(realloc),
2629 MAC_MALLOC_REDZONE_SZB );
2630
2631 MAC_( new_mem_heap) = & mc_new_mem_heap;
2632 MAC_( ban_mem_heap) = & mc_make_noaccess;
2633 MAC_(copy_mem_heap) = & mc_copy_address_range_state;
2634 MAC_( die_mem_heap) = & mc_make_noaccess;
2635 MAC_(check_noaccess) = & mc_check_noaccess;
2636
2637 VG_(track_new_mem_startup) ( & mc_new_mem_startup );
2638 VG_(track_new_mem_stack_signal)( & mc_make_writable );
2639 VG_(track_new_mem_brk) ( & mc_make_writable );
2640 VG_(track_new_mem_mmap) ( & mc_new_mem_mmap );
2641
2642 VG_(track_copy_mem_remap) ( & mc_copy_address_range_state );
njn81623712005-10-07 04:48:37 +00002643
2644 // Nb: we don't do anything with mprotect. This means that V bits are
2645 // preserved if a program, for example, marks some memory as inaccessible
2646 // and then later marks it as accessible again.
2647 //
2648 // If an access violation occurs (eg. writing to read-only memory) we let
2649 // it fault and print an informative termination message. This doesn't
2650 // happen if the program catches the signal, though, which is bad. If we
2651 // had two A bits (for readability and writability) that were completely
2652 // distinct from V bits, then we could handle all this properly.
2653 VG_(track_change_mem_mprotect) ( NULL );
njn51d827b2005-05-09 01:02:08 +00002654
2655 VG_(track_die_mem_stack_signal)( & mc_make_noaccess );
2656 VG_(track_die_mem_brk) ( & mc_make_noaccess );
2657 VG_(track_die_mem_munmap) ( & mc_make_noaccess );
2658
2659 VG_(track_new_mem_stack_4) ( & MAC_(new_mem_stack_4) );
2660 VG_(track_new_mem_stack_8) ( & MAC_(new_mem_stack_8) );
2661 VG_(track_new_mem_stack_12) ( & MAC_(new_mem_stack_12) );
2662 VG_(track_new_mem_stack_16) ( & MAC_(new_mem_stack_16) );
2663 VG_(track_new_mem_stack_32) ( & MAC_(new_mem_stack_32) );
2664 VG_(track_new_mem_stack) ( & MAC_(new_mem_stack) );
2665
2666 VG_(track_die_mem_stack_4) ( & MAC_(die_mem_stack_4) );
2667 VG_(track_die_mem_stack_8) ( & MAC_(die_mem_stack_8) );
2668 VG_(track_die_mem_stack_12) ( & MAC_(die_mem_stack_12) );
2669 VG_(track_die_mem_stack_16) ( & MAC_(die_mem_stack_16) );
2670 VG_(track_die_mem_stack_32) ( & MAC_(die_mem_stack_32) );
2671 VG_(track_die_mem_stack) ( & MAC_(die_mem_stack) );
2672
2673 VG_(track_ban_mem_stack) ( & mc_make_noaccess );
2674
2675 VG_(track_pre_mem_read) ( & mc_check_is_readable );
2676 VG_(track_pre_mem_read_asciiz) ( & mc_check_is_readable_asciiz );
2677 VG_(track_pre_mem_write) ( & mc_check_is_writable );
2678 VG_(track_post_mem_write) ( & mc_post_mem_write );
2679
2680 VG_(track_pre_reg_read) ( & mc_pre_reg_read );
2681
2682 VG_(track_post_reg_write) ( & mc_post_reg_write );
2683 VG_(track_post_reg_write_clientcall_return)( & mc_post_reg_write_clientcall );
2684
2685 VG_(register_profile_event) ( VgpSetMem, "set-mem-perms" );
2686 VG_(register_profile_event) ( VgpCheckMem, "check-mem-perms" );
2687 VG_(register_profile_event) ( VgpESPAdj, "adjust-ESP" );
2688
2689 /* Additional block description for VG_(describe_addr)() */
2690 MAC_(describe_addr_supp) = client_perm_maybe_describe;
2691
2692 init_shadow_memory();
2693 MAC_(common_pre_clo_init)();
2694
2695 tl_assert( mc_expensive_sanity_check() );
2696}
2697
sewardj45f4e7c2005-09-27 19:20:21 +00002698VG_DETERMINE_INTERFACE_VERSION(mc_pre_clo_init)
fitzhardinge98abfc72003-12-16 02:05:15 +00002699
njn25e49d8e72002-09-23 09:36:25 +00002700/*--------------------------------------------------------------------*/
njn25cac76cb2002-09-23 11:21:57 +00002701/*--- end mc_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00002702/*--------------------------------------------------------------------*/