blob: 1f6328b13af00057b4461f43aac11a825b634628 [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
sewardj03f8d3f2012-08-05 15:46:46 +000012 Copyright (C) 2000-2012 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
njnc7561b92005-06-19 01:24:32 +000033#include "pub_tool_basics.h"
njn4802b382005-06-11 04:58:29 +000034#include "pub_tool_aspacemgr.h"
sewardj3b290482011-05-06 21:02:55 +000035#include "pub_tool_gdbserver.h"
philippe6643e962012-01-17 21:16:30 +000036#include "pub_tool_poolalloc.h"
njn1d0825f2006-03-27 11:37:07 +000037#include "pub_tool_hashtable.h" // For mc_include.h
njn97405b22005-06-02 03:39:33 +000038#include "pub_tool_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000039#include "pub_tool_libcassert.h"
njn36a20fa2005-06-03 03:08:39 +000040#include "pub_tool_libcprint.h"
njnf536bbb2005-06-13 04:21:38 +000041#include "pub_tool_machine.h"
njnc7561b92005-06-19 01:24:32 +000042#include "pub_tool_mallocfree.h"
43#include "pub_tool_options.h"
njn1d0825f2006-03-27 11:37:07 +000044#include "pub_tool_oset.h"
njnc7561b92005-06-19 01:24:32 +000045#include "pub_tool_replacemalloc.h"
46#include "pub_tool_tooliface.h"
47#include "pub_tool_threadstate.h"
48
49#include "mc_include.h"
50#include "memcheck.h" /* for client requests */
njn25e49d8e72002-09-23 09:36:25 +000051
sewardjc1a2cda2005-04-21 17:34:00 +000052
njn1d0825f2006-03-27 11:37:07 +000053/* Set to 1 to do a little more sanity checking */
sewardj23eb2fd2005-04-22 16:29:19 +000054#define VG_DEBUG_MEMORY 0
sewardjc1a2cda2005-04-21 17:34:00 +000055
njn25e49d8e72002-09-23 09:36:25 +000056#define DEBUG(fmt, args...) //VG_(printf)(fmt, ## args)
57
sewardj7cf4e6b2008-05-01 20:24:26 +000058static void ocache_sarp_Set_Origins ( Addr, UWord, UInt ); /* fwds */
59static void ocache_sarp_Clear_Origins ( Addr, UWord ); /* fwds */
60
njn25e49d8e72002-09-23 09:36:25 +000061
njn25e49d8e72002-09-23 09:36:25 +000062/*------------------------------------------------------------*/
njn1d0825f2006-03-27 11:37:07 +000063/*--- Fast-case knobs ---*/
64/*------------------------------------------------------------*/
65
66// Comment these out to disable the fast cases (don't just set them to zero).
67
68#define PERF_FAST_LOADV 1
69#define PERF_FAST_STOREV 1
70
71#define PERF_FAST_SARP 1
72
73#define PERF_FAST_STACK 1
74#define PERF_FAST_STACK2 1
75
sewardj7cf4e6b2008-05-01 20:24:26 +000076/* Change this to 1 to enable assertions on origin tracking cache fast
77 paths */
78#define OC_ENABLE_ASSERTIONS 0
79
80
njn1d0825f2006-03-27 11:37:07 +000081/*------------------------------------------------------------*/
sewardj77139802008-05-05 09:48:56 +000082/*--- Comments on the origin tracking implementation ---*/
83/*------------------------------------------------------------*/
84
85/* See detailed comment entitled
86 AN OVERVIEW OF THE ORIGIN TRACKING IMPLEMENTATION
87 which is contained further on in this file. */
88
89
90/*------------------------------------------------------------*/
njn1d0825f2006-03-27 11:37:07 +000091/*--- V bits and A bits ---*/
92/*------------------------------------------------------------*/
93
94/* Conceptually, every byte value has 8 V bits, which track whether Memcheck
95 thinks the corresponding value bit is defined. And every memory byte
96 has an A bit, which tracks whether Memcheck thinks the program can access
njnf76d27a2009-05-28 01:53:07 +000097 it safely (ie. it's mapped, and has at least one of the RWX permission bits
98 set). So every N-bit register is shadowed with N V bits, and every memory
99 byte is shadowed with 8 V bits and one A bit.
njn1d0825f2006-03-27 11:37:07 +0000100
101 In the implementation, we use two forms of compression (compressed V bits
102 and distinguished secondary maps) to avoid the 9-bit-per-byte overhead
103 for memory.
104
105 Memcheck also tracks extra information about each heap block that is
106 allocated, for detecting memory leaks and other purposes.
107*/
108
109/*------------------------------------------------------------*/
sewardj45d94cc2005-04-20 14:44:11 +0000110/*--- Basic A/V bitmap representation. ---*/
njn25e49d8e72002-09-23 09:36:25 +0000111/*------------------------------------------------------------*/
112
njn1d0825f2006-03-27 11:37:07 +0000113/* All reads and writes are checked against a memory map (a.k.a. shadow
114 memory), which records the state of all memory in the process.
115
116 On 32-bit machines the memory map is organised as follows.
117 The top 16 bits of an address are used to index into a top-level
118 map table, containing 65536 entries. Each entry is a pointer to a
119 second-level map, which records the accesibililty and validity
120 permissions for the 65536 bytes indexed by the lower 16 bits of the
121 address. Each byte is represented by two bits (details are below). So
122 each second-level map contains 16384 bytes. This two-level arrangement
123 conveniently divides the 4G address space into 64k lumps, each size 64k
124 bytes.
125
126 All entries in the primary (top-level) map must point to a valid
127 secondary (second-level) map. Since many of the 64kB chunks will
njndbf7ca72006-03-31 11:57:59 +0000128 have the same status for every bit -- ie. noaccess (for unused
129 address space) or entirely addressable and defined (for code segments) --
130 there are three distinguished secondary maps, which indicate 'noaccess',
131 'undefined' and 'defined'. For these uniform 64kB chunks, the primary
132 map entry points to the relevant distinguished map. In practice,
133 typically more than half of the addressable memory is represented with
134 the 'undefined' or 'defined' distinguished secondary map, so it gives a
135 good saving. It also lets us set the V+A bits of large address regions
136 quickly in set_address_range_perms().
njn1d0825f2006-03-27 11:37:07 +0000137
138 On 64-bit machines it's more complicated. If we followed the same basic
139 scheme we'd have a four-level table which would require too many memory
140 accesses. So instead the top-level map table has 2^19 entries (indexed
141 using bits 16..34 of the address); this covers the bottom 32GB. Any
142 accesses above 32GB are handled with a slow, sparse auxiliary table.
143 Valgrind's address space manager tries very hard to keep things below
144 this 32GB barrier so that performance doesn't suffer too much.
145
146 Note that this file has a lot of different functions for reading and
147 writing shadow memory. Only a couple are strictly necessary (eg.
148 get_vabits2 and set_vabits2), most are just specialised for specific
149 common cases to improve performance.
150
151 Aside: the V+A bits are less precise than they could be -- we have no way
152 of marking memory as read-only. It would be great if we could add an
153 extra state VA_BITSn_READONLY. But then we'd have 5 different states,
154 which requires 2.3 bits to hold, and there's no way to do that elegantly
155 -- we'd have to double up to 4 bits of metadata per byte, which doesn't
156 seem worth it.
157*/
sewardjc859fbf2005-04-22 21:10:28 +0000158
sewardj45d94cc2005-04-20 14:44:11 +0000159/* --------------- Basic configuration --------------- */
sewardj95448072004-11-22 20:19:51 +0000160
sewardj23eb2fd2005-04-22 16:29:19 +0000161/* Only change this. N_PRIMARY_MAP *must* be a power of 2. */
sewardj21f7ff42005-04-28 10:32:02 +0000162
sewardje4ccc012005-05-02 12:53:38 +0000163#if VG_WORDSIZE == 4
sewardj21f7ff42005-04-28 10:32:02 +0000164
165/* cover the entire address space */
166# define N_PRIMARY_BITS 16
167
168#else
169
sewardj6805a4a2013-01-29 21:14:46 +0000170/* Just handle the first 64G fast and the rest via auxiliary
sewardj7244e712008-05-02 12:35:48 +0000171 primaries. If you change this, Memcheck will assert at startup.
172 See the definition of UNALIGNED_OR_HIGH for extensive comments. */
sewardj6805a4a2013-01-29 21:14:46 +0000173# define N_PRIMARY_BITS 20
sewardj21f7ff42005-04-28 10:32:02 +0000174
175#endif
176
sewardj45d94cc2005-04-20 14:44:11 +0000177
sewardjc1a2cda2005-04-21 17:34:00 +0000178/* Do not change this. */
sewardje4ccc012005-05-02 12:53:38 +0000179#define N_PRIMARY_MAP ( ((UWord)1) << N_PRIMARY_BITS)
sewardjc1a2cda2005-04-21 17:34:00 +0000180
181/* Do not change this. */
sewardj23eb2fd2005-04-22 16:29:19 +0000182#define MAX_PRIMARY_ADDRESS (Addr)((((Addr)65536) * N_PRIMARY_MAP)-1)
183
184
sewardj45d94cc2005-04-20 14:44:11 +0000185/* --------------- Secondary maps --------------- */
njn25e49d8e72002-09-23 09:36:25 +0000186
njn1d0825f2006-03-27 11:37:07 +0000187// Each byte of memory conceptually has an A bit, which indicates its
188// addressability, and 8 V bits, which indicates its definedness.
189//
190// But because very few bytes are partially defined, we can use a nice
191// compression scheme to reduce the size of shadow memory. Each byte of
192// memory has 2 bits which indicates its state (ie. V+A bits):
193//
njndbf7ca72006-03-31 11:57:59 +0000194// 00: noaccess (unaddressable but treated as fully defined)
195// 01: undefined (addressable and fully undefined)
196// 10: defined (addressable and fully defined)
197// 11: partdefined (addressable and partially defined)
njn1d0825f2006-03-27 11:37:07 +0000198//
njndbf7ca72006-03-31 11:57:59 +0000199// In the "partdefined" case, we use a secondary table to store the V bits.
200// Each entry in the secondary-V-bits table maps a byte address to its 8 V
201// bits.
njn1d0825f2006-03-27 11:37:07 +0000202//
203// We store the compressed V+A bits in 8-bit chunks, ie. the V+A bits for
204// four bytes (32 bits) of memory are in each chunk. Hence the name
205// "vabits8". This lets us get the V+A bits for four bytes at a time
206// easily (without having to do any shifting and/or masking), and that is a
207// very common operation. (Note that although each vabits8 chunk
208// is 8 bits in size, it represents 32 bits of memory.)
209//
210// The representation is "inverse" little-endian... each 4 bytes of
211// memory is represented by a 1 byte value, where:
212//
213// - the status of byte (a+0) is held in bits [1..0]
214// - the status of byte (a+1) is held in bits [3..2]
215// - the status of byte (a+2) is held in bits [5..4]
216// - the status of byte (a+3) is held in bits [7..6]
217//
218// It's "inverse" because endianness normally describes a mapping from
219// value bits to memory addresses; in this case the mapping is inverted.
220// Ie. instead of particular value bits being held in certain addresses, in
221// this case certain addresses are represented by particular value bits.
222// See insert_vabits2_into_vabits8() for an example.
223//
224// But note that we don't compress the V bits stored in registers; they
225// need to be explicit to made the shadow operations possible. Therefore
226// when moving values between registers and memory we need to convert
227// between the expanded in-register format and the compressed in-memory
228// format. This isn't so difficult, it just requires careful attention in a
229// few places.
230
231// These represent eight bits of memory.
232#define VA_BITS2_NOACCESS 0x0 // 00b
njndbf7ca72006-03-31 11:57:59 +0000233#define VA_BITS2_UNDEFINED 0x1 // 01b
234#define VA_BITS2_DEFINED 0x2 // 10b
235#define VA_BITS2_PARTDEFINED 0x3 // 11b
njn1d0825f2006-03-27 11:37:07 +0000236
237// These represent 16 bits of memory.
238#define VA_BITS4_NOACCESS 0x0 // 00_00b
njndbf7ca72006-03-31 11:57:59 +0000239#define VA_BITS4_UNDEFINED 0x5 // 01_01b
240#define VA_BITS4_DEFINED 0xa // 10_10b
njn1d0825f2006-03-27 11:37:07 +0000241
242// These represent 32 bits of memory.
243#define VA_BITS8_NOACCESS 0x00 // 00_00_00_00b
njndbf7ca72006-03-31 11:57:59 +0000244#define VA_BITS8_UNDEFINED 0x55 // 01_01_01_01b
245#define VA_BITS8_DEFINED 0xaa // 10_10_10_10b
njn1d0825f2006-03-27 11:37:07 +0000246
247// These represent 64 bits of memory.
248#define VA_BITS16_NOACCESS 0x0000 // 00_00_00_00b x 2
njndbf7ca72006-03-31 11:57:59 +0000249#define VA_BITS16_UNDEFINED 0x5555 // 01_01_01_01b x 2
250#define VA_BITS16_DEFINED 0xaaaa // 10_10_10_10b x 2
njn1d0825f2006-03-27 11:37:07 +0000251
252
253#define SM_CHUNKS 16384
254#define SM_OFF(aaa) (((aaa) & 0xffff) >> 2)
255#define SM_OFF_16(aaa) (((aaa) & 0xffff) >> 3)
256
257// Paranoia: it's critical for performance that the requested inlining
258// occurs. So try extra hard.
259#define INLINE inline __attribute__((always_inline))
260
261static INLINE Addr start_of_this_sm ( Addr a ) {
262 return (a & (~SM_MASK));
263}
264static INLINE Bool is_start_of_sm ( Addr a ) {
265 return (start_of_this_sm(a) == a);
266}
267
njn25e49d8e72002-09-23 09:36:25 +0000268typedef
269 struct {
njn1d0825f2006-03-27 11:37:07 +0000270 UChar vabits8[SM_CHUNKS];
njn25e49d8e72002-09-23 09:36:25 +0000271 }
272 SecMap;
273
njn1d0825f2006-03-27 11:37:07 +0000274// 3 distinguished secondary maps, one for no-access, one for
275// accessible but undefined, and one for accessible and defined.
276// Distinguished secondaries may never be modified.
277#define SM_DIST_NOACCESS 0
njndbf7ca72006-03-31 11:57:59 +0000278#define SM_DIST_UNDEFINED 1
279#define SM_DIST_DEFINED 2
njnb8dca862005-03-14 02:42:44 +0000280
sewardj45d94cc2005-04-20 14:44:11 +0000281static SecMap sm_distinguished[3];
njnb8dca862005-03-14 02:42:44 +0000282
njn1d0825f2006-03-27 11:37:07 +0000283static INLINE Bool is_distinguished_sm ( SecMap* sm ) {
sewardj45d94cc2005-04-20 14:44:11 +0000284 return sm >= &sm_distinguished[0] && sm <= &sm_distinguished[2];
285}
njnb8dca862005-03-14 02:42:44 +0000286
njn1d0825f2006-03-27 11:37:07 +0000287// Forward declaration
288static void update_SM_counts(SecMap* oldSM, SecMap* newSM);
289
sewardj45d94cc2005-04-20 14:44:11 +0000290/* dist_sm points to one of our three distinguished secondaries. Make
291 a copy of it so that we can write to it.
292*/
293static SecMap* copy_for_writing ( SecMap* dist_sm )
294{
295 SecMap* new_sm;
296 tl_assert(dist_sm == &sm_distinguished[0]
njn1d0825f2006-03-27 11:37:07 +0000297 || dist_sm == &sm_distinguished[1]
298 || dist_sm == &sm_distinguished[2]);
njnb8dca862005-03-14 02:42:44 +0000299
sewardj45f4e7c2005-09-27 19:20:21 +0000300 new_sm = VG_(am_shadow_alloc)(sizeof(SecMap));
301 if (new_sm == NULL)
302 VG_(out_of_memory_NORETURN)( "memcheck:allocate new SecMap",
303 sizeof(SecMap) );
sewardj45d94cc2005-04-20 14:44:11 +0000304 VG_(memcpy)(new_sm, dist_sm, sizeof(SecMap));
njn1d0825f2006-03-27 11:37:07 +0000305 update_SM_counts(dist_sm, new_sm);
sewardj45d94cc2005-04-20 14:44:11 +0000306 return new_sm;
307}
njnb8dca862005-03-14 02:42:44 +0000308
njn1d0825f2006-03-27 11:37:07 +0000309/* --------------- Stats --------------- */
310
njndbf7ca72006-03-31 11:57:59 +0000311static Int n_issued_SMs = 0;
312static Int n_deissued_SMs = 0;
313static Int n_noaccess_SMs = N_PRIMARY_MAP; // start with many noaccess DSMs
314static Int n_undefined_SMs = 0;
315static Int n_defined_SMs = 0;
316static Int n_non_DSM_SMs = 0;
317static Int max_noaccess_SMs = 0;
318static Int max_undefined_SMs = 0;
319static Int max_defined_SMs = 0;
320static Int max_non_DSM_SMs = 0;
njn1d0825f2006-03-27 11:37:07 +0000321
sewardj05a46732006-10-17 01:28:10 +0000322/* # searches initiated in auxmap_L1, and # base cmps required */
323static ULong n_auxmap_L1_searches = 0;
324static ULong n_auxmap_L1_cmps = 0;
325/* # of searches that missed in auxmap_L1 and therefore had to
326 be handed to auxmap_L2. And the number of nodes inserted. */
327static ULong n_auxmap_L2_searches = 0;
328static ULong n_auxmap_L2_nodes = 0;
329
njn1d0825f2006-03-27 11:37:07 +0000330static Int n_sanity_cheap = 0;
331static Int n_sanity_expensive = 0;
332
333static Int n_secVBit_nodes = 0;
334static Int max_secVBit_nodes = 0;
335
336static void update_SM_counts(SecMap* oldSM, SecMap* newSM)
337{
njndbf7ca72006-03-31 11:57:59 +0000338 if (oldSM == &sm_distinguished[SM_DIST_NOACCESS ]) n_noaccess_SMs --;
339 else if (oldSM == &sm_distinguished[SM_DIST_UNDEFINED]) n_undefined_SMs--;
340 else if (oldSM == &sm_distinguished[SM_DIST_DEFINED ]) n_defined_SMs --;
341 else { n_non_DSM_SMs --;
342 n_deissued_SMs ++; }
njn1d0825f2006-03-27 11:37:07 +0000343
njndbf7ca72006-03-31 11:57:59 +0000344 if (newSM == &sm_distinguished[SM_DIST_NOACCESS ]) n_noaccess_SMs ++;
345 else if (newSM == &sm_distinguished[SM_DIST_UNDEFINED]) n_undefined_SMs++;
346 else if (newSM == &sm_distinguished[SM_DIST_DEFINED ]) n_defined_SMs ++;
347 else { n_non_DSM_SMs ++;
348 n_issued_SMs ++; }
njn1d0825f2006-03-27 11:37:07 +0000349
njndbf7ca72006-03-31 11:57:59 +0000350 if (n_noaccess_SMs > max_noaccess_SMs ) max_noaccess_SMs = n_noaccess_SMs;
351 if (n_undefined_SMs > max_undefined_SMs) max_undefined_SMs = n_undefined_SMs;
352 if (n_defined_SMs > max_defined_SMs ) max_defined_SMs = n_defined_SMs;
353 if (n_non_DSM_SMs > max_non_DSM_SMs ) max_non_DSM_SMs = n_non_DSM_SMs;
njn1d0825f2006-03-27 11:37:07 +0000354}
sewardj45d94cc2005-04-20 14:44:11 +0000355
356/* --------------- Primary maps --------------- */
357
358/* The main primary map. This covers some initial part of the address
sewardj23eb2fd2005-04-22 16:29:19 +0000359 space, addresses 0 .. (N_PRIMARY_MAP << 16)-1. The rest of it is
sewardj45d94cc2005-04-20 14:44:11 +0000360 handled using the auxiliary primary map.
361*/
sewardj23eb2fd2005-04-22 16:29:19 +0000362static SecMap* primary_map[N_PRIMARY_MAP];
sewardj45d94cc2005-04-20 14:44:11 +0000363
364
365/* An entry in the auxiliary primary map. base must be a 64k-aligned
366 value, and sm points at the relevant secondary map. As with the
367 main primary map, the secondary may be either a real secondary, or
sewardj05a46732006-10-17 01:28:10 +0000368 one of the three distinguished secondaries. DO NOT CHANGE THIS
369 LAYOUT: the first word has to be the key for OSet fast lookups.
sewardj45d94cc2005-04-20 14:44:11 +0000370*/
371typedef
372 struct {
sewardj23eb2fd2005-04-22 16:29:19 +0000373 Addr base;
sewardj45d94cc2005-04-20 14:44:11 +0000374 SecMap* sm;
375 }
376 AuxMapEnt;
377
sewardj05a46732006-10-17 01:28:10 +0000378/* Tunable parameter: How big is the L1 queue? */
379#define N_AUXMAP_L1 24
sewardj45d94cc2005-04-20 14:44:11 +0000380
sewardj05a46732006-10-17 01:28:10 +0000381/* Tunable parameter: How far along the L1 queue to insert
382 entries resulting from L2 lookups? */
383#define AUXMAP_L1_INSERT_IX 12
sewardj45d94cc2005-04-20 14:44:11 +0000384
sewardj05a46732006-10-17 01:28:10 +0000385static struct {
386 Addr base;
387 AuxMapEnt* ent; // pointer to the matching auxmap_L2 node
388 }
389 auxmap_L1[N_AUXMAP_L1];
390
391static OSet* auxmap_L2 = NULL;
392
393static void init_auxmap_L1_L2 ( void )
sewardj45d94cc2005-04-20 14:44:11 +0000394{
sewardj05a46732006-10-17 01:28:10 +0000395 Int i;
396 for (i = 0; i < N_AUXMAP_L1; i++) {
397 auxmap_L1[i].base = 0;
398 auxmap_L1[i].ent = NULL;
sewardj45d94cc2005-04-20 14:44:11 +0000399 }
400
sewardj05a46732006-10-17 01:28:10 +0000401 tl_assert(0 == offsetof(AuxMapEnt,base));
402 tl_assert(sizeof(Addr) == sizeof(void*));
njne2a9ad32007-09-17 05:30:48 +0000403 auxmap_L2 = VG_(OSetGen_Create)( /*keyOff*/ offsetof(AuxMapEnt,base),
404 /*fastCmp*/ NULL,
sewardj9c606bd2008-09-18 18:12:50 +0000405 VG_(malloc), "mc.iaLL.1", VG_(free) );
sewardj05fe85e2005-04-27 22:46:36 +0000406}
407
sewardj05a46732006-10-17 01:28:10 +0000408/* Check representation invariants; if OK return NULL; else a
409 descriptive bit of text. Also return the number of
410 non-distinguished secondary maps referred to from the auxiliary
411 primary maps. */
sewardj05fe85e2005-04-27 22:46:36 +0000412
florian19f91bb2012-11-10 22:29:54 +0000413static const HChar* check_auxmap_L1_L2_sanity ( Word* n_secmaps_found )
sewardj05fe85e2005-04-27 22:46:36 +0000414{
sewardj05a46732006-10-17 01:28:10 +0000415 Word i, j;
416 /* On a 32-bit platform, the L2 and L1 tables should
417 both remain empty forever.
sewardj05fe85e2005-04-27 22:46:36 +0000418
sewardj05a46732006-10-17 01:28:10 +0000419 On a 64-bit platform:
420 In the L2 table:
421 all .base & 0xFFFF == 0
422 all .base > MAX_PRIMARY_ADDRESS
423 In the L1 table:
424 all .base & 0xFFFF == 0
425 all (.base > MAX_PRIMARY_ADDRESS
426 .base & 0xFFFF == 0
427 and .ent points to an AuxMapEnt with the same .base)
428 or
429 (.base == 0 and .ent == NULL)
430 */
431 *n_secmaps_found = 0;
432 if (sizeof(void*) == 4) {
433 /* 32-bit platform */
njne2a9ad32007-09-17 05:30:48 +0000434 if (VG_(OSetGen_Size)(auxmap_L2) != 0)
sewardj05a46732006-10-17 01:28:10 +0000435 return "32-bit: auxmap_L2 is non-empty";
436 for (i = 0; i < N_AUXMAP_L1; i++)
437 if (auxmap_L1[i].base != 0 || auxmap_L1[i].ent != NULL)
438 return "32-bit: auxmap_L1 is non-empty";
439 } else {
440 /* 64-bit platform */
441 UWord elems_seen = 0;
442 AuxMapEnt *elem, *res;
443 AuxMapEnt key;
444 /* L2 table */
njne2a9ad32007-09-17 05:30:48 +0000445 VG_(OSetGen_ResetIter)(auxmap_L2);
446 while ( (elem = VG_(OSetGen_Next)(auxmap_L2)) ) {
sewardj05a46732006-10-17 01:28:10 +0000447 elems_seen++;
448 if (0 != (elem->base & (Addr)0xFFFF))
449 return "64-bit: nonzero .base & 0xFFFF in auxmap_L2";
450 if (elem->base <= MAX_PRIMARY_ADDRESS)
451 return "64-bit: .base <= MAX_PRIMARY_ADDRESS in auxmap_L2";
452 if (elem->sm == NULL)
453 return "64-bit: .sm in _L2 is NULL";
454 if (!is_distinguished_sm(elem->sm))
455 (*n_secmaps_found)++;
456 }
457 if (elems_seen != n_auxmap_L2_nodes)
458 return "64-bit: disagreement on number of elems in _L2";
459 /* Check L1-L2 correspondence */
460 for (i = 0; i < N_AUXMAP_L1; i++) {
461 if (auxmap_L1[i].base == 0 && auxmap_L1[i].ent == NULL)
462 continue;
463 if (0 != (auxmap_L1[i].base & (Addr)0xFFFF))
464 return "64-bit: nonzero .base & 0xFFFF in auxmap_L1";
465 if (auxmap_L1[i].base <= MAX_PRIMARY_ADDRESS)
466 return "64-bit: .base <= MAX_PRIMARY_ADDRESS in auxmap_L1";
467 if (auxmap_L1[i].ent == NULL)
468 return "64-bit: .ent is NULL in auxmap_L1";
469 if (auxmap_L1[i].ent->base != auxmap_L1[i].base)
470 return "64-bit: _L1 and _L2 bases are inconsistent";
471 /* Look it up in auxmap_L2. */
472 key.base = auxmap_L1[i].base;
473 key.sm = 0;
njne2a9ad32007-09-17 05:30:48 +0000474 res = VG_(OSetGen_Lookup)(auxmap_L2, &key);
sewardj05a46732006-10-17 01:28:10 +0000475 if (res == NULL)
476 return "64-bit: _L1 .base not found in _L2";
477 if (res != auxmap_L1[i].ent)
478 return "64-bit: _L1 .ent disagrees with _L2 entry";
479 }
480 /* Check L1 contains no duplicates */
481 for (i = 0; i < N_AUXMAP_L1; i++) {
482 if (auxmap_L1[i].base == 0)
483 continue;
484 for (j = i+1; j < N_AUXMAP_L1; j++) {
485 if (auxmap_L1[j].base == 0)
486 continue;
487 if (auxmap_L1[j].base == auxmap_L1[i].base)
488 return "64-bit: duplicate _L1 .base entries";
489 }
490 }
491 }
492 return NULL; /* ok */
493}
494
495static void insert_into_auxmap_L1_at ( Word rank, AuxMapEnt* ent )
496{
497 Word i;
498 tl_assert(ent);
499 tl_assert(rank >= 0 && rank < N_AUXMAP_L1);
500 for (i = N_AUXMAP_L1-1; i > rank; i--)
501 auxmap_L1[i] = auxmap_L1[i-1];
502 auxmap_L1[rank].base = ent->base;
503 auxmap_L1[rank].ent = ent;
504}
505
506static INLINE AuxMapEnt* maybe_find_in_auxmap ( Addr a )
507{
508 AuxMapEnt key;
509 AuxMapEnt* res;
510 Word i;
511
512 tl_assert(a > MAX_PRIMARY_ADDRESS);
513 a &= ~(Addr)0xFFFF;
514
515 /* First search the front-cache, which is a self-organising
516 list containing the most popular entries. */
517
bart5dd8e6a2008-03-22 08:04:29 +0000518 if (LIKELY(auxmap_L1[0].base == a))
sewardj05a46732006-10-17 01:28:10 +0000519 return auxmap_L1[0].ent;
bart5dd8e6a2008-03-22 08:04:29 +0000520 if (LIKELY(auxmap_L1[1].base == a)) {
sewardj05a46732006-10-17 01:28:10 +0000521 Addr t_base = auxmap_L1[0].base;
522 AuxMapEnt* t_ent = auxmap_L1[0].ent;
523 auxmap_L1[0].base = auxmap_L1[1].base;
524 auxmap_L1[0].ent = auxmap_L1[1].ent;
525 auxmap_L1[1].base = t_base;
526 auxmap_L1[1].ent = t_ent;
527 return auxmap_L1[0].ent;
sewardj45d94cc2005-04-20 14:44:11 +0000528 }
529
sewardj05a46732006-10-17 01:28:10 +0000530 n_auxmap_L1_searches++;
sewardj45d94cc2005-04-20 14:44:11 +0000531
sewardj05a46732006-10-17 01:28:10 +0000532 for (i = 0; i < N_AUXMAP_L1; i++) {
533 if (auxmap_L1[i].base == a) {
534 break;
535 }
536 }
537 tl_assert(i >= 0 && i <= N_AUXMAP_L1);
sewardj45d94cc2005-04-20 14:44:11 +0000538
sewardj05a46732006-10-17 01:28:10 +0000539 n_auxmap_L1_cmps += (ULong)(i+1);
sewardj45d94cc2005-04-20 14:44:11 +0000540
sewardj05a46732006-10-17 01:28:10 +0000541 if (i < N_AUXMAP_L1) {
542 if (i > 0) {
543 Addr t_base = auxmap_L1[i-1].base;
544 AuxMapEnt* t_ent = auxmap_L1[i-1].ent;
545 auxmap_L1[i-1].base = auxmap_L1[i-0].base;
546 auxmap_L1[i-1].ent = auxmap_L1[i-0].ent;
547 auxmap_L1[i-0].base = t_base;
548 auxmap_L1[i-0].ent = t_ent;
549 i--;
550 }
551 return auxmap_L1[i].ent;
552 }
553
554 n_auxmap_L2_searches++;
555
556 /* First see if we already have it. */
557 key.base = a;
558 key.sm = 0;
559
njne2a9ad32007-09-17 05:30:48 +0000560 res = VG_(OSetGen_Lookup)(auxmap_L2, &key);
sewardj05a46732006-10-17 01:28:10 +0000561 if (res)
562 insert_into_auxmap_L1_at( AUXMAP_L1_INSERT_IX, res );
563 return res;
564}
565
566static AuxMapEnt* find_or_alloc_in_auxmap ( Addr a )
567{
568 AuxMapEnt *nyu, *res;
569
570 /* First see if we already have it. */
571 res = maybe_find_in_auxmap( a );
bart5dd8e6a2008-03-22 08:04:29 +0000572 if (LIKELY(res))
sewardj05a46732006-10-17 01:28:10 +0000573 return res;
574
575 /* Ok, there's no entry in the secondary map, so we'll have
576 to allocate one. */
577 a &= ~(Addr)0xFFFF;
578
njne2a9ad32007-09-17 05:30:48 +0000579 nyu = (AuxMapEnt*) VG_(OSetGen_AllocNode)( auxmap_L2, sizeof(AuxMapEnt) );
sewardj05a46732006-10-17 01:28:10 +0000580 tl_assert(nyu);
581 nyu->base = a;
582 nyu->sm = &sm_distinguished[SM_DIST_NOACCESS];
njne2a9ad32007-09-17 05:30:48 +0000583 VG_(OSetGen_Insert)( auxmap_L2, nyu );
sewardj05a46732006-10-17 01:28:10 +0000584 insert_into_auxmap_L1_at( AUXMAP_L1_INSERT_IX, nyu );
585 n_auxmap_L2_nodes++;
586 return nyu;
sewardj45d94cc2005-04-20 14:44:11 +0000587}
588
sewardj45d94cc2005-04-20 14:44:11 +0000589/* --------------- SecMap fundamentals --------------- */
590
njn1d0825f2006-03-27 11:37:07 +0000591// In all these, 'low' means it's definitely in the main primary map,
592// 'high' means it's definitely in the auxiliary table.
593
594static INLINE SecMap** get_secmap_low_ptr ( Addr a )
595{
596 UWord pm_off = a >> 16;
597# if VG_DEBUG_MEMORY >= 1
598 tl_assert(pm_off < N_PRIMARY_MAP);
599# endif
600 return &primary_map[ pm_off ];
601}
602
603static INLINE SecMap** get_secmap_high_ptr ( Addr a )
604{
605 AuxMapEnt* am = find_or_alloc_in_auxmap(a);
606 return &am->sm;
607}
608
609static SecMap** get_secmap_ptr ( Addr a )
610{
611 return ( a <= MAX_PRIMARY_ADDRESS
612 ? get_secmap_low_ptr(a)
613 : get_secmap_high_ptr(a));
614}
615
njna7c7ebd2006-03-28 12:51:02 +0000616static INLINE SecMap* get_secmap_for_reading_low ( Addr a )
njn1d0825f2006-03-27 11:37:07 +0000617{
618 return *get_secmap_low_ptr(a);
619}
620
njna7c7ebd2006-03-28 12:51:02 +0000621static INLINE SecMap* get_secmap_for_reading_high ( Addr a )
njn1d0825f2006-03-27 11:37:07 +0000622{
623 return *get_secmap_high_ptr(a);
624}
625
njna7c7ebd2006-03-28 12:51:02 +0000626static INLINE SecMap* get_secmap_for_writing_low(Addr a)
njn1d0825f2006-03-27 11:37:07 +0000627{
628 SecMap** p = get_secmap_low_ptr(a);
bart5dd8e6a2008-03-22 08:04:29 +0000629 if (UNLIKELY(is_distinguished_sm(*p)))
njn1d0825f2006-03-27 11:37:07 +0000630 *p = copy_for_writing(*p);
631 return *p;
632}
633
njna7c7ebd2006-03-28 12:51:02 +0000634static INLINE SecMap* get_secmap_for_writing_high ( Addr a )
njn1d0825f2006-03-27 11:37:07 +0000635{
636 SecMap** p = get_secmap_high_ptr(a);
bart5dd8e6a2008-03-22 08:04:29 +0000637 if (UNLIKELY(is_distinguished_sm(*p)))
njn1d0825f2006-03-27 11:37:07 +0000638 *p = copy_for_writing(*p);
639 return *p;
640}
641
sewardj45d94cc2005-04-20 14:44:11 +0000642/* Produce the secmap for 'a', either from the primary map or by
643 ensuring there is an entry for it in the aux primary map. The
644 secmap may be a distinguished one as the caller will only want to
645 be able to read it.
646*/
sewardj05a46732006-10-17 01:28:10 +0000647static INLINE SecMap* get_secmap_for_reading ( Addr a )
sewardj45d94cc2005-04-20 14:44:11 +0000648{
njn1d0825f2006-03-27 11:37:07 +0000649 return ( a <= MAX_PRIMARY_ADDRESS
njna7c7ebd2006-03-28 12:51:02 +0000650 ? get_secmap_for_reading_low (a)
651 : get_secmap_for_reading_high(a) );
sewardj45d94cc2005-04-20 14:44:11 +0000652}
653
654/* Produce the secmap for 'a', either from the primary map or by
655 ensuring there is an entry for it in the aux primary map. The
656 secmap may not be a distinguished one, since the caller will want
657 to be able to write it. If it is a distinguished secondary, make a
658 writable copy of it, install it, and return the copy instead. (COW
659 semantics).
660*/
njna7c7ebd2006-03-28 12:51:02 +0000661static SecMap* get_secmap_for_writing ( Addr a )
sewardj45d94cc2005-04-20 14:44:11 +0000662{
njn1d0825f2006-03-27 11:37:07 +0000663 return ( a <= MAX_PRIMARY_ADDRESS
njna7c7ebd2006-03-28 12:51:02 +0000664 ? get_secmap_for_writing_low (a)
665 : get_secmap_for_writing_high(a) );
njn1d0825f2006-03-27 11:37:07 +0000666}
667
668/* If 'a' has a SecMap, produce it. Else produce NULL. But don't
669 allocate one if one doesn't already exist. This is used by the
670 leak checker.
671*/
672static SecMap* maybe_get_secmap_for ( Addr a )
673{
sewardj45d94cc2005-04-20 14:44:11 +0000674 if (a <= MAX_PRIMARY_ADDRESS) {
njna7c7ebd2006-03-28 12:51:02 +0000675 return get_secmap_for_reading_low(a);
sewardj45d94cc2005-04-20 14:44:11 +0000676 } else {
njn1d0825f2006-03-27 11:37:07 +0000677 AuxMapEnt* am = maybe_find_in_auxmap(a);
678 return am ? am->sm : NULL;
sewardj45d94cc2005-04-20 14:44:11 +0000679 }
680}
681
njn1d0825f2006-03-27 11:37:07 +0000682/* --------------- Fundamental functions --------------- */
683
684static INLINE
685void insert_vabits2_into_vabits8 ( Addr a, UChar vabits2, UChar* vabits8 )
686{
687 UInt shift = (a & 3) << 1; // shift by 0, 2, 4, or 6
688 *vabits8 &= ~(0x3 << shift); // mask out the two old bits
689 *vabits8 |= (vabits2 << shift); // mask in the two new bits
690}
691
692static INLINE
693void insert_vabits4_into_vabits8 ( Addr a, UChar vabits4, UChar* vabits8 )
694{
695 UInt shift;
696 tl_assert(VG_IS_2_ALIGNED(a)); // Must be 2-aligned
697 shift = (a & 2) << 1; // shift by 0 or 4
698 *vabits8 &= ~(0xf << shift); // mask out the four old bits
699 *vabits8 |= (vabits4 << shift); // mask in the four new bits
700}
701
702static INLINE
703UChar extract_vabits2_from_vabits8 ( Addr a, UChar vabits8 )
704{
705 UInt shift = (a & 3) << 1; // shift by 0, 2, 4, or 6
706 vabits8 >>= shift; // shift the two bits to the bottom
707 return 0x3 & vabits8; // mask out the rest
708}
709
710static INLINE
711UChar extract_vabits4_from_vabits8 ( Addr a, UChar vabits8 )
712{
713 UInt shift;
714 tl_assert(VG_IS_2_ALIGNED(a)); // Must be 2-aligned
715 shift = (a & 2) << 1; // shift by 0 or 4
716 vabits8 >>= shift; // shift the four bits to the bottom
717 return 0xf & vabits8; // mask out the rest
718}
719
720// Note that these four are only used in slow cases. The fast cases do
721// clever things like combine the auxmap check (in
722// get_secmap_{read,writ}able) with alignment checks.
723
724// *** WARNING! ***
725// Any time this function is called, if it is possible that vabits2
njndbf7ca72006-03-31 11:57:59 +0000726// is equal to VA_BITS2_PARTDEFINED, then the corresponding entry in the
njn1d0825f2006-03-27 11:37:07 +0000727// sec-V-bits table must also be set!
728static INLINE
729void set_vabits2 ( Addr a, UChar vabits2 )
730{
njna7c7ebd2006-03-28 12:51:02 +0000731 SecMap* sm = get_secmap_for_writing(a);
njn1d0825f2006-03-27 11:37:07 +0000732 UWord sm_off = SM_OFF(a);
733 insert_vabits2_into_vabits8( a, vabits2, &(sm->vabits8[sm_off]) );
734}
735
736static INLINE
737UChar get_vabits2 ( Addr a )
738{
njna7c7ebd2006-03-28 12:51:02 +0000739 SecMap* sm = get_secmap_for_reading(a);
njn1d0825f2006-03-27 11:37:07 +0000740 UWord sm_off = SM_OFF(a);
741 UChar vabits8 = sm->vabits8[sm_off];
742 return extract_vabits2_from_vabits8(a, vabits8);
743}
744
sewardjf2184912006-05-03 22:13:57 +0000745// *** WARNING! ***
746// Any time this function is called, if it is possible that any of the
747// 4 2-bit fields in vabits8 are equal to VA_BITS2_PARTDEFINED, then the
748// corresponding entry(s) in the sec-V-bits table must also be set!
749static INLINE
750UChar get_vabits8_for_aligned_word32 ( Addr a )
751{
752 SecMap* sm = get_secmap_for_reading(a);
753 UWord sm_off = SM_OFF(a);
754 UChar vabits8 = sm->vabits8[sm_off];
755 return vabits8;
756}
757
758static INLINE
759void set_vabits8_for_aligned_word32 ( Addr a, UChar vabits8 )
760{
761 SecMap* sm = get_secmap_for_writing(a);
762 UWord sm_off = SM_OFF(a);
763 sm->vabits8[sm_off] = vabits8;
764}
765
766
njn1d0825f2006-03-27 11:37:07 +0000767// Forward declarations
768static UWord get_sec_vbits8(Addr a);
769static void set_sec_vbits8(Addr a, UWord vbits8);
770
771// Returns False if there was an addressability error.
772static INLINE
773Bool set_vbits8 ( Addr a, UChar vbits8 )
774{
775 Bool ok = True;
776 UChar vabits2 = get_vabits2(a);
777 if ( VA_BITS2_NOACCESS != vabits2 ) {
778 // Addressable. Convert in-register format to in-memory format.
779 // Also remove any existing sec V bit entry for the byte if no
780 // longer necessary.
njndbf7ca72006-03-31 11:57:59 +0000781 if ( V_BITS8_DEFINED == vbits8 ) { vabits2 = VA_BITS2_DEFINED; }
782 else if ( V_BITS8_UNDEFINED == vbits8 ) { vabits2 = VA_BITS2_UNDEFINED; }
783 else { vabits2 = VA_BITS2_PARTDEFINED;
njn1d0825f2006-03-27 11:37:07 +0000784 set_sec_vbits8(a, vbits8); }
785 set_vabits2(a, vabits2);
786
787 } else {
788 // Unaddressable! Do nothing -- when writing to unaddressable
789 // memory it acts as a black hole, and the V bits can never be seen
790 // again. So we don't have to write them at all.
791 ok = False;
792 }
793 return ok;
794}
795
796// Returns False if there was an addressability error. In that case, we put
797// all defined bits into vbits8.
798static INLINE
799Bool get_vbits8 ( Addr a, UChar* vbits8 )
800{
801 Bool ok = True;
802 UChar vabits2 = get_vabits2(a);
803
804 // Convert the in-memory format to in-register format.
njndbf7ca72006-03-31 11:57:59 +0000805 if ( VA_BITS2_DEFINED == vabits2 ) { *vbits8 = V_BITS8_DEFINED; }
806 else if ( VA_BITS2_UNDEFINED == vabits2 ) { *vbits8 = V_BITS8_UNDEFINED; }
807 else if ( VA_BITS2_NOACCESS == vabits2 ) {
njn1d0825f2006-03-27 11:37:07 +0000808 *vbits8 = V_BITS8_DEFINED; // Make V bits defined!
809 ok = False;
810 } else {
njndbf7ca72006-03-31 11:57:59 +0000811 tl_assert( VA_BITS2_PARTDEFINED == vabits2 );
njn1d0825f2006-03-27 11:37:07 +0000812 *vbits8 = get_sec_vbits8(a);
813 }
814 return ok;
815}
816
817
818/* --------------- Secondary V bit table ------------ */
819
820// This table holds the full V bit pattern for partially-defined bytes
njndbf7ca72006-03-31 11:57:59 +0000821// (PDBs) that are represented by VA_BITS2_PARTDEFINED in the main shadow
822// memory.
njn1d0825f2006-03-27 11:37:07 +0000823//
824// Note: the nodes in this table can become stale. Eg. if you write a PDB,
825// then overwrite the same address with a fully defined byte, the sec-V-bit
826// node will not necessarily be removed. This is because checking for
827// whether removal is necessary would slow down the fast paths.
828//
829// To avoid the stale nodes building up too much, we periodically (once the
830// table reaches a certain size) garbage collect (GC) the table by
sewardj8ce5c242012-02-14 12:11:47 +0000831// traversing it and evicting any nodes not having PDB.
njn1d0825f2006-03-27 11:37:07 +0000832// If more than a certain proportion of nodes survived, we increase the
833// table size so that GCs occur less often.
834//
njn1d0825f2006-03-27 11:37:07 +0000835// This policy is designed to avoid bad table bloat in the worst case where
836// a program creates huge numbers of stale PDBs -- we would get this bloat
837// if we had no GC -- while handling well the case where a node becomes
838// stale but shortly afterwards is rewritten with a PDB and so becomes
839// non-stale again (which happens quite often, eg. in perf/bz2). If we just
840// remove all stale nodes as soon as possible, we just end up re-adding a
841// lot of them in later again. The "sufficiently stale" approach avoids
842// this. (If a program has many live PDBs, performance will just suck,
843// there's no way around that.)
sewardj8ce5c242012-02-14 12:11:47 +0000844//
845// Further comments, JRS 14 Feb 2012. It turns out that the policy of
846// holding on to stale entries for 2 GCs before discarding them can lead
847// to massive space leaks. So we're changing to an arrangement where
848// lines are evicted as soon as they are observed to be stale during a
849// GC. This also has a side benefit of allowing the sufficiently_stale
850// field to be removed from the SecVBitNode struct, reducing its size by
851// 8 bytes, which is a substantial space saving considering that the
852// struct was previously 32 or so bytes, on a 64 bit target.
853//
854// In order to try and mitigate the problem that the "sufficiently stale"
855// heuristic was designed to avoid, the table size is allowed to drift
856// up ("DRIFTUP") slowly to 80000, even if the residency is low. This
857// means that nodes will exist in the table longer on average, and hopefully
858// will be deleted and re-added less frequently.
859//
860// The previous scaling up mechanism (now called STEPUP) is retained:
861// if residency exceeds 50%, the table is scaled up, although by a
862// factor sqrt(2) rather than 2 as before. This effectively doubles the
863// frequency of GCs when there are many PDBs at reduces the tendency of
864// stale PDBs to reside for long periods in the table.
njn1d0825f2006-03-27 11:37:07 +0000865
866static OSet* secVBitTable;
867
868// Stats
869static ULong sec_vbits_new_nodes = 0;
870static ULong sec_vbits_updates = 0;
871
872// This must be a power of two; this is checked in mc_pre_clo_init().
873// The size chosen here is a trade-off: if the nodes are bigger (ie. cover
874// a larger address range) they take more space but we can get multiple
875// partially-defined bytes in one if they are close to each other, reducing
876// the number of total nodes. In practice sometimes they are clustered (eg.
877// perf/bz2 repeatedly writes then reads more than 20,000 in a contiguous
878// row), but often not. So we choose something intermediate.
879#define BYTES_PER_SEC_VBIT_NODE 16
880
sewardj8ce5c242012-02-14 12:11:47 +0000881// We make the table bigger by a factor of STEPUP_GROWTH_FACTOR if
882// more than this many nodes survive a GC.
883#define STEPUP_SURVIVOR_PROPORTION 0.5
884#define STEPUP_GROWTH_FACTOR 1.414213562
njn1d0825f2006-03-27 11:37:07 +0000885
sewardj8ce5c242012-02-14 12:11:47 +0000886// If the above heuristic doesn't apply, then we may make the table
887// slightly bigger, by a factor of DRIFTUP_GROWTH_FACTOR, if more than
888// this many nodes survive a GC, _and_ the total table size does
889// not exceed a fixed limit. The numbers are somewhat arbitrary, but
890// work tolerably well on long Firefox runs. The scaleup ratio of 1.5%
891// effectively although gradually reduces residency and increases time
892// between GCs for programs with small numbers of PDBs. The 80000 limit
893// effectively limits the table size to around 2MB for programs with
894// small numbers of PDBs, whilst giving a reasonably long lifetime to
895// entries, to try and reduce the costs resulting from deleting and
896// re-adding of entries.
897#define DRIFTUP_SURVIVOR_PROPORTION 0.15
898#define DRIFTUP_GROWTH_FACTOR 1.015
899#define DRIFTUP_MAX_SIZE 80000
njn1d0825f2006-03-27 11:37:07 +0000900
njn1d0825f2006-03-27 11:37:07 +0000901// We GC the table when it gets this many nodes in it, ie. it's effectively
902// the table size. It can change.
sewardj8ce5c242012-02-14 12:11:47 +0000903static Int secVBitLimit = 1000;
njn1d0825f2006-03-27 11:37:07 +0000904
905// The number of GCs done, used to age sec-V-bit nodes for eviction.
906// Because it's unsigned, wrapping doesn't matter -- the right answer will
907// come out anyway.
908static UInt GCs_done = 0;
909
910typedef
911 struct {
912 Addr a;
913 UChar vbits8[BYTES_PER_SEC_VBIT_NODE];
njn1d0825f2006-03-27 11:37:07 +0000914 }
915 SecVBitNode;
916
917static OSet* createSecVBitTable(void)
918{
philippe6643e962012-01-17 21:16:30 +0000919 OSet* newSecVBitTable;
920 newSecVBitTable = VG_(OSetGen_Create_With_Pool)
921 ( offsetof(SecVBitNode, a),
922 NULL, // use fast comparisons
923 VG_(malloc), "mc.cSVT.1 (sec VBit table)",
924 VG_(free),
925 1000,
926 sizeof(SecVBitNode));
927 return newSecVBitTable;
njn1d0825f2006-03-27 11:37:07 +0000928}
929
930static void gcSecVBitTable(void)
931{
932 OSet* secVBitTable2;
933 SecVBitNode* n;
934 Int i, n_nodes = 0, n_survivors = 0;
935
936 GCs_done++;
937
938 // Create the new table.
939 secVBitTable2 = createSecVBitTable();
940
941 // Traverse the table, moving fresh nodes into the new table.
njne2a9ad32007-09-17 05:30:48 +0000942 VG_(OSetGen_ResetIter)(secVBitTable);
943 while ( (n = VG_(OSetGen_Next)(secVBitTable)) ) {
sewardj8ce5c242012-02-14 12:11:47 +0000944 // Keep node if any of its bytes are non-stale. Using
945 // get_vabits2() for the lookup is not very efficient, but I don't
946 // think it matters.
947 for (i = 0; i < BYTES_PER_SEC_VBIT_NODE; i++) {
948 if (VA_BITS2_PARTDEFINED == get_vabits2(n->a + i)) {
949 // Found a non-stale byte, so keep =>
950 // Insert a copy of the node into the new table.
951 SecVBitNode* n2 =
952 VG_(OSetGen_AllocNode)(secVBitTable2, sizeof(SecVBitNode));
953 *n2 = *n;
954 VG_(OSetGen_Insert)(secVBitTable2, n2);
955 break;
njn1d0825f2006-03-27 11:37:07 +0000956 }
957 }
njn1d0825f2006-03-27 11:37:07 +0000958 }
959
960 // Get the before and after sizes.
njne2a9ad32007-09-17 05:30:48 +0000961 n_nodes = VG_(OSetGen_Size)(secVBitTable);
962 n_survivors = VG_(OSetGen_Size)(secVBitTable2);
njn1d0825f2006-03-27 11:37:07 +0000963
964 // Destroy the old table, and put the new one in its place.
njne2a9ad32007-09-17 05:30:48 +0000965 VG_(OSetGen_Destroy)(secVBitTable);
njn1d0825f2006-03-27 11:37:07 +0000966 secVBitTable = secVBitTable2;
967
968 if (VG_(clo_verbosity) > 1) {
floriandbb35842012-10-27 18:39:11 +0000969 HChar percbuf[7];
njn1d0825f2006-03-27 11:37:07 +0000970 VG_(percentify)(n_survivors, n_nodes, 1, 6, percbuf);
sewardj6b523cd2009-07-15 14:49:40 +0000971 VG_(message)(Vg_DebugMsg, "memcheck GC: %d nodes, %d survivors (%s)\n",
njn1d0825f2006-03-27 11:37:07 +0000972 n_nodes, n_survivors, percbuf);
973 }
974
975 // Increase table size if necessary.
sewardj8ce5c242012-02-14 12:11:47 +0000976 if ((Double)n_survivors
977 > ((Double)secVBitLimit * STEPUP_SURVIVOR_PROPORTION)) {
978 secVBitLimit = (Int)((Double)secVBitLimit * (Double)STEPUP_GROWTH_FACTOR);
njn1d0825f2006-03-27 11:37:07 +0000979 if (VG_(clo_verbosity) > 1)
sewardj8ce5c242012-02-14 12:11:47 +0000980 VG_(message)(Vg_DebugMsg,
981 "memcheck GC: %d new table size (stepup)\n",
982 secVBitLimit);
983 }
984 else
985 if (secVBitLimit < DRIFTUP_MAX_SIZE
986 && (Double)n_survivors
987 > ((Double)secVBitLimit * DRIFTUP_SURVIVOR_PROPORTION)) {
988 secVBitLimit = (Int)((Double)secVBitLimit * (Double)DRIFTUP_GROWTH_FACTOR);
989 if (VG_(clo_verbosity) > 1)
990 VG_(message)(Vg_DebugMsg,
991 "memcheck GC: %d new table size (driftup)\n",
njn1d0825f2006-03-27 11:37:07 +0000992 secVBitLimit);
993 }
994}
995
996static UWord get_sec_vbits8(Addr a)
997{
998 Addr aAligned = VG_ROUNDDN(a, BYTES_PER_SEC_VBIT_NODE);
999 Int amod = a % BYTES_PER_SEC_VBIT_NODE;
njne2a9ad32007-09-17 05:30:48 +00001000 SecVBitNode* n = VG_(OSetGen_Lookup)(secVBitTable, &aAligned);
njn1d0825f2006-03-27 11:37:07 +00001001 UChar vbits8;
1002 tl_assert2(n, "get_sec_vbits8: no node for address %p (%p)\n", aAligned, a);
1003 // Shouldn't be fully defined or fully undefined -- those cases shouldn't
1004 // make it to the secondary V bits table.
1005 vbits8 = n->vbits8[amod];
1006 tl_assert(V_BITS8_DEFINED != vbits8 && V_BITS8_UNDEFINED != vbits8);
1007 return vbits8;
1008}
1009
1010static void set_sec_vbits8(Addr a, UWord vbits8)
1011{
1012 Addr aAligned = VG_ROUNDDN(a, BYTES_PER_SEC_VBIT_NODE);
1013 Int i, amod = a % BYTES_PER_SEC_VBIT_NODE;
njne2a9ad32007-09-17 05:30:48 +00001014 SecVBitNode* n = VG_(OSetGen_Lookup)(secVBitTable, &aAligned);
njn1d0825f2006-03-27 11:37:07 +00001015 // Shouldn't be fully defined or fully undefined -- those cases shouldn't
1016 // make it to the secondary V bits table.
1017 tl_assert(V_BITS8_DEFINED != vbits8 && V_BITS8_UNDEFINED != vbits8);
1018 if (n) {
1019 n->vbits8[amod] = vbits8; // update
njn1d0825f2006-03-27 11:37:07 +00001020 sec_vbits_updates++;
1021 } else {
philippe6643e962012-01-17 21:16:30 +00001022 // Do a table GC if necessary. Nb: do this before creating and
1023 // inserting the new node, to avoid erroneously GC'ing the new node.
1024 if (secVBitLimit == VG_(OSetGen_Size)(secVBitTable)) {
1025 gcSecVBitTable();
1026 }
1027
njn1d0825f2006-03-27 11:37:07 +00001028 // New node: assign the specific byte, make the rest invalid (they
1029 // should never be read as-is, but be cautious).
njne2a9ad32007-09-17 05:30:48 +00001030 n = VG_(OSetGen_AllocNode)(secVBitTable, sizeof(SecVBitNode));
njn1d0825f2006-03-27 11:37:07 +00001031 n->a = aAligned;
1032 for (i = 0; i < BYTES_PER_SEC_VBIT_NODE; i++) {
1033 n->vbits8[i] = V_BITS8_UNDEFINED;
1034 }
1035 n->vbits8[amod] = vbits8;
njn1d0825f2006-03-27 11:37:07 +00001036
njn1d0825f2006-03-27 11:37:07 +00001037 // Insert the new node.
njne2a9ad32007-09-17 05:30:48 +00001038 VG_(OSetGen_Insert)(secVBitTable, n);
njn1d0825f2006-03-27 11:37:07 +00001039 sec_vbits_new_nodes++;
1040
njne2a9ad32007-09-17 05:30:48 +00001041 n_secVBit_nodes = VG_(OSetGen_Size)(secVBitTable);
njn1d0825f2006-03-27 11:37:07 +00001042 if (n_secVBit_nodes > max_secVBit_nodes)
1043 max_secVBit_nodes = n_secVBit_nodes;
1044 }
1045}
sewardj45d94cc2005-04-20 14:44:11 +00001046
1047/* --------------- Endianness helpers --------------- */
1048
1049/* Returns the offset in memory of the byteno-th most significant byte
1050 in a wordszB-sized word, given the specified endianness. */
njn1d0825f2006-03-27 11:37:07 +00001051static INLINE UWord byte_offset_w ( UWord wordszB, Bool bigendian,
sewardj45d94cc2005-04-20 14:44:11 +00001052 UWord byteno ) {
1053 return bigendian ? (wordszB-1-byteno) : byteno;
1054}
1055
sewardj05a46732006-10-17 01:28:10 +00001056
1057/* --------------- Ignored address ranges --------------- */
1058
1059#define M_IGNORE_RANGES 4
1060
1061typedef
1062 struct {
1063 Int used;
1064 Addr start[M_IGNORE_RANGES];
1065 Addr end[M_IGNORE_RANGES];
1066 }
1067 IgnoreRanges;
1068
1069static IgnoreRanges ignoreRanges;
1070
sewardj7ce71662008-05-02 10:33:15 +00001071INLINE Bool MC_(in_ignored_range) ( Addr a )
sewardj05a46732006-10-17 01:28:10 +00001072{
1073 Int i;
bart5dd8e6a2008-03-22 08:04:29 +00001074 if (LIKELY(ignoreRanges.used == 0))
sewardj05a46732006-10-17 01:28:10 +00001075 return False;
1076 for (i = 0; i < ignoreRanges.used; i++) {
1077 if (a >= ignoreRanges.start[i] && a < ignoreRanges.end[i])
1078 return True;
1079 }
1080 return False;
1081}
1082
sewardj3b290482011-05-06 21:02:55 +00001083/* Parse two Addr separated by a dash, or fail. */
sewardj05a46732006-10-17 01:28:10 +00001084
florian19f91bb2012-11-10 22:29:54 +00001085static Bool parse_range ( const HChar** ppc, Addr* result1, Addr* result2 )
sewardj05a46732006-10-17 01:28:10 +00001086{
sewardj3b290482011-05-06 21:02:55 +00001087 Bool ok = VG_(parse_Addr) (ppc, result1);
sewardj05a46732006-10-17 01:28:10 +00001088 if (!ok)
1089 return False;
1090 if (**ppc != '-')
1091 return False;
1092 (*ppc)++;
sewardj3b290482011-05-06 21:02:55 +00001093 ok = VG_(parse_Addr) (ppc, result2);
sewardj05a46732006-10-17 01:28:10 +00001094 if (!ok)
1095 return False;
1096 return True;
1097}
1098
1099/* Parse a set of ranges separated by commas into 'ignoreRanges', or
1100 fail. */
1101
florian19f91bb2012-11-10 22:29:54 +00001102static Bool parse_ignore_ranges ( const HChar* str0 )
sewardj05a46732006-10-17 01:28:10 +00001103{
1104 Addr start, end;
1105 Bool ok;
florian19f91bb2012-11-10 22:29:54 +00001106 const HChar* str = str0;
1107 const HChar** ppc = &str;
sewardj05a46732006-10-17 01:28:10 +00001108 ignoreRanges.used = 0;
1109 while (1) {
1110 ok = parse_range(ppc, &start, &end);
1111 if (!ok)
1112 return False;
1113 if (ignoreRanges.used >= M_IGNORE_RANGES)
1114 return False;
1115 ignoreRanges.start[ignoreRanges.used] = start;
1116 ignoreRanges.end[ignoreRanges.used] = end;
1117 ignoreRanges.used++;
1118 if (**ppc == 0)
1119 return True;
1120 if (**ppc != ',')
1121 return False;
1122 (*ppc)++;
1123 }
1124 /*NOTREACHED*/
1125 return False;
1126}
1127
1128
sewardj45d94cc2005-04-20 14:44:11 +00001129/* --------------- Load/store slow cases. --------------- */
1130
1131static
sewardj14a81782011-08-20 15:55:07 +00001132__attribute__((noinline))
njn45e81252006-03-28 12:35:08 +00001133ULong mc_LOADVn_slow ( Addr a, SizeT nBits, Bool bigendian )
sewardj45d94cc2005-04-20 14:44:11 +00001134{
sewardjc1a2cda2005-04-21 17:34:00 +00001135 PROF_EVENT(30, "mc_LOADVn_slow");
sewardj05a46732006-10-17 01:28:10 +00001136
1137 /* ------------ BEGIN semi-fast cases ------------ */
1138 /* These deal quickly-ish with the common auxiliary primary map
1139 cases on 64-bit platforms. Are merely a speedup hack; can be
1140 omitted without loss of correctness/functionality. Note that in
1141 both cases the "sizeof(void*) == 8" causes these cases to be
1142 folded out by compilers on 32-bit platforms. These are derived
1143 from LOADV64 and LOADV32.
1144 */
bart5dd8e6a2008-03-22 08:04:29 +00001145 if (LIKELY(sizeof(void*) == 8
sewardj05a46732006-10-17 01:28:10 +00001146 && nBits == 64 && VG_IS_8_ALIGNED(a))) {
1147 SecMap* sm = get_secmap_for_reading(a);
1148 UWord sm_off16 = SM_OFF_16(a);
1149 UWord vabits16 = ((UShort*)(sm->vabits8))[sm_off16];
bart5dd8e6a2008-03-22 08:04:29 +00001150 if (LIKELY(vabits16 == VA_BITS16_DEFINED))
sewardj05a46732006-10-17 01:28:10 +00001151 return V_BITS64_DEFINED;
bart5dd8e6a2008-03-22 08:04:29 +00001152 if (LIKELY(vabits16 == VA_BITS16_UNDEFINED))
sewardj05a46732006-10-17 01:28:10 +00001153 return V_BITS64_UNDEFINED;
1154 /* else fall into the slow case */
1155 }
bart5dd8e6a2008-03-22 08:04:29 +00001156 if (LIKELY(sizeof(void*) == 8
sewardj05a46732006-10-17 01:28:10 +00001157 && nBits == 32 && VG_IS_4_ALIGNED(a))) {
1158 SecMap* sm = get_secmap_for_reading(a);
1159 UWord sm_off = SM_OFF(a);
1160 UWord vabits8 = sm->vabits8[sm_off];
bart5dd8e6a2008-03-22 08:04:29 +00001161 if (LIKELY(vabits8 == VA_BITS8_DEFINED))
sewardj05a46732006-10-17 01:28:10 +00001162 return ((UWord)0xFFFFFFFF00000000ULL | (UWord)V_BITS32_DEFINED);
bart5dd8e6a2008-03-22 08:04:29 +00001163 if (LIKELY(vabits8 == VA_BITS8_UNDEFINED))
sewardj05a46732006-10-17 01:28:10 +00001164 return ((UWord)0xFFFFFFFF00000000ULL | (UWord)V_BITS32_UNDEFINED);
1165 /* else fall into slow case */
1166 }
1167 /* ------------ END semi-fast cases ------------ */
1168
sewardjda04f3e2012-03-08 14:51:01 +00001169 ULong vbits64 = V_BITS64_UNDEFINED; /* result */
1170 ULong pessim64 = V_BITS64_DEFINED; /* only used when p-l-ok=yes */
1171 SSizeT szB = nBits / 8;
1172 SSizeT i; /* Must be signed. */
1173 SizeT n_addrs_bad = 0;
1174 Addr ai;
1175 UChar vbits8;
1176 Bool ok;
1177
njn45e81252006-03-28 12:35:08 +00001178 tl_assert(nBits == 64 || nBits == 32 || nBits == 16 || nBits == 8);
sewardj45d94cc2005-04-20 14:44:11 +00001179
sewardjda04f3e2012-03-08 14:51:01 +00001180 /* Make up a 64-bit result V word, which contains the loaded data
1181 for valid addresses and Defined for invalid addresses. Iterate
1182 over the bytes in the word, from the most significant down to
1183 the least. The vbits to return are calculated into vbits64.
1184 Also compute the pessimising value to be used when
1185 --partial-loads-ok=yes. n_addrs_bad is redundant (the relevant
1186 info can be gleaned from pessim64) but is used as a
1187 cross-check. */
njn1d0825f2006-03-27 11:37:07 +00001188 for (i = szB-1; i >= 0; i--) {
sewardjc1a2cda2005-04-21 17:34:00 +00001189 PROF_EVENT(31, "mc_LOADVn_slow(loop)");
njn45e81252006-03-28 12:35:08 +00001190 ai = a + byte_offset_w(szB, bigendian, i);
njn1d0825f2006-03-27 11:37:07 +00001191 ok = get_vbits8(ai, &vbits8);
njn1d0825f2006-03-27 11:37:07 +00001192 vbits64 <<= 8;
1193 vbits64 |= vbits8;
sewardjda04f3e2012-03-08 14:51:01 +00001194 if (!ok) n_addrs_bad++;
1195 pessim64 <<= 8;
1196 pessim64 |= (ok ? V_BITS8_DEFINED : V_BITS8_UNDEFINED);
sewardj45d94cc2005-04-20 14:44:11 +00001197 }
1198
sewardjda04f3e2012-03-08 14:51:01 +00001199 /* In the common case, all the addresses involved are valid, so we
1200 just return the computed V bits and have done. */
1201 if (LIKELY(n_addrs_bad == 0))
1202 return vbits64;
sewardj0ded7a42005-11-08 02:25:37 +00001203
sewardjda04f3e2012-03-08 14:51:01 +00001204 /* If there's no possibility of getting a partial-loads-ok
1205 exemption, report the error and quit. */
1206 if (!MC_(clo_partial_loads_ok)) {
1207 MC_(record_address_error)( VG_(get_running_tid)(), a, szB, False );
1208 return vbits64;
1209 }
1210
1211 /* The partial-loads-ok excemption might apply. Find out if it
1212 does. If so, don't report an addressing error, but do return
1213 Undefined for the bytes that are out of range, so as to avoid
1214 false negatives. If it doesn't apply, just report an addressing
1215 error in the usual way. */
1216
1217 /* Some code steps along byte strings in aligned word-sized chunks
1218 even when there is only a partially defined word at the end (eg,
1219 optimised strlen). This is allowed by the memory model of
1220 modern machines, since an aligned load cannot span two pages and
1221 thus cannot "partially fault". Despite such behaviour being
1222 declared undefined by ANSI C/C++.
1223
1224 Therefore, a load from a partially-addressible place is allowed
1225 if all of the following hold:
1226 - the command-line flag is set [by default, it isn't]
sewardj0ded7a42005-11-08 02:25:37 +00001227 - it's a word-sized, word-aligned load
1228 - at least one of the addresses in the word *is* valid
sewardj0ded7a42005-11-08 02:25:37 +00001229
sewardjda04f3e2012-03-08 14:51:01 +00001230 Since this suppresses the addressing error, we avoid false
1231 negatives by marking bytes undefined when they come from an
1232 invalid address.
1233 */
1234
1235 /* "at least one of the addresses is invalid" */
1236 tl_assert(pessim64 != V_BITS64_DEFINED);
1237
1238 if (szB == VG_WORDSIZE && VG_IS_WORD_ALIGNED(a)
1239 && n_addrs_bad < VG_WORDSIZE) {
1240 /* Exemption applies. Use the previously computed pessimising
1241 value for vbits64 and return the combined result, but don't
1242 flag an addressing error. The pessimising value is Defined
1243 for valid addresses and Undefined for invalid addresses. */
1244 /* for assumption that doing bitwise or implements UifU */
1245 tl_assert(V_BIT_UNDEFINED == 1 && V_BIT_DEFINED == 0);
1246 /* (really need "UifU" here...)
1247 vbits64 UifU= pessim64 (is pessimised by it, iow) */
1248 vbits64 |= pessim64;
1249 return vbits64;
1250 }
1251
1252 /* Exemption doesn't apply. Flag an addressing error in the normal
1253 way. */
1254 MC_(record_address_error)( VG_(get_running_tid)(), a, szB, False );
sewardj45d94cc2005-04-20 14:44:11 +00001255
njn1d0825f2006-03-27 11:37:07 +00001256 return vbits64;
sewardj45d94cc2005-04-20 14:44:11 +00001257}
1258
1259
njn1d0825f2006-03-27 11:37:07 +00001260static
sewardj14a81782011-08-20 15:55:07 +00001261__attribute__((noinline))
njn45e81252006-03-28 12:35:08 +00001262void mc_STOREVn_slow ( Addr a, SizeT nBits, ULong vbytes, Bool bigendian )
sewardj45d94cc2005-04-20 14:44:11 +00001263{
njn45e81252006-03-28 12:35:08 +00001264 SizeT szB = nBits / 8;
njn1d0825f2006-03-27 11:37:07 +00001265 SizeT i, n_addrs_bad = 0;
1266 UChar vbits8;
sewardj45d94cc2005-04-20 14:44:11 +00001267 Addr ai;
njn1d0825f2006-03-27 11:37:07 +00001268 Bool ok;
sewardj45d94cc2005-04-20 14:44:11 +00001269
sewardjc1a2cda2005-04-21 17:34:00 +00001270 PROF_EVENT(35, "mc_STOREVn_slow");
sewardj05a46732006-10-17 01:28:10 +00001271
1272 /* ------------ BEGIN semi-fast cases ------------ */
1273 /* These deal quickly-ish with the common auxiliary primary map
1274 cases on 64-bit platforms. Are merely a speedup hack; can be
1275 omitted without loss of correctness/functionality. Note that in
1276 both cases the "sizeof(void*) == 8" causes these cases to be
1277 folded out by compilers on 32-bit platforms. These are derived
1278 from STOREV64 and STOREV32.
1279 */
bart5dd8e6a2008-03-22 08:04:29 +00001280 if (LIKELY(sizeof(void*) == 8
sewardj05a46732006-10-17 01:28:10 +00001281 && nBits == 64 && VG_IS_8_ALIGNED(a))) {
1282 SecMap* sm = get_secmap_for_reading(a);
1283 UWord sm_off16 = SM_OFF_16(a);
1284 UWord vabits16 = ((UShort*)(sm->vabits8))[sm_off16];
bart5dd8e6a2008-03-22 08:04:29 +00001285 if (LIKELY( !is_distinguished_sm(sm) &&
sewardj05a46732006-10-17 01:28:10 +00001286 (VA_BITS16_DEFINED == vabits16 ||
1287 VA_BITS16_UNDEFINED == vabits16) )) {
1288 /* Handle common case quickly: a is suitably aligned, */
1289 /* is mapped, and is addressible. */
1290 // Convert full V-bits in register to compact 2-bit form.
bart5dd8e6a2008-03-22 08:04:29 +00001291 if (LIKELY(V_BITS64_DEFINED == vbytes)) {
sewardj05a46732006-10-17 01:28:10 +00001292 ((UShort*)(sm->vabits8))[sm_off16] = (UShort)VA_BITS16_DEFINED;
1293 return;
1294 } else if (V_BITS64_UNDEFINED == vbytes) {
1295 ((UShort*)(sm->vabits8))[sm_off16] = (UShort)VA_BITS16_UNDEFINED;
1296 return;
1297 }
1298 /* else fall into the slow case */
1299 }
1300 /* else fall into the slow case */
1301 }
bart5dd8e6a2008-03-22 08:04:29 +00001302 if (LIKELY(sizeof(void*) == 8
sewardj05a46732006-10-17 01:28:10 +00001303 && nBits == 32 && VG_IS_4_ALIGNED(a))) {
1304 SecMap* sm = get_secmap_for_reading(a);
1305 UWord sm_off = SM_OFF(a);
1306 UWord vabits8 = sm->vabits8[sm_off];
bart5dd8e6a2008-03-22 08:04:29 +00001307 if (LIKELY( !is_distinguished_sm(sm) &&
sewardj05a46732006-10-17 01:28:10 +00001308 (VA_BITS8_DEFINED == vabits8 ||
1309 VA_BITS8_UNDEFINED == vabits8) )) {
1310 /* Handle common case quickly: a is suitably aligned, */
1311 /* is mapped, and is addressible. */
1312 // Convert full V-bits in register to compact 2-bit form.
bart5dd8e6a2008-03-22 08:04:29 +00001313 if (LIKELY(V_BITS32_DEFINED == (vbytes & 0xFFFFFFFF))) {
sewardj05a46732006-10-17 01:28:10 +00001314 sm->vabits8[sm_off] = VA_BITS8_DEFINED;
1315 return;
1316 } else if (V_BITS32_UNDEFINED == (vbytes & 0xFFFFFFFF)) {
1317 sm->vabits8[sm_off] = VA_BITS8_UNDEFINED;
1318 return;
1319 }
1320 /* else fall into the slow case */
1321 }
1322 /* else fall into the slow case */
1323 }
1324 /* ------------ END semi-fast cases ------------ */
1325
njn45e81252006-03-28 12:35:08 +00001326 tl_assert(nBits == 64 || nBits == 32 || nBits == 16 || nBits == 8);
sewardj45d94cc2005-04-20 14:44:11 +00001327
1328 /* Dump vbytes in memory, iterating from least to most significant
njn718d3b12006-12-16 00:54:12 +00001329 byte. At the same time establish addressibility of the location. */
sewardj45d94cc2005-04-20 14:44:11 +00001330 for (i = 0; i < szB; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +00001331 PROF_EVENT(36, "mc_STOREVn_slow(loop)");
njn45e81252006-03-28 12:35:08 +00001332 ai = a + byte_offset_w(szB, bigendian, i);
njn1d0825f2006-03-27 11:37:07 +00001333 vbits8 = vbytes & 0xff;
1334 ok = set_vbits8(ai, vbits8);
1335 if (!ok) n_addrs_bad++;
sewardj45d94cc2005-04-20 14:44:11 +00001336 vbytes >>= 8;
1337 }
1338
1339 /* If an address error has happened, report it. */
1340 if (n_addrs_bad > 0)
sewardj7ce71662008-05-02 10:33:15 +00001341 MC_(record_address_error)( VG_(get_running_tid)(), a, szB, True );
sewardj45d94cc2005-04-20 14:44:11 +00001342}
1343
1344
njn25e49d8e72002-09-23 09:36:25 +00001345/*------------------------------------------------------------*/
1346/*--- Setting permissions over address ranges. ---*/
1347/*------------------------------------------------------------*/
1348
njn1d0825f2006-03-27 11:37:07 +00001349static void set_address_range_perms ( Addr a, SizeT lenT, UWord vabits16,
1350 UWord dsm_num )
sewardj23eb2fd2005-04-22 16:29:19 +00001351{
njn1d0825f2006-03-27 11:37:07 +00001352 UWord sm_off, sm_off16;
1353 UWord vabits2 = vabits16 & 0x3;
1354 SizeT lenA, lenB, len_to_next_secmap;
1355 Addr aNext;
sewardjae986ca2005-10-12 12:53:20 +00001356 SecMap* sm;
njn1d0825f2006-03-27 11:37:07 +00001357 SecMap** sm_ptr;
sewardjae986ca2005-10-12 12:53:20 +00001358 SecMap* example_dsm;
1359
sewardj23eb2fd2005-04-22 16:29:19 +00001360 PROF_EVENT(150, "set_address_range_perms");
1361
njn1d0825f2006-03-27 11:37:07 +00001362 /* Check the V+A bits make sense. */
njndbf7ca72006-03-31 11:57:59 +00001363 tl_assert(VA_BITS16_NOACCESS == vabits16 ||
1364 VA_BITS16_UNDEFINED == vabits16 ||
1365 VA_BITS16_DEFINED == vabits16);
sewardj23eb2fd2005-04-22 16:29:19 +00001366
njn1d0825f2006-03-27 11:37:07 +00001367 // This code should never write PDBs; ensure this. (See comment above
1368 // set_vabits2().)
njndbf7ca72006-03-31 11:57:59 +00001369 tl_assert(VA_BITS2_PARTDEFINED != vabits2);
njn1d0825f2006-03-27 11:37:07 +00001370
1371 if (lenT == 0)
sewardj23eb2fd2005-04-22 16:29:19 +00001372 return;
1373
njn59973402009-05-20 03:44:09 +00001374 if (lenT > 256 * 1024 * 1024) {
njn1d0825f2006-03-27 11:37:07 +00001375 if (VG_(clo_verbosity) > 0 && !VG_(clo_xml)) {
floriana5f894c2012-10-21 03:43:20 +00001376 const HChar* s = "unknown???";
njndbf7ca72006-03-31 11:57:59 +00001377 if (vabits16 == VA_BITS16_NOACCESS ) s = "noaccess";
1378 if (vabits16 == VA_BITS16_UNDEFINED) s = "undefined";
1379 if (vabits16 == VA_BITS16_DEFINED ) s = "defined";
njn1d0825f2006-03-27 11:37:07 +00001380 VG_(message)(Vg_UserMsg, "Warning: set address range perms: "
sewardj6b523cd2009-07-15 14:49:40 +00001381 "large range [0x%lx, 0x%lx) (%s)\n",
tom2a836b52008-07-18 08:38:44 +00001382 a, a + lenT, s);
sewardj23eb2fd2005-04-22 16:29:19 +00001383 }
1384 }
1385
njn1d0825f2006-03-27 11:37:07 +00001386#ifndef PERF_FAST_SARP
sewardj23eb2fd2005-04-22 16:29:19 +00001387 /*------------------ debug-only case ------------------ */
njn1d0825f2006-03-27 11:37:07 +00001388 {
1389 // Endianness doesn't matter here because all bytes are being set to
1390 // the same value.
1391 // Nb: We don't have to worry about updating the sec-V-bits table
1392 // after these set_vabits2() calls because this code never writes
njndbf7ca72006-03-31 11:57:59 +00001393 // VA_BITS2_PARTDEFINED values.
njn1d0825f2006-03-27 11:37:07 +00001394 SizeT i;
1395 for (i = 0; i < lenT; i++) {
1396 set_vabits2(a + i, vabits2);
1397 }
1398 return;
njn25e49d8e72002-09-23 09:36:25 +00001399 }
njn1d0825f2006-03-27 11:37:07 +00001400#endif
sewardj23eb2fd2005-04-22 16:29:19 +00001401
1402 /*------------------ standard handling ------------------ */
sewardj23eb2fd2005-04-22 16:29:19 +00001403
njn1d0825f2006-03-27 11:37:07 +00001404 /* Get the distinguished secondary that we might want
sewardj23eb2fd2005-04-22 16:29:19 +00001405 to use (part of the space-compression scheme). */
njn1d0825f2006-03-27 11:37:07 +00001406 example_dsm = &sm_distinguished[dsm_num];
1407
1408 // We have to handle ranges covering various combinations of partial and
1409 // whole sec-maps. Here is how parts 1, 2 and 3 are used in each case.
1410 // Cases marked with a '*' are common.
1411 //
1412 // TYPE PARTS USED
1413 // ---- ----------
1414 // * one partial sec-map (p) 1
1415 // - one whole sec-map (P) 2
1416 //
1417 // * two partial sec-maps (pp) 1,3
1418 // - one partial, one whole sec-map (pP) 1,2
1419 // - one whole, one partial sec-map (Pp) 2,3
1420 // - two whole sec-maps (PP) 2,2
1421 //
1422 // * one partial, one whole, one partial (pPp) 1,2,3
1423 // - one partial, two whole (pPP) 1,2,2
1424 // - two whole, one partial (PPp) 2,2,3
1425 // - three whole (PPP) 2,2,2
1426 //
1427 // * one partial, N-2 whole, one partial (pP...Pp) 1,2...2,3
1428 // - one partial, N-1 whole (pP...PP) 1,2...2,2
1429 // - N-1 whole, one partial (PP...Pp) 2,2...2,3
1430 // - N whole (PP...PP) 2,2...2,3
1431
1432 // Break up total length (lenT) into two parts: length in the first
1433 // sec-map (lenA), and the rest (lenB); lenT == lenA + lenB.
1434 aNext = start_of_this_sm(a) + SM_SIZE;
1435 len_to_next_secmap = aNext - a;
1436 if ( lenT <= len_to_next_secmap ) {
1437 // Range entirely within one sec-map. Covers almost all cases.
1438 PROF_EVENT(151, "set_address_range_perms-single-secmap");
1439 lenA = lenT;
1440 lenB = 0;
1441 } else if (is_start_of_sm(a)) {
1442 // Range spans at least one whole sec-map, and starts at the beginning
1443 // of a sec-map; skip to Part 2.
1444 PROF_EVENT(152, "set_address_range_perms-startof-secmap");
1445 lenA = 0;
1446 lenB = lenT;
1447 goto part2;
sewardj23eb2fd2005-04-22 16:29:19 +00001448 } else {
njn1d0825f2006-03-27 11:37:07 +00001449 // Range spans two or more sec-maps, first one is partial.
1450 PROF_EVENT(153, "set_address_range_perms-multiple-secmaps");
1451 lenA = len_to_next_secmap;
1452 lenB = lenT - lenA;
1453 }
1454
1455 //------------------------------------------------------------------------
1456 // Part 1: Deal with the first sec_map. Most of the time the range will be
1457 // entirely within a sec_map and this part alone will suffice. Also,
1458 // doing it this way lets us avoid repeatedly testing for the crossing of
1459 // a sec-map boundary within these loops.
1460 //------------------------------------------------------------------------
1461
1462 // If it's distinguished, make it undistinguished if necessary.
1463 sm_ptr = get_secmap_ptr(a);
1464 if (is_distinguished_sm(*sm_ptr)) {
1465 if (*sm_ptr == example_dsm) {
1466 // Sec-map already has the V+A bits that we want, so skip.
1467 PROF_EVENT(154, "set_address_range_perms-dist-sm1-quick");
1468 a = aNext;
1469 lenA = 0;
sewardj23eb2fd2005-04-22 16:29:19 +00001470 } else {
njn1d0825f2006-03-27 11:37:07 +00001471 PROF_EVENT(155, "set_address_range_perms-dist-sm1");
1472 *sm_ptr = copy_for_writing(*sm_ptr);
sewardj23eb2fd2005-04-22 16:29:19 +00001473 }
1474 }
njn1d0825f2006-03-27 11:37:07 +00001475 sm = *sm_ptr;
sewardj23eb2fd2005-04-22 16:29:19 +00001476
njn1d0825f2006-03-27 11:37:07 +00001477 // 1 byte steps
sewardj23eb2fd2005-04-22 16:29:19 +00001478 while (True) {
sewardj23eb2fd2005-04-22 16:29:19 +00001479 if (VG_IS_8_ALIGNED(a)) break;
njn1d0825f2006-03-27 11:37:07 +00001480 if (lenA < 1) break;
1481 PROF_EVENT(156, "set_address_range_perms-loop1a");
1482 sm_off = SM_OFF(a);
1483 insert_vabits2_into_vabits8( a, vabits2, &(sm->vabits8[sm_off]) );
1484 a += 1;
1485 lenA -= 1;
1486 }
1487 // 8-aligned, 8 byte steps
sewardj23eb2fd2005-04-22 16:29:19 +00001488 while (True) {
njn1d0825f2006-03-27 11:37:07 +00001489 if (lenA < 8) break;
1490 PROF_EVENT(157, "set_address_range_perms-loop8a");
1491 sm_off16 = SM_OFF_16(a);
1492 ((UShort*)(sm->vabits8))[sm_off16] = vabits16;
1493 a += 8;
1494 lenA -= 8;
1495 }
1496 // 1 byte steps
1497 while (True) {
1498 if (lenA < 1) break;
1499 PROF_EVENT(158, "set_address_range_perms-loop1b");
1500 sm_off = SM_OFF(a);
1501 insert_vabits2_into_vabits8( a, vabits2, &(sm->vabits8[sm_off]) );
1502 a += 1;
1503 lenA -= 1;
sewardj23eb2fd2005-04-22 16:29:19 +00001504 }
1505
njn1d0825f2006-03-27 11:37:07 +00001506 // We've finished the first sec-map. Is that it?
1507 if (lenB == 0)
sewardj23eb2fd2005-04-22 16:29:19 +00001508 return;
1509
njn1d0825f2006-03-27 11:37:07 +00001510 //------------------------------------------------------------------------
1511 // Part 2: Fast-set entire sec-maps at a time.
1512 //------------------------------------------------------------------------
1513 part2:
1514 // 64KB-aligned, 64KB steps.
1515 // Nb: we can reach here with lenB < SM_SIZE
njn4c245e52009-03-15 23:25:38 +00001516 tl_assert(0 == lenA);
sewardj23eb2fd2005-04-22 16:29:19 +00001517 while (True) {
njn1d0825f2006-03-27 11:37:07 +00001518 if (lenB < SM_SIZE) break;
1519 tl_assert(is_start_of_sm(a));
1520 PROF_EVENT(159, "set_address_range_perms-loop64K");
1521 sm_ptr = get_secmap_ptr(a);
1522 if (!is_distinguished_sm(*sm_ptr)) {
1523 PROF_EVENT(160, "set_address_range_perms-loop64K-free-dist-sm");
1524 // Free the non-distinguished sec-map that we're replacing. This
1525 // case happens moderately often, enough to be worthwhile.
philippe37725662012-05-13 22:58:09 +00001526 SysRes sres = VG_(am_munmap_valgrind)((Addr)*sm_ptr, sizeof(SecMap));
1527 tl_assert2(! sr_isError(sres), "SecMap valgrind munmap failure\n");
njn1d0825f2006-03-27 11:37:07 +00001528 }
1529 update_SM_counts(*sm_ptr, example_dsm);
1530 // Make the sec-map entry point to the example DSM
1531 *sm_ptr = example_dsm;
1532 lenB -= SM_SIZE;
1533 a += SM_SIZE;
1534 }
sewardj23eb2fd2005-04-22 16:29:19 +00001535
njn1d0825f2006-03-27 11:37:07 +00001536 // We've finished the whole sec-maps. Is that it?
1537 if (lenB == 0)
1538 return;
1539
1540 //------------------------------------------------------------------------
1541 // Part 3: Finish off the final partial sec-map, if necessary.
1542 //------------------------------------------------------------------------
1543
1544 tl_assert(is_start_of_sm(a) && lenB < SM_SIZE);
1545
1546 // If it's distinguished, make it undistinguished if necessary.
1547 sm_ptr = get_secmap_ptr(a);
1548 if (is_distinguished_sm(*sm_ptr)) {
1549 if (*sm_ptr == example_dsm) {
1550 // Sec-map already has the V+A bits that we want, so stop.
1551 PROF_EVENT(161, "set_address_range_perms-dist-sm2-quick");
1552 return;
1553 } else {
1554 PROF_EVENT(162, "set_address_range_perms-dist-sm2");
1555 *sm_ptr = copy_for_writing(*sm_ptr);
1556 }
1557 }
1558 sm = *sm_ptr;
1559
1560 // 8-aligned, 8 byte steps
1561 while (True) {
1562 if (lenB < 8) break;
1563 PROF_EVENT(163, "set_address_range_perms-loop8b");
1564 sm_off16 = SM_OFF_16(a);
1565 ((UShort*)(sm->vabits8))[sm_off16] = vabits16;
1566 a += 8;
1567 lenB -= 8;
1568 }
1569 // 1 byte steps
1570 while (True) {
1571 if (lenB < 1) return;
1572 PROF_EVENT(164, "set_address_range_perms-loop1c");
1573 sm_off = SM_OFF(a);
1574 insert_vabits2_into_vabits8( a, vabits2, &(sm->vabits8[sm_off]) );
1575 a += 1;
1576 lenB -= 1;
1577 }
sewardj23eb2fd2005-04-22 16:29:19 +00001578}
sewardj45d94cc2005-04-20 14:44:11 +00001579
sewardjc859fbf2005-04-22 21:10:28 +00001580
1581/* --- Set permissions for arbitrary address ranges --- */
njn25e49d8e72002-09-23 09:36:25 +00001582
njndbf7ca72006-03-31 11:57:59 +00001583void MC_(make_mem_noaccess) ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +00001584{
njndbf7ca72006-03-31 11:57:59 +00001585 PROF_EVENT(40, "MC_(make_mem_noaccess)");
1586 DEBUG("MC_(make_mem_noaccess)(%p, %lu)\n", a, len);
njn1d0825f2006-03-27 11:37:07 +00001587 set_address_range_perms ( a, len, VA_BITS16_NOACCESS, SM_DIST_NOACCESS );
sewardj7cf4e6b2008-05-01 20:24:26 +00001588 if (UNLIKELY( MC_(clo_mc_level) == 3 ))
1589 ocache_sarp_Clear_Origins ( a, len );
njn25e49d8e72002-09-23 09:36:25 +00001590}
1591
sewardj7cf4e6b2008-05-01 20:24:26 +00001592static void make_mem_undefined ( Addr a, SizeT len )
1593{
1594 PROF_EVENT(41, "make_mem_undefined");
1595 DEBUG("make_mem_undefined(%p, %lu)\n", a, len);
1596 set_address_range_perms ( a, len, VA_BITS16_UNDEFINED, SM_DIST_UNDEFINED );
1597}
1598
1599void MC_(make_mem_undefined_w_otag) ( Addr a, SizeT len, UInt otag )
njn25e49d8e72002-09-23 09:36:25 +00001600{
njndbf7ca72006-03-31 11:57:59 +00001601 PROF_EVENT(41, "MC_(make_mem_undefined)");
1602 DEBUG("MC_(make_mem_undefined)(%p, %lu)\n", a, len);
1603 set_address_range_perms ( a, len, VA_BITS16_UNDEFINED, SM_DIST_UNDEFINED );
sewardj7cf4e6b2008-05-01 20:24:26 +00001604 if (UNLIKELY( MC_(clo_mc_level) == 3 ))
1605 ocache_sarp_Set_Origins ( a, len, otag );
njn25e49d8e72002-09-23 09:36:25 +00001606}
1607
sewardj7cf4e6b2008-05-01 20:24:26 +00001608static
1609void make_mem_undefined_w_tid_and_okind ( Addr a, SizeT len,
1610 ThreadId tid, UInt okind )
1611{
1612 UInt ecu;
1613 ExeContext* here;
1614 /* VG_(record_ExeContext) checks for validity of tid, and asserts
1615 if it is invalid. So no need to do it here. */
1616 tl_assert(okind <= 3);
1617 here = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ );
1618 tl_assert(here);
1619 ecu = VG_(get_ECU_from_ExeContext)(here);
1620 tl_assert(VG_(is_plausible_ECU)(ecu));
1621 MC_(make_mem_undefined_w_otag) ( a, len, ecu | okind );
1622}
1623
1624static
philippe5db022b2013-01-13 15:01:21 +00001625void mc_new_mem_w_tid_make_ECU ( Addr a, SizeT len, ThreadId tid )
1626{
sewardj7cf4e6b2008-05-01 20:24:26 +00001627 make_mem_undefined_w_tid_and_okind ( a, len, tid, MC_OKIND_UNKNOWN );
1628}
1629
philippe5db022b2013-01-13 15:01:21 +00001630static
1631void mc_new_mem_w_tid_no_ECU ( Addr a, SizeT len, ThreadId tid )
1632{
1633 MC_(make_mem_undefined_w_otag) ( a, len, MC_OKIND_UNKNOWN );
1634}
sewardj7cf4e6b2008-05-01 20:24:26 +00001635
njndbf7ca72006-03-31 11:57:59 +00001636void MC_(make_mem_defined) ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +00001637{
njndbf7ca72006-03-31 11:57:59 +00001638 PROF_EVENT(42, "MC_(make_mem_defined)");
1639 DEBUG("MC_(make_mem_defined)(%p, %lu)\n", a, len);
1640 set_address_range_perms ( a, len, VA_BITS16_DEFINED, SM_DIST_DEFINED );
sewardj7cf4e6b2008-05-01 20:24:26 +00001641 if (UNLIKELY( MC_(clo_mc_level) == 3 ))
1642 ocache_sarp_Clear_Origins ( a, len );
njn25e49d8e72002-09-23 09:36:25 +00001643}
1644
sewardjfb1e9ad2006-03-10 13:41:58 +00001645/* For each byte in [a,a+len), if the byte is addressable, make it be
1646 defined, but if it isn't addressible, leave it alone. In other
njndbf7ca72006-03-31 11:57:59 +00001647 words a version of MC_(make_mem_defined) that doesn't mess with
sewardjfb1e9ad2006-03-10 13:41:58 +00001648 addressibility. Low-performance implementation. */
njndbf7ca72006-03-31 11:57:59 +00001649static void make_mem_defined_if_addressable ( Addr a, SizeT len )
sewardjfb1e9ad2006-03-10 13:41:58 +00001650{
1651 SizeT i;
njn1d0825f2006-03-27 11:37:07 +00001652 UChar vabits2;
njndbf7ca72006-03-31 11:57:59 +00001653 DEBUG("make_mem_defined_if_addressable(%p, %llu)\n", a, (ULong)len);
sewardjfb1e9ad2006-03-10 13:41:58 +00001654 for (i = 0; i < len; i++) {
njn1d0825f2006-03-27 11:37:07 +00001655 vabits2 = get_vabits2( a+i );
bart5dd8e6a2008-03-22 08:04:29 +00001656 if (LIKELY(VA_BITS2_NOACCESS != vabits2)) {
njndbf7ca72006-03-31 11:57:59 +00001657 set_vabits2(a+i, VA_BITS2_DEFINED);
sewardj7cf4e6b2008-05-01 20:24:26 +00001658 if (UNLIKELY(MC_(clo_mc_level) >= 3)) {
1659 MC_(helperc_b_store1)( a+i, 0 ); /* clear the origin tag */
1660 }
njn1d0825f2006-03-27 11:37:07 +00001661 }
sewardjfb1e9ad2006-03-10 13:41:58 +00001662 }
1663}
1664
sewardj6f95e7e2010-01-27 10:28:00 +00001665/* Similarly (needed for mprotect handling ..) */
1666static void make_mem_defined_if_noaccess ( Addr a, SizeT len )
1667{
1668 SizeT i;
1669 UChar vabits2;
1670 DEBUG("make_mem_defined_if_noaccess(%p, %llu)\n", a, (ULong)len);
1671 for (i = 0; i < len; i++) {
1672 vabits2 = get_vabits2( a+i );
1673 if (LIKELY(VA_BITS2_NOACCESS == vabits2)) {
1674 set_vabits2(a+i, VA_BITS2_DEFINED);
1675 if (UNLIKELY(MC_(clo_mc_level) >= 3)) {
1676 MC_(helperc_b_store1)( a+i, 0 ); /* clear the origin tag */
1677 }
1678 }
1679 }
1680}
njn9b007f62003-04-07 14:40:25 +00001681
sewardj45f4e7c2005-09-27 19:20:21 +00001682/* --- Block-copy permissions (needed for implementing realloc() and
1683 sys_mremap). --- */
sewardjc859fbf2005-04-22 21:10:28 +00001684
njn1d0825f2006-03-27 11:37:07 +00001685void MC_(copy_address_range_state) ( Addr src, Addr dst, SizeT len )
sewardjc859fbf2005-04-22 21:10:28 +00001686{
sewardj45f4e7c2005-09-27 19:20:21 +00001687 SizeT i, j;
sewardjf2184912006-05-03 22:13:57 +00001688 UChar vabits2, vabits8;
1689 Bool aligned, nooverlap;
sewardjc859fbf2005-04-22 21:10:28 +00001690
njn1d0825f2006-03-27 11:37:07 +00001691 DEBUG("MC_(copy_address_range_state)\n");
1692 PROF_EVENT(50, "MC_(copy_address_range_state)");
sewardj45f4e7c2005-09-27 19:20:21 +00001693
sewardjf2184912006-05-03 22:13:57 +00001694 if (len == 0 || src == dst)
sewardj45f4e7c2005-09-27 19:20:21 +00001695 return;
1696
sewardjf2184912006-05-03 22:13:57 +00001697 aligned = VG_IS_4_ALIGNED(src) && VG_IS_4_ALIGNED(dst);
1698 nooverlap = src+len <= dst || dst+len <= src;
sewardj45f4e7c2005-09-27 19:20:21 +00001699
sewardjf2184912006-05-03 22:13:57 +00001700 if (nooverlap && aligned) {
1701
1702 /* Vectorised fast case, when no overlap and suitably aligned */
1703 /* vector loop */
1704 i = 0;
1705 while (len >= 4) {
1706 vabits8 = get_vabits8_for_aligned_word32( src+i );
1707 set_vabits8_for_aligned_word32( dst+i, vabits8 );
bart5dd8e6a2008-03-22 08:04:29 +00001708 if (LIKELY(VA_BITS8_DEFINED == vabits8
sewardjf2184912006-05-03 22:13:57 +00001709 || VA_BITS8_UNDEFINED == vabits8
1710 || VA_BITS8_NOACCESS == vabits8)) {
1711 /* do nothing */
1712 } else {
1713 /* have to copy secondary map info */
1714 if (VA_BITS2_PARTDEFINED == get_vabits2( src+i+0 ))
1715 set_sec_vbits8( dst+i+0, get_sec_vbits8( src+i+0 ) );
1716 if (VA_BITS2_PARTDEFINED == get_vabits2( src+i+1 ))
1717 set_sec_vbits8( dst+i+1, get_sec_vbits8( src+i+1 ) );
1718 if (VA_BITS2_PARTDEFINED == get_vabits2( src+i+2 ))
1719 set_sec_vbits8( dst+i+2, get_sec_vbits8( src+i+2 ) );
1720 if (VA_BITS2_PARTDEFINED == get_vabits2( src+i+3 ))
1721 set_sec_vbits8( dst+i+3, get_sec_vbits8( src+i+3 ) );
1722 }
1723 i += 4;
1724 len -= 4;
1725 }
1726 /* fixup loop */
1727 while (len >= 1) {
njn1d0825f2006-03-27 11:37:07 +00001728 vabits2 = get_vabits2( src+i );
1729 set_vabits2( dst+i, vabits2 );
njndbf7ca72006-03-31 11:57:59 +00001730 if (VA_BITS2_PARTDEFINED == vabits2) {
njn1d0825f2006-03-27 11:37:07 +00001731 set_sec_vbits8( dst+i, get_sec_vbits8( src+i ) );
1732 }
sewardjf2184912006-05-03 22:13:57 +00001733 i++;
1734 len--;
1735 }
1736
1737 } else {
1738
1739 /* We have to do things the slow way */
1740 if (src < dst) {
1741 for (i = 0, j = len-1; i < len; i++, j--) {
1742 PROF_EVENT(51, "MC_(copy_address_range_state)(loop)");
1743 vabits2 = get_vabits2( src+j );
1744 set_vabits2( dst+j, vabits2 );
1745 if (VA_BITS2_PARTDEFINED == vabits2) {
1746 set_sec_vbits8( dst+j, get_sec_vbits8( src+j ) );
1747 }
1748 }
1749 }
1750
1751 if (src > dst) {
1752 for (i = 0; i < len; i++) {
1753 PROF_EVENT(52, "MC_(copy_address_range_state)(loop)");
1754 vabits2 = get_vabits2( src+i );
1755 set_vabits2( dst+i, vabits2 );
1756 if (VA_BITS2_PARTDEFINED == vabits2) {
1757 set_sec_vbits8( dst+i, get_sec_vbits8( src+i ) );
1758 }
1759 }
sewardj45f4e7c2005-09-27 19:20:21 +00001760 }
sewardjc859fbf2005-04-22 21:10:28 +00001761 }
sewardjf2184912006-05-03 22:13:57 +00001762
sewardjc859fbf2005-04-22 21:10:28 +00001763}
1764
1765
sewardj7cf4e6b2008-05-01 20:24:26 +00001766/*------------------------------------------------------------*/
1767/*--- Origin tracking stuff - cache basics ---*/
1768/*------------------------------------------------------------*/
sewardjc859fbf2005-04-22 21:10:28 +00001769
sewardj77139802008-05-05 09:48:56 +00001770/* AN OVERVIEW OF THE ORIGIN TRACKING IMPLEMENTATION
1771 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sewardj7cf4e6b2008-05-01 20:24:26 +00001772
1773 Note that this implementation draws inspiration from the "origin
1774 tracking by value piggybacking" scheme described in "Tracking Bad
1775 Apples: Reporting the Origin of Null and Undefined Value Errors"
1776 (Michael Bond, Nicholas Nethercote, Stephen Kent, Samuel Guyer,
1777 Kathryn McKinley, OOPSLA07, Montreal, Oct 2007) but in fact it is
1778 implemented completely differently.
1779
sewardj77139802008-05-05 09:48:56 +00001780 Origin tags and ECUs -- about the shadow values
1781 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1782
1783 This implementation tracks the defining point of all uninitialised
1784 values using so called "origin tags", which are 32-bit integers,
1785 rather than using the values themselves to encode the origins. The
1786 latter, so-called value piggybacking", is what the OOPSLA07 paper
sewardj7cf4e6b2008-05-01 20:24:26 +00001787 describes.
1788
1789 Origin tags, as tracked by the machinery below, are 32-bit unsigned
sewardj77139802008-05-05 09:48:56 +00001790 ints (UInts), regardless of the machine's word size. Each tag
1791 comprises an upper 30-bit ECU field and a lower 2-bit
1792 'kind' field. The ECU field is a number given out by m_execontext
1793 and has a 1-1 mapping with ExeContext*s. An ECU can be used
1794 directly as an origin tag (otag), but in fact we want to put
1795 additional information 'kind' field to indicate roughly where the
1796 tag came from. This helps print more understandable error messages
1797 for the user -- it has no other purpose. In summary:
1798
1799 * Both ECUs and origin tags are represented as 32-bit words
1800
1801 * m_execontext and the core-tool interface deal purely in ECUs.
1802 They have no knowledge of origin tags - that is a purely
1803 Memcheck-internal matter.
1804
1805 * all valid ECUs have the lowest 2 bits zero and at least
1806 one of the upper 30 bits nonzero (see VG_(is_plausible_ECU))
1807
1808 * to convert from an ECU to an otag, OR in one of the MC_OKIND_
1809 constants defined in mc_include.h.
1810
1811 * to convert an otag back to an ECU, AND it with ~3
1812
1813 One important fact is that no valid otag is zero. A zero otag is
1814 used by the implementation to indicate "no origin", which could
1815 mean that either the value is defined, or it is undefined but the
1816 implementation somehow managed to lose the origin.
1817
1818 The ECU used for memory created by malloc etc is derived from the
1819 stack trace at the time the malloc etc happens. This means the
1820 mechanism can show the exact allocation point for heap-created
1821 uninitialised values.
1822
1823 In contrast, it is simply too expensive to create a complete
1824 backtrace for each stack allocation. Therefore we merely use a
1825 depth-1 backtrace for stack allocations, which can be done once at
1826 translation time, rather than N times at run time. The result of
1827 this is that, for stack created uninitialised values, Memcheck can
1828 only show the allocating function, and not what called it.
1829 Furthermore, compilers tend to move the stack pointer just once at
1830 the start of the function, to allocate all locals, and so in fact
1831 the stack origin almost always simply points to the opening brace
1832 of the function. Net result is, for stack origins, the mechanism
1833 can tell you in which function the undefined value was created, but
1834 that's all. Users will need to carefully check all locals in the
1835 specified function.
1836
1837 Shadowing registers and memory
1838 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1839
1840 Memory is shadowed using a two level cache structure (ocacheL1 and
1841 ocacheL2). Memory references are first directed to ocacheL1. This
1842 is a traditional 2-way set associative cache with 32-byte lines and
1843 approximate LRU replacement within each set.
1844
1845 A naive implementation would require storing one 32 bit otag for
1846 each byte of memory covered, a 4:1 space overhead. Instead, there
1847 is one otag for every 4 bytes of memory covered, plus a 4-bit mask
1848 that shows which of the 4 bytes have that shadow value and which
1849 have a shadow value of zero (indicating no origin). Hence a lot of
1850 space is saved, but the cost is that only one different origin per
1851 4 bytes of address space can be represented. This is a source of
1852 imprecision, but how much of a problem it really is remains to be
1853 seen.
1854
1855 A cache line that contains all zeroes ("no origins") contains no
1856 useful information, and can be ejected from the L1 cache "for
1857 free", in the sense that a read miss on the L1 causes a line of
1858 zeroes to be installed. However, ejecting a line containing
1859 nonzeroes risks losing origin information permanently. In order to
1860 prevent such lossage, ejected nonzero lines are placed in a
1861 secondary cache (ocacheL2), which is an OSet (AVL tree) of cache
1862 lines. This can grow arbitrarily large, and so should ensure that
1863 Memcheck runs out of memory in preference to losing useful origin
1864 info due to cache size limitations.
1865
1866 Shadowing registers is a bit tricky, because the shadow values are
1867 32 bits, regardless of the size of the register. That gives a
1868 problem for registers smaller than 32 bits. The solution is to
1869 find spaces in the guest state that are unused, and use those to
1870 shadow guest state fragments smaller than 32 bits. For example, on
1871 ppc32/64, each vector register is 16 bytes long. If 4 bytes of the
1872 shadow are allocated for the register's otag, then there are still
1873 12 bytes left over which could be used to shadow 3 other values.
1874
1875 This implies there is some non-obvious mapping from guest state
1876 (start,length) pairs to the relevant shadow offset (for the origin
1877 tags). And it is unfortunately guest-architecture specific. The
1878 mapping is contained in mc_machine.c, which is quite lengthy but
1879 straightforward.
1880
1881 Instrumenting the IR
1882 ~~~~~~~~~~~~~~~~~~~~
1883
1884 Instrumentation is largely straightforward, and done by the
1885 functions schemeE and schemeS in mc_translate.c. These generate
1886 code for handling the origin tags of expressions (E) and statements
1887 (S) respectively. The rather strange names are a reference to the
1888 "compilation schemes" shown in Simon Peyton Jones' book "The
1889 Implementation of Functional Programming Languages" (Prentice Hall,
1890 1987, see
1891 http://research.microsoft.com/~simonpj/papers/slpj-book-1987/index.htm).
1892
1893 schemeS merely arranges to move shadow values around the guest
1894 state to track the incoming IR. schemeE is largely trivial too.
1895 The only significant point is how to compute the otag corresponding
1896 to binary (or ternary, quaternary, etc) operator applications. The
1897 rule is simple: just take whichever value is larger (32-bit
1898 unsigned max). Constants get the special value zero. Hence this
1899 rule always propagates a nonzero (known) otag in preference to a
1900 zero (unknown, or more likely, value-is-defined) tag, as we want.
1901 If two different undefined values are inputs to a binary operator
1902 application, then which is propagated is arbitrary, but that
1903 doesn't matter, since the program is erroneous in using either of
1904 the values, and so there's no point in attempting to propagate
1905 both.
1906
1907 Since constants are abstracted to (otag) zero, much of the
1908 instrumentation code can be folded out without difficulty by the
1909 generic post-instrumentation IR cleanup pass, using these rules:
1910 Max32U(0,x) -> x, Max32U(x,0) -> x, Max32(x,y) where x and y are
1911 constants is evaluated at JIT time. And the resulting dead code
1912 removal. In practice this causes surprisingly few Max32Us to
1913 survive through to backend code generation.
1914
1915 Integration with the V-bits machinery
1916 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1917
1918 This is again largely straightforward. Mostly the otag and V bits
1919 stuff are independent. The only point of interaction is when the V
1920 bits instrumenter creates a call to a helper function to report an
1921 uninitialised value error -- in that case it must first use schemeE
1922 to get hold of the origin tag expression for the value, and pass
1923 that to the helper too.
1924
1925 There is the usual stuff to do with setting address range
1926 permissions. When memory is painted undefined, we must also know
1927 the origin tag to paint with, which involves some tedious plumbing,
1928 particularly to do with the fast case stack handlers. When memory
1929 is painted defined or noaccess then the origin tags must be forced
1930 to zero.
1931
1932 One of the goals of the implementation was to ensure that the
1933 non-origin tracking mode isn't slowed down at all. To do this,
1934 various functions to do with memory permissions setting (again,
1935 mostly pertaining to the stack) are duplicated for the with- and
1936 without-otag case.
1937
1938 Dealing with stack redzones, and the NIA cache
1939 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1940
1941 This is one of the few non-obvious parts of the implementation.
1942
1943 Some ABIs (amd64-ELF, ppc64-ELF, ppc32/64-XCOFF) define a small
1944 reserved area below the stack pointer, that can be used as scratch
1945 space by compiler generated code for functions. In the Memcheck
1946 sources this is referred to as the "stack redzone". The important
1947 thing here is that such redzones are considered volatile across
1948 function calls and returns. So Memcheck takes care to mark them as
1949 undefined for each call and return, on the afflicted platforms.
1950 Past experience shows this is essential in order to get reliable
1951 messages about uninitialised values that come from the stack.
1952
1953 So the question is, when we paint a redzone undefined, what origin
1954 tag should we use for it? Consider a function f() calling g(). If
1955 we paint the redzone using an otag derived from the ExeContext of
1956 the CALL/BL instruction in f, then any errors in g causing it to
1957 use uninitialised values that happen to lie in the redzone, will be
1958 reported as having their origin in f. Which is highly confusing.
1959
1960 The same applies for returns: if, on a return, we paint the redzone
1961 using a origin tag derived from the ExeContext of the RET/BLR
1962 instruction in g, then any later errors in f causing it to use
1963 uninitialised values in the redzone, will be reported as having
1964 their origin in g. Which is just as confusing.
1965
1966 To do it right, in both cases we need to use an origin tag which
1967 pertains to the instruction which dynamically follows the CALL/BL
1968 or RET/BLR. In short, one derived from the NIA - the "next
1969 instruction address".
1970
1971 To make this work, Memcheck's redzone-painting helper,
1972 MC_(helperc_MAKE_STACK_UNINIT), now takes a third argument, the
1973 NIA. It converts the NIA to a 1-element ExeContext, and uses that
1974 ExeContext's ECU as the basis for the otag used to paint the
1975 redzone. The expensive part of this is converting an NIA into an
1976 ECU, since this happens once for every call and every return. So
1977 we use a simple 511-line, 2-way set associative cache
1978 (nia_to_ecu_cache) to cache the mappings, and that knocks most of
1979 the cost out.
1980
1981 Further background comments
1982 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
sewardj7cf4e6b2008-05-01 20:24:26 +00001983
1984 > Question: why is otag a UInt? Wouldn't a UWord be better? Isn't
1985 > it really just the address of the relevant ExeContext?
1986
1987 Well, it's not the address, but a value which has a 1-1 mapping
1988 with ExeContexts, and is guaranteed not to be zero, since zero
1989 denotes (to memcheck) "unknown origin or defined value". So these
sewardj77139802008-05-05 09:48:56 +00001990 UInts are just numbers starting at 4 and incrementing by 4; each
1991 ExeContext is given a number when it is created. (*** NOTE this
1992 confuses otags and ECUs; see comments above ***).
sewardj7cf4e6b2008-05-01 20:24:26 +00001993
1994 Making these otags 32-bit regardless of the machine's word size
1995 makes the 64-bit implementation easier (next para). And it doesn't
1996 really limit us in any way, since for the tags to overflow would
sewardj77139802008-05-05 09:48:56 +00001997 require that the program somehow caused 2^30-1 different
sewardj7cf4e6b2008-05-01 20:24:26 +00001998 ExeContexts to be created, in which case it is probably in deep
1999 trouble. Not to mention V will have soaked up many tens of
2000 gigabytes of memory merely to store them all.
2001
2002 So having 64-bit origins doesn't really buy you anything, and has
2003 the following downsides:
2004
2005 Suppose that instead, an otag is a UWord. This would mean that, on
2006 a 64-bit target,
2007
2008 1. It becomes hard to shadow any element of guest state which is
2009 smaller than 8 bytes. To do so means you'd need to find some
2010 8-byte-sized hole in the guest state which you don't want to
2011 shadow, and use that instead to hold the otag. On ppc64, the
2012 condition code register(s) are split into 20 UChar sized pieces,
2013 all of which need to be tracked (guest_XER_SO .. guest_CR7_0)
2014 and so that would entail finding 160 bytes somewhere else in the
2015 guest state.
2016
2017 Even on x86, I want to track origins for %AH .. %DH (bits 15:8
2018 of %EAX .. %EDX) that are separate from %AL .. %DL (bits 7:0 of
2019 same) and so I had to look for 4 untracked otag-sized areas in
2020 the guest state to make that possible.
2021
2022 The same problem exists of course when origin tags are only 32
2023 bits, but it's less extreme.
2024
2025 2. (More compelling) it doubles the size of the origin shadow
2026 memory. Given that the shadow memory is organised as a fixed
2027 size cache, and that accuracy of tracking is limited by origins
2028 falling out the cache due to space conflicts, this isn't good.
2029
2030 > Another question: is the origin tracking perfect, or are there
2031 > cases where it fails to determine an origin?
2032
2033 It is imperfect for at least for the following reasons, and
2034 probably more:
2035
2036 * Insufficient capacity in the origin cache. When a line is
2037 evicted from the cache it is gone forever, and so subsequent
2038 queries for the line produce zero, indicating no origin
2039 information. Interestingly, a line containing all zeroes can be
2040 evicted "free" from the cache, since it contains no useful
2041 information, so there is scope perhaps for some cleverer cache
sewardj77139802008-05-05 09:48:56 +00002042 management schemes. (*** NOTE, with the introduction of the
2043 second level origin tag cache, ocacheL2, this is no longer a
2044 problem. ***)
sewardj7cf4e6b2008-05-01 20:24:26 +00002045
2046 * The origin cache only stores one otag per 32-bits of address
2047 space, plus 4 bits indicating which of the 4 bytes has that tag
2048 and which are considered defined. The result is that if two
2049 undefined bytes in the same word are stored in memory, the first
2050 stored byte's origin will be lost and replaced by the origin for
2051 the second byte.
2052
2053 * Nonzero origin tags for defined values. Consider a binary
2054 operator application op(x,y). Suppose y is undefined (and so has
2055 a valid nonzero origin tag), and x is defined, but erroneously
2056 has a nonzero origin tag (defined values should have tag zero).
2057 If the erroneous tag has a numeric value greater than y's tag,
2058 then the rule for propagating origin tags though binary
2059 operations, which is simply to take the unsigned max of the two
2060 tags, will erroneously propagate x's tag rather than y's.
2061
2062 * Some obscure uses of x86/amd64 byte registers can cause lossage
2063 or confusion of origins. %AH .. %DH are treated as different
2064 from, and unrelated to, their parent registers, %EAX .. %EDX.
2065 So some wierd sequences like
2066
2067 movb undefined-value, %AH
2068 movb defined-value, %AL
2069 .. use %AX or %EAX ..
2070
2071 will cause the origin attributed to %AH to be ignored, since %AL,
2072 %AX, %EAX are treated as the same register, and %AH as a
2073 completely separate one.
2074
2075 But having said all that, it actually seems to work fairly well in
2076 practice.
2077*/
2078
2079static UWord stats_ocacheL1_find = 0;
2080static UWord stats_ocacheL1_found_at_1 = 0;
2081static UWord stats_ocacheL1_found_at_N = 0;
2082static UWord stats_ocacheL1_misses = 0;
2083static UWord stats_ocacheL1_lossage = 0;
2084static UWord stats_ocacheL1_movefwds = 0;
2085
2086static UWord stats__ocacheL2_refs = 0;
2087static UWord stats__ocacheL2_misses = 0;
2088static UWord stats__ocacheL2_n_nodes_max = 0;
2089
2090/* Cache of 32-bit values, one every 32 bits of address space */
2091
2092#define OC_BITS_PER_LINE 5
2093#define OC_W32S_PER_LINE (1 << (OC_BITS_PER_LINE - 2))
2094
2095static INLINE UWord oc_line_offset ( Addr a ) {
2096 return (a >> 2) & (OC_W32S_PER_LINE - 1);
2097}
2098static INLINE Bool is_valid_oc_tag ( Addr tag ) {
2099 return 0 == (tag & ((1 << OC_BITS_PER_LINE) - 1));
2100}
2101
2102#define OC_LINES_PER_SET 2
2103
2104#define OC_N_SET_BITS 20
2105#define OC_N_SETS (1 << OC_N_SET_BITS)
2106
2107/* These settings give:
2108 64 bit host: ocache: 100,663,296 sizeB 67,108,864 useful
2109 32 bit host: ocache: 92,274,688 sizeB 67,108,864 useful
2110*/
2111
2112#define OC_MOVE_FORWARDS_EVERY_BITS 7
2113
2114
2115typedef
2116 struct {
2117 Addr tag;
2118 UInt w32[OC_W32S_PER_LINE];
2119 UChar descr[OC_W32S_PER_LINE];
2120 }
2121 OCacheLine;
2122
2123/* Classify and also sanity-check 'line'. Return 'e' (empty) if not
2124 in use, 'n' (nonzero) if it contains at least one valid origin tag,
2125 and 'z' if all the represented tags are zero. */
2126static UChar classify_OCacheLine ( OCacheLine* line )
2127{
2128 UWord i;
2129 if (line->tag == 1/*invalid*/)
2130 return 'e'; /* EMPTY */
2131 tl_assert(is_valid_oc_tag(line->tag));
2132 for (i = 0; i < OC_W32S_PER_LINE; i++) {
2133 tl_assert(0 == ((~0xF) & line->descr[i]));
2134 if (line->w32[i] > 0 && line->descr[i] > 0)
2135 return 'n'; /* NONZERO - contains useful info */
2136 }
2137 return 'z'; /* ZERO - no useful info */
2138}
2139
2140typedef
2141 struct {
2142 OCacheLine line[OC_LINES_PER_SET];
2143 }
2144 OCacheSet;
2145
2146typedef
2147 struct {
2148 OCacheSet set[OC_N_SETS];
2149 }
2150 OCache;
2151
sewardj77139802008-05-05 09:48:56 +00002152static OCache* ocacheL1 = NULL;
2153static UWord ocacheL1_event_ctr = 0;
sewardj7cf4e6b2008-05-01 20:24:26 +00002154
2155static void init_ocacheL2 ( void ); /* fwds */
2156static void init_OCache ( void )
2157{
2158 UWord line, set;
sewardj9d624d12008-05-02 13:35:29 +00002159 tl_assert(MC_(clo_mc_level) >= 3);
sewardj77139802008-05-05 09:48:56 +00002160 tl_assert(ocacheL1 == NULL);
2161 ocacheL1 = VG_(am_shadow_alloc)(sizeof(OCache));
2162 if (ocacheL1 == NULL) {
2163 VG_(out_of_memory_NORETURN)( "memcheck:allocating ocacheL1",
sewardj9d624d12008-05-02 13:35:29 +00002164 sizeof(OCache) );
2165 }
sewardj77139802008-05-05 09:48:56 +00002166 tl_assert(ocacheL1 != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +00002167 for (set = 0; set < OC_N_SETS; set++) {
2168 for (line = 0; line < OC_LINES_PER_SET; line++) {
sewardj77139802008-05-05 09:48:56 +00002169 ocacheL1->set[set].line[line].tag = 1/*invalid*/;
sewardj7cf4e6b2008-05-01 20:24:26 +00002170 }
2171 }
2172 init_ocacheL2();
2173}
2174
2175static void moveLineForwards ( OCacheSet* set, UWord lineno )
2176{
2177 OCacheLine tmp;
2178 stats_ocacheL1_movefwds++;
2179 tl_assert(lineno > 0 && lineno < OC_LINES_PER_SET);
2180 tmp = set->line[lineno-1];
2181 set->line[lineno-1] = set->line[lineno];
2182 set->line[lineno] = tmp;
2183}
2184
2185static void zeroise_OCacheLine ( OCacheLine* line, Addr tag ) {
2186 UWord i;
2187 for (i = 0; i < OC_W32S_PER_LINE; i++) {
2188 line->w32[i] = 0; /* NO ORIGIN */
2189 line->descr[i] = 0; /* REALLY REALLY NO ORIGIN! */
2190 }
2191 line->tag = tag;
2192}
2193
2194//////////////////////////////////////////////////////////////
2195//// OCache backing store
2196
2197static OSet* ocacheL2 = NULL;
2198
florian54fe2022012-10-27 23:07:42 +00002199static void* ocacheL2_malloc ( const HChar* cc, SizeT szB ) {
sewardj9c606bd2008-09-18 18:12:50 +00002200 return VG_(malloc)(cc, szB);
sewardj7cf4e6b2008-05-01 20:24:26 +00002201}
2202static void ocacheL2_free ( void* v ) {
2203 VG_(free)( v );
2204}
2205
2206/* Stats: # nodes currently in tree */
2207static UWord stats__ocacheL2_n_nodes = 0;
2208
2209static void init_ocacheL2 ( void )
2210{
2211 tl_assert(!ocacheL2);
2212 tl_assert(sizeof(Word) == sizeof(Addr)); /* since OCacheLine.tag :: Addr */
2213 tl_assert(0 == offsetof(OCacheLine,tag));
2214 ocacheL2
2215 = VG_(OSetGen_Create)( offsetof(OCacheLine,tag),
2216 NULL, /* fast cmp */
philippe6643e962012-01-17 21:16:30 +00002217 ocacheL2_malloc, "mc.ioL2", ocacheL2_free);
sewardj7cf4e6b2008-05-01 20:24:26 +00002218 tl_assert(ocacheL2);
2219 stats__ocacheL2_n_nodes = 0;
2220}
2221
2222/* Find line with the given tag in the tree, or NULL if not found. */
2223static OCacheLine* ocacheL2_find_tag ( Addr tag )
2224{
2225 OCacheLine* line;
2226 tl_assert(is_valid_oc_tag(tag));
2227 stats__ocacheL2_refs++;
2228 line = VG_(OSetGen_Lookup)( ocacheL2, &tag );
2229 return line;
2230}
2231
2232/* Delete the line with the given tag from the tree, if it is present, and
2233 free up the associated memory. */
2234static void ocacheL2_del_tag ( Addr tag )
2235{
2236 OCacheLine* line;
2237 tl_assert(is_valid_oc_tag(tag));
2238 stats__ocacheL2_refs++;
2239 line = VG_(OSetGen_Remove)( ocacheL2, &tag );
2240 if (line) {
2241 VG_(OSetGen_FreeNode)(ocacheL2, line);
2242 tl_assert(stats__ocacheL2_n_nodes > 0);
2243 stats__ocacheL2_n_nodes--;
2244 }
2245}
2246
2247/* Add a copy of the given line to the tree. It must not already be
2248 present. */
2249static void ocacheL2_add_line ( OCacheLine* line )
2250{
2251 OCacheLine* copy;
2252 tl_assert(is_valid_oc_tag(line->tag));
2253 copy = VG_(OSetGen_AllocNode)( ocacheL2, sizeof(OCacheLine) );
2254 tl_assert(copy);
2255 *copy = *line;
2256 stats__ocacheL2_refs++;
2257 VG_(OSetGen_Insert)( ocacheL2, copy );
2258 stats__ocacheL2_n_nodes++;
2259 if (stats__ocacheL2_n_nodes > stats__ocacheL2_n_nodes_max)
2260 stats__ocacheL2_n_nodes_max = stats__ocacheL2_n_nodes;
2261}
2262
2263////
2264//////////////////////////////////////////////////////////////
2265
2266__attribute__((noinline))
2267static OCacheLine* find_OCacheLine_SLOW ( Addr a )
2268{
2269 OCacheLine *victim, *inL2;
2270 UChar c;
2271 UWord line;
2272 UWord setno = (a >> OC_BITS_PER_LINE) & (OC_N_SETS - 1);
2273 UWord tagmask = ~((1 << OC_BITS_PER_LINE) - 1);
2274 UWord tag = a & tagmask;
2275 tl_assert(setno >= 0 && setno < OC_N_SETS);
2276
2277 /* we already tried line == 0; skip therefore. */
2278 for (line = 1; line < OC_LINES_PER_SET; line++) {
sewardj77139802008-05-05 09:48:56 +00002279 if (ocacheL1->set[setno].line[line].tag == tag) {
sewardj7cf4e6b2008-05-01 20:24:26 +00002280 if (line == 1) {
2281 stats_ocacheL1_found_at_1++;
2282 } else {
2283 stats_ocacheL1_found_at_N++;
2284 }
sewardj77139802008-05-05 09:48:56 +00002285 if (UNLIKELY(0 == (ocacheL1_event_ctr++
sewardj7cf4e6b2008-05-01 20:24:26 +00002286 & ((1<<OC_MOVE_FORWARDS_EVERY_BITS)-1)))) {
sewardj77139802008-05-05 09:48:56 +00002287 moveLineForwards( &ocacheL1->set[setno], line );
sewardj7cf4e6b2008-05-01 20:24:26 +00002288 line--;
2289 }
sewardj77139802008-05-05 09:48:56 +00002290 return &ocacheL1->set[setno].line[line];
sewardj7cf4e6b2008-05-01 20:24:26 +00002291 }
2292 }
2293
2294 /* A miss. Use the last slot. Implicitly this means we're
2295 ejecting the line in the last slot. */
2296 stats_ocacheL1_misses++;
2297 tl_assert(line == OC_LINES_PER_SET);
2298 line--;
2299 tl_assert(line > 0);
2300
2301 /* First, move the to-be-ejected line to the L2 cache. */
sewardj77139802008-05-05 09:48:56 +00002302 victim = &ocacheL1->set[setno].line[line];
sewardj7cf4e6b2008-05-01 20:24:26 +00002303 c = classify_OCacheLine(victim);
2304 switch (c) {
2305 case 'e':
2306 /* the line is empty (has invalid tag); ignore it. */
2307 break;
2308 case 'z':
2309 /* line contains zeroes. We must ensure the backing store is
2310 updated accordingly, either by copying the line there
2311 verbatim, or by ensuring it isn't present there. We
2312 chosse the latter on the basis that it reduces the size of
2313 the backing store. */
2314 ocacheL2_del_tag( victim->tag );
2315 break;
2316 case 'n':
2317 /* line contains at least one real, useful origin. Copy it
2318 to the backing store. */
2319 stats_ocacheL1_lossage++;
2320 inL2 = ocacheL2_find_tag( victim->tag );
2321 if (inL2) {
2322 *inL2 = *victim;
2323 } else {
2324 ocacheL2_add_line( victim );
2325 }
2326 break;
2327 default:
2328 tl_assert(0);
2329 }
2330
2331 /* Now we must reload the L1 cache from the backing tree, if
2332 possible. */
2333 tl_assert(tag != victim->tag); /* stay sane */
2334 inL2 = ocacheL2_find_tag( tag );
2335 if (inL2) {
2336 /* We're in luck. It's in the L2. */
sewardj77139802008-05-05 09:48:56 +00002337 ocacheL1->set[setno].line[line] = *inL2;
sewardj7cf4e6b2008-05-01 20:24:26 +00002338 } else {
2339 /* Missed at both levels of the cache hierarchy. We have to
2340 declare it as full of zeroes (unknown origins). */
2341 stats__ocacheL2_misses++;
sewardj77139802008-05-05 09:48:56 +00002342 zeroise_OCacheLine( &ocacheL1->set[setno].line[line], tag );
sewardj7cf4e6b2008-05-01 20:24:26 +00002343 }
2344
2345 /* Move it one forwards */
sewardj77139802008-05-05 09:48:56 +00002346 moveLineForwards( &ocacheL1->set[setno], line );
sewardj7cf4e6b2008-05-01 20:24:26 +00002347 line--;
2348
sewardj77139802008-05-05 09:48:56 +00002349 return &ocacheL1->set[setno].line[line];
sewardj7cf4e6b2008-05-01 20:24:26 +00002350}
2351
2352static INLINE OCacheLine* find_OCacheLine ( Addr a )
2353{
2354 UWord setno = (a >> OC_BITS_PER_LINE) & (OC_N_SETS - 1);
2355 UWord tagmask = ~((1 << OC_BITS_PER_LINE) - 1);
2356 UWord tag = a & tagmask;
2357
2358 stats_ocacheL1_find++;
2359
2360 if (OC_ENABLE_ASSERTIONS) {
2361 tl_assert(setno >= 0 && setno < OC_N_SETS);
2362 tl_assert(0 == (tag & (4 * OC_W32S_PER_LINE - 1)));
2363 }
2364
sewardj77139802008-05-05 09:48:56 +00002365 if (LIKELY(ocacheL1->set[setno].line[0].tag == tag)) {
2366 return &ocacheL1->set[setno].line[0];
sewardj7cf4e6b2008-05-01 20:24:26 +00002367 }
2368
2369 return find_OCacheLine_SLOW( a );
2370}
2371
2372static INLINE void set_aligned_word64_Origin_to_undef ( Addr a, UInt otag )
2373{
2374 //// BEGIN inlined, specialised version of MC_(helperc_b_store8)
2375 //// Set the origins for a+0 .. a+7
2376 { OCacheLine* line;
2377 UWord lineoff = oc_line_offset(a);
2378 if (OC_ENABLE_ASSERTIONS) {
2379 tl_assert(lineoff >= 0
2380 && lineoff < OC_W32S_PER_LINE -1/*'cos 8-aligned*/);
2381 }
2382 line = find_OCacheLine( a );
2383 line->descr[lineoff+0] = 0xF;
2384 line->descr[lineoff+1] = 0xF;
2385 line->w32[lineoff+0] = otag;
2386 line->w32[lineoff+1] = otag;
2387 }
2388 //// END inlined, specialised version of MC_(helperc_b_store8)
2389}
2390
2391
2392/*------------------------------------------------------------*/
2393/*--- Aligned fast case permission setters, ---*/
2394/*--- for dealing with stacks ---*/
2395/*------------------------------------------------------------*/
2396
2397/*--------------------- 32-bit ---------------------*/
2398
2399/* Nb: by "aligned" here we mean 4-byte aligned */
2400
2401static INLINE void make_aligned_word32_undefined ( Addr a )
njn9b007f62003-04-07 14:40:25 +00002402{
njndbf7ca72006-03-31 11:57:59 +00002403 PROF_EVENT(300, "make_aligned_word32_undefined");
sewardj5d28efc2005-04-21 22:16:29 +00002404
njn1d0825f2006-03-27 11:37:07 +00002405#ifndef PERF_FAST_STACK2
sewardj7cf4e6b2008-05-01 20:24:26 +00002406 make_mem_undefined(a, 4);
njn1d0825f2006-03-27 11:37:07 +00002407#else
njneccf7c02009-01-19 23:42:45 +00002408 {
2409 UWord sm_off;
2410 SecMap* sm;
sewardj5d28efc2005-04-21 22:16:29 +00002411
njneccf7c02009-01-19 23:42:45 +00002412 if (UNLIKELY(a > MAX_PRIMARY_ADDRESS)) {
2413 PROF_EVENT(301, "make_aligned_word32_undefined-slow1");
2414 make_mem_undefined(a, 4);
2415 return;
2416 }
2417
2418 sm = get_secmap_for_writing_low(a);
2419 sm_off = SM_OFF(a);
2420 sm->vabits8[sm_off] = VA_BITS8_UNDEFINED;
2421 }
njn1d0825f2006-03-27 11:37:07 +00002422#endif
njn9b007f62003-04-07 14:40:25 +00002423}
2424
sewardj7cf4e6b2008-05-01 20:24:26 +00002425static INLINE
2426void make_aligned_word32_undefined_w_otag ( Addr a, UInt otag )
2427{
2428 make_aligned_word32_undefined(a);
2429 //// BEGIN inlined, specialised version of MC_(helperc_b_store4)
2430 //// Set the origins for a+0 .. a+3
2431 { OCacheLine* line;
2432 UWord lineoff = oc_line_offset(a);
2433 if (OC_ENABLE_ASSERTIONS) {
2434 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
2435 }
2436 line = find_OCacheLine( a );
2437 line->descr[lineoff] = 0xF;
2438 line->w32[lineoff] = otag;
2439 }
2440 //// END inlined, specialised version of MC_(helperc_b_store4)
2441}
sewardj5d28efc2005-04-21 22:16:29 +00002442
njn1d0825f2006-03-27 11:37:07 +00002443static INLINE
2444void make_aligned_word32_noaccess ( Addr a )
sewardj5d28efc2005-04-21 22:16:29 +00002445{
2446 PROF_EVENT(310, "make_aligned_word32_noaccess");
2447
njn1d0825f2006-03-27 11:37:07 +00002448#ifndef PERF_FAST_STACK2
njndbf7ca72006-03-31 11:57:59 +00002449 MC_(make_mem_noaccess)(a, 4);
njn1d0825f2006-03-27 11:37:07 +00002450#else
njneccf7c02009-01-19 23:42:45 +00002451 {
2452 UWord sm_off;
2453 SecMap* sm;
sewardj5d28efc2005-04-21 22:16:29 +00002454
njneccf7c02009-01-19 23:42:45 +00002455 if (UNLIKELY(a > MAX_PRIMARY_ADDRESS)) {
2456 PROF_EVENT(311, "make_aligned_word32_noaccess-slow1");
2457 MC_(make_mem_noaccess)(a, 4);
2458 return;
sewardj7cf4e6b2008-05-01 20:24:26 +00002459 }
njneccf7c02009-01-19 23:42:45 +00002460
2461 sm = get_secmap_for_writing_low(a);
2462 sm_off = SM_OFF(a);
2463 sm->vabits8[sm_off] = VA_BITS8_NOACCESS;
2464
2465 //// BEGIN inlined, specialised version of MC_(helperc_b_store4)
2466 //// Set the origins for a+0 .. a+3.
2467 if (UNLIKELY( MC_(clo_mc_level) == 3 )) {
2468 OCacheLine* line;
2469 UWord lineoff = oc_line_offset(a);
2470 if (OC_ENABLE_ASSERTIONS) {
2471 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
2472 }
2473 line = find_OCacheLine( a );
2474 line->descr[lineoff] = 0;
2475 }
2476 //// END inlined, specialised version of MC_(helperc_b_store4)
sewardj7cf4e6b2008-05-01 20:24:26 +00002477 }
njn1d0825f2006-03-27 11:37:07 +00002478#endif
sewardj5d28efc2005-04-21 22:16:29 +00002479}
2480
sewardj7cf4e6b2008-05-01 20:24:26 +00002481/*--------------------- 64-bit ---------------------*/
sewardj5d28efc2005-04-21 22:16:29 +00002482
njn9b007f62003-04-07 14:40:25 +00002483/* Nb: by "aligned" here we mean 8-byte aligned */
sewardj7cf4e6b2008-05-01 20:24:26 +00002484
2485static INLINE void make_aligned_word64_undefined ( Addr a )
njn9b007f62003-04-07 14:40:25 +00002486{
njndbf7ca72006-03-31 11:57:59 +00002487 PROF_EVENT(320, "make_aligned_word64_undefined");
sewardj23eb2fd2005-04-22 16:29:19 +00002488
njn1d0825f2006-03-27 11:37:07 +00002489#ifndef PERF_FAST_STACK2
sewardj7cf4e6b2008-05-01 20:24:26 +00002490 make_mem_undefined(a, 8);
njn1d0825f2006-03-27 11:37:07 +00002491#else
njneccf7c02009-01-19 23:42:45 +00002492 {
2493 UWord sm_off16;
2494 SecMap* sm;
sewardj23eb2fd2005-04-22 16:29:19 +00002495
njneccf7c02009-01-19 23:42:45 +00002496 if (UNLIKELY(a > MAX_PRIMARY_ADDRESS)) {
2497 PROF_EVENT(321, "make_aligned_word64_undefined-slow1");
2498 make_mem_undefined(a, 8);
2499 return;
2500 }
2501
2502 sm = get_secmap_for_writing_low(a);
2503 sm_off16 = SM_OFF_16(a);
2504 ((UShort*)(sm->vabits8))[sm_off16] = VA_BITS16_UNDEFINED;
2505 }
njn1d0825f2006-03-27 11:37:07 +00002506#endif
njn9b007f62003-04-07 14:40:25 +00002507}
2508
sewardj7cf4e6b2008-05-01 20:24:26 +00002509static INLINE
2510void make_aligned_word64_undefined_w_otag ( Addr a, UInt otag )
2511{
2512 make_aligned_word64_undefined(a);
2513 //// BEGIN inlined, specialised version of MC_(helperc_b_store8)
2514 //// Set the origins for a+0 .. a+7
2515 { OCacheLine* line;
2516 UWord lineoff = oc_line_offset(a);
2517 tl_assert(lineoff >= 0
2518 && lineoff < OC_W32S_PER_LINE -1/*'cos 8-aligned*/);
2519 line = find_OCacheLine( a );
2520 line->descr[lineoff+0] = 0xF;
2521 line->descr[lineoff+1] = 0xF;
2522 line->w32[lineoff+0] = otag;
2523 line->w32[lineoff+1] = otag;
2524 }
2525 //// END inlined, specialised version of MC_(helperc_b_store8)
2526}
sewardj23eb2fd2005-04-22 16:29:19 +00002527
njn1d0825f2006-03-27 11:37:07 +00002528static INLINE
2529void make_aligned_word64_noaccess ( Addr a )
njn9b007f62003-04-07 14:40:25 +00002530{
sewardj23eb2fd2005-04-22 16:29:19 +00002531 PROF_EVENT(330, "make_aligned_word64_noaccess");
2532
njn1d0825f2006-03-27 11:37:07 +00002533#ifndef PERF_FAST_STACK2
njndbf7ca72006-03-31 11:57:59 +00002534 MC_(make_mem_noaccess)(a, 8);
njn1d0825f2006-03-27 11:37:07 +00002535#else
njneccf7c02009-01-19 23:42:45 +00002536 {
2537 UWord sm_off16;
2538 SecMap* sm;
sewardj23eb2fd2005-04-22 16:29:19 +00002539
njneccf7c02009-01-19 23:42:45 +00002540 if (UNLIKELY(a > MAX_PRIMARY_ADDRESS)) {
2541 PROF_EVENT(331, "make_aligned_word64_noaccess-slow1");
2542 MC_(make_mem_noaccess)(a, 8);
2543 return;
2544 }
sewardj7cf4e6b2008-05-01 20:24:26 +00002545
njneccf7c02009-01-19 23:42:45 +00002546 sm = get_secmap_for_writing_low(a);
2547 sm_off16 = SM_OFF_16(a);
2548 ((UShort*)(sm->vabits8))[sm_off16] = VA_BITS16_NOACCESS;
2549
2550 //// BEGIN inlined, specialised version of MC_(helperc_b_store8)
2551 //// Clear the origins for a+0 .. a+7.
2552 if (UNLIKELY( MC_(clo_mc_level) == 3 )) {
2553 OCacheLine* line;
2554 UWord lineoff = oc_line_offset(a);
2555 tl_assert(lineoff >= 0
2556 && lineoff < OC_W32S_PER_LINE -1/*'cos 8-aligned*/);
2557 line = find_OCacheLine( a );
2558 line->descr[lineoff+0] = 0;
2559 line->descr[lineoff+1] = 0;
2560 }
2561 //// END inlined, specialised version of MC_(helperc_b_store8)
sewardj7cf4e6b2008-05-01 20:24:26 +00002562 }
njn1d0825f2006-03-27 11:37:07 +00002563#endif
njn9b007f62003-04-07 14:40:25 +00002564}
2565
sewardj23eb2fd2005-04-22 16:29:19 +00002566
njn1d0825f2006-03-27 11:37:07 +00002567/*------------------------------------------------------------*/
2568/*--- Stack pointer adjustment ---*/
2569/*------------------------------------------------------------*/
2570
njneccf7c02009-01-19 23:42:45 +00002571#ifdef PERF_FAST_STACK
2572# define MAYBE_USED
2573#else
2574# define MAYBE_USED __attribute__((unused))
2575#endif
2576
sewardj7cf4e6b2008-05-01 20:24:26 +00002577/*--------------- adjustment by 4 bytes ---------------*/
2578
njneccf7c02009-01-19 23:42:45 +00002579MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00002580static void VG_REGPARM(2) mc_new_mem_stack_4_w_ECU(Addr new_SP, UInt ecu)
2581{
2582 UInt otag = ecu | MC_OKIND_STACK;
2583 PROF_EVENT(110, "new_mem_stack_4");
2584 if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2585 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP, otag );
2586 } else {
2587 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 4, otag );
2588 }
2589}
2590
njneccf7c02009-01-19 23:42:45 +00002591MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002592static void VG_REGPARM(1) mc_new_mem_stack_4(Addr new_SP)
2593{
2594 PROF_EVENT(110, "new_mem_stack_4");
sewardj05a46732006-10-17 01:28:10 +00002595 if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00002596 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
njn1d0825f2006-03-27 11:37:07 +00002597 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00002598 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 4 );
njn1d0825f2006-03-27 11:37:07 +00002599 }
2600}
2601
njneccf7c02009-01-19 23:42:45 +00002602MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002603static void VG_REGPARM(1) mc_die_mem_stack_4(Addr new_SP)
2604{
2605 PROF_EVENT(120, "die_mem_stack_4");
sewardj05a46732006-10-17 01:28:10 +00002606 if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00002607 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-4 );
njn1d0825f2006-03-27 11:37:07 +00002608 } else {
njndbf7ca72006-03-31 11:57:59 +00002609 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-4, 4 );
njn1d0825f2006-03-27 11:37:07 +00002610 }
2611}
2612
sewardj7cf4e6b2008-05-01 20:24:26 +00002613/*--------------- adjustment by 8 bytes ---------------*/
2614
njneccf7c02009-01-19 23:42:45 +00002615MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00002616static void VG_REGPARM(2) mc_new_mem_stack_8_w_ECU(Addr new_SP, UInt ecu)
2617{
2618 UInt otag = ecu | MC_OKIND_STACK;
2619 PROF_EVENT(111, "new_mem_stack_8");
2620 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2621 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP, otag );
2622 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2623 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
2624 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+4, otag );
2625 } else {
2626 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 8, otag );
2627 }
2628}
2629
njneccf7c02009-01-19 23:42:45 +00002630MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002631static void VG_REGPARM(1) mc_new_mem_stack_8(Addr new_SP)
2632{
2633 PROF_EVENT(111, "new_mem_stack_8");
sewardj05a46732006-10-17 01:28:10 +00002634 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00002635 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
sewardj05a46732006-10-17 01:28:10 +00002636 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj7cf4e6b2008-05-01 20:24:26 +00002637 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
njndbf7ca72006-03-31 11:57:59 +00002638 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP+4 );
njn1d0825f2006-03-27 11:37:07 +00002639 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00002640 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 8 );
njn1d0825f2006-03-27 11:37:07 +00002641 }
2642}
2643
njneccf7c02009-01-19 23:42:45 +00002644MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002645static void VG_REGPARM(1) mc_die_mem_stack_8(Addr new_SP)
2646{
2647 PROF_EVENT(121, "die_mem_stack_8");
sewardj05a46732006-10-17 01:28:10 +00002648 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00002649 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-8 );
sewardj05a46732006-10-17 01:28:10 +00002650 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00002651 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-8 );
2652 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-4 );
njn1d0825f2006-03-27 11:37:07 +00002653 } else {
njndbf7ca72006-03-31 11:57:59 +00002654 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-8, 8 );
njn1d0825f2006-03-27 11:37:07 +00002655 }
2656}
2657
sewardj7cf4e6b2008-05-01 20:24:26 +00002658/*--------------- adjustment by 12 bytes ---------------*/
2659
njneccf7c02009-01-19 23:42:45 +00002660MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00002661static void VG_REGPARM(2) mc_new_mem_stack_12_w_ECU(Addr new_SP, UInt ecu)
2662{
2663 UInt otag = ecu | MC_OKIND_STACK;
2664 PROF_EVENT(112, "new_mem_stack_12");
2665 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2666 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
2667 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+8, otag );
2668 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2669 /* from previous test we don't have 8-alignment at offset +0,
2670 hence must have 8 alignment at offsets +4/-4. Hence safe to
2671 do 4 at +0 and then 8 at +4/. */
2672 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
2673 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+4, otag );
2674 } else {
2675 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 12, otag );
2676 }
2677}
2678
njneccf7c02009-01-19 23:42:45 +00002679MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002680static void VG_REGPARM(1) mc_new_mem_stack_12(Addr new_SP)
2681{
2682 PROF_EVENT(112, "new_mem_stack_12");
sewardj05a46732006-10-17 01:28:10 +00002683 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj7cf4e6b2008-05-01 20:24:26 +00002684 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
njndbf7ca72006-03-31 11:57:59 +00002685 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 );
sewardj05a46732006-10-17 01:28:10 +00002686 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00002687 /* from previous test we don't have 8-alignment at offset +0,
2688 hence must have 8 alignment at offsets +4/-4. Hence safe to
2689 do 4 at +0 and then 8 at +4/. */
sewardj7cf4e6b2008-05-01 20:24:26 +00002690 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
njndbf7ca72006-03-31 11:57:59 +00002691 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+4 );
njn1d0825f2006-03-27 11:37:07 +00002692 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00002693 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 12 );
njn1d0825f2006-03-27 11:37:07 +00002694 }
2695}
2696
njneccf7c02009-01-19 23:42:45 +00002697MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002698static void VG_REGPARM(1) mc_die_mem_stack_12(Addr new_SP)
2699{
2700 PROF_EVENT(122, "die_mem_stack_12");
2701 /* Note the -12 in the test */
sewardj43fcfd92006-10-17 23:14:42 +00002702 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP-12 )) {
2703 /* We have 8-alignment at -12, hence ok to do 8 at -12 and 4 at
2704 -4. */
njndbf7ca72006-03-31 11:57:59 +00002705 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-12 );
2706 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-4 );
sewardj05a46732006-10-17 01:28:10 +00002707 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00002708 /* We have 4-alignment at +0, but we don't have 8-alignment at
2709 -12. So we must have 8-alignment at -8. Hence do 4 at -12
2710 and then 8 at -8. */
njndbf7ca72006-03-31 11:57:59 +00002711 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-12 );
2712 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-8 );
njn1d0825f2006-03-27 11:37:07 +00002713 } else {
njndbf7ca72006-03-31 11:57:59 +00002714 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-12, 12 );
njn1d0825f2006-03-27 11:37:07 +00002715 }
2716}
2717
sewardj7cf4e6b2008-05-01 20:24:26 +00002718/*--------------- adjustment by 16 bytes ---------------*/
2719
njneccf7c02009-01-19 23:42:45 +00002720MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00002721static void VG_REGPARM(2) mc_new_mem_stack_16_w_ECU(Addr new_SP, UInt ecu)
2722{
2723 UInt otag = ecu | MC_OKIND_STACK;
2724 PROF_EVENT(113, "new_mem_stack_16");
2725 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2726 /* Have 8-alignment at +0, hence do 8 at +0 and 8 at +8. */
2727 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
2728 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+8, otag );
2729 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2730 /* Have 4 alignment at +0 but not 8; hence 8 must be at +4.
2731 Hence do 4 at +0, 8 at +4, 4 at +12. */
2732 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
2733 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+4 , otag );
2734 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+12, otag );
2735 } else {
2736 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 16, otag );
2737 }
2738}
2739
njneccf7c02009-01-19 23:42:45 +00002740MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002741static void VG_REGPARM(1) mc_new_mem_stack_16(Addr new_SP)
2742{
2743 PROF_EVENT(113, "new_mem_stack_16");
sewardj05a46732006-10-17 01:28:10 +00002744 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00002745 /* Have 8-alignment at +0, hence do 8 at +0 and 8 at +8. */
sewardj7cf4e6b2008-05-01 20:24:26 +00002746 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
njndbf7ca72006-03-31 11:57:59 +00002747 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 );
sewardj05a46732006-10-17 01:28:10 +00002748 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00002749 /* Have 4 alignment at +0 but not 8; hence 8 must be at +4.
2750 Hence do 4 at +0, 8 at +4, 4 at +12. */
sewardj7cf4e6b2008-05-01 20:24:26 +00002751 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
njndbf7ca72006-03-31 11:57:59 +00002752 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+4 );
2753 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP+12 );
njn1d0825f2006-03-27 11:37:07 +00002754 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00002755 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 16 );
njn1d0825f2006-03-27 11:37:07 +00002756 }
2757}
2758
njneccf7c02009-01-19 23:42:45 +00002759MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002760static void VG_REGPARM(1) mc_die_mem_stack_16(Addr new_SP)
2761{
2762 PROF_EVENT(123, "die_mem_stack_16");
sewardj05a46732006-10-17 01:28:10 +00002763 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00002764 /* Have 8-alignment at +0, hence do 8 at -16 and 8 at -8. */
njndbf7ca72006-03-31 11:57:59 +00002765 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 );
2766 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-8 );
sewardj05a46732006-10-17 01:28:10 +00002767 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00002768 /* 8 alignment must be at -12. Do 4 at -16, 8 at -12, 4 at -4. */
njndbf7ca72006-03-31 11:57:59 +00002769 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 );
2770 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-12 );
2771 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-4 );
njn1d0825f2006-03-27 11:37:07 +00002772 } else {
njndbf7ca72006-03-31 11:57:59 +00002773 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-16, 16 );
njn1d0825f2006-03-27 11:37:07 +00002774 }
2775}
2776
sewardj7cf4e6b2008-05-01 20:24:26 +00002777/*--------------- adjustment by 32 bytes ---------------*/
2778
njneccf7c02009-01-19 23:42:45 +00002779MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00002780static void VG_REGPARM(2) mc_new_mem_stack_32_w_ECU(Addr new_SP, UInt ecu)
2781{
2782 UInt otag = ecu | MC_OKIND_STACK;
2783 PROF_EVENT(114, "new_mem_stack_32");
2784 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2785 /* Straightforward */
2786 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
2787 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+8 , otag );
2788 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+16, otag );
2789 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+24, otag );
2790 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2791 /* 8 alignment must be at +4. Hence do 8 at +4,+12,+20 and 4 at
2792 +0,+28. */
2793 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
2794 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+4 , otag );
2795 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+12, otag );
2796 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+20, otag );
2797 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+28, otag );
2798 } else {
2799 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 32, otag );
2800 }
2801}
2802
njneccf7c02009-01-19 23:42:45 +00002803MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002804static void VG_REGPARM(1) mc_new_mem_stack_32(Addr new_SP)
2805{
2806 PROF_EVENT(114, "new_mem_stack_32");
sewardj05a46732006-10-17 01:28:10 +00002807 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00002808 /* Straightforward */
sewardj7cf4e6b2008-05-01 20:24:26 +00002809 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
2810 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 );
njndbf7ca72006-03-31 11:57:59 +00002811 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+16 );
2812 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+24 );
sewardj05a46732006-10-17 01:28:10 +00002813 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00002814 /* 8 alignment must be at +4. Hence do 8 at +4,+12,+20 and 4 at
2815 +0,+28. */
sewardj7cf4e6b2008-05-01 20:24:26 +00002816 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
2817 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+4 );
njndbf7ca72006-03-31 11:57:59 +00002818 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+12 );
2819 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+20 );
2820 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP+28 );
njn1d0825f2006-03-27 11:37:07 +00002821 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00002822 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 32 );
njn1d0825f2006-03-27 11:37:07 +00002823 }
2824}
2825
njneccf7c02009-01-19 23:42:45 +00002826MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002827static void VG_REGPARM(1) mc_die_mem_stack_32(Addr new_SP)
2828{
2829 PROF_EVENT(124, "die_mem_stack_32");
sewardj05a46732006-10-17 01:28:10 +00002830 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00002831 /* Straightforward */
njndbf7ca72006-03-31 11:57:59 +00002832 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-32 );
2833 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-24 );
2834 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 );
2835 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP- 8 );
sewardj05a46732006-10-17 01:28:10 +00002836 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00002837 /* 8 alignment must be at -4 etc. Hence do 8 at -12,-20,-28 and
2838 4 at -32,-4. */
njndbf7ca72006-03-31 11:57:59 +00002839 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-32 );
2840 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-28 );
2841 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-20 );
2842 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-12 );
2843 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-4 );
njn1d0825f2006-03-27 11:37:07 +00002844 } else {
njndbf7ca72006-03-31 11:57:59 +00002845 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-32, 32 );
njn1d0825f2006-03-27 11:37:07 +00002846 }
2847}
2848
sewardj7cf4e6b2008-05-01 20:24:26 +00002849/*--------------- adjustment by 112 bytes ---------------*/
2850
njneccf7c02009-01-19 23:42:45 +00002851MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00002852static void VG_REGPARM(2) mc_new_mem_stack_112_w_ECU(Addr new_SP, UInt ecu)
2853{
2854 UInt otag = ecu | MC_OKIND_STACK;
2855 PROF_EVENT(115, "new_mem_stack_112");
2856 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2857 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
2858 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+8 , otag );
2859 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+16, otag );
2860 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+24, otag );
2861 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+32, otag );
2862 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+40, otag );
2863 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+48, otag );
2864 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+56, otag );
2865 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+64, otag );
2866 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+72, otag );
2867 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+80, otag );
2868 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+88, otag );
2869 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+96, otag );
2870 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+104, otag );
2871 } else {
2872 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 112, otag );
2873 }
2874}
2875
njneccf7c02009-01-19 23:42:45 +00002876MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002877static void VG_REGPARM(1) mc_new_mem_stack_112(Addr new_SP)
2878{
2879 PROF_EVENT(115, "new_mem_stack_112");
sewardj05a46732006-10-17 01:28:10 +00002880 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj7cf4e6b2008-05-01 20:24:26 +00002881 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
2882 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 );
njndbf7ca72006-03-31 11:57:59 +00002883 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+16 );
2884 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+24 );
2885 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+32 );
2886 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+40 );
2887 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+48 );
2888 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+56 );
2889 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+64 );
2890 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+72 );
2891 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+80 );
2892 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+88 );
2893 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+96 );
sewardj7cf4e6b2008-05-01 20:24:26 +00002894 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+104 );
njn1d0825f2006-03-27 11:37:07 +00002895 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00002896 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 112 );
njn1d0825f2006-03-27 11:37:07 +00002897 }
2898}
2899
njneccf7c02009-01-19 23:42:45 +00002900MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002901static void VG_REGPARM(1) mc_die_mem_stack_112(Addr new_SP)
2902{
2903 PROF_EVENT(125, "die_mem_stack_112");
sewardj05a46732006-10-17 01:28:10 +00002904 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00002905 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-112);
2906 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-104);
2907 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-96 );
2908 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-88 );
2909 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-80 );
2910 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-72 );
2911 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-64 );
2912 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-56 );
2913 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-48 );
2914 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-40 );
2915 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-32 );
2916 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-24 );
2917 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 );
2918 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP- 8 );
njn1d0825f2006-03-27 11:37:07 +00002919 } else {
njndbf7ca72006-03-31 11:57:59 +00002920 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-112, 112 );
njn1d0825f2006-03-27 11:37:07 +00002921 }
2922}
2923
sewardj7cf4e6b2008-05-01 20:24:26 +00002924/*--------------- adjustment by 128 bytes ---------------*/
2925
njneccf7c02009-01-19 23:42:45 +00002926MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00002927static void VG_REGPARM(2) mc_new_mem_stack_128_w_ECU(Addr new_SP, UInt ecu)
2928{
2929 UInt otag = ecu | MC_OKIND_STACK;
2930 PROF_EVENT(116, "new_mem_stack_128");
2931 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2932 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
2933 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+8 , otag );
2934 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+16, otag );
2935 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+24, otag );
2936 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+32, otag );
2937 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+40, otag );
2938 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+48, otag );
2939 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+56, otag );
2940 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+64, otag );
2941 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+72, otag );
2942 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+80, otag );
2943 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+88, otag );
2944 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+96, otag );
2945 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+104, otag );
2946 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+112, otag );
2947 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+120, otag );
2948 } else {
2949 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 128, otag );
2950 }
2951}
2952
njneccf7c02009-01-19 23:42:45 +00002953MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002954static void VG_REGPARM(1) mc_new_mem_stack_128(Addr new_SP)
2955{
2956 PROF_EVENT(116, "new_mem_stack_128");
sewardj05a46732006-10-17 01:28:10 +00002957 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj7cf4e6b2008-05-01 20:24:26 +00002958 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
2959 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 );
njndbf7ca72006-03-31 11:57:59 +00002960 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+16 );
2961 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+24 );
2962 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+32 );
2963 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+40 );
2964 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+48 );
2965 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+56 );
2966 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+64 );
2967 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+72 );
2968 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+80 );
2969 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+88 );
2970 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+96 );
sewardj7cf4e6b2008-05-01 20:24:26 +00002971 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+104 );
2972 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+112 );
2973 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+120 );
njn1d0825f2006-03-27 11:37:07 +00002974 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00002975 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 128 );
njn1d0825f2006-03-27 11:37:07 +00002976 }
2977}
2978
njneccf7c02009-01-19 23:42:45 +00002979MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002980static void VG_REGPARM(1) mc_die_mem_stack_128(Addr new_SP)
2981{
2982 PROF_EVENT(126, "die_mem_stack_128");
sewardj05a46732006-10-17 01:28:10 +00002983 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00002984 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-128);
2985 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-120);
2986 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-112);
2987 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-104);
2988 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-96 );
2989 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-88 );
2990 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-80 );
2991 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-72 );
2992 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-64 );
2993 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-56 );
2994 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-48 );
2995 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-40 );
2996 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-32 );
2997 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-24 );
2998 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 );
2999 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP- 8 );
njn1d0825f2006-03-27 11:37:07 +00003000 } else {
njndbf7ca72006-03-31 11:57:59 +00003001 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-128, 128 );
njn1d0825f2006-03-27 11:37:07 +00003002 }
3003}
3004
sewardj7cf4e6b2008-05-01 20:24:26 +00003005/*--------------- adjustment by 144 bytes ---------------*/
3006
njneccf7c02009-01-19 23:42:45 +00003007MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00003008static void VG_REGPARM(2) mc_new_mem_stack_144_w_ECU(Addr new_SP, UInt ecu)
3009{
3010 UInt otag = ecu | MC_OKIND_STACK;
3011 PROF_EVENT(117, "new_mem_stack_144");
3012 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
3013 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP, otag );
3014 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+8, otag );
3015 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+16, otag );
3016 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+24, otag );
3017 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+32, otag );
3018 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+40, otag );
3019 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+48, otag );
3020 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+56, otag );
3021 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+64, otag );
3022 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+72, otag );
3023 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+80, otag );
3024 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+88, otag );
3025 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+96, otag );
3026 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+104, otag );
3027 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+112, otag );
3028 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+120, otag );
3029 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+128, otag );
3030 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+136, otag );
3031 } else {
3032 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 144, otag );
3033 }
3034}
3035
njneccf7c02009-01-19 23:42:45 +00003036MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00003037static void VG_REGPARM(1) mc_new_mem_stack_144(Addr new_SP)
3038{
3039 PROF_EVENT(117, "new_mem_stack_144");
sewardj05a46732006-10-17 01:28:10 +00003040 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj7cf4e6b2008-05-01 20:24:26 +00003041 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
3042 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 );
njndbf7ca72006-03-31 11:57:59 +00003043 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+16 );
3044 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+24 );
3045 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+32 );
3046 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+40 );
3047 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+48 );
3048 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+56 );
3049 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+64 );
3050 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+72 );
3051 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+80 );
3052 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+88 );
3053 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+96 );
sewardj7cf4e6b2008-05-01 20:24:26 +00003054 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+104 );
3055 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+112 );
3056 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+120 );
3057 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+128 );
3058 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+136 );
njn1d0825f2006-03-27 11:37:07 +00003059 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00003060 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 144 );
njn1d0825f2006-03-27 11:37:07 +00003061 }
3062}
3063
njneccf7c02009-01-19 23:42:45 +00003064MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00003065static void VG_REGPARM(1) mc_die_mem_stack_144(Addr new_SP)
3066{
3067 PROF_EVENT(127, "die_mem_stack_144");
sewardj05a46732006-10-17 01:28:10 +00003068 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00003069 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-144);
3070 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-136);
3071 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-128);
3072 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-120);
3073 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-112);
3074 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-104);
3075 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-96 );
3076 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-88 );
3077 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-80 );
3078 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-72 );
3079 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-64 );
3080 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-56 );
3081 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-48 );
3082 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-40 );
3083 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-32 );
3084 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-24 );
3085 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 );
3086 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP- 8 );
njn1d0825f2006-03-27 11:37:07 +00003087 } else {
njndbf7ca72006-03-31 11:57:59 +00003088 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-144, 144 );
njn1d0825f2006-03-27 11:37:07 +00003089 }
3090}
3091
sewardj7cf4e6b2008-05-01 20:24:26 +00003092/*--------------- adjustment by 160 bytes ---------------*/
3093
njneccf7c02009-01-19 23:42:45 +00003094MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00003095static void VG_REGPARM(2) mc_new_mem_stack_160_w_ECU(Addr new_SP, UInt ecu)
3096{
3097 UInt otag = ecu | MC_OKIND_STACK;
3098 PROF_EVENT(118, "new_mem_stack_160");
3099 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
3100 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP, otag );
3101 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+8, otag );
3102 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+16, otag );
3103 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+24, otag );
3104 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+32, otag );
3105 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+40, otag );
3106 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+48, otag );
3107 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+56, otag );
3108 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+64, otag );
3109 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+72, otag );
3110 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+80, otag );
3111 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+88, otag );
3112 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+96, otag );
3113 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+104, otag );
3114 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+112, otag );
3115 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+120, otag );
3116 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+128, otag );
3117 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+136, otag );
3118 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+144, otag );
3119 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+152, otag );
3120 } else {
3121 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 160, otag );
3122 }
3123}
3124
njneccf7c02009-01-19 23:42:45 +00003125MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00003126static void VG_REGPARM(1) mc_new_mem_stack_160(Addr new_SP)
3127{
3128 PROF_EVENT(118, "new_mem_stack_160");
sewardj05a46732006-10-17 01:28:10 +00003129 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj7cf4e6b2008-05-01 20:24:26 +00003130 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
3131 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 );
njndbf7ca72006-03-31 11:57:59 +00003132 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+16 );
3133 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+24 );
3134 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+32 );
3135 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+40 );
3136 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+48 );
3137 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+56 );
3138 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+64 );
3139 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+72 );
3140 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+80 );
3141 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+88 );
3142 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+96 );
sewardj7cf4e6b2008-05-01 20:24:26 +00003143 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+104 );
3144 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+112 );
3145 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+120 );
3146 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+128 );
3147 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+136 );
3148 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+144 );
3149 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+152 );
njn1d0825f2006-03-27 11:37:07 +00003150 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00003151 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 160 );
njn1d0825f2006-03-27 11:37:07 +00003152 }
3153}
3154
njneccf7c02009-01-19 23:42:45 +00003155MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00003156static void VG_REGPARM(1) mc_die_mem_stack_160(Addr new_SP)
3157{
3158 PROF_EVENT(128, "die_mem_stack_160");
sewardj05a46732006-10-17 01:28:10 +00003159 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00003160 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-160);
3161 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-152);
3162 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-144);
3163 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-136);
3164 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-128);
3165 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-120);
3166 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-112);
3167 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-104);
3168 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-96 );
3169 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-88 );
3170 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-80 );
3171 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-72 );
3172 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-64 );
3173 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-56 );
3174 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-48 );
3175 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-40 );
3176 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-32 );
3177 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-24 );
3178 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 );
3179 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP- 8 );
njn1d0825f2006-03-27 11:37:07 +00003180 } else {
njndbf7ca72006-03-31 11:57:59 +00003181 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-160, 160 );
njn1d0825f2006-03-27 11:37:07 +00003182 }
3183}
3184
sewardj7cf4e6b2008-05-01 20:24:26 +00003185/*--------------- adjustment by N bytes ---------------*/
3186
3187static void mc_new_mem_stack_w_ECU ( Addr a, SizeT len, UInt ecu )
3188{
3189 UInt otag = ecu | MC_OKIND_STACK;
3190 PROF_EVENT(115, "new_mem_stack_w_otag");
3191 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + a, len, otag );
3192}
3193
njn1d0825f2006-03-27 11:37:07 +00003194static void mc_new_mem_stack ( Addr a, SizeT len )
3195{
3196 PROF_EVENT(115, "new_mem_stack");
sewardj7cf4e6b2008-05-01 20:24:26 +00003197 make_mem_undefined ( -VG_STACK_REDZONE_SZB + a, len );
njn1d0825f2006-03-27 11:37:07 +00003198}
3199
3200static void mc_die_mem_stack ( Addr a, SizeT len )
3201{
3202 PROF_EVENT(125, "die_mem_stack");
njndbf7ca72006-03-31 11:57:59 +00003203 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + a, len );
njn1d0825f2006-03-27 11:37:07 +00003204}
njn9b007f62003-04-07 14:40:25 +00003205
sewardj45d94cc2005-04-20 14:44:11 +00003206
njn1d0825f2006-03-27 11:37:07 +00003207/* The AMD64 ABI says:
3208
3209 "The 128-byte area beyond the location pointed to by %rsp is considered
3210 to be reserved and shall not be modified by signal or interrupt
3211 handlers. Therefore, functions may use this area for temporary data
3212 that is not needed across function calls. In particular, leaf functions
3213 may use this area for their entire stack frame, rather than adjusting
3214 the stack pointer in the prologue and epilogue. This area is known as
3215 red zone [sic]."
3216
3217 So after any call or return we need to mark this redzone as containing
3218 undefined values.
3219
3220 Consider this: we're in function f. f calls g. g moves rsp down
3221 modestly (say 16 bytes) and writes stuff all over the red zone, making it
3222 defined. g returns. f is buggy and reads from parts of the red zone
3223 that it didn't write on. But because g filled that area in, f is going
3224 to be picking up defined V bits and so any errors from reading bits of
3225 the red zone it didn't write, will be missed. The only solution I could
3226 think of was to make the red zone undefined when g returns to f.
3227
3228 This is in accordance with the ABI, which makes it clear the redzone
3229 is volatile across function calls.
3230
3231 The problem occurs the other way round too: f could fill the RZ up
3232 with defined values and g could mistakenly read them. So the RZ
3233 also needs to be nuked on function calls.
3234*/
sewardj7cf4e6b2008-05-01 20:24:26 +00003235
3236
3237/* Here's a simple cache to hold nia -> ECU mappings. It could be
3238 improved so as to have a lower miss rate. */
3239
3240static UWord stats__nia_cache_queries = 0;
3241static UWord stats__nia_cache_misses = 0;
3242
3243typedef
3244 struct { UWord nia0; UWord ecu0; /* nia0 maps to ecu0 */
3245 UWord nia1; UWord ecu1; } /* nia1 maps to ecu1 */
3246 WCacheEnt;
3247
3248#define N_NIA_TO_ECU_CACHE 511
3249
3250static WCacheEnt nia_to_ecu_cache[N_NIA_TO_ECU_CACHE];
3251
3252static void init_nia_to_ecu_cache ( void )
sewardj826ec492005-05-12 18:05:00 +00003253{
sewardj7cf4e6b2008-05-01 20:24:26 +00003254 UWord i;
3255 Addr zero_addr = 0;
3256 ExeContext* zero_ec;
3257 UInt zero_ecu;
3258 /* Fill all the slots with an entry for address zero, and the
3259 relevant otags accordingly. Hence the cache is initially filled
3260 with valid data. */
3261 zero_ec = VG_(make_depth_1_ExeContext_from_Addr)(zero_addr);
3262 tl_assert(zero_ec);
3263 zero_ecu = VG_(get_ECU_from_ExeContext)(zero_ec);
3264 tl_assert(VG_(is_plausible_ECU)(zero_ecu));
3265 for (i = 0; i < N_NIA_TO_ECU_CACHE; i++) {
3266 nia_to_ecu_cache[i].nia0 = zero_addr;
3267 nia_to_ecu_cache[i].ecu0 = zero_ecu;
3268 nia_to_ecu_cache[i].nia1 = zero_addr;
3269 nia_to_ecu_cache[i].ecu1 = zero_ecu;
3270 }
3271}
3272
3273static inline UInt convert_nia_to_ecu ( Addr nia )
3274{
3275 UWord i;
3276 UInt ecu;
3277 ExeContext* ec;
3278
3279 tl_assert( sizeof(nia_to_ecu_cache[0].nia1) == sizeof(nia) );
3280
3281 stats__nia_cache_queries++;
3282 i = nia % N_NIA_TO_ECU_CACHE;
3283 tl_assert(i >= 0 && i < N_NIA_TO_ECU_CACHE);
3284
3285 if (LIKELY( nia_to_ecu_cache[i].nia0 == nia ))
3286 return nia_to_ecu_cache[i].ecu0;
3287
3288 if (LIKELY( nia_to_ecu_cache[i].nia1 == nia )) {
3289# define SWAP(_w1,_w2) { UWord _t = _w1; _w1 = _w2; _w2 = _t; }
3290 SWAP( nia_to_ecu_cache[i].nia0, nia_to_ecu_cache[i].nia1 );
3291 SWAP( nia_to_ecu_cache[i].ecu0, nia_to_ecu_cache[i].ecu1 );
3292# undef SWAP
3293 return nia_to_ecu_cache[i].ecu0;
3294 }
3295
3296 stats__nia_cache_misses++;
3297 ec = VG_(make_depth_1_ExeContext_from_Addr)(nia);
3298 tl_assert(ec);
3299 ecu = VG_(get_ECU_from_ExeContext)(ec);
3300 tl_assert(VG_(is_plausible_ECU)(ecu));
3301
3302 nia_to_ecu_cache[i].nia1 = nia_to_ecu_cache[i].nia0;
3303 nia_to_ecu_cache[i].ecu1 = nia_to_ecu_cache[i].ecu0;
3304
3305 nia_to_ecu_cache[i].nia0 = nia;
3306 nia_to_ecu_cache[i].ecu0 = (UWord)ecu;
3307 return ecu;
3308}
3309
3310
3311/* Note that this serves both the origin-tracking and
3312 no-origin-tracking modes. We assume that calls to it are
3313 sufficiently infrequent that it isn't worth specialising for the
3314 with/without origin-tracking cases. */
3315void MC_(helperc_MAKE_STACK_UNINIT) ( Addr base, UWord len, Addr nia )
3316{
3317 UInt otag;
sewardj826ec492005-05-12 18:05:00 +00003318 tl_assert(sizeof(UWord) == sizeof(SizeT));
sewardj2a3a1a72005-05-12 23:25:43 +00003319 if (0)
barta0b6b2c2008-07-07 06:49:24 +00003320 VG_(printf)("helperc_MAKE_STACK_UNINIT (%#lx,%lu,nia=%#lx)\n",
sewardj7cf4e6b2008-05-01 20:24:26 +00003321 base, len, nia );
3322
3323 if (UNLIKELY( MC_(clo_mc_level) == 3 )) {
3324 UInt ecu = convert_nia_to_ecu ( nia );
3325 tl_assert(VG_(is_plausible_ECU)(ecu));
3326 otag = ecu | MC_OKIND_STACK;
3327 } else {
3328 tl_assert(nia == 0);
3329 otag = 0;
3330 }
sewardj2a3a1a72005-05-12 23:25:43 +00003331
3332# if 0
3333 /* Really slow version */
sewardj7cf4e6b2008-05-01 20:24:26 +00003334 MC_(make_mem_undefined)(base, len, otag);
sewardj2a3a1a72005-05-12 23:25:43 +00003335# endif
3336
3337# if 0
3338 /* Slow(ish) version, which is fairly easily seen to be correct.
3339 */
bart5dd8e6a2008-03-22 08:04:29 +00003340 if (LIKELY( VG_IS_8_ALIGNED(base) && len==128 )) {
sewardj7cf4e6b2008-05-01 20:24:26 +00003341 make_aligned_word64_undefined(base + 0, otag);
3342 make_aligned_word64_undefined(base + 8, otag);
3343 make_aligned_word64_undefined(base + 16, otag);
3344 make_aligned_word64_undefined(base + 24, otag);
sewardj2a3a1a72005-05-12 23:25:43 +00003345
sewardj7cf4e6b2008-05-01 20:24:26 +00003346 make_aligned_word64_undefined(base + 32, otag);
3347 make_aligned_word64_undefined(base + 40, otag);
3348 make_aligned_word64_undefined(base + 48, otag);
3349 make_aligned_word64_undefined(base + 56, otag);
sewardj2a3a1a72005-05-12 23:25:43 +00003350
sewardj7cf4e6b2008-05-01 20:24:26 +00003351 make_aligned_word64_undefined(base + 64, otag);
3352 make_aligned_word64_undefined(base + 72, otag);
3353 make_aligned_word64_undefined(base + 80, otag);
3354 make_aligned_word64_undefined(base + 88, otag);
sewardj2a3a1a72005-05-12 23:25:43 +00003355
sewardj7cf4e6b2008-05-01 20:24:26 +00003356 make_aligned_word64_undefined(base + 96, otag);
3357 make_aligned_word64_undefined(base + 104, otag);
3358 make_aligned_word64_undefined(base + 112, otag);
3359 make_aligned_word64_undefined(base + 120, otag);
sewardj2a3a1a72005-05-12 23:25:43 +00003360 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00003361 MC_(make_mem_undefined)(base, len, otag);
sewardj2a3a1a72005-05-12 23:25:43 +00003362 }
3363# endif
3364
3365 /* Idea is: go fast when
3366 * 8-aligned and length is 128
3367 * the sm is available in the main primary map
njn1d0825f2006-03-27 11:37:07 +00003368 * the address range falls entirely with a single secondary map
3369 If all those conditions hold, just update the V+A bits by writing
3370 directly into the vabits array. (If the sm was distinguished, this
3371 will make a copy and then write to it.)
sewardj2a3a1a72005-05-12 23:25:43 +00003372 */
sewardj7cf4e6b2008-05-01 20:24:26 +00003373
bart5dd8e6a2008-03-22 08:04:29 +00003374 if (LIKELY( len == 128 && VG_IS_8_ALIGNED(base) )) {
njn1d0825f2006-03-27 11:37:07 +00003375 /* Now we know the address range is suitably sized and aligned. */
3376 UWord a_lo = (UWord)(base);
sewardj3f5f5562006-06-16 21:39:08 +00003377 UWord a_hi = (UWord)(base + 128 - 1);
njn1d0825f2006-03-27 11:37:07 +00003378 tl_assert(a_lo < a_hi); // paranoia: detect overflow
sewardj7244e712008-05-02 12:35:48 +00003379 if (a_hi <= MAX_PRIMARY_ADDRESS) {
njn1d0825f2006-03-27 11:37:07 +00003380 // Now we know the entire range is within the main primary map.
njna7c7ebd2006-03-28 12:51:02 +00003381 SecMap* sm = get_secmap_for_writing_low(a_lo);
3382 SecMap* sm_hi = get_secmap_for_writing_low(a_hi);
sewardj2a3a1a72005-05-12 23:25:43 +00003383 /* Now we know that the entire address range falls within a
3384 single secondary map, and that that secondary 'lives' in
3385 the main primary map. */
bart5dd8e6a2008-03-22 08:04:29 +00003386 if (LIKELY(sm == sm_hi)) {
njn1d0825f2006-03-27 11:37:07 +00003387 // Finally, we know that the range is entirely within one secmap.
3388 UWord v_off = SM_OFF(a_lo);
3389 UShort* p = (UShort*)(&sm->vabits8[v_off]);
njndbf7ca72006-03-31 11:57:59 +00003390 p[ 0] = VA_BITS16_UNDEFINED;
3391 p[ 1] = VA_BITS16_UNDEFINED;
3392 p[ 2] = VA_BITS16_UNDEFINED;
3393 p[ 3] = VA_BITS16_UNDEFINED;
3394 p[ 4] = VA_BITS16_UNDEFINED;
3395 p[ 5] = VA_BITS16_UNDEFINED;
3396 p[ 6] = VA_BITS16_UNDEFINED;
3397 p[ 7] = VA_BITS16_UNDEFINED;
3398 p[ 8] = VA_BITS16_UNDEFINED;
3399 p[ 9] = VA_BITS16_UNDEFINED;
3400 p[10] = VA_BITS16_UNDEFINED;
3401 p[11] = VA_BITS16_UNDEFINED;
3402 p[12] = VA_BITS16_UNDEFINED;
3403 p[13] = VA_BITS16_UNDEFINED;
3404 p[14] = VA_BITS16_UNDEFINED;
3405 p[15] = VA_BITS16_UNDEFINED;
sewardj7cf4e6b2008-05-01 20:24:26 +00003406 if (UNLIKELY( MC_(clo_mc_level) == 3 )) {
3407 set_aligned_word64_Origin_to_undef( base + 8 * 0, otag );
3408 set_aligned_word64_Origin_to_undef( base + 8 * 1, otag );
3409 set_aligned_word64_Origin_to_undef( base + 8 * 2, otag );
3410 set_aligned_word64_Origin_to_undef( base + 8 * 3, otag );
3411 set_aligned_word64_Origin_to_undef( base + 8 * 4, otag );
3412 set_aligned_word64_Origin_to_undef( base + 8 * 5, otag );
3413 set_aligned_word64_Origin_to_undef( base + 8 * 6, otag );
3414 set_aligned_word64_Origin_to_undef( base + 8 * 7, otag );
3415 set_aligned_word64_Origin_to_undef( base + 8 * 8, otag );
3416 set_aligned_word64_Origin_to_undef( base + 8 * 9, otag );
3417 set_aligned_word64_Origin_to_undef( base + 8 * 10, otag );
3418 set_aligned_word64_Origin_to_undef( base + 8 * 11, otag );
3419 set_aligned_word64_Origin_to_undef( base + 8 * 12, otag );
3420 set_aligned_word64_Origin_to_undef( base + 8 * 13, otag );
3421 set_aligned_word64_Origin_to_undef( base + 8 * 14, otag );
3422 set_aligned_word64_Origin_to_undef( base + 8 * 15, otag );
3423 }
sewardj2a3a1a72005-05-12 23:25:43 +00003424 return;
njn1d0825f2006-03-27 11:37:07 +00003425 }
sewardj2a3a1a72005-05-12 23:25:43 +00003426 }
3427 }
3428
sewardj2e1a6772006-01-18 04:16:27 +00003429 /* 288 bytes (36 ULongs) is the magic value for ELF ppc64. */
bart5dd8e6a2008-03-22 08:04:29 +00003430 if (LIKELY( len == 288 && VG_IS_8_ALIGNED(base) )) {
njn1d0825f2006-03-27 11:37:07 +00003431 /* Now we know the address range is suitably sized and aligned. */
3432 UWord a_lo = (UWord)(base);
sewardj3f5f5562006-06-16 21:39:08 +00003433 UWord a_hi = (UWord)(base + 288 - 1);
njn1d0825f2006-03-27 11:37:07 +00003434 tl_assert(a_lo < a_hi); // paranoia: detect overflow
sewardj7244e712008-05-02 12:35:48 +00003435 if (a_hi <= MAX_PRIMARY_ADDRESS) {
njn1d0825f2006-03-27 11:37:07 +00003436 // Now we know the entire range is within the main primary map.
njna7c7ebd2006-03-28 12:51:02 +00003437 SecMap* sm = get_secmap_for_writing_low(a_lo);
3438 SecMap* sm_hi = get_secmap_for_writing_low(a_hi);
sewardj2e1a6772006-01-18 04:16:27 +00003439 /* Now we know that the entire address range falls within a
3440 single secondary map, and that that secondary 'lives' in
3441 the main primary map. */
bart5dd8e6a2008-03-22 08:04:29 +00003442 if (LIKELY(sm == sm_hi)) {
njn1d0825f2006-03-27 11:37:07 +00003443 // Finally, we know that the range is entirely within one secmap.
3444 UWord v_off = SM_OFF(a_lo);
3445 UShort* p = (UShort*)(&sm->vabits8[v_off]);
njndbf7ca72006-03-31 11:57:59 +00003446 p[ 0] = VA_BITS16_UNDEFINED;
3447 p[ 1] = VA_BITS16_UNDEFINED;
3448 p[ 2] = VA_BITS16_UNDEFINED;
3449 p[ 3] = VA_BITS16_UNDEFINED;
3450 p[ 4] = VA_BITS16_UNDEFINED;
3451 p[ 5] = VA_BITS16_UNDEFINED;
3452 p[ 6] = VA_BITS16_UNDEFINED;
3453 p[ 7] = VA_BITS16_UNDEFINED;
3454 p[ 8] = VA_BITS16_UNDEFINED;
3455 p[ 9] = VA_BITS16_UNDEFINED;
3456 p[10] = VA_BITS16_UNDEFINED;
3457 p[11] = VA_BITS16_UNDEFINED;
3458 p[12] = VA_BITS16_UNDEFINED;
3459 p[13] = VA_BITS16_UNDEFINED;
3460 p[14] = VA_BITS16_UNDEFINED;
3461 p[15] = VA_BITS16_UNDEFINED;
3462 p[16] = VA_BITS16_UNDEFINED;
3463 p[17] = VA_BITS16_UNDEFINED;
3464 p[18] = VA_BITS16_UNDEFINED;
3465 p[19] = VA_BITS16_UNDEFINED;
3466 p[20] = VA_BITS16_UNDEFINED;
3467 p[21] = VA_BITS16_UNDEFINED;
3468 p[22] = VA_BITS16_UNDEFINED;
3469 p[23] = VA_BITS16_UNDEFINED;
3470 p[24] = VA_BITS16_UNDEFINED;
3471 p[25] = VA_BITS16_UNDEFINED;
3472 p[26] = VA_BITS16_UNDEFINED;
3473 p[27] = VA_BITS16_UNDEFINED;
3474 p[28] = VA_BITS16_UNDEFINED;
3475 p[29] = VA_BITS16_UNDEFINED;
3476 p[30] = VA_BITS16_UNDEFINED;
3477 p[31] = VA_BITS16_UNDEFINED;
3478 p[32] = VA_BITS16_UNDEFINED;
3479 p[33] = VA_BITS16_UNDEFINED;
3480 p[34] = VA_BITS16_UNDEFINED;
3481 p[35] = VA_BITS16_UNDEFINED;
sewardj7cf4e6b2008-05-01 20:24:26 +00003482 if (UNLIKELY( MC_(clo_mc_level) == 3 )) {
3483 set_aligned_word64_Origin_to_undef( base + 8 * 0, otag );
3484 set_aligned_word64_Origin_to_undef( base + 8 * 1, otag );
3485 set_aligned_word64_Origin_to_undef( base + 8 * 2, otag );
3486 set_aligned_word64_Origin_to_undef( base + 8 * 3, otag );
3487 set_aligned_word64_Origin_to_undef( base + 8 * 4, otag );
3488 set_aligned_word64_Origin_to_undef( base + 8 * 5, otag );
3489 set_aligned_word64_Origin_to_undef( base + 8 * 6, otag );
3490 set_aligned_word64_Origin_to_undef( base + 8 * 7, otag );
3491 set_aligned_word64_Origin_to_undef( base + 8 * 8, otag );
3492 set_aligned_word64_Origin_to_undef( base + 8 * 9, otag );
3493 set_aligned_word64_Origin_to_undef( base + 8 * 10, otag );
3494 set_aligned_word64_Origin_to_undef( base + 8 * 11, otag );
3495 set_aligned_word64_Origin_to_undef( base + 8 * 12, otag );
3496 set_aligned_word64_Origin_to_undef( base + 8 * 13, otag );
3497 set_aligned_word64_Origin_to_undef( base + 8 * 14, otag );
3498 set_aligned_word64_Origin_to_undef( base + 8 * 15, otag );
3499 set_aligned_word64_Origin_to_undef( base + 8 * 16, otag );
3500 set_aligned_word64_Origin_to_undef( base + 8 * 17, otag );
3501 set_aligned_word64_Origin_to_undef( base + 8 * 18, otag );
3502 set_aligned_word64_Origin_to_undef( base + 8 * 19, otag );
3503 set_aligned_word64_Origin_to_undef( base + 8 * 20, otag );
3504 set_aligned_word64_Origin_to_undef( base + 8 * 21, otag );
3505 set_aligned_word64_Origin_to_undef( base + 8 * 22, otag );
3506 set_aligned_word64_Origin_to_undef( base + 8 * 23, otag );
3507 set_aligned_word64_Origin_to_undef( base + 8 * 24, otag );
3508 set_aligned_word64_Origin_to_undef( base + 8 * 25, otag );
3509 set_aligned_word64_Origin_to_undef( base + 8 * 26, otag );
3510 set_aligned_word64_Origin_to_undef( base + 8 * 27, otag );
3511 set_aligned_word64_Origin_to_undef( base + 8 * 28, otag );
3512 set_aligned_word64_Origin_to_undef( base + 8 * 29, otag );
3513 set_aligned_word64_Origin_to_undef( base + 8 * 30, otag );
3514 set_aligned_word64_Origin_to_undef( base + 8 * 31, otag );
3515 set_aligned_word64_Origin_to_undef( base + 8 * 32, otag );
3516 set_aligned_word64_Origin_to_undef( base + 8 * 33, otag );
3517 set_aligned_word64_Origin_to_undef( base + 8 * 34, otag );
3518 set_aligned_word64_Origin_to_undef( base + 8 * 35, otag );
3519 }
sewardj2e1a6772006-01-18 04:16:27 +00003520 return;
njn1d0825f2006-03-27 11:37:07 +00003521 }
sewardj2e1a6772006-01-18 04:16:27 +00003522 }
3523 }
3524
sewardj2a3a1a72005-05-12 23:25:43 +00003525 /* else fall into slow case */
sewardj7cf4e6b2008-05-01 20:24:26 +00003526 MC_(make_mem_undefined_w_otag)(base, len, otag);
sewardj826ec492005-05-12 18:05:00 +00003527}
3528
3529
nethercote8b76fe52004-11-08 19:20:09 +00003530/*------------------------------------------------------------*/
3531/*--- Checking memory ---*/
3532/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00003533
sewardje4ccc012005-05-02 12:53:38 +00003534typedef
3535 enum {
3536 MC_Ok = 5,
3537 MC_AddrErr = 6,
3538 MC_ValueErr = 7
3539 }
3540 MC_ReadResult;
3541
3542
njn25e49d8e72002-09-23 09:36:25 +00003543/* Check permissions for address range. If inadequate permissions
3544 exist, *bad_addr is set to the offending address, so the caller can
3545 know what it is. */
3546
sewardjecf8e102003-07-12 12:11:39 +00003547/* Returns True if [a .. a+len) is not addressible. Otherwise,
3548 returns False, and if bad_addr is non-NULL, sets *bad_addr to
3549 indicate the lowest failing address. Functions below are
3550 similar. */
njndbf7ca72006-03-31 11:57:59 +00003551Bool MC_(check_mem_is_noaccess) ( Addr a, SizeT len, Addr* bad_addr )
sewardjecf8e102003-07-12 12:11:39 +00003552{
nethercote451eae92004-11-02 13:06:32 +00003553 SizeT i;
njn1d0825f2006-03-27 11:37:07 +00003554 UWord vabits2;
3555
njndbf7ca72006-03-31 11:57:59 +00003556 PROF_EVENT(60, "check_mem_is_noaccess");
sewardjecf8e102003-07-12 12:11:39 +00003557 for (i = 0; i < len; i++) {
njndbf7ca72006-03-31 11:57:59 +00003558 PROF_EVENT(61, "check_mem_is_noaccess(loop)");
njn1d0825f2006-03-27 11:37:07 +00003559 vabits2 = get_vabits2(a);
3560 if (VA_BITS2_NOACCESS != vabits2) {
3561 if (bad_addr != NULL) *bad_addr = a;
sewardjecf8e102003-07-12 12:11:39 +00003562 return False;
3563 }
3564 a++;
3565 }
3566 return True;
3567}
3568
sewardj7cf4e6b2008-05-01 20:24:26 +00003569static Bool is_mem_addressable ( Addr a, SizeT len,
3570 /*OUT*/Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +00003571{
nethercote451eae92004-11-02 13:06:32 +00003572 SizeT i;
njn1d0825f2006-03-27 11:37:07 +00003573 UWord vabits2;
3574
njndbf7ca72006-03-31 11:57:59 +00003575 PROF_EVENT(62, "is_mem_addressable");
njn25e49d8e72002-09-23 09:36:25 +00003576 for (i = 0; i < len; i++) {
njndbf7ca72006-03-31 11:57:59 +00003577 PROF_EVENT(63, "is_mem_addressable(loop)");
njn1d0825f2006-03-27 11:37:07 +00003578 vabits2 = get_vabits2(a);
3579 if (VA_BITS2_NOACCESS == vabits2) {
njn25e49d8e72002-09-23 09:36:25 +00003580 if (bad_addr != NULL) *bad_addr = a;
3581 return False;
3582 }
3583 a++;
3584 }
3585 return True;
3586}
3587
sewardj7cf4e6b2008-05-01 20:24:26 +00003588static MC_ReadResult is_mem_defined ( Addr a, SizeT len,
3589 /*OUT*/Addr* bad_addr,
3590 /*OUT*/UInt* otag )
njn25e49d8e72002-09-23 09:36:25 +00003591{
nethercote451eae92004-11-02 13:06:32 +00003592 SizeT i;
njn1d0825f2006-03-27 11:37:07 +00003593 UWord vabits2;
njn25e49d8e72002-09-23 09:36:25 +00003594
njndbf7ca72006-03-31 11:57:59 +00003595 PROF_EVENT(64, "is_mem_defined");
3596 DEBUG("is_mem_defined\n");
sewardj7cf4e6b2008-05-01 20:24:26 +00003597
3598 if (otag) *otag = 0;
3599 if (bad_addr) *bad_addr = 0;
njn25e49d8e72002-09-23 09:36:25 +00003600 for (i = 0; i < len; i++) {
njndbf7ca72006-03-31 11:57:59 +00003601 PROF_EVENT(65, "is_mem_defined(loop)");
njn1d0825f2006-03-27 11:37:07 +00003602 vabits2 = get_vabits2(a);
njndbf7ca72006-03-31 11:57:59 +00003603 if (VA_BITS2_DEFINED != vabits2) {
njn1d0825f2006-03-27 11:37:07 +00003604 // Error! Nb: Report addressability errors in preference to
3605 // definedness errors. And don't report definedeness errors unless
3606 // --undef-value-errors=yes.
sewardj7cf4e6b2008-05-01 20:24:26 +00003607 if (bad_addr) {
3608 *bad_addr = a;
3609 }
3610 if (VA_BITS2_NOACCESS == vabits2) {
3611 return MC_AddrErr;
3612 }
3613 if (MC_(clo_mc_level) >= 2) {
3614 if (otag && MC_(clo_mc_level) == 3) {
3615 *otag = MC_(helperc_b_load1)( a );
3616 }
3617 return MC_ValueErr;
3618 }
njn25e49d8e72002-09-23 09:36:25 +00003619 }
3620 a++;
3621 }
nethercote8b76fe52004-11-08 19:20:09 +00003622 return MC_Ok;
njn25e49d8e72002-09-23 09:36:25 +00003623}
3624
3625
sewardj4ef552a2011-10-24 05:59:54 +00003626/* Like is_mem_defined but doesn't give up at the first uninitialised
3627 byte -- the entire range is always checked. This is important for
3628 detecting errors in the case where a checked range strays into
3629 invalid memory, but that fact is not detected by the ordinary
3630 is_mem_defined(), because of an undefined section that precedes the
3631 out of range section, possibly as a result of an alignment hole in
3632 the checked data. This version always checks the entire range and
3633 can report both a definedness and an accessbility error, if
3634 necessary. */
3635static void is_mem_defined_comprehensive (
3636 Addr a, SizeT len,
3637 /*OUT*/Bool* errorV, /* is there a definedness err? */
3638 /*OUT*/Addr* bad_addrV, /* if so where? */
3639 /*OUT*/UInt* otagV, /* and what's its otag? */
3640 /*OUT*/Bool* errorA, /* is there an addressability err? */
3641 /*OUT*/Addr* bad_addrA /* if so where? */
3642 )
3643{
3644 SizeT i;
3645 UWord vabits2;
3646 Bool already_saw_errV = False;
3647
3648 PROF_EVENT(64, "is_mem_defined"); // fixme
3649 DEBUG("is_mem_defined_comprehensive\n");
3650
3651 tl_assert(!(*errorV || *errorA));
3652
3653 for (i = 0; i < len; i++) {
3654 PROF_EVENT(65, "is_mem_defined(loop)"); // fixme
3655 vabits2 = get_vabits2(a);
3656 switch (vabits2) {
3657 case VA_BITS2_DEFINED:
3658 a++;
3659 break;
3660 case VA_BITS2_UNDEFINED:
3661 case VA_BITS2_PARTDEFINED:
3662 if (!already_saw_errV) {
3663 *errorV = True;
3664 *bad_addrV = a;
3665 if (MC_(clo_mc_level) == 3) {
3666 *otagV = MC_(helperc_b_load1)( a );
3667 } else {
3668 *otagV = 0;
3669 }
3670 already_saw_errV = True;
3671 }
3672 a++; /* keep going */
3673 break;
3674 case VA_BITS2_NOACCESS:
3675 *errorA = True;
3676 *bad_addrA = a;
3677 return; /* give up now. */
3678 default:
3679 tl_assert(0);
3680 }
3681 }
3682}
3683
3684
njn25e49d8e72002-09-23 09:36:25 +00003685/* Check a zero-terminated ascii string. Tricky -- don't want to
3686 examine the actual bytes, to find the end, until we're sure it is
3687 safe to do so. */
3688
sewardj7cf4e6b2008-05-01 20:24:26 +00003689static Bool mc_is_defined_asciiz ( Addr a, Addr* bad_addr, UInt* otag )
njn25e49d8e72002-09-23 09:36:25 +00003690{
njn1d0825f2006-03-27 11:37:07 +00003691 UWord vabits2;
3692
njndbf7ca72006-03-31 11:57:59 +00003693 PROF_EVENT(66, "mc_is_defined_asciiz");
3694 DEBUG("mc_is_defined_asciiz\n");
sewardj7cf4e6b2008-05-01 20:24:26 +00003695
3696 if (otag) *otag = 0;
3697 if (bad_addr) *bad_addr = 0;
njn25e49d8e72002-09-23 09:36:25 +00003698 while (True) {
njndbf7ca72006-03-31 11:57:59 +00003699 PROF_EVENT(67, "mc_is_defined_asciiz(loop)");
njn1d0825f2006-03-27 11:37:07 +00003700 vabits2 = get_vabits2(a);
njndbf7ca72006-03-31 11:57:59 +00003701 if (VA_BITS2_DEFINED != vabits2) {
njn1d0825f2006-03-27 11:37:07 +00003702 // Error! Nb: Report addressability errors in preference to
3703 // definedness errors. And don't report definedeness errors unless
3704 // --undef-value-errors=yes.
sewardj7cf4e6b2008-05-01 20:24:26 +00003705 if (bad_addr) {
3706 *bad_addr = a;
3707 }
3708 if (VA_BITS2_NOACCESS == vabits2) {
3709 return MC_AddrErr;
3710 }
3711 if (MC_(clo_mc_level) >= 2) {
3712 if (otag && MC_(clo_mc_level) == 3) {
3713 *otag = MC_(helperc_b_load1)( a );
3714 }
3715 return MC_ValueErr;
3716 }
njn25e49d8e72002-09-23 09:36:25 +00003717 }
3718 /* Ok, a is safe to read. */
njn1d0825f2006-03-27 11:37:07 +00003719 if (* ((UChar*)a) == 0) {
sewardj45d94cc2005-04-20 14:44:11 +00003720 return MC_Ok;
njn1d0825f2006-03-27 11:37:07 +00003721 }
njn25e49d8e72002-09-23 09:36:25 +00003722 a++;
3723 }
3724}
3725
3726
3727/*------------------------------------------------------------*/
3728/*--- Memory event handlers ---*/
3729/*------------------------------------------------------------*/
3730
njn25e49d8e72002-09-23 09:36:25 +00003731static
floriane543f302012-10-21 19:43:43 +00003732void check_mem_is_addressable ( CorePart part, ThreadId tid, const HChar* s,
njndbf7ca72006-03-31 11:57:59 +00003733 Addr base, SizeT size )
njn25e49d8e72002-09-23 09:36:25 +00003734{
njn25e49d8e72002-09-23 09:36:25 +00003735 Addr bad_addr;
njndbf7ca72006-03-31 11:57:59 +00003736 Bool ok = is_mem_addressable ( base, size, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +00003737
njn25e49d8e72002-09-23 09:36:25 +00003738 if (!ok) {
3739 switch (part) {
3740 case Vg_CoreSysCall:
sewardj7ce71662008-05-02 10:33:15 +00003741 MC_(record_memparam_error) ( tid, bad_addr,
3742 /*isAddrErr*/True, s, 0/*otag*/ );
njn25e49d8e72002-09-23 09:36:25 +00003743 break;
3744
njn25e49d8e72002-09-23 09:36:25 +00003745 case Vg_CoreSignal:
njn1dcee092009-02-24 03:07:37 +00003746 MC_(record_core_mem_error)( tid, s );
njn25e49d8e72002-09-23 09:36:25 +00003747 break;
3748
3749 default:
njndbf7ca72006-03-31 11:57:59 +00003750 VG_(tool_panic)("check_mem_is_addressable: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +00003751 }
3752 }
njn25e49d8e72002-09-23 09:36:25 +00003753}
3754
3755static
floriane543f302012-10-21 19:43:43 +00003756void check_mem_is_defined ( CorePart part, ThreadId tid, const HChar* s,
nethercote451eae92004-11-02 13:06:32 +00003757 Addr base, SizeT size )
njn25e49d8e72002-09-23 09:36:25 +00003758{
sewardj7cf4e6b2008-05-01 20:24:26 +00003759 UInt otag = 0;
njn25e49d8e72002-09-23 09:36:25 +00003760 Addr bad_addr;
sewardj7cf4e6b2008-05-01 20:24:26 +00003761 MC_ReadResult res = is_mem_defined ( base, size, &bad_addr, &otag );
sewardj45f4e7c2005-09-27 19:20:21 +00003762
nethercote8b76fe52004-11-08 19:20:09 +00003763 if (MC_Ok != res) {
njn718d3b12006-12-16 00:54:12 +00003764 Bool isAddrErr = ( MC_AddrErr == res ? True : False );
sewardj45f4e7c2005-09-27 19:20:21 +00003765
njn25e49d8e72002-09-23 09:36:25 +00003766 switch (part) {
3767 case Vg_CoreSysCall:
sewardj7ce71662008-05-02 10:33:15 +00003768 MC_(record_memparam_error) ( tid, bad_addr, isAddrErr, s,
3769 isAddrErr ? 0 : otag );
njn25e49d8e72002-09-23 09:36:25 +00003770 break;
3771
njnf76d27a2009-05-28 01:53:07 +00003772 case Vg_CoreSysCallArgInMem:
3773 MC_(record_regparam_error) ( tid, s, otag );
3774 break;
3775
njn25e49d8e72002-09-23 09:36:25 +00003776 /* If we're being asked to jump to a silly address, record an error
3777 message before potentially crashing the entire system. */
3778 case Vg_CoreTranslate:
sewardj7ce71662008-05-02 10:33:15 +00003779 MC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +00003780 break;
3781
3782 default:
njndbf7ca72006-03-31 11:57:59 +00003783 VG_(tool_panic)("check_mem_is_defined: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +00003784 }
3785 }
njn25e49d8e72002-09-23 09:36:25 +00003786}
3787
3788static
njndbf7ca72006-03-31 11:57:59 +00003789void check_mem_is_defined_asciiz ( CorePart part, ThreadId tid,
floriane543f302012-10-21 19:43:43 +00003790 const HChar* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +00003791{
nethercote8b76fe52004-11-08 19:20:09 +00003792 MC_ReadResult res;
njn5ab96ac2005-05-08 02:59:50 +00003793 Addr bad_addr = 0; // shut GCC up
sewardj7cf4e6b2008-05-01 20:24:26 +00003794 UInt otag = 0;
njn25e49d8e72002-09-23 09:36:25 +00003795
njnca82cc02004-11-22 17:18:48 +00003796 tl_assert(part == Vg_CoreSysCall);
sewardj7cf4e6b2008-05-01 20:24:26 +00003797 res = mc_is_defined_asciiz ( (Addr)str, &bad_addr, &otag );
nethercote8b76fe52004-11-08 19:20:09 +00003798 if (MC_Ok != res) {
njn718d3b12006-12-16 00:54:12 +00003799 Bool isAddrErr = ( MC_AddrErr == res ? True : False );
sewardj7ce71662008-05-02 10:33:15 +00003800 MC_(record_memparam_error) ( tid, bad_addr, isAddrErr, s,
3801 isAddrErr ? 0 : otag );
njn25e49d8e72002-09-23 09:36:25 +00003802 }
njn25e49d8e72002-09-23 09:36:25 +00003803}
3804
sewardj6f95e7e2010-01-27 10:28:00 +00003805/* Handling of mmap and mprotect is not as simple as it seems.
3806
3807 The underlying semantics are that memory obtained from mmap is
3808 always initialised, but may be inaccessible. And changes to the
3809 protection of memory do not change its contents and hence not its
3810 definedness state. Problem is we can't model
3811 inaccessible-but-with-some-definedness state; once we mark memory
3812 as inaccessible we lose all info about definedness, and so can't
3813 restore that if it is later made accessible again.
3814
3815 One obvious thing to do is this:
3816
3817 mmap/mprotect NONE -> noaccess
3818 mmap/mprotect other -> defined
3819
3820 The problem case here is: taking accessible memory, writing
3821 uninitialised data to it, mprotecting it NONE and later mprotecting
3822 it back to some accessible state causes the undefinedness to be
3823 lost.
3824
3825 A better proposal is:
3826
3827 (1) mmap NONE -> make noaccess
3828 (2) mmap other -> make defined
3829
3830 (3) mprotect NONE -> # no change
3831 (4) mprotect other -> change any "noaccess" to "defined"
3832
3833 (2) is OK because memory newly obtained from mmap really is defined
3834 (zeroed out by the kernel -- doing anything else would
3835 constitute a massive security hole.)
3836
3837 (1) is OK because the only way to make the memory usable is via
3838 (4), in which case we also wind up correctly marking it all as
3839 defined.
3840
3841 (3) is the weak case. We choose not to change memory state.
3842 (presumably the range is in some mixture of "defined" and
3843 "undefined", viz, accessible but with arbitrary V bits). Doing
3844 nothing means we retain the V bits, so that if the memory is
3845 later mprotected "other", the V bits remain unchanged, so there
3846 can be no false negatives. The bad effect is that if there's
3847 an access in the area, then MC cannot warn; but at least we'll
3848 get a SEGV to show, so it's better than nothing.
3849
3850 Consider the sequence (3) followed by (4). Any memory that was
3851 "defined" or "undefined" previously retains its state (as
3852 required). Any memory that was "noaccess" before can only have
3853 been made that way by (1), and so it's OK to change it to
3854 "defined".
3855
3856 See https://bugs.kde.org/show_bug.cgi?id=205541
3857 and https://bugs.kde.org/show_bug.cgi?id=210268
3858*/
njn25e49d8e72002-09-23 09:36:25 +00003859static
njnf76d27a2009-05-28 01:53:07 +00003860void mc_new_mem_mmap ( Addr a, SizeT len, Bool rr, Bool ww, Bool xx,
3861 ULong di_handle )
3862{
sewardj6f95e7e2010-01-27 10:28:00 +00003863 if (rr || ww || xx) {
3864 /* (2) mmap/mprotect other -> defined */
njnf76d27a2009-05-28 01:53:07 +00003865 MC_(make_mem_defined)(a, len);
sewardj6f95e7e2010-01-27 10:28:00 +00003866 } else {
3867 /* (1) mmap/mprotect NONE -> noaccess */
njnf76d27a2009-05-28 01:53:07 +00003868 MC_(make_mem_noaccess)(a, len);
sewardj6f95e7e2010-01-27 10:28:00 +00003869 }
njnf76d27a2009-05-28 01:53:07 +00003870}
3871
3872static
sewardj6f95e7e2010-01-27 10:28:00 +00003873void mc_new_mem_mprotect ( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
3874{
3875 if (rr || ww || xx) {
3876 /* (4) mprotect other -> change any "noaccess" to "defined" */
3877 make_mem_defined_if_noaccess(a, len);
3878 } else {
3879 /* (3) mprotect NONE -> # no change */
3880 /* do nothing */
3881 }
3882}
3883
3884
3885static
sewardj9c606bd2008-09-18 18:12:50 +00003886void mc_new_mem_startup( Addr a, SizeT len,
3887 Bool rr, Bool ww, Bool xx, ULong di_handle )
njn25e49d8e72002-09-23 09:36:25 +00003888{
njnba7b4582006-09-21 15:59:30 +00003889 // Because code is defined, initialised variables get put in the data
3890 // segment and are defined, and uninitialised variables get put in the
3891 // bss segment and are auto-zeroed (and so defined).
3892 //
3893 // It's possible that there will be padding between global variables.
3894 // This will also be auto-zeroed, and marked as defined by Memcheck. If
3895 // a program uses it, Memcheck will not complain. This is arguably a
3896 // false negative, but it's a grey area -- the behaviour is defined (the
3897 // padding is zeroed) but it's probably not what the user intended. And
3898 // we can't avoid it.
njnf76d27a2009-05-28 01:53:07 +00003899 //
3900 // Note: we generally ignore RWX permissions, because we can't track them
3901 // without requiring more than one A bit which would slow things down a
3902 // lot. But on Darwin the 0th page is mapped but !R and !W and !X.
3903 // So we mark any such pages as "unaddressable".
barta0b6b2c2008-07-07 06:49:24 +00003904 DEBUG("mc_new_mem_startup(%#lx, %llu, rr=%u, ww=%u, xx=%u)\n",
njndbf7ca72006-03-31 11:57:59 +00003905 a, (ULong)len, rr, ww, xx);
njnf76d27a2009-05-28 01:53:07 +00003906 mc_new_mem_mmap(a, len, rr, ww, xx, di_handle);
njn25e49d8e72002-09-23 09:36:25 +00003907}
3908
njncf45fd42004-11-24 16:30:22 +00003909static
3910void mc_post_mem_write(CorePart part, ThreadId tid, Addr a, SizeT len)
3911{
njndbf7ca72006-03-31 11:57:59 +00003912 MC_(make_mem_defined)(a, len);
njncf45fd42004-11-24 16:30:22 +00003913}
njn25e49d8e72002-09-23 09:36:25 +00003914
sewardj45d94cc2005-04-20 14:44:11 +00003915
njn25e49d8e72002-09-23 09:36:25 +00003916/*------------------------------------------------------------*/
njnd3040452003-05-19 15:04:06 +00003917/*--- Register event handlers ---*/
3918/*------------------------------------------------------------*/
3919
sewardj7cf4e6b2008-05-01 20:24:26 +00003920/* Try and get a nonzero origin for the guest state section of thread
3921 tid characterised by (offset,size). Return 0 if nothing to show
3922 for it. */
3923static UInt mb_get_origin_for_guest_offset ( ThreadId tid,
3924 Int offset, SizeT size )
3925{
3926 Int sh2off;
florian3dfd6bb2012-03-03 18:46:05 +00003927 UInt area[3];
sewardj7cf4e6b2008-05-01 20:24:26 +00003928 UInt otag;
3929 sh2off = MC_(get_otrack_shadow_offset)( offset, size );
3930 if (sh2off == -1)
3931 return 0; /* This piece of guest state is not tracked */
3932 tl_assert(sh2off >= 0);
3933 tl_assert(0 == (sh2off % 4));
florian3dfd6bb2012-03-03 18:46:05 +00003934 area[0] = 0x31313131;
3935 area[2] = 0x27272727;
3936 VG_(get_shadow_regs_area)( tid, (UChar *)&area[1], 2/*shadowno*/,sh2off,4 );
3937 tl_assert(area[0] == 0x31313131);
3938 tl_assert(area[2] == 0x27272727);
3939 otag = area[1];
sewardj7cf4e6b2008-05-01 20:24:26 +00003940 return otag;
3941}
3942
3943
sewardj45d94cc2005-04-20 14:44:11 +00003944/* When some chunk of guest state is written, mark the corresponding
3945 shadow area as valid. This is used to initialise arbitrarily large
sewardj62eae5f2006-01-17 01:58:24 +00003946 chunks of guest state, hence the _SIZE value, which has to be as
3947 big as the biggest guest state.
sewardj45d94cc2005-04-20 14:44:11 +00003948*/
3949static void mc_post_reg_write ( CorePart part, ThreadId tid,
njnc4431bf2009-01-15 21:29:24 +00003950 PtrdiffT offset, SizeT size)
njnd3040452003-05-19 15:04:06 +00003951{
sewardj2ac31f42012-05-21 11:01:35 +00003952# define MAX_REG_WRITE_SIZE 1696
cerion21082042005-12-06 19:07:08 +00003953 UChar area[MAX_REG_WRITE_SIZE];
3954 tl_assert(size <= MAX_REG_WRITE_SIZE);
njn1d0825f2006-03-27 11:37:07 +00003955 VG_(memset)(area, V_BITS8_DEFINED, size);
sewardj7cf4e6b2008-05-01 20:24:26 +00003956 VG_(set_shadow_regs_area)( tid, 1/*shadowNo*/,offset,size, area );
cerion21082042005-12-06 19:07:08 +00003957# undef MAX_REG_WRITE_SIZE
njnd3040452003-05-19 15:04:06 +00003958}
3959
sewardj45d94cc2005-04-20 14:44:11 +00003960static
3961void mc_post_reg_write_clientcall ( ThreadId tid,
njnc4431bf2009-01-15 21:29:24 +00003962 PtrdiffT offset, SizeT size, Addr f)
njnd3040452003-05-19 15:04:06 +00003963{
njncf45fd42004-11-24 16:30:22 +00003964 mc_post_reg_write(/*dummy*/0, tid, offset, size);
njnd3040452003-05-19 15:04:06 +00003965}
3966
sewardj45d94cc2005-04-20 14:44:11 +00003967/* Look at the definedness of the guest's shadow state for
3968 [offset, offset+len). If any part of that is undefined, record
3969 a parameter error.
3970*/
floriane543f302012-10-21 19:43:43 +00003971static void mc_pre_reg_read ( CorePart part, ThreadId tid, const HChar* s,
njnc4431bf2009-01-15 21:29:24 +00003972 PtrdiffT offset, SizeT size)
nethercote8b76fe52004-11-08 19:20:09 +00003973{
sewardj45d94cc2005-04-20 14:44:11 +00003974 Int i;
3975 Bool bad;
sewardj7cf4e6b2008-05-01 20:24:26 +00003976 UInt otag;
sewardj45d94cc2005-04-20 14:44:11 +00003977
3978 UChar area[16];
3979 tl_assert(size <= 16);
3980
sewardj7cf4e6b2008-05-01 20:24:26 +00003981 VG_(get_shadow_regs_area)( tid, area, 1/*shadowNo*/,offset,size );
sewardj45d94cc2005-04-20 14:44:11 +00003982
3983 bad = False;
3984 for (i = 0; i < size; i++) {
njn1d0825f2006-03-27 11:37:07 +00003985 if (area[i] != V_BITS8_DEFINED) {
sewardj2c27f702005-05-03 18:19:05 +00003986 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00003987 break;
3988 }
nethercote8b76fe52004-11-08 19:20:09 +00003989 }
3990
sewardj7cf4e6b2008-05-01 20:24:26 +00003991 if (!bad)
3992 return;
3993
3994 /* We've found some undefinedness. See if we can also find an
3995 origin for it. */
3996 otag = mb_get_origin_for_guest_offset( tid, offset, size );
sewardj7ce71662008-05-02 10:33:15 +00003997 MC_(record_regparam_error) ( tid, s, otag );
nethercote8b76fe52004-11-08 19:20:09 +00003998}
njnd3040452003-05-19 15:04:06 +00003999
njn25e49d8e72002-09-23 09:36:25 +00004000
sewardj6cf40ff2005-04-20 22:31:26 +00004001/*------------------------------------------------------------*/
sewardjc859fbf2005-04-22 21:10:28 +00004002/*--- Functions called directly from generated code: ---*/
4003/*--- Load/store handlers. ---*/
sewardj6cf40ff2005-04-20 22:31:26 +00004004/*------------------------------------------------------------*/
4005
njn1d0825f2006-03-27 11:37:07 +00004006/* Types: LOADV32, LOADV16, LOADV8 are:
sewardj6cf40ff2005-04-20 22:31:26 +00004007 UWord fn ( Addr a )
4008 so they return 32-bits on 32-bit machines and 64-bits on
4009 64-bit machines. Addr has the same size as a host word.
4010
njn1d0825f2006-03-27 11:37:07 +00004011 LOADV64 is always ULong fn ( Addr a )
sewardj6cf40ff2005-04-20 22:31:26 +00004012
njn1d0825f2006-03-27 11:37:07 +00004013 Similarly for STOREV8, STOREV16, STOREV32, the supplied vbits
4014 are a UWord, and for STOREV64 they are a ULong.
sewardj6cf40ff2005-04-20 22:31:26 +00004015*/
4016
sewardj7244e712008-05-02 12:35:48 +00004017/* If any part of '_a' indicated by the mask is 1, either '_a' is not
4018 naturally '_sz/8'-aligned, or it exceeds the range covered by the
4019 primary map. This is all very tricky (and important!), so let's
4020 work through the maths by hand (below), *and* assert for these
4021 values at startup. */
4022#define MASK(_szInBytes) \
4023 ( ~((0x10000UL-(_szInBytes)) | ((N_PRIMARY_MAP-1) << 16)) )
4024
4025/* MASK only exists so as to define this macro. */
4026#define UNALIGNED_OR_HIGH(_a,_szInBits) \
4027 ((_a) & MASK((_szInBits>>3)))
4028
4029/* On a 32-bit machine:
4030
4031 N_PRIMARY_BITS == 16, so
4032 N_PRIMARY_MAP == 0x10000, so
4033 N_PRIMARY_MAP-1 == 0xFFFF, so
4034 (N_PRIMARY_MAP-1) << 16 == 0xFFFF0000, and so
4035
4036 MASK(1) = ~ ( (0x10000 - 1) | 0xFFFF0000 )
4037 = ~ ( 0xFFFF | 0xFFFF0000 )
4038 = ~ 0xFFFF'FFFF
4039 = 0
4040
4041 MASK(2) = ~ ( (0x10000 - 2) | 0xFFFF0000 )
4042 = ~ ( 0xFFFE | 0xFFFF0000 )
4043 = ~ 0xFFFF'FFFE
4044 = 1
4045
4046 MASK(4) = ~ ( (0x10000 - 4) | 0xFFFF0000 )
4047 = ~ ( 0xFFFC | 0xFFFF0000 )
4048 = ~ 0xFFFF'FFFC
4049 = 3
4050
4051 MASK(8) = ~ ( (0x10000 - 8) | 0xFFFF0000 )
4052 = ~ ( 0xFFF8 | 0xFFFF0000 )
4053 = ~ 0xFFFF'FFF8
4054 = 7
4055
4056 Hence in the 32-bit case, "a & MASK(1/2/4/8)" is a nonzero value
4057 precisely when a is not 1/2/4/8-bytes aligned. And obviously, for
4058 the 1-byte alignment case, it is always a zero value, since MASK(1)
4059 is zero. All as expected.
4060
4061 On a 64-bit machine, it's more complex, since we're testing
4062 simultaneously for misalignment and for the address being at or
4063 above 32G:
4064
4065 N_PRIMARY_BITS == 19, so
4066 N_PRIMARY_MAP == 0x80000, so
4067 N_PRIMARY_MAP-1 == 0x7FFFF, so
4068 (N_PRIMARY_MAP-1) << 16 == 0x7FFFF'0000, and so
4069
4070 MASK(1) = ~ ( (0x10000 - 1) | 0x7FFFF'0000 )
4071 = ~ ( 0xFFFF | 0x7FFFF'0000 )
4072 = ~ 0x7FFFF'FFFF
4073 = 0xFFFF'FFF8'0000'0000
4074
4075 MASK(2) = ~ ( (0x10000 - 2) | 0x7FFFF'0000 )
4076 = ~ ( 0xFFFE | 0x7FFFF'0000 )
4077 = ~ 0x7FFFF'FFFE
4078 = 0xFFFF'FFF8'0000'0001
4079
4080 MASK(4) = ~ ( (0x10000 - 4) | 0x7FFFF'0000 )
4081 = ~ ( 0xFFFC | 0x7FFFF'0000 )
4082 = ~ 0x7FFFF'FFFC
4083 = 0xFFFF'FFF8'0000'0003
4084
4085 MASK(8) = ~ ( (0x10000 - 8) | 0x7FFFF'0000 )
4086 = ~ ( 0xFFF8 | 0x7FFFF'0000 )
4087 = ~ 0x7FFFF'FFF8
4088 = 0xFFFF'FFF8'0000'0007
4089*/
njn1d0825f2006-03-27 11:37:07 +00004090
4091
sewardj95448072004-11-22 20:19:51 +00004092/* ------------------------ Size = 8 ------------------------ */
4093
njn1d0825f2006-03-27 11:37:07 +00004094static INLINE
4095ULong mc_LOADV64 ( Addr a, Bool isBigEndian )
4096{
njn1d0825f2006-03-27 11:37:07 +00004097 PROF_EVENT(200, "mc_LOADV64");
4098
4099#ifndef PERF_FAST_LOADV
njn45e81252006-03-28 12:35:08 +00004100 return mc_LOADVn_slow( a, 64, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00004101#else
njneccf7c02009-01-19 23:42:45 +00004102 {
4103 UWord sm_off16, vabits16;
4104 SecMap* sm;
sewardjf9d81612005-04-23 23:25:49 +00004105
njneccf7c02009-01-19 23:42:45 +00004106 if (UNLIKELY( UNALIGNED_OR_HIGH(a,64) )) {
4107 PROF_EVENT(201, "mc_LOADV64-slow1");
4108 return (ULong)mc_LOADVn_slow( a, 64, isBigEndian );
4109 }
njn1d0825f2006-03-27 11:37:07 +00004110
njneccf7c02009-01-19 23:42:45 +00004111 sm = get_secmap_for_reading_low(a);
4112 sm_off16 = SM_OFF_16(a);
4113 vabits16 = ((UShort*)(sm->vabits8))[sm_off16];
4114
4115 // Handle common case quickly: a is suitably aligned, is mapped, and
4116 // addressible.
4117 // Convert V bits from compact memory form to expanded register form.
4118 if (LIKELY(vabits16 == VA_BITS16_DEFINED)) {
4119 return V_BITS64_DEFINED;
4120 } else if (LIKELY(vabits16 == VA_BITS16_UNDEFINED)) {
4121 return V_BITS64_UNDEFINED;
4122 } else {
4123 /* Slow case: the 8 bytes are not all-defined or all-undefined. */
4124 PROF_EVENT(202, "mc_LOADV64-slow2");
4125 return mc_LOADVn_slow( a, 64, isBigEndian );
4126 }
njn1d0825f2006-03-27 11:37:07 +00004127 }
4128#endif
4129}
4130
4131VG_REGPARM(1) ULong MC_(helperc_LOADV64be) ( Addr a )
4132{
4133 return mc_LOADV64(a, True);
4134}
4135VG_REGPARM(1) ULong MC_(helperc_LOADV64le) ( Addr a )
4136{
4137 return mc_LOADV64(a, False);
4138}
sewardjf9d81612005-04-23 23:25:49 +00004139
sewardjf9d81612005-04-23 23:25:49 +00004140
njn1d0825f2006-03-27 11:37:07 +00004141static INLINE
njn4cf530b2006-04-06 13:33:48 +00004142void mc_STOREV64 ( Addr a, ULong vbits64, Bool isBigEndian )
njn1d0825f2006-03-27 11:37:07 +00004143{
njn1d0825f2006-03-27 11:37:07 +00004144 PROF_EVENT(210, "mc_STOREV64");
4145
4146#ifndef PERF_FAST_STOREV
4147 // XXX: this slow case seems to be marginally faster than the fast case!
4148 // Investigate further.
njn4cf530b2006-04-06 13:33:48 +00004149 mc_STOREVn_slow( a, 64, vbits64, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00004150#else
njn1d0825f2006-03-27 11:37:07 +00004151 {
njneccf7c02009-01-19 23:42:45 +00004152 UWord sm_off16, vabits16;
4153 SecMap* sm;
4154
4155 if (UNLIKELY( UNALIGNED_OR_HIGH(a,64) )) {
4156 PROF_EVENT(211, "mc_STOREV64-slow1");
4157 mc_STOREVn_slow( a, 64, vbits64, isBigEndian );
4158 return;
4159 }
4160
4161 sm = get_secmap_for_reading_low(a);
4162 sm_off16 = SM_OFF_16(a);
4163 vabits16 = ((UShort*)(sm->vabits8))[sm_off16];
4164
4165 if (LIKELY( !is_distinguished_sm(sm) &&
4166 (VA_BITS16_DEFINED == vabits16 ||
4167 VA_BITS16_UNDEFINED == vabits16) ))
4168 {
4169 /* Handle common case quickly: a is suitably aligned, */
4170 /* is mapped, and is addressible. */
4171 // Convert full V-bits in register to compact 2-bit form.
4172 if (V_BITS64_DEFINED == vbits64) {
4173 ((UShort*)(sm->vabits8))[sm_off16] = (UShort)VA_BITS16_DEFINED;
4174 } else if (V_BITS64_UNDEFINED == vbits64) {
4175 ((UShort*)(sm->vabits8))[sm_off16] = (UShort)VA_BITS16_UNDEFINED;
4176 } else {
4177 /* Slow but general case -- writing partially defined bytes. */
4178 PROF_EVENT(212, "mc_STOREV64-slow2");
4179 mc_STOREVn_slow( a, 64, vbits64, isBigEndian );
4180 }
njn1d0825f2006-03-27 11:37:07 +00004181 } else {
njneccf7c02009-01-19 23:42:45 +00004182 /* Slow but general case. */
4183 PROF_EVENT(213, "mc_STOREV64-slow3");
njn4cf530b2006-04-06 13:33:48 +00004184 mc_STOREVn_slow( a, 64, vbits64, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00004185 }
njn1d0825f2006-03-27 11:37:07 +00004186 }
4187#endif
4188}
4189
njn4cf530b2006-04-06 13:33:48 +00004190VG_REGPARM(1) void MC_(helperc_STOREV64be) ( Addr a, ULong vbits64 )
njn1d0825f2006-03-27 11:37:07 +00004191{
njn4cf530b2006-04-06 13:33:48 +00004192 mc_STOREV64(a, vbits64, True);
njn1d0825f2006-03-27 11:37:07 +00004193}
njn4cf530b2006-04-06 13:33:48 +00004194VG_REGPARM(1) void MC_(helperc_STOREV64le) ( Addr a, ULong vbits64 )
njn1d0825f2006-03-27 11:37:07 +00004195{
njn4cf530b2006-04-06 13:33:48 +00004196 mc_STOREV64(a, vbits64, False);
njn1d0825f2006-03-27 11:37:07 +00004197}
sewardj95448072004-11-22 20:19:51 +00004198
sewardj95448072004-11-22 20:19:51 +00004199
4200/* ------------------------ Size = 4 ------------------------ */
4201
njn1d0825f2006-03-27 11:37:07 +00004202static INLINE
4203UWord mc_LOADV32 ( Addr a, Bool isBigEndian )
4204{
njn1d0825f2006-03-27 11:37:07 +00004205 PROF_EVENT(220, "mc_LOADV32");
4206
4207#ifndef PERF_FAST_LOADV
njn45e81252006-03-28 12:35:08 +00004208 return (UWord)mc_LOADVn_slow( a, 32, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00004209#else
njneccf7c02009-01-19 23:42:45 +00004210 {
4211 UWord sm_off, vabits8;
4212 SecMap* sm;
sewardjc1a2cda2005-04-21 17:34:00 +00004213
njneccf7c02009-01-19 23:42:45 +00004214 if (UNLIKELY( UNALIGNED_OR_HIGH(a,32) )) {
4215 PROF_EVENT(221, "mc_LOADV32-slow1");
4216 return (UWord)mc_LOADVn_slow( a, 32, isBigEndian );
4217 }
njn1d0825f2006-03-27 11:37:07 +00004218
njneccf7c02009-01-19 23:42:45 +00004219 sm = get_secmap_for_reading_low(a);
4220 sm_off = SM_OFF(a);
4221 vabits8 = sm->vabits8[sm_off];
4222
4223 // Handle common case quickly: a is suitably aligned, is mapped, and the
4224 // entire word32 it lives in is addressible.
4225 // Convert V bits from compact memory form to expanded register form.
4226 // For 64-bit platforms, set the high 32 bits of retval to 1 (undefined).
4227 // Almost certainly not necessary, but be paranoid.
4228 if (LIKELY(vabits8 == VA_BITS8_DEFINED)) {
4229 return ((UWord)0xFFFFFFFF00000000ULL | (UWord)V_BITS32_DEFINED);
4230 } else if (LIKELY(vabits8 == VA_BITS8_UNDEFINED)) {
4231 return ((UWord)0xFFFFFFFF00000000ULL | (UWord)V_BITS32_UNDEFINED);
4232 } else {
4233 /* Slow case: the 4 bytes are not all-defined or all-undefined. */
4234 PROF_EVENT(222, "mc_LOADV32-slow2");
4235 return (UWord)mc_LOADVn_slow( a, 32, isBigEndian );
4236 }
njn1d0825f2006-03-27 11:37:07 +00004237 }
4238#endif
4239}
4240
4241VG_REGPARM(1) UWord MC_(helperc_LOADV32be) ( Addr a )
4242{
4243 return mc_LOADV32(a, True);
4244}
4245VG_REGPARM(1) UWord MC_(helperc_LOADV32le) ( Addr a )
4246{
4247 return mc_LOADV32(a, False);
4248}
sewardjc1a2cda2005-04-21 17:34:00 +00004249
sewardjc1a2cda2005-04-21 17:34:00 +00004250
njn1d0825f2006-03-27 11:37:07 +00004251static INLINE
njn4cf530b2006-04-06 13:33:48 +00004252void mc_STOREV32 ( Addr a, UWord vbits32, Bool isBigEndian )
njn1d0825f2006-03-27 11:37:07 +00004253{
njn1d0825f2006-03-27 11:37:07 +00004254 PROF_EVENT(230, "mc_STOREV32");
4255
4256#ifndef PERF_FAST_STOREV
njn4cf530b2006-04-06 13:33:48 +00004257 mc_STOREVn_slow( a, 32, (ULong)vbits32, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00004258#else
njneccf7c02009-01-19 23:42:45 +00004259 {
4260 UWord sm_off, vabits8;
4261 SecMap* sm;
sewardjc1a2cda2005-04-21 17:34:00 +00004262
njneccf7c02009-01-19 23:42:45 +00004263 if (UNLIKELY( UNALIGNED_OR_HIGH(a,32) )) {
4264 PROF_EVENT(231, "mc_STOREV32-slow1");
4265 mc_STOREVn_slow( a, 32, (ULong)vbits32, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00004266 return;
njneccf7c02009-01-19 23:42:45 +00004267 }
4268
4269 sm = get_secmap_for_reading_low(a);
4270 sm_off = SM_OFF(a);
4271 vabits8 = sm->vabits8[sm_off];
4272
4273 // Cleverness: sometimes we don't have to write the shadow memory at
4274 // all, if we can tell that what we want to write is the same as what is
4275 // already there. The 64/16/8 bit cases also have cleverness at this
4276 // point, but it works a little differently to the code below.
4277 if (V_BITS32_DEFINED == vbits32) {
4278 if (vabits8 == (UInt)VA_BITS8_DEFINED) {
4279 return;
4280 } else if (!is_distinguished_sm(sm) && VA_BITS8_UNDEFINED == vabits8) {
4281 sm->vabits8[sm_off] = (UInt)VA_BITS8_DEFINED;
4282 } else {
4283 // not defined/undefined, or distinguished and changing state
4284 PROF_EVENT(232, "mc_STOREV32-slow2");
4285 mc_STOREVn_slow( a, 32, (ULong)vbits32, isBigEndian );
4286 }
4287 } else if (V_BITS32_UNDEFINED == vbits32) {
4288 if (vabits8 == (UInt)VA_BITS8_UNDEFINED) {
4289 return;
4290 } else if (!is_distinguished_sm(sm) && VA_BITS8_DEFINED == vabits8) {
4291 sm->vabits8[sm_off] = (UInt)VA_BITS8_UNDEFINED;
4292 } else {
4293 // not defined/undefined, or distinguished and changing state
4294 PROF_EVENT(233, "mc_STOREV32-slow3");
4295 mc_STOREVn_slow( a, 32, (ULong)vbits32, isBigEndian );
4296 }
njn1d0825f2006-03-27 11:37:07 +00004297 } else {
njneccf7c02009-01-19 23:42:45 +00004298 // Partially defined word
4299 PROF_EVENT(234, "mc_STOREV32-slow4");
njn4cf530b2006-04-06 13:33:48 +00004300 mc_STOREVn_slow( a, 32, (ULong)vbits32, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00004301 }
njn1d0825f2006-03-27 11:37:07 +00004302 }
njn1d0825f2006-03-27 11:37:07 +00004303#endif
4304}
4305
njn4cf530b2006-04-06 13:33:48 +00004306VG_REGPARM(2) void MC_(helperc_STOREV32be) ( Addr a, UWord vbits32 )
njn1d0825f2006-03-27 11:37:07 +00004307{
njn4cf530b2006-04-06 13:33:48 +00004308 mc_STOREV32(a, vbits32, True);
njn1d0825f2006-03-27 11:37:07 +00004309}
njn4cf530b2006-04-06 13:33:48 +00004310VG_REGPARM(2) void MC_(helperc_STOREV32le) ( Addr a, UWord vbits32 )
njn1d0825f2006-03-27 11:37:07 +00004311{
njn4cf530b2006-04-06 13:33:48 +00004312 mc_STOREV32(a, vbits32, False);
njn1d0825f2006-03-27 11:37:07 +00004313}
njn25e49d8e72002-09-23 09:36:25 +00004314
njn25e49d8e72002-09-23 09:36:25 +00004315
sewardj95448072004-11-22 20:19:51 +00004316/* ------------------------ Size = 2 ------------------------ */
4317
njn1d0825f2006-03-27 11:37:07 +00004318static INLINE
4319UWord mc_LOADV16 ( Addr a, Bool isBigEndian )
4320{
njn1d0825f2006-03-27 11:37:07 +00004321 PROF_EVENT(240, "mc_LOADV16");
4322
4323#ifndef PERF_FAST_LOADV
njn45e81252006-03-28 12:35:08 +00004324 return (UWord)mc_LOADVn_slow( a, 16, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00004325#else
njneccf7c02009-01-19 23:42:45 +00004326 {
4327 UWord sm_off, vabits8;
4328 SecMap* sm;
sewardjc1a2cda2005-04-21 17:34:00 +00004329
njneccf7c02009-01-19 23:42:45 +00004330 if (UNLIKELY( UNALIGNED_OR_HIGH(a,16) )) {
4331 PROF_EVENT(241, "mc_LOADV16-slow1");
njn45e81252006-03-28 12:35:08 +00004332 return (UWord)mc_LOADVn_slow( a, 16, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00004333 }
njneccf7c02009-01-19 23:42:45 +00004334
4335 sm = get_secmap_for_reading_low(a);
4336 sm_off = SM_OFF(a);
4337 vabits8 = sm->vabits8[sm_off];
4338 // Handle common case quickly: a is suitably aligned, is mapped, and is
4339 // addressible.
4340 // Convert V bits from compact memory form to expanded register form
sewardj14a81782011-08-20 15:55:07 +00004341 if (LIKELY(vabits8 == VA_BITS8_DEFINED )) { return V_BITS16_DEFINED; }
4342 else if (LIKELY(vabits8 == VA_BITS8_UNDEFINED)) { return V_BITS16_UNDEFINED; }
njneccf7c02009-01-19 23:42:45 +00004343 else {
4344 // The 4 (yes, 4) bytes are not all-defined or all-undefined, check
4345 // the two sub-bytes.
4346 UChar vabits4 = extract_vabits4_from_vabits8(a, vabits8);
4347 if (vabits4 == VA_BITS4_DEFINED ) { return V_BITS16_DEFINED; }
4348 else if (vabits4 == VA_BITS4_UNDEFINED) { return V_BITS16_UNDEFINED; }
4349 else {
4350 /* Slow case: the two bytes are not all-defined or all-undefined. */
4351 PROF_EVENT(242, "mc_LOADV16-slow2");
4352 return (UWord)mc_LOADVn_slow( a, 16, isBigEndian );
4353 }
4354 }
njn1d0825f2006-03-27 11:37:07 +00004355 }
4356#endif
4357}
4358
4359VG_REGPARM(1) UWord MC_(helperc_LOADV16be) ( Addr a )
4360{
4361 return mc_LOADV16(a, True);
4362}
4363VG_REGPARM(1) UWord MC_(helperc_LOADV16le) ( Addr a )
4364{
4365 return mc_LOADV16(a, False);
4366}
sewardjc1a2cda2005-04-21 17:34:00 +00004367
sewardjc1a2cda2005-04-21 17:34:00 +00004368
njn1d0825f2006-03-27 11:37:07 +00004369static INLINE
njn4cf530b2006-04-06 13:33:48 +00004370void mc_STOREV16 ( Addr a, UWord vbits16, Bool isBigEndian )
njn1d0825f2006-03-27 11:37:07 +00004371{
njn1d0825f2006-03-27 11:37:07 +00004372 PROF_EVENT(250, "mc_STOREV16");
4373
4374#ifndef PERF_FAST_STOREV
njn4cf530b2006-04-06 13:33:48 +00004375 mc_STOREVn_slow( a, 16, (ULong)vbits16, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00004376#else
njn1d0825f2006-03-27 11:37:07 +00004377 {
njneccf7c02009-01-19 23:42:45 +00004378 UWord sm_off, vabits8;
4379 SecMap* sm;
4380
4381 if (UNLIKELY( UNALIGNED_OR_HIGH(a,16) )) {
4382 PROF_EVENT(251, "mc_STOREV16-slow1");
4383 mc_STOREVn_slow( a, 16, (ULong)vbits16, isBigEndian );
4384 return;
4385 }
4386
4387 sm = get_secmap_for_reading_low(a);
4388 sm_off = SM_OFF(a);
4389 vabits8 = sm->vabits8[sm_off];
4390 if (LIKELY( !is_distinguished_sm(sm) &&
4391 (VA_BITS8_DEFINED == vabits8 ||
4392 VA_BITS8_UNDEFINED == vabits8) ))
4393 {
4394 /* Handle common case quickly: a is suitably aligned, */
4395 /* is mapped, and is addressible. */
4396 // Convert full V-bits in register to compact 2-bit form.
4397 if (V_BITS16_DEFINED == vbits16) {
4398 insert_vabits4_into_vabits8( a, VA_BITS4_DEFINED ,
4399 &(sm->vabits8[sm_off]) );
4400 } else if (V_BITS16_UNDEFINED == vbits16) {
4401 insert_vabits4_into_vabits8( a, VA_BITS4_UNDEFINED,
4402 &(sm->vabits8[sm_off]) );
4403 } else {
4404 /* Slow but general case -- writing partially defined bytes. */
4405 PROF_EVENT(252, "mc_STOREV16-slow2");
4406 mc_STOREVn_slow( a, 16, (ULong)vbits16, isBigEndian );
4407 }
njn1d0825f2006-03-27 11:37:07 +00004408 } else {
njneccf7c02009-01-19 23:42:45 +00004409 /* Slow but general case. */
4410 PROF_EVENT(253, "mc_STOREV16-slow3");
njn4cf530b2006-04-06 13:33:48 +00004411 mc_STOREVn_slow( a, 16, (ULong)vbits16, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00004412 }
njn1d0825f2006-03-27 11:37:07 +00004413 }
4414#endif
4415}
njn25e49d8e72002-09-23 09:36:25 +00004416
njn4cf530b2006-04-06 13:33:48 +00004417VG_REGPARM(2) void MC_(helperc_STOREV16be) ( Addr a, UWord vbits16 )
njn1d0825f2006-03-27 11:37:07 +00004418{
njn4cf530b2006-04-06 13:33:48 +00004419 mc_STOREV16(a, vbits16, True);
njn1d0825f2006-03-27 11:37:07 +00004420}
njn4cf530b2006-04-06 13:33:48 +00004421VG_REGPARM(2) void MC_(helperc_STOREV16le) ( Addr a, UWord vbits16 )
njn1d0825f2006-03-27 11:37:07 +00004422{
njn4cf530b2006-04-06 13:33:48 +00004423 mc_STOREV16(a, vbits16, False);
njn1d0825f2006-03-27 11:37:07 +00004424}
sewardj5d28efc2005-04-21 22:16:29 +00004425
njn25e49d8e72002-09-23 09:36:25 +00004426
sewardj95448072004-11-22 20:19:51 +00004427/* ------------------------ Size = 1 ------------------------ */
sewardj8cf88b72005-07-08 01:29:33 +00004428/* Note: endianness is irrelevant for size == 1 */
sewardj95448072004-11-22 20:19:51 +00004429
njnaf839f52005-06-23 03:27:57 +00004430VG_REGPARM(1)
njn1d0825f2006-03-27 11:37:07 +00004431UWord MC_(helperc_LOADV8) ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00004432{
njn1d0825f2006-03-27 11:37:07 +00004433 PROF_EVENT(260, "mc_LOADV8");
sewardjc1a2cda2005-04-21 17:34:00 +00004434
njn1d0825f2006-03-27 11:37:07 +00004435#ifndef PERF_FAST_LOADV
njn45e81252006-03-28 12:35:08 +00004436 return (UWord)mc_LOADVn_slow( a, 8, False/*irrelevant*/ );
njn1d0825f2006-03-27 11:37:07 +00004437#else
njneccf7c02009-01-19 23:42:45 +00004438 {
4439 UWord sm_off, vabits8;
4440 SecMap* sm;
sewardjc1a2cda2005-04-21 17:34:00 +00004441
njneccf7c02009-01-19 23:42:45 +00004442 if (UNLIKELY( UNALIGNED_OR_HIGH(a,8) )) {
4443 PROF_EVENT(261, "mc_LOADV8-slow1");
njn45e81252006-03-28 12:35:08 +00004444 return (UWord)mc_LOADVn_slow( a, 8, False/*irrelevant*/ );
njn1d0825f2006-03-27 11:37:07 +00004445 }
njneccf7c02009-01-19 23:42:45 +00004446
4447 sm = get_secmap_for_reading_low(a);
4448 sm_off = SM_OFF(a);
4449 vabits8 = sm->vabits8[sm_off];
4450 // Convert V bits from compact memory form to expanded register form
4451 // Handle common case quickly: a is mapped, and the entire
4452 // word32 it lives in is addressible.
sewardj14a81782011-08-20 15:55:07 +00004453 if (LIKELY(vabits8 == VA_BITS8_DEFINED )) { return V_BITS8_DEFINED; }
4454 else if (LIKELY(vabits8 == VA_BITS8_UNDEFINED)) { return V_BITS8_UNDEFINED; }
njneccf7c02009-01-19 23:42:45 +00004455 else {
4456 // The 4 (yes, 4) bytes are not all-defined or all-undefined, check
4457 // the single byte.
4458 UChar vabits2 = extract_vabits2_from_vabits8(a, vabits8);
4459 if (vabits2 == VA_BITS2_DEFINED ) { return V_BITS8_DEFINED; }
4460 else if (vabits2 == VA_BITS2_UNDEFINED) { return V_BITS8_UNDEFINED; }
4461 else {
4462 /* Slow case: the byte is not all-defined or all-undefined. */
4463 PROF_EVENT(262, "mc_LOADV8-slow2");
4464 return (UWord)mc_LOADVn_slow( a, 8, False/*irrelevant*/ );
4465 }
4466 }
sewardjc1a2cda2005-04-21 17:34:00 +00004467 }
njn1d0825f2006-03-27 11:37:07 +00004468#endif
njn25e49d8e72002-09-23 09:36:25 +00004469}
4470
sewardjc1a2cda2005-04-21 17:34:00 +00004471
njnaf839f52005-06-23 03:27:57 +00004472VG_REGPARM(2)
njn4cf530b2006-04-06 13:33:48 +00004473void MC_(helperc_STOREV8) ( Addr a, UWord vbits8 )
njn25e49d8e72002-09-23 09:36:25 +00004474{
njn1d0825f2006-03-27 11:37:07 +00004475 PROF_EVENT(270, "mc_STOREV8");
sewardjc1a2cda2005-04-21 17:34:00 +00004476
njn1d0825f2006-03-27 11:37:07 +00004477#ifndef PERF_FAST_STOREV
njn4cf530b2006-04-06 13:33:48 +00004478 mc_STOREVn_slow( a, 8, (ULong)vbits8, False/*irrelevant*/ );
njn1d0825f2006-03-27 11:37:07 +00004479#else
njn1d0825f2006-03-27 11:37:07 +00004480 {
njneccf7c02009-01-19 23:42:45 +00004481 UWord sm_off, vabits8;
4482 SecMap* sm;
4483
4484 if (UNLIKELY( UNALIGNED_OR_HIGH(a,8) )) {
4485 PROF_EVENT(271, "mc_STOREV8-slow1");
4486 mc_STOREVn_slow( a, 8, (ULong)vbits8, False/*irrelevant*/ );
4487 return;
4488 }
4489
4490 sm = get_secmap_for_reading_low(a);
4491 sm_off = SM_OFF(a);
4492 vabits8 = sm->vabits8[sm_off];
4493 if (LIKELY
4494 ( !is_distinguished_sm(sm) &&
4495 ( (VA_BITS8_DEFINED == vabits8 || VA_BITS8_UNDEFINED == vabits8)
4496 || (VA_BITS2_NOACCESS != extract_vabits2_from_vabits8(a, vabits8))
4497 )
4498 )
4499 )
4500 {
4501 /* Handle common case quickly: a is mapped, the entire word32 it
4502 lives in is addressible. */
4503 // Convert full V-bits in register to compact 2-bit form.
4504 if (V_BITS8_DEFINED == vbits8) {
4505 insert_vabits2_into_vabits8( a, VA_BITS2_DEFINED,
4506 &(sm->vabits8[sm_off]) );
4507 } else if (V_BITS8_UNDEFINED == vbits8) {
4508 insert_vabits2_into_vabits8( a, VA_BITS2_UNDEFINED,
4509 &(sm->vabits8[sm_off]) );
4510 } else {
4511 /* Slow but general case -- writing partially defined bytes. */
4512 PROF_EVENT(272, "mc_STOREV8-slow2");
4513 mc_STOREVn_slow( a, 8, (ULong)vbits8, False/*irrelevant*/ );
4514 }
njn1d0825f2006-03-27 11:37:07 +00004515 } else {
njneccf7c02009-01-19 23:42:45 +00004516 /* Slow but general case. */
4517 PROF_EVENT(273, "mc_STOREV8-slow3");
njn4cf530b2006-04-06 13:33:48 +00004518 mc_STOREVn_slow( a, 8, (ULong)vbits8, False/*irrelevant*/ );
njn1d0825f2006-03-27 11:37:07 +00004519 }
sewardjc1a2cda2005-04-21 17:34:00 +00004520 }
njn1d0825f2006-03-27 11:37:07 +00004521#endif
njn25e49d8e72002-09-23 09:36:25 +00004522}
4523
4524
sewardjc859fbf2005-04-22 21:10:28 +00004525/*------------------------------------------------------------*/
4526/*--- Functions called directly from generated code: ---*/
4527/*--- Value-check failure handlers. ---*/
4528/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00004529
sewardj7cf4e6b2008-05-01 20:24:26 +00004530/* Call these ones when an origin is available ... */
4531VG_REGPARM(1)
4532void MC_(helperc_value_check0_fail_w_o) ( UWord origin ) {
sewardj7ce71662008-05-02 10:33:15 +00004533 MC_(record_cond_error) ( VG_(get_running_tid)(), (UInt)origin );
njn25e49d8e72002-09-23 09:36:25 +00004534}
4535
sewardj7cf4e6b2008-05-01 20:24:26 +00004536VG_REGPARM(1)
4537void MC_(helperc_value_check1_fail_w_o) ( UWord origin ) {
sewardj7ce71662008-05-02 10:33:15 +00004538 MC_(record_value_error) ( VG_(get_running_tid)(), 1, (UInt)origin );
njn25e49d8e72002-09-23 09:36:25 +00004539}
4540
sewardj7cf4e6b2008-05-01 20:24:26 +00004541VG_REGPARM(1)
4542void MC_(helperc_value_check4_fail_w_o) ( UWord origin ) {
sewardj7ce71662008-05-02 10:33:15 +00004543 MC_(record_value_error) ( VG_(get_running_tid)(), 4, (UInt)origin );
njn25e49d8e72002-09-23 09:36:25 +00004544}
4545
sewardj7cf4e6b2008-05-01 20:24:26 +00004546VG_REGPARM(1)
4547void MC_(helperc_value_check8_fail_w_o) ( UWord origin ) {
sewardj7ce71662008-05-02 10:33:15 +00004548 MC_(record_value_error) ( VG_(get_running_tid)(), 8, (UInt)origin );
sewardj11bcc4e2005-04-23 22:38:38 +00004549}
4550
sewardj7cf4e6b2008-05-01 20:24:26 +00004551VG_REGPARM(2)
4552void MC_(helperc_value_checkN_fail_w_o) ( HWord sz, UWord origin ) {
sewardj7ce71662008-05-02 10:33:15 +00004553 MC_(record_value_error) ( VG_(get_running_tid)(), (Int)sz, (UInt)origin );
sewardj7cf4e6b2008-05-01 20:24:26 +00004554}
4555
4556/* ... and these when an origin isn't available. */
4557
4558VG_REGPARM(0)
4559void MC_(helperc_value_check0_fail_no_o) ( void ) {
sewardj7ce71662008-05-02 10:33:15 +00004560 MC_(record_cond_error) ( VG_(get_running_tid)(), 0/*origin*/ );
sewardj7cf4e6b2008-05-01 20:24:26 +00004561}
4562
4563VG_REGPARM(0)
4564void MC_(helperc_value_check1_fail_no_o) ( void ) {
sewardj7ce71662008-05-02 10:33:15 +00004565 MC_(record_value_error) ( VG_(get_running_tid)(), 1, 0/*origin*/ );
sewardj7cf4e6b2008-05-01 20:24:26 +00004566}
4567
4568VG_REGPARM(0)
4569void MC_(helperc_value_check4_fail_no_o) ( void ) {
sewardj7ce71662008-05-02 10:33:15 +00004570 MC_(record_value_error) ( VG_(get_running_tid)(), 4, 0/*origin*/ );
sewardj7cf4e6b2008-05-01 20:24:26 +00004571}
4572
4573VG_REGPARM(0)
4574void MC_(helperc_value_check8_fail_no_o) ( void ) {
sewardj7ce71662008-05-02 10:33:15 +00004575 MC_(record_value_error) ( VG_(get_running_tid)(), 8, 0/*origin*/ );
sewardj7cf4e6b2008-05-01 20:24:26 +00004576}
4577
4578VG_REGPARM(1)
4579void MC_(helperc_value_checkN_fail_no_o) ( HWord sz ) {
sewardj7ce71662008-05-02 10:33:15 +00004580 MC_(record_value_error) ( VG_(get_running_tid)(), (Int)sz, 0/*origin*/ );
sewardj95448072004-11-22 20:19:51 +00004581}
4582
njn25e49d8e72002-09-23 09:36:25 +00004583
sewardjc2c12c22006-03-08 13:20:09 +00004584/*------------------------------------------------------------*/
4585/*--- Metadata get/set functions, for client requests. ---*/
4586/*------------------------------------------------------------*/
4587
njn1d0825f2006-03-27 11:37:07 +00004588// Nb: this expands the V+A bits out into register-form V bits, even though
4589// they're in memory. This is for backward compatibility, and because it's
4590// probably what the user wants.
4591
4592/* Copy Vbits from/to address 'a'. Returns: 1 == OK, 2 == alignment
sewardjc2c12c22006-03-08 13:20:09 +00004593 error [no longer used], 3 == addressing error. */
njn718d3b12006-12-16 00:54:12 +00004594/* Nb: We used to issue various definedness/addressability errors from here,
4595 but we took them out because they ranged from not-very-helpful to
4596 downright annoying, and they complicated the error data structures. */
sewardjc2c12c22006-03-08 13:20:09 +00004597static Int mc_get_or_set_vbits_for_client (
njn1d0825f2006-03-27 11:37:07 +00004598 Addr a,
4599 Addr vbits,
4600 SizeT szB,
sewardj3b290482011-05-06 21:02:55 +00004601 Bool setting, /* True <=> set vbits, False <=> get vbits */
4602 Bool is_client_request /* True <=> real user request
4603 False <=> internal call from gdbserver */
sewardjc2c12c22006-03-08 13:20:09 +00004604)
4605{
sewardjc2c12c22006-03-08 13:20:09 +00004606 SizeT i;
njn1d0825f2006-03-27 11:37:07 +00004607 Bool ok;
4608 UChar vbits8;
sewardjc2c12c22006-03-08 13:20:09 +00004609
sewardj3b290482011-05-06 21:02:55 +00004610 /* Check that arrays are addressible before doing any getting/setting.
4611 vbits to be checked only for real user request. */
njn1d0825f2006-03-27 11:37:07 +00004612 for (i = 0; i < szB; i++) {
njn718d3b12006-12-16 00:54:12 +00004613 if (VA_BITS2_NOACCESS == get_vabits2(a + i) ||
sewardj3b290482011-05-06 21:02:55 +00004614 (is_client_request && VA_BITS2_NOACCESS == get_vabits2(vbits + i))) {
njn1d0825f2006-03-27 11:37:07 +00004615 return 3;
sewardjc2c12c22006-03-08 13:20:09 +00004616 }
4617 }
njn1d0825f2006-03-27 11:37:07 +00004618
sewardjc2c12c22006-03-08 13:20:09 +00004619 /* Do the copy */
4620 if (setting) {
njn1d0825f2006-03-27 11:37:07 +00004621 /* setting */
4622 for (i = 0; i < szB; i++) {
4623 ok = set_vbits8(a + i, ((UChar*)vbits)[i]);
4624 tl_assert(ok);
sewardjc2c12c22006-03-08 13:20:09 +00004625 }
4626 } else {
4627 /* getting */
njn1d0825f2006-03-27 11:37:07 +00004628 for (i = 0; i < szB; i++) {
4629 ok = get_vbits8(a + i, &vbits8);
4630 tl_assert(ok);
njn1d0825f2006-03-27 11:37:07 +00004631 ((UChar*)vbits)[i] = vbits8;
sewardjc2c12c22006-03-08 13:20:09 +00004632 }
sewardj3b290482011-05-06 21:02:55 +00004633 if (is_client_request)
4634 // The bytes in vbits[] have now been set, so mark them as such.
4635 MC_(make_mem_defined)(vbits, szB);
njn1d0825f2006-03-27 11:37:07 +00004636 }
sewardjc2c12c22006-03-08 13:20:09 +00004637
4638 return 1;
4639}
sewardj05fe85e2005-04-27 22:46:36 +00004640
4641
4642/*------------------------------------------------------------*/
4643/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
4644/*------------------------------------------------------------*/
4645
4646/* For the memory leak detector, say whether an entire 64k chunk of
4647 address space is possibly in use, or not. If in doubt return
4648 True.
4649*/
njn8225cc02009-03-09 22:52:24 +00004650Bool MC_(is_within_valid_secondary) ( Addr a )
sewardj05fe85e2005-04-27 22:46:36 +00004651{
4652 SecMap* sm = maybe_get_secmap_for ( a );
philippee1e8fce2012-07-11 23:06:07 +00004653 if (sm == NULL || sm == &sm_distinguished[SM_DIST_NOACCESS]) {
sewardj05fe85e2005-04-27 22:46:36 +00004654 /* Definitely not in use. */
4655 return False;
4656 } else {
4657 return True;
4658 }
4659}
4660
4661
4662/* For the memory leak detector, say whether or not a given word
4663 address is to be regarded as valid. */
njn8225cc02009-03-09 22:52:24 +00004664Bool MC_(is_valid_aligned_word) ( Addr a )
sewardj05fe85e2005-04-27 22:46:36 +00004665{
4666 tl_assert(sizeof(UWord) == 4 || sizeof(UWord) == 8);
njn8225cc02009-03-09 22:52:24 +00004667 tl_assert(VG_IS_WORD_ALIGNED(a));
philippe57a16a22012-07-18 22:26:51 +00004668 if (get_vabits8_for_aligned_word32 (a) != VA_BITS8_DEFINED)
sewardj05fe85e2005-04-27 22:46:36 +00004669 return False;
philippe57a16a22012-07-18 22:26:51 +00004670 if (sizeof(UWord) == 8) {
4671 if (get_vabits8_for_aligned_word32 (a + 4) != VA_BITS8_DEFINED)
4672 return False;
sewardj05fe85e2005-04-27 22:46:36 +00004673 }
philippe57a16a22012-07-18 22:26:51 +00004674 if (UNLIKELY(MC_(in_ignored_range)(a)))
4675 return False;
4676 else
4677 return True;
sewardj05fe85e2005-04-27 22:46:36 +00004678}
sewardja4495682002-10-21 07:29:59 +00004679
4680
sewardjc859fbf2005-04-22 21:10:28 +00004681/*------------------------------------------------------------*/
4682/*--- Initialisation ---*/
4683/*------------------------------------------------------------*/
4684
4685static void init_shadow_memory ( void )
4686{
4687 Int i;
4688 SecMap* sm;
4689
njn1d0825f2006-03-27 11:37:07 +00004690 tl_assert(V_BIT_UNDEFINED == 1);
4691 tl_assert(V_BIT_DEFINED == 0);
4692 tl_assert(V_BITS8_UNDEFINED == 0xFF);
4693 tl_assert(V_BITS8_DEFINED == 0);
4694
sewardjc859fbf2005-04-22 21:10:28 +00004695 /* Build the 3 distinguished secondaries */
sewardjc859fbf2005-04-22 21:10:28 +00004696 sm = &sm_distinguished[SM_DIST_NOACCESS];
njn1d0825f2006-03-27 11:37:07 +00004697 for (i = 0; i < SM_CHUNKS; i++) sm->vabits8[i] = VA_BITS8_NOACCESS;
sewardjc859fbf2005-04-22 21:10:28 +00004698
njndbf7ca72006-03-31 11:57:59 +00004699 sm = &sm_distinguished[SM_DIST_UNDEFINED];
4700 for (i = 0; i < SM_CHUNKS; i++) sm->vabits8[i] = VA_BITS8_UNDEFINED;
sewardjc859fbf2005-04-22 21:10:28 +00004701
njndbf7ca72006-03-31 11:57:59 +00004702 sm = &sm_distinguished[SM_DIST_DEFINED];
4703 for (i = 0; i < SM_CHUNKS; i++) sm->vabits8[i] = VA_BITS8_DEFINED;
sewardjc859fbf2005-04-22 21:10:28 +00004704
4705 /* Set up the primary map. */
4706 /* These entries gradually get overwritten as the used address
4707 space expands. */
4708 for (i = 0; i < N_PRIMARY_MAP; i++)
4709 primary_map[i] = &sm_distinguished[SM_DIST_NOACCESS];
4710
sewardj05a46732006-10-17 01:28:10 +00004711 /* Auxiliary primary maps */
4712 init_auxmap_L1_L2();
4713
sewardjc859fbf2005-04-22 21:10:28 +00004714 /* auxmap_size = auxmap_used = 0;
4715 no ... these are statically initialised */
njn1d0825f2006-03-27 11:37:07 +00004716
4717 /* Secondary V bit table */
4718 secVBitTable = createSecVBitTable();
sewardjc859fbf2005-04-22 21:10:28 +00004719}
4720
4721
4722/*------------------------------------------------------------*/
4723/*--- Sanity check machinery (permanently engaged) ---*/
4724/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00004725
njn51d827b2005-05-09 01:02:08 +00004726static Bool mc_cheap_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00004727{
sewardj23eb2fd2005-04-22 16:29:19 +00004728 n_sanity_cheap++;
sewardjc1a2cda2005-04-21 17:34:00 +00004729 PROF_EVENT(490, "cheap_sanity_check");
sewardj7cf4e6b2008-05-01 20:24:26 +00004730 /* Check for sane operating level */
4731 if (MC_(clo_mc_level) < 1 || MC_(clo_mc_level) > 3)
4732 return False;
4733 /* nothing else useful we can rapidly check */
jseward9800fd32004-01-04 23:08:04 +00004734 return True;
njn25e49d8e72002-09-23 09:36:25 +00004735}
4736
njn51d827b2005-05-09 01:02:08 +00004737static Bool mc_expensive_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00004738{
sewardj05a46732006-10-17 01:28:10 +00004739 Int i;
4740 Word n_secmaps_found;
sewardj45d94cc2005-04-20 14:44:11 +00004741 SecMap* sm;
florian19f91bb2012-11-10 22:29:54 +00004742 const HChar* errmsg;
sewardj23eb2fd2005-04-22 16:29:19 +00004743 Bool bad = False;
njn25e49d8e72002-09-23 09:36:25 +00004744
sewardj05a46732006-10-17 01:28:10 +00004745 if (0) VG_(printf)("expensive sanity check\n");
4746 if (0) return True;
4747
sewardj23eb2fd2005-04-22 16:29:19 +00004748 n_sanity_expensive++;
sewardjc1a2cda2005-04-21 17:34:00 +00004749 PROF_EVENT(491, "expensive_sanity_check");
4750
sewardj7cf4e6b2008-05-01 20:24:26 +00004751 /* Check for sane operating level */
4752 if (MC_(clo_mc_level) < 1 || MC_(clo_mc_level) > 3)
4753 return False;
4754
njn1d0825f2006-03-27 11:37:07 +00004755 /* Check that the 3 distinguished SMs are still as they should be. */
njn25e49d8e72002-09-23 09:36:25 +00004756
njndbf7ca72006-03-31 11:57:59 +00004757 /* Check noaccess DSM. */
sewardj45d94cc2005-04-20 14:44:11 +00004758 sm = &sm_distinguished[SM_DIST_NOACCESS];
njn1d0825f2006-03-27 11:37:07 +00004759 for (i = 0; i < SM_CHUNKS; i++)
4760 if (sm->vabits8[i] != VA_BITS8_NOACCESS)
sewardj23eb2fd2005-04-22 16:29:19 +00004761 bad = True;
njn25e49d8e72002-09-23 09:36:25 +00004762
njndbf7ca72006-03-31 11:57:59 +00004763 /* Check undefined DSM. */
4764 sm = &sm_distinguished[SM_DIST_UNDEFINED];
njn1d0825f2006-03-27 11:37:07 +00004765 for (i = 0; i < SM_CHUNKS; i++)
njndbf7ca72006-03-31 11:57:59 +00004766 if (sm->vabits8[i] != VA_BITS8_UNDEFINED)
sewardj23eb2fd2005-04-22 16:29:19 +00004767 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00004768
njndbf7ca72006-03-31 11:57:59 +00004769 /* Check defined DSM. */
4770 sm = &sm_distinguished[SM_DIST_DEFINED];
njn1d0825f2006-03-27 11:37:07 +00004771 for (i = 0; i < SM_CHUNKS; i++)
njndbf7ca72006-03-31 11:57:59 +00004772 if (sm->vabits8[i] != VA_BITS8_DEFINED)
sewardj23eb2fd2005-04-22 16:29:19 +00004773 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00004774
sewardj23eb2fd2005-04-22 16:29:19 +00004775 if (bad) {
4776 VG_(printf)("memcheck expensive sanity: "
4777 "distinguished_secondaries have changed\n");
4778 return False;
4779 }
4780
njn1d0825f2006-03-27 11:37:07 +00004781 /* If we're not checking for undefined value errors, the secondary V bit
4782 * table should be empty. */
sewardj7cf4e6b2008-05-01 20:24:26 +00004783 if (MC_(clo_mc_level) == 1) {
njne2a9ad32007-09-17 05:30:48 +00004784 if (0 != VG_(OSetGen_Size)(secVBitTable))
njn1d0825f2006-03-27 11:37:07 +00004785 return False;
4786 }
4787
sewardj05a46732006-10-17 01:28:10 +00004788 /* check the auxiliary maps, very thoroughly */
4789 n_secmaps_found = 0;
4790 errmsg = check_auxmap_L1_L2_sanity( &n_secmaps_found );
4791 if (errmsg) {
4792 VG_(printf)("memcheck expensive sanity, auxmaps:\n\t%s", errmsg);
sewardj23eb2fd2005-04-22 16:29:19 +00004793 return False;
4794 }
4795
sewardj05a46732006-10-17 01:28:10 +00004796 /* n_secmaps_found is now the number referred to by the auxiliary
4797 primary map. Now add on the ones referred to by the main
4798 primary map. */
sewardj23eb2fd2005-04-22 16:29:19 +00004799 for (i = 0; i < N_PRIMARY_MAP; i++) {
sewardj05a46732006-10-17 01:28:10 +00004800 if (primary_map[i] == NULL) {
sewardj23eb2fd2005-04-22 16:29:19 +00004801 bad = True;
4802 } else {
sewardj05a46732006-10-17 01:28:10 +00004803 if (!is_distinguished_sm(primary_map[i]))
sewardj23eb2fd2005-04-22 16:29:19 +00004804 n_secmaps_found++;
4805 }
4806 }
4807
sewardj05a46732006-10-17 01:28:10 +00004808 /* check that the number of secmaps issued matches the number that
4809 are reachable (iow, no secmap leaks) */
njn1d0825f2006-03-27 11:37:07 +00004810 if (n_secmaps_found != (n_issued_SMs - n_deissued_SMs))
sewardj23eb2fd2005-04-22 16:29:19 +00004811 bad = True;
4812
4813 if (bad) {
4814 VG_(printf)("memcheck expensive sanity: "
4815 "apparent secmap leakage\n");
4816 return False;
4817 }
4818
sewardj23eb2fd2005-04-22 16:29:19 +00004819 if (bad) {
4820 VG_(printf)("memcheck expensive sanity: "
4821 "auxmap covers wrong address space\n");
4822 return False;
4823 }
4824
4825 /* there is only one pointer to each secmap (expensive) */
njn25e49d8e72002-09-23 09:36:25 +00004826
4827 return True;
4828}
sewardj45d94cc2005-04-20 14:44:11 +00004829
njn25e49d8e72002-09-23 09:36:25 +00004830/*------------------------------------------------------------*/
njnd3040452003-05-19 15:04:06 +00004831/*--- Command line args ---*/
njn25e49d8e72002-09-23 09:36:25 +00004832/*------------------------------------------------------------*/
4833
philippe2193a7c2012-12-08 17:54:16 +00004834
njn1d0825f2006-03-27 11:37:07 +00004835Bool MC_(clo_partial_loads_ok) = False;
sewardja88fb0b2010-10-13 21:19:54 +00004836Long MC_(clo_freelist_vol) = 20*1000*1000LL;
sewardj403d8aa2011-10-22 19:48:57 +00004837Long MC_(clo_freelist_big_blocks) = 1*1000*1000LL;
njn1d0825f2006-03-27 11:37:07 +00004838LeakCheckMode MC_(clo_leak_check) = LC_Summary;
njn5daa2d32009-07-10 08:16:29 +00004839VgRes MC_(clo_leak_resolution) = Vg_HighRes;
philippe2193a7c2012-12-08 17:54:16 +00004840UInt MC_(clo_show_leak_kinds) = R2S(Possible) | R2S(Unreached);
4841UInt MC_(clo_error_for_leak_kinds) = R2S(Possible) | R2S(Unreached);
njn1d0825f2006-03-27 11:37:07 +00004842Bool MC_(clo_workaround_gcc296_bugs) = False;
sewardjeb0fa932007-11-30 21:41:40 +00004843Int MC_(clo_malloc_fill) = -1;
4844Int MC_(clo_free_fill) = -1;
philippe8617b5b2013-01-12 19:53:08 +00004845KeepStacktraces MC_(clo_keep_stacktraces) = KS_alloc_then_free;
sewardj7cf4e6b2008-05-01 20:24:26 +00004846Int MC_(clo_mc_level) = 2;
njn1d0825f2006-03-27 11:37:07 +00004847
florian19f91bb2012-11-10 22:29:54 +00004848static Bool mc_process_cmd_line_options(const HChar* arg)
njn25e49d8e72002-09-23 09:36:25 +00004849{
florian19f91bb2012-11-10 22:29:54 +00004850 const HChar* tmp_str;
philippe2193a7c2012-12-08 17:54:16 +00004851 Int tmp_show;
njn83df0b62009-02-25 01:01:05 +00004852
sewardj7cf4e6b2008-05-01 20:24:26 +00004853 tl_assert( MC_(clo_mc_level) >= 1 && MC_(clo_mc_level) <= 3 );
4854
4855 /* Set MC_(clo_mc_level):
4856 1 = A bit tracking only
4857 2 = A and V bit tracking, but no V bit origins
4858 3 = A and V bit tracking, and V bit origins
4859
4860 Do this by inspecting --undef-value-errors= and
4861 --track-origins=. Reject the case --undef-value-errors=no
4862 --track-origins=yes as meaningless.
4863 */
4864 if (0 == VG_(strcmp)(arg, "--undef-value-errors=no")) {
njn83df0b62009-02-25 01:01:05 +00004865 if (MC_(clo_mc_level) == 3) {
njnb1cc5d62010-07-06 04:05:23 +00004866 goto bad_level;
njn83df0b62009-02-25 01:01:05 +00004867 } else {
4868 MC_(clo_mc_level) = 1;
4869 return True;
4870 }
sewardj7cf4e6b2008-05-01 20:24:26 +00004871 }
4872 if (0 == VG_(strcmp)(arg, "--undef-value-errors=yes")) {
4873 if (MC_(clo_mc_level) == 1)
4874 MC_(clo_mc_level) = 2;
4875 return True;
4876 }
4877 if (0 == VG_(strcmp)(arg, "--track-origins=no")) {
4878 if (MC_(clo_mc_level) == 3)
4879 MC_(clo_mc_level) = 2;
4880 return True;
4881 }
4882 if (0 == VG_(strcmp)(arg, "--track-origins=yes")) {
njn83df0b62009-02-25 01:01:05 +00004883 if (MC_(clo_mc_level) == 1) {
njnb1cc5d62010-07-06 04:05:23 +00004884 goto bad_level;
njn83df0b62009-02-25 01:01:05 +00004885 } else {
4886 MC_(clo_mc_level) = 3;
4887 return True;
4888 }
sewardj7cf4e6b2008-05-01 20:24:26 +00004889 }
4890
philippe2193a7c2012-12-08 17:54:16 +00004891 if VG_BOOL_CLO(arg, "--partial-loads-ok", MC_(clo_partial_loads_ok)) {}
4892 else if VG_STR_CLO(arg, "--errors-for-leak-kinds" , tmp_str) {
4893 if (!MC_(parse_leak_kinds)(tmp_str, &MC_(clo_error_for_leak_kinds)))
4894 return False;
4895 }
4896 else if VG_STR_CLO(arg, "--show-leak-kinds", tmp_str) {
4897 if (!MC_(parse_leak_kinds)(tmp_str, &MC_(clo_show_leak_kinds)))
4898 return False;
4899 }
4900 else if (VG_BOOL_CLO(arg, "--show-reachable", tmp_show)) {
4901 if (tmp_show) {
4902 MC_(clo_show_leak_kinds) = RallS;
4903 } else {
4904 MC_(clo_show_leak_kinds) &= ~R2S(Reachable);
4905 }
4906 }
4907 else if VG_BOOL_CLO(arg, "--show-possibly-lost", tmp_show) {
4908 if (tmp_show) {
4909 MC_(clo_show_leak_kinds) |= R2S(Possible);
4910 } else {
4911 MC_(clo_show_leak_kinds) &= ~R2S(Possible);
4912 }
4913 }
njn83df0b62009-02-25 01:01:05 +00004914 else if VG_BOOL_CLO(arg, "--workaround-gcc296-bugs",
4915 MC_(clo_workaround_gcc296_bugs)) {}
njn1d0825f2006-03-27 11:37:07 +00004916
njn83df0b62009-02-25 01:01:05 +00004917 else if VG_BINT_CLO(arg, "--freelist-vol", MC_(clo_freelist_vol),
4918 0, 10*1000*1000*1000LL) {}
sewardj403d8aa2011-10-22 19:48:57 +00004919
4920 else if VG_BINT_CLO(arg, "--freelist-big-blocks",
4921 MC_(clo_freelist_big_blocks),
4922 0, 10*1000*1000*1000LL) {}
4923
njn83df0b62009-02-25 01:01:05 +00004924 else if VG_XACT_CLO(arg, "--leak-check=no",
4925 MC_(clo_leak_check), LC_Off) {}
4926 else if VG_XACT_CLO(arg, "--leak-check=summary",
4927 MC_(clo_leak_check), LC_Summary) {}
4928 else if VG_XACT_CLO(arg, "--leak-check=yes",
4929 MC_(clo_leak_check), LC_Full) {}
4930 else if VG_XACT_CLO(arg, "--leak-check=full",
4931 MC_(clo_leak_check), LC_Full) {}
njn1d0825f2006-03-27 11:37:07 +00004932
njn83df0b62009-02-25 01:01:05 +00004933 else if VG_XACT_CLO(arg, "--leak-resolution=low",
4934 MC_(clo_leak_resolution), Vg_LowRes) {}
4935 else if VG_XACT_CLO(arg, "--leak-resolution=med",
4936 MC_(clo_leak_resolution), Vg_MedRes) {}
4937 else if VG_XACT_CLO(arg, "--leak-resolution=high",
4938 MC_(clo_leak_resolution), Vg_HighRes) {}
njn1d0825f2006-03-27 11:37:07 +00004939
njn83df0b62009-02-25 01:01:05 +00004940 else if VG_STR_CLO(arg, "--ignore-ranges", tmp_str) {
4941 Int i;
4942 Bool ok = parse_ignore_ranges(tmp_str);
sewardj05a46732006-10-17 01:28:10 +00004943 if (!ok)
4944 return False;
4945 tl_assert(ignoreRanges.used >= 0);
4946 tl_assert(ignoreRanges.used < M_IGNORE_RANGES);
4947 for (i = 0; i < ignoreRanges.used; i++) {
4948 Addr s = ignoreRanges.start[i];
4949 Addr e = ignoreRanges.end[i];
4950 Addr limit = 0x4000000; /* 64M - entirely arbitrary limit */
4951 if (e <= s) {
4952 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00004953 "ERROR: --ignore-ranges: end <= start in range:\n");
sewardj05a46732006-10-17 01:28:10 +00004954 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00004955 " 0x%lx-0x%lx\n", s, e);
sewardj05a46732006-10-17 01:28:10 +00004956 return False;
4957 }
4958 if (e - s > limit) {
4959 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00004960 "ERROR: --ignore-ranges: suspiciously large range:\n");
sewardj05a46732006-10-17 01:28:10 +00004961 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00004962 " 0x%lx-0x%lx (size %ld)\n", s, e, (UWord)(e-s));
sewardj05a46732006-10-17 01:28:10 +00004963 return False;
4964 }
4965 }
4966 }
4967
njn83df0b62009-02-25 01:01:05 +00004968 else if VG_BHEX_CLO(arg, "--malloc-fill", MC_(clo_malloc_fill), 0x00,0xFF) {}
4969 else if VG_BHEX_CLO(arg, "--free-fill", MC_(clo_free_fill), 0x00,0xFF) {}
sewardjeb0fa932007-11-30 21:41:40 +00004970
philippe8617b5b2013-01-12 19:53:08 +00004971 else if VG_XACT_CLO(arg, "--keep-stacktraces=alloc",
4972 MC_(clo_keep_stacktraces), KS_alloc) {}
4973 else if VG_XACT_CLO(arg, "--keep-stacktraces=free",
4974 MC_(clo_keep_stacktraces), KS_free) {}
4975 else if VG_XACT_CLO(arg, "--keep-stacktraces=alloc-and-free",
4976 MC_(clo_keep_stacktraces), KS_alloc_and_free) {}
4977 else if VG_XACT_CLO(arg, "--keep-stacktraces=alloc-then-free",
4978 MC_(clo_keep_stacktraces), KS_alloc_then_free) {}
4979 else if VG_XACT_CLO(arg, "--keep-stacktraces=none",
4980 MC_(clo_keep_stacktraces), KS_none) {}
4981
njn1d0825f2006-03-27 11:37:07 +00004982 else
4983 return VG_(replacement_malloc_process_cmd_line_option)(arg);
4984
4985 return True;
njnb1cc5d62010-07-06 04:05:23 +00004986
4987
4988 bad_level:
4989 VG_(fmsg_bad_option)(arg,
4990 "--track-origins=yes has no effect when --undef-value-errors=no.\n");
njn25e49d8e72002-09-23 09:36:25 +00004991}
4992
njn51d827b2005-05-09 01:02:08 +00004993static void mc_print_usage(void)
njn25e49d8e72002-09-23 09:36:25 +00004994{
njn1d0825f2006-03-27 11:37:07 +00004995 VG_(printf)(
4996" --leak-check=no|summary|full search for memory leaks at exit? [summary]\n"
njn5daa2d32009-07-10 08:16:29 +00004997" --leak-resolution=low|med|high differentiation of leak stack traces [high]\n"
philippe2193a7c2012-12-08 17:54:16 +00004998" --show-leak-kinds=kind1,kind2,.. which leak kinds to show?\n"
4999" [definite,possible]\n"
5000" --errors-for-leak-kinds=kind1,kind2,.. which leak kinds are errors?\n"
5001" [definite,possible]\n"
5002" where kind is one of definite indirect possible reachable all none\n"
5003" --show-reachable=yes same as --show-leak-kinds=all\n"
5004" --show-reachable=no --show-possibly-lost=yes\n"
5005" same as --show-leak-kinds=definite,possible\n"
5006" --show-reachable=no --show-possibly-lost=no\n"
5007" same as --show-leak-kinds=definite\n"
njn1d0825f2006-03-27 11:37:07 +00005008" --undef-value-errors=no|yes check for undefined value errors [yes]\n"
sewardj7cf4e6b2008-05-01 20:24:26 +00005009" --track-origins=no|yes show origins of undefined values? [no]\n"
njn1d0825f2006-03-27 11:37:07 +00005010" --partial-loads-ok=no|yes too hard to explain here; see manual [no]\n"
philippe2193a7c2012-12-08 17:54:16 +00005011" --freelist-vol=<number> volume of freed blocks queue [20000000]\n"
5012" --freelist-big-blocks=<number> releases first blocks with size>= [1000000]\n"
njn1d0825f2006-03-27 11:37:07 +00005013" --workaround-gcc296-bugs=no|yes self explanatory [no]\n"
sewardj05a46732006-10-17 01:28:10 +00005014" --ignore-ranges=0xPP-0xQQ[,0xRR-0xSS] assume given addresses are OK\n"
sewardjeb0fa932007-11-30 21:41:40 +00005015" --malloc-fill=<hexnumber> fill malloc'd areas with given value\n"
5016" --free-fill=<hexnumber> fill free'd areas with given value\n"
philippe8617b5b2013-01-12 19:53:08 +00005017" --keep-stacktraces=alloc|free|alloc-and-free|alloc-then-free|none\n"
5018" stack trace(s) to keep for malloc'd/free'd areas [alloc-then-free]\n"
njn1d0825f2006-03-27 11:37:07 +00005019 );
njn3e884182003-04-15 13:03:23 +00005020}
5021
njn51d827b2005-05-09 01:02:08 +00005022static void mc_print_debug_usage(void)
njn3e884182003-04-15 13:03:23 +00005023{
njn97db7612009-08-04 02:32:55 +00005024 VG_(printf)(
5025" (none)\n"
5026 );
njn25e49d8e72002-09-23 09:36:25 +00005027}
5028
sewardjf3418c02005-11-08 14:10:24 +00005029
nethercote8b76fe52004-11-08 19:20:09 +00005030/*------------------------------------------------------------*/
sewardj7ce71662008-05-02 10:33:15 +00005031/*--- Client blocks ---*/
nethercote8b76fe52004-11-08 19:20:09 +00005032/*------------------------------------------------------------*/
5033
5034/* Client block management:
5035
5036 This is managed as an expanding array of client block descriptors.
5037 Indices of live descriptors are issued to the client, so it can ask
5038 to free them later. Therefore we cannot slide live entries down
5039 over dead ones. Instead we must use free/inuse flags and scan for
5040 an empty slot at allocation time. This in turn means allocation is
5041 relatively expensive, so we hope this does not happen too often.
nethercote8b76fe52004-11-08 19:20:09 +00005042
sewardjedc75ab2005-03-15 23:30:32 +00005043 An unused block has start == size == 0
5044*/
nethercote8b76fe52004-11-08 19:20:09 +00005045
sewardj7ce71662008-05-02 10:33:15 +00005046/* type CGenBlock is defined in mc_include.h */
nethercote8b76fe52004-11-08 19:20:09 +00005047
5048/* This subsystem is self-initialising. */
sewardj56adc352008-05-02 11:25:17 +00005049static UWord cgb_size = 0;
5050static UWord cgb_used = 0;
njn695c16e2005-03-27 03:40:28 +00005051static CGenBlock* cgbs = NULL;
nethercote8b76fe52004-11-08 19:20:09 +00005052
5053/* Stats for this subsystem. */
sewardj56adc352008-05-02 11:25:17 +00005054static ULong cgb_used_MAX = 0; /* Max in use. */
5055static ULong cgb_allocs = 0; /* Number of allocs. */
5056static ULong cgb_discards = 0; /* Number of discards. */
5057static ULong cgb_search = 0; /* Number of searches. */
nethercote8b76fe52004-11-08 19:20:09 +00005058
5059
sewardj7ce71662008-05-02 10:33:15 +00005060/* Get access to the client block array. */
5061void MC_(get_ClientBlock_array)( /*OUT*/CGenBlock** blocks,
5062 /*OUT*/UWord* nBlocks )
5063{
5064 *blocks = cgbs;
5065 *nBlocks = cgb_used;
5066}
5067
5068
nethercote8b76fe52004-11-08 19:20:09 +00005069static
njn695c16e2005-03-27 03:40:28 +00005070Int alloc_client_block ( void )
nethercote8b76fe52004-11-08 19:20:09 +00005071{
sewardj56adc352008-05-02 11:25:17 +00005072 UWord i, sz_new;
nethercote8b76fe52004-11-08 19:20:09 +00005073 CGenBlock* cgbs_new;
5074
njn695c16e2005-03-27 03:40:28 +00005075 cgb_allocs++;
nethercote8b76fe52004-11-08 19:20:09 +00005076
njn695c16e2005-03-27 03:40:28 +00005077 for (i = 0; i < cgb_used; i++) {
5078 cgb_search++;
5079 if (cgbs[i].start == 0 && cgbs[i].size == 0)
nethercote8b76fe52004-11-08 19:20:09 +00005080 return i;
5081 }
5082
5083 /* Not found. Try to allocate one at the end. */
njn695c16e2005-03-27 03:40:28 +00005084 if (cgb_used < cgb_size) {
5085 cgb_used++;
5086 return cgb_used-1;
nethercote8b76fe52004-11-08 19:20:09 +00005087 }
5088
5089 /* Ok, we have to allocate a new one. */
njn695c16e2005-03-27 03:40:28 +00005090 tl_assert(cgb_used == cgb_size);
5091 sz_new = (cgbs == NULL) ? 10 : (2 * cgb_size);
nethercote8b76fe52004-11-08 19:20:09 +00005092
sewardj9c606bd2008-09-18 18:12:50 +00005093 cgbs_new = VG_(malloc)( "mc.acb.1", sz_new * sizeof(CGenBlock) );
njn695c16e2005-03-27 03:40:28 +00005094 for (i = 0; i < cgb_used; i++)
5095 cgbs_new[i] = cgbs[i];
nethercote8b76fe52004-11-08 19:20:09 +00005096
njn695c16e2005-03-27 03:40:28 +00005097 if (cgbs != NULL)
5098 VG_(free)( cgbs );
5099 cgbs = cgbs_new;
nethercote8b76fe52004-11-08 19:20:09 +00005100
njn695c16e2005-03-27 03:40:28 +00005101 cgb_size = sz_new;
5102 cgb_used++;
5103 if (cgb_used > cgb_used_MAX)
5104 cgb_used_MAX = cgb_used;
5105 return cgb_used-1;
nethercote8b76fe52004-11-08 19:20:09 +00005106}
5107
5108
5109static void show_client_block_stats ( void )
5110{
5111 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00005112 "general CBs: %llu allocs, %llu discards, %llu maxinuse, %llu search\n",
njn695c16e2005-03-27 03:40:28 +00005113 cgb_allocs, cgb_discards, cgb_used_MAX, cgb_search
nethercote8b76fe52004-11-08 19:20:09 +00005114 );
5115}
sewardj3b290482011-05-06 21:02:55 +00005116static void print_monitor_help ( void )
5117{
5118 VG_(gdb_printf)
5119 (
5120"\n"
5121"memcheck monitor commands:\n"
sewardj30b3eca2011-06-28 08:20:39 +00005122" get_vbits <addr> [<len>]\n"
sewardj3b290482011-05-06 21:02:55 +00005123" returns validity bits for <len> (or 1) bytes at <addr>\n"
5124" bit values 0 = valid, 1 = invalid, __ = unaddressable byte\n"
sewardj30b3eca2011-06-28 08:20:39 +00005125" Example: get_vbits 0x8049c78 10\n"
5126" make_memory [noaccess|undefined\n"
5127" |defined|Definedifaddressable] <addr> [<len>]\n"
sewardj3b290482011-05-06 21:02:55 +00005128" mark <len> (or 1) bytes at <addr> with the given accessibility\n"
sewardj30b3eca2011-06-28 08:20:39 +00005129" check_memory [addressable|defined] <addr> [<len>]\n"
sewardj3b290482011-05-06 21:02:55 +00005130" check that <len> (or 1) bytes at <addr> have the given accessibility\n"
5131" and outputs a description of <addr>\n"
philippe2193a7c2012-12-08 17:54:16 +00005132" leak_check [full*|summary]\n"
5133" [kinds kind1,kind2,...|reachable|possibleleak*|definiteleak]\n"
sewardjc8bd1df2011-06-26 12:41:33 +00005134" [increased*|changed|any]\n"
philippe84234902012-01-14 13:53:13 +00005135" [unlimited*|limited <max_loss_records_output>]\n"
sewardj3b290482011-05-06 21:02:55 +00005136" * = defaults\n"
philippe2193a7c2012-12-08 17:54:16 +00005137" where kind is one of definite indirect possible reachable all none\n"
sewardj30b3eca2011-06-28 08:20:39 +00005138" Examples: leak_check\n"
5139" leak_check summary any\n"
philippe2193a7c2012-12-08 17:54:16 +00005140" leak_check full kinds indirect,possible\n"
philippe84234902012-01-14 13:53:13 +00005141" leak_check full reachable any limited 100\n"
philippea22f59d2012-01-26 23:13:52 +00005142" block_list <loss_record_nr>\n"
5143" after a leak search, shows the list of blocks of <loss_record_nr>\n"
5144" who_points_at <addr> [<len>]\n"
5145" shows places pointing inside <len> (default 1) bytes at <addr>\n"
5146" (with len 1, only shows \"start pointers\" pointing exactly to <addr>,\n"
5147" with len > 1, will also show \"interior pointers\")\n"
sewardj3b290482011-05-06 21:02:55 +00005148"\n");
5149}
5150
5151/* return True if request recognised, False otherwise */
florian19f91bb2012-11-10 22:29:54 +00005152static Bool handle_gdb_monitor_command (ThreadId tid, HChar *req)
sewardj3b290482011-05-06 21:02:55 +00005153{
florian19f91bb2012-11-10 22:29:54 +00005154 HChar* wcmd;
5155 HChar s[VG_(strlen(req))]; /* copy for strtok_r */
5156 HChar *ssaveptr;
sewardj3b290482011-05-06 21:02:55 +00005157
5158 VG_(strcpy) (s, req);
5159
5160 wcmd = VG_(strtok_r) (s, " ", &ssaveptr);
5161 /* NB: if possible, avoid introducing a new command below which
sewardj30b3eca2011-06-28 08:20:39 +00005162 starts with the same first letter(s) as an already existing
sewardj3b290482011-05-06 21:02:55 +00005163 command. This ensures a shorter abbreviation for the user. */
5164 switch (VG_(keyword_id)
philippea22f59d2012-01-26 23:13:52 +00005165 ("help get_vbits leak_check make_memory check_memory "
5166 "block_list who_points_at",
sewardj3b290482011-05-06 21:02:55 +00005167 wcmd, kwd_report_duplicated_matches)) {
5168 case -2: /* multiple matches */
5169 return True;
5170 case -1: /* not found */
5171 return False;
5172 case 0: /* help */
5173 print_monitor_help();
5174 return True;
sewardj30b3eca2011-06-28 08:20:39 +00005175 case 1: { /* get_vbits */
sewardj3b290482011-05-06 21:02:55 +00005176 Addr address;
5177 SizeT szB = 1;
5178 VG_(strtok_get_address_and_size) (&address, &szB, &ssaveptr);
5179 if (szB != 0) {
5180 UChar vbits;
5181 Int i;
5182 Int unaddressable = 0;
5183 for (i = 0; i < szB; i++) {
5184 Int res = mc_get_or_set_vbits_for_client
5185 (address+i, (Addr) &vbits, 1,
5186 False, /* get them */
5187 False /* is client request */ );
philippe8d674252012-03-20 19:04:39 +00005188 /* we are before the first character on next line, print a \n. */
sewardj3b290482011-05-06 21:02:55 +00005189 if ((i % 32) == 0 && i != 0)
5190 VG_(gdb_printf) ("\n");
philippe8d674252012-03-20 19:04:39 +00005191 /* we are before the next block of 4 starts, print a space. */
sewardj3b290482011-05-06 21:02:55 +00005192 else if ((i % 4) == 0 && i != 0)
5193 VG_(gdb_printf) (" ");
5194 if (res == 1) {
5195 VG_(gdb_printf) ("%02x", vbits);
5196 } else {
5197 tl_assert(3 == res);
5198 unaddressable++;
5199 VG_(gdb_printf) ("__");
5200 }
5201 }
philippe8d674252012-03-20 19:04:39 +00005202 VG_(gdb_printf) ("\n");
sewardj3b290482011-05-06 21:02:55 +00005203 if (unaddressable) {
5204 VG_(gdb_printf)
5205 ("Address %p len %ld has %d bytes unaddressable\n",
5206 (void *)address, szB, unaddressable);
5207 }
5208 }
5209 return True;
5210 }
sewardj30b3eca2011-06-28 08:20:39 +00005211 case 2: { /* leak_check */
sewardj3b290482011-05-06 21:02:55 +00005212 Int err = 0;
sewardjc8bd1df2011-06-26 12:41:33 +00005213 LeakCheckParams lcp;
florian19f91bb2012-11-10 22:29:54 +00005214 HChar* kw;
sewardj3b290482011-05-06 21:02:55 +00005215
sewardjc8bd1df2011-06-26 12:41:33 +00005216 lcp.mode = LC_Full;
philippe2193a7c2012-12-08 17:54:16 +00005217 lcp.show_leak_kinds = R2S(Possible) | R2S(Unreached);
5218 lcp.errors_for_leak_kinds = 0; /* no errors for interactive leak search. */
sewardjc8bd1df2011-06-26 12:41:33 +00005219 lcp.deltamode = LCD_Increased;
philippe84234902012-01-14 13:53:13 +00005220 lcp.max_loss_records_output = 999999999;
sewardjc8bd1df2011-06-26 12:41:33 +00005221 lcp.requested_by_monitor_command = True;
sewardj3b290482011-05-06 21:02:55 +00005222
5223 for (kw = VG_(strtok_r) (NULL, " ", &ssaveptr);
5224 kw != NULL;
5225 kw = VG_(strtok_r) (NULL, " ", &ssaveptr)) {
5226 switch (VG_(keyword_id)
5227 ("full summary "
philippe2193a7c2012-12-08 17:54:16 +00005228 "kinds reachable possibleleak definiteleak "
philippe84234902012-01-14 13:53:13 +00005229 "increased changed any "
5230 "unlimited limited ",
sewardj3b290482011-05-06 21:02:55 +00005231 kw, kwd_report_all)) {
5232 case -2: err++; break;
5233 case -1: err++; break;
sewardjc8bd1df2011-06-26 12:41:33 +00005234 case 0: /* full */
5235 lcp.mode = LC_Full; break;
5236 case 1: /* summary */
5237 lcp.mode = LC_Summary; break;
philippe2193a7c2012-12-08 17:54:16 +00005238 case 2: { /* kinds */
5239 wcmd = VG_(strtok_r) (NULL, " ", &ssaveptr);
5240 if (wcmd == NULL || !MC_(parse_leak_kinds)(wcmd,
5241 &lcp.show_leak_kinds)) {
5242 VG_(gdb_printf) ("missing or malformed leak kinds set\n");
5243 err++;
5244 }
5245 break;
5246 }
5247 case 3: /* reachable */
5248 lcp.show_leak_kinds = RallS;
5249 break;
5250 case 4: /* possibleleak */
5251 lcp.show_leak_kinds
5252 = R2S(Possible) | R2S(IndirectLeak) | R2S(Unreached);
5253 break;
5254 case 5: /* definiteleak */
5255 lcp.show_leak_kinds = R2S(Unreached);
5256 break;
5257 case 6: /* increased */
sewardjc8bd1df2011-06-26 12:41:33 +00005258 lcp.deltamode = LCD_Increased; break;
philippe2193a7c2012-12-08 17:54:16 +00005259 case 7: /* changed */
sewardjc8bd1df2011-06-26 12:41:33 +00005260 lcp.deltamode = LCD_Changed; break;
philippe2193a7c2012-12-08 17:54:16 +00005261 case 8: /* any */
sewardjc8bd1df2011-06-26 12:41:33 +00005262 lcp.deltamode = LCD_Any; break;
philippe2193a7c2012-12-08 17:54:16 +00005263 case 9: /* unlimited */
philippe84234902012-01-14 13:53:13 +00005264 lcp.max_loss_records_output = 999999999; break;
philippe2193a7c2012-12-08 17:54:16 +00005265 case 10: { /* limited */
florian19f91bb2012-11-10 22:29:54 +00005266 Int int_value;
florian6bd9dc12012-11-23 16:17:43 +00005267 const HChar* endptr;
philippe84234902012-01-14 13:53:13 +00005268
5269 wcmd = VG_(strtok_r) (NULL, " ", &ssaveptr);
5270 if (wcmd == NULL) {
5271 int_value = 0;
5272 endptr = "empty"; /* to report an error below */
5273 } else {
florian6bd9dc12012-11-23 16:17:43 +00005274 HChar *the_end;
5275 int_value = VG_(strtoll10) (wcmd, &the_end);
5276 endptr = the_end;
philippe84234902012-01-14 13:53:13 +00005277 }
5278 if (*endptr != '\0')
5279 VG_(gdb_printf) ("missing or malformed integer value\n");
5280 else if (int_value > 0)
5281 lcp.max_loss_records_output = (UInt) int_value;
5282 else
5283 VG_(gdb_printf) ("max_loss_records_output must be >= 1, got %d\n",
5284 int_value);
5285 break;
5286 }
sewardjc8bd1df2011-06-26 12:41:33 +00005287 default:
5288 tl_assert (0);
sewardj3b290482011-05-06 21:02:55 +00005289 }
5290 }
5291 if (!err)
philippe84234902012-01-14 13:53:13 +00005292 MC_(detect_memory_leaks)(tid, &lcp);
sewardj3b290482011-05-06 21:02:55 +00005293 return True;
5294 }
5295
sewardj30b3eca2011-06-28 08:20:39 +00005296 case 3: { /* make_memory */
sewardj3b290482011-05-06 21:02:55 +00005297 Addr address;
5298 SizeT szB = 1;
florian19f91bb2012-11-10 22:29:54 +00005299 Int kwdid = VG_(keyword_id)
sewardj30b3eca2011-06-28 08:20:39 +00005300 ("noaccess undefined defined Definedifaddressable",
sewardj3b290482011-05-06 21:02:55 +00005301 VG_(strtok_r) (NULL, " ", &ssaveptr), kwd_report_all);
5302 VG_(strtok_get_address_and_size) (&address, &szB, &ssaveptr);
5303 if (address == (Addr) 0 && szB == 0) return True;
5304 switch (kwdid) {
5305 case -2: break;
5306 case -1: break;
5307 case 0: MC_(make_mem_noaccess) (address, szB); break;
5308 case 1: make_mem_undefined_w_tid_and_okind ( address, szB, tid,
5309 MC_OKIND_USER ); break;
5310 case 2: MC_(make_mem_defined) ( address, szB ); break;
5311 case 3: make_mem_defined_if_addressable ( address, szB ); break;;
5312 default: tl_assert(0);
5313 }
5314 return True;
5315 }
5316
sewardj30b3eca2011-06-28 08:20:39 +00005317 case 4: { /* check_memory */
sewardj3b290482011-05-06 21:02:55 +00005318 Addr address;
5319 SizeT szB = 1;
5320 Addr bad_addr;
5321 UInt okind;
florian6bd9dc12012-11-23 16:17:43 +00005322 const HChar* src;
sewardj3b290482011-05-06 21:02:55 +00005323 UInt otag;
5324 UInt ecu;
5325 ExeContext* origin_ec;
5326 MC_ReadResult res;
5327
florian19f91bb2012-11-10 22:29:54 +00005328 Int kwdid = VG_(keyword_id)
sewardj3b290482011-05-06 21:02:55 +00005329 ("addressable defined",
5330 VG_(strtok_r) (NULL, " ", &ssaveptr), kwd_report_all);
5331 VG_(strtok_get_address_and_size) (&address, &szB, &ssaveptr);
5332 if (address == (Addr) 0 && szB == 0) return True;
5333 switch (kwdid) {
5334 case -2: break;
5335 case -1: break;
5336 case 0:
5337 if (is_mem_addressable ( address, szB, &bad_addr ))
5338 VG_(gdb_printf) ("Address %p len %ld addressable\n",
5339 (void *)address, szB);
5340 else
5341 VG_(gdb_printf)
5342 ("Address %p len %ld not addressable:\nbad address %p\n",
5343 (void *)address, szB, (void *) bad_addr);
5344 MC_(pp_describe_addr) (address);
5345 break;
5346 case 1: res = is_mem_defined ( address, szB, &bad_addr, &otag );
5347 if (MC_AddrErr == res)
5348 VG_(gdb_printf)
5349 ("Address %p len %ld not addressable:\nbad address %p\n",
5350 (void *)address, szB, (void *) bad_addr);
5351 else if (MC_ValueErr == res) {
5352 okind = otag & 3;
5353 switch (okind) {
5354 case MC_OKIND_STACK:
5355 src = " was created by a stack allocation"; break;
5356 case MC_OKIND_HEAP:
5357 src = " was created by a heap allocation"; break;
5358 case MC_OKIND_USER:
5359 src = " was created by a client request"; break;
5360 case MC_OKIND_UNKNOWN:
5361 src = ""; break;
5362 default: tl_assert(0);
5363 }
5364 VG_(gdb_printf)
5365 ("Address %p len %ld not defined:\n"
5366 "Uninitialised value at %p%s\n",
5367 (void *)address, szB, (void *) bad_addr, src);
5368 ecu = otag & ~3;
5369 if (VG_(is_plausible_ECU)(ecu)) {
5370 origin_ec = VG_(get_ExeContext_from_ECU)( ecu );
5371 VG_(pp_ExeContext)( origin_ec );
5372 }
5373 }
5374 else
5375 VG_(gdb_printf) ("Address %p len %ld defined\n",
5376 (void *)address, szB);
5377 MC_(pp_describe_addr) (address);
5378 break;
5379 default: tl_assert(0);
5380 }
5381 return True;
5382 }
5383
philippea22f59d2012-01-26 23:13:52 +00005384 case 5: { /* block_list */
florian19f91bb2012-11-10 22:29:54 +00005385 HChar* wl;
5386 HChar *endptr;
philippea22f59d2012-01-26 23:13:52 +00005387 UInt lr_nr = 0;
5388 wl = VG_(strtok_r) (NULL, " ", &ssaveptr);
philippe77241c72013-01-21 22:05:47 +00005389 if (wl != NULL)
5390 lr_nr = VG_(strtoull10) (wl, &endptr);
5391 if (wl == NULL || *endptr != '\0') {
5392 VG_(gdb_printf) ("malformed or missing integer\n");
philippea22f59d2012-01-26 23:13:52 +00005393 } else {
5394 // lr_nr-1 as what is shown to the user is 1 more than the index in lr_array.
5395 if (lr_nr == 0 || ! MC_(print_block_list) (lr_nr-1))
5396 VG_(gdb_printf) ("invalid loss record nr\n");
5397 }
5398 return True;
5399 }
5400
5401 case 6: { /* who_points_at */
5402 Addr address;
5403 SizeT szB = 1;
5404
5405 VG_(strtok_get_address_and_size) (&address, &szB, &ssaveptr);
5406 if (address == (Addr) 0) {
5407 VG_(gdb_printf) ("Cannot search who points at 0x0\n");
5408 return True;
5409 }
5410 MC_(who_points_at) (address, szB);
5411 return True;
5412 }
5413
sewardj3b290482011-05-06 21:02:55 +00005414 default:
5415 tl_assert(0);
5416 return False;
5417 }
5418}
nethercote8b76fe52004-11-08 19:20:09 +00005419
sewardj7ce71662008-05-02 10:33:15 +00005420/*------------------------------------------------------------*/
5421/*--- Client requests ---*/
5422/*------------------------------------------------------------*/
nethercote8b76fe52004-11-08 19:20:09 +00005423
njn51d827b2005-05-09 01:02:08 +00005424static Bool mc_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret )
nethercote8b76fe52004-11-08 19:20:09 +00005425{
5426 Int i;
5427 Bool ok;
5428 Addr bad_addr;
5429
njnfc26ff92004-11-22 19:12:49 +00005430 if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
sewardj7ce71662008-05-02 10:33:15 +00005431 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
bart91347382011-03-25 20:07:25 +00005432 && VG_USERREQ__RESIZEINPLACE_BLOCK != arg[0]
sewardj7ce71662008-05-02 10:33:15 +00005433 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
5434 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
5435 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
5436 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
5437 && VG_USERREQ__MEMPOOL_FREE != arg[0]
5438 && VG_USERREQ__MEMPOOL_TRIM != arg[0]
5439 && VG_USERREQ__MOVE_MEMPOOL != arg[0]
5440 && VG_USERREQ__MEMPOOL_CHANGE != arg[0]
sewardj3b290482011-05-06 21:02:55 +00005441 && VG_USERREQ__MEMPOOL_EXISTS != arg[0]
5442 && VG_USERREQ__GDB_MONITOR_COMMAND != arg[0])
nethercote8b76fe52004-11-08 19:20:09 +00005443 return False;
5444
5445 switch (arg[0]) {
njndbf7ca72006-03-31 11:57:59 +00005446 case VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE:
5447 ok = is_mem_addressable ( arg[1], arg[2], &bad_addr );
nethercote8b76fe52004-11-08 19:20:09 +00005448 if (!ok)
sewardj7ce71662008-05-02 10:33:15 +00005449 MC_(record_user_error) ( tid, bad_addr, /*isAddrErr*/True, 0 );
nethercote8b76fe52004-11-08 19:20:09 +00005450 *ret = ok ? (UWord)NULL : bad_addr;
sewardj8cf88b72005-07-08 01:29:33 +00005451 break;
nethercote8b76fe52004-11-08 19:20:09 +00005452
njndbf7ca72006-03-31 11:57:59 +00005453 case VG_USERREQ__CHECK_MEM_IS_DEFINED: {
sewardj4ef552a2011-10-24 05:59:54 +00005454 Bool errorV = False;
5455 Addr bad_addrV = 0;
5456 UInt otagV = 0;
5457 Bool errorA = False;
5458 Addr bad_addrA = 0;
5459 is_mem_defined_comprehensive(
5460 arg[1], arg[2],
5461 &errorV, &bad_addrV, &otagV, &errorA, &bad_addrA
5462 );
5463 if (errorV) {
5464 MC_(record_user_error) ( tid, bad_addrV,
5465 /*isAddrErr*/False, otagV );
5466 }
5467 if (errorA) {
5468 MC_(record_user_error) ( tid, bad_addrA,
5469 /*isAddrErr*/True, 0 );
5470 }
5471 /* Return the lower of the two erring addresses, if any. */
5472 *ret = 0;
5473 if (errorV && !errorA) {
5474 *ret = bad_addrV;
5475 }
5476 if (!errorV && errorA) {
5477 *ret = bad_addrA;
5478 }
5479 if (errorV && errorA) {
5480 *ret = bad_addrV < bad_addrA ? bad_addrV : bad_addrA;
5481 }
sewardj8cf88b72005-07-08 01:29:33 +00005482 break;
nethercote8b76fe52004-11-08 19:20:09 +00005483 }
5484
sewardjc8bd1df2011-06-26 12:41:33 +00005485 case VG_USERREQ__DO_LEAK_CHECK: {
5486 LeakCheckParams lcp;
5487
5488 if (arg[1] == 0)
5489 lcp.mode = LC_Full;
5490 else if (arg[1] == 1)
5491 lcp.mode = LC_Summary;
5492 else {
5493 VG_(message)(Vg_UserMsg,
5494 "Warning: unknown memcheck leak search mode\n");
5495 lcp.mode = LC_Full;
5496 }
5497
philippe2193a7c2012-12-08 17:54:16 +00005498 lcp.show_leak_kinds = MC_(clo_show_leak_kinds);
5499 lcp.errors_for_leak_kinds = MC_(clo_error_for_leak_kinds);
sewardjc8bd1df2011-06-26 12:41:33 +00005500
5501 if (arg[2] == 0)
5502 lcp.deltamode = LCD_Any;
5503 else if (arg[2] == 1)
5504 lcp.deltamode = LCD_Increased;
5505 else if (arg[2] == 2)
5506 lcp.deltamode = LCD_Changed;
5507 else {
5508 VG_(message)
5509 (Vg_UserMsg,
5510 "Warning: unknown memcheck leak search deltamode\n");
5511 lcp.deltamode = LCD_Any;
5512 }
philippe84234902012-01-14 13:53:13 +00005513 lcp.max_loss_records_output = 999999999;
sewardjc8bd1df2011-06-26 12:41:33 +00005514 lcp.requested_by_monitor_command = False;
5515
philippe84234902012-01-14 13:53:13 +00005516 MC_(detect_memory_leaks)(tid, &lcp);
sewardj8cf88b72005-07-08 01:29:33 +00005517 *ret = 0; /* return value is meaningless */
5518 break;
sewardjc8bd1df2011-06-26 12:41:33 +00005519 }
nethercote8b76fe52004-11-08 19:20:09 +00005520
njndbf7ca72006-03-31 11:57:59 +00005521 case VG_USERREQ__MAKE_MEM_NOACCESS:
5522 MC_(make_mem_noaccess) ( arg[1], arg[2] );
sewardj8cf88b72005-07-08 01:29:33 +00005523 *ret = -1;
5524 break;
nethercote8b76fe52004-11-08 19:20:09 +00005525
njndbf7ca72006-03-31 11:57:59 +00005526 case VG_USERREQ__MAKE_MEM_UNDEFINED:
sewardj7ce71662008-05-02 10:33:15 +00005527 make_mem_undefined_w_tid_and_okind ( arg[1], arg[2], tid,
5528 MC_OKIND_USER );
sewardjedc75ab2005-03-15 23:30:32 +00005529 *ret = -1;
sewardj8cf88b72005-07-08 01:29:33 +00005530 break;
nethercote8b76fe52004-11-08 19:20:09 +00005531
njndbf7ca72006-03-31 11:57:59 +00005532 case VG_USERREQ__MAKE_MEM_DEFINED:
5533 MC_(make_mem_defined) ( arg[1], arg[2] );
sewardj8cf88b72005-07-08 01:29:33 +00005534 *ret = -1;
nethercote8b76fe52004-11-08 19:20:09 +00005535 break;
5536
njndbf7ca72006-03-31 11:57:59 +00005537 case VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE:
5538 make_mem_defined_if_addressable ( arg[1], arg[2] );
sewardjfb1e9ad2006-03-10 13:41:58 +00005539 *ret = -1;
5540 break;
5541
sewardjedc75ab2005-03-15 23:30:32 +00005542 case VG_USERREQ__CREATE_BLOCK: /* describe a block */
sewardj8cf88b72005-07-08 01:29:33 +00005543 if (arg[1] != 0 && arg[2] != 0) {
5544 i = alloc_client_block();
5545 /* VG_(printf)("allocated %d %p\n", i, cgbs); */
5546 cgbs[i].start = arg[1];
5547 cgbs[i].size = arg[2];
florian19f91bb2012-11-10 22:29:54 +00005548 cgbs[i].desc = VG_(strdup)("mc.mhcr.1", (HChar *)arg[3]);
sewardj39f34232007-11-09 23:02:28 +00005549 cgbs[i].where = VG_(record_ExeContext) ( tid, 0/*first_ip_delta*/ );
sewardj8cf88b72005-07-08 01:29:33 +00005550 *ret = i;
5551 } else
5552 *ret = -1;
5553 break;
sewardjedc75ab2005-03-15 23:30:32 +00005554
nethercote8b76fe52004-11-08 19:20:09 +00005555 case VG_USERREQ__DISCARD: /* discard */
njn695c16e2005-03-27 03:40:28 +00005556 if (cgbs == NULL
5557 || arg[2] >= cgb_used ||
sewardj8cf88b72005-07-08 01:29:33 +00005558 (cgbs[arg[2]].start == 0 && cgbs[arg[2]].size == 0)) {
sewardjedc75ab2005-03-15 23:30:32 +00005559 *ret = 1;
sewardj8cf88b72005-07-08 01:29:33 +00005560 } else {
5561 tl_assert(arg[2] >= 0 && arg[2] < cgb_used);
5562 cgbs[arg[2]].start = cgbs[arg[2]].size = 0;
5563 VG_(free)(cgbs[arg[2]].desc);
5564 cgb_discards++;
5565 *ret = 0;
5566 }
5567 break;
nethercote8b76fe52004-11-08 19:20:09 +00005568
sewardjc2c12c22006-03-08 13:20:09 +00005569 case VG_USERREQ__GET_VBITS:
sewardjc2c12c22006-03-08 13:20:09 +00005570 *ret = mc_get_or_set_vbits_for_client
sewardj3b290482011-05-06 21:02:55 +00005571 ( arg[1], arg[2], arg[3],
5572 False /* get them */,
5573 True /* is client request */ );
sewardjc2c12c22006-03-08 13:20:09 +00005574 break;
5575
5576 case VG_USERREQ__SET_VBITS:
sewardjc2c12c22006-03-08 13:20:09 +00005577 *ret = mc_get_or_set_vbits_for_client
sewardj3b290482011-05-06 21:02:55 +00005578 ( arg[1], arg[2], arg[3],
5579 True /* set them */,
5580 True /* is client request */ );
sewardjc2c12c22006-03-08 13:20:09 +00005581 break;
nethercote8b76fe52004-11-08 19:20:09 +00005582
njn1d0825f2006-03-27 11:37:07 +00005583 case VG_USERREQ__COUNT_LEAKS: { /* count leaked bytes */
5584 UWord** argp = (UWord**)arg;
5585 // MC_(bytes_leaked) et al were set by the last leak check (or zero
5586 // if no prior leak checks performed).
5587 *argp[1] = MC_(bytes_leaked) + MC_(bytes_indirect);
5588 *argp[2] = MC_(bytes_dubious);
5589 *argp[3] = MC_(bytes_reachable);
5590 *argp[4] = MC_(bytes_suppressed);
5591 // there is no argp[5]
5592 //*argp[5] = MC_(bytes_indirect);
njn8df80b22009-03-02 05:11:06 +00005593 // XXX need to make *argp[1-4] defined; currently done in the
5594 // VALGRIND_COUNT_LEAKS_MACRO by initialising them to zero.
5595 *ret = 0;
5596 return True;
5597 }
5598 case VG_USERREQ__COUNT_LEAK_BLOCKS: { /* count leaked blocks */
5599 UWord** argp = (UWord**)arg;
5600 // MC_(blocks_leaked) et al were set by the last leak check (or zero
5601 // if no prior leak checks performed).
5602 *argp[1] = MC_(blocks_leaked) + MC_(blocks_indirect);
5603 *argp[2] = MC_(blocks_dubious);
5604 *argp[3] = MC_(blocks_reachable);
5605 *argp[4] = MC_(blocks_suppressed);
5606 // there is no argp[5]
5607 //*argp[5] = MC_(blocks_indirect);
5608 // XXX need to make *argp[1-4] defined; currently done in the
5609 // VALGRIND_COUNT_LEAK_BLOCKS_MACRO by initialising them to zero.
njn1d0825f2006-03-27 11:37:07 +00005610 *ret = 0;
5611 return True;
5612 }
5613 case VG_USERREQ__MALLOCLIKE_BLOCK: {
5614 Addr p = (Addr)arg[1];
5615 SizeT sizeB = arg[2];
philippe11cc9ce2012-03-11 17:59:00 +00005616 UInt rzB = arg[3];
njn1d0825f2006-03-27 11:37:07 +00005617 Bool is_zeroed = (Bool)arg[4];
5618
njn1dcee092009-02-24 03:07:37 +00005619 MC_(new_block) ( tid, p, sizeB, /*ignored*/0, is_zeroed,
njn1d0825f2006-03-27 11:37:07 +00005620 MC_AllocCustom, MC_(malloc_list) );
philippe11cc9ce2012-03-11 17:59:00 +00005621 if (rzB > 0) {
5622 MC_(make_mem_noaccess) ( p - rzB, rzB);
5623 MC_(make_mem_noaccess) ( p + sizeB, rzB);
5624 }
njn1d0825f2006-03-27 11:37:07 +00005625 return True;
5626 }
bart91347382011-03-25 20:07:25 +00005627 case VG_USERREQ__RESIZEINPLACE_BLOCK: {
5628 Addr p = (Addr)arg[1];
5629 SizeT oldSizeB = arg[2];
5630 SizeT newSizeB = arg[3];
5631 UInt rzB = arg[4];
5632
5633 MC_(handle_resizeInPlace) ( tid, p, oldSizeB, newSizeB, rzB );
5634 return True;
5635 }
njn1d0825f2006-03-27 11:37:07 +00005636 case VG_USERREQ__FREELIKE_BLOCK: {
5637 Addr p = (Addr)arg[1];
5638 UInt rzB = arg[2];
5639
5640 MC_(handle_free) ( tid, p, rzB, MC_AllocCustom );
5641 return True;
5642 }
5643
5644 case _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR: {
florian19f91bb2012-11-10 22:29:54 +00005645 HChar* s = (HChar*)arg[1];
njn718d3b12006-12-16 00:54:12 +00005646 Addr dst = (Addr) arg[2];
5647 Addr src = (Addr) arg[3];
5648 SizeT len = (SizeT)arg[4];
sewardj7ce71662008-05-02 10:33:15 +00005649 MC_(record_overlap_error)(tid, s, src, dst, len);
njn1d0825f2006-03-27 11:37:07 +00005650 return True;
5651 }
5652
5653 case VG_USERREQ__CREATE_MEMPOOL: {
5654 Addr pool = (Addr)arg[1];
5655 UInt rzB = arg[2];
5656 Bool is_zeroed = (Bool)arg[3];
5657
5658 MC_(create_mempool) ( pool, rzB, is_zeroed );
5659 return True;
5660 }
5661
5662 case VG_USERREQ__DESTROY_MEMPOOL: {
5663 Addr pool = (Addr)arg[1];
5664
5665 MC_(destroy_mempool) ( pool );
5666 return True;
5667 }
5668
5669 case VG_USERREQ__MEMPOOL_ALLOC: {
5670 Addr pool = (Addr)arg[1];
5671 Addr addr = (Addr)arg[2];
5672 UInt size = arg[3];
5673
5674 MC_(mempool_alloc) ( tid, pool, addr, size );
5675 return True;
5676 }
5677
5678 case VG_USERREQ__MEMPOOL_FREE: {
5679 Addr pool = (Addr)arg[1];
5680 Addr addr = (Addr)arg[2];
5681
5682 MC_(mempool_free) ( pool, addr );
5683 return True;
5684 }
5685
sewardj2c1c9df2006-07-28 00:06:37 +00005686 case VG_USERREQ__MEMPOOL_TRIM: {
5687 Addr pool = (Addr)arg[1];
5688 Addr addr = (Addr)arg[2];
5689 UInt size = arg[3];
5690
5691 MC_(mempool_trim) ( pool, addr, size );
5692 return True;
5693 }
5694
sewardjc740d762006-10-05 17:59:23 +00005695 case VG_USERREQ__MOVE_MEMPOOL: {
5696 Addr poolA = (Addr)arg[1];
5697 Addr poolB = (Addr)arg[2];
5698
5699 MC_(move_mempool) ( poolA, poolB );
5700 return True;
5701 }
5702
5703 case VG_USERREQ__MEMPOOL_CHANGE: {
5704 Addr pool = (Addr)arg[1];
5705 Addr addrA = (Addr)arg[2];
5706 Addr addrB = (Addr)arg[3];
5707 UInt size = arg[4];
5708
5709 MC_(mempool_change) ( pool, addrA, addrB, size );
5710 return True;
5711 }
5712
5713 case VG_USERREQ__MEMPOOL_EXISTS: {
5714 Addr pool = (Addr)arg[1];
5715
5716 *ret = (UWord) MC_(mempool_exists) ( pool );
5717 return True;
5718 }
5719
sewardj3b290482011-05-06 21:02:55 +00005720 case VG_USERREQ__GDB_MONITOR_COMMAND: {
florian19f91bb2012-11-10 22:29:54 +00005721 Bool handled = handle_gdb_monitor_command (tid, (HChar*)arg[1]);
sewardj3b290482011-05-06 21:02:55 +00005722 if (handled)
5723 *ret = 1;
5724 else
5725 *ret = 0;
5726 return handled;
5727 }
sewardjc740d762006-10-05 17:59:23 +00005728
nethercote8b76fe52004-11-08 19:20:09 +00005729 default:
sewardj6b523cd2009-07-15 14:49:40 +00005730 VG_(message)(
5731 Vg_UserMsg,
5732 "Warning: unknown memcheck client request code %llx\n",
5733 (ULong)arg[0]
5734 );
njn1d0825f2006-03-27 11:37:07 +00005735 return False;
nethercote8b76fe52004-11-08 19:20:09 +00005736 }
5737 return True;
5738}
njn25e49d8e72002-09-23 09:36:25 +00005739
njnf76d27a2009-05-28 01:53:07 +00005740
njn25e49d8e72002-09-23 09:36:25 +00005741/*------------------------------------------------------------*/
njn1d0825f2006-03-27 11:37:07 +00005742/*--- Crude profiling machinery. ---*/
5743/*------------------------------------------------------------*/
5744
5745// We track a number of interesting events (using PROF_EVENT)
5746// if MC_PROFILE_MEMORY is defined.
5747
5748#ifdef MC_PROFILE_MEMORY
5749
5750UInt MC_(event_ctr)[N_PROF_EVENTS];
5751HChar* MC_(event_ctr_name)[N_PROF_EVENTS];
5752
5753static void init_prof_mem ( void )
5754{
5755 Int i;
5756 for (i = 0; i < N_PROF_EVENTS; i++) {
5757 MC_(event_ctr)[i] = 0;
5758 MC_(event_ctr_name)[i] = NULL;
5759 }
5760}
5761
5762static void done_prof_mem ( void )
5763{
5764 Int i;
5765 Bool spaced = False;
5766 for (i = 0; i < N_PROF_EVENTS; i++) {
5767 if (!spaced && (i % 10) == 0) {
5768 VG_(printf)("\n");
5769 spaced = True;
5770 }
5771 if (MC_(event_ctr)[i] > 0) {
5772 spaced = False;
5773 VG_(printf)( "prof mem event %3d: %9d %s\n",
5774 i, MC_(event_ctr)[i],
5775 MC_(event_ctr_name)[i]
5776 ? MC_(event_ctr_name)[i] : "unnamed");
5777 }
5778 }
5779}
5780
5781#else
5782
5783static void init_prof_mem ( void ) { }
5784static void done_prof_mem ( void ) { }
5785
5786#endif
5787
sewardj7cf4e6b2008-05-01 20:24:26 +00005788
5789/*------------------------------------------------------------*/
5790/*--- Origin tracking stuff ---*/
5791/*------------------------------------------------------------*/
5792
5793/*--------------------------------------------*/
5794/*--- Origin tracking: load handlers ---*/
5795/*--------------------------------------------*/
5796
5797static INLINE UInt merge_origins ( UInt or1, UInt or2 ) {
5798 return or1 > or2 ? or1 : or2;
5799}
5800
5801UWord VG_REGPARM(1) MC_(helperc_b_load1)( Addr a ) {
5802 OCacheLine* line;
5803 UChar descr;
5804 UWord lineoff = oc_line_offset(a);
5805 UWord byteoff = a & 3; /* 0, 1, 2 or 3 */
5806
5807 if (OC_ENABLE_ASSERTIONS) {
5808 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
5809 }
5810
5811 line = find_OCacheLine( a );
5812
5813 descr = line->descr[lineoff];
5814 if (OC_ENABLE_ASSERTIONS) {
5815 tl_assert(descr < 0x10);
5816 }
5817
5818 if (LIKELY(0 == (descr & (1 << byteoff)))) {
5819 return 0;
5820 } else {
5821 return line->w32[lineoff];
5822 }
5823}
5824
5825UWord VG_REGPARM(1) MC_(helperc_b_load2)( Addr a ) {
5826 OCacheLine* line;
5827 UChar descr;
5828 UWord lineoff, byteoff;
5829
5830 if (UNLIKELY(a & 1)) {
5831 /* Handle misaligned case, slowly. */
5832 UInt oLo = (UInt)MC_(helperc_b_load1)( a + 0 );
5833 UInt oHi = (UInt)MC_(helperc_b_load1)( a + 1 );
5834 return merge_origins(oLo, oHi);
5835 }
5836
5837 lineoff = oc_line_offset(a);
5838 byteoff = a & 3; /* 0 or 2 */
5839
5840 if (OC_ENABLE_ASSERTIONS) {
5841 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
5842 }
5843 line = find_OCacheLine( a );
5844
5845 descr = line->descr[lineoff];
5846 if (OC_ENABLE_ASSERTIONS) {
5847 tl_assert(descr < 0x10);
5848 }
5849
5850 if (LIKELY(0 == (descr & (3 << byteoff)))) {
5851 return 0;
5852 } else {
5853 return line->w32[lineoff];
5854 }
5855}
5856
5857UWord VG_REGPARM(1) MC_(helperc_b_load4)( Addr a ) {
5858 OCacheLine* line;
5859 UChar descr;
5860 UWord lineoff;
5861
5862 if (UNLIKELY(a & 3)) {
5863 /* Handle misaligned case, slowly. */
5864 UInt oLo = (UInt)MC_(helperc_b_load2)( a + 0 );
5865 UInt oHi = (UInt)MC_(helperc_b_load2)( a + 2 );
5866 return merge_origins(oLo, oHi);
5867 }
5868
5869 lineoff = oc_line_offset(a);
5870 if (OC_ENABLE_ASSERTIONS) {
5871 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
5872 }
5873
5874 line = find_OCacheLine( a );
5875
5876 descr = line->descr[lineoff];
5877 if (OC_ENABLE_ASSERTIONS) {
5878 tl_assert(descr < 0x10);
5879 }
5880
5881 if (LIKELY(0 == descr)) {
5882 return 0;
5883 } else {
5884 return line->w32[lineoff];
5885 }
5886}
5887
5888UWord VG_REGPARM(1) MC_(helperc_b_load8)( Addr a ) {
5889 OCacheLine* line;
5890 UChar descrLo, descrHi, descr;
5891 UWord lineoff;
5892
5893 if (UNLIKELY(a & 7)) {
5894 /* Handle misaligned case, slowly. */
5895 UInt oLo = (UInt)MC_(helperc_b_load4)( a + 0 );
5896 UInt oHi = (UInt)MC_(helperc_b_load4)( a + 4 );
5897 return merge_origins(oLo, oHi);
5898 }
5899
5900 lineoff = oc_line_offset(a);
5901 if (OC_ENABLE_ASSERTIONS) {
5902 tl_assert(lineoff == (lineoff & 6)); /*0,2,4,6*//*since 8-aligned*/
5903 }
5904
5905 line = find_OCacheLine( a );
5906
5907 descrLo = line->descr[lineoff + 0];
5908 descrHi = line->descr[lineoff + 1];
5909 descr = descrLo | descrHi;
5910 if (OC_ENABLE_ASSERTIONS) {
5911 tl_assert(descr < 0x10);
5912 }
5913
5914 if (LIKELY(0 == descr)) {
5915 return 0; /* both 32-bit chunks are defined */
5916 } else {
5917 UInt oLo = descrLo == 0 ? 0 : line->w32[lineoff + 0];
5918 UInt oHi = descrHi == 0 ? 0 : line->w32[lineoff + 1];
5919 return merge_origins(oLo, oHi);
5920 }
5921}
5922
5923UWord VG_REGPARM(1) MC_(helperc_b_load16)( Addr a ) {
5924 UInt oLo = (UInt)MC_(helperc_b_load8)( a + 0 );
5925 UInt oHi = (UInt)MC_(helperc_b_load8)( a + 8 );
5926 UInt oBoth = merge_origins(oLo, oHi);
5927 return (UWord)oBoth;
5928}
5929
sewardj45fa9f42012-05-21 10:18:10 +00005930UWord VG_REGPARM(1) MC_(helperc_b_load32)( Addr a ) {
5931 UInt oQ0 = (UInt)MC_(helperc_b_load8)( a + 0 );
5932 UInt oQ1 = (UInt)MC_(helperc_b_load8)( a + 8 );
5933 UInt oQ2 = (UInt)MC_(helperc_b_load8)( a + 16 );
5934 UInt oQ3 = (UInt)MC_(helperc_b_load8)( a + 24 );
5935 UInt oAll = merge_origins(merge_origins(oQ0, oQ1),
5936 merge_origins(oQ2, oQ3));
5937 return (UWord)oAll;
5938}
5939
sewardj7cf4e6b2008-05-01 20:24:26 +00005940
5941/*--------------------------------------------*/
5942/*--- Origin tracking: store handlers ---*/
5943/*--------------------------------------------*/
5944
5945void VG_REGPARM(2) MC_(helperc_b_store1)( Addr a, UWord d32 ) {
5946 OCacheLine* line;
5947 UWord lineoff = oc_line_offset(a);
5948 UWord byteoff = a & 3; /* 0, 1, 2 or 3 */
5949
5950 if (OC_ENABLE_ASSERTIONS) {
5951 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
5952 }
5953
5954 line = find_OCacheLine( a );
5955
5956 if (d32 == 0) {
5957 line->descr[lineoff] &= ~(1 << byteoff);
5958 } else {
5959 line->descr[lineoff] |= (1 << byteoff);
5960 line->w32[lineoff] = d32;
5961 }
5962}
5963
5964void VG_REGPARM(2) MC_(helperc_b_store2)( Addr a, UWord d32 ) {
5965 OCacheLine* line;
5966 UWord lineoff, byteoff;
5967
5968 if (UNLIKELY(a & 1)) {
5969 /* Handle misaligned case, slowly. */
5970 MC_(helperc_b_store1)( a + 0, d32 );
5971 MC_(helperc_b_store1)( a + 1, d32 );
5972 return;
5973 }
5974
5975 lineoff = oc_line_offset(a);
5976 byteoff = a & 3; /* 0 or 2 */
5977
5978 if (OC_ENABLE_ASSERTIONS) {
5979 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
5980 }
5981
5982 line = find_OCacheLine( a );
5983
5984 if (d32 == 0) {
5985 line->descr[lineoff] &= ~(3 << byteoff);
5986 } else {
5987 line->descr[lineoff] |= (3 << byteoff);
5988 line->w32[lineoff] = d32;
5989 }
5990}
5991
5992void VG_REGPARM(2) MC_(helperc_b_store4)( Addr a, UWord d32 ) {
5993 OCacheLine* line;
5994 UWord lineoff;
5995
5996 if (UNLIKELY(a & 3)) {
5997 /* Handle misaligned case, slowly. */
5998 MC_(helperc_b_store2)( a + 0, d32 );
5999 MC_(helperc_b_store2)( a + 2, d32 );
6000 return;
6001 }
6002
6003 lineoff = oc_line_offset(a);
6004 if (OC_ENABLE_ASSERTIONS) {
6005 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
6006 }
6007
6008 line = find_OCacheLine( a );
6009
6010 if (d32 == 0) {
6011 line->descr[lineoff] = 0;
6012 } else {
6013 line->descr[lineoff] = 0xF;
6014 line->w32[lineoff] = d32;
6015 }
6016}
6017
6018void VG_REGPARM(2) MC_(helperc_b_store8)( Addr a, UWord d32 ) {
6019 OCacheLine* line;
6020 UWord lineoff;
6021
6022 if (UNLIKELY(a & 7)) {
6023 /* Handle misaligned case, slowly. */
6024 MC_(helperc_b_store4)( a + 0, d32 );
6025 MC_(helperc_b_store4)( a + 4, d32 );
6026 return;
6027 }
6028
6029 lineoff = oc_line_offset(a);
6030 if (OC_ENABLE_ASSERTIONS) {
6031 tl_assert(lineoff == (lineoff & 6)); /*0,2,4,6*//*since 8-aligned*/
6032 }
6033
6034 line = find_OCacheLine( a );
6035
6036 if (d32 == 0) {
6037 line->descr[lineoff + 0] = 0;
6038 line->descr[lineoff + 1] = 0;
6039 } else {
6040 line->descr[lineoff + 0] = 0xF;
6041 line->descr[lineoff + 1] = 0xF;
6042 line->w32[lineoff + 0] = d32;
6043 line->w32[lineoff + 1] = d32;
6044 }
6045}
6046
6047void VG_REGPARM(2) MC_(helperc_b_store16)( Addr a, UWord d32 ) {
6048 MC_(helperc_b_store8)( a + 0, d32 );
6049 MC_(helperc_b_store8)( a + 8, d32 );
6050}
6051
sewardj45fa9f42012-05-21 10:18:10 +00006052void VG_REGPARM(2) MC_(helperc_b_store32)( Addr a, UWord d32 ) {
6053 MC_(helperc_b_store8)( a + 0, d32 );
6054 MC_(helperc_b_store8)( a + 8, d32 );
6055 MC_(helperc_b_store8)( a + 16, d32 );
6056 MC_(helperc_b_store8)( a + 24, d32 );
6057}
6058
sewardj7cf4e6b2008-05-01 20:24:26 +00006059
6060/*--------------------------------------------*/
6061/*--- Origin tracking: sarp handlers ---*/
6062/*--------------------------------------------*/
6063
6064__attribute__((noinline))
6065static void ocache_sarp_Set_Origins ( Addr a, UWord len, UInt otag ) {
6066 if ((a & 1) && len >= 1) {
6067 MC_(helperc_b_store1)( a, otag );
6068 a++;
6069 len--;
6070 }
6071 if ((a & 2) && len >= 2) {
6072 MC_(helperc_b_store2)( a, otag );
6073 a += 2;
6074 len -= 2;
6075 }
6076 if (len >= 4)
6077 tl_assert(0 == (a & 3));
6078 while (len >= 4) {
6079 MC_(helperc_b_store4)( a, otag );
6080 a += 4;
6081 len -= 4;
6082 }
6083 if (len >= 2) {
6084 MC_(helperc_b_store2)( a, otag );
6085 a += 2;
6086 len -= 2;
6087 }
6088 if (len >= 1) {
6089 MC_(helperc_b_store1)( a, otag );
njn4c245e52009-03-15 23:25:38 +00006090 //a++;
sewardj7cf4e6b2008-05-01 20:24:26 +00006091 len--;
6092 }
6093 tl_assert(len == 0);
6094}
6095
6096__attribute__((noinline))
6097static void ocache_sarp_Clear_Origins ( Addr a, UWord len ) {
6098 if ((a & 1) && len >= 1) {
6099 MC_(helperc_b_store1)( a, 0 );
6100 a++;
6101 len--;
6102 }
6103 if ((a & 2) && len >= 2) {
6104 MC_(helperc_b_store2)( a, 0 );
6105 a += 2;
6106 len -= 2;
6107 }
6108 if (len >= 4)
6109 tl_assert(0 == (a & 3));
6110 while (len >= 4) {
6111 MC_(helperc_b_store4)( a, 0 );
6112 a += 4;
6113 len -= 4;
6114 }
6115 if (len >= 2) {
6116 MC_(helperc_b_store2)( a, 0 );
6117 a += 2;
6118 len -= 2;
6119 }
6120 if (len >= 1) {
6121 MC_(helperc_b_store1)( a, 0 );
njn4c245e52009-03-15 23:25:38 +00006122 //a++;
sewardj7cf4e6b2008-05-01 20:24:26 +00006123 len--;
6124 }
6125 tl_assert(len == 0);
6126}
6127
6128
njn1d0825f2006-03-27 11:37:07 +00006129/*------------------------------------------------------------*/
njn51d827b2005-05-09 01:02:08 +00006130/*--- Setup and finalisation ---*/
njn25e49d8e72002-09-23 09:36:25 +00006131/*------------------------------------------------------------*/
6132
njn51d827b2005-05-09 01:02:08 +00006133static void mc_post_clo_init ( void )
njn5c004e42002-11-18 11:04:50 +00006134{
sewardj71bc3cb2005-05-19 00:25:45 +00006135 /* If we've been asked to emit XML, mash around various other
6136 options so as to constrain the output somewhat. */
6137 if (VG_(clo_xml)) {
6138 /* Extract as much info as possible from the leak checker. */
njn1d0825f2006-03-27 11:37:07 +00006139 MC_(clo_leak_check) = LC_Full;
sewardj71bc3cb2005-05-19 00:25:45 +00006140 }
sewardj7cf4e6b2008-05-01 20:24:26 +00006141
sewardj403d8aa2011-10-22 19:48:57 +00006142 if (MC_(clo_freelist_big_blocks) >= MC_(clo_freelist_vol))
6143 VG_(message)(Vg_UserMsg,
6144 "Warning: --freelist-big-blocks value %lld has no effect\n"
6145 "as it is >= to --freelist-vol value %lld\n",
6146 MC_(clo_freelist_big_blocks),
6147 MC_(clo_freelist_vol));
6148
sewardj7cf4e6b2008-05-01 20:24:26 +00006149 tl_assert( MC_(clo_mc_level) >= 1 && MC_(clo_mc_level) <= 3 );
6150
6151 if (MC_(clo_mc_level) == 3) {
6152 /* We're doing origin tracking. */
6153# ifdef PERF_FAST_STACK
6154 VG_(track_new_mem_stack_4_w_ECU) ( mc_new_mem_stack_4_w_ECU );
6155 VG_(track_new_mem_stack_8_w_ECU) ( mc_new_mem_stack_8_w_ECU );
6156 VG_(track_new_mem_stack_12_w_ECU) ( mc_new_mem_stack_12_w_ECU );
6157 VG_(track_new_mem_stack_16_w_ECU) ( mc_new_mem_stack_16_w_ECU );
6158 VG_(track_new_mem_stack_32_w_ECU) ( mc_new_mem_stack_32_w_ECU );
6159 VG_(track_new_mem_stack_112_w_ECU) ( mc_new_mem_stack_112_w_ECU );
6160 VG_(track_new_mem_stack_128_w_ECU) ( mc_new_mem_stack_128_w_ECU );
6161 VG_(track_new_mem_stack_144_w_ECU) ( mc_new_mem_stack_144_w_ECU );
6162 VG_(track_new_mem_stack_160_w_ECU) ( mc_new_mem_stack_160_w_ECU );
6163# endif
6164 VG_(track_new_mem_stack_w_ECU) ( mc_new_mem_stack_w_ECU );
philippe5db022b2013-01-13 15:01:21 +00006165 VG_(track_new_mem_stack_signal) ( mc_new_mem_w_tid_make_ECU );
sewardj7cf4e6b2008-05-01 20:24:26 +00006166 } else {
6167 /* Not doing origin tracking */
6168# ifdef PERF_FAST_STACK
6169 VG_(track_new_mem_stack_4) ( mc_new_mem_stack_4 );
6170 VG_(track_new_mem_stack_8) ( mc_new_mem_stack_8 );
6171 VG_(track_new_mem_stack_12) ( mc_new_mem_stack_12 );
6172 VG_(track_new_mem_stack_16) ( mc_new_mem_stack_16 );
6173 VG_(track_new_mem_stack_32) ( mc_new_mem_stack_32 );
6174 VG_(track_new_mem_stack_112) ( mc_new_mem_stack_112 );
6175 VG_(track_new_mem_stack_128) ( mc_new_mem_stack_128 );
6176 VG_(track_new_mem_stack_144) ( mc_new_mem_stack_144 );
6177 VG_(track_new_mem_stack_160) ( mc_new_mem_stack_160 );
6178# endif
6179 VG_(track_new_mem_stack) ( mc_new_mem_stack );
philippe5db022b2013-01-13 15:01:21 +00006180 VG_(track_new_mem_stack_signal) ( mc_new_mem_w_tid_no_ECU );
sewardj7cf4e6b2008-05-01 20:24:26 +00006181 }
sewardj9d624d12008-05-02 13:35:29 +00006182
philippe5db022b2013-01-13 15:01:21 +00006183 // We assume that brk()/sbrk() does not initialise new memory. Is this
6184 // accurate? John Reiser says:
6185 //
6186 // 0) sbrk() can *decrease* process address space. No zero fill is done
6187 // for a decrease, not even the fragment on the high end of the last page
6188 // that is beyond the new highest address. For maximum safety and
6189 // portability, then the bytes in the last page that reside above [the
6190 // new] sbrk(0) should be considered to be uninitialized, but in practice
6191 // it is exceedingly likely that they will retain their previous
6192 // contents.
6193 //
6194 // 1) If an increase is large enough to require new whole pages, then
6195 // those new whole pages (like all new pages) are zero-filled by the
6196 // operating system. So if sbrk(0) already is page aligned, then
6197 // sbrk(PAGE_SIZE) *does* zero-fill the new memory.
6198 //
6199 // 2) Any increase that lies within an existing allocated page is not
6200 // changed. So if (x = sbrk(0)) is not page aligned, then
6201 // sbrk(PAGE_SIZE) yields ((PAGE_SIZE -1) & -x) bytes which keep their
6202 // existing contents, and an additional PAGE_SIZE bytes which are zeroed.
6203 // ((PAGE_SIZE -1) & x) of them are "covered" by the sbrk(), and the rest
6204 // of them come along for the ride because the operating system deals
6205 // only in whole pages. Again, for maximum safety and portability, then
6206 // anything that lives above [the new] sbrk(0) should be considered
6207 // uninitialized, but in practice will retain previous contents [zero in
6208 // this case.]"
6209 //
6210 // In short:
6211 //
6212 // A key property of sbrk/brk is that new whole pages that are supplied
6213 // by the operating system *do* get initialized to zero.
6214 //
6215 // As for the portability of all this:
6216 //
6217 // sbrk and brk are not POSIX. However, any system that is a derivative
6218 // of *nix has sbrk and brk because there are too many softwares (such as
6219 // the Bourne shell) which rely on the traditional memory map (.text,
6220 // .data+.bss, stack) and the existence of sbrk/brk.
6221 //
6222 // So we should arguably observe all this. However:
6223 // - The current inaccuracy has caused maybe one complaint in seven years(?)
6224 // - Relying on the zeroed-ness of whole brk'd pages is pretty grotty... I
6225 // doubt most programmers know the above information.
6226 // So I'm not terribly unhappy with marking it as undefined. --njn.
6227 //
6228 // [More: I think most of what John said only applies to sbrk(). It seems
6229 // that brk() always deals in whole pages. And since this event deals
6230 // directly with brk(), not with sbrk(), perhaps it would be reasonable to
6231 // just mark all memory it allocates as defined.]
6232 //
6233 if (MC_(clo_mc_level) == 3)
6234 VG_(track_new_mem_brk) ( mc_new_mem_w_tid_make_ECU );
6235 else
6236 VG_(track_new_mem_brk) ( mc_new_mem_w_tid_no_ECU );
6237
sewardj9d624d12008-05-02 13:35:29 +00006238 /* This origin tracking cache is huge (~100M), so only initialise
6239 if we need it. */
6240 if (MC_(clo_mc_level) >= 3) {
6241 init_OCache();
sewardj77139802008-05-05 09:48:56 +00006242 tl_assert(ocacheL1 != NULL);
sewardj9d624d12008-05-02 13:35:29 +00006243 tl_assert(ocacheL2 != NULL);
6244 } else {
sewardj77139802008-05-05 09:48:56 +00006245 tl_assert(ocacheL1 == NULL);
sewardj9d624d12008-05-02 13:35:29 +00006246 tl_assert(ocacheL2 == NULL);
6247 }
florian971ab8f2012-05-12 18:06:35 +00006248
philippe8617b5b2013-01-12 19:53:08 +00006249 MC_(chunk_poolalloc) = VG_(newPA)
6250 (sizeof(MC_Chunk) + MC_(n_where_pointers)() * sizeof(ExeContext*),
6251 1000,
6252 VG_(malloc),
6253 "mc.cMC.1 (MC_Chunk pools)",
6254 VG_(free));
6255
florian971ab8f2012-05-12 18:06:35 +00006256 /* Do not check definedness of guest state if --undef-value-errors=no */
6257 if (MC_(clo_mc_level) >= 2)
6258 VG_(track_pre_reg_read) ( mc_pre_reg_read );
njn5c004e42002-11-18 11:04:50 +00006259}
6260
florian19f91bb2012-11-10 22:29:54 +00006261static void print_SM_info(const HChar* type, Int n_SMs)
njn1d0825f2006-03-27 11:37:07 +00006262{
6263 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006264 " memcheck: SMs: %s = %d (%ldk, %ldM)\n",
njn1d0825f2006-03-27 11:37:07 +00006265 type,
6266 n_SMs,
barta0b6b2c2008-07-07 06:49:24 +00006267 n_SMs * sizeof(SecMap) / 1024UL,
6268 n_SMs * sizeof(SecMap) / (1024 * 1024UL) );
njn1d0825f2006-03-27 11:37:07 +00006269}
6270
njn51d827b2005-05-09 01:02:08 +00006271static void mc_fini ( Int exitcode )
njn5c004e42002-11-18 11:04:50 +00006272{
njn1d0825f2006-03-27 11:37:07 +00006273 MC_(print_malloc_stats)();
sewardj23eb2fd2005-04-22 16:29:19 +00006274
sewardj2d9e8742009-08-07 15:46:56 +00006275 if (MC_(clo_leak_check) != LC_Off) {
sewardjc8bd1df2011-06-26 12:41:33 +00006276 LeakCheckParams lcp;
6277 lcp.mode = MC_(clo_leak_check);
philippe2193a7c2012-12-08 17:54:16 +00006278 lcp.show_leak_kinds = MC_(clo_show_leak_kinds);
6279 lcp.errors_for_leak_kinds = MC_(clo_error_for_leak_kinds);
sewardjc8bd1df2011-06-26 12:41:33 +00006280 lcp.deltamode = LCD_Any;
philippe84234902012-01-14 13:53:13 +00006281 lcp.max_loss_records_output = 999999999;
sewardjc8bd1df2011-06-26 12:41:33 +00006282 lcp.requested_by_monitor_command = False;
philippe84234902012-01-14 13:53:13 +00006283 MC_(detect_memory_leaks)(1/*bogus ThreadId*/, &lcp);
njnb6267bd2009-08-12 00:14:16 +00006284 } else {
6285 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
6286 VG_(umsg)(
6287 "For a detailed leak analysis, rerun with: --leak-check=full\n"
6288 "\n"
6289 );
6290 }
sewardj2d9e8742009-08-07 15:46:56 +00006291 }
6292
6293 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
6294 VG_(message)(Vg_UserMsg,
6295 "For counts of detected and suppressed errors, rerun with: -v\n");
6296 }
sewardj7cf4e6b2008-05-01 20:24:26 +00006297
sewardj7ce71662008-05-02 10:33:15 +00006298 if (MC_(any_value_errors) && !VG_(clo_xml) && VG_(clo_verbosity) >= 1
sewardj7cf4e6b2008-05-01 20:24:26 +00006299 && MC_(clo_mc_level) == 2) {
6300 VG_(message)(Vg_UserMsg,
6301 "Use --track-origins=yes to see where "
sewardj6b523cd2009-07-15 14:49:40 +00006302 "uninitialised values come from\n");
sewardj7cf4e6b2008-05-01 20:24:26 +00006303 }
6304
njn1d0825f2006-03-27 11:37:07 +00006305 done_prof_mem();
sewardjae986ca2005-10-12 12:53:20 +00006306
sewardj2d9e8742009-08-07 15:46:56 +00006307 if (VG_(clo_stats)) {
njn1d0825f2006-03-27 11:37:07 +00006308 SizeT max_secVBit_szB, max_SMs_szB, max_shmem_szB;
6309
sewardj45d94cc2005-04-20 14:44:11 +00006310 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006311 " memcheck: sanity checks: %d cheap, %d expensive\n",
sewardj23eb2fd2005-04-22 16:29:19 +00006312 n_sanity_cheap, n_sanity_expensive );
sewardj45d94cc2005-04-20 14:44:11 +00006313 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006314 " memcheck: auxmaps: %lld auxmap entries (%lldk, %lldM) in use\n",
sewardj05a46732006-10-17 01:28:10 +00006315 n_auxmap_L2_nodes,
6316 n_auxmap_L2_nodes * 64,
6317 n_auxmap_L2_nodes / 16 );
sewardj23eb2fd2005-04-22 16:29:19 +00006318 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006319 " memcheck: auxmaps_L1: %lld searches, %lld cmps, ratio %lld:10\n",
sewardj05a46732006-10-17 01:28:10 +00006320 n_auxmap_L1_searches, n_auxmap_L1_cmps,
6321 (10ULL * n_auxmap_L1_cmps)
6322 / (n_auxmap_L1_searches ? n_auxmap_L1_searches : 1)
6323 );
6324 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006325 " memcheck: auxmaps_L2: %lld searches, %lld nodes\n",
sewardj05a46732006-10-17 01:28:10 +00006326 n_auxmap_L2_searches, n_auxmap_L2_nodes
6327 );
sewardj23eb2fd2005-04-22 16:29:19 +00006328
njndbf7ca72006-03-31 11:57:59 +00006329 print_SM_info("n_issued ", n_issued_SMs);
6330 print_SM_info("n_deissued ", n_deissued_SMs);
6331 print_SM_info("max_noaccess ", max_noaccess_SMs);
6332 print_SM_info("max_undefined", max_undefined_SMs);
6333 print_SM_info("max_defined ", max_defined_SMs);
6334 print_SM_info("max_non_DSM ", max_non_DSM_SMs);
njn1d0825f2006-03-27 11:37:07 +00006335
6336 // Three DSMs, plus the non-DSM ones
6337 max_SMs_szB = (3 + max_non_DSM_SMs) * sizeof(SecMap);
6338 // The 3*sizeof(Word) bytes is the AVL node metadata size.
philipped895fee2012-02-08 22:23:55 +00006339 // The VG_ROUNDUP is because the OSet pool allocator will/must align
6340 // the elements on pointer size.
6341 // Note that the pool allocator has some additional small overhead
6342 // which is not counted in the below.
6343 // Hardwiring this logic sucks, but I don't see how else to do it.
njn1d0825f2006-03-27 11:37:07 +00006344 max_secVBit_szB = max_secVBit_nodes *
philipped895fee2012-02-08 22:23:55 +00006345 (3*sizeof(Word) + VG_ROUNDUP(sizeof(SecVBitNode), sizeof(void*)));
njn1d0825f2006-03-27 11:37:07 +00006346 max_shmem_szB = sizeof(primary_map) + max_SMs_szB + max_secVBit_szB;
sewardj23eb2fd2005-04-22 16:29:19 +00006347
6348 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006349 " memcheck: max sec V bit nodes: %d (%ldk, %ldM)\n",
njn1d0825f2006-03-27 11:37:07 +00006350 max_secVBit_nodes, max_secVBit_szB / 1024,
6351 max_secVBit_szB / (1024 * 1024));
6352 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006353 " memcheck: set_sec_vbits8 calls: %llu (new: %llu, updates: %llu)\n",
njn1d0825f2006-03-27 11:37:07 +00006354 sec_vbits_new_nodes + sec_vbits_updates,
6355 sec_vbits_new_nodes, sec_vbits_updates );
6356 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006357 " memcheck: max shadow mem size: %ldk, %ldM\n",
njn1d0825f2006-03-27 11:37:07 +00006358 max_shmem_szB / 1024, max_shmem_szB / (1024 * 1024));
sewardj7cf4e6b2008-05-01 20:24:26 +00006359
6360 if (MC_(clo_mc_level) >= 3) {
6361 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006362 " ocacheL1: %'12lu refs %'12lu misses (%'lu lossage)\n",
sewardj7cf4e6b2008-05-01 20:24:26 +00006363 stats_ocacheL1_find,
6364 stats_ocacheL1_misses,
6365 stats_ocacheL1_lossage );
6366 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006367 " ocacheL1: %'12lu at 0 %'12lu at 1\n",
sewardj7cf4e6b2008-05-01 20:24:26 +00006368 stats_ocacheL1_find - stats_ocacheL1_misses
6369 - stats_ocacheL1_found_at_1
6370 - stats_ocacheL1_found_at_N,
6371 stats_ocacheL1_found_at_1 );
6372 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006373 " ocacheL1: %'12lu at 2+ %'12lu move-fwds\n",
sewardj7cf4e6b2008-05-01 20:24:26 +00006374 stats_ocacheL1_found_at_N,
6375 stats_ocacheL1_movefwds );
6376 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006377 " ocacheL1: %'12lu sizeB %'12u useful\n",
sewardj7cf4e6b2008-05-01 20:24:26 +00006378 (UWord)sizeof(OCache),
6379 4 * OC_W32S_PER_LINE * OC_LINES_PER_SET * OC_N_SETS );
6380 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006381 " ocacheL2: %'12lu refs %'12lu misses\n",
sewardj7cf4e6b2008-05-01 20:24:26 +00006382 stats__ocacheL2_refs,
6383 stats__ocacheL2_misses );
6384 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006385 " ocacheL2: %'9lu max nodes %'9lu curr nodes\n",
sewardj7cf4e6b2008-05-01 20:24:26 +00006386 stats__ocacheL2_n_nodes_max,
6387 stats__ocacheL2_n_nodes );
6388 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006389 " niacache: %'12lu refs %'12lu misses\n",
sewardj7cf4e6b2008-05-01 20:24:26 +00006390 stats__nia_cache_queries, stats__nia_cache_misses);
sewardj9d624d12008-05-02 13:35:29 +00006391 } else {
sewardj77139802008-05-05 09:48:56 +00006392 tl_assert(ocacheL1 == NULL);
sewardj9d624d12008-05-02 13:35:29 +00006393 tl_assert(ocacheL2 == NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +00006394 }
sewardj45d94cc2005-04-20 14:44:11 +00006395 }
6396
njn5c004e42002-11-18 11:04:50 +00006397 if (0) {
6398 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006399 "------ Valgrind's client block stats follow ---------------\n" );
nethercote8b76fe52004-11-08 19:20:09 +00006400 show_client_block_stats();
njn5c004e42002-11-18 11:04:50 +00006401 }
njn25e49d8e72002-09-23 09:36:25 +00006402}
6403
sewardj3b290482011-05-06 21:02:55 +00006404/* mark the given addr/len unaddressable for watchpoint implementation
6405 The PointKind will be handled at access time */
6406static Bool mc_mark_unaddressable_for_watchpoint (PointKind kind, Bool insert,
6407 Addr addr, SizeT len)
6408{
6409 /* GDBTD this is somewhat fishy. We might rather have to save the previous
6410 accessibility and definedness in gdbserver so as to allow restoring it
6411 properly. Currently, we assume that the user only watches things
6412 which are properly addressable and defined */
6413 if (insert)
6414 MC_(make_mem_noaccess) (addr, len);
6415 else
6416 MC_(make_mem_defined) (addr, len);
6417 return True;
6418}
6419
njn51d827b2005-05-09 01:02:08 +00006420static void mc_pre_clo_init(void)
6421{
6422 VG_(details_name) ("Memcheck");
6423 VG_(details_version) (NULL);
6424 VG_(details_description) ("a memory error detector");
6425 VG_(details_copyright_author)(
sewardj03f8d3f2012-08-05 15:46:46 +00006426 "Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.");
njn51d827b2005-05-09 01:02:08 +00006427 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardj1e0fff62011-01-10 15:01:03 +00006428 VG_(details_avg_translation_sizeB) ( 640 );
njn51d827b2005-05-09 01:02:08 +00006429
6430 VG_(basic_tool_funcs) (mc_post_clo_init,
6431 MC_(instrument),
6432 mc_fini);
6433
sewardj81651dc2007-08-28 06:05:20 +00006434 VG_(needs_final_IR_tidy_pass) ( MC_(final_tidy) );
6435
6436
njn51d827b2005-05-09 01:02:08 +00006437 VG_(needs_core_errors) ();
sewardj7ce71662008-05-02 10:33:15 +00006438 VG_(needs_tool_errors) (MC_(eq_Error),
sewardj6b523cd2009-07-15 14:49:40 +00006439 MC_(before_pp_Error),
sewardj7ce71662008-05-02 10:33:15 +00006440 MC_(pp_Error),
sewardj39f34232007-11-09 23:02:28 +00006441 True,/*show TIDs for errors*/
sewardj7ce71662008-05-02 10:33:15 +00006442 MC_(update_Error_extra),
6443 MC_(is_recognised_suppression),
6444 MC_(read_extra_suppression_info),
6445 MC_(error_matches_suppression),
6446 MC_(get_error_name),
sewardj588adef2009-08-15 22:41:51 +00006447 MC_(get_extra_suppression_info));
njn51d827b2005-05-09 01:02:08 +00006448 VG_(needs_libc_freeres) ();
njn1d0825f2006-03-27 11:37:07 +00006449 VG_(needs_command_line_options)(mc_process_cmd_line_options,
njn51d827b2005-05-09 01:02:08 +00006450 mc_print_usage,
6451 mc_print_debug_usage);
6452 VG_(needs_client_requests) (mc_handle_client_request);
6453 VG_(needs_sanity_checks) (mc_cheap_sanity_check,
6454 mc_expensive_sanity_check);
njn1d0825f2006-03-27 11:37:07 +00006455 VG_(needs_malloc_replacement) (MC_(malloc),
6456 MC_(__builtin_new),
6457 MC_(__builtin_vec_new),
6458 MC_(memalign),
6459 MC_(calloc),
6460 MC_(free),
6461 MC_(__builtin_delete),
6462 MC_(__builtin_vec_delete),
6463 MC_(realloc),
njn8b140de2009-02-17 04:31:18 +00006464 MC_(malloc_usable_size),
philipped99c26a2012-07-31 22:17:28 +00006465 MC_MALLOC_DEFAULT_REDZONE_SZB );
6466 MC_(Malloc_Redzone_SzB) = VG_(malloc_effective_client_redzone_size)();
sewardj6b523cd2009-07-15 14:49:40 +00006467
njnca54af32006-04-16 10:25:43 +00006468 VG_(needs_xml_output) ();
njn51d827b2005-05-09 01:02:08 +00006469
njn1d0825f2006-03-27 11:37:07 +00006470 VG_(track_new_mem_startup) ( mc_new_mem_startup );
sewardj6f95e7e2010-01-27 10:28:00 +00006471
6472 // Handling of mmap and mprotect isn't simple (well, it is simple,
6473 // but the justification isn't.) See comments above, just prior to
6474 // mc_new_mem_mmap.
njn1d0825f2006-03-27 11:37:07 +00006475 VG_(track_new_mem_mmap) ( mc_new_mem_mmap );
sewardj6f95e7e2010-01-27 10:28:00 +00006476 VG_(track_change_mem_mprotect) ( mc_new_mem_mprotect );
njn51d827b2005-05-09 01:02:08 +00006477
njn1d0825f2006-03-27 11:37:07 +00006478 VG_(track_copy_mem_remap) ( MC_(copy_address_range_state) );
njn81623712005-10-07 04:48:37 +00006479
njndbf7ca72006-03-31 11:57:59 +00006480 VG_(track_die_mem_stack_signal)( MC_(make_mem_noaccess) );
6481 VG_(track_die_mem_brk) ( MC_(make_mem_noaccess) );
6482 VG_(track_die_mem_munmap) ( MC_(make_mem_noaccess) );
njn51d827b2005-05-09 01:02:08 +00006483
sewardj7cf4e6b2008-05-01 20:24:26 +00006484 /* Defer the specification of the new_mem_stack functions to the
6485 post_clo_init function, since we need to first parse the command
6486 line before deciding which set to use. */
njn51d827b2005-05-09 01:02:08 +00006487
sewardj7cf4e6b2008-05-01 20:24:26 +00006488# ifdef PERF_FAST_STACK
njn1d0825f2006-03-27 11:37:07 +00006489 VG_(track_die_mem_stack_4) ( mc_die_mem_stack_4 );
6490 VG_(track_die_mem_stack_8) ( mc_die_mem_stack_8 );
6491 VG_(track_die_mem_stack_12) ( mc_die_mem_stack_12 );
6492 VG_(track_die_mem_stack_16) ( mc_die_mem_stack_16 );
6493 VG_(track_die_mem_stack_32) ( mc_die_mem_stack_32 );
6494 VG_(track_die_mem_stack_112) ( mc_die_mem_stack_112 );
6495 VG_(track_die_mem_stack_128) ( mc_die_mem_stack_128 );
6496 VG_(track_die_mem_stack_144) ( mc_die_mem_stack_144 );
6497 VG_(track_die_mem_stack_160) ( mc_die_mem_stack_160 );
sewardj7cf4e6b2008-05-01 20:24:26 +00006498# endif
njn1d0825f2006-03-27 11:37:07 +00006499 VG_(track_die_mem_stack) ( mc_die_mem_stack );
njn51d827b2005-05-09 01:02:08 +00006500
njndbf7ca72006-03-31 11:57:59 +00006501 VG_(track_ban_mem_stack) ( MC_(make_mem_noaccess) );
njn51d827b2005-05-09 01:02:08 +00006502
njndbf7ca72006-03-31 11:57:59 +00006503 VG_(track_pre_mem_read) ( check_mem_is_defined );
6504 VG_(track_pre_mem_read_asciiz) ( check_mem_is_defined_asciiz );
6505 VG_(track_pre_mem_write) ( check_mem_is_addressable );
njn1d0825f2006-03-27 11:37:07 +00006506 VG_(track_post_mem_write) ( mc_post_mem_write );
njn51d827b2005-05-09 01:02:08 +00006507
njn1d0825f2006-03-27 11:37:07 +00006508 VG_(track_post_reg_write) ( mc_post_reg_write );
6509 VG_(track_post_reg_write_clientcall_return)( mc_post_reg_write_clientcall );
njn51d827b2005-05-09 01:02:08 +00006510
sewardj3b290482011-05-06 21:02:55 +00006511 VG_(needs_watchpoint) ( mc_mark_unaddressable_for_watchpoint );
6512
njn51d827b2005-05-09 01:02:08 +00006513 init_shadow_memory();
philippe8617b5b2013-01-12 19:53:08 +00006514 // MC_(chunk_poolalloc) must be allocated in post_clo_init
6515 tl_assert(MC_(chunk_poolalloc) == NULL);
sewardj3f94a7d2007-08-25 07:19:08 +00006516 MC_(malloc_list) = VG_(HT_construct)( "MC_(malloc_list)" );
6517 MC_(mempool_list) = VG_(HT_construct)( "MC_(mempool_list)" );
njn1d0825f2006-03-27 11:37:07 +00006518 init_prof_mem();
njn51d827b2005-05-09 01:02:08 +00006519
6520 tl_assert( mc_expensive_sanity_check() );
njn1d0825f2006-03-27 11:37:07 +00006521
6522 // {LOADV,STOREV}[8421] will all fail horribly if this isn't true.
6523 tl_assert(sizeof(UWord) == sizeof(Addr));
sewardj05a46732006-10-17 01:28:10 +00006524 // Call me paranoid. I don't care.
6525 tl_assert(sizeof(void*) == sizeof(Addr));
njn1d0825f2006-03-27 11:37:07 +00006526
6527 // BYTES_PER_SEC_VBIT_NODE must be a power of two.
6528 tl_assert(-1 != VG_(log2)(BYTES_PER_SEC_VBIT_NODE));
sewardj7cf4e6b2008-05-01 20:24:26 +00006529
sewardj9d624d12008-05-02 13:35:29 +00006530 /* This is small. Always initialise it. */
sewardj7cf4e6b2008-05-01 20:24:26 +00006531 init_nia_to_ecu_cache();
sewardj7244e712008-05-02 12:35:48 +00006532
sewardj77139802008-05-05 09:48:56 +00006533 /* We can't initialise ocacheL1/ocacheL2 yet, since we don't know
6534 if we need to, since the command line args haven't been
6535 processed yet. Hence defer it to mc_post_clo_init. */
6536 tl_assert(ocacheL1 == NULL);
sewardj9d624d12008-05-02 13:35:29 +00006537 tl_assert(ocacheL2 == NULL);
6538
sewardj7244e712008-05-02 12:35:48 +00006539 /* Check some important stuff. See extensive comments above
6540 re UNALIGNED_OR_HIGH for background. */
6541# if VG_WORDSIZE == 4
6542 tl_assert(sizeof(void*) == 4);
6543 tl_assert(sizeof(Addr) == 4);
6544 tl_assert(sizeof(UWord) == 4);
6545 tl_assert(sizeof(Word) == 4);
6546 tl_assert(MAX_PRIMARY_ADDRESS == 0xFFFFFFFFUL);
6547 tl_assert(MASK(1) == 0UL);
6548 tl_assert(MASK(2) == 1UL);
6549 tl_assert(MASK(4) == 3UL);
6550 tl_assert(MASK(8) == 7UL);
6551# else
6552 tl_assert(VG_WORDSIZE == 8);
6553 tl_assert(sizeof(void*) == 8);
6554 tl_assert(sizeof(Addr) == 8);
6555 tl_assert(sizeof(UWord) == 8);
6556 tl_assert(sizeof(Word) == 8);
sewardj6805a4a2013-01-29 21:14:46 +00006557 tl_assert(MAX_PRIMARY_ADDRESS == 0xFFFFFFFFFULL);
6558 tl_assert(MASK(1) == 0xFFFFFFF000000000ULL);
6559 tl_assert(MASK(2) == 0xFFFFFFF000000001ULL);
6560 tl_assert(MASK(4) == 0xFFFFFFF000000003ULL);
6561 tl_assert(MASK(8) == 0xFFFFFFF000000007ULL);
sewardj7244e712008-05-02 12:35:48 +00006562# endif
njn51d827b2005-05-09 01:02:08 +00006563}
6564
sewardj45f4e7c2005-09-27 19:20:21 +00006565VG_DETERMINE_INTERFACE_VERSION(mc_pre_clo_init)
fitzhardinge98abfc72003-12-16 02:05:15 +00006566
njn25e49d8e72002-09-23 09:36:25 +00006567/*--------------------------------------------------------------------*/
sewardj7ce71662008-05-02 10:33:15 +00006568/*--- end mc_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00006569/*--------------------------------------------------------------------*/