blob: 30fa0084e96ff9fb19ea748776da69558b87ecb4 [file] [log] [blame]
florian60042192015-08-04 15:58:41 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
njnc9539842002-10-02 13:26:35 +00002
njn25e49d8e72002-09-23 09:36:25 +00003/*--------------------------------------------------------------------*/
njnc9539842002-10-02 13:26:35 +00004/*--- MemCheck: Maintain bitmaps of memory, tracking the ---*/
5/*--- accessibility (A) and validity (V) status of each byte. ---*/
njn25cac76cb2002-09-23 11:21:57 +00006/*--- mc_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00007/*--------------------------------------------------------------------*/
8
9/*
nethercote137bc552003-11-14 17:47:54 +000010 This file is part of MemCheck, a heavyweight Valgrind tool for
njnc9539842002-10-02 13:26:35 +000011 detecting memory errors.
njn25e49d8e72002-09-23 09:36:25 +000012
sewardjb3a1e4b2015-08-21 11:32:26 +000013 Copyright (C) 2000-2015 Julian Seward
njn25e49d8e72002-09-23 09:36:25 +000014 jseward@acm.org
15
16 This program is free software; you can redistribute it and/or
17 modify it under the terms of the GNU General Public License as
18 published by the Free Software Foundation; either version 2 of the
19 License, or (at your option) any later version.
20
21 This program is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29 02111-1307, USA.
30
31 The GNU General Public License is contained in the file COPYING.
32*/
33
njnc7561b92005-06-19 01:24:32 +000034#include "pub_tool_basics.h"
njn4802b382005-06-11 04:58:29 +000035#include "pub_tool_aspacemgr.h"
sewardj3b290482011-05-06 21:02:55 +000036#include "pub_tool_gdbserver.h"
philippe6643e962012-01-17 21:16:30 +000037#include "pub_tool_poolalloc.h"
njn1d0825f2006-03-27 11:37:07 +000038#include "pub_tool_hashtable.h" // For mc_include.h
njn97405b22005-06-02 03:39:33 +000039#include "pub_tool_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000040#include "pub_tool_libcassert.h"
njn36a20fa2005-06-03 03:08:39 +000041#include "pub_tool_libcprint.h"
njnf536bbb2005-06-13 04:21:38 +000042#include "pub_tool_machine.h"
njnc7561b92005-06-19 01:24:32 +000043#include "pub_tool_mallocfree.h"
44#include "pub_tool_options.h"
njn1d0825f2006-03-27 11:37:07 +000045#include "pub_tool_oset.h"
sewardjc5fc8662014-03-20 23:00:09 +000046#include "pub_tool_rangemap.h"
njnc7561b92005-06-19 01:24:32 +000047#include "pub_tool_replacemalloc.h"
48#include "pub_tool_tooliface.h"
49#include "pub_tool_threadstate.h"
50
51#include "mc_include.h"
52#include "memcheck.h" /* for client requests */
njn25e49d8e72002-09-23 09:36:25 +000053
sewardjc1a2cda2005-04-21 17:34:00 +000054
sewardj7b1f9eb2015-06-05 13:33:46 +000055/* Set to 1 to enable handwritten assembly helpers on targets for
56 which it is supported. */
57#define ENABLE_ASSEMBLY_HELPERS 1
58
njn1d0825f2006-03-27 11:37:07 +000059/* Set to 1 to do a little more sanity checking */
sewardj23eb2fd2005-04-22 16:29:19 +000060#define VG_DEBUG_MEMORY 0
sewardjc1a2cda2005-04-21 17:34:00 +000061
njn25e49d8e72002-09-23 09:36:25 +000062#define DEBUG(fmt, args...) //VG_(printf)(fmt, ## args)
63
sewardj7cf4e6b2008-05-01 20:24:26 +000064static void ocache_sarp_Set_Origins ( Addr, UWord, UInt ); /* fwds */
65static void ocache_sarp_Clear_Origins ( Addr, UWord ); /* fwds */
66
njn25e49d8e72002-09-23 09:36:25 +000067
njn25e49d8e72002-09-23 09:36:25 +000068/*------------------------------------------------------------*/
njn1d0825f2006-03-27 11:37:07 +000069/*--- Fast-case knobs ---*/
70/*------------------------------------------------------------*/
71
72// Comment these out to disable the fast cases (don't just set them to zero).
73
74#define PERF_FAST_LOADV 1
75#define PERF_FAST_STOREV 1
76
77#define PERF_FAST_SARP 1
78
79#define PERF_FAST_STACK 1
80#define PERF_FAST_STACK2 1
81
sewardj7cf4e6b2008-05-01 20:24:26 +000082/* Change this to 1 to enable assertions on origin tracking cache fast
83 paths */
84#define OC_ENABLE_ASSERTIONS 0
85
86
njn1d0825f2006-03-27 11:37:07 +000087/*------------------------------------------------------------*/
sewardj77139802008-05-05 09:48:56 +000088/*--- Comments on the origin tracking implementation ---*/
89/*------------------------------------------------------------*/
90
91/* See detailed comment entitled
92 AN OVERVIEW OF THE ORIGIN TRACKING IMPLEMENTATION
93 which is contained further on in this file. */
94
95
96/*------------------------------------------------------------*/
njn1d0825f2006-03-27 11:37:07 +000097/*--- V bits and A bits ---*/
98/*------------------------------------------------------------*/
99
100/* Conceptually, every byte value has 8 V bits, which track whether Memcheck
101 thinks the corresponding value bit is defined. And every memory byte
102 has an A bit, which tracks whether Memcheck thinks the program can access
njnf76d27a2009-05-28 01:53:07 +0000103 it safely (ie. it's mapped, and has at least one of the RWX permission bits
104 set). So every N-bit register is shadowed with N V bits, and every memory
105 byte is shadowed with 8 V bits and one A bit.
njn1d0825f2006-03-27 11:37:07 +0000106
107 In the implementation, we use two forms of compression (compressed V bits
108 and distinguished secondary maps) to avoid the 9-bit-per-byte overhead
109 for memory.
110
111 Memcheck also tracks extra information about each heap block that is
112 allocated, for detecting memory leaks and other purposes.
113*/
114
115/*------------------------------------------------------------*/
sewardj45d94cc2005-04-20 14:44:11 +0000116/*--- Basic A/V bitmap representation. ---*/
njn25e49d8e72002-09-23 09:36:25 +0000117/*------------------------------------------------------------*/
118
njn1d0825f2006-03-27 11:37:07 +0000119/* All reads and writes are checked against a memory map (a.k.a. shadow
120 memory), which records the state of all memory in the process.
121
122 On 32-bit machines the memory map is organised as follows.
123 The top 16 bits of an address are used to index into a top-level
124 map table, containing 65536 entries. Each entry is a pointer to a
125 second-level map, which records the accesibililty and validity
126 permissions for the 65536 bytes indexed by the lower 16 bits of the
127 address. Each byte is represented by two bits (details are below). So
128 each second-level map contains 16384 bytes. This two-level arrangement
129 conveniently divides the 4G address space into 64k lumps, each size 64k
130 bytes.
131
132 All entries in the primary (top-level) map must point to a valid
133 secondary (second-level) map. Since many of the 64kB chunks will
njndbf7ca72006-03-31 11:57:59 +0000134 have the same status for every bit -- ie. noaccess (for unused
135 address space) or entirely addressable and defined (for code segments) --
136 there are three distinguished secondary maps, which indicate 'noaccess',
137 'undefined' and 'defined'. For these uniform 64kB chunks, the primary
138 map entry points to the relevant distinguished map. In practice,
139 typically more than half of the addressable memory is represented with
140 the 'undefined' or 'defined' distinguished secondary map, so it gives a
141 good saving. It also lets us set the V+A bits of large address regions
142 quickly in set_address_range_perms().
njn1d0825f2006-03-27 11:37:07 +0000143
144 On 64-bit machines it's more complicated. If we followed the same basic
145 scheme we'd have a four-level table which would require too many memory
philippe6e468f42014-09-22 19:46:48 +0000146 accesses. So instead the top-level map table has 2^20 entries (indexed
147 using bits 16..35 of the address); this covers the bottom 64GB. Any
148 accesses above 64GB are handled with a slow, sparse auxiliary table.
njn1d0825f2006-03-27 11:37:07 +0000149 Valgrind's address space manager tries very hard to keep things below
philippe6e468f42014-09-22 19:46:48 +0000150 this 64GB barrier so that performance doesn't suffer too much.
njn1d0825f2006-03-27 11:37:07 +0000151
152 Note that this file has a lot of different functions for reading and
153 writing shadow memory. Only a couple are strictly necessary (eg.
154 get_vabits2 and set_vabits2), most are just specialised for specific
155 common cases to improve performance.
156
157 Aside: the V+A bits are less precise than they could be -- we have no way
158 of marking memory as read-only. It would be great if we could add an
159 extra state VA_BITSn_READONLY. But then we'd have 5 different states,
160 which requires 2.3 bits to hold, and there's no way to do that elegantly
161 -- we'd have to double up to 4 bits of metadata per byte, which doesn't
162 seem worth it.
163*/
sewardjc859fbf2005-04-22 21:10:28 +0000164
sewardj45d94cc2005-04-20 14:44:11 +0000165/* --------------- Basic configuration --------------- */
sewardj95448072004-11-22 20:19:51 +0000166
sewardj23eb2fd2005-04-22 16:29:19 +0000167/* Only change this. N_PRIMARY_MAP *must* be a power of 2. */
sewardj21f7ff42005-04-28 10:32:02 +0000168
sewardje4ccc012005-05-02 12:53:38 +0000169#if VG_WORDSIZE == 4
sewardj21f7ff42005-04-28 10:32:02 +0000170
171/* cover the entire address space */
172# define N_PRIMARY_BITS 16
173
174#else
175
sewardj6805a4a2013-01-29 21:14:46 +0000176/* Just handle the first 64G fast and the rest via auxiliary
sewardj7244e712008-05-02 12:35:48 +0000177 primaries. If you change this, Memcheck will assert at startup.
178 See the definition of UNALIGNED_OR_HIGH for extensive comments. */
sewardj6805a4a2013-01-29 21:14:46 +0000179# define N_PRIMARY_BITS 20
sewardj21f7ff42005-04-28 10:32:02 +0000180
181#endif
182
sewardj45d94cc2005-04-20 14:44:11 +0000183
sewardjc1a2cda2005-04-21 17:34:00 +0000184/* Do not change this. */
sewardje4ccc012005-05-02 12:53:38 +0000185#define N_PRIMARY_MAP ( ((UWord)1) << N_PRIMARY_BITS)
sewardjc1a2cda2005-04-21 17:34:00 +0000186
187/* Do not change this. */
sewardj23eb2fd2005-04-22 16:29:19 +0000188#define MAX_PRIMARY_ADDRESS (Addr)((((Addr)65536) * N_PRIMARY_MAP)-1)
189
190
sewardj45d94cc2005-04-20 14:44:11 +0000191/* --------------- Secondary maps --------------- */
njn25e49d8e72002-09-23 09:36:25 +0000192
njn1d0825f2006-03-27 11:37:07 +0000193// Each byte of memory conceptually has an A bit, which indicates its
194// addressability, and 8 V bits, which indicates its definedness.
195//
196// But because very few bytes are partially defined, we can use a nice
197// compression scheme to reduce the size of shadow memory. Each byte of
198// memory has 2 bits which indicates its state (ie. V+A bits):
199//
njndbf7ca72006-03-31 11:57:59 +0000200// 00: noaccess (unaddressable but treated as fully defined)
201// 01: undefined (addressable and fully undefined)
202// 10: defined (addressable and fully defined)
203// 11: partdefined (addressable and partially defined)
njn1d0825f2006-03-27 11:37:07 +0000204//
njndbf7ca72006-03-31 11:57:59 +0000205// In the "partdefined" case, we use a secondary table to store the V bits.
206// Each entry in the secondary-V-bits table maps a byte address to its 8 V
207// bits.
njn1d0825f2006-03-27 11:37:07 +0000208//
209// We store the compressed V+A bits in 8-bit chunks, ie. the V+A bits for
210// four bytes (32 bits) of memory are in each chunk. Hence the name
211// "vabits8". This lets us get the V+A bits for four bytes at a time
212// easily (without having to do any shifting and/or masking), and that is a
213// very common operation. (Note that although each vabits8 chunk
214// is 8 bits in size, it represents 32 bits of memory.)
215//
216// The representation is "inverse" little-endian... each 4 bytes of
217// memory is represented by a 1 byte value, where:
218//
219// - the status of byte (a+0) is held in bits [1..0]
220// - the status of byte (a+1) is held in bits [3..2]
221// - the status of byte (a+2) is held in bits [5..4]
222// - the status of byte (a+3) is held in bits [7..6]
223//
224// It's "inverse" because endianness normally describes a mapping from
225// value bits to memory addresses; in this case the mapping is inverted.
226// Ie. instead of particular value bits being held in certain addresses, in
227// this case certain addresses are represented by particular value bits.
228// See insert_vabits2_into_vabits8() for an example.
229//
230// But note that we don't compress the V bits stored in registers; they
231// need to be explicit to made the shadow operations possible. Therefore
232// when moving values between registers and memory we need to convert
233// between the expanded in-register format and the compressed in-memory
234// format. This isn't so difficult, it just requires careful attention in a
235// few places.
236
237// These represent eight bits of memory.
238#define VA_BITS2_NOACCESS 0x0 // 00b
njndbf7ca72006-03-31 11:57:59 +0000239#define VA_BITS2_UNDEFINED 0x1 // 01b
240#define VA_BITS2_DEFINED 0x2 // 10b
241#define VA_BITS2_PARTDEFINED 0x3 // 11b
njn1d0825f2006-03-27 11:37:07 +0000242
243// These represent 16 bits of memory.
244#define VA_BITS4_NOACCESS 0x0 // 00_00b
njndbf7ca72006-03-31 11:57:59 +0000245#define VA_BITS4_UNDEFINED 0x5 // 01_01b
246#define VA_BITS4_DEFINED 0xa // 10_10b
njn1d0825f2006-03-27 11:37:07 +0000247
248// These represent 32 bits of memory.
249#define VA_BITS8_NOACCESS 0x00 // 00_00_00_00b
njndbf7ca72006-03-31 11:57:59 +0000250#define VA_BITS8_UNDEFINED 0x55 // 01_01_01_01b
251#define VA_BITS8_DEFINED 0xaa // 10_10_10_10b
njn1d0825f2006-03-27 11:37:07 +0000252
253// These represent 64 bits of memory.
254#define VA_BITS16_NOACCESS 0x0000 // 00_00_00_00b x 2
njndbf7ca72006-03-31 11:57:59 +0000255#define VA_BITS16_UNDEFINED 0x5555 // 01_01_01_01b x 2
256#define VA_BITS16_DEFINED 0xaaaa // 10_10_10_10b x 2
njn1d0825f2006-03-27 11:37:07 +0000257
Elliott Hughesa0664b92017-04-18 17:46:52 -0700258// These represent 128 bits of memory.
259#define VA_BITS32_UNDEFINED 0x55555555 // 01_01_01_01b x 4
260
njn1d0825f2006-03-27 11:37:07 +0000261
sewardj7b1f9eb2015-06-05 13:33:46 +0000262#define SM_CHUNKS 16384 // Each SM covers 64k of memory.
njn1d0825f2006-03-27 11:37:07 +0000263#define SM_OFF(aaa) (((aaa) & 0xffff) >> 2)
264#define SM_OFF_16(aaa) (((aaa) & 0xffff) >> 3)
265
266// Paranoia: it's critical for performance that the requested inlining
267// occurs. So try extra hard.
268#define INLINE inline __attribute__((always_inline))
269
270static INLINE Addr start_of_this_sm ( Addr a ) {
271 return (a & (~SM_MASK));
272}
273static INLINE Bool is_start_of_sm ( Addr a ) {
274 return (start_of_this_sm(a) == a);
275}
276
njn25e49d8e72002-09-23 09:36:25 +0000277typedef
278 struct {
njn1d0825f2006-03-27 11:37:07 +0000279 UChar vabits8[SM_CHUNKS];
njn25e49d8e72002-09-23 09:36:25 +0000280 }
281 SecMap;
282
njn1d0825f2006-03-27 11:37:07 +0000283// 3 distinguished secondary maps, one for no-access, one for
284// accessible but undefined, and one for accessible and defined.
285// Distinguished secondaries may never be modified.
286#define SM_DIST_NOACCESS 0
njndbf7ca72006-03-31 11:57:59 +0000287#define SM_DIST_UNDEFINED 1
288#define SM_DIST_DEFINED 2
njnb8dca862005-03-14 02:42:44 +0000289
sewardj45d94cc2005-04-20 14:44:11 +0000290static SecMap sm_distinguished[3];
njnb8dca862005-03-14 02:42:44 +0000291
njn1d0825f2006-03-27 11:37:07 +0000292static INLINE Bool is_distinguished_sm ( SecMap* sm ) {
sewardj45d94cc2005-04-20 14:44:11 +0000293 return sm >= &sm_distinguished[0] && sm <= &sm_distinguished[2];
294}
njnb8dca862005-03-14 02:42:44 +0000295
njn1d0825f2006-03-27 11:37:07 +0000296// Forward declaration
297static void update_SM_counts(SecMap* oldSM, SecMap* newSM);
298
sewardj45d94cc2005-04-20 14:44:11 +0000299/* dist_sm points to one of our three distinguished secondaries. Make
300 a copy of it so that we can write to it.
301*/
302static SecMap* copy_for_writing ( SecMap* dist_sm )
303{
304 SecMap* new_sm;
305 tl_assert(dist_sm == &sm_distinguished[0]
njn1d0825f2006-03-27 11:37:07 +0000306 || dist_sm == &sm_distinguished[1]
307 || dist_sm == &sm_distinguished[2]);
njnb8dca862005-03-14 02:42:44 +0000308
sewardj45f4e7c2005-09-27 19:20:21 +0000309 new_sm = VG_(am_shadow_alloc)(sizeof(SecMap));
310 if (new_sm == NULL)
311 VG_(out_of_memory_NORETURN)( "memcheck:allocate new SecMap",
312 sizeof(SecMap) );
sewardj45d94cc2005-04-20 14:44:11 +0000313 VG_(memcpy)(new_sm, dist_sm, sizeof(SecMap));
njn1d0825f2006-03-27 11:37:07 +0000314 update_SM_counts(dist_sm, new_sm);
sewardj45d94cc2005-04-20 14:44:11 +0000315 return new_sm;
316}
njnb8dca862005-03-14 02:42:44 +0000317
njn1d0825f2006-03-27 11:37:07 +0000318/* --------------- Stats --------------- */
319
njndbf7ca72006-03-31 11:57:59 +0000320static Int n_issued_SMs = 0;
321static Int n_deissued_SMs = 0;
322static Int n_noaccess_SMs = N_PRIMARY_MAP; // start with many noaccess DSMs
323static Int n_undefined_SMs = 0;
324static Int n_defined_SMs = 0;
325static Int n_non_DSM_SMs = 0;
326static Int max_noaccess_SMs = 0;
327static Int max_undefined_SMs = 0;
328static Int max_defined_SMs = 0;
329static Int max_non_DSM_SMs = 0;
njn1d0825f2006-03-27 11:37:07 +0000330
sewardj05a46732006-10-17 01:28:10 +0000331/* # searches initiated in auxmap_L1, and # base cmps required */
332static ULong n_auxmap_L1_searches = 0;
333static ULong n_auxmap_L1_cmps = 0;
334/* # of searches that missed in auxmap_L1 and therefore had to
335 be handed to auxmap_L2. And the number of nodes inserted. */
336static ULong n_auxmap_L2_searches = 0;
337static ULong n_auxmap_L2_nodes = 0;
338
njn1d0825f2006-03-27 11:37:07 +0000339static Int n_sanity_cheap = 0;
340static Int n_sanity_expensive = 0;
341
342static Int n_secVBit_nodes = 0;
343static Int max_secVBit_nodes = 0;
344
345static void update_SM_counts(SecMap* oldSM, SecMap* newSM)
346{
njndbf7ca72006-03-31 11:57:59 +0000347 if (oldSM == &sm_distinguished[SM_DIST_NOACCESS ]) n_noaccess_SMs --;
348 else if (oldSM == &sm_distinguished[SM_DIST_UNDEFINED]) n_undefined_SMs--;
349 else if (oldSM == &sm_distinguished[SM_DIST_DEFINED ]) n_defined_SMs --;
350 else { n_non_DSM_SMs --;
351 n_deissued_SMs ++; }
njn1d0825f2006-03-27 11:37:07 +0000352
njndbf7ca72006-03-31 11:57:59 +0000353 if (newSM == &sm_distinguished[SM_DIST_NOACCESS ]) n_noaccess_SMs ++;
354 else if (newSM == &sm_distinguished[SM_DIST_UNDEFINED]) n_undefined_SMs++;
355 else if (newSM == &sm_distinguished[SM_DIST_DEFINED ]) n_defined_SMs ++;
356 else { n_non_DSM_SMs ++;
357 n_issued_SMs ++; }
njn1d0825f2006-03-27 11:37:07 +0000358
njndbf7ca72006-03-31 11:57:59 +0000359 if (n_noaccess_SMs > max_noaccess_SMs ) max_noaccess_SMs = n_noaccess_SMs;
360 if (n_undefined_SMs > max_undefined_SMs) max_undefined_SMs = n_undefined_SMs;
361 if (n_defined_SMs > max_defined_SMs ) max_defined_SMs = n_defined_SMs;
362 if (n_non_DSM_SMs > max_non_DSM_SMs ) max_non_DSM_SMs = n_non_DSM_SMs;
njn1d0825f2006-03-27 11:37:07 +0000363}
sewardj45d94cc2005-04-20 14:44:11 +0000364
365/* --------------- Primary maps --------------- */
366
367/* The main primary map. This covers some initial part of the address
sewardj23eb2fd2005-04-22 16:29:19 +0000368 space, addresses 0 .. (N_PRIMARY_MAP << 16)-1. The rest of it is
sewardj45d94cc2005-04-20 14:44:11 +0000369 handled using the auxiliary primary map.
370*/
sewardj23eb2fd2005-04-22 16:29:19 +0000371static SecMap* primary_map[N_PRIMARY_MAP];
sewardj45d94cc2005-04-20 14:44:11 +0000372
373
374/* An entry in the auxiliary primary map. base must be a 64k-aligned
375 value, and sm points at the relevant secondary map. As with the
376 main primary map, the secondary may be either a real secondary, or
sewardj05a46732006-10-17 01:28:10 +0000377 one of the three distinguished secondaries. DO NOT CHANGE THIS
378 LAYOUT: the first word has to be the key for OSet fast lookups.
sewardj45d94cc2005-04-20 14:44:11 +0000379*/
380typedef
381 struct {
sewardj23eb2fd2005-04-22 16:29:19 +0000382 Addr base;
sewardj45d94cc2005-04-20 14:44:11 +0000383 SecMap* sm;
384 }
385 AuxMapEnt;
386
sewardj05a46732006-10-17 01:28:10 +0000387/* Tunable parameter: How big is the L1 queue? */
388#define N_AUXMAP_L1 24
sewardj45d94cc2005-04-20 14:44:11 +0000389
sewardj05a46732006-10-17 01:28:10 +0000390/* Tunable parameter: How far along the L1 queue to insert
391 entries resulting from L2 lookups? */
392#define AUXMAP_L1_INSERT_IX 12
sewardj45d94cc2005-04-20 14:44:11 +0000393
sewardj05a46732006-10-17 01:28:10 +0000394static struct {
395 Addr base;
396 AuxMapEnt* ent; // pointer to the matching auxmap_L2 node
397 }
398 auxmap_L1[N_AUXMAP_L1];
399
400static OSet* auxmap_L2 = NULL;
401
402static void init_auxmap_L1_L2 ( void )
sewardj45d94cc2005-04-20 14:44:11 +0000403{
sewardj05a46732006-10-17 01:28:10 +0000404 Int i;
405 for (i = 0; i < N_AUXMAP_L1; i++) {
406 auxmap_L1[i].base = 0;
407 auxmap_L1[i].ent = NULL;
sewardj45d94cc2005-04-20 14:44:11 +0000408 }
409
sewardj05a46732006-10-17 01:28:10 +0000410 tl_assert(0 == offsetof(AuxMapEnt,base));
411 tl_assert(sizeof(Addr) == sizeof(void*));
njne2a9ad32007-09-17 05:30:48 +0000412 auxmap_L2 = VG_(OSetGen_Create)( /*keyOff*/ offsetof(AuxMapEnt,base),
413 /*fastCmp*/ NULL,
sewardj9c606bd2008-09-18 18:12:50 +0000414 VG_(malloc), "mc.iaLL.1", VG_(free) );
sewardj05fe85e2005-04-27 22:46:36 +0000415}
416
sewardj05a46732006-10-17 01:28:10 +0000417/* Check representation invariants; if OK return NULL; else a
418 descriptive bit of text. Also return the number of
419 non-distinguished secondary maps referred to from the auxiliary
420 primary maps. */
sewardj05fe85e2005-04-27 22:46:36 +0000421
florian19f91bb2012-11-10 22:29:54 +0000422static const HChar* check_auxmap_L1_L2_sanity ( Word* n_secmaps_found )
sewardj05fe85e2005-04-27 22:46:36 +0000423{
sewardj05a46732006-10-17 01:28:10 +0000424 Word i, j;
425 /* On a 32-bit platform, the L2 and L1 tables should
426 both remain empty forever.
sewardj05fe85e2005-04-27 22:46:36 +0000427
sewardj05a46732006-10-17 01:28:10 +0000428 On a 64-bit platform:
429 In the L2 table:
430 all .base & 0xFFFF == 0
431 all .base > MAX_PRIMARY_ADDRESS
432 In the L1 table:
433 all .base & 0xFFFF == 0
434 all (.base > MAX_PRIMARY_ADDRESS
435 .base & 0xFFFF == 0
436 and .ent points to an AuxMapEnt with the same .base)
437 or
438 (.base == 0 and .ent == NULL)
439 */
440 *n_secmaps_found = 0;
441 if (sizeof(void*) == 4) {
442 /* 32-bit platform */
njne2a9ad32007-09-17 05:30:48 +0000443 if (VG_(OSetGen_Size)(auxmap_L2) != 0)
sewardj05a46732006-10-17 01:28:10 +0000444 return "32-bit: auxmap_L2 is non-empty";
445 for (i = 0; i < N_AUXMAP_L1; i++)
446 if (auxmap_L1[i].base != 0 || auxmap_L1[i].ent != NULL)
447 return "32-bit: auxmap_L1 is non-empty";
448 } else {
449 /* 64-bit platform */
450 UWord elems_seen = 0;
451 AuxMapEnt *elem, *res;
452 AuxMapEnt key;
453 /* L2 table */
njne2a9ad32007-09-17 05:30:48 +0000454 VG_(OSetGen_ResetIter)(auxmap_L2);
455 while ( (elem = VG_(OSetGen_Next)(auxmap_L2)) ) {
sewardj05a46732006-10-17 01:28:10 +0000456 elems_seen++;
457 if (0 != (elem->base & (Addr)0xFFFF))
458 return "64-bit: nonzero .base & 0xFFFF in auxmap_L2";
459 if (elem->base <= MAX_PRIMARY_ADDRESS)
460 return "64-bit: .base <= MAX_PRIMARY_ADDRESS in auxmap_L2";
461 if (elem->sm == NULL)
462 return "64-bit: .sm in _L2 is NULL";
463 if (!is_distinguished_sm(elem->sm))
464 (*n_secmaps_found)++;
465 }
466 if (elems_seen != n_auxmap_L2_nodes)
467 return "64-bit: disagreement on number of elems in _L2";
468 /* Check L1-L2 correspondence */
469 for (i = 0; i < N_AUXMAP_L1; i++) {
470 if (auxmap_L1[i].base == 0 && auxmap_L1[i].ent == NULL)
471 continue;
472 if (0 != (auxmap_L1[i].base & (Addr)0xFFFF))
473 return "64-bit: nonzero .base & 0xFFFF in auxmap_L1";
474 if (auxmap_L1[i].base <= MAX_PRIMARY_ADDRESS)
475 return "64-bit: .base <= MAX_PRIMARY_ADDRESS in auxmap_L1";
476 if (auxmap_L1[i].ent == NULL)
477 return "64-bit: .ent is NULL in auxmap_L1";
478 if (auxmap_L1[i].ent->base != auxmap_L1[i].base)
479 return "64-bit: _L1 and _L2 bases are inconsistent";
480 /* Look it up in auxmap_L2. */
481 key.base = auxmap_L1[i].base;
482 key.sm = 0;
njne2a9ad32007-09-17 05:30:48 +0000483 res = VG_(OSetGen_Lookup)(auxmap_L2, &key);
sewardj05a46732006-10-17 01:28:10 +0000484 if (res == NULL)
485 return "64-bit: _L1 .base not found in _L2";
486 if (res != auxmap_L1[i].ent)
487 return "64-bit: _L1 .ent disagrees with _L2 entry";
488 }
489 /* Check L1 contains no duplicates */
490 for (i = 0; i < N_AUXMAP_L1; i++) {
491 if (auxmap_L1[i].base == 0)
492 continue;
493 for (j = i+1; j < N_AUXMAP_L1; j++) {
494 if (auxmap_L1[j].base == 0)
495 continue;
496 if (auxmap_L1[j].base == auxmap_L1[i].base)
497 return "64-bit: duplicate _L1 .base entries";
498 }
499 }
500 }
501 return NULL; /* ok */
502}
503
504static void insert_into_auxmap_L1_at ( Word rank, AuxMapEnt* ent )
505{
506 Word i;
507 tl_assert(ent);
508 tl_assert(rank >= 0 && rank < N_AUXMAP_L1);
509 for (i = N_AUXMAP_L1-1; i > rank; i--)
510 auxmap_L1[i] = auxmap_L1[i-1];
511 auxmap_L1[rank].base = ent->base;
512 auxmap_L1[rank].ent = ent;
513}
514
515static INLINE AuxMapEnt* maybe_find_in_auxmap ( Addr a )
516{
517 AuxMapEnt key;
518 AuxMapEnt* res;
519 Word i;
520
521 tl_assert(a > MAX_PRIMARY_ADDRESS);
522 a &= ~(Addr)0xFFFF;
523
524 /* First search the front-cache, which is a self-organising
525 list containing the most popular entries. */
526
bart5dd8e6a2008-03-22 08:04:29 +0000527 if (LIKELY(auxmap_L1[0].base == a))
sewardj05a46732006-10-17 01:28:10 +0000528 return auxmap_L1[0].ent;
bart5dd8e6a2008-03-22 08:04:29 +0000529 if (LIKELY(auxmap_L1[1].base == a)) {
sewardj05a46732006-10-17 01:28:10 +0000530 Addr t_base = auxmap_L1[0].base;
531 AuxMapEnt* t_ent = auxmap_L1[0].ent;
532 auxmap_L1[0].base = auxmap_L1[1].base;
533 auxmap_L1[0].ent = auxmap_L1[1].ent;
534 auxmap_L1[1].base = t_base;
535 auxmap_L1[1].ent = t_ent;
536 return auxmap_L1[0].ent;
sewardj45d94cc2005-04-20 14:44:11 +0000537 }
538
sewardj05a46732006-10-17 01:28:10 +0000539 n_auxmap_L1_searches++;
sewardj45d94cc2005-04-20 14:44:11 +0000540
sewardj05a46732006-10-17 01:28:10 +0000541 for (i = 0; i < N_AUXMAP_L1; i++) {
542 if (auxmap_L1[i].base == a) {
543 break;
544 }
545 }
546 tl_assert(i >= 0 && i <= N_AUXMAP_L1);
sewardj45d94cc2005-04-20 14:44:11 +0000547
sewardj05a46732006-10-17 01:28:10 +0000548 n_auxmap_L1_cmps += (ULong)(i+1);
sewardj45d94cc2005-04-20 14:44:11 +0000549
sewardj05a46732006-10-17 01:28:10 +0000550 if (i < N_AUXMAP_L1) {
551 if (i > 0) {
552 Addr t_base = auxmap_L1[i-1].base;
553 AuxMapEnt* t_ent = auxmap_L1[i-1].ent;
554 auxmap_L1[i-1].base = auxmap_L1[i-0].base;
555 auxmap_L1[i-1].ent = auxmap_L1[i-0].ent;
556 auxmap_L1[i-0].base = t_base;
557 auxmap_L1[i-0].ent = t_ent;
558 i--;
559 }
560 return auxmap_L1[i].ent;
561 }
562
563 n_auxmap_L2_searches++;
564
565 /* First see if we already have it. */
566 key.base = a;
567 key.sm = 0;
568
njne2a9ad32007-09-17 05:30:48 +0000569 res = VG_(OSetGen_Lookup)(auxmap_L2, &key);
sewardj05a46732006-10-17 01:28:10 +0000570 if (res)
571 insert_into_auxmap_L1_at( AUXMAP_L1_INSERT_IX, res );
572 return res;
573}
574
575static AuxMapEnt* find_or_alloc_in_auxmap ( Addr a )
576{
577 AuxMapEnt *nyu, *res;
578
579 /* First see if we already have it. */
580 res = maybe_find_in_auxmap( a );
bart5dd8e6a2008-03-22 08:04:29 +0000581 if (LIKELY(res))
sewardj05a46732006-10-17 01:28:10 +0000582 return res;
583
584 /* Ok, there's no entry in the secondary map, so we'll have
585 to allocate one. */
586 a &= ~(Addr)0xFFFF;
587
njne2a9ad32007-09-17 05:30:48 +0000588 nyu = (AuxMapEnt*) VG_(OSetGen_AllocNode)( auxmap_L2, sizeof(AuxMapEnt) );
sewardj05a46732006-10-17 01:28:10 +0000589 nyu->base = a;
590 nyu->sm = &sm_distinguished[SM_DIST_NOACCESS];
njne2a9ad32007-09-17 05:30:48 +0000591 VG_(OSetGen_Insert)( auxmap_L2, nyu );
sewardj05a46732006-10-17 01:28:10 +0000592 insert_into_auxmap_L1_at( AUXMAP_L1_INSERT_IX, nyu );
593 n_auxmap_L2_nodes++;
594 return nyu;
sewardj45d94cc2005-04-20 14:44:11 +0000595}
596
sewardj45d94cc2005-04-20 14:44:11 +0000597/* --------------- SecMap fundamentals --------------- */
598
njn1d0825f2006-03-27 11:37:07 +0000599// In all these, 'low' means it's definitely in the main primary map,
600// 'high' means it's definitely in the auxiliary table.
601
Elliott Hughesa0664b92017-04-18 17:46:52 -0700602static INLINE UWord get_primary_map_low_offset ( Addr a )
603{
604 UWord pm_off = a >> 16;
605 return pm_off;
606}
607
njn1d0825f2006-03-27 11:37:07 +0000608static INLINE SecMap** get_secmap_low_ptr ( Addr a )
609{
610 UWord pm_off = a >> 16;
611# if VG_DEBUG_MEMORY >= 1
612 tl_assert(pm_off < N_PRIMARY_MAP);
613# endif
614 return &primary_map[ pm_off ];
615}
616
617static INLINE SecMap** get_secmap_high_ptr ( Addr a )
618{
619 AuxMapEnt* am = find_or_alloc_in_auxmap(a);
620 return &am->sm;
621}
622
philippeb8ac5ac2014-04-22 22:07:01 +0000623static INLINE SecMap** get_secmap_ptr ( Addr a )
njn1d0825f2006-03-27 11:37:07 +0000624{
625 return ( a <= MAX_PRIMARY_ADDRESS
626 ? get_secmap_low_ptr(a)
627 : get_secmap_high_ptr(a));
628}
629
njna7c7ebd2006-03-28 12:51:02 +0000630static INLINE SecMap* get_secmap_for_reading_low ( Addr a )
njn1d0825f2006-03-27 11:37:07 +0000631{
632 return *get_secmap_low_ptr(a);
633}
634
njna7c7ebd2006-03-28 12:51:02 +0000635static INLINE SecMap* get_secmap_for_reading_high ( Addr a )
njn1d0825f2006-03-27 11:37:07 +0000636{
637 return *get_secmap_high_ptr(a);
638}
639
njna7c7ebd2006-03-28 12:51:02 +0000640static INLINE SecMap* get_secmap_for_writing_low(Addr a)
njn1d0825f2006-03-27 11:37:07 +0000641{
642 SecMap** p = get_secmap_low_ptr(a);
bart5dd8e6a2008-03-22 08:04:29 +0000643 if (UNLIKELY(is_distinguished_sm(*p)))
njn1d0825f2006-03-27 11:37:07 +0000644 *p = copy_for_writing(*p);
645 return *p;
646}
647
njna7c7ebd2006-03-28 12:51:02 +0000648static INLINE SecMap* get_secmap_for_writing_high ( Addr a )
njn1d0825f2006-03-27 11:37:07 +0000649{
650 SecMap** p = get_secmap_high_ptr(a);
bart5dd8e6a2008-03-22 08:04:29 +0000651 if (UNLIKELY(is_distinguished_sm(*p)))
njn1d0825f2006-03-27 11:37:07 +0000652 *p = copy_for_writing(*p);
653 return *p;
654}
655
sewardj45d94cc2005-04-20 14:44:11 +0000656/* Produce the secmap for 'a', either from the primary map or by
657 ensuring there is an entry for it in the aux primary map. The
658 secmap may be a distinguished one as the caller will only want to
659 be able to read it.
660*/
sewardj05a46732006-10-17 01:28:10 +0000661static INLINE SecMap* get_secmap_for_reading ( 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_reading_low (a)
665 : get_secmap_for_reading_high(a) );
sewardj45d94cc2005-04-20 14:44:11 +0000666}
667
668/* Produce the secmap for 'a', either from the primary map or by
669 ensuring there is an entry for it in the aux primary map. The
670 secmap may not be a distinguished one, since the caller will want
671 to be able to write it. If it is a distinguished secondary, make a
672 writable copy of it, install it, and return the copy instead. (COW
673 semantics).
674*/
philippeb8ac5ac2014-04-22 22:07:01 +0000675static INLINE SecMap* get_secmap_for_writing ( Addr a )
sewardj45d94cc2005-04-20 14:44:11 +0000676{
njn1d0825f2006-03-27 11:37:07 +0000677 return ( a <= MAX_PRIMARY_ADDRESS
njna7c7ebd2006-03-28 12:51:02 +0000678 ? get_secmap_for_writing_low (a)
679 : get_secmap_for_writing_high(a) );
njn1d0825f2006-03-27 11:37:07 +0000680}
681
682/* If 'a' has a SecMap, produce it. Else produce NULL. But don't
683 allocate one if one doesn't already exist. This is used by the
684 leak checker.
685*/
686static SecMap* maybe_get_secmap_for ( Addr a )
687{
sewardj45d94cc2005-04-20 14:44:11 +0000688 if (a <= MAX_PRIMARY_ADDRESS) {
njna7c7ebd2006-03-28 12:51:02 +0000689 return get_secmap_for_reading_low(a);
sewardj45d94cc2005-04-20 14:44:11 +0000690 } else {
njn1d0825f2006-03-27 11:37:07 +0000691 AuxMapEnt* am = maybe_find_in_auxmap(a);
692 return am ? am->sm : NULL;
sewardj45d94cc2005-04-20 14:44:11 +0000693 }
694}
695
njn1d0825f2006-03-27 11:37:07 +0000696/* --------------- Fundamental functions --------------- */
697
698static INLINE
699void insert_vabits2_into_vabits8 ( Addr a, UChar vabits2, UChar* vabits8 )
700{
701 UInt shift = (a & 3) << 1; // shift by 0, 2, 4, or 6
702 *vabits8 &= ~(0x3 << shift); // mask out the two old bits
703 *vabits8 |= (vabits2 << shift); // mask in the two new bits
704}
705
706static INLINE
707void insert_vabits4_into_vabits8 ( Addr a, UChar vabits4, UChar* vabits8 )
708{
709 UInt shift;
710 tl_assert(VG_IS_2_ALIGNED(a)); // Must be 2-aligned
711 shift = (a & 2) << 1; // shift by 0 or 4
712 *vabits8 &= ~(0xf << shift); // mask out the four old bits
713 *vabits8 |= (vabits4 << shift); // mask in the four new bits
714}
715
716static INLINE
717UChar extract_vabits2_from_vabits8 ( Addr a, UChar vabits8 )
718{
719 UInt shift = (a & 3) << 1; // shift by 0, 2, 4, or 6
720 vabits8 >>= shift; // shift the two bits to the bottom
721 return 0x3 & vabits8; // mask out the rest
722}
723
724static INLINE
725UChar extract_vabits4_from_vabits8 ( Addr a, UChar vabits8 )
726{
727 UInt shift;
728 tl_assert(VG_IS_2_ALIGNED(a)); // Must be 2-aligned
729 shift = (a & 2) << 1; // shift by 0 or 4
730 vabits8 >>= shift; // shift the four bits to the bottom
731 return 0xf & vabits8; // mask out the rest
732}
733
734// Note that these four are only used in slow cases. The fast cases do
735// clever things like combine the auxmap check (in
736// get_secmap_{read,writ}able) with alignment checks.
737
738// *** WARNING! ***
739// Any time this function is called, if it is possible that vabits2
njndbf7ca72006-03-31 11:57:59 +0000740// is equal to VA_BITS2_PARTDEFINED, then the corresponding entry in the
njn1d0825f2006-03-27 11:37:07 +0000741// sec-V-bits table must also be set!
742static INLINE
743void set_vabits2 ( Addr a, UChar vabits2 )
744{
njna7c7ebd2006-03-28 12:51:02 +0000745 SecMap* sm = get_secmap_for_writing(a);
njn1d0825f2006-03-27 11:37:07 +0000746 UWord sm_off = SM_OFF(a);
747 insert_vabits2_into_vabits8( a, vabits2, &(sm->vabits8[sm_off]) );
748}
749
750static INLINE
751UChar get_vabits2 ( Addr a )
752{
njna7c7ebd2006-03-28 12:51:02 +0000753 SecMap* sm = get_secmap_for_reading(a);
njn1d0825f2006-03-27 11:37:07 +0000754 UWord sm_off = SM_OFF(a);
755 UChar vabits8 = sm->vabits8[sm_off];
756 return extract_vabits2_from_vabits8(a, vabits8);
757}
758
sewardjf2184912006-05-03 22:13:57 +0000759// *** WARNING! ***
760// Any time this function is called, if it is possible that any of the
761// 4 2-bit fields in vabits8 are equal to VA_BITS2_PARTDEFINED, then the
762// corresponding entry(s) in the sec-V-bits table must also be set!
763static INLINE
764UChar get_vabits8_for_aligned_word32 ( Addr a )
765{
766 SecMap* sm = get_secmap_for_reading(a);
767 UWord sm_off = SM_OFF(a);
768 UChar vabits8 = sm->vabits8[sm_off];
769 return vabits8;
770}
771
772static INLINE
773void set_vabits8_for_aligned_word32 ( Addr a, UChar vabits8 )
774{
775 SecMap* sm = get_secmap_for_writing(a);
776 UWord sm_off = SM_OFF(a);
777 sm->vabits8[sm_off] = vabits8;
778}
779
780
njn1d0825f2006-03-27 11:37:07 +0000781// Forward declarations
782static UWord get_sec_vbits8(Addr a);
783static void set_sec_vbits8(Addr a, UWord vbits8);
784
785// Returns False if there was an addressability error.
786static INLINE
787Bool set_vbits8 ( Addr a, UChar vbits8 )
788{
789 Bool ok = True;
790 UChar vabits2 = get_vabits2(a);
791 if ( VA_BITS2_NOACCESS != vabits2 ) {
792 // Addressable. Convert in-register format to in-memory format.
793 // Also remove any existing sec V bit entry for the byte if no
794 // longer necessary.
njndbf7ca72006-03-31 11:57:59 +0000795 if ( V_BITS8_DEFINED == vbits8 ) { vabits2 = VA_BITS2_DEFINED; }
796 else if ( V_BITS8_UNDEFINED == vbits8 ) { vabits2 = VA_BITS2_UNDEFINED; }
797 else { vabits2 = VA_BITS2_PARTDEFINED;
njn1d0825f2006-03-27 11:37:07 +0000798 set_sec_vbits8(a, vbits8); }
799 set_vabits2(a, vabits2);
800
801 } else {
802 // Unaddressable! Do nothing -- when writing to unaddressable
803 // memory it acts as a black hole, and the V bits can never be seen
804 // again. So we don't have to write them at all.
805 ok = False;
806 }
807 return ok;
808}
809
810// Returns False if there was an addressability error. In that case, we put
811// all defined bits into vbits8.
812static INLINE
813Bool get_vbits8 ( Addr a, UChar* vbits8 )
814{
815 Bool ok = True;
816 UChar vabits2 = get_vabits2(a);
817
818 // Convert the in-memory format to in-register format.
njndbf7ca72006-03-31 11:57:59 +0000819 if ( VA_BITS2_DEFINED == vabits2 ) { *vbits8 = V_BITS8_DEFINED; }
820 else if ( VA_BITS2_UNDEFINED == vabits2 ) { *vbits8 = V_BITS8_UNDEFINED; }
821 else if ( VA_BITS2_NOACCESS == vabits2 ) {
njn1d0825f2006-03-27 11:37:07 +0000822 *vbits8 = V_BITS8_DEFINED; // Make V bits defined!
823 ok = False;
824 } else {
njndbf7ca72006-03-31 11:57:59 +0000825 tl_assert( VA_BITS2_PARTDEFINED == vabits2 );
njn1d0825f2006-03-27 11:37:07 +0000826 *vbits8 = get_sec_vbits8(a);
827 }
828 return ok;
829}
830
831
832/* --------------- Secondary V bit table ------------ */
833
834// This table holds the full V bit pattern for partially-defined bytes
njndbf7ca72006-03-31 11:57:59 +0000835// (PDBs) that are represented by VA_BITS2_PARTDEFINED in the main shadow
836// memory.
njn1d0825f2006-03-27 11:37:07 +0000837//
838// Note: the nodes in this table can become stale. Eg. if you write a PDB,
839// then overwrite the same address with a fully defined byte, the sec-V-bit
840// node will not necessarily be removed. This is because checking for
841// whether removal is necessary would slow down the fast paths.
842//
843// To avoid the stale nodes building up too much, we periodically (once the
844// table reaches a certain size) garbage collect (GC) the table by
sewardj8ce5c242012-02-14 12:11:47 +0000845// traversing it and evicting any nodes not having PDB.
njn1d0825f2006-03-27 11:37:07 +0000846// If more than a certain proportion of nodes survived, we increase the
847// table size so that GCs occur less often.
848//
njn1d0825f2006-03-27 11:37:07 +0000849// This policy is designed to avoid bad table bloat in the worst case where
850// a program creates huge numbers of stale PDBs -- we would get this bloat
851// if we had no GC -- while handling well the case where a node becomes
852// stale but shortly afterwards is rewritten with a PDB and so becomes
853// non-stale again (which happens quite often, eg. in perf/bz2). If we just
854// remove all stale nodes as soon as possible, we just end up re-adding a
855// lot of them in later again. The "sufficiently stale" approach avoids
856// this. (If a program has many live PDBs, performance will just suck,
857// there's no way around that.)
sewardj8ce5c242012-02-14 12:11:47 +0000858//
859// Further comments, JRS 14 Feb 2012. It turns out that the policy of
860// holding on to stale entries for 2 GCs before discarding them can lead
861// to massive space leaks. So we're changing to an arrangement where
862// lines are evicted as soon as they are observed to be stale during a
863// GC. This also has a side benefit of allowing the sufficiently_stale
864// field to be removed from the SecVBitNode struct, reducing its size by
865// 8 bytes, which is a substantial space saving considering that the
866// struct was previously 32 or so bytes, on a 64 bit target.
867//
868// In order to try and mitigate the problem that the "sufficiently stale"
869// heuristic was designed to avoid, the table size is allowed to drift
870// up ("DRIFTUP") slowly to 80000, even if the residency is low. This
871// means that nodes will exist in the table longer on average, and hopefully
872// will be deleted and re-added less frequently.
873//
874// The previous scaling up mechanism (now called STEPUP) is retained:
875// if residency exceeds 50%, the table is scaled up, although by a
876// factor sqrt(2) rather than 2 as before. This effectively doubles the
877// frequency of GCs when there are many PDBs at reduces the tendency of
878// stale PDBs to reside for long periods in the table.
njn1d0825f2006-03-27 11:37:07 +0000879
880static OSet* secVBitTable;
881
882// Stats
883static ULong sec_vbits_new_nodes = 0;
884static ULong sec_vbits_updates = 0;
885
886// This must be a power of two; this is checked in mc_pre_clo_init().
887// The size chosen here is a trade-off: if the nodes are bigger (ie. cover
888// a larger address range) they take more space but we can get multiple
889// partially-defined bytes in one if they are close to each other, reducing
890// the number of total nodes. In practice sometimes they are clustered (eg.
891// perf/bz2 repeatedly writes then reads more than 20,000 in a contiguous
892// row), but often not. So we choose something intermediate.
893#define BYTES_PER_SEC_VBIT_NODE 16
894
sewardj8ce5c242012-02-14 12:11:47 +0000895// We make the table bigger by a factor of STEPUP_GROWTH_FACTOR if
896// more than this many nodes survive a GC.
897#define STEPUP_SURVIVOR_PROPORTION 0.5
898#define STEPUP_GROWTH_FACTOR 1.414213562
njn1d0825f2006-03-27 11:37:07 +0000899
sewardj8ce5c242012-02-14 12:11:47 +0000900// If the above heuristic doesn't apply, then we may make the table
901// slightly bigger, by a factor of DRIFTUP_GROWTH_FACTOR, if more than
902// this many nodes survive a GC, _and_ the total table size does
903// not exceed a fixed limit. The numbers are somewhat arbitrary, but
904// work tolerably well on long Firefox runs. The scaleup ratio of 1.5%
905// effectively although gradually reduces residency and increases time
906// between GCs for programs with small numbers of PDBs. The 80000 limit
907// effectively limits the table size to around 2MB for programs with
908// small numbers of PDBs, whilst giving a reasonably long lifetime to
909// entries, to try and reduce the costs resulting from deleting and
910// re-adding of entries.
911#define DRIFTUP_SURVIVOR_PROPORTION 0.15
912#define DRIFTUP_GROWTH_FACTOR 1.015
913#define DRIFTUP_MAX_SIZE 80000
njn1d0825f2006-03-27 11:37:07 +0000914
njn1d0825f2006-03-27 11:37:07 +0000915// We GC the table when it gets this many nodes in it, ie. it's effectively
916// the table size. It can change.
sewardj8ce5c242012-02-14 12:11:47 +0000917static Int secVBitLimit = 1000;
njn1d0825f2006-03-27 11:37:07 +0000918
919// The number of GCs done, used to age sec-V-bit nodes for eviction.
920// Because it's unsigned, wrapping doesn't matter -- the right answer will
921// come out anyway.
922static UInt GCs_done = 0;
923
924typedef
925 struct {
926 Addr a;
927 UChar vbits8[BYTES_PER_SEC_VBIT_NODE];
njn1d0825f2006-03-27 11:37:07 +0000928 }
929 SecVBitNode;
930
931static OSet* createSecVBitTable(void)
932{
philippe6643e962012-01-17 21:16:30 +0000933 OSet* newSecVBitTable;
934 newSecVBitTable = VG_(OSetGen_Create_With_Pool)
935 ( offsetof(SecVBitNode, a),
936 NULL, // use fast comparisons
937 VG_(malloc), "mc.cSVT.1 (sec VBit table)",
938 VG_(free),
939 1000,
940 sizeof(SecVBitNode));
941 return newSecVBitTable;
njn1d0825f2006-03-27 11:37:07 +0000942}
943
944static void gcSecVBitTable(void)
945{
946 OSet* secVBitTable2;
947 SecVBitNode* n;
948 Int i, n_nodes = 0, n_survivors = 0;
949
950 GCs_done++;
951
952 // Create the new table.
953 secVBitTable2 = createSecVBitTable();
954
955 // Traverse the table, moving fresh nodes into the new table.
njne2a9ad32007-09-17 05:30:48 +0000956 VG_(OSetGen_ResetIter)(secVBitTable);
957 while ( (n = VG_(OSetGen_Next)(secVBitTable)) ) {
sewardj8ce5c242012-02-14 12:11:47 +0000958 // Keep node if any of its bytes are non-stale. Using
959 // get_vabits2() for the lookup is not very efficient, but I don't
960 // think it matters.
961 for (i = 0; i < BYTES_PER_SEC_VBIT_NODE; i++) {
962 if (VA_BITS2_PARTDEFINED == get_vabits2(n->a + i)) {
963 // Found a non-stale byte, so keep =>
964 // Insert a copy of the node into the new table.
965 SecVBitNode* n2 =
966 VG_(OSetGen_AllocNode)(secVBitTable2, sizeof(SecVBitNode));
967 *n2 = *n;
968 VG_(OSetGen_Insert)(secVBitTable2, n2);
969 break;
njn1d0825f2006-03-27 11:37:07 +0000970 }
971 }
njn1d0825f2006-03-27 11:37:07 +0000972 }
973
974 // Get the before and after sizes.
njne2a9ad32007-09-17 05:30:48 +0000975 n_nodes = VG_(OSetGen_Size)(secVBitTable);
976 n_survivors = VG_(OSetGen_Size)(secVBitTable2);
njn1d0825f2006-03-27 11:37:07 +0000977
978 // Destroy the old table, and put the new one in its place.
njne2a9ad32007-09-17 05:30:48 +0000979 VG_(OSetGen_Destroy)(secVBitTable);
njn1d0825f2006-03-27 11:37:07 +0000980 secVBitTable = secVBitTable2;
981
florian227a1ec2014-12-12 19:32:10 +0000982 if (VG_(clo_verbosity) > 1 && n_nodes != 0) {
983 VG_(message)(Vg_DebugMsg, "memcheck GC: %d nodes, %d survivors (%.1f%%)\n",
984 n_nodes, n_survivors, n_survivors * 100.0 / n_nodes);
njn1d0825f2006-03-27 11:37:07 +0000985 }
986
987 // Increase table size if necessary.
sewardj8ce5c242012-02-14 12:11:47 +0000988 if ((Double)n_survivors
989 > ((Double)secVBitLimit * STEPUP_SURVIVOR_PROPORTION)) {
990 secVBitLimit = (Int)((Double)secVBitLimit * (Double)STEPUP_GROWTH_FACTOR);
njn1d0825f2006-03-27 11:37:07 +0000991 if (VG_(clo_verbosity) > 1)
sewardj8ce5c242012-02-14 12:11:47 +0000992 VG_(message)(Vg_DebugMsg,
993 "memcheck GC: %d new table size (stepup)\n",
994 secVBitLimit);
995 }
996 else
997 if (secVBitLimit < DRIFTUP_MAX_SIZE
998 && (Double)n_survivors
999 > ((Double)secVBitLimit * DRIFTUP_SURVIVOR_PROPORTION)) {
1000 secVBitLimit = (Int)((Double)secVBitLimit * (Double)DRIFTUP_GROWTH_FACTOR);
1001 if (VG_(clo_verbosity) > 1)
1002 VG_(message)(Vg_DebugMsg,
1003 "memcheck GC: %d new table size (driftup)\n",
njn1d0825f2006-03-27 11:37:07 +00001004 secVBitLimit);
1005 }
1006}
1007
1008static UWord get_sec_vbits8(Addr a)
1009{
1010 Addr aAligned = VG_ROUNDDN(a, BYTES_PER_SEC_VBIT_NODE);
1011 Int amod = a % BYTES_PER_SEC_VBIT_NODE;
njne2a9ad32007-09-17 05:30:48 +00001012 SecVBitNode* n = VG_(OSetGen_Lookup)(secVBitTable, &aAligned);
njn1d0825f2006-03-27 11:37:07 +00001013 UChar vbits8;
1014 tl_assert2(n, "get_sec_vbits8: no node for address %p (%p)\n", aAligned, a);
1015 // Shouldn't be fully defined or fully undefined -- those cases shouldn't
1016 // make it to the secondary V bits table.
1017 vbits8 = n->vbits8[amod];
1018 tl_assert(V_BITS8_DEFINED != vbits8 && V_BITS8_UNDEFINED != vbits8);
1019 return vbits8;
1020}
1021
1022static void set_sec_vbits8(Addr a, UWord vbits8)
1023{
1024 Addr aAligned = VG_ROUNDDN(a, BYTES_PER_SEC_VBIT_NODE);
1025 Int i, amod = a % BYTES_PER_SEC_VBIT_NODE;
njne2a9ad32007-09-17 05:30:48 +00001026 SecVBitNode* n = VG_(OSetGen_Lookup)(secVBitTable, &aAligned);
njn1d0825f2006-03-27 11:37:07 +00001027 // Shouldn't be fully defined or fully undefined -- those cases shouldn't
1028 // make it to the secondary V bits table.
1029 tl_assert(V_BITS8_DEFINED != vbits8 && V_BITS8_UNDEFINED != vbits8);
1030 if (n) {
1031 n->vbits8[amod] = vbits8; // update
njn1d0825f2006-03-27 11:37:07 +00001032 sec_vbits_updates++;
1033 } else {
philippe6643e962012-01-17 21:16:30 +00001034 // Do a table GC if necessary. Nb: do this before creating and
1035 // inserting the new node, to avoid erroneously GC'ing the new node.
1036 if (secVBitLimit == VG_(OSetGen_Size)(secVBitTable)) {
1037 gcSecVBitTable();
1038 }
1039
njn1d0825f2006-03-27 11:37:07 +00001040 // New node: assign the specific byte, make the rest invalid (they
1041 // should never be read as-is, but be cautious).
njne2a9ad32007-09-17 05:30:48 +00001042 n = VG_(OSetGen_AllocNode)(secVBitTable, sizeof(SecVBitNode));
njn1d0825f2006-03-27 11:37:07 +00001043 n->a = aAligned;
1044 for (i = 0; i < BYTES_PER_SEC_VBIT_NODE; i++) {
1045 n->vbits8[i] = V_BITS8_UNDEFINED;
1046 }
1047 n->vbits8[amod] = vbits8;
njn1d0825f2006-03-27 11:37:07 +00001048
njn1d0825f2006-03-27 11:37:07 +00001049 // Insert the new node.
njne2a9ad32007-09-17 05:30:48 +00001050 VG_(OSetGen_Insert)(secVBitTable, n);
njn1d0825f2006-03-27 11:37:07 +00001051 sec_vbits_new_nodes++;
1052
njne2a9ad32007-09-17 05:30:48 +00001053 n_secVBit_nodes = VG_(OSetGen_Size)(secVBitTable);
njn1d0825f2006-03-27 11:37:07 +00001054 if (n_secVBit_nodes > max_secVBit_nodes)
1055 max_secVBit_nodes = n_secVBit_nodes;
1056 }
1057}
sewardj45d94cc2005-04-20 14:44:11 +00001058
1059/* --------------- Endianness helpers --------------- */
1060
1061/* Returns the offset in memory of the byteno-th most significant byte
1062 in a wordszB-sized word, given the specified endianness. */
njn1d0825f2006-03-27 11:37:07 +00001063static INLINE UWord byte_offset_w ( UWord wordszB, Bool bigendian,
sewardj45d94cc2005-04-20 14:44:11 +00001064 UWord byteno ) {
1065 return bigendian ? (wordszB-1-byteno) : byteno;
1066}
1067
sewardj05a46732006-10-17 01:28:10 +00001068
1069/* --------------- Ignored address ranges --------------- */
1070
sewardjc5fc8662014-03-20 23:00:09 +00001071/* Denotes the address-error-reportability status for address ranges:
1072 IAR_NotIgnored: the usual case -- report errors in this range
1073 IAR_CommandLine: don't report errors -- from command line setting
1074 IAR_ClientReq: don't report errors -- from client request
1075*/
sewardj05a46732006-10-17 01:28:10 +00001076typedef
sewardjc5fc8662014-03-20 23:00:09 +00001077 enum { IAR_INVALID=99,
1078 IAR_NotIgnored,
1079 IAR_CommandLine,
1080 IAR_ClientReq }
1081 IARKind;
sewardj05a46732006-10-17 01:28:10 +00001082
sewardjc5fc8662014-03-20 23:00:09 +00001083static const HChar* showIARKind ( IARKind iark )
1084{
1085 switch (iark) {
1086 case IAR_INVALID: return "INVALID";
1087 case IAR_NotIgnored: return "NotIgnored";
1088 case IAR_CommandLine: return "CommandLine";
1089 case IAR_ClientReq: return "ClientReq";
1090 default: return "???";
1091 }
1092}
1093
1094// RangeMap<IARKind>
1095static RangeMap* gIgnoredAddressRanges = NULL;
1096
1097static void init_gIgnoredAddressRanges ( void )
1098{
1099 if (LIKELY(gIgnoredAddressRanges != NULL))
1100 return;
1101 gIgnoredAddressRanges = VG_(newRangeMap)( VG_(malloc), "mc.igIAR.1",
1102 VG_(free), IAR_NotIgnored );
sewardjc5fc8662014-03-20 23:00:09 +00001103}
sewardj05a46732006-10-17 01:28:10 +00001104
florianccfddfb2014-10-13 21:00:00 +00001105Bool MC_(in_ignored_range) ( Addr a )
sewardj05a46732006-10-17 01:28:10 +00001106{
sewardjc5fc8662014-03-20 23:00:09 +00001107 if (LIKELY(gIgnoredAddressRanges == NULL))
sewardj05a46732006-10-17 01:28:10 +00001108 return False;
sewardjc5fc8662014-03-20 23:00:09 +00001109 UWord how = IAR_INVALID;
1110 UWord key_min = ~(UWord)0;
1111 UWord key_max = (UWord)0;
1112 VG_(lookupRangeMap)(&key_min, &key_max, &how, gIgnoredAddressRanges, a);
1113 tl_assert(key_min <= a && a <= key_max);
1114 switch (how) {
1115 case IAR_NotIgnored: return False;
1116 case IAR_CommandLine: return True;
1117 case IAR_ClientReq: return True;
1118 default: break; /* invalid */
sewardj05a46732006-10-17 01:28:10 +00001119 }
sewardjc5fc8662014-03-20 23:00:09 +00001120 VG_(tool_panic)("MC_(in_ignore_range)");
1121 /*NOTREACHED*/
sewardj05a46732006-10-17 01:28:10 +00001122}
1123
Elliott Hughesa0664b92017-04-18 17:46:52 -07001124Bool MC_(in_ignored_range_below_sp) ( Addr sp, Addr a, UInt szB )
1125{
1126 if (LIKELY(!MC_(clo_ignore_range_below_sp)))
1127 return False;
1128 tl_assert(szB >= 1 && szB <= 32);
1129 tl_assert(MC_(clo_ignore_range_below_sp__first_offset)
1130 > MC_(clo_ignore_range_below_sp__last_offset));
1131 Addr range_lo = sp - MC_(clo_ignore_range_below_sp__first_offset);
1132 Addr range_hi = sp - MC_(clo_ignore_range_below_sp__last_offset);
1133 if (range_lo >= range_hi) {
1134 /* Bizarre. We have a wraparound situation. What should we do? */
1135 return False; // Play safe
1136 } else {
1137 /* This is the expected case. */
1138 if (range_lo <= a && a + szB - 1 <= range_hi)
1139 return True;
1140 else
1141 return False;
1142 }
1143 /*NOTREACHED*/
1144 tl_assert(0);
1145}
sewardj05a46732006-10-17 01:28:10 +00001146
Elliott Hughesa0664b92017-04-18 17:46:52 -07001147/* Parse two Addrs (in hex) separated by a dash, or fail. */
1148
1149static Bool parse_Addr_pair ( const HChar** ppc, Addr* result1, Addr* result2 )
sewardj05a46732006-10-17 01:28:10 +00001150{
sewardj3b290482011-05-06 21:02:55 +00001151 Bool ok = VG_(parse_Addr) (ppc, result1);
sewardj05a46732006-10-17 01:28:10 +00001152 if (!ok)
1153 return False;
1154 if (**ppc != '-')
1155 return False;
1156 (*ppc)++;
sewardj3b290482011-05-06 21:02:55 +00001157 ok = VG_(parse_Addr) (ppc, result2);
sewardj05a46732006-10-17 01:28:10 +00001158 if (!ok)
1159 return False;
1160 return True;
1161}
1162
Elliott Hughesa0664b92017-04-18 17:46:52 -07001163/* Parse two UInts (32 bit unsigned, in decimal) separated by a dash,
1164 or fail. */
1165
1166static Bool parse_UInt_pair ( const HChar** ppc, UInt* result1, UInt* result2 )
1167{
1168 Bool ok = VG_(parse_UInt) (ppc, result1);
1169 if (!ok)
1170 return False;
1171 if (**ppc != '-')
1172 return False;
1173 (*ppc)++;
1174 ok = VG_(parse_UInt) (ppc, result2);
1175 if (!ok)
1176 return False;
1177 return True;
1178}
1179
sewardj05a46732006-10-17 01:28:10 +00001180/* Parse a set of ranges separated by commas into 'ignoreRanges', or
sewardjc5fc8662014-03-20 23:00:09 +00001181 fail. If they are valid, add them to the global set of ignored
1182 ranges. */
florian19f91bb2012-11-10 22:29:54 +00001183static Bool parse_ignore_ranges ( const HChar* str0 )
sewardj05a46732006-10-17 01:28:10 +00001184{
sewardjc5fc8662014-03-20 23:00:09 +00001185 init_gIgnoredAddressRanges();
florian19f91bb2012-11-10 22:29:54 +00001186 const HChar* str = str0;
1187 const HChar** ppc = &str;
sewardj05a46732006-10-17 01:28:10 +00001188 while (1) {
sewardjc5fc8662014-03-20 23:00:09 +00001189 Addr start = ~(Addr)0;
1190 Addr end = (Addr)0;
Elliott Hughesa0664b92017-04-18 17:46:52 -07001191 Bool ok = parse_Addr_pair(ppc, &start, &end);
sewardj05a46732006-10-17 01:28:10 +00001192 if (!ok)
1193 return False;
sewardjc5fc8662014-03-20 23:00:09 +00001194 if (start > end)
sewardj05a46732006-10-17 01:28:10 +00001195 return False;
sewardjc5fc8662014-03-20 23:00:09 +00001196 VG_(bindRangeMap)( gIgnoredAddressRanges, start, end, IAR_CommandLine );
sewardj05a46732006-10-17 01:28:10 +00001197 if (**ppc == 0)
1198 return True;
1199 if (**ppc != ',')
1200 return False;
1201 (*ppc)++;
1202 }
1203 /*NOTREACHED*/
1204 return False;
1205}
1206
sewardjc5fc8662014-03-20 23:00:09 +00001207/* Add or remove [start, +len) from the set of ignored ranges. */
1208static Bool modify_ignore_ranges ( Bool addRange, Addr start, Addr len )
1209{
1210 init_gIgnoredAddressRanges();
1211 const Bool verbose = (VG_(clo_verbosity) > 1);
1212 if (len == 0) {
1213 return False;
1214 }
1215 if (addRange) {
1216 VG_(bindRangeMap)(gIgnoredAddressRanges,
1217 start, start+len-1, IAR_ClientReq);
1218 if (verbose)
1219 VG_(dmsg)("memcheck: modify_ignore_ranges: add %p %p\n",
1220 (void*)start, (void*)(start+len-1));
1221 } else {
1222 VG_(bindRangeMap)(gIgnoredAddressRanges,
1223 start, start+len-1, IAR_NotIgnored);
1224 if (verbose)
1225 VG_(dmsg)("memcheck: modify_ignore_ranges: del %p %p\n",
1226 (void*)start, (void*)(start+len-1));
1227 }
1228 if (verbose) {
florianca631452015-08-05 13:23:11 +00001229 VG_(dmsg)("memcheck: now have %u ranges:\n",
sewardjc5fc8662014-03-20 23:00:09 +00001230 VG_(sizeRangeMap)(gIgnoredAddressRanges));
florianca631452015-08-05 13:23:11 +00001231 UInt i;
sewardjc5fc8662014-03-20 23:00:09 +00001232 for (i = 0; i < VG_(sizeRangeMap)(gIgnoredAddressRanges); i++) {
1233 UWord val = IAR_INVALID;
1234 UWord key_min = ~(UWord)0;
1235 UWord key_max = (UWord)0;
1236 VG_(indexRangeMap)( &key_min, &key_max, &val,
1237 gIgnoredAddressRanges, i );
florianca631452015-08-05 13:23:11 +00001238 VG_(dmsg)("memcheck: [%u] %016lx-%016lx %s\n",
1239 i, key_min, key_max, showIARKind(val));
sewardjc5fc8662014-03-20 23:00:09 +00001240 }
1241 }
1242 return True;
1243}
1244
sewardj05a46732006-10-17 01:28:10 +00001245
sewardj45d94cc2005-04-20 14:44:11 +00001246/* --------------- Load/store slow cases. --------------- */
1247
1248static
sewardj14a81782011-08-20 15:55:07 +00001249__attribute__((noinline))
sewardj92ef91b2013-08-18 10:20:22 +00001250void mc_LOADV_128_or_256_slow ( /*OUT*/ULong* res,
1251 Addr a, SizeT nBits, Bool bigendian )
sewardj21a5f8c2013-08-08 10:41:46 +00001252{
sewardj92ef91b2013-08-18 10:20:22 +00001253 ULong pessim[4]; /* only used when p-l-ok=yes */
sewardj67564542013-08-16 08:31:29 +00001254 SSizeT szB = nBits / 8;
sewardj92ef91b2013-08-18 10:20:22 +00001255 SSizeT szL = szB / 8; /* Size in Longs (64-bit units) */
sewardj21a5f8c2013-08-08 10:41:46 +00001256 SSizeT i, j; /* Must be signed. */
1257 SizeT n_addrs_bad = 0;
1258 Addr ai;
1259 UChar vbits8;
1260 Bool ok;
1261
sewardj67564542013-08-16 08:31:29 +00001262 /* Code below assumes load size is a power of two and at least 64
1263 bits. */
1264 tl_assert((szB & (szB-1)) == 0 && szL > 0);
sewardj21a5f8c2013-08-08 10:41:46 +00001265
sewardj67564542013-08-16 08:31:29 +00001266 /* If this triggers, you probably just need to increase the size of
1267 the pessim array. */
1268 tl_assert(szL <= sizeof(pessim) / sizeof(pessim[0]));
sewardj21a5f8c2013-08-08 10:41:46 +00001269
sewardj92ef91b2013-08-18 10:20:22 +00001270 for (j = 0; j < szL; j++) {
sewardj67564542013-08-16 08:31:29 +00001271 pessim[j] = V_BITS64_DEFINED;
1272 res[j] = V_BITS64_UNDEFINED;
1273 }
1274
1275 /* Make up a result V word, which contains the loaded data for
1276 valid addresses and Defined for invalid addresses. Iterate over
1277 the bytes in the word, from the most significant down to the
1278 least. The vbits to return are calculated into vbits128. Also
1279 compute the pessimising value to be used when
sewardj21a5f8c2013-08-08 10:41:46 +00001280 --partial-loads-ok=yes. n_addrs_bad is redundant (the relevant
sewardj67564542013-08-16 08:31:29 +00001281 info can be gleaned from the pessim array) but is used as a
sewardj21a5f8c2013-08-08 10:41:46 +00001282 cross-check. */
sewardj92ef91b2013-08-18 10:20:22 +00001283 for (j = szL-1; j >= 0; j--) {
1284 ULong vbits64 = V_BITS64_UNDEFINED;
1285 ULong pessim64 = V_BITS64_DEFINED;
1286 UWord long_index = byte_offset_w(szL, bigendian, j);
sewardj67564542013-08-16 08:31:29 +00001287 for (i = 8-1; i >= 0; i--) {
florian60042192015-08-04 15:58:41 +00001288 PROF_EVENT(MCPE_LOADV_128_OR_256_SLOW_LOOP);
sewardj67564542013-08-16 08:31:29 +00001289 ai = a + 8*long_index + byte_offset_w(8, bigendian, i);
sewardj21a5f8c2013-08-08 10:41:46 +00001290 ok = get_vbits8(ai, &vbits8);
1291 vbits64 <<= 8;
1292 vbits64 |= vbits8;
1293 if (!ok) n_addrs_bad++;
1294 pessim64 <<= 8;
1295 pessim64 |= (ok ? V_BITS8_DEFINED : V_BITS8_UNDEFINED);
1296 }
sewardj67564542013-08-16 08:31:29 +00001297 res[long_index] = vbits64;
1298 pessim[long_index] = pessim64;
sewardj21a5f8c2013-08-08 10:41:46 +00001299 }
1300
1301 /* In the common case, all the addresses involved are valid, so we
1302 just return the computed V bits and have done. */
sewardj67564542013-08-16 08:31:29 +00001303 if (LIKELY(n_addrs_bad == 0))
sewardj21a5f8c2013-08-08 10:41:46 +00001304 return;
sewardj21a5f8c2013-08-08 10:41:46 +00001305
1306 /* If there's no possibility of getting a partial-loads-ok
1307 exemption, report the error and quit. */
1308 if (!MC_(clo_partial_loads_ok)) {
1309 MC_(record_address_error)( VG_(get_running_tid)(), a, szB, False );
sewardj21a5f8c2013-08-08 10:41:46 +00001310 return;
1311 }
1312
1313 /* The partial-loads-ok excemption might apply. Find out if it
1314 does. If so, don't report an addressing error, but do return
1315 Undefined for the bytes that are out of range, so as to avoid
1316 false negatives. If it doesn't apply, just report an addressing
1317 error in the usual way. */
1318
sewardj67564542013-08-16 08:31:29 +00001319 /* Some code steps along byte strings in aligned chunks
sewardj21a5f8c2013-08-08 10:41:46 +00001320 even when there is only a partially defined word at the end (eg,
1321 optimised strlen). This is allowed by the memory model of
1322 modern machines, since an aligned load cannot span two pages and
1323 thus cannot "partially fault".
1324
1325 Therefore, a load from a partially-addressible place is allowed
1326 if all of the following hold:
1327 - the command-line flag is set [by default, it isn't]
1328 - it's an aligned load
1329 - at least one of the addresses in the word *is* valid
1330
1331 Since this suppresses the addressing error, we avoid false
1332 negatives by marking bytes undefined when they come from an
1333 invalid address.
1334 */
1335
1336 /* "at least one of the addresses is invalid" */
sewardj67564542013-08-16 08:31:29 +00001337 ok = False;
sewardj92ef91b2013-08-18 10:20:22 +00001338 for (j = 0; j < szL; j++)
sewardj1e4fc952014-08-22 19:07:12 +00001339 ok |= pessim[j] != V_BITS64_DEFINED;
sewardj67564542013-08-16 08:31:29 +00001340 tl_assert(ok);
sewardj21a5f8c2013-08-08 10:41:46 +00001341
1342 if (0 == (a & (szB - 1)) && n_addrs_bad < szB) {
1343 /* Exemption applies. Use the previously computed pessimising
sewardj67564542013-08-16 08:31:29 +00001344 value and return the combined result, but don't flag an
1345 addressing error. The pessimising value is Defined for valid
1346 addresses and Undefined for invalid addresses. */
sewardj21a5f8c2013-08-08 10:41:46 +00001347 /* for assumption that doing bitwise or implements UifU */
1348 tl_assert(V_BIT_UNDEFINED == 1 && V_BIT_DEFINED == 0);
1349 /* (really need "UifU" here...)
sewardj67564542013-08-16 08:31:29 +00001350 vbits[j] UifU= pessim[j] (is pessimised by it, iow) */
sewardj92ef91b2013-08-18 10:20:22 +00001351 for (j = szL-1; j >= 0; j--)
sewardj67564542013-08-16 08:31:29 +00001352 res[j] |= pessim[j];
sewardj21a5f8c2013-08-08 10:41:46 +00001353 return;
1354 }
1355
1356 /* Exemption doesn't apply. Flag an addressing error in the normal
1357 way. */
1358 MC_(record_address_error)( VG_(get_running_tid)(), a, szB, False );
sewardj21a5f8c2013-08-08 10:41:46 +00001359}
1360
1361
1362static
1363__attribute__((noinline))
sewardjb9437c52015-07-20 13:11:03 +00001364__attribute__((used))
sewardj7b1f9eb2015-06-05 13:33:46 +00001365VG_REGPARM(3) /* make sure we're using a fixed calling convention, since
1366 this function may get called from hand written assembly. */
njn45e81252006-03-28 12:35:08 +00001367ULong mc_LOADVn_slow ( Addr a, SizeT nBits, Bool bigendian )
sewardj45d94cc2005-04-20 14:44:11 +00001368{
florian60042192015-08-04 15:58:41 +00001369 PROF_EVENT(MCPE_LOADVN_SLOW);
sewardj05a46732006-10-17 01:28:10 +00001370
1371 /* ------------ BEGIN semi-fast cases ------------ */
1372 /* These deal quickly-ish with the common auxiliary primary map
1373 cases on 64-bit platforms. Are merely a speedup hack; can be
1374 omitted without loss of correctness/functionality. Note that in
1375 both cases the "sizeof(void*) == 8" causes these cases to be
1376 folded out by compilers on 32-bit platforms. These are derived
1377 from LOADV64 and LOADV32.
1378 */
bart5dd8e6a2008-03-22 08:04:29 +00001379 if (LIKELY(sizeof(void*) == 8
sewardj05a46732006-10-17 01:28:10 +00001380 && nBits == 64 && VG_IS_8_ALIGNED(a))) {
1381 SecMap* sm = get_secmap_for_reading(a);
1382 UWord sm_off16 = SM_OFF_16(a);
1383 UWord vabits16 = ((UShort*)(sm->vabits8))[sm_off16];
bart5dd8e6a2008-03-22 08:04:29 +00001384 if (LIKELY(vabits16 == VA_BITS16_DEFINED))
sewardj05a46732006-10-17 01:28:10 +00001385 return V_BITS64_DEFINED;
bart5dd8e6a2008-03-22 08:04:29 +00001386 if (LIKELY(vabits16 == VA_BITS16_UNDEFINED))
sewardj05a46732006-10-17 01:28:10 +00001387 return V_BITS64_UNDEFINED;
1388 /* else fall into the slow case */
1389 }
bart5dd8e6a2008-03-22 08:04:29 +00001390 if (LIKELY(sizeof(void*) == 8
sewardj05a46732006-10-17 01:28:10 +00001391 && nBits == 32 && VG_IS_4_ALIGNED(a))) {
1392 SecMap* sm = get_secmap_for_reading(a);
1393 UWord sm_off = SM_OFF(a);
1394 UWord vabits8 = sm->vabits8[sm_off];
bart5dd8e6a2008-03-22 08:04:29 +00001395 if (LIKELY(vabits8 == VA_BITS8_DEFINED))
sewardj05a46732006-10-17 01:28:10 +00001396 return ((UWord)0xFFFFFFFF00000000ULL | (UWord)V_BITS32_DEFINED);
bart5dd8e6a2008-03-22 08:04:29 +00001397 if (LIKELY(vabits8 == VA_BITS8_UNDEFINED))
sewardj05a46732006-10-17 01:28:10 +00001398 return ((UWord)0xFFFFFFFF00000000ULL | (UWord)V_BITS32_UNDEFINED);
1399 /* else fall into slow case */
1400 }
1401 /* ------------ END semi-fast cases ------------ */
1402
sewardjda04f3e2012-03-08 14:51:01 +00001403 ULong vbits64 = V_BITS64_UNDEFINED; /* result */
1404 ULong pessim64 = V_BITS64_DEFINED; /* only used when p-l-ok=yes */
1405 SSizeT szB = nBits / 8;
1406 SSizeT i; /* Must be signed. */
1407 SizeT n_addrs_bad = 0;
1408 Addr ai;
1409 UChar vbits8;
1410 Bool ok;
1411
njn45e81252006-03-28 12:35:08 +00001412 tl_assert(nBits == 64 || nBits == 32 || nBits == 16 || nBits == 8);
sewardj45d94cc2005-04-20 14:44:11 +00001413
sewardjda04f3e2012-03-08 14:51:01 +00001414 /* Make up a 64-bit result V word, which contains the loaded data
1415 for valid addresses and Defined for invalid addresses. Iterate
1416 over the bytes in the word, from the most significant down to
1417 the least. The vbits to return are calculated into vbits64.
1418 Also compute the pessimising value to be used when
1419 --partial-loads-ok=yes. n_addrs_bad is redundant (the relevant
1420 info can be gleaned from pessim64) but is used as a
1421 cross-check. */
njn1d0825f2006-03-27 11:37:07 +00001422 for (i = szB-1; i >= 0; i--) {
florian60042192015-08-04 15:58:41 +00001423 PROF_EVENT(MCPE_LOADVN_SLOW_LOOP);
njn45e81252006-03-28 12:35:08 +00001424 ai = a + byte_offset_w(szB, bigendian, i);
njn1d0825f2006-03-27 11:37:07 +00001425 ok = get_vbits8(ai, &vbits8);
njn1d0825f2006-03-27 11:37:07 +00001426 vbits64 <<= 8;
1427 vbits64 |= vbits8;
sewardjda04f3e2012-03-08 14:51:01 +00001428 if (!ok) n_addrs_bad++;
1429 pessim64 <<= 8;
1430 pessim64 |= (ok ? V_BITS8_DEFINED : V_BITS8_UNDEFINED);
sewardj45d94cc2005-04-20 14:44:11 +00001431 }
1432
sewardjda04f3e2012-03-08 14:51:01 +00001433 /* In the common case, all the addresses involved are valid, so we
1434 just return the computed V bits and have done. */
1435 if (LIKELY(n_addrs_bad == 0))
1436 return vbits64;
sewardj0ded7a42005-11-08 02:25:37 +00001437
sewardjda04f3e2012-03-08 14:51:01 +00001438 /* If there's no possibility of getting a partial-loads-ok
1439 exemption, report the error and quit. */
1440 if (!MC_(clo_partial_loads_ok)) {
1441 MC_(record_address_error)( VG_(get_running_tid)(), a, szB, False );
1442 return vbits64;
1443 }
1444
1445 /* The partial-loads-ok excemption might apply. Find out if it
1446 does. If so, don't report an addressing error, but do return
1447 Undefined for the bytes that are out of range, so as to avoid
1448 false negatives. If it doesn't apply, just report an addressing
1449 error in the usual way. */
1450
1451 /* Some code steps along byte strings in aligned word-sized chunks
1452 even when there is only a partially defined word at the end (eg,
1453 optimised strlen). This is allowed by the memory model of
1454 modern machines, since an aligned load cannot span two pages and
1455 thus cannot "partially fault". Despite such behaviour being
1456 declared undefined by ANSI C/C++.
1457
1458 Therefore, a load from a partially-addressible place is allowed
1459 if all of the following hold:
1460 - the command-line flag is set [by default, it isn't]
sewardj0ded7a42005-11-08 02:25:37 +00001461 - it's a word-sized, word-aligned load
1462 - at least one of the addresses in the word *is* valid
sewardj0ded7a42005-11-08 02:25:37 +00001463
sewardjda04f3e2012-03-08 14:51:01 +00001464 Since this suppresses the addressing error, we avoid false
1465 negatives by marking bytes undefined when they come from an
1466 invalid address.
1467 */
1468
1469 /* "at least one of the addresses is invalid" */
1470 tl_assert(pessim64 != V_BITS64_DEFINED);
1471
1472 if (szB == VG_WORDSIZE && VG_IS_WORD_ALIGNED(a)
1473 && n_addrs_bad < VG_WORDSIZE) {
1474 /* Exemption applies. Use the previously computed pessimising
1475 value for vbits64 and return the combined result, but don't
1476 flag an addressing error. The pessimising value is Defined
1477 for valid addresses and Undefined for invalid addresses. */
1478 /* for assumption that doing bitwise or implements UifU */
1479 tl_assert(V_BIT_UNDEFINED == 1 && V_BIT_DEFINED == 0);
1480 /* (really need "UifU" here...)
1481 vbits64 UifU= pessim64 (is pessimised by it, iow) */
1482 vbits64 |= pessim64;
1483 return vbits64;
1484 }
1485
sewardjd53d3172013-10-22 15:36:59 +00001486 /* Also, in appears that gcc generates string-stepping code in
1487 32-bit chunks on 64 bit platforms. So, also grant an exception
1488 for this case. Note that the first clause of the conditional
1489 (VG_WORDSIZE == 8) is known at compile time, so the whole clause
1490 will get folded out in 32 bit builds. */
1491 if (VG_WORDSIZE == 8
1492 && VG_IS_4_ALIGNED(a) && nBits == 32 && n_addrs_bad < 4) {
1493 tl_assert(V_BIT_UNDEFINED == 1 && V_BIT_DEFINED == 0);
1494 /* (really need "UifU" here...)
1495 vbits64 UifU= pessim64 (is pessimised by it, iow) */
1496 vbits64 |= pessim64;
1497 /* Mark the upper 32 bits as undefined, just to be on the safe
1498 side. */
1499 vbits64 |= (((ULong)V_BITS32_UNDEFINED) << 32);
1500 return vbits64;
1501 }
1502
sewardjda04f3e2012-03-08 14:51:01 +00001503 /* Exemption doesn't apply. Flag an addressing error in the normal
1504 way. */
1505 MC_(record_address_error)( VG_(get_running_tid)(), a, szB, False );
sewardj45d94cc2005-04-20 14:44:11 +00001506
njn1d0825f2006-03-27 11:37:07 +00001507 return vbits64;
sewardj45d94cc2005-04-20 14:44:11 +00001508}
1509
1510
njn1d0825f2006-03-27 11:37:07 +00001511static
sewardj14a81782011-08-20 15:55:07 +00001512__attribute__((noinline))
njn45e81252006-03-28 12:35:08 +00001513void mc_STOREVn_slow ( Addr a, SizeT nBits, ULong vbytes, Bool bigendian )
sewardj45d94cc2005-04-20 14:44:11 +00001514{
njn45e81252006-03-28 12:35:08 +00001515 SizeT szB = nBits / 8;
njn1d0825f2006-03-27 11:37:07 +00001516 SizeT i, n_addrs_bad = 0;
1517 UChar vbits8;
sewardj45d94cc2005-04-20 14:44:11 +00001518 Addr ai;
njn1d0825f2006-03-27 11:37:07 +00001519 Bool ok;
sewardj45d94cc2005-04-20 14:44:11 +00001520
florian60042192015-08-04 15:58:41 +00001521 PROF_EVENT(MCPE_STOREVN_SLOW);
sewardj05a46732006-10-17 01:28:10 +00001522
1523 /* ------------ BEGIN semi-fast cases ------------ */
1524 /* These deal quickly-ish with the common auxiliary primary map
1525 cases on 64-bit platforms. Are merely a speedup hack; can be
1526 omitted without loss of correctness/functionality. Note that in
1527 both cases the "sizeof(void*) == 8" causes these cases to be
philippeb8ac5ac2014-04-22 22:07:01 +00001528 folded out by compilers on 32-bit platforms. The logic below
1529 is somewhat similar to some cases extensively commented in
1530 MC_(helperc_STOREV8).
sewardj05a46732006-10-17 01:28:10 +00001531 */
bart5dd8e6a2008-03-22 08:04:29 +00001532 if (LIKELY(sizeof(void*) == 8
sewardj05a46732006-10-17 01:28:10 +00001533 && nBits == 64 && VG_IS_8_ALIGNED(a))) {
1534 SecMap* sm = get_secmap_for_reading(a);
1535 UWord sm_off16 = SM_OFF_16(a);
1536 UWord vabits16 = ((UShort*)(sm->vabits8))[sm_off16];
bart5dd8e6a2008-03-22 08:04:29 +00001537 if (LIKELY( !is_distinguished_sm(sm) &&
sewardj05a46732006-10-17 01:28:10 +00001538 (VA_BITS16_DEFINED == vabits16 ||
1539 VA_BITS16_UNDEFINED == vabits16) )) {
1540 /* Handle common case quickly: a is suitably aligned, */
1541 /* is mapped, and is addressible. */
1542 // Convert full V-bits in register to compact 2-bit form.
bart5dd8e6a2008-03-22 08:04:29 +00001543 if (LIKELY(V_BITS64_DEFINED == vbytes)) {
sewardj05a46732006-10-17 01:28:10 +00001544 ((UShort*)(sm->vabits8))[sm_off16] = (UShort)VA_BITS16_DEFINED;
1545 return;
1546 } else if (V_BITS64_UNDEFINED == vbytes) {
1547 ((UShort*)(sm->vabits8))[sm_off16] = (UShort)VA_BITS16_UNDEFINED;
1548 return;
1549 }
1550 /* else fall into the slow case */
1551 }
1552 /* else fall into the slow case */
1553 }
bart5dd8e6a2008-03-22 08:04:29 +00001554 if (LIKELY(sizeof(void*) == 8
sewardj05a46732006-10-17 01:28:10 +00001555 && nBits == 32 && VG_IS_4_ALIGNED(a))) {
1556 SecMap* sm = get_secmap_for_reading(a);
1557 UWord sm_off = SM_OFF(a);
1558 UWord vabits8 = sm->vabits8[sm_off];
bart5dd8e6a2008-03-22 08:04:29 +00001559 if (LIKELY( !is_distinguished_sm(sm) &&
sewardj05a46732006-10-17 01:28:10 +00001560 (VA_BITS8_DEFINED == vabits8 ||
1561 VA_BITS8_UNDEFINED == vabits8) )) {
1562 /* Handle common case quickly: a is suitably aligned, */
1563 /* is mapped, and is addressible. */
1564 // Convert full V-bits in register to compact 2-bit form.
bart5dd8e6a2008-03-22 08:04:29 +00001565 if (LIKELY(V_BITS32_DEFINED == (vbytes & 0xFFFFFFFF))) {
sewardj05a46732006-10-17 01:28:10 +00001566 sm->vabits8[sm_off] = VA_BITS8_DEFINED;
1567 return;
1568 } else if (V_BITS32_UNDEFINED == (vbytes & 0xFFFFFFFF)) {
1569 sm->vabits8[sm_off] = VA_BITS8_UNDEFINED;
1570 return;
1571 }
1572 /* else fall into the slow case */
1573 }
1574 /* else fall into the slow case */
1575 }
1576 /* ------------ END semi-fast cases ------------ */
1577
njn45e81252006-03-28 12:35:08 +00001578 tl_assert(nBits == 64 || nBits == 32 || nBits == 16 || nBits == 8);
sewardj45d94cc2005-04-20 14:44:11 +00001579
1580 /* Dump vbytes in memory, iterating from least to most significant
njn718d3b12006-12-16 00:54:12 +00001581 byte. At the same time establish addressibility of the location. */
sewardj45d94cc2005-04-20 14:44:11 +00001582 for (i = 0; i < szB; i++) {
florian60042192015-08-04 15:58:41 +00001583 PROF_EVENT(MCPE_STOREVN_SLOW_LOOP);
njn45e81252006-03-28 12:35:08 +00001584 ai = a + byte_offset_w(szB, bigendian, i);
njn1d0825f2006-03-27 11:37:07 +00001585 vbits8 = vbytes & 0xff;
1586 ok = set_vbits8(ai, vbits8);
1587 if (!ok) n_addrs_bad++;
sewardj45d94cc2005-04-20 14:44:11 +00001588 vbytes >>= 8;
1589 }
1590
1591 /* If an address error has happened, report it. */
1592 if (n_addrs_bad > 0)
sewardj7ce71662008-05-02 10:33:15 +00001593 MC_(record_address_error)( VG_(get_running_tid)(), a, szB, True );
sewardj45d94cc2005-04-20 14:44:11 +00001594}
1595
1596
njn25e49d8e72002-09-23 09:36:25 +00001597/*------------------------------------------------------------*/
1598/*--- Setting permissions over address ranges. ---*/
1599/*------------------------------------------------------------*/
1600
njn1d0825f2006-03-27 11:37:07 +00001601static void set_address_range_perms ( Addr a, SizeT lenT, UWord vabits16,
1602 UWord dsm_num )
sewardj23eb2fd2005-04-22 16:29:19 +00001603{
njn1d0825f2006-03-27 11:37:07 +00001604 UWord sm_off, sm_off16;
1605 UWord vabits2 = vabits16 & 0x3;
1606 SizeT lenA, lenB, len_to_next_secmap;
1607 Addr aNext;
sewardjae986ca2005-10-12 12:53:20 +00001608 SecMap* sm;
njn1d0825f2006-03-27 11:37:07 +00001609 SecMap** sm_ptr;
sewardjae986ca2005-10-12 12:53:20 +00001610 SecMap* example_dsm;
1611
florian60042192015-08-04 15:58:41 +00001612 PROF_EVENT(MCPE_SET_ADDRESS_RANGE_PERMS);
sewardj23eb2fd2005-04-22 16:29:19 +00001613
njn1d0825f2006-03-27 11:37:07 +00001614 /* Check the V+A bits make sense. */
njndbf7ca72006-03-31 11:57:59 +00001615 tl_assert(VA_BITS16_NOACCESS == vabits16 ||
1616 VA_BITS16_UNDEFINED == vabits16 ||
1617 VA_BITS16_DEFINED == vabits16);
sewardj23eb2fd2005-04-22 16:29:19 +00001618
njn1d0825f2006-03-27 11:37:07 +00001619 // This code should never write PDBs; ensure this. (See comment above
1620 // set_vabits2().)
njndbf7ca72006-03-31 11:57:59 +00001621 tl_assert(VA_BITS2_PARTDEFINED != vabits2);
njn1d0825f2006-03-27 11:37:07 +00001622
1623 if (lenT == 0)
sewardj23eb2fd2005-04-22 16:29:19 +00001624 return;
1625
njn59973402009-05-20 03:44:09 +00001626 if (lenT > 256 * 1024 * 1024) {
njn1d0825f2006-03-27 11:37:07 +00001627 if (VG_(clo_verbosity) > 0 && !VG_(clo_xml)) {
floriana5f894c2012-10-21 03:43:20 +00001628 const HChar* s = "unknown???";
njndbf7ca72006-03-31 11:57:59 +00001629 if (vabits16 == VA_BITS16_NOACCESS ) s = "noaccess";
1630 if (vabits16 == VA_BITS16_UNDEFINED) s = "undefined";
1631 if (vabits16 == VA_BITS16_DEFINED ) s = "defined";
njn1d0825f2006-03-27 11:37:07 +00001632 VG_(message)(Vg_UserMsg, "Warning: set address range perms: "
sewardj6b523cd2009-07-15 14:49:40 +00001633 "large range [0x%lx, 0x%lx) (%s)\n",
tom2a836b52008-07-18 08:38:44 +00001634 a, a + lenT, s);
sewardj23eb2fd2005-04-22 16:29:19 +00001635 }
1636 }
1637
njn1d0825f2006-03-27 11:37:07 +00001638#ifndef PERF_FAST_SARP
sewardj23eb2fd2005-04-22 16:29:19 +00001639 /*------------------ debug-only case ------------------ */
njn1d0825f2006-03-27 11:37:07 +00001640 {
1641 // Endianness doesn't matter here because all bytes are being set to
1642 // the same value.
1643 // Nb: We don't have to worry about updating the sec-V-bits table
1644 // after these set_vabits2() calls because this code never writes
njndbf7ca72006-03-31 11:57:59 +00001645 // VA_BITS2_PARTDEFINED values.
njn1d0825f2006-03-27 11:37:07 +00001646 SizeT i;
1647 for (i = 0; i < lenT; i++) {
1648 set_vabits2(a + i, vabits2);
1649 }
1650 return;
njn25e49d8e72002-09-23 09:36:25 +00001651 }
njn1d0825f2006-03-27 11:37:07 +00001652#endif
sewardj23eb2fd2005-04-22 16:29:19 +00001653
1654 /*------------------ standard handling ------------------ */
sewardj23eb2fd2005-04-22 16:29:19 +00001655
njn1d0825f2006-03-27 11:37:07 +00001656 /* Get the distinguished secondary that we might want
sewardj23eb2fd2005-04-22 16:29:19 +00001657 to use (part of the space-compression scheme). */
njn1d0825f2006-03-27 11:37:07 +00001658 example_dsm = &sm_distinguished[dsm_num];
1659
1660 // We have to handle ranges covering various combinations of partial and
1661 // whole sec-maps. Here is how parts 1, 2 and 3 are used in each case.
1662 // Cases marked with a '*' are common.
1663 //
1664 // TYPE PARTS USED
1665 // ---- ----------
1666 // * one partial sec-map (p) 1
1667 // - one whole sec-map (P) 2
1668 //
1669 // * two partial sec-maps (pp) 1,3
1670 // - one partial, one whole sec-map (pP) 1,2
1671 // - one whole, one partial sec-map (Pp) 2,3
1672 // - two whole sec-maps (PP) 2,2
1673 //
1674 // * one partial, one whole, one partial (pPp) 1,2,3
1675 // - one partial, two whole (pPP) 1,2,2
1676 // - two whole, one partial (PPp) 2,2,3
1677 // - three whole (PPP) 2,2,2
1678 //
1679 // * one partial, N-2 whole, one partial (pP...Pp) 1,2...2,3
1680 // - one partial, N-1 whole (pP...PP) 1,2...2,2
1681 // - N-1 whole, one partial (PP...Pp) 2,2...2,3
1682 // - N whole (PP...PP) 2,2...2,3
1683
1684 // Break up total length (lenT) into two parts: length in the first
1685 // sec-map (lenA), and the rest (lenB); lenT == lenA + lenB.
1686 aNext = start_of_this_sm(a) + SM_SIZE;
1687 len_to_next_secmap = aNext - a;
1688 if ( lenT <= len_to_next_secmap ) {
1689 // Range entirely within one sec-map. Covers almost all cases.
florian60042192015-08-04 15:58:41 +00001690 PROF_EVENT(MCPE_SET_ADDRESS_RANGE_PERMS_SINGLE_SECMAP);
njn1d0825f2006-03-27 11:37:07 +00001691 lenA = lenT;
1692 lenB = 0;
1693 } else if (is_start_of_sm(a)) {
1694 // Range spans at least one whole sec-map, and starts at the beginning
1695 // of a sec-map; skip to Part 2.
florian60042192015-08-04 15:58:41 +00001696 PROF_EVENT(MCPE_SET_ADDRESS_RANGE_PERMS_STARTOF_SECMAP);
njn1d0825f2006-03-27 11:37:07 +00001697 lenA = 0;
1698 lenB = lenT;
1699 goto part2;
sewardj23eb2fd2005-04-22 16:29:19 +00001700 } else {
njn1d0825f2006-03-27 11:37:07 +00001701 // Range spans two or more sec-maps, first one is partial.
florian60042192015-08-04 15:58:41 +00001702 PROF_EVENT(MCPE_SET_ADDRESS_RANGE_PERMS_MULTIPLE_SECMAPS);
njn1d0825f2006-03-27 11:37:07 +00001703 lenA = len_to_next_secmap;
1704 lenB = lenT - lenA;
1705 }
1706
1707 //------------------------------------------------------------------------
1708 // Part 1: Deal with the first sec_map. Most of the time the range will be
1709 // entirely within a sec_map and this part alone will suffice. Also,
1710 // doing it this way lets us avoid repeatedly testing for the crossing of
1711 // a sec-map boundary within these loops.
1712 //------------------------------------------------------------------------
1713
1714 // If it's distinguished, make it undistinguished if necessary.
1715 sm_ptr = get_secmap_ptr(a);
1716 if (is_distinguished_sm(*sm_ptr)) {
1717 if (*sm_ptr == example_dsm) {
1718 // Sec-map already has the V+A bits that we want, so skip.
florian60042192015-08-04 15:58:41 +00001719 PROF_EVENT(MCPE_SET_ADDRESS_RANGE_PERMS_DIST_SM1_QUICK);
njn1d0825f2006-03-27 11:37:07 +00001720 a = aNext;
1721 lenA = 0;
sewardj23eb2fd2005-04-22 16:29:19 +00001722 } else {
florian60042192015-08-04 15:58:41 +00001723 PROF_EVENT(MCPE_SET_ADDRESS_RANGE_PERMS_DIST_SM1);
njn1d0825f2006-03-27 11:37:07 +00001724 *sm_ptr = copy_for_writing(*sm_ptr);
sewardj23eb2fd2005-04-22 16:29:19 +00001725 }
1726 }
njn1d0825f2006-03-27 11:37:07 +00001727 sm = *sm_ptr;
sewardj23eb2fd2005-04-22 16:29:19 +00001728
njn1d0825f2006-03-27 11:37:07 +00001729 // 1 byte steps
sewardj23eb2fd2005-04-22 16:29:19 +00001730 while (True) {
sewardj23eb2fd2005-04-22 16:29:19 +00001731 if (VG_IS_8_ALIGNED(a)) break;
njn1d0825f2006-03-27 11:37:07 +00001732 if (lenA < 1) break;
florian60042192015-08-04 15:58:41 +00001733 PROF_EVENT(MCPE_SET_ADDRESS_RANGE_PERMS_LOOP1A);
njn1d0825f2006-03-27 11:37:07 +00001734 sm_off = SM_OFF(a);
1735 insert_vabits2_into_vabits8( a, vabits2, &(sm->vabits8[sm_off]) );
1736 a += 1;
1737 lenA -= 1;
1738 }
1739 // 8-aligned, 8 byte steps
sewardj23eb2fd2005-04-22 16:29:19 +00001740 while (True) {
njn1d0825f2006-03-27 11:37:07 +00001741 if (lenA < 8) break;
florian60042192015-08-04 15:58:41 +00001742 PROF_EVENT(MCPE_SET_ADDRESS_RANGE_PERMS_LOOP8A);
njn1d0825f2006-03-27 11:37:07 +00001743 sm_off16 = SM_OFF_16(a);
1744 ((UShort*)(sm->vabits8))[sm_off16] = vabits16;
1745 a += 8;
1746 lenA -= 8;
1747 }
1748 // 1 byte steps
1749 while (True) {
1750 if (lenA < 1) break;
florian60042192015-08-04 15:58:41 +00001751 PROF_EVENT(MCPE_SET_ADDRESS_RANGE_PERMS_LOOP1B);
njn1d0825f2006-03-27 11:37:07 +00001752 sm_off = SM_OFF(a);
1753 insert_vabits2_into_vabits8( a, vabits2, &(sm->vabits8[sm_off]) );
1754 a += 1;
1755 lenA -= 1;
sewardj23eb2fd2005-04-22 16:29:19 +00001756 }
1757
njn1d0825f2006-03-27 11:37:07 +00001758 // We've finished the first sec-map. Is that it?
1759 if (lenB == 0)
sewardj23eb2fd2005-04-22 16:29:19 +00001760 return;
1761
njn1d0825f2006-03-27 11:37:07 +00001762 //------------------------------------------------------------------------
1763 // Part 2: Fast-set entire sec-maps at a time.
1764 //------------------------------------------------------------------------
1765 part2:
1766 // 64KB-aligned, 64KB steps.
1767 // Nb: we can reach here with lenB < SM_SIZE
njn4c245e52009-03-15 23:25:38 +00001768 tl_assert(0 == lenA);
sewardj23eb2fd2005-04-22 16:29:19 +00001769 while (True) {
njn1d0825f2006-03-27 11:37:07 +00001770 if (lenB < SM_SIZE) break;
1771 tl_assert(is_start_of_sm(a));
florian60042192015-08-04 15:58:41 +00001772 PROF_EVENT(MCPE_SET_ADDRESS_RANGE_PERMS_LOOP64K);
njn1d0825f2006-03-27 11:37:07 +00001773 sm_ptr = get_secmap_ptr(a);
1774 if (!is_distinguished_sm(*sm_ptr)) {
florian60042192015-08-04 15:58:41 +00001775 PROF_EVENT(MCPE_SET_ADDRESS_RANGE_PERMS_LOOP64K_FREE_DIST_SM);
njn1d0825f2006-03-27 11:37:07 +00001776 // Free the non-distinguished sec-map that we're replacing. This
1777 // case happens moderately often, enough to be worthwhile.
philippe37725662012-05-13 22:58:09 +00001778 SysRes sres = VG_(am_munmap_valgrind)((Addr)*sm_ptr, sizeof(SecMap));
1779 tl_assert2(! sr_isError(sres), "SecMap valgrind munmap failure\n");
njn1d0825f2006-03-27 11:37:07 +00001780 }
1781 update_SM_counts(*sm_ptr, example_dsm);
1782 // Make the sec-map entry point to the example DSM
1783 *sm_ptr = example_dsm;
1784 lenB -= SM_SIZE;
1785 a += SM_SIZE;
1786 }
sewardj23eb2fd2005-04-22 16:29:19 +00001787
njn1d0825f2006-03-27 11:37:07 +00001788 // We've finished the whole sec-maps. Is that it?
1789 if (lenB == 0)
1790 return;
1791
1792 //------------------------------------------------------------------------
1793 // Part 3: Finish off the final partial sec-map, if necessary.
1794 //------------------------------------------------------------------------
1795
1796 tl_assert(is_start_of_sm(a) && lenB < SM_SIZE);
1797
1798 // If it's distinguished, make it undistinguished if necessary.
1799 sm_ptr = get_secmap_ptr(a);
1800 if (is_distinguished_sm(*sm_ptr)) {
1801 if (*sm_ptr == example_dsm) {
1802 // Sec-map already has the V+A bits that we want, so stop.
florian60042192015-08-04 15:58:41 +00001803 PROF_EVENT(MCPE_SET_ADDRESS_RANGE_PERMS_DIST_SM2_QUICK);
njn1d0825f2006-03-27 11:37:07 +00001804 return;
1805 } else {
florian60042192015-08-04 15:58:41 +00001806 PROF_EVENT(MCPE_SET_ADDRESS_RANGE_PERMS_DIST_SM2);
njn1d0825f2006-03-27 11:37:07 +00001807 *sm_ptr = copy_for_writing(*sm_ptr);
1808 }
1809 }
1810 sm = *sm_ptr;
1811
1812 // 8-aligned, 8 byte steps
1813 while (True) {
1814 if (lenB < 8) break;
florian60042192015-08-04 15:58:41 +00001815 PROF_EVENT(MCPE_SET_ADDRESS_RANGE_PERMS_LOOP8B);
njn1d0825f2006-03-27 11:37:07 +00001816 sm_off16 = SM_OFF_16(a);
1817 ((UShort*)(sm->vabits8))[sm_off16] = vabits16;
1818 a += 8;
1819 lenB -= 8;
1820 }
1821 // 1 byte steps
1822 while (True) {
1823 if (lenB < 1) return;
florian60042192015-08-04 15:58:41 +00001824 PROF_EVENT(MCPE_SET_ADDRESS_RANGE_PERMS_LOOP1C);
njn1d0825f2006-03-27 11:37:07 +00001825 sm_off = SM_OFF(a);
1826 insert_vabits2_into_vabits8( a, vabits2, &(sm->vabits8[sm_off]) );
1827 a += 1;
1828 lenB -= 1;
1829 }
sewardj23eb2fd2005-04-22 16:29:19 +00001830}
sewardj45d94cc2005-04-20 14:44:11 +00001831
sewardjc859fbf2005-04-22 21:10:28 +00001832
1833/* --- Set permissions for arbitrary address ranges --- */
njn25e49d8e72002-09-23 09:36:25 +00001834
njndbf7ca72006-03-31 11:57:59 +00001835void MC_(make_mem_noaccess) ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +00001836{
florian60042192015-08-04 15:58:41 +00001837 PROF_EVENT(MCPE_MAKE_MEM_NOACCESS);
njndbf7ca72006-03-31 11:57:59 +00001838 DEBUG("MC_(make_mem_noaccess)(%p, %lu)\n", a, len);
njn1d0825f2006-03-27 11:37:07 +00001839 set_address_range_perms ( a, len, VA_BITS16_NOACCESS, SM_DIST_NOACCESS );
sewardj7cf4e6b2008-05-01 20:24:26 +00001840 if (UNLIKELY( MC_(clo_mc_level) == 3 ))
1841 ocache_sarp_Clear_Origins ( a, len );
njn25e49d8e72002-09-23 09:36:25 +00001842}
1843
sewardj7cf4e6b2008-05-01 20:24:26 +00001844static void make_mem_undefined ( Addr a, SizeT len )
1845{
florian60042192015-08-04 15:58:41 +00001846 PROF_EVENT(MCPE_MAKE_MEM_UNDEFINED);
sewardj7cf4e6b2008-05-01 20:24:26 +00001847 DEBUG("make_mem_undefined(%p, %lu)\n", a, len);
1848 set_address_range_perms ( a, len, VA_BITS16_UNDEFINED, SM_DIST_UNDEFINED );
1849}
1850
1851void MC_(make_mem_undefined_w_otag) ( Addr a, SizeT len, UInt otag )
njn25e49d8e72002-09-23 09:36:25 +00001852{
florian60042192015-08-04 15:58:41 +00001853 PROF_EVENT(MCPE_MAKE_MEM_UNDEFINED_W_OTAG);
njndbf7ca72006-03-31 11:57:59 +00001854 DEBUG("MC_(make_mem_undefined)(%p, %lu)\n", a, len);
1855 set_address_range_perms ( a, len, VA_BITS16_UNDEFINED, SM_DIST_UNDEFINED );
sewardj7cf4e6b2008-05-01 20:24:26 +00001856 if (UNLIKELY( MC_(clo_mc_level) == 3 ))
1857 ocache_sarp_Set_Origins ( a, len, otag );
njn25e49d8e72002-09-23 09:36:25 +00001858}
1859
sewardj7cf4e6b2008-05-01 20:24:26 +00001860static
1861void make_mem_undefined_w_tid_and_okind ( Addr a, SizeT len,
1862 ThreadId tid, UInt okind )
1863{
1864 UInt ecu;
1865 ExeContext* here;
1866 /* VG_(record_ExeContext) checks for validity of tid, and asserts
1867 if it is invalid. So no need to do it here. */
1868 tl_assert(okind <= 3);
1869 here = VG_(record_ExeContext)( tid, 0/*first_ip_delta*/ );
1870 tl_assert(here);
1871 ecu = VG_(get_ECU_from_ExeContext)(here);
1872 tl_assert(VG_(is_plausible_ECU)(ecu));
1873 MC_(make_mem_undefined_w_otag) ( a, len, ecu | okind );
1874}
1875
1876static
philippe5db022b2013-01-13 15:01:21 +00001877void mc_new_mem_w_tid_make_ECU ( Addr a, SizeT len, ThreadId tid )
1878{
sewardj7cf4e6b2008-05-01 20:24:26 +00001879 make_mem_undefined_w_tid_and_okind ( a, len, tid, MC_OKIND_UNKNOWN );
1880}
1881
philippe5db022b2013-01-13 15:01:21 +00001882static
1883void mc_new_mem_w_tid_no_ECU ( Addr a, SizeT len, ThreadId tid )
1884{
1885 MC_(make_mem_undefined_w_otag) ( a, len, MC_OKIND_UNKNOWN );
1886}
sewardj7cf4e6b2008-05-01 20:24:26 +00001887
njndbf7ca72006-03-31 11:57:59 +00001888void MC_(make_mem_defined) ( Addr a, SizeT len )
njn25e49d8e72002-09-23 09:36:25 +00001889{
florian60042192015-08-04 15:58:41 +00001890 PROF_EVENT(MCPE_MAKE_MEM_DEFINED);
njndbf7ca72006-03-31 11:57:59 +00001891 DEBUG("MC_(make_mem_defined)(%p, %lu)\n", a, len);
1892 set_address_range_perms ( a, len, VA_BITS16_DEFINED, SM_DIST_DEFINED );
sewardj7cf4e6b2008-05-01 20:24:26 +00001893 if (UNLIKELY( MC_(clo_mc_level) == 3 ))
1894 ocache_sarp_Clear_Origins ( a, len );
njn25e49d8e72002-09-23 09:36:25 +00001895}
1896
sewardj8eb8bab2015-07-21 14:44:28 +00001897__attribute__((unused))
1898static void make_mem_defined_w_tid ( Addr a, SizeT len, ThreadId tid )
1899{
1900 MC_(make_mem_defined)(a, len);
1901}
1902
sewardjfb1e9ad2006-03-10 13:41:58 +00001903/* For each byte in [a,a+len), if the byte is addressable, make it be
1904 defined, but if it isn't addressible, leave it alone. In other
njndbf7ca72006-03-31 11:57:59 +00001905 words a version of MC_(make_mem_defined) that doesn't mess with
sewardjfb1e9ad2006-03-10 13:41:58 +00001906 addressibility. Low-performance implementation. */
njndbf7ca72006-03-31 11:57:59 +00001907static void make_mem_defined_if_addressable ( Addr a, SizeT len )
sewardjfb1e9ad2006-03-10 13:41:58 +00001908{
1909 SizeT i;
njn1d0825f2006-03-27 11:37:07 +00001910 UChar vabits2;
njndbf7ca72006-03-31 11:57:59 +00001911 DEBUG("make_mem_defined_if_addressable(%p, %llu)\n", a, (ULong)len);
sewardjfb1e9ad2006-03-10 13:41:58 +00001912 for (i = 0; i < len; i++) {
njn1d0825f2006-03-27 11:37:07 +00001913 vabits2 = get_vabits2( a+i );
bart5dd8e6a2008-03-22 08:04:29 +00001914 if (LIKELY(VA_BITS2_NOACCESS != vabits2)) {
njndbf7ca72006-03-31 11:57:59 +00001915 set_vabits2(a+i, VA_BITS2_DEFINED);
sewardj7cf4e6b2008-05-01 20:24:26 +00001916 if (UNLIKELY(MC_(clo_mc_level) >= 3)) {
1917 MC_(helperc_b_store1)( a+i, 0 ); /* clear the origin tag */
1918 }
njn1d0825f2006-03-27 11:37:07 +00001919 }
sewardjfb1e9ad2006-03-10 13:41:58 +00001920 }
1921}
1922
sewardj6f95e7e2010-01-27 10:28:00 +00001923/* Similarly (needed for mprotect handling ..) */
1924static void make_mem_defined_if_noaccess ( Addr a, SizeT len )
1925{
1926 SizeT i;
1927 UChar vabits2;
1928 DEBUG("make_mem_defined_if_noaccess(%p, %llu)\n", a, (ULong)len);
1929 for (i = 0; i < len; i++) {
1930 vabits2 = get_vabits2( a+i );
1931 if (LIKELY(VA_BITS2_NOACCESS == vabits2)) {
1932 set_vabits2(a+i, VA_BITS2_DEFINED);
1933 if (UNLIKELY(MC_(clo_mc_level) >= 3)) {
1934 MC_(helperc_b_store1)( a+i, 0 ); /* clear the origin tag */
1935 }
1936 }
1937 }
1938}
njn9b007f62003-04-07 14:40:25 +00001939
sewardj45f4e7c2005-09-27 19:20:21 +00001940/* --- Block-copy permissions (needed for implementing realloc() and
1941 sys_mremap). --- */
sewardjc859fbf2005-04-22 21:10:28 +00001942
njn1d0825f2006-03-27 11:37:07 +00001943void MC_(copy_address_range_state) ( Addr src, Addr dst, SizeT len )
sewardjc859fbf2005-04-22 21:10:28 +00001944{
sewardj45f4e7c2005-09-27 19:20:21 +00001945 SizeT i, j;
sewardjf2184912006-05-03 22:13:57 +00001946 UChar vabits2, vabits8;
1947 Bool aligned, nooverlap;
sewardjc859fbf2005-04-22 21:10:28 +00001948
njn1d0825f2006-03-27 11:37:07 +00001949 DEBUG("MC_(copy_address_range_state)\n");
florian60042192015-08-04 15:58:41 +00001950 PROF_EVENT(MCPE_COPY_ADDRESS_RANGE_STATE);
sewardj45f4e7c2005-09-27 19:20:21 +00001951
sewardjf2184912006-05-03 22:13:57 +00001952 if (len == 0 || src == dst)
sewardj45f4e7c2005-09-27 19:20:21 +00001953 return;
1954
sewardjf2184912006-05-03 22:13:57 +00001955 aligned = VG_IS_4_ALIGNED(src) && VG_IS_4_ALIGNED(dst);
1956 nooverlap = src+len <= dst || dst+len <= src;
sewardj45f4e7c2005-09-27 19:20:21 +00001957
sewardjf2184912006-05-03 22:13:57 +00001958 if (nooverlap && aligned) {
1959
1960 /* Vectorised fast case, when no overlap and suitably aligned */
1961 /* vector loop */
1962 i = 0;
1963 while (len >= 4) {
1964 vabits8 = get_vabits8_for_aligned_word32( src+i );
1965 set_vabits8_for_aligned_word32( dst+i, vabits8 );
bart5dd8e6a2008-03-22 08:04:29 +00001966 if (LIKELY(VA_BITS8_DEFINED == vabits8
sewardjf2184912006-05-03 22:13:57 +00001967 || VA_BITS8_UNDEFINED == vabits8
1968 || VA_BITS8_NOACCESS == vabits8)) {
1969 /* do nothing */
1970 } else {
1971 /* have to copy secondary map info */
1972 if (VA_BITS2_PARTDEFINED == get_vabits2( src+i+0 ))
1973 set_sec_vbits8( dst+i+0, get_sec_vbits8( src+i+0 ) );
1974 if (VA_BITS2_PARTDEFINED == get_vabits2( src+i+1 ))
1975 set_sec_vbits8( dst+i+1, get_sec_vbits8( src+i+1 ) );
1976 if (VA_BITS2_PARTDEFINED == get_vabits2( src+i+2 ))
1977 set_sec_vbits8( dst+i+2, get_sec_vbits8( src+i+2 ) );
1978 if (VA_BITS2_PARTDEFINED == get_vabits2( src+i+3 ))
1979 set_sec_vbits8( dst+i+3, get_sec_vbits8( src+i+3 ) );
1980 }
1981 i += 4;
1982 len -= 4;
1983 }
1984 /* fixup loop */
1985 while (len >= 1) {
njn1d0825f2006-03-27 11:37:07 +00001986 vabits2 = get_vabits2( src+i );
1987 set_vabits2( dst+i, vabits2 );
njndbf7ca72006-03-31 11:57:59 +00001988 if (VA_BITS2_PARTDEFINED == vabits2) {
njn1d0825f2006-03-27 11:37:07 +00001989 set_sec_vbits8( dst+i, get_sec_vbits8( src+i ) );
1990 }
sewardjf2184912006-05-03 22:13:57 +00001991 i++;
1992 len--;
1993 }
1994
1995 } else {
1996
1997 /* We have to do things the slow way */
1998 if (src < dst) {
1999 for (i = 0, j = len-1; i < len; i++, j--) {
florian60042192015-08-04 15:58:41 +00002000 PROF_EVENT(MCPE_COPY_ADDRESS_RANGE_STATE_LOOP1);
sewardjf2184912006-05-03 22:13:57 +00002001 vabits2 = get_vabits2( src+j );
2002 set_vabits2( dst+j, vabits2 );
2003 if (VA_BITS2_PARTDEFINED == vabits2) {
2004 set_sec_vbits8( dst+j, get_sec_vbits8( src+j ) );
2005 }
2006 }
2007 }
2008
2009 if (src > dst) {
2010 for (i = 0; i < len; i++) {
florian60042192015-08-04 15:58:41 +00002011 PROF_EVENT(MCPE_COPY_ADDRESS_RANGE_STATE_LOOP2);
sewardjf2184912006-05-03 22:13:57 +00002012 vabits2 = get_vabits2( src+i );
2013 set_vabits2( dst+i, vabits2 );
2014 if (VA_BITS2_PARTDEFINED == vabits2) {
2015 set_sec_vbits8( dst+i, get_sec_vbits8( src+i ) );
2016 }
2017 }
sewardj45f4e7c2005-09-27 19:20:21 +00002018 }
sewardjc859fbf2005-04-22 21:10:28 +00002019 }
sewardjf2184912006-05-03 22:13:57 +00002020
sewardjc859fbf2005-04-22 21:10:28 +00002021}
2022
2023
sewardj7cf4e6b2008-05-01 20:24:26 +00002024/*------------------------------------------------------------*/
2025/*--- Origin tracking stuff - cache basics ---*/
2026/*------------------------------------------------------------*/
sewardjc859fbf2005-04-22 21:10:28 +00002027
sewardj77139802008-05-05 09:48:56 +00002028/* AN OVERVIEW OF THE ORIGIN TRACKING IMPLEMENTATION
2029 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sewardj7cf4e6b2008-05-01 20:24:26 +00002030
2031 Note that this implementation draws inspiration from the "origin
2032 tracking by value piggybacking" scheme described in "Tracking Bad
2033 Apples: Reporting the Origin of Null and Undefined Value Errors"
2034 (Michael Bond, Nicholas Nethercote, Stephen Kent, Samuel Guyer,
2035 Kathryn McKinley, OOPSLA07, Montreal, Oct 2007) but in fact it is
2036 implemented completely differently.
2037
sewardj77139802008-05-05 09:48:56 +00002038 Origin tags and ECUs -- about the shadow values
2039 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2040
2041 This implementation tracks the defining point of all uninitialised
2042 values using so called "origin tags", which are 32-bit integers,
2043 rather than using the values themselves to encode the origins. The
2044 latter, so-called value piggybacking", is what the OOPSLA07 paper
sewardj7cf4e6b2008-05-01 20:24:26 +00002045 describes.
2046
2047 Origin tags, as tracked by the machinery below, are 32-bit unsigned
sewardj77139802008-05-05 09:48:56 +00002048 ints (UInts), regardless of the machine's word size. Each tag
2049 comprises an upper 30-bit ECU field and a lower 2-bit
2050 'kind' field. The ECU field is a number given out by m_execontext
2051 and has a 1-1 mapping with ExeContext*s. An ECU can be used
2052 directly as an origin tag (otag), but in fact we want to put
2053 additional information 'kind' field to indicate roughly where the
2054 tag came from. This helps print more understandable error messages
2055 for the user -- it has no other purpose. In summary:
2056
2057 * Both ECUs and origin tags are represented as 32-bit words
2058
2059 * m_execontext and the core-tool interface deal purely in ECUs.
2060 They have no knowledge of origin tags - that is a purely
2061 Memcheck-internal matter.
2062
2063 * all valid ECUs have the lowest 2 bits zero and at least
2064 one of the upper 30 bits nonzero (see VG_(is_plausible_ECU))
2065
2066 * to convert from an ECU to an otag, OR in one of the MC_OKIND_
2067 constants defined in mc_include.h.
2068
2069 * to convert an otag back to an ECU, AND it with ~3
2070
2071 One important fact is that no valid otag is zero. A zero otag is
2072 used by the implementation to indicate "no origin", which could
2073 mean that either the value is defined, or it is undefined but the
2074 implementation somehow managed to lose the origin.
2075
2076 The ECU used for memory created by malloc etc is derived from the
2077 stack trace at the time the malloc etc happens. This means the
2078 mechanism can show the exact allocation point for heap-created
2079 uninitialised values.
2080
2081 In contrast, it is simply too expensive to create a complete
2082 backtrace for each stack allocation. Therefore we merely use a
2083 depth-1 backtrace for stack allocations, which can be done once at
2084 translation time, rather than N times at run time. The result of
2085 this is that, for stack created uninitialised values, Memcheck can
2086 only show the allocating function, and not what called it.
2087 Furthermore, compilers tend to move the stack pointer just once at
2088 the start of the function, to allocate all locals, and so in fact
2089 the stack origin almost always simply points to the opening brace
2090 of the function. Net result is, for stack origins, the mechanism
2091 can tell you in which function the undefined value was created, but
2092 that's all. Users will need to carefully check all locals in the
2093 specified function.
2094
2095 Shadowing registers and memory
2096 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2097
2098 Memory is shadowed using a two level cache structure (ocacheL1 and
2099 ocacheL2). Memory references are first directed to ocacheL1. This
2100 is a traditional 2-way set associative cache with 32-byte lines and
2101 approximate LRU replacement within each set.
2102
2103 A naive implementation would require storing one 32 bit otag for
2104 each byte of memory covered, a 4:1 space overhead. Instead, there
2105 is one otag for every 4 bytes of memory covered, plus a 4-bit mask
2106 that shows which of the 4 bytes have that shadow value and which
2107 have a shadow value of zero (indicating no origin). Hence a lot of
2108 space is saved, but the cost is that only one different origin per
2109 4 bytes of address space can be represented. This is a source of
2110 imprecision, but how much of a problem it really is remains to be
2111 seen.
2112
2113 A cache line that contains all zeroes ("no origins") contains no
2114 useful information, and can be ejected from the L1 cache "for
2115 free", in the sense that a read miss on the L1 causes a line of
2116 zeroes to be installed. However, ejecting a line containing
2117 nonzeroes risks losing origin information permanently. In order to
2118 prevent such lossage, ejected nonzero lines are placed in a
2119 secondary cache (ocacheL2), which is an OSet (AVL tree) of cache
2120 lines. This can grow arbitrarily large, and so should ensure that
2121 Memcheck runs out of memory in preference to losing useful origin
2122 info due to cache size limitations.
2123
2124 Shadowing registers is a bit tricky, because the shadow values are
2125 32 bits, regardless of the size of the register. That gives a
2126 problem for registers smaller than 32 bits. The solution is to
2127 find spaces in the guest state that are unused, and use those to
2128 shadow guest state fragments smaller than 32 bits. For example, on
2129 ppc32/64, each vector register is 16 bytes long. If 4 bytes of the
2130 shadow are allocated for the register's otag, then there are still
2131 12 bytes left over which could be used to shadow 3 other values.
2132
2133 This implies there is some non-obvious mapping from guest state
2134 (start,length) pairs to the relevant shadow offset (for the origin
2135 tags). And it is unfortunately guest-architecture specific. The
2136 mapping is contained in mc_machine.c, which is quite lengthy but
2137 straightforward.
2138
2139 Instrumenting the IR
2140 ~~~~~~~~~~~~~~~~~~~~
2141
2142 Instrumentation is largely straightforward, and done by the
2143 functions schemeE and schemeS in mc_translate.c. These generate
2144 code for handling the origin tags of expressions (E) and statements
2145 (S) respectively. The rather strange names are a reference to the
2146 "compilation schemes" shown in Simon Peyton Jones' book "The
2147 Implementation of Functional Programming Languages" (Prentice Hall,
2148 1987, see
2149 http://research.microsoft.com/~simonpj/papers/slpj-book-1987/index.htm).
2150
2151 schemeS merely arranges to move shadow values around the guest
2152 state to track the incoming IR. schemeE is largely trivial too.
2153 The only significant point is how to compute the otag corresponding
2154 to binary (or ternary, quaternary, etc) operator applications. The
2155 rule is simple: just take whichever value is larger (32-bit
2156 unsigned max). Constants get the special value zero. Hence this
2157 rule always propagates a nonzero (known) otag in preference to a
2158 zero (unknown, or more likely, value-is-defined) tag, as we want.
2159 If two different undefined values are inputs to a binary operator
2160 application, then which is propagated is arbitrary, but that
2161 doesn't matter, since the program is erroneous in using either of
2162 the values, and so there's no point in attempting to propagate
2163 both.
2164
2165 Since constants are abstracted to (otag) zero, much of the
2166 instrumentation code can be folded out without difficulty by the
2167 generic post-instrumentation IR cleanup pass, using these rules:
2168 Max32U(0,x) -> x, Max32U(x,0) -> x, Max32(x,y) where x and y are
2169 constants is evaluated at JIT time. And the resulting dead code
2170 removal. In practice this causes surprisingly few Max32Us to
2171 survive through to backend code generation.
2172
2173 Integration with the V-bits machinery
2174 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2175
2176 This is again largely straightforward. Mostly the otag and V bits
2177 stuff are independent. The only point of interaction is when the V
2178 bits instrumenter creates a call to a helper function to report an
2179 uninitialised value error -- in that case it must first use schemeE
2180 to get hold of the origin tag expression for the value, and pass
2181 that to the helper too.
2182
2183 There is the usual stuff to do with setting address range
2184 permissions. When memory is painted undefined, we must also know
2185 the origin tag to paint with, which involves some tedious plumbing,
2186 particularly to do with the fast case stack handlers. When memory
2187 is painted defined or noaccess then the origin tags must be forced
2188 to zero.
2189
2190 One of the goals of the implementation was to ensure that the
2191 non-origin tracking mode isn't slowed down at all. To do this,
2192 various functions to do with memory permissions setting (again,
2193 mostly pertaining to the stack) are duplicated for the with- and
2194 without-otag case.
2195
2196 Dealing with stack redzones, and the NIA cache
2197 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2198
2199 This is one of the few non-obvious parts of the implementation.
2200
2201 Some ABIs (amd64-ELF, ppc64-ELF, ppc32/64-XCOFF) define a small
2202 reserved area below the stack pointer, that can be used as scratch
2203 space by compiler generated code for functions. In the Memcheck
2204 sources this is referred to as the "stack redzone". The important
2205 thing here is that such redzones are considered volatile across
2206 function calls and returns. So Memcheck takes care to mark them as
2207 undefined for each call and return, on the afflicted platforms.
2208 Past experience shows this is essential in order to get reliable
2209 messages about uninitialised values that come from the stack.
2210
2211 So the question is, when we paint a redzone undefined, what origin
2212 tag should we use for it? Consider a function f() calling g(). If
2213 we paint the redzone using an otag derived from the ExeContext of
2214 the CALL/BL instruction in f, then any errors in g causing it to
2215 use uninitialised values that happen to lie in the redzone, will be
2216 reported as having their origin in f. Which is highly confusing.
2217
2218 The same applies for returns: if, on a return, we paint the redzone
2219 using a origin tag derived from the ExeContext of the RET/BLR
2220 instruction in g, then any later errors in f causing it to use
2221 uninitialised values in the redzone, will be reported as having
2222 their origin in g. Which is just as confusing.
2223
2224 To do it right, in both cases we need to use an origin tag which
2225 pertains to the instruction which dynamically follows the CALL/BL
2226 or RET/BLR. In short, one derived from the NIA - the "next
2227 instruction address".
2228
2229 To make this work, Memcheck's redzone-painting helper,
2230 MC_(helperc_MAKE_STACK_UNINIT), now takes a third argument, the
2231 NIA. It converts the NIA to a 1-element ExeContext, and uses that
2232 ExeContext's ECU as the basis for the otag used to paint the
2233 redzone. The expensive part of this is converting an NIA into an
2234 ECU, since this happens once for every call and every return. So
2235 we use a simple 511-line, 2-way set associative cache
2236 (nia_to_ecu_cache) to cache the mappings, and that knocks most of
2237 the cost out.
2238
2239 Further background comments
2240 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
sewardj7cf4e6b2008-05-01 20:24:26 +00002241
2242 > Question: why is otag a UInt? Wouldn't a UWord be better? Isn't
2243 > it really just the address of the relevant ExeContext?
2244
2245 Well, it's not the address, but a value which has a 1-1 mapping
2246 with ExeContexts, and is guaranteed not to be zero, since zero
2247 denotes (to memcheck) "unknown origin or defined value". So these
sewardj77139802008-05-05 09:48:56 +00002248 UInts are just numbers starting at 4 and incrementing by 4; each
2249 ExeContext is given a number when it is created. (*** NOTE this
2250 confuses otags and ECUs; see comments above ***).
sewardj7cf4e6b2008-05-01 20:24:26 +00002251
2252 Making these otags 32-bit regardless of the machine's word size
2253 makes the 64-bit implementation easier (next para). And it doesn't
2254 really limit us in any way, since for the tags to overflow would
sewardj77139802008-05-05 09:48:56 +00002255 require that the program somehow caused 2^30-1 different
sewardj7cf4e6b2008-05-01 20:24:26 +00002256 ExeContexts to be created, in which case it is probably in deep
2257 trouble. Not to mention V will have soaked up many tens of
2258 gigabytes of memory merely to store them all.
2259
2260 So having 64-bit origins doesn't really buy you anything, and has
2261 the following downsides:
2262
2263 Suppose that instead, an otag is a UWord. This would mean that, on
2264 a 64-bit target,
2265
2266 1. It becomes hard to shadow any element of guest state which is
2267 smaller than 8 bytes. To do so means you'd need to find some
2268 8-byte-sized hole in the guest state which you don't want to
2269 shadow, and use that instead to hold the otag. On ppc64, the
2270 condition code register(s) are split into 20 UChar sized pieces,
2271 all of which need to be tracked (guest_XER_SO .. guest_CR7_0)
2272 and so that would entail finding 160 bytes somewhere else in the
2273 guest state.
2274
2275 Even on x86, I want to track origins for %AH .. %DH (bits 15:8
2276 of %EAX .. %EDX) that are separate from %AL .. %DL (bits 7:0 of
2277 same) and so I had to look for 4 untracked otag-sized areas in
2278 the guest state to make that possible.
2279
2280 The same problem exists of course when origin tags are only 32
2281 bits, but it's less extreme.
2282
2283 2. (More compelling) it doubles the size of the origin shadow
2284 memory. Given that the shadow memory is organised as a fixed
2285 size cache, and that accuracy of tracking is limited by origins
2286 falling out the cache due to space conflicts, this isn't good.
2287
2288 > Another question: is the origin tracking perfect, or are there
2289 > cases where it fails to determine an origin?
2290
2291 It is imperfect for at least for the following reasons, and
2292 probably more:
2293
2294 * Insufficient capacity in the origin cache. When a line is
2295 evicted from the cache it is gone forever, and so subsequent
2296 queries for the line produce zero, indicating no origin
2297 information. Interestingly, a line containing all zeroes can be
2298 evicted "free" from the cache, since it contains no useful
2299 information, so there is scope perhaps for some cleverer cache
sewardj77139802008-05-05 09:48:56 +00002300 management schemes. (*** NOTE, with the introduction of the
2301 second level origin tag cache, ocacheL2, this is no longer a
2302 problem. ***)
sewardj7cf4e6b2008-05-01 20:24:26 +00002303
2304 * The origin cache only stores one otag per 32-bits of address
2305 space, plus 4 bits indicating which of the 4 bytes has that tag
2306 and which are considered defined. The result is that if two
2307 undefined bytes in the same word are stored in memory, the first
2308 stored byte's origin will be lost and replaced by the origin for
2309 the second byte.
2310
2311 * Nonzero origin tags for defined values. Consider a binary
2312 operator application op(x,y). Suppose y is undefined (and so has
2313 a valid nonzero origin tag), and x is defined, but erroneously
2314 has a nonzero origin tag (defined values should have tag zero).
2315 If the erroneous tag has a numeric value greater than y's tag,
2316 then the rule for propagating origin tags though binary
2317 operations, which is simply to take the unsigned max of the two
2318 tags, will erroneously propagate x's tag rather than y's.
2319
2320 * Some obscure uses of x86/amd64 byte registers can cause lossage
2321 or confusion of origins. %AH .. %DH are treated as different
2322 from, and unrelated to, their parent registers, %EAX .. %EDX.
florianad4e9792015-07-05 21:53:33 +00002323 So some weird sequences like
sewardj7cf4e6b2008-05-01 20:24:26 +00002324
2325 movb undefined-value, %AH
2326 movb defined-value, %AL
2327 .. use %AX or %EAX ..
2328
2329 will cause the origin attributed to %AH to be ignored, since %AL,
2330 %AX, %EAX are treated as the same register, and %AH as a
2331 completely separate one.
2332
2333 But having said all that, it actually seems to work fairly well in
2334 practice.
2335*/
2336
2337static UWord stats_ocacheL1_find = 0;
2338static UWord stats_ocacheL1_found_at_1 = 0;
2339static UWord stats_ocacheL1_found_at_N = 0;
2340static UWord stats_ocacheL1_misses = 0;
2341static UWord stats_ocacheL1_lossage = 0;
2342static UWord stats_ocacheL1_movefwds = 0;
2343
2344static UWord stats__ocacheL2_refs = 0;
2345static UWord stats__ocacheL2_misses = 0;
2346static UWord stats__ocacheL2_n_nodes_max = 0;
2347
2348/* Cache of 32-bit values, one every 32 bits of address space */
2349
2350#define OC_BITS_PER_LINE 5
2351#define OC_W32S_PER_LINE (1 << (OC_BITS_PER_LINE - 2))
2352
2353static INLINE UWord oc_line_offset ( Addr a ) {
2354 return (a >> 2) & (OC_W32S_PER_LINE - 1);
2355}
2356static INLINE Bool is_valid_oc_tag ( Addr tag ) {
2357 return 0 == (tag & ((1 << OC_BITS_PER_LINE) - 1));
2358}
2359
2360#define OC_LINES_PER_SET 2
2361
2362#define OC_N_SET_BITS 20
2363#define OC_N_SETS (1 << OC_N_SET_BITS)
2364
2365/* These settings give:
2366 64 bit host: ocache: 100,663,296 sizeB 67,108,864 useful
2367 32 bit host: ocache: 92,274,688 sizeB 67,108,864 useful
2368*/
2369
2370#define OC_MOVE_FORWARDS_EVERY_BITS 7
2371
2372
2373typedef
2374 struct {
2375 Addr tag;
2376 UInt w32[OC_W32S_PER_LINE];
2377 UChar descr[OC_W32S_PER_LINE];
2378 }
2379 OCacheLine;
2380
2381/* Classify and also sanity-check 'line'. Return 'e' (empty) if not
2382 in use, 'n' (nonzero) if it contains at least one valid origin tag,
2383 and 'z' if all the represented tags are zero. */
2384static UChar classify_OCacheLine ( OCacheLine* line )
2385{
2386 UWord i;
2387 if (line->tag == 1/*invalid*/)
2388 return 'e'; /* EMPTY */
2389 tl_assert(is_valid_oc_tag(line->tag));
2390 for (i = 0; i < OC_W32S_PER_LINE; i++) {
2391 tl_assert(0 == ((~0xF) & line->descr[i]));
2392 if (line->w32[i] > 0 && line->descr[i] > 0)
2393 return 'n'; /* NONZERO - contains useful info */
2394 }
2395 return 'z'; /* ZERO - no useful info */
2396}
2397
2398typedef
2399 struct {
2400 OCacheLine line[OC_LINES_PER_SET];
2401 }
2402 OCacheSet;
2403
2404typedef
2405 struct {
2406 OCacheSet set[OC_N_SETS];
2407 }
2408 OCache;
2409
sewardj77139802008-05-05 09:48:56 +00002410static OCache* ocacheL1 = NULL;
2411static UWord ocacheL1_event_ctr = 0;
sewardj7cf4e6b2008-05-01 20:24:26 +00002412
2413static void init_ocacheL2 ( void ); /* fwds */
2414static void init_OCache ( void )
2415{
2416 UWord line, set;
sewardj9d624d12008-05-02 13:35:29 +00002417 tl_assert(MC_(clo_mc_level) >= 3);
sewardj77139802008-05-05 09:48:56 +00002418 tl_assert(ocacheL1 == NULL);
2419 ocacheL1 = VG_(am_shadow_alloc)(sizeof(OCache));
2420 if (ocacheL1 == NULL) {
2421 VG_(out_of_memory_NORETURN)( "memcheck:allocating ocacheL1",
sewardj9d624d12008-05-02 13:35:29 +00002422 sizeof(OCache) );
2423 }
sewardj77139802008-05-05 09:48:56 +00002424 tl_assert(ocacheL1 != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +00002425 for (set = 0; set < OC_N_SETS; set++) {
2426 for (line = 0; line < OC_LINES_PER_SET; line++) {
sewardj77139802008-05-05 09:48:56 +00002427 ocacheL1->set[set].line[line].tag = 1/*invalid*/;
sewardj7cf4e6b2008-05-01 20:24:26 +00002428 }
2429 }
2430 init_ocacheL2();
2431}
2432
2433static void moveLineForwards ( OCacheSet* set, UWord lineno )
2434{
2435 OCacheLine tmp;
2436 stats_ocacheL1_movefwds++;
2437 tl_assert(lineno > 0 && lineno < OC_LINES_PER_SET);
2438 tmp = set->line[lineno-1];
2439 set->line[lineno-1] = set->line[lineno];
2440 set->line[lineno] = tmp;
2441}
2442
2443static void zeroise_OCacheLine ( OCacheLine* line, Addr tag ) {
2444 UWord i;
2445 for (i = 0; i < OC_W32S_PER_LINE; i++) {
2446 line->w32[i] = 0; /* NO ORIGIN */
2447 line->descr[i] = 0; /* REALLY REALLY NO ORIGIN! */
2448 }
2449 line->tag = tag;
2450}
2451
2452//////////////////////////////////////////////////////////////
2453//// OCache backing store
2454
2455static OSet* ocacheL2 = NULL;
2456
florian54fe2022012-10-27 23:07:42 +00002457static void* ocacheL2_malloc ( const HChar* cc, SizeT szB ) {
sewardj9c606bd2008-09-18 18:12:50 +00002458 return VG_(malloc)(cc, szB);
sewardj7cf4e6b2008-05-01 20:24:26 +00002459}
2460static void ocacheL2_free ( void* v ) {
2461 VG_(free)( v );
2462}
2463
2464/* Stats: # nodes currently in tree */
2465static UWord stats__ocacheL2_n_nodes = 0;
2466
2467static void init_ocacheL2 ( void )
2468{
2469 tl_assert(!ocacheL2);
2470 tl_assert(sizeof(Word) == sizeof(Addr)); /* since OCacheLine.tag :: Addr */
2471 tl_assert(0 == offsetof(OCacheLine,tag));
2472 ocacheL2
2473 = VG_(OSetGen_Create)( offsetof(OCacheLine,tag),
2474 NULL, /* fast cmp */
philippe6643e962012-01-17 21:16:30 +00002475 ocacheL2_malloc, "mc.ioL2", ocacheL2_free);
sewardj7cf4e6b2008-05-01 20:24:26 +00002476 stats__ocacheL2_n_nodes = 0;
2477}
2478
2479/* Find line with the given tag in the tree, or NULL if not found. */
2480static OCacheLine* ocacheL2_find_tag ( Addr tag )
2481{
2482 OCacheLine* line;
2483 tl_assert(is_valid_oc_tag(tag));
2484 stats__ocacheL2_refs++;
2485 line = VG_(OSetGen_Lookup)( ocacheL2, &tag );
2486 return line;
2487}
2488
2489/* Delete the line with the given tag from the tree, if it is present, and
2490 free up the associated memory. */
2491static void ocacheL2_del_tag ( Addr tag )
2492{
2493 OCacheLine* line;
2494 tl_assert(is_valid_oc_tag(tag));
2495 stats__ocacheL2_refs++;
2496 line = VG_(OSetGen_Remove)( ocacheL2, &tag );
2497 if (line) {
2498 VG_(OSetGen_FreeNode)(ocacheL2, line);
2499 tl_assert(stats__ocacheL2_n_nodes > 0);
2500 stats__ocacheL2_n_nodes--;
2501 }
2502}
2503
2504/* Add a copy of the given line to the tree. It must not already be
2505 present. */
2506static void ocacheL2_add_line ( OCacheLine* line )
2507{
2508 OCacheLine* copy;
2509 tl_assert(is_valid_oc_tag(line->tag));
2510 copy = VG_(OSetGen_AllocNode)( ocacheL2, sizeof(OCacheLine) );
sewardj7cf4e6b2008-05-01 20:24:26 +00002511 *copy = *line;
2512 stats__ocacheL2_refs++;
2513 VG_(OSetGen_Insert)( ocacheL2, copy );
2514 stats__ocacheL2_n_nodes++;
2515 if (stats__ocacheL2_n_nodes > stats__ocacheL2_n_nodes_max)
2516 stats__ocacheL2_n_nodes_max = stats__ocacheL2_n_nodes;
2517}
2518
2519////
2520//////////////////////////////////////////////////////////////
2521
2522__attribute__((noinline))
2523static OCacheLine* find_OCacheLine_SLOW ( Addr a )
2524{
2525 OCacheLine *victim, *inL2;
2526 UChar c;
2527 UWord line;
2528 UWord setno = (a >> OC_BITS_PER_LINE) & (OC_N_SETS - 1);
2529 UWord tagmask = ~((1 << OC_BITS_PER_LINE) - 1);
2530 UWord tag = a & tagmask;
2531 tl_assert(setno >= 0 && setno < OC_N_SETS);
2532
2533 /* we already tried line == 0; skip therefore. */
2534 for (line = 1; line < OC_LINES_PER_SET; line++) {
sewardj77139802008-05-05 09:48:56 +00002535 if (ocacheL1->set[setno].line[line].tag == tag) {
sewardj7cf4e6b2008-05-01 20:24:26 +00002536 if (line == 1) {
2537 stats_ocacheL1_found_at_1++;
2538 } else {
2539 stats_ocacheL1_found_at_N++;
2540 }
sewardj77139802008-05-05 09:48:56 +00002541 if (UNLIKELY(0 == (ocacheL1_event_ctr++
sewardj7cf4e6b2008-05-01 20:24:26 +00002542 & ((1<<OC_MOVE_FORWARDS_EVERY_BITS)-1)))) {
sewardj77139802008-05-05 09:48:56 +00002543 moveLineForwards( &ocacheL1->set[setno], line );
sewardj7cf4e6b2008-05-01 20:24:26 +00002544 line--;
2545 }
sewardj77139802008-05-05 09:48:56 +00002546 return &ocacheL1->set[setno].line[line];
sewardj7cf4e6b2008-05-01 20:24:26 +00002547 }
2548 }
2549
2550 /* A miss. Use the last slot. Implicitly this means we're
2551 ejecting the line in the last slot. */
2552 stats_ocacheL1_misses++;
2553 tl_assert(line == OC_LINES_PER_SET);
2554 line--;
2555 tl_assert(line > 0);
2556
2557 /* First, move the to-be-ejected line to the L2 cache. */
sewardj77139802008-05-05 09:48:56 +00002558 victim = &ocacheL1->set[setno].line[line];
sewardj7cf4e6b2008-05-01 20:24:26 +00002559 c = classify_OCacheLine(victim);
2560 switch (c) {
2561 case 'e':
2562 /* the line is empty (has invalid tag); ignore it. */
2563 break;
2564 case 'z':
2565 /* line contains zeroes. We must ensure the backing store is
2566 updated accordingly, either by copying the line there
2567 verbatim, or by ensuring it isn't present there. We
2568 chosse the latter on the basis that it reduces the size of
2569 the backing store. */
2570 ocacheL2_del_tag( victim->tag );
2571 break;
2572 case 'n':
2573 /* line contains at least one real, useful origin. Copy it
2574 to the backing store. */
2575 stats_ocacheL1_lossage++;
2576 inL2 = ocacheL2_find_tag( victim->tag );
2577 if (inL2) {
2578 *inL2 = *victim;
2579 } else {
2580 ocacheL2_add_line( victim );
2581 }
2582 break;
2583 default:
2584 tl_assert(0);
2585 }
2586
2587 /* Now we must reload the L1 cache from the backing tree, if
2588 possible. */
2589 tl_assert(tag != victim->tag); /* stay sane */
2590 inL2 = ocacheL2_find_tag( tag );
2591 if (inL2) {
2592 /* We're in luck. It's in the L2. */
sewardj77139802008-05-05 09:48:56 +00002593 ocacheL1->set[setno].line[line] = *inL2;
sewardj7cf4e6b2008-05-01 20:24:26 +00002594 } else {
2595 /* Missed at both levels of the cache hierarchy. We have to
2596 declare it as full of zeroes (unknown origins). */
2597 stats__ocacheL2_misses++;
sewardj77139802008-05-05 09:48:56 +00002598 zeroise_OCacheLine( &ocacheL1->set[setno].line[line], tag );
sewardj7cf4e6b2008-05-01 20:24:26 +00002599 }
2600
2601 /* Move it one forwards */
sewardj77139802008-05-05 09:48:56 +00002602 moveLineForwards( &ocacheL1->set[setno], line );
sewardj7cf4e6b2008-05-01 20:24:26 +00002603 line--;
2604
sewardj77139802008-05-05 09:48:56 +00002605 return &ocacheL1->set[setno].line[line];
sewardj7cf4e6b2008-05-01 20:24:26 +00002606}
2607
2608static INLINE OCacheLine* find_OCacheLine ( Addr a )
2609{
2610 UWord setno = (a >> OC_BITS_PER_LINE) & (OC_N_SETS - 1);
2611 UWord tagmask = ~((1 << OC_BITS_PER_LINE) - 1);
2612 UWord tag = a & tagmask;
2613
2614 stats_ocacheL1_find++;
2615
2616 if (OC_ENABLE_ASSERTIONS) {
2617 tl_assert(setno >= 0 && setno < OC_N_SETS);
2618 tl_assert(0 == (tag & (4 * OC_W32S_PER_LINE - 1)));
2619 }
2620
sewardj77139802008-05-05 09:48:56 +00002621 if (LIKELY(ocacheL1->set[setno].line[0].tag == tag)) {
2622 return &ocacheL1->set[setno].line[0];
sewardj7cf4e6b2008-05-01 20:24:26 +00002623 }
2624
2625 return find_OCacheLine_SLOW( a );
2626}
2627
2628static INLINE void set_aligned_word64_Origin_to_undef ( Addr a, UInt otag )
2629{
2630 //// BEGIN inlined, specialised version of MC_(helperc_b_store8)
2631 //// Set the origins for a+0 .. a+7
2632 { OCacheLine* line;
2633 UWord lineoff = oc_line_offset(a);
2634 if (OC_ENABLE_ASSERTIONS) {
2635 tl_assert(lineoff >= 0
2636 && lineoff < OC_W32S_PER_LINE -1/*'cos 8-aligned*/);
2637 }
2638 line = find_OCacheLine( a );
2639 line->descr[lineoff+0] = 0xF;
2640 line->descr[lineoff+1] = 0xF;
2641 line->w32[lineoff+0] = otag;
2642 line->w32[lineoff+1] = otag;
2643 }
2644 //// END inlined, specialised version of MC_(helperc_b_store8)
2645}
2646
2647
2648/*------------------------------------------------------------*/
2649/*--- Aligned fast case permission setters, ---*/
2650/*--- for dealing with stacks ---*/
2651/*------------------------------------------------------------*/
2652
2653/*--------------------- 32-bit ---------------------*/
2654
2655/* Nb: by "aligned" here we mean 4-byte aligned */
2656
2657static INLINE void make_aligned_word32_undefined ( Addr a )
njn9b007f62003-04-07 14:40:25 +00002658{
florian60042192015-08-04 15:58:41 +00002659 PROF_EVENT(MCPE_MAKE_ALIGNED_WORD32_UNDEFINED);
sewardj5d28efc2005-04-21 22:16:29 +00002660
njn1d0825f2006-03-27 11:37:07 +00002661#ifndef PERF_FAST_STACK2
sewardj7cf4e6b2008-05-01 20:24:26 +00002662 make_mem_undefined(a, 4);
njn1d0825f2006-03-27 11:37:07 +00002663#else
njneccf7c02009-01-19 23:42:45 +00002664 {
2665 UWord sm_off;
2666 SecMap* sm;
sewardj5d28efc2005-04-21 22:16:29 +00002667
njneccf7c02009-01-19 23:42:45 +00002668 if (UNLIKELY(a > MAX_PRIMARY_ADDRESS)) {
florian60042192015-08-04 15:58:41 +00002669 PROF_EVENT(MCPE_MAKE_ALIGNED_WORD32_UNDEFINED_SLOW);
njneccf7c02009-01-19 23:42:45 +00002670 make_mem_undefined(a, 4);
2671 return;
2672 }
2673
2674 sm = get_secmap_for_writing_low(a);
2675 sm_off = SM_OFF(a);
2676 sm->vabits8[sm_off] = VA_BITS8_UNDEFINED;
2677 }
njn1d0825f2006-03-27 11:37:07 +00002678#endif
njn9b007f62003-04-07 14:40:25 +00002679}
2680
sewardj7cf4e6b2008-05-01 20:24:26 +00002681static INLINE
2682void make_aligned_word32_undefined_w_otag ( Addr a, UInt otag )
2683{
2684 make_aligned_word32_undefined(a);
2685 //// BEGIN inlined, specialised version of MC_(helperc_b_store4)
2686 //// Set the origins for a+0 .. a+3
2687 { OCacheLine* line;
2688 UWord lineoff = oc_line_offset(a);
2689 if (OC_ENABLE_ASSERTIONS) {
2690 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
2691 }
2692 line = find_OCacheLine( a );
2693 line->descr[lineoff] = 0xF;
2694 line->w32[lineoff] = otag;
2695 }
2696 //// END inlined, specialised version of MC_(helperc_b_store4)
2697}
sewardj5d28efc2005-04-21 22:16:29 +00002698
njn1d0825f2006-03-27 11:37:07 +00002699static INLINE
2700void make_aligned_word32_noaccess ( Addr a )
sewardj5d28efc2005-04-21 22:16:29 +00002701{
florian60042192015-08-04 15:58:41 +00002702 PROF_EVENT(MCPE_MAKE_ALIGNED_WORD32_NOACCESS);
sewardj5d28efc2005-04-21 22:16:29 +00002703
njn1d0825f2006-03-27 11:37:07 +00002704#ifndef PERF_FAST_STACK2
njndbf7ca72006-03-31 11:57:59 +00002705 MC_(make_mem_noaccess)(a, 4);
njn1d0825f2006-03-27 11:37:07 +00002706#else
njneccf7c02009-01-19 23:42:45 +00002707 {
2708 UWord sm_off;
2709 SecMap* sm;
sewardj5d28efc2005-04-21 22:16:29 +00002710
njneccf7c02009-01-19 23:42:45 +00002711 if (UNLIKELY(a > MAX_PRIMARY_ADDRESS)) {
florian60042192015-08-04 15:58:41 +00002712 PROF_EVENT(MCPE_MAKE_ALIGNED_WORD32_NOACCESS_SLOW);
njneccf7c02009-01-19 23:42:45 +00002713 MC_(make_mem_noaccess)(a, 4);
2714 return;
sewardj7cf4e6b2008-05-01 20:24:26 +00002715 }
njneccf7c02009-01-19 23:42:45 +00002716
2717 sm = get_secmap_for_writing_low(a);
2718 sm_off = SM_OFF(a);
2719 sm->vabits8[sm_off] = VA_BITS8_NOACCESS;
2720
2721 //// BEGIN inlined, specialised version of MC_(helperc_b_store4)
2722 //// Set the origins for a+0 .. a+3.
2723 if (UNLIKELY( MC_(clo_mc_level) == 3 )) {
2724 OCacheLine* line;
2725 UWord lineoff = oc_line_offset(a);
2726 if (OC_ENABLE_ASSERTIONS) {
2727 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
2728 }
2729 line = find_OCacheLine( a );
2730 line->descr[lineoff] = 0;
2731 }
2732 //// END inlined, specialised version of MC_(helperc_b_store4)
sewardj7cf4e6b2008-05-01 20:24:26 +00002733 }
njn1d0825f2006-03-27 11:37:07 +00002734#endif
sewardj5d28efc2005-04-21 22:16:29 +00002735}
2736
sewardj7cf4e6b2008-05-01 20:24:26 +00002737/*--------------------- 64-bit ---------------------*/
sewardj5d28efc2005-04-21 22:16:29 +00002738
njn9b007f62003-04-07 14:40:25 +00002739/* Nb: by "aligned" here we mean 8-byte aligned */
sewardj7cf4e6b2008-05-01 20:24:26 +00002740
2741static INLINE void make_aligned_word64_undefined ( Addr a )
njn9b007f62003-04-07 14:40:25 +00002742{
florian60042192015-08-04 15:58:41 +00002743 PROF_EVENT(MCPE_MAKE_ALIGNED_WORD64_UNDEFINED);
sewardj23eb2fd2005-04-22 16:29:19 +00002744
njn1d0825f2006-03-27 11:37:07 +00002745#ifndef PERF_FAST_STACK2
sewardj7cf4e6b2008-05-01 20:24:26 +00002746 make_mem_undefined(a, 8);
njn1d0825f2006-03-27 11:37:07 +00002747#else
njneccf7c02009-01-19 23:42:45 +00002748 {
2749 UWord sm_off16;
2750 SecMap* sm;
sewardj23eb2fd2005-04-22 16:29:19 +00002751
njneccf7c02009-01-19 23:42:45 +00002752 if (UNLIKELY(a > MAX_PRIMARY_ADDRESS)) {
florian60042192015-08-04 15:58:41 +00002753 PROF_EVENT(MCPE_MAKE_ALIGNED_WORD64_UNDEFINED_SLOW);
njneccf7c02009-01-19 23:42:45 +00002754 make_mem_undefined(a, 8);
2755 return;
2756 }
2757
2758 sm = get_secmap_for_writing_low(a);
2759 sm_off16 = SM_OFF_16(a);
2760 ((UShort*)(sm->vabits8))[sm_off16] = VA_BITS16_UNDEFINED;
2761 }
njn1d0825f2006-03-27 11:37:07 +00002762#endif
njn9b007f62003-04-07 14:40:25 +00002763}
2764
sewardj7cf4e6b2008-05-01 20:24:26 +00002765static INLINE
2766void make_aligned_word64_undefined_w_otag ( Addr a, UInt otag )
2767{
2768 make_aligned_word64_undefined(a);
2769 //// BEGIN inlined, specialised version of MC_(helperc_b_store8)
2770 //// Set the origins for a+0 .. a+7
2771 { OCacheLine* line;
2772 UWord lineoff = oc_line_offset(a);
2773 tl_assert(lineoff >= 0
2774 && lineoff < OC_W32S_PER_LINE -1/*'cos 8-aligned*/);
2775 line = find_OCacheLine( a );
2776 line->descr[lineoff+0] = 0xF;
2777 line->descr[lineoff+1] = 0xF;
2778 line->w32[lineoff+0] = otag;
2779 line->w32[lineoff+1] = otag;
2780 }
2781 //// END inlined, specialised version of MC_(helperc_b_store8)
2782}
sewardj23eb2fd2005-04-22 16:29:19 +00002783
njn1d0825f2006-03-27 11:37:07 +00002784static INLINE
2785void make_aligned_word64_noaccess ( Addr a )
njn9b007f62003-04-07 14:40:25 +00002786{
florian60042192015-08-04 15:58:41 +00002787 PROF_EVENT(MCPE_MAKE_ALIGNED_WORD64_NOACCESS);
sewardj23eb2fd2005-04-22 16:29:19 +00002788
njn1d0825f2006-03-27 11:37:07 +00002789#ifndef PERF_FAST_STACK2
njndbf7ca72006-03-31 11:57:59 +00002790 MC_(make_mem_noaccess)(a, 8);
njn1d0825f2006-03-27 11:37:07 +00002791#else
njneccf7c02009-01-19 23:42:45 +00002792 {
2793 UWord sm_off16;
2794 SecMap* sm;
sewardj23eb2fd2005-04-22 16:29:19 +00002795
njneccf7c02009-01-19 23:42:45 +00002796 if (UNLIKELY(a > MAX_PRIMARY_ADDRESS)) {
florian60042192015-08-04 15:58:41 +00002797 PROF_EVENT(MCPE_MAKE_ALIGNED_WORD64_NOACCESS_SLOW);
njneccf7c02009-01-19 23:42:45 +00002798 MC_(make_mem_noaccess)(a, 8);
2799 return;
2800 }
sewardj7cf4e6b2008-05-01 20:24:26 +00002801
njneccf7c02009-01-19 23:42:45 +00002802 sm = get_secmap_for_writing_low(a);
2803 sm_off16 = SM_OFF_16(a);
2804 ((UShort*)(sm->vabits8))[sm_off16] = VA_BITS16_NOACCESS;
2805
2806 //// BEGIN inlined, specialised version of MC_(helperc_b_store8)
2807 //// Clear the origins for a+0 .. a+7.
2808 if (UNLIKELY( MC_(clo_mc_level) == 3 )) {
2809 OCacheLine* line;
2810 UWord lineoff = oc_line_offset(a);
2811 tl_assert(lineoff >= 0
2812 && lineoff < OC_W32S_PER_LINE -1/*'cos 8-aligned*/);
2813 line = find_OCacheLine( a );
2814 line->descr[lineoff+0] = 0;
2815 line->descr[lineoff+1] = 0;
2816 }
2817 //// END inlined, specialised version of MC_(helperc_b_store8)
sewardj7cf4e6b2008-05-01 20:24:26 +00002818 }
njn1d0825f2006-03-27 11:37:07 +00002819#endif
njn9b007f62003-04-07 14:40:25 +00002820}
2821
sewardj23eb2fd2005-04-22 16:29:19 +00002822
njn1d0825f2006-03-27 11:37:07 +00002823/*------------------------------------------------------------*/
2824/*--- Stack pointer adjustment ---*/
2825/*------------------------------------------------------------*/
2826
njneccf7c02009-01-19 23:42:45 +00002827#ifdef PERF_FAST_STACK
2828# define MAYBE_USED
2829#else
2830# define MAYBE_USED __attribute__((unused))
2831#endif
2832
sewardj7cf4e6b2008-05-01 20:24:26 +00002833/*--------------- adjustment by 4 bytes ---------------*/
2834
njneccf7c02009-01-19 23:42:45 +00002835MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00002836static void VG_REGPARM(2) mc_new_mem_stack_4_w_ECU(Addr new_SP, UInt ecu)
2837{
2838 UInt otag = ecu | MC_OKIND_STACK;
florian60042192015-08-04 15:58:41 +00002839 PROF_EVENT(MCPE_NEW_MEM_STACK_4);
sewardj7cf4e6b2008-05-01 20:24:26 +00002840 if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2841 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP, otag );
2842 } else {
2843 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 4, otag );
2844 }
2845}
2846
njneccf7c02009-01-19 23:42:45 +00002847MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002848static void VG_REGPARM(1) mc_new_mem_stack_4(Addr new_SP)
2849{
florian60042192015-08-04 15:58:41 +00002850 PROF_EVENT(MCPE_NEW_MEM_STACK_4);
sewardj05a46732006-10-17 01:28:10 +00002851 if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00002852 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
njn1d0825f2006-03-27 11:37:07 +00002853 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00002854 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 4 );
njn1d0825f2006-03-27 11:37:07 +00002855 }
2856}
2857
njneccf7c02009-01-19 23:42:45 +00002858MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002859static void VG_REGPARM(1) mc_die_mem_stack_4(Addr new_SP)
2860{
florian60042192015-08-04 15:58:41 +00002861 PROF_EVENT(MCPE_DIE_MEM_STACK_4);
sewardj05a46732006-10-17 01:28:10 +00002862 if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00002863 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-4 );
njn1d0825f2006-03-27 11:37:07 +00002864 } else {
njndbf7ca72006-03-31 11:57:59 +00002865 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-4, 4 );
njn1d0825f2006-03-27 11:37:07 +00002866 }
2867}
2868
sewardj7cf4e6b2008-05-01 20:24:26 +00002869/*--------------- adjustment by 8 bytes ---------------*/
2870
njneccf7c02009-01-19 23:42:45 +00002871MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00002872static void VG_REGPARM(2) mc_new_mem_stack_8_w_ECU(Addr new_SP, UInt ecu)
2873{
2874 UInt otag = ecu | MC_OKIND_STACK;
florian60042192015-08-04 15:58:41 +00002875 PROF_EVENT(MCPE_NEW_MEM_STACK_8);
sewardj7cf4e6b2008-05-01 20:24:26 +00002876 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2877 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP, otag );
2878 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2879 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
2880 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+4, otag );
2881 } else {
2882 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 8, otag );
2883 }
2884}
2885
njneccf7c02009-01-19 23:42:45 +00002886MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002887static void VG_REGPARM(1) mc_new_mem_stack_8(Addr new_SP)
2888{
florian60042192015-08-04 15:58:41 +00002889 PROF_EVENT(MCPE_NEW_MEM_STACK_8);
sewardj05a46732006-10-17 01:28:10 +00002890 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00002891 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
sewardj05a46732006-10-17 01:28:10 +00002892 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj7cf4e6b2008-05-01 20:24:26 +00002893 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
njndbf7ca72006-03-31 11:57:59 +00002894 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP+4 );
njn1d0825f2006-03-27 11:37:07 +00002895 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00002896 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 8 );
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_8(Addr new_SP)
2902{
florian60042192015-08-04 15:58:41 +00002903 PROF_EVENT(MCPE_DIE_MEM_STACK_8);
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-8 );
sewardj05a46732006-10-17 01:28:10 +00002906 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00002907 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-8 );
2908 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-4 );
njn1d0825f2006-03-27 11:37:07 +00002909 } else {
njndbf7ca72006-03-31 11:57:59 +00002910 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-8, 8 );
njn1d0825f2006-03-27 11:37:07 +00002911 }
2912}
2913
sewardj7cf4e6b2008-05-01 20:24:26 +00002914/*--------------- adjustment by 12 bytes ---------------*/
2915
njneccf7c02009-01-19 23:42:45 +00002916MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00002917static void VG_REGPARM(2) mc_new_mem_stack_12_w_ECU(Addr new_SP, UInt ecu)
2918{
2919 UInt otag = ecu | MC_OKIND_STACK;
florian60042192015-08-04 15:58:41 +00002920 PROF_EVENT(MCPE_NEW_MEM_STACK_12);
sewardj7cf4e6b2008-05-01 20:24:26 +00002921 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2922 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
2923 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+8, otag );
2924 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2925 /* from previous test we don't have 8-alignment at offset +0,
2926 hence must have 8 alignment at offsets +4/-4. Hence safe to
2927 do 4 at +0 and then 8 at +4/. */
2928 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
2929 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+4, otag );
2930 } else {
2931 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 12, otag );
2932 }
2933}
2934
njneccf7c02009-01-19 23:42:45 +00002935MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002936static void VG_REGPARM(1) mc_new_mem_stack_12(Addr new_SP)
2937{
florian60042192015-08-04 15:58:41 +00002938 PROF_EVENT(MCPE_NEW_MEM_STACK_12);
sewardj05a46732006-10-17 01:28:10 +00002939 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj7cf4e6b2008-05-01 20:24:26 +00002940 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
njndbf7ca72006-03-31 11:57:59 +00002941 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 );
sewardj05a46732006-10-17 01:28:10 +00002942 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00002943 /* from previous test we don't have 8-alignment at offset +0,
2944 hence must have 8 alignment at offsets +4/-4. Hence safe to
2945 do 4 at +0 and then 8 at +4/. */
sewardj7cf4e6b2008-05-01 20:24:26 +00002946 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
njndbf7ca72006-03-31 11:57:59 +00002947 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+4 );
njn1d0825f2006-03-27 11:37:07 +00002948 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00002949 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 12 );
njn1d0825f2006-03-27 11:37:07 +00002950 }
2951}
2952
njneccf7c02009-01-19 23:42:45 +00002953MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002954static void VG_REGPARM(1) mc_die_mem_stack_12(Addr new_SP)
2955{
florian60042192015-08-04 15:58:41 +00002956 PROF_EVENT(MCPE_DIE_MEM_STACK_12);
njn1d0825f2006-03-27 11:37:07 +00002957 /* Note the -12 in the test */
sewardj43fcfd92006-10-17 23:14:42 +00002958 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP-12 )) {
2959 /* We have 8-alignment at -12, hence ok to do 8 at -12 and 4 at
2960 -4. */
njndbf7ca72006-03-31 11:57:59 +00002961 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-12 );
2962 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-4 );
sewardj05a46732006-10-17 01:28:10 +00002963 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00002964 /* We have 4-alignment at +0, but we don't have 8-alignment at
2965 -12. So we must have 8-alignment at -8. Hence do 4 at -12
2966 and then 8 at -8. */
njndbf7ca72006-03-31 11:57:59 +00002967 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-12 );
2968 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-8 );
njn1d0825f2006-03-27 11:37:07 +00002969 } else {
njndbf7ca72006-03-31 11:57:59 +00002970 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-12, 12 );
njn1d0825f2006-03-27 11:37:07 +00002971 }
2972}
2973
sewardj7cf4e6b2008-05-01 20:24:26 +00002974/*--------------- adjustment by 16 bytes ---------------*/
2975
njneccf7c02009-01-19 23:42:45 +00002976MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00002977static void VG_REGPARM(2) mc_new_mem_stack_16_w_ECU(Addr new_SP, UInt ecu)
2978{
2979 UInt otag = ecu | MC_OKIND_STACK;
florian60042192015-08-04 15:58:41 +00002980 PROF_EVENT(MCPE_NEW_MEM_STACK_16);
sewardj7cf4e6b2008-05-01 20:24:26 +00002981 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2982 /* Have 8-alignment at +0, hence do 8 at +0 and 8 at +8. */
2983 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
2984 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+8, otag );
2985 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
2986 /* Have 4 alignment at +0 but not 8; hence 8 must be at +4.
2987 Hence do 4 at +0, 8 at +4, 4 at +12. */
2988 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
2989 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+4 , otag );
2990 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+12, otag );
2991 } else {
2992 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 16, otag );
2993 }
2994}
2995
njneccf7c02009-01-19 23:42:45 +00002996MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00002997static void VG_REGPARM(1) mc_new_mem_stack_16(Addr new_SP)
2998{
florian60042192015-08-04 15:58:41 +00002999 PROF_EVENT(MCPE_NEW_MEM_STACK_16);
sewardj05a46732006-10-17 01:28:10 +00003000 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00003001 /* Have 8-alignment at +0, hence do 8 at +0 and 8 at +8. */
sewardj7cf4e6b2008-05-01 20:24:26 +00003002 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
njndbf7ca72006-03-31 11:57:59 +00003003 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 );
sewardj05a46732006-10-17 01:28:10 +00003004 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00003005 /* Have 4 alignment at +0 but not 8; hence 8 must be at +4.
3006 Hence do 4 at +0, 8 at +4, 4 at +12. */
sewardj7cf4e6b2008-05-01 20:24:26 +00003007 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
njndbf7ca72006-03-31 11:57:59 +00003008 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+4 );
3009 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP+12 );
njn1d0825f2006-03-27 11:37:07 +00003010 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00003011 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 16 );
njn1d0825f2006-03-27 11:37:07 +00003012 }
3013}
3014
njneccf7c02009-01-19 23:42:45 +00003015MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00003016static void VG_REGPARM(1) mc_die_mem_stack_16(Addr new_SP)
3017{
florian60042192015-08-04 15:58:41 +00003018 PROF_EVENT(MCPE_DIE_MEM_STACK_16);
sewardj05a46732006-10-17 01:28:10 +00003019 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00003020 /* Have 8-alignment at +0, hence do 8 at -16 and 8 at -8. */
njndbf7ca72006-03-31 11:57:59 +00003021 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 );
3022 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-8 );
sewardj05a46732006-10-17 01:28:10 +00003023 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00003024 /* 8 alignment must be at -12. Do 4 at -16, 8 at -12, 4 at -4. */
njndbf7ca72006-03-31 11:57:59 +00003025 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 );
3026 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-12 );
3027 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-4 );
njn1d0825f2006-03-27 11:37:07 +00003028 } else {
njndbf7ca72006-03-31 11:57:59 +00003029 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-16, 16 );
njn1d0825f2006-03-27 11:37:07 +00003030 }
3031}
3032
sewardj7cf4e6b2008-05-01 20:24:26 +00003033/*--------------- adjustment by 32 bytes ---------------*/
3034
njneccf7c02009-01-19 23:42:45 +00003035MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00003036static void VG_REGPARM(2) mc_new_mem_stack_32_w_ECU(Addr new_SP, UInt ecu)
3037{
3038 UInt otag = ecu | MC_OKIND_STACK;
florian60042192015-08-04 15:58:41 +00003039 PROF_EVENT(MCPE_NEW_MEM_STACK_32);
sewardj7cf4e6b2008-05-01 20:24:26 +00003040 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
3041 /* Straightforward */
3042 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
3043 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+8 , otag );
3044 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+16, otag );
3045 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+24, otag );
3046 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
3047 /* 8 alignment must be at +4. Hence do 8 at +4,+12,+20 and 4 at
3048 +0,+28. */
3049 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
3050 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+4 , otag );
3051 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+12, otag );
3052 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+20, otag );
3053 make_aligned_word32_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+28, otag );
3054 } else {
3055 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 32, otag );
3056 }
3057}
3058
njneccf7c02009-01-19 23:42:45 +00003059MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00003060static void VG_REGPARM(1) mc_new_mem_stack_32(Addr new_SP)
3061{
florian60042192015-08-04 15:58:41 +00003062 PROF_EVENT(MCPE_NEW_MEM_STACK_32);
sewardj05a46732006-10-17 01:28:10 +00003063 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00003064 /* Straightforward */
sewardj7cf4e6b2008-05-01 20:24:26 +00003065 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
3066 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 );
njndbf7ca72006-03-31 11:57:59 +00003067 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+16 );
3068 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+24 );
sewardj05a46732006-10-17 01:28:10 +00003069 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00003070 /* 8 alignment must be at +4. Hence do 8 at +4,+12,+20 and 4 at
3071 +0,+28. */
sewardj7cf4e6b2008-05-01 20:24:26 +00003072 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
3073 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+4 );
njndbf7ca72006-03-31 11:57:59 +00003074 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+12 );
3075 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+20 );
3076 make_aligned_word32_undefined ( -VG_STACK_REDZONE_SZB + new_SP+28 );
njn1d0825f2006-03-27 11:37:07 +00003077 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00003078 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 32 );
njn1d0825f2006-03-27 11:37:07 +00003079 }
3080}
3081
njneccf7c02009-01-19 23:42:45 +00003082MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00003083static void VG_REGPARM(1) mc_die_mem_stack_32(Addr new_SP)
3084{
florian60042192015-08-04 15:58:41 +00003085 PROF_EVENT(MCPE_DIE_MEM_STACK_32);
sewardj05a46732006-10-17 01:28:10 +00003086 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00003087 /* Straightforward */
njndbf7ca72006-03-31 11:57:59 +00003088 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-32 );
3089 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-24 );
3090 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 );
3091 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP- 8 );
sewardj05a46732006-10-17 01:28:10 +00003092 } else if (VG_IS_4_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj43fcfd92006-10-17 23:14:42 +00003093 /* 8 alignment must be at -4 etc. Hence do 8 at -12,-20,-28 and
3094 4 at -32,-4. */
njndbf7ca72006-03-31 11:57:59 +00003095 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-32 );
3096 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-28 );
3097 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-20 );
3098 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-12 );
3099 make_aligned_word32_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-4 );
njn1d0825f2006-03-27 11:37:07 +00003100 } else {
njndbf7ca72006-03-31 11:57:59 +00003101 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-32, 32 );
njn1d0825f2006-03-27 11:37:07 +00003102 }
3103}
3104
sewardj7cf4e6b2008-05-01 20:24:26 +00003105/*--------------- adjustment by 112 bytes ---------------*/
3106
njneccf7c02009-01-19 23:42:45 +00003107MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00003108static void VG_REGPARM(2) mc_new_mem_stack_112_w_ECU(Addr new_SP, UInt ecu)
3109{
3110 UInt otag = ecu | MC_OKIND_STACK;
florian60042192015-08-04 15:58:41 +00003111 PROF_EVENT(MCPE_NEW_MEM_STACK_112);
sewardj7cf4e6b2008-05-01 20:24:26 +00003112 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
3113 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
3114 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+8 , otag );
3115 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+16, otag );
3116 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+24, otag );
3117 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+32, otag );
3118 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+40, otag );
3119 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+48, otag );
3120 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+56, otag );
3121 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+64, otag );
3122 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+72, otag );
3123 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+80, otag );
3124 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+88, otag );
3125 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+96, otag );
3126 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+104, otag );
3127 } else {
3128 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 112, otag );
3129 }
3130}
3131
njneccf7c02009-01-19 23:42:45 +00003132MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00003133static void VG_REGPARM(1) mc_new_mem_stack_112(Addr new_SP)
3134{
florian60042192015-08-04 15:58:41 +00003135 PROF_EVENT(MCPE_NEW_MEM_STACK_112);
sewardj05a46732006-10-17 01:28:10 +00003136 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj7cf4e6b2008-05-01 20:24:26 +00003137 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
3138 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 );
njndbf7ca72006-03-31 11:57:59 +00003139 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+16 );
3140 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+24 );
3141 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+32 );
3142 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+40 );
3143 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+48 );
3144 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+56 );
3145 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+64 );
3146 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+72 );
3147 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+80 );
3148 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+88 );
3149 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+96 );
sewardj7cf4e6b2008-05-01 20:24:26 +00003150 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+104 );
njn1d0825f2006-03-27 11:37:07 +00003151 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00003152 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 112 );
njn1d0825f2006-03-27 11:37:07 +00003153 }
3154}
3155
njneccf7c02009-01-19 23:42:45 +00003156MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00003157static void VG_REGPARM(1) mc_die_mem_stack_112(Addr new_SP)
3158{
florian60042192015-08-04 15:58:41 +00003159 PROF_EVENT(MCPE_DIE_MEM_STACK_112);
sewardj05a46732006-10-17 01:28:10 +00003160 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00003161 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-112);
3162 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-104);
3163 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-96 );
3164 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-88 );
3165 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-80 );
3166 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-72 );
3167 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-64 );
3168 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-56 );
3169 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-48 );
3170 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-40 );
3171 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-32 );
3172 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-24 );
3173 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 );
3174 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP- 8 );
njn1d0825f2006-03-27 11:37:07 +00003175 } else {
njndbf7ca72006-03-31 11:57:59 +00003176 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-112, 112 );
njn1d0825f2006-03-27 11:37:07 +00003177 }
3178}
3179
sewardj7cf4e6b2008-05-01 20:24:26 +00003180/*--------------- adjustment by 128 bytes ---------------*/
3181
njneccf7c02009-01-19 23:42:45 +00003182MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00003183static void VG_REGPARM(2) mc_new_mem_stack_128_w_ECU(Addr new_SP, UInt ecu)
3184{
3185 UInt otag = ecu | MC_OKIND_STACK;
florian60042192015-08-04 15:58:41 +00003186 PROF_EVENT(MCPE_NEW_MEM_STACK_128);
sewardj7cf4e6b2008-05-01 20:24:26 +00003187 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
3188 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP , otag );
3189 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+8 , otag );
3190 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+16, otag );
3191 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+24, otag );
3192 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+32, otag );
3193 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+40, otag );
3194 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+48, otag );
3195 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+56, otag );
3196 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+64, otag );
3197 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+72, otag );
3198 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+80, otag );
3199 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+88, otag );
3200 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+96, otag );
3201 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+104, otag );
3202 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+112, otag );
3203 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+120, otag );
3204 } else {
3205 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 128, otag );
3206 }
3207}
3208
njneccf7c02009-01-19 23:42:45 +00003209MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00003210static void VG_REGPARM(1) mc_new_mem_stack_128(Addr new_SP)
3211{
florian60042192015-08-04 15:58:41 +00003212 PROF_EVENT(MCPE_NEW_MEM_STACK_128);
sewardj05a46732006-10-17 01:28:10 +00003213 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj7cf4e6b2008-05-01 20:24:26 +00003214 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
3215 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 );
njndbf7ca72006-03-31 11:57:59 +00003216 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+16 );
3217 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+24 );
3218 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+32 );
3219 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+40 );
3220 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+48 );
3221 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+56 );
3222 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+64 );
3223 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+72 );
3224 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+80 );
3225 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+88 );
3226 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+96 );
sewardj7cf4e6b2008-05-01 20:24:26 +00003227 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+104 );
3228 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+112 );
3229 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+120 );
njn1d0825f2006-03-27 11:37:07 +00003230 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00003231 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 128 );
njn1d0825f2006-03-27 11:37:07 +00003232 }
3233}
3234
njneccf7c02009-01-19 23:42:45 +00003235MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00003236static void VG_REGPARM(1) mc_die_mem_stack_128(Addr new_SP)
3237{
florian60042192015-08-04 15:58:41 +00003238 PROF_EVENT(MCPE_DIE_MEM_STACK_128);
sewardj05a46732006-10-17 01:28:10 +00003239 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00003240 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-128);
3241 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-120);
3242 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-112);
3243 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-104);
3244 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-96 );
3245 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-88 );
3246 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-80 );
3247 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-72 );
3248 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-64 );
3249 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-56 );
3250 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-48 );
3251 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-40 );
3252 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-32 );
3253 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-24 );
3254 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 );
3255 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP- 8 );
njn1d0825f2006-03-27 11:37:07 +00003256 } else {
njndbf7ca72006-03-31 11:57:59 +00003257 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-128, 128 );
njn1d0825f2006-03-27 11:37:07 +00003258 }
3259}
3260
sewardj7cf4e6b2008-05-01 20:24:26 +00003261/*--------------- adjustment by 144 bytes ---------------*/
3262
njneccf7c02009-01-19 23:42:45 +00003263MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00003264static void VG_REGPARM(2) mc_new_mem_stack_144_w_ECU(Addr new_SP, UInt ecu)
3265{
3266 UInt otag = ecu | MC_OKIND_STACK;
florian60042192015-08-04 15:58:41 +00003267 PROF_EVENT(MCPE_NEW_MEM_STACK_144);
sewardj7cf4e6b2008-05-01 20:24:26 +00003268 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
3269 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP, otag );
3270 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+8, otag );
3271 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+16, otag );
3272 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+24, otag );
3273 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+32, otag );
3274 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+40, otag );
3275 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+48, otag );
3276 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+56, otag );
3277 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+64, otag );
3278 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+72, otag );
3279 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+80, otag );
3280 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+88, otag );
3281 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+96, otag );
3282 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+104, otag );
3283 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+112, otag );
3284 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+120, otag );
3285 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+128, otag );
3286 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+136, otag );
3287 } else {
3288 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 144, otag );
3289 }
3290}
3291
njneccf7c02009-01-19 23:42:45 +00003292MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00003293static void VG_REGPARM(1) mc_new_mem_stack_144(Addr new_SP)
3294{
florian60042192015-08-04 15:58:41 +00003295 PROF_EVENT(MCPE_NEW_MEM_STACK_144);
sewardj05a46732006-10-17 01:28:10 +00003296 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj7cf4e6b2008-05-01 20:24:26 +00003297 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
3298 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 );
njndbf7ca72006-03-31 11:57:59 +00003299 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+16 );
3300 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+24 );
3301 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+32 );
3302 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+40 );
3303 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+48 );
3304 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+56 );
3305 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+64 );
3306 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+72 );
3307 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+80 );
3308 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+88 );
3309 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+96 );
sewardj7cf4e6b2008-05-01 20:24:26 +00003310 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+104 );
3311 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+112 );
3312 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+120 );
3313 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+128 );
3314 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+136 );
njn1d0825f2006-03-27 11:37:07 +00003315 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00003316 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 144 );
njn1d0825f2006-03-27 11:37:07 +00003317 }
3318}
3319
njneccf7c02009-01-19 23:42:45 +00003320MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00003321static void VG_REGPARM(1) mc_die_mem_stack_144(Addr new_SP)
3322{
florian60042192015-08-04 15:58:41 +00003323 PROF_EVENT(MCPE_DIE_MEM_STACK_144);
sewardj05a46732006-10-17 01:28:10 +00003324 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00003325 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-144);
3326 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-136);
3327 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-128);
3328 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-120);
3329 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-112);
3330 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-104);
3331 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-96 );
3332 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-88 );
3333 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-80 );
3334 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-72 );
3335 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-64 );
3336 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-56 );
3337 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-48 );
3338 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-40 );
3339 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-32 );
3340 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-24 );
3341 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 );
3342 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP- 8 );
njn1d0825f2006-03-27 11:37:07 +00003343 } else {
njndbf7ca72006-03-31 11:57:59 +00003344 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-144, 144 );
njn1d0825f2006-03-27 11:37:07 +00003345 }
3346}
3347
sewardj7cf4e6b2008-05-01 20:24:26 +00003348/*--------------- adjustment by 160 bytes ---------------*/
3349
njneccf7c02009-01-19 23:42:45 +00003350MAYBE_USED
sewardj7cf4e6b2008-05-01 20:24:26 +00003351static void VG_REGPARM(2) mc_new_mem_stack_160_w_ECU(Addr new_SP, UInt ecu)
3352{
3353 UInt otag = ecu | MC_OKIND_STACK;
florian60042192015-08-04 15:58:41 +00003354 PROF_EVENT(MCPE_NEW_MEM_STACK_160);
sewardj7cf4e6b2008-05-01 20:24:26 +00003355 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
3356 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP, otag );
3357 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+8, otag );
3358 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+16, otag );
3359 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+24, otag );
3360 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+32, otag );
3361 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+40, otag );
3362 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+48, otag );
3363 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+56, otag );
3364 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+64, otag );
3365 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+72, otag );
3366 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+80, otag );
3367 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+88, otag );
3368 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+96, otag );
3369 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+104, otag );
3370 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+112, otag );
3371 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+120, otag );
3372 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+128, otag );
3373 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+136, otag );
3374 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+144, otag );
3375 make_aligned_word64_undefined_w_otag ( -VG_STACK_REDZONE_SZB + new_SP+152, otag );
3376 } else {
3377 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + new_SP, 160, otag );
3378 }
3379}
3380
njneccf7c02009-01-19 23:42:45 +00003381MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00003382static void VG_REGPARM(1) mc_new_mem_stack_160(Addr new_SP)
3383{
florian60042192015-08-04 15:58:41 +00003384 PROF_EVENT(MCPE_NEW_MEM_STACK_160);
sewardj05a46732006-10-17 01:28:10 +00003385 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
sewardj7cf4e6b2008-05-01 20:24:26 +00003386 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP );
3387 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+8 );
njndbf7ca72006-03-31 11:57:59 +00003388 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+16 );
3389 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+24 );
3390 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+32 );
3391 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+40 );
3392 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+48 );
3393 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+56 );
3394 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+64 );
3395 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+72 );
3396 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+80 );
3397 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+88 );
3398 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+96 );
sewardj7cf4e6b2008-05-01 20:24:26 +00003399 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+104 );
3400 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+112 );
3401 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+120 );
3402 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+128 );
3403 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+136 );
3404 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+144 );
3405 make_aligned_word64_undefined ( -VG_STACK_REDZONE_SZB + new_SP+152 );
njn1d0825f2006-03-27 11:37:07 +00003406 } else {
sewardj7cf4e6b2008-05-01 20:24:26 +00003407 make_mem_undefined ( -VG_STACK_REDZONE_SZB + new_SP, 160 );
njn1d0825f2006-03-27 11:37:07 +00003408 }
3409}
3410
njneccf7c02009-01-19 23:42:45 +00003411MAYBE_USED
njn1d0825f2006-03-27 11:37:07 +00003412static void VG_REGPARM(1) mc_die_mem_stack_160(Addr new_SP)
3413{
florian60042192015-08-04 15:58:41 +00003414 PROF_EVENT(MCPE_DIE_MEM_STACK_160);
sewardj05a46732006-10-17 01:28:10 +00003415 if (VG_IS_8_ALIGNED( -VG_STACK_REDZONE_SZB + new_SP )) {
njndbf7ca72006-03-31 11:57:59 +00003416 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-160);
3417 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-152);
3418 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-144);
3419 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-136);
3420 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-128);
3421 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-120);
3422 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-112);
3423 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-104);
3424 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-96 );
3425 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-88 );
3426 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-80 );
3427 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-72 );
3428 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-64 );
3429 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-56 );
3430 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-48 );
3431 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-40 );
3432 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-32 );
3433 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-24 );
3434 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP-16 );
3435 make_aligned_word64_noaccess ( -VG_STACK_REDZONE_SZB + new_SP- 8 );
njn1d0825f2006-03-27 11:37:07 +00003436 } else {
njndbf7ca72006-03-31 11:57:59 +00003437 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + new_SP-160, 160 );
njn1d0825f2006-03-27 11:37:07 +00003438 }
3439}
3440
sewardj7cf4e6b2008-05-01 20:24:26 +00003441/*--------------- adjustment by N bytes ---------------*/
3442
3443static void mc_new_mem_stack_w_ECU ( Addr a, SizeT len, UInt ecu )
3444{
3445 UInt otag = ecu | MC_OKIND_STACK;
florian60042192015-08-04 15:58:41 +00003446 PROF_EVENT(MCPE_NEW_MEM_STACK);
sewardj7cf4e6b2008-05-01 20:24:26 +00003447 MC_(make_mem_undefined_w_otag) ( -VG_STACK_REDZONE_SZB + a, len, otag );
3448}
3449
njn1d0825f2006-03-27 11:37:07 +00003450static void mc_new_mem_stack ( Addr a, SizeT len )
3451{
florian60042192015-08-04 15:58:41 +00003452 PROF_EVENT(MCPE_NEW_MEM_STACK);
sewardj7cf4e6b2008-05-01 20:24:26 +00003453 make_mem_undefined ( -VG_STACK_REDZONE_SZB + a, len );
njn1d0825f2006-03-27 11:37:07 +00003454}
3455
3456static void mc_die_mem_stack ( Addr a, SizeT len )
3457{
florian60042192015-08-04 15:58:41 +00003458 PROF_EVENT(MCPE_DIE_MEM_STACK);
njndbf7ca72006-03-31 11:57:59 +00003459 MC_(make_mem_noaccess) ( -VG_STACK_REDZONE_SZB + a, len );
njn1d0825f2006-03-27 11:37:07 +00003460}
njn9b007f62003-04-07 14:40:25 +00003461
sewardj45d94cc2005-04-20 14:44:11 +00003462
njn1d0825f2006-03-27 11:37:07 +00003463/* The AMD64 ABI says:
3464
3465 "The 128-byte area beyond the location pointed to by %rsp is considered
3466 to be reserved and shall not be modified by signal or interrupt
3467 handlers. Therefore, functions may use this area for temporary data
3468 that is not needed across function calls. In particular, leaf functions
3469 may use this area for their entire stack frame, rather than adjusting
3470 the stack pointer in the prologue and epilogue. This area is known as
3471 red zone [sic]."
3472
3473 So after any call or return we need to mark this redzone as containing
3474 undefined values.
3475
3476 Consider this: we're in function f. f calls g. g moves rsp down
3477 modestly (say 16 bytes) and writes stuff all over the red zone, making it
3478 defined. g returns. f is buggy and reads from parts of the red zone
3479 that it didn't write on. But because g filled that area in, f is going
3480 to be picking up defined V bits and so any errors from reading bits of
3481 the red zone it didn't write, will be missed. The only solution I could
3482 think of was to make the red zone undefined when g returns to f.
3483
3484 This is in accordance with the ABI, which makes it clear the redzone
3485 is volatile across function calls.
3486
3487 The problem occurs the other way round too: f could fill the RZ up
3488 with defined values and g could mistakenly read them. So the RZ
3489 also needs to be nuked on function calls.
3490*/
sewardj7cf4e6b2008-05-01 20:24:26 +00003491
3492
3493/* Here's a simple cache to hold nia -> ECU mappings. It could be
3494 improved so as to have a lower miss rate. */
3495
3496static UWord stats__nia_cache_queries = 0;
3497static UWord stats__nia_cache_misses = 0;
3498
3499typedef
3500 struct { UWord nia0; UWord ecu0; /* nia0 maps to ecu0 */
3501 UWord nia1; UWord ecu1; } /* nia1 maps to ecu1 */
3502 WCacheEnt;
3503
3504#define N_NIA_TO_ECU_CACHE 511
3505
3506static WCacheEnt nia_to_ecu_cache[N_NIA_TO_ECU_CACHE];
3507
3508static void init_nia_to_ecu_cache ( void )
sewardj826ec492005-05-12 18:05:00 +00003509{
sewardj7cf4e6b2008-05-01 20:24:26 +00003510 UWord i;
3511 Addr zero_addr = 0;
3512 ExeContext* zero_ec;
3513 UInt zero_ecu;
3514 /* Fill all the slots with an entry for address zero, and the
3515 relevant otags accordingly. Hence the cache is initially filled
3516 with valid data. */
3517 zero_ec = VG_(make_depth_1_ExeContext_from_Addr)(zero_addr);
3518 tl_assert(zero_ec);
3519 zero_ecu = VG_(get_ECU_from_ExeContext)(zero_ec);
3520 tl_assert(VG_(is_plausible_ECU)(zero_ecu));
3521 for (i = 0; i < N_NIA_TO_ECU_CACHE; i++) {
3522 nia_to_ecu_cache[i].nia0 = zero_addr;
3523 nia_to_ecu_cache[i].ecu0 = zero_ecu;
3524 nia_to_ecu_cache[i].nia1 = zero_addr;
3525 nia_to_ecu_cache[i].ecu1 = zero_ecu;
3526 }
3527}
3528
3529static inline UInt convert_nia_to_ecu ( Addr nia )
3530{
3531 UWord i;
3532 UInt ecu;
3533 ExeContext* ec;
3534
3535 tl_assert( sizeof(nia_to_ecu_cache[0].nia1) == sizeof(nia) );
3536
3537 stats__nia_cache_queries++;
3538 i = nia % N_NIA_TO_ECU_CACHE;
3539 tl_assert(i >= 0 && i < N_NIA_TO_ECU_CACHE);
3540
3541 if (LIKELY( nia_to_ecu_cache[i].nia0 == nia ))
3542 return nia_to_ecu_cache[i].ecu0;
3543
3544 if (LIKELY( nia_to_ecu_cache[i].nia1 == nia )) {
3545# define SWAP(_w1,_w2) { UWord _t = _w1; _w1 = _w2; _w2 = _t; }
3546 SWAP( nia_to_ecu_cache[i].nia0, nia_to_ecu_cache[i].nia1 );
3547 SWAP( nia_to_ecu_cache[i].ecu0, nia_to_ecu_cache[i].ecu1 );
3548# undef SWAP
3549 return nia_to_ecu_cache[i].ecu0;
3550 }
3551
3552 stats__nia_cache_misses++;
3553 ec = VG_(make_depth_1_ExeContext_from_Addr)(nia);
3554 tl_assert(ec);
3555 ecu = VG_(get_ECU_from_ExeContext)(ec);
3556 tl_assert(VG_(is_plausible_ECU)(ecu));
3557
3558 nia_to_ecu_cache[i].nia1 = nia_to_ecu_cache[i].nia0;
3559 nia_to_ecu_cache[i].ecu1 = nia_to_ecu_cache[i].ecu0;
3560
3561 nia_to_ecu_cache[i].nia0 = nia;
3562 nia_to_ecu_cache[i].ecu0 = (UWord)ecu;
3563 return ecu;
3564}
3565
3566
Elliott Hughesa0664b92017-04-18 17:46:52 -07003567/* This marks the stack as addressible but undefined, after a call or
3568 return for a target that has an ABI defined stack redzone. It
3569 happens quite a lot and needs to be fast. This is the version for
3570 origin tracking. The non-origin-tracking version is below. */
3571VG_REGPARM(3)
3572void MC_(helperc_MAKE_STACK_UNINIT_w_o) ( Addr base, UWord len, Addr nia )
sewardj7cf4e6b2008-05-01 20:24:26 +00003573{
Elliott Hughesa0664b92017-04-18 17:46:52 -07003574 PROF_EVENT(MCPE_MAKE_STACK_UNINIT_W_O);
sewardj2a3a1a72005-05-12 23:25:43 +00003575 if (0)
Elliott Hughesa0664b92017-04-18 17:46:52 -07003576 VG_(printf)("helperc_MAKE_STACK_UNINIT_w_o (%#lx,%lu,nia=%#lx)\n",
sewardj7cf4e6b2008-05-01 20:24:26 +00003577 base, len, nia );
3578
Elliott Hughesa0664b92017-04-18 17:46:52 -07003579 UInt ecu = convert_nia_to_ecu ( nia );
3580 tl_assert(VG_(is_plausible_ECU)(ecu));
sewardj2a3a1a72005-05-12 23:25:43 +00003581
Elliott Hughesa0664b92017-04-18 17:46:52 -07003582 UInt otag = ecu | MC_OKIND_STACK;
sewardj2a3a1a72005-05-12 23:25:43 +00003583
3584# if 0
3585 /* Slow(ish) version, which is fairly easily seen to be correct.
3586 */
bart5dd8e6a2008-03-22 08:04:29 +00003587 if (LIKELY( VG_IS_8_ALIGNED(base) && len==128 )) {
Elliott Hughesa0664b92017-04-18 17:46:52 -07003588 make_aligned_word64_undefined_w_otag(base + 0, otag);
3589 make_aligned_word64_undefined_w_otag(base + 8, otag);
3590 make_aligned_word64_undefined_w_otag(base + 16, otag);
3591 make_aligned_word64_undefined_w_otag(base + 24, otag);
sewardj2a3a1a72005-05-12 23:25:43 +00003592
Elliott Hughesa0664b92017-04-18 17:46:52 -07003593 make_aligned_word64_undefined_w_otag(base + 32, otag);
3594 make_aligned_word64_undefined_w_otag(base + 40, otag);
3595 make_aligned_word64_undefined_w_otag(base + 48, otag);
3596 make_aligned_word64_undefined_w_otag(base + 56, otag);
sewardj2a3a1a72005-05-12 23:25:43 +00003597
Elliott Hughesa0664b92017-04-18 17:46:52 -07003598 make_aligned_word64_undefined_w_otag(base + 64, otag);
3599 make_aligned_word64_undefined_w_otag(base + 72, otag);
3600 make_aligned_word64_undefined_w_otag(base + 80, otag);
3601 make_aligned_word64_undefined_w_otag(base + 88, otag);
sewardj2a3a1a72005-05-12 23:25:43 +00003602
Elliott Hughesa0664b92017-04-18 17:46:52 -07003603 make_aligned_word64_undefined_w_otag(base + 96, otag);
3604 make_aligned_word64_undefined_w_otag(base + 104, otag);
3605 make_aligned_word64_undefined_w_otag(base + 112, otag);
3606 make_aligned_word64_undefined_w_otag(base + 120, otag);
sewardj2a3a1a72005-05-12 23:25:43 +00003607 } else {
Elliott Hughesa0664b92017-04-18 17:46:52 -07003608 MC_(make_mem_undefined_w_otag)(base, len, otag);
sewardj2a3a1a72005-05-12 23:25:43 +00003609 }
3610# endif
3611
3612 /* Idea is: go fast when
3613 * 8-aligned and length is 128
3614 * the sm is available in the main primary map
njn1d0825f2006-03-27 11:37:07 +00003615 * the address range falls entirely with a single secondary map
3616 If all those conditions hold, just update the V+A bits by writing
3617 directly into the vabits array. (If the sm was distinguished, this
3618 will make a copy and then write to it.)
sewardj2a3a1a72005-05-12 23:25:43 +00003619 */
bart5dd8e6a2008-03-22 08:04:29 +00003620 if (LIKELY( len == 128 && VG_IS_8_ALIGNED(base) )) {
njn1d0825f2006-03-27 11:37:07 +00003621 /* Now we know the address range is suitably sized and aligned. */
3622 UWord a_lo = (UWord)(base);
sewardj3f5f5562006-06-16 21:39:08 +00003623 UWord a_hi = (UWord)(base + 128 - 1);
njn1d0825f2006-03-27 11:37:07 +00003624 tl_assert(a_lo < a_hi); // paranoia: detect overflow
Elliott Hughesa0664b92017-04-18 17:46:52 -07003625 if (LIKELY(a_hi <= MAX_PRIMARY_ADDRESS)) {
3626 /* Now we know the entire range is within the main primary map. */
3627 UWord pm_off_lo = get_primary_map_low_offset(a_lo);
3628 UWord pm_off_hi = get_primary_map_low_offset(a_hi);
3629 if (LIKELY(pm_off_lo == pm_off_hi)) {
3630 /* Now we know that the entire address range falls within a
3631 single secondary map, and that that secondary 'lives' in
3632 the main primary map. */
3633 SecMap* sm = get_secmap_for_writing_low(a_lo);
njn1d0825f2006-03-27 11:37:07 +00003634 UWord v_off = SM_OFF(a_lo);
3635 UShort* p = (UShort*)(&sm->vabits8[v_off]);
njndbf7ca72006-03-31 11:57:59 +00003636 p[ 0] = VA_BITS16_UNDEFINED;
3637 p[ 1] = VA_BITS16_UNDEFINED;
3638 p[ 2] = VA_BITS16_UNDEFINED;
3639 p[ 3] = VA_BITS16_UNDEFINED;
3640 p[ 4] = VA_BITS16_UNDEFINED;
3641 p[ 5] = VA_BITS16_UNDEFINED;
3642 p[ 6] = VA_BITS16_UNDEFINED;
3643 p[ 7] = VA_BITS16_UNDEFINED;
3644 p[ 8] = VA_BITS16_UNDEFINED;
3645 p[ 9] = VA_BITS16_UNDEFINED;
3646 p[10] = VA_BITS16_UNDEFINED;
3647 p[11] = VA_BITS16_UNDEFINED;
3648 p[12] = VA_BITS16_UNDEFINED;
3649 p[13] = VA_BITS16_UNDEFINED;
3650 p[14] = VA_BITS16_UNDEFINED;
3651 p[15] = VA_BITS16_UNDEFINED;
Elliott Hughesa0664b92017-04-18 17:46:52 -07003652 set_aligned_word64_Origin_to_undef( base + 8 * 0, otag );
3653 set_aligned_word64_Origin_to_undef( base + 8 * 1, otag );
3654 set_aligned_word64_Origin_to_undef( base + 8 * 2, otag );
3655 set_aligned_word64_Origin_to_undef( base + 8 * 3, otag );
3656 set_aligned_word64_Origin_to_undef( base + 8 * 4, otag );
3657 set_aligned_word64_Origin_to_undef( base + 8 * 5, otag );
3658 set_aligned_word64_Origin_to_undef( base + 8 * 6, otag );
3659 set_aligned_word64_Origin_to_undef( base + 8 * 7, otag );
3660 set_aligned_word64_Origin_to_undef( base + 8 * 8, otag );
3661 set_aligned_word64_Origin_to_undef( base + 8 * 9, otag );
3662 set_aligned_word64_Origin_to_undef( base + 8 * 10, otag );
3663 set_aligned_word64_Origin_to_undef( base + 8 * 11, otag );
3664 set_aligned_word64_Origin_to_undef( base + 8 * 12, otag );
3665 set_aligned_word64_Origin_to_undef( base + 8 * 13, otag );
3666 set_aligned_word64_Origin_to_undef( base + 8 * 14, otag );
3667 set_aligned_word64_Origin_to_undef( base + 8 * 15, otag );
sewardj2a3a1a72005-05-12 23:25:43 +00003668 return;
njn1d0825f2006-03-27 11:37:07 +00003669 }
sewardj2a3a1a72005-05-12 23:25:43 +00003670 }
3671 }
3672
sewardj2e1a6772006-01-18 04:16:27 +00003673 /* 288 bytes (36 ULongs) is the magic value for ELF ppc64. */
bart5dd8e6a2008-03-22 08:04:29 +00003674 if (LIKELY( len == 288 && VG_IS_8_ALIGNED(base) )) {
njn1d0825f2006-03-27 11:37:07 +00003675 /* Now we know the address range is suitably sized and aligned. */
3676 UWord a_lo = (UWord)(base);
sewardj3f5f5562006-06-16 21:39:08 +00003677 UWord a_hi = (UWord)(base + 288 - 1);
njn1d0825f2006-03-27 11:37:07 +00003678 tl_assert(a_lo < a_hi); // paranoia: detect overflow
sewardj7244e712008-05-02 12:35:48 +00003679 if (a_hi <= MAX_PRIMARY_ADDRESS) {
Elliott Hughesa0664b92017-04-18 17:46:52 -07003680 UWord pm_off_lo = get_primary_map_low_offset(a_lo);
3681 UWord pm_off_hi = get_primary_map_low_offset(a_hi);
3682 if (LIKELY(pm_off_lo == pm_off_hi)) {
3683 /* Now we know that the entire address range falls within a
3684 single secondary map, and that that secondary 'lives' in
3685 the main primary map. */
3686 SecMap* sm = get_secmap_for_writing_low(a_lo);
njn1d0825f2006-03-27 11:37:07 +00003687 UWord v_off = SM_OFF(a_lo);
3688 UShort* p = (UShort*)(&sm->vabits8[v_off]);
njndbf7ca72006-03-31 11:57:59 +00003689 p[ 0] = VA_BITS16_UNDEFINED;
3690 p[ 1] = VA_BITS16_UNDEFINED;
3691 p[ 2] = VA_BITS16_UNDEFINED;
3692 p[ 3] = VA_BITS16_UNDEFINED;
3693 p[ 4] = VA_BITS16_UNDEFINED;
3694 p[ 5] = VA_BITS16_UNDEFINED;
3695 p[ 6] = VA_BITS16_UNDEFINED;
3696 p[ 7] = VA_BITS16_UNDEFINED;
3697 p[ 8] = VA_BITS16_UNDEFINED;
3698 p[ 9] = VA_BITS16_UNDEFINED;
3699 p[10] = VA_BITS16_UNDEFINED;
3700 p[11] = VA_BITS16_UNDEFINED;
3701 p[12] = VA_BITS16_UNDEFINED;
3702 p[13] = VA_BITS16_UNDEFINED;
3703 p[14] = VA_BITS16_UNDEFINED;
3704 p[15] = VA_BITS16_UNDEFINED;
3705 p[16] = VA_BITS16_UNDEFINED;
3706 p[17] = VA_BITS16_UNDEFINED;
3707 p[18] = VA_BITS16_UNDEFINED;
3708 p[19] = VA_BITS16_UNDEFINED;
3709 p[20] = VA_BITS16_UNDEFINED;
3710 p[21] = VA_BITS16_UNDEFINED;
3711 p[22] = VA_BITS16_UNDEFINED;
3712 p[23] = VA_BITS16_UNDEFINED;
3713 p[24] = VA_BITS16_UNDEFINED;
3714 p[25] = VA_BITS16_UNDEFINED;
3715 p[26] = VA_BITS16_UNDEFINED;
3716 p[27] = VA_BITS16_UNDEFINED;
3717 p[28] = VA_BITS16_UNDEFINED;
3718 p[29] = VA_BITS16_UNDEFINED;
3719 p[30] = VA_BITS16_UNDEFINED;
3720 p[31] = VA_BITS16_UNDEFINED;
3721 p[32] = VA_BITS16_UNDEFINED;
3722 p[33] = VA_BITS16_UNDEFINED;
3723 p[34] = VA_BITS16_UNDEFINED;
3724 p[35] = VA_BITS16_UNDEFINED;
Elliott Hughesa0664b92017-04-18 17:46:52 -07003725 set_aligned_word64_Origin_to_undef( base + 8 * 0, otag );
3726 set_aligned_word64_Origin_to_undef( base + 8 * 1, otag );
3727 set_aligned_word64_Origin_to_undef( base + 8 * 2, otag );
3728 set_aligned_word64_Origin_to_undef( base + 8 * 3, otag );
3729 set_aligned_word64_Origin_to_undef( base + 8 * 4, otag );
3730 set_aligned_word64_Origin_to_undef( base + 8 * 5, otag );
3731 set_aligned_word64_Origin_to_undef( base + 8 * 6, otag );
3732 set_aligned_word64_Origin_to_undef( base + 8 * 7, otag );
3733 set_aligned_word64_Origin_to_undef( base + 8 * 8, otag );
3734 set_aligned_word64_Origin_to_undef( base + 8 * 9, otag );
3735 set_aligned_word64_Origin_to_undef( base + 8 * 10, otag );
3736 set_aligned_word64_Origin_to_undef( base + 8 * 11, otag );
3737 set_aligned_word64_Origin_to_undef( base + 8 * 12, otag );
3738 set_aligned_word64_Origin_to_undef( base + 8 * 13, otag );
3739 set_aligned_word64_Origin_to_undef( base + 8 * 14, otag );
3740 set_aligned_word64_Origin_to_undef( base + 8 * 15, otag );
3741 set_aligned_word64_Origin_to_undef( base + 8 * 16, otag );
3742 set_aligned_word64_Origin_to_undef( base + 8 * 17, otag );
3743 set_aligned_word64_Origin_to_undef( base + 8 * 18, otag );
3744 set_aligned_word64_Origin_to_undef( base + 8 * 19, otag );
3745 set_aligned_word64_Origin_to_undef( base + 8 * 20, otag );
3746 set_aligned_word64_Origin_to_undef( base + 8 * 21, otag );
3747 set_aligned_word64_Origin_to_undef( base + 8 * 22, otag );
3748 set_aligned_word64_Origin_to_undef( base + 8 * 23, otag );
3749 set_aligned_word64_Origin_to_undef( base + 8 * 24, otag );
3750 set_aligned_word64_Origin_to_undef( base + 8 * 25, otag );
3751 set_aligned_word64_Origin_to_undef( base + 8 * 26, otag );
3752 set_aligned_word64_Origin_to_undef( base + 8 * 27, otag );
3753 set_aligned_word64_Origin_to_undef( base + 8 * 28, otag );
3754 set_aligned_word64_Origin_to_undef( base + 8 * 29, otag );
3755 set_aligned_word64_Origin_to_undef( base + 8 * 30, otag );
3756 set_aligned_word64_Origin_to_undef( base + 8 * 31, otag );
3757 set_aligned_word64_Origin_to_undef( base + 8 * 32, otag );
3758 set_aligned_word64_Origin_to_undef( base + 8 * 33, otag );
3759 set_aligned_word64_Origin_to_undef( base + 8 * 34, otag );
3760 set_aligned_word64_Origin_to_undef( base + 8 * 35, otag );
sewardj2e1a6772006-01-18 04:16:27 +00003761 return;
njn1d0825f2006-03-27 11:37:07 +00003762 }
sewardj2e1a6772006-01-18 04:16:27 +00003763 }
3764 }
3765
sewardj2a3a1a72005-05-12 23:25:43 +00003766 /* else fall into slow case */
sewardj7cf4e6b2008-05-01 20:24:26 +00003767 MC_(make_mem_undefined_w_otag)(base, len, otag);
sewardj826ec492005-05-12 18:05:00 +00003768}
3769
3770
Elliott Hughesa0664b92017-04-18 17:46:52 -07003771/* This is a version of MC_(helperc_MAKE_STACK_UNINIT_w_o) that is
3772 specialised for the non-origin-tracking case. */
3773VG_REGPARM(2)
3774void MC_(helperc_MAKE_STACK_UNINIT_no_o) ( Addr base, UWord len )
3775{
3776 PROF_EVENT(MCPE_MAKE_STACK_UNINIT_NO_O);
3777 if (0)
3778 VG_(printf)("helperc_MAKE_STACK_UNINIT_no_o (%#lx,%lu)\n",
3779 base, len );
3780
3781# if 0
3782 /* Slow(ish) version, which is fairly easily seen to be correct.
3783 */
3784 if (LIKELY( VG_IS_8_ALIGNED(base) && len==128 )) {
3785 make_aligned_word64_undefined(base + 0);
3786 make_aligned_word64_undefined(base + 8);
3787 make_aligned_word64_undefined(base + 16);
3788 make_aligned_word64_undefined(base + 24);
3789
3790 make_aligned_word64_undefined(base + 32);
3791 make_aligned_word64_undefined(base + 40);
3792 make_aligned_word64_undefined(base + 48);
3793 make_aligned_word64_undefined(base + 56);
3794
3795 make_aligned_word64_undefined(base + 64);
3796 make_aligned_word64_undefined(base + 72);
3797 make_aligned_word64_undefined(base + 80);
3798 make_aligned_word64_undefined(base + 88);
3799
3800 make_aligned_word64_undefined(base + 96);
3801 make_aligned_word64_undefined(base + 104);
3802 make_aligned_word64_undefined(base + 112);
3803 make_aligned_word64_undefined(base + 120);
3804 } else {
3805 make_mem_undefined(base, len);
3806 }
3807# endif
3808
3809 /* Idea is: go fast when
3810 * 8-aligned and length is 128
3811 * the sm is available in the main primary map
3812 * the address range falls entirely with a single secondary map
3813 If all those conditions hold, just update the V+A bits by writing
3814 directly into the vabits array. (If the sm was distinguished, this
3815 will make a copy and then write to it.)
3816 */
3817 if (LIKELY( len == 128 && VG_IS_8_ALIGNED(base) )) {
3818 /* Now we know the address range is suitably sized and aligned. */
3819 UWord a_lo = (UWord)(base);
3820 UWord a_hi = (UWord)(base + 128 - 1);
3821 tl_assert(a_lo < a_hi); // paranoia: detect overflow
3822 if (LIKELY(a_hi <= MAX_PRIMARY_ADDRESS)) {
3823 /* Now we know the entire range is within the main primary map. */
3824 UWord pm_off_lo = get_primary_map_low_offset(a_lo);
3825 UWord pm_off_hi = get_primary_map_low_offset(a_hi);
3826 if (LIKELY(pm_off_lo == pm_off_hi)) {
3827 /* Now we know that the entire address range falls within a
3828 single secondary map, and that that secondary 'lives' in
3829 the main primary map. */
3830 SecMap* sm = get_secmap_for_writing_low(a_lo);
3831 UWord v_off = SM_OFF(a_lo);
3832 UShort* p = (UShort*)(&sm->vabits8[v_off]);
3833 p[ 0] = VA_BITS16_UNDEFINED;
3834 p[ 1] = VA_BITS16_UNDEFINED;
3835 p[ 2] = VA_BITS16_UNDEFINED;
3836 p[ 3] = VA_BITS16_UNDEFINED;
3837 p[ 4] = VA_BITS16_UNDEFINED;
3838 p[ 5] = VA_BITS16_UNDEFINED;
3839 p[ 6] = VA_BITS16_UNDEFINED;
3840 p[ 7] = VA_BITS16_UNDEFINED;
3841 p[ 8] = VA_BITS16_UNDEFINED;
3842 p[ 9] = VA_BITS16_UNDEFINED;
3843 p[10] = VA_BITS16_UNDEFINED;
3844 p[11] = VA_BITS16_UNDEFINED;
3845 p[12] = VA_BITS16_UNDEFINED;
3846 p[13] = VA_BITS16_UNDEFINED;
3847 p[14] = VA_BITS16_UNDEFINED;
3848 p[15] = VA_BITS16_UNDEFINED;
3849 return;
3850 }
3851 }
3852 }
3853
3854 /* 288 bytes (36 ULongs) is the magic value for ELF ppc64. */
3855 if (LIKELY( len == 288 && VG_IS_8_ALIGNED(base) )) {
3856 /* Now we know the address range is suitably sized and aligned. */
3857 UWord a_lo = (UWord)(base);
3858 UWord a_hi = (UWord)(base + 288 - 1);
3859 tl_assert(a_lo < a_hi); // paranoia: detect overflow
3860 if (a_hi <= MAX_PRIMARY_ADDRESS) {
3861 UWord pm_off_lo = get_primary_map_low_offset(a_lo);
3862 UWord pm_off_hi = get_primary_map_low_offset(a_hi);
3863 if (LIKELY(pm_off_lo == pm_off_hi)) {
3864 /* Now we know that the entire address range falls within a
3865 single secondary map, and that that secondary 'lives' in
3866 the main primary map. */
3867 SecMap* sm = get_secmap_for_writing_low(a_lo);
3868 UWord v_off = SM_OFF(a_lo);
3869 UShort* p = (UShort*)(&sm->vabits8[v_off]);
3870 p[ 0] = VA_BITS16_UNDEFINED;
3871 p[ 1] = VA_BITS16_UNDEFINED;
3872 p[ 2] = VA_BITS16_UNDEFINED;
3873 p[ 3] = VA_BITS16_UNDEFINED;
3874 p[ 4] = VA_BITS16_UNDEFINED;
3875 p[ 5] = VA_BITS16_UNDEFINED;
3876 p[ 6] = VA_BITS16_UNDEFINED;
3877 p[ 7] = VA_BITS16_UNDEFINED;
3878 p[ 8] = VA_BITS16_UNDEFINED;
3879 p[ 9] = VA_BITS16_UNDEFINED;
3880 p[10] = VA_BITS16_UNDEFINED;
3881 p[11] = VA_BITS16_UNDEFINED;
3882 p[12] = VA_BITS16_UNDEFINED;
3883 p[13] = VA_BITS16_UNDEFINED;
3884 p[14] = VA_BITS16_UNDEFINED;
3885 p[15] = VA_BITS16_UNDEFINED;
3886 p[16] = VA_BITS16_UNDEFINED;
3887 p[17] = VA_BITS16_UNDEFINED;
3888 p[18] = VA_BITS16_UNDEFINED;
3889 p[19] = VA_BITS16_UNDEFINED;
3890 p[20] = VA_BITS16_UNDEFINED;
3891 p[21] = VA_BITS16_UNDEFINED;
3892 p[22] = VA_BITS16_UNDEFINED;
3893 p[23] = VA_BITS16_UNDEFINED;
3894 p[24] = VA_BITS16_UNDEFINED;
3895 p[25] = VA_BITS16_UNDEFINED;
3896 p[26] = VA_BITS16_UNDEFINED;
3897 p[27] = VA_BITS16_UNDEFINED;
3898 p[28] = VA_BITS16_UNDEFINED;
3899 p[29] = VA_BITS16_UNDEFINED;
3900 p[30] = VA_BITS16_UNDEFINED;
3901 p[31] = VA_BITS16_UNDEFINED;
3902 p[32] = VA_BITS16_UNDEFINED;
3903 p[33] = VA_BITS16_UNDEFINED;
3904 p[34] = VA_BITS16_UNDEFINED;
3905 p[35] = VA_BITS16_UNDEFINED;
3906 return;
3907 }
3908 }
3909 }
3910
3911 /* else fall into slow case */
3912 make_mem_undefined(base, len);
3913}
3914
3915
3916/* And this is an even more specialised case, for the case where there
3917 is no origin tracking, and the length is 128. */
3918VG_REGPARM(1)
3919void MC_(helperc_MAKE_STACK_UNINIT_128_no_o) ( Addr base )
3920{
3921 PROF_EVENT(MCPE_MAKE_STACK_UNINIT_128_NO_O);
3922 if (0)
3923 VG_(printf)("helperc_MAKE_STACK_UNINIT_128_no_o (%#lx)\n", base );
3924
3925# if 0
3926 /* Slow(ish) version, which is fairly easily seen to be correct.
3927 */
3928 if (LIKELY( VG_IS_8_ALIGNED(base) )) {
3929 make_aligned_word64_undefined(base + 0);
3930 make_aligned_word64_undefined(base + 8);
3931 make_aligned_word64_undefined(base + 16);
3932 make_aligned_word64_undefined(base + 24);
3933
3934 make_aligned_word64_undefined(base + 32);
3935 make_aligned_word64_undefined(base + 40);
3936 make_aligned_word64_undefined(base + 48);
3937 make_aligned_word64_undefined(base + 56);
3938
3939 make_aligned_word64_undefined(base + 64);
3940 make_aligned_word64_undefined(base + 72);
3941 make_aligned_word64_undefined(base + 80);
3942 make_aligned_word64_undefined(base + 88);
3943
3944 make_aligned_word64_undefined(base + 96);
3945 make_aligned_word64_undefined(base + 104);
3946 make_aligned_word64_undefined(base + 112);
3947 make_aligned_word64_undefined(base + 120);
3948 } else {
3949 make_mem_undefined(base, 128);
3950 }
3951# endif
3952
3953 /* Idea is: go fast when
3954 * 16-aligned and length is 128
3955 * the sm is available in the main primary map
3956 * the address range falls entirely with a single secondary map
3957 If all those conditions hold, just update the V+A bits by writing
3958 directly into the vabits array. (If the sm was distinguished, this
3959 will make a copy and then write to it.)
3960
3961 Typically this applies to amd64 'ret' instructions, since RSP is
3962 16-aligned (0 % 16) after the instruction (per the amd64-ELF ABI).
3963 */
3964 if (LIKELY( VG_IS_16_ALIGNED(base) )) {
3965 /* Now we know the address range is suitably sized and aligned. */
3966 UWord a_lo = (UWord)(base);
3967 UWord a_hi = (UWord)(base + 128 - 1);
3968 /* FIXME: come up with a sane story on the wraparound case
3969 (which of course cnanot happen, but still..) */
3970 /* tl_assert(a_lo < a_hi); */ // paranoia: detect overflow
3971 if (LIKELY(a_hi <= MAX_PRIMARY_ADDRESS)) {
3972 /* Now we know the entire range is within the main primary map. */
3973 UWord pm_off_lo = get_primary_map_low_offset(a_lo);
3974 UWord pm_off_hi = get_primary_map_low_offset(a_hi);
3975 if (LIKELY(pm_off_lo == pm_off_hi)) {
3976 /* Now we know that the entire address range falls within a
3977 single secondary map, and that that secondary 'lives' in
3978 the main primary map. */
3979 PROF_EVENT(MCPE_MAKE_STACK_UNINIT_128_NO_O_ALIGNED_16);
3980 SecMap* sm = get_secmap_for_writing_low(a_lo);
3981 UWord v_off = SM_OFF(a_lo);
3982 UInt* w32 = (UInt*)(&sm->vabits8[v_off]);
3983 w32[ 0] = VA_BITS32_UNDEFINED;
3984 w32[ 1] = VA_BITS32_UNDEFINED;
3985 w32[ 2] = VA_BITS32_UNDEFINED;
3986 w32[ 3] = VA_BITS32_UNDEFINED;
3987 w32[ 4] = VA_BITS32_UNDEFINED;
3988 w32[ 5] = VA_BITS32_UNDEFINED;
3989 w32[ 6] = VA_BITS32_UNDEFINED;
3990 w32[ 7] = VA_BITS32_UNDEFINED;
3991 return;
3992 }
3993 }
3994 }
3995
3996 /* The same, but for when base is 8 % 16, which is the situation
3997 with RSP for amd64-ELF immediately after call instructions.
3998 */
3999 if (LIKELY( VG_IS_16_ALIGNED(base+8) )) { // restricts to 8 aligned
4000 /* Now we know the address range is suitably sized and aligned. */
4001 UWord a_lo = (UWord)(base);
4002 UWord a_hi = (UWord)(base + 128 - 1);
4003 /* FIXME: come up with a sane story on the wraparound case
4004 (which of course cnanot happen, but still..) */
4005 /* tl_assert(a_lo < a_hi); */ // paranoia: detect overflow
4006 if (LIKELY(a_hi <= MAX_PRIMARY_ADDRESS)) {
4007 /* Now we know the entire range is within the main primary map. */
4008 UWord pm_off_lo = get_primary_map_low_offset(a_lo);
4009 UWord pm_off_hi = get_primary_map_low_offset(a_hi);
4010 if (LIKELY(pm_off_lo == pm_off_hi)) {
4011 PROF_EVENT(MCPE_MAKE_STACK_UNINIT_128_NO_O_ALIGNED_8);
4012 /* Now we know that the entire address range falls within a
4013 single secondary map, and that that secondary 'lives' in
4014 the main primary map. */
4015 SecMap* sm = get_secmap_for_writing_low(a_lo);
4016 UWord v_off = SM_OFF(a_lo);
4017 UShort* w16 = (UShort*)(&sm->vabits8[v_off]);
4018 UInt* w32 = (UInt*)(&w16[1]);
4019 /* The following assertion is commented out for obvious
4020 performance reasons, but was verified as valid when
4021 running the entire testsuite and also Firefox. */
4022 /* tl_assert(VG_IS_4_ALIGNED(w32)); */
4023 w16[ 0] = VA_BITS16_UNDEFINED; // w16[0]
4024 w32[ 0] = VA_BITS32_UNDEFINED; // w16[1,2]
4025 w32[ 1] = VA_BITS32_UNDEFINED; // w16[3,4]
4026 w32[ 2] = VA_BITS32_UNDEFINED; // w16[5,6]
4027 w32[ 3] = VA_BITS32_UNDEFINED; // w16[7,8]
4028 w32[ 4] = VA_BITS32_UNDEFINED; // w16[9,10]
4029 w32[ 5] = VA_BITS32_UNDEFINED; // w16[11,12]
4030 w32[ 6] = VA_BITS32_UNDEFINED; // w16[13,14]
4031 w16[15] = VA_BITS16_UNDEFINED; // w16[15]
4032 return;
4033 }
4034 }
4035 }
4036
4037 /* else fall into slow case */
4038 PROF_EVENT(MCPE_MAKE_STACK_UNINIT_128_NO_O_SLOWCASE);
4039 make_mem_undefined(base, 128);
4040}
4041
4042
nethercote8b76fe52004-11-08 19:20:09 +00004043/*------------------------------------------------------------*/
4044/*--- Checking memory ---*/
4045/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00004046
sewardje4ccc012005-05-02 12:53:38 +00004047typedef
4048 enum {
4049 MC_Ok = 5,
4050 MC_AddrErr = 6,
4051 MC_ValueErr = 7
4052 }
4053 MC_ReadResult;
4054
4055
njn25e49d8e72002-09-23 09:36:25 +00004056/* Check permissions for address range. If inadequate permissions
4057 exist, *bad_addr is set to the offending address, so the caller can
4058 know what it is. */
4059
sewardjecf8e102003-07-12 12:11:39 +00004060/* Returns True if [a .. a+len) is not addressible. Otherwise,
4061 returns False, and if bad_addr is non-NULL, sets *bad_addr to
4062 indicate the lowest failing address. Functions below are
4063 similar. */
njndbf7ca72006-03-31 11:57:59 +00004064Bool MC_(check_mem_is_noaccess) ( Addr a, SizeT len, Addr* bad_addr )
sewardjecf8e102003-07-12 12:11:39 +00004065{
nethercote451eae92004-11-02 13:06:32 +00004066 SizeT i;
njn1d0825f2006-03-27 11:37:07 +00004067 UWord vabits2;
4068
florian60042192015-08-04 15:58:41 +00004069 PROF_EVENT(MCPE_CHECK_MEM_IS_NOACCESS);
sewardjecf8e102003-07-12 12:11:39 +00004070 for (i = 0; i < len; i++) {
florian60042192015-08-04 15:58:41 +00004071 PROF_EVENT(MCPE_CHECK_MEM_IS_NOACCESS_LOOP);
njn1d0825f2006-03-27 11:37:07 +00004072 vabits2 = get_vabits2(a);
4073 if (VA_BITS2_NOACCESS != vabits2) {
4074 if (bad_addr != NULL) *bad_addr = a;
sewardjecf8e102003-07-12 12:11:39 +00004075 return False;
4076 }
4077 a++;
4078 }
4079 return True;
4080}
4081
sewardj7cf4e6b2008-05-01 20:24:26 +00004082static Bool is_mem_addressable ( Addr a, SizeT len,
4083 /*OUT*/Addr* bad_addr )
njn25e49d8e72002-09-23 09:36:25 +00004084{
nethercote451eae92004-11-02 13:06:32 +00004085 SizeT i;
njn1d0825f2006-03-27 11:37:07 +00004086 UWord vabits2;
4087
florian60042192015-08-04 15:58:41 +00004088 PROF_EVENT(MCPE_IS_MEM_ADDRESSABLE);
njn25e49d8e72002-09-23 09:36:25 +00004089 for (i = 0; i < len; i++) {
florian60042192015-08-04 15:58:41 +00004090 PROF_EVENT(MCPE_IS_MEM_ADDRESSABLE_LOOP);
njn1d0825f2006-03-27 11:37:07 +00004091 vabits2 = get_vabits2(a);
4092 if (VA_BITS2_NOACCESS == vabits2) {
njn25e49d8e72002-09-23 09:36:25 +00004093 if (bad_addr != NULL) *bad_addr = a;
4094 return False;
4095 }
4096 a++;
4097 }
4098 return True;
4099}
4100
sewardj7cf4e6b2008-05-01 20:24:26 +00004101static MC_ReadResult is_mem_defined ( Addr a, SizeT len,
4102 /*OUT*/Addr* bad_addr,
4103 /*OUT*/UInt* otag )
njn25e49d8e72002-09-23 09:36:25 +00004104{
nethercote451eae92004-11-02 13:06:32 +00004105 SizeT i;
njn1d0825f2006-03-27 11:37:07 +00004106 UWord vabits2;
njn25e49d8e72002-09-23 09:36:25 +00004107
florian60042192015-08-04 15:58:41 +00004108 PROF_EVENT(MCPE_IS_MEM_DEFINED);
njndbf7ca72006-03-31 11:57:59 +00004109 DEBUG("is_mem_defined\n");
sewardj7cf4e6b2008-05-01 20:24:26 +00004110
4111 if (otag) *otag = 0;
4112 if (bad_addr) *bad_addr = 0;
njn25e49d8e72002-09-23 09:36:25 +00004113 for (i = 0; i < len; i++) {
florian60042192015-08-04 15:58:41 +00004114 PROF_EVENT(MCPE_IS_MEM_DEFINED_LOOP);
njn1d0825f2006-03-27 11:37:07 +00004115 vabits2 = get_vabits2(a);
njndbf7ca72006-03-31 11:57:59 +00004116 if (VA_BITS2_DEFINED != vabits2) {
njn1d0825f2006-03-27 11:37:07 +00004117 // Error! Nb: Report addressability errors in preference to
4118 // definedness errors. And don't report definedeness errors unless
4119 // --undef-value-errors=yes.
sewardj7cf4e6b2008-05-01 20:24:26 +00004120 if (bad_addr) {
4121 *bad_addr = a;
4122 }
4123 if (VA_BITS2_NOACCESS == vabits2) {
4124 return MC_AddrErr;
4125 }
4126 if (MC_(clo_mc_level) >= 2) {
4127 if (otag && MC_(clo_mc_level) == 3) {
4128 *otag = MC_(helperc_b_load1)( a );
4129 }
4130 return MC_ValueErr;
4131 }
njn25e49d8e72002-09-23 09:36:25 +00004132 }
4133 a++;
4134 }
nethercote8b76fe52004-11-08 19:20:09 +00004135 return MC_Ok;
njn25e49d8e72002-09-23 09:36:25 +00004136}
4137
4138
sewardj4ef552a2011-10-24 05:59:54 +00004139/* Like is_mem_defined but doesn't give up at the first uninitialised
4140 byte -- the entire range is always checked. This is important for
4141 detecting errors in the case where a checked range strays into
4142 invalid memory, but that fact is not detected by the ordinary
4143 is_mem_defined(), because of an undefined section that precedes the
4144 out of range section, possibly as a result of an alignment hole in
4145 the checked data. This version always checks the entire range and
4146 can report both a definedness and an accessbility error, if
4147 necessary. */
4148static void is_mem_defined_comprehensive (
4149 Addr a, SizeT len,
4150 /*OUT*/Bool* errorV, /* is there a definedness err? */
4151 /*OUT*/Addr* bad_addrV, /* if so where? */
4152 /*OUT*/UInt* otagV, /* and what's its otag? */
4153 /*OUT*/Bool* errorA, /* is there an addressability err? */
4154 /*OUT*/Addr* bad_addrA /* if so where? */
4155 )
4156{
4157 SizeT i;
4158 UWord vabits2;
4159 Bool already_saw_errV = False;
4160
florian60042192015-08-04 15:58:41 +00004161 PROF_EVENT(MCPE_IS_MEM_DEFINED_COMPREHENSIVE);
sewardj4ef552a2011-10-24 05:59:54 +00004162 DEBUG("is_mem_defined_comprehensive\n");
4163
4164 tl_assert(!(*errorV || *errorA));
4165
4166 for (i = 0; i < len; i++) {
florian60042192015-08-04 15:58:41 +00004167 PROF_EVENT(MCPE_IS_MEM_DEFINED_COMPREHENSIVE_LOOP);
sewardj4ef552a2011-10-24 05:59:54 +00004168 vabits2 = get_vabits2(a);
4169 switch (vabits2) {
4170 case VA_BITS2_DEFINED:
4171 a++;
4172 break;
4173 case VA_BITS2_UNDEFINED:
4174 case VA_BITS2_PARTDEFINED:
4175 if (!already_saw_errV) {
4176 *errorV = True;
4177 *bad_addrV = a;
4178 if (MC_(clo_mc_level) == 3) {
4179 *otagV = MC_(helperc_b_load1)( a );
4180 } else {
4181 *otagV = 0;
4182 }
4183 already_saw_errV = True;
4184 }
4185 a++; /* keep going */
4186 break;
4187 case VA_BITS2_NOACCESS:
4188 *errorA = True;
4189 *bad_addrA = a;
4190 return; /* give up now. */
4191 default:
4192 tl_assert(0);
4193 }
4194 }
4195}
4196
4197
njn25e49d8e72002-09-23 09:36:25 +00004198/* Check a zero-terminated ascii string. Tricky -- don't want to
4199 examine the actual bytes, to find the end, until we're sure it is
4200 safe to do so. */
4201
sewardj7cf4e6b2008-05-01 20:24:26 +00004202static Bool mc_is_defined_asciiz ( Addr a, Addr* bad_addr, UInt* otag )
njn25e49d8e72002-09-23 09:36:25 +00004203{
njn1d0825f2006-03-27 11:37:07 +00004204 UWord vabits2;
4205
florian60042192015-08-04 15:58:41 +00004206 PROF_EVENT(MCPE_IS_DEFINED_ASCIIZ);
njndbf7ca72006-03-31 11:57:59 +00004207 DEBUG("mc_is_defined_asciiz\n");
sewardj7cf4e6b2008-05-01 20:24:26 +00004208
4209 if (otag) *otag = 0;
4210 if (bad_addr) *bad_addr = 0;
njn25e49d8e72002-09-23 09:36:25 +00004211 while (True) {
florian60042192015-08-04 15:58:41 +00004212 PROF_EVENT(MCPE_IS_DEFINED_ASCIIZ_LOOP);
njn1d0825f2006-03-27 11:37:07 +00004213 vabits2 = get_vabits2(a);
njndbf7ca72006-03-31 11:57:59 +00004214 if (VA_BITS2_DEFINED != vabits2) {
njn1d0825f2006-03-27 11:37:07 +00004215 // Error! Nb: Report addressability errors in preference to
4216 // definedness errors. And don't report definedeness errors unless
4217 // --undef-value-errors=yes.
sewardj7cf4e6b2008-05-01 20:24:26 +00004218 if (bad_addr) {
4219 *bad_addr = a;
4220 }
4221 if (VA_BITS2_NOACCESS == vabits2) {
4222 return MC_AddrErr;
4223 }
4224 if (MC_(clo_mc_level) >= 2) {
4225 if (otag && MC_(clo_mc_level) == 3) {
4226 *otag = MC_(helperc_b_load1)( a );
4227 }
4228 return MC_ValueErr;
4229 }
njn25e49d8e72002-09-23 09:36:25 +00004230 }
4231 /* Ok, a is safe to read. */
njn1d0825f2006-03-27 11:37:07 +00004232 if (* ((UChar*)a) == 0) {
sewardj45d94cc2005-04-20 14:44:11 +00004233 return MC_Ok;
njn1d0825f2006-03-27 11:37:07 +00004234 }
njn25e49d8e72002-09-23 09:36:25 +00004235 a++;
4236 }
4237}
4238
4239
4240/*------------------------------------------------------------*/
4241/*--- Memory event handlers ---*/
4242/*------------------------------------------------------------*/
4243
njn25e49d8e72002-09-23 09:36:25 +00004244static
floriane543f302012-10-21 19:43:43 +00004245void check_mem_is_addressable ( CorePart part, ThreadId tid, const HChar* s,
njndbf7ca72006-03-31 11:57:59 +00004246 Addr base, SizeT size )
njn25e49d8e72002-09-23 09:36:25 +00004247{
njn25e49d8e72002-09-23 09:36:25 +00004248 Addr bad_addr;
njndbf7ca72006-03-31 11:57:59 +00004249 Bool ok = is_mem_addressable ( base, size, &bad_addr );
njn25e49d8e72002-09-23 09:36:25 +00004250
njn25e49d8e72002-09-23 09:36:25 +00004251 if (!ok) {
4252 switch (part) {
4253 case Vg_CoreSysCall:
sewardj7ce71662008-05-02 10:33:15 +00004254 MC_(record_memparam_error) ( tid, bad_addr,
4255 /*isAddrErr*/True, s, 0/*otag*/ );
njn25e49d8e72002-09-23 09:36:25 +00004256 break;
4257
njn25e49d8e72002-09-23 09:36:25 +00004258 case Vg_CoreSignal:
njn1dcee092009-02-24 03:07:37 +00004259 MC_(record_core_mem_error)( tid, s );
njn25e49d8e72002-09-23 09:36:25 +00004260 break;
4261
4262 default:
njndbf7ca72006-03-31 11:57:59 +00004263 VG_(tool_panic)("check_mem_is_addressable: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +00004264 }
4265 }
njn25e49d8e72002-09-23 09:36:25 +00004266}
4267
4268static
floriane543f302012-10-21 19:43:43 +00004269void check_mem_is_defined ( CorePart part, ThreadId tid, const HChar* s,
nethercote451eae92004-11-02 13:06:32 +00004270 Addr base, SizeT size )
njn25e49d8e72002-09-23 09:36:25 +00004271{
sewardj7cf4e6b2008-05-01 20:24:26 +00004272 UInt otag = 0;
njn25e49d8e72002-09-23 09:36:25 +00004273 Addr bad_addr;
sewardj7cf4e6b2008-05-01 20:24:26 +00004274 MC_ReadResult res = is_mem_defined ( base, size, &bad_addr, &otag );
sewardj45f4e7c2005-09-27 19:20:21 +00004275
nethercote8b76fe52004-11-08 19:20:09 +00004276 if (MC_Ok != res) {
njn718d3b12006-12-16 00:54:12 +00004277 Bool isAddrErr = ( MC_AddrErr == res ? True : False );
sewardj45f4e7c2005-09-27 19:20:21 +00004278
njn25e49d8e72002-09-23 09:36:25 +00004279 switch (part) {
4280 case Vg_CoreSysCall:
sewardj7ce71662008-05-02 10:33:15 +00004281 MC_(record_memparam_error) ( tid, bad_addr, isAddrErr, s,
4282 isAddrErr ? 0 : otag );
njn25e49d8e72002-09-23 09:36:25 +00004283 break;
4284
njnf76d27a2009-05-28 01:53:07 +00004285 case Vg_CoreSysCallArgInMem:
4286 MC_(record_regparam_error) ( tid, s, otag );
4287 break;
4288
njn25e49d8e72002-09-23 09:36:25 +00004289 /* If we're being asked to jump to a silly address, record an error
4290 message before potentially crashing the entire system. */
4291 case Vg_CoreTranslate:
sewardj7ce71662008-05-02 10:33:15 +00004292 MC_(record_jump_error)( tid, bad_addr );
njn25e49d8e72002-09-23 09:36:25 +00004293 break;
4294
4295 default:
njndbf7ca72006-03-31 11:57:59 +00004296 VG_(tool_panic)("check_mem_is_defined: unexpected CorePart");
njn25e49d8e72002-09-23 09:36:25 +00004297 }
4298 }
njn25e49d8e72002-09-23 09:36:25 +00004299}
4300
4301static
njndbf7ca72006-03-31 11:57:59 +00004302void check_mem_is_defined_asciiz ( CorePart part, ThreadId tid,
floriane543f302012-10-21 19:43:43 +00004303 const HChar* s, Addr str )
njn25e49d8e72002-09-23 09:36:25 +00004304{
nethercote8b76fe52004-11-08 19:20:09 +00004305 MC_ReadResult res;
njn5ab96ac2005-05-08 02:59:50 +00004306 Addr bad_addr = 0; // shut GCC up
sewardj7cf4e6b2008-05-01 20:24:26 +00004307 UInt otag = 0;
njn25e49d8e72002-09-23 09:36:25 +00004308
njnca82cc02004-11-22 17:18:48 +00004309 tl_assert(part == Vg_CoreSysCall);
sewardj7cf4e6b2008-05-01 20:24:26 +00004310 res = mc_is_defined_asciiz ( (Addr)str, &bad_addr, &otag );
nethercote8b76fe52004-11-08 19:20:09 +00004311 if (MC_Ok != res) {
njn718d3b12006-12-16 00:54:12 +00004312 Bool isAddrErr = ( MC_AddrErr == res ? True : False );
sewardj7ce71662008-05-02 10:33:15 +00004313 MC_(record_memparam_error) ( tid, bad_addr, isAddrErr, s,
4314 isAddrErr ? 0 : otag );
njn25e49d8e72002-09-23 09:36:25 +00004315 }
njn25e49d8e72002-09-23 09:36:25 +00004316}
4317
sewardj6f95e7e2010-01-27 10:28:00 +00004318/* Handling of mmap and mprotect is not as simple as it seems.
4319
4320 The underlying semantics are that memory obtained from mmap is
4321 always initialised, but may be inaccessible. And changes to the
4322 protection of memory do not change its contents and hence not its
4323 definedness state. Problem is we can't model
4324 inaccessible-but-with-some-definedness state; once we mark memory
4325 as inaccessible we lose all info about definedness, and so can't
4326 restore that if it is later made accessible again.
4327
4328 One obvious thing to do is this:
4329
4330 mmap/mprotect NONE -> noaccess
4331 mmap/mprotect other -> defined
4332
4333 The problem case here is: taking accessible memory, writing
4334 uninitialised data to it, mprotecting it NONE and later mprotecting
4335 it back to some accessible state causes the undefinedness to be
4336 lost.
4337
4338 A better proposal is:
4339
4340 (1) mmap NONE -> make noaccess
4341 (2) mmap other -> make defined
4342
4343 (3) mprotect NONE -> # no change
4344 (4) mprotect other -> change any "noaccess" to "defined"
4345
4346 (2) is OK because memory newly obtained from mmap really is defined
4347 (zeroed out by the kernel -- doing anything else would
4348 constitute a massive security hole.)
4349
4350 (1) is OK because the only way to make the memory usable is via
4351 (4), in which case we also wind up correctly marking it all as
4352 defined.
4353
4354 (3) is the weak case. We choose not to change memory state.
4355 (presumably the range is in some mixture of "defined" and
4356 "undefined", viz, accessible but with arbitrary V bits). Doing
4357 nothing means we retain the V bits, so that if the memory is
4358 later mprotected "other", the V bits remain unchanged, so there
4359 can be no false negatives. The bad effect is that if there's
4360 an access in the area, then MC cannot warn; but at least we'll
4361 get a SEGV to show, so it's better than nothing.
4362
4363 Consider the sequence (3) followed by (4). Any memory that was
4364 "defined" or "undefined" previously retains its state (as
4365 required). Any memory that was "noaccess" before can only have
4366 been made that way by (1), and so it's OK to change it to
4367 "defined".
4368
4369 See https://bugs.kde.org/show_bug.cgi?id=205541
4370 and https://bugs.kde.org/show_bug.cgi?id=210268
4371*/
njn25e49d8e72002-09-23 09:36:25 +00004372static
njnf76d27a2009-05-28 01:53:07 +00004373void mc_new_mem_mmap ( Addr a, SizeT len, Bool rr, Bool ww, Bool xx,
4374 ULong di_handle )
4375{
sewardj6f95e7e2010-01-27 10:28:00 +00004376 if (rr || ww || xx) {
4377 /* (2) mmap/mprotect other -> defined */
njnf76d27a2009-05-28 01:53:07 +00004378 MC_(make_mem_defined)(a, len);
sewardj6f95e7e2010-01-27 10:28:00 +00004379 } else {
4380 /* (1) mmap/mprotect NONE -> noaccess */
njnf76d27a2009-05-28 01:53:07 +00004381 MC_(make_mem_noaccess)(a, len);
sewardj6f95e7e2010-01-27 10:28:00 +00004382 }
njnf76d27a2009-05-28 01:53:07 +00004383}
4384
4385static
sewardj6f95e7e2010-01-27 10:28:00 +00004386void mc_new_mem_mprotect ( Addr a, SizeT len, Bool rr, Bool ww, Bool xx )
4387{
4388 if (rr || ww || xx) {
4389 /* (4) mprotect other -> change any "noaccess" to "defined" */
4390 make_mem_defined_if_noaccess(a, len);
4391 } else {
4392 /* (3) mprotect NONE -> # no change */
4393 /* do nothing */
4394 }
4395}
4396
4397
4398static
sewardj9c606bd2008-09-18 18:12:50 +00004399void mc_new_mem_startup( Addr a, SizeT len,
4400 Bool rr, Bool ww, Bool xx, ULong di_handle )
njn25e49d8e72002-09-23 09:36:25 +00004401{
njnba7b4582006-09-21 15:59:30 +00004402 // Because code is defined, initialised variables get put in the data
4403 // segment and are defined, and uninitialised variables get put in the
4404 // bss segment and are auto-zeroed (and so defined).
4405 //
4406 // It's possible that there will be padding between global variables.
4407 // This will also be auto-zeroed, and marked as defined by Memcheck. If
4408 // a program uses it, Memcheck will not complain. This is arguably a
4409 // false negative, but it's a grey area -- the behaviour is defined (the
4410 // padding is zeroed) but it's probably not what the user intended. And
4411 // we can't avoid it.
njnf76d27a2009-05-28 01:53:07 +00004412 //
4413 // Note: we generally ignore RWX permissions, because we can't track them
4414 // without requiring more than one A bit which would slow things down a
4415 // lot. But on Darwin the 0th page is mapped but !R and !W and !X.
4416 // So we mark any such pages as "unaddressable".
barta0b6b2c2008-07-07 06:49:24 +00004417 DEBUG("mc_new_mem_startup(%#lx, %llu, rr=%u, ww=%u, xx=%u)\n",
njndbf7ca72006-03-31 11:57:59 +00004418 a, (ULong)len, rr, ww, xx);
njnf76d27a2009-05-28 01:53:07 +00004419 mc_new_mem_mmap(a, len, rr, ww, xx, di_handle);
njn25e49d8e72002-09-23 09:36:25 +00004420}
4421
njncf45fd42004-11-24 16:30:22 +00004422static
4423void mc_post_mem_write(CorePart part, ThreadId tid, Addr a, SizeT len)
4424{
njndbf7ca72006-03-31 11:57:59 +00004425 MC_(make_mem_defined)(a, len);
njncf45fd42004-11-24 16:30:22 +00004426}
njn25e49d8e72002-09-23 09:36:25 +00004427
sewardj45d94cc2005-04-20 14:44:11 +00004428
njn25e49d8e72002-09-23 09:36:25 +00004429/*------------------------------------------------------------*/
njnd3040452003-05-19 15:04:06 +00004430/*--- Register event handlers ---*/
4431/*------------------------------------------------------------*/
4432
sewardj7cf4e6b2008-05-01 20:24:26 +00004433/* Try and get a nonzero origin for the guest state section of thread
4434 tid characterised by (offset,size). Return 0 if nothing to show
4435 for it. */
4436static UInt mb_get_origin_for_guest_offset ( ThreadId tid,
4437 Int offset, SizeT size )
4438{
4439 Int sh2off;
florian3dfd6bb2012-03-03 18:46:05 +00004440 UInt area[3];
sewardj7cf4e6b2008-05-01 20:24:26 +00004441 UInt otag;
4442 sh2off = MC_(get_otrack_shadow_offset)( offset, size );
4443 if (sh2off == -1)
4444 return 0; /* This piece of guest state is not tracked */
4445 tl_assert(sh2off >= 0);
4446 tl_assert(0 == (sh2off % 4));
florian3dfd6bb2012-03-03 18:46:05 +00004447 area[0] = 0x31313131;
4448 area[2] = 0x27272727;
4449 VG_(get_shadow_regs_area)( tid, (UChar *)&area[1], 2/*shadowno*/,sh2off,4 );
4450 tl_assert(area[0] == 0x31313131);
4451 tl_assert(area[2] == 0x27272727);
4452 otag = area[1];
sewardj7cf4e6b2008-05-01 20:24:26 +00004453 return otag;
4454}
4455
4456
sewardj45d94cc2005-04-20 14:44:11 +00004457/* When some chunk of guest state is written, mark the corresponding
4458 shadow area as valid. This is used to initialise arbitrarily large
sewardj62eae5f2006-01-17 01:58:24 +00004459 chunks of guest state, hence the _SIZE value, which has to be as
4460 big as the biggest guest state.
sewardj45d94cc2005-04-20 14:44:11 +00004461*/
4462static void mc_post_reg_write ( CorePart part, ThreadId tid,
njnc4431bf2009-01-15 21:29:24 +00004463 PtrdiffT offset, SizeT size)
njnd3040452003-05-19 15:04:06 +00004464{
carll7cd6d832015-04-22 16:17:06 +00004465# define MAX_REG_WRITE_SIZE 1712
cerion21082042005-12-06 19:07:08 +00004466 UChar area[MAX_REG_WRITE_SIZE];
4467 tl_assert(size <= MAX_REG_WRITE_SIZE);
njn1d0825f2006-03-27 11:37:07 +00004468 VG_(memset)(area, V_BITS8_DEFINED, size);
sewardj7cf4e6b2008-05-01 20:24:26 +00004469 VG_(set_shadow_regs_area)( tid, 1/*shadowNo*/,offset,size, area );
cerion21082042005-12-06 19:07:08 +00004470# undef MAX_REG_WRITE_SIZE
njnd3040452003-05-19 15:04:06 +00004471}
4472
sewardj45d94cc2005-04-20 14:44:11 +00004473static
4474void mc_post_reg_write_clientcall ( ThreadId tid,
njnc4431bf2009-01-15 21:29:24 +00004475 PtrdiffT offset, SizeT size, Addr f)
njnd3040452003-05-19 15:04:06 +00004476{
njncf45fd42004-11-24 16:30:22 +00004477 mc_post_reg_write(/*dummy*/0, tid, offset, size);
njnd3040452003-05-19 15:04:06 +00004478}
4479
sewardj45d94cc2005-04-20 14:44:11 +00004480/* Look at the definedness of the guest's shadow state for
4481 [offset, offset+len). If any part of that is undefined, record
4482 a parameter error.
4483*/
floriane543f302012-10-21 19:43:43 +00004484static void mc_pre_reg_read ( CorePart part, ThreadId tid, const HChar* s,
njnc4431bf2009-01-15 21:29:24 +00004485 PtrdiffT offset, SizeT size)
nethercote8b76fe52004-11-08 19:20:09 +00004486{
sewardj45d94cc2005-04-20 14:44:11 +00004487 Int i;
4488 Bool bad;
sewardj7cf4e6b2008-05-01 20:24:26 +00004489 UInt otag;
sewardj45d94cc2005-04-20 14:44:11 +00004490
4491 UChar area[16];
4492 tl_assert(size <= 16);
4493
sewardj7cf4e6b2008-05-01 20:24:26 +00004494 VG_(get_shadow_regs_area)( tid, area, 1/*shadowNo*/,offset,size );
sewardj45d94cc2005-04-20 14:44:11 +00004495
4496 bad = False;
4497 for (i = 0; i < size; i++) {
njn1d0825f2006-03-27 11:37:07 +00004498 if (area[i] != V_BITS8_DEFINED) {
sewardj2c27f702005-05-03 18:19:05 +00004499 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00004500 break;
4501 }
nethercote8b76fe52004-11-08 19:20:09 +00004502 }
4503
sewardj7cf4e6b2008-05-01 20:24:26 +00004504 if (!bad)
4505 return;
4506
4507 /* We've found some undefinedness. See if we can also find an
4508 origin for it. */
4509 otag = mb_get_origin_for_guest_offset( tid, offset, size );
sewardj7ce71662008-05-02 10:33:15 +00004510 MC_(record_regparam_error) ( tid, s, otag );
nethercote8b76fe52004-11-08 19:20:09 +00004511}
njnd3040452003-05-19 15:04:06 +00004512
njn25e49d8e72002-09-23 09:36:25 +00004513
sewardj6cf40ff2005-04-20 22:31:26 +00004514/*------------------------------------------------------------*/
sewardj8eb8bab2015-07-21 14:44:28 +00004515/*--- Register-memory event handlers ---*/
4516/*------------------------------------------------------------*/
4517
4518static void mc_copy_mem_to_reg ( CorePart part, ThreadId tid, Addr a,
4519 PtrdiffT guest_state_offset, SizeT size )
4520{
4521 SizeT i;
4522 UChar vbits8;
4523 Int offset;
4524 UInt d32;
4525
4526 /* Slow loop. */
4527 for (i = 0; i < size; i++) {
4528 get_vbits8( a+i, &vbits8 );
4529 VG_(set_shadow_regs_area)( tid, 1/*shadowNo*/, guest_state_offset+i,
4530 1, &vbits8 );
4531 }
4532
4533 if (MC_(clo_mc_level) != 3)
4534 return;
4535
4536 /* Track origins. */
4537 offset = MC_(get_otrack_shadow_offset)( guest_state_offset, size );
4538 if (offset == -1)
4539 return;
4540
4541 switch (size) {
4542 case 1:
4543 d32 = MC_(helperc_b_load1)( a );
4544 break;
4545 case 2:
4546 d32 = MC_(helperc_b_load2)( a );
4547 break;
4548 case 4:
4549 d32 = MC_(helperc_b_load4)( a );
4550 break;
4551 case 8:
4552 d32 = MC_(helperc_b_load8)( a );
4553 break;
4554 case 16:
4555 d32 = MC_(helperc_b_load16)( a );
4556 break;
4557 case 32:
4558 d32 = MC_(helperc_b_load32)( a );
4559 break;
4560 default:
4561 tl_assert(0);
4562 }
4563
4564 VG_(set_shadow_regs_area)( tid, 2/*shadowNo*/, offset, 4, (UChar*)&d32 );
4565}
4566
4567static void mc_copy_reg_to_mem ( CorePart part, ThreadId tid,
4568 PtrdiffT guest_state_offset, Addr a,
4569 SizeT size )
4570{
4571 SizeT i;
4572 UChar vbits8;
4573 Int offset;
4574 UInt d32;
4575
4576 /* Slow loop. */
4577 for (i = 0; i < size; i++) {
4578 VG_(get_shadow_regs_area)( tid, &vbits8, 1/*shadowNo*/,
4579 guest_state_offset+i, 1 );
4580 set_vbits8( a+i, vbits8 );
4581 }
4582
4583 if (MC_(clo_mc_level) != 3)
4584 return;
4585
4586 /* Track origins. */
4587 offset = MC_(get_otrack_shadow_offset)( guest_state_offset, size );
4588 if (offset == -1)
4589 return;
4590
4591 VG_(get_shadow_regs_area)( tid, (UChar*)&d32, 2/*shadowNo*/, offset, 4 );
4592 switch (size) {
4593 case 1:
4594 MC_(helperc_b_store1)( a, d32 );
4595 break;
4596 case 2:
4597 MC_(helperc_b_store2)( a, d32 );
4598 break;
4599 case 4:
4600 MC_(helperc_b_store4)( a, d32 );
4601 break;
4602 case 8:
4603 MC_(helperc_b_store8)( a, d32 );
4604 break;
4605 case 16:
4606 MC_(helperc_b_store16)( a, d32 );
4607 break;
4608 case 32:
4609 MC_(helperc_b_store32)( a, d32 );
4610 break;
4611 default:
4612 tl_assert(0);
4613 }
4614}
4615
4616
4617/*------------------------------------------------------------*/
sewardj7b1f9eb2015-06-05 13:33:46 +00004618/*--- Some static assertions ---*/
4619/*------------------------------------------------------------*/
4620
4621/* The handwritten assembly helpers below have baked-in assumptions
4622 about various constant values. These assertions attempt to make
4623 that a bit safer by checking those values and flagging changes that
4624 would make the assembly invalid. Not perfect but it's better than
4625 nothing. */
4626
4627STATIC_ASSERT(SM_CHUNKS * 4 == 65536);
4628
4629STATIC_ASSERT(VA_BITS8_DEFINED == 0xAA);
4630STATIC_ASSERT(VA_BITS8_UNDEFINED == 0x55);
4631
4632STATIC_ASSERT(V_BITS32_DEFINED == 0x00000000);
4633STATIC_ASSERT(V_BITS32_UNDEFINED == 0xFFFFFFFF);
4634
4635STATIC_ASSERT(VA_BITS4_DEFINED == 0xA);
4636STATIC_ASSERT(VA_BITS4_UNDEFINED == 0x5);
4637
4638STATIC_ASSERT(V_BITS16_DEFINED == 0x0000);
4639STATIC_ASSERT(V_BITS16_UNDEFINED == 0xFFFF);
4640
4641STATIC_ASSERT(VA_BITS2_DEFINED == 2);
4642STATIC_ASSERT(VA_BITS2_UNDEFINED == 1);
4643
4644STATIC_ASSERT(V_BITS8_DEFINED == 0x00);
4645STATIC_ASSERT(V_BITS8_UNDEFINED == 0xFF);
4646
4647
4648/*------------------------------------------------------------*/
sewardjc859fbf2005-04-22 21:10:28 +00004649/*--- Functions called directly from generated code: ---*/
4650/*--- Load/store handlers. ---*/
sewardj6cf40ff2005-04-20 22:31:26 +00004651/*------------------------------------------------------------*/
4652
njn1d0825f2006-03-27 11:37:07 +00004653/* Types: LOADV32, LOADV16, LOADV8 are:
sewardj6cf40ff2005-04-20 22:31:26 +00004654 UWord fn ( Addr a )
4655 so they return 32-bits on 32-bit machines and 64-bits on
4656 64-bit machines. Addr has the same size as a host word.
4657
njn1d0825f2006-03-27 11:37:07 +00004658 LOADV64 is always ULong fn ( Addr a )
sewardj6cf40ff2005-04-20 22:31:26 +00004659
njn1d0825f2006-03-27 11:37:07 +00004660 Similarly for STOREV8, STOREV16, STOREV32, the supplied vbits
4661 are a UWord, and for STOREV64 they are a ULong.
sewardj6cf40ff2005-04-20 22:31:26 +00004662*/
4663
sewardj7244e712008-05-02 12:35:48 +00004664/* If any part of '_a' indicated by the mask is 1, either '_a' is not
4665 naturally '_sz/8'-aligned, or it exceeds the range covered by the
4666 primary map. This is all very tricky (and important!), so let's
4667 work through the maths by hand (below), *and* assert for these
4668 values at startup. */
4669#define MASK(_szInBytes) \
4670 ( ~((0x10000UL-(_szInBytes)) | ((N_PRIMARY_MAP-1) << 16)) )
4671
4672/* MASK only exists so as to define this macro. */
4673#define UNALIGNED_OR_HIGH(_a,_szInBits) \
4674 ((_a) & MASK((_szInBits>>3)))
4675
4676/* On a 32-bit machine:
4677
4678 N_PRIMARY_BITS == 16, so
4679 N_PRIMARY_MAP == 0x10000, so
4680 N_PRIMARY_MAP-1 == 0xFFFF, so
4681 (N_PRIMARY_MAP-1) << 16 == 0xFFFF0000, and so
4682
4683 MASK(1) = ~ ( (0x10000 - 1) | 0xFFFF0000 )
4684 = ~ ( 0xFFFF | 0xFFFF0000 )
4685 = ~ 0xFFFF'FFFF
4686 = 0
4687
4688 MASK(2) = ~ ( (0x10000 - 2) | 0xFFFF0000 )
4689 = ~ ( 0xFFFE | 0xFFFF0000 )
4690 = ~ 0xFFFF'FFFE
4691 = 1
4692
4693 MASK(4) = ~ ( (0x10000 - 4) | 0xFFFF0000 )
4694 = ~ ( 0xFFFC | 0xFFFF0000 )
4695 = ~ 0xFFFF'FFFC
4696 = 3
4697
4698 MASK(8) = ~ ( (0x10000 - 8) | 0xFFFF0000 )
4699 = ~ ( 0xFFF8 | 0xFFFF0000 )
4700 = ~ 0xFFFF'FFF8
4701 = 7
4702
4703 Hence in the 32-bit case, "a & MASK(1/2/4/8)" is a nonzero value
4704 precisely when a is not 1/2/4/8-bytes aligned. And obviously, for
4705 the 1-byte alignment case, it is always a zero value, since MASK(1)
4706 is zero. All as expected.
4707
4708 On a 64-bit machine, it's more complex, since we're testing
4709 simultaneously for misalignment and for the address being at or
sewardj21a5f8c2013-08-08 10:41:46 +00004710 above 64G:
sewardj7244e712008-05-02 12:35:48 +00004711
sewardj21a5f8c2013-08-08 10:41:46 +00004712 N_PRIMARY_BITS == 20, so
4713 N_PRIMARY_MAP == 0x100000, so
4714 N_PRIMARY_MAP-1 == 0xFFFFF, so
4715 (N_PRIMARY_MAP-1) << 16 == 0xF'FFFF'0000, and so
sewardj7244e712008-05-02 12:35:48 +00004716
sewardj21a5f8c2013-08-08 10:41:46 +00004717 MASK(1) = ~ ( (0x10000 - 1) | 0xF'FFFF'0000 )
4718 = ~ ( 0xFFFF | 0xF'FFFF'0000 )
4719 = ~ 0xF'FFFF'FFFF
4720 = 0xFFFF'FFF0'0000'0000
sewardj7244e712008-05-02 12:35:48 +00004721
sewardj21a5f8c2013-08-08 10:41:46 +00004722 MASK(2) = ~ ( (0x10000 - 2) | 0xF'FFFF'0000 )
4723 = ~ ( 0xFFFE | 0xF'FFFF'0000 )
4724 = ~ 0xF'FFFF'FFFE
4725 = 0xFFFF'FFF0'0000'0001
sewardj7244e712008-05-02 12:35:48 +00004726
sewardj21a5f8c2013-08-08 10:41:46 +00004727 MASK(4) = ~ ( (0x10000 - 4) | 0xF'FFFF'0000 )
4728 = ~ ( 0xFFFC | 0xF'FFFF'0000 )
4729 = ~ 0xF'FFFF'FFFC
4730 = 0xFFFF'FFF0'0000'0003
sewardj7244e712008-05-02 12:35:48 +00004731
sewardj21a5f8c2013-08-08 10:41:46 +00004732 MASK(8) = ~ ( (0x10000 - 8) | 0xF'FFFF'0000 )
4733 = ~ ( 0xFFF8 | 0xF'FFFF'0000 )
4734 = ~ 0xF'FFFF'FFF8
4735 = 0xFFFF'FFF0'0000'0007
sewardj7244e712008-05-02 12:35:48 +00004736*/
njn1d0825f2006-03-27 11:37:07 +00004737
sewardjb9437c52015-07-20 13:11:03 +00004738/*------------------------------------------------------------*/
4739/*--- LOADV256 and LOADV128 ---*/
4740/*------------------------------------------------------------*/
sewardj21a5f8c2013-08-08 10:41:46 +00004741
4742static INLINE
sewardj92ef91b2013-08-18 10:20:22 +00004743void mc_LOADV_128_or_256 ( /*OUT*/ULong* res,
4744 Addr a, SizeT nBits, Bool isBigEndian )
sewardj21a5f8c2013-08-08 10:41:46 +00004745{
florian60042192015-08-04 15:58:41 +00004746 PROF_EVENT(MCPE_LOADV_128_OR_256);
sewardj21a5f8c2013-08-08 10:41:46 +00004747
4748#ifndef PERF_FAST_LOADV
sewardj92ef91b2013-08-18 10:20:22 +00004749 mc_LOADV_128_or_256_slow( res, a, nBits, isBigEndian );
sewardj21a5f8c2013-08-08 10:41:46 +00004750 return;
4751#else
4752 {
sewardj92ef91b2013-08-18 10:20:22 +00004753 UWord sm_off16, vabits16, j;
4754 UWord nBytes = nBits / 8;
4755 UWord nULongs = nBytes / 8;
sewardj21a5f8c2013-08-08 10:41:46 +00004756 SecMap* sm;
sewardj21a5f8c2013-08-08 10:41:46 +00004757
sewardj67564542013-08-16 08:31:29 +00004758 if (UNLIKELY( UNALIGNED_OR_HIGH(a,nBits) )) {
florian60042192015-08-04 15:58:41 +00004759 PROF_EVENT(MCPE_LOADV_128_OR_256_SLOW1);
sewardj92ef91b2013-08-18 10:20:22 +00004760 mc_LOADV_128_or_256_slow( res, a, nBits, isBigEndian );
sewardj21a5f8c2013-08-08 10:41:46 +00004761 return;
4762 }
4763
sewardj67564542013-08-16 08:31:29 +00004764 /* Handle common cases quickly: a (and a+8 and a+16 etc.) is
4765 suitably aligned, is mapped, and addressible. */
sewardj92ef91b2013-08-18 10:20:22 +00004766 for (j = 0; j < nULongs; j++) {
sewardj21a5f8c2013-08-08 10:41:46 +00004767 sm = get_secmap_for_reading_low(a + 8*j);
4768 sm_off16 = SM_OFF_16(a + 8*j);
4769 vabits16 = ((UShort*)(sm->vabits8))[sm_off16];
4770
4771 // Convert V bits from compact memory form to expanded
4772 // register form.
4773 if (LIKELY(vabits16 == VA_BITS16_DEFINED)) {
sewardj67564542013-08-16 08:31:29 +00004774 res[j] = V_BITS64_DEFINED;
sewardj21a5f8c2013-08-08 10:41:46 +00004775 } else if (LIKELY(vabits16 == VA_BITS16_UNDEFINED)) {
sewardj67564542013-08-16 08:31:29 +00004776 res[j] = V_BITS64_UNDEFINED;
sewardj21a5f8c2013-08-08 10:41:46 +00004777 } else {
4778 /* Slow case: some block of 8 bytes are not all-defined or
4779 all-undefined. */
florian60042192015-08-04 15:58:41 +00004780 PROF_EVENT(MCPE_LOADV_128_OR_256_SLOW2);
sewardj92ef91b2013-08-18 10:20:22 +00004781 mc_LOADV_128_or_256_slow( res, a, nBits, isBigEndian );
sewardj21a5f8c2013-08-08 10:41:46 +00004782 return;
4783 }
4784 }
4785 return;
4786 }
4787#endif
4788}
4789
sewardj67564542013-08-16 08:31:29 +00004790VG_REGPARM(2) void MC_(helperc_LOADV256be) ( /*OUT*/V256* res, Addr a )
4791{
sewardj92ef91b2013-08-18 10:20:22 +00004792 mc_LOADV_128_or_256(&res->w64[0], a, 256, True);
sewardj67564542013-08-16 08:31:29 +00004793}
4794VG_REGPARM(2) void MC_(helperc_LOADV256le) ( /*OUT*/V256* res, Addr a )
4795{
sewardj92ef91b2013-08-18 10:20:22 +00004796 mc_LOADV_128_or_256(&res->w64[0], a, 256, False);
sewardj67564542013-08-16 08:31:29 +00004797}
4798
sewardj21a5f8c2013-08-08 10:41:46 +00004799VG_REGPARM(2) void MC_(helperc_LOADV128be) ( /*OUT*/V128* res, Addr a )
4800{
sewardj92ef91b2013-08-18 10:20:22 +00004801 mc_LOADV_128_or_256(&res->w64[0], a, 128, True);
sewardj21a5f8c2013-08-08 10:41:46 +00004802}
4803VG_REGPARM(2) void MC_(helperc_LOADV128le) ( /*OUT*/V128* res, Addr a )
4804{
sewardj92ef91b2013-08-18 10:20:22 +00004805 mc_LOADV_128_or_256(&res->w64[0], a, 128, False);
sewardj21a5f8c2013-08-08 10:41:46 +00004806}
4807
sewardjb9437c52015-07-20 13:11:03 +00004808/*------------------------------------------------------------*/
4809/*--- LOADV64 ---*/
4810/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00004811
njn1d0825f2006-03-27 11:37:07 +00004812static INLINE
4813ULong mc_LOADV64 ( Addr a, Bool isBigEndian )
4814{
florian60042192015-08-04 15:58:41 +00004815 PROF_EVENT(MCPE_LOADV64);
njn1d0825f2006-03-27 11:37:07 +00004816
4817#ifndef PERF_FAST_LOADV
njn45e81252006-03-28 12:35:08 +00004818 return mc_LOADVn_slow( a, 64, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00004819#else
njneccf7c02009-01-19 23:42:45 +00004820 {
4821 UWord sm_off16, vabits16;
4822 SecMap* sm;
sewardjf9d81612005-04-23 23:25:49 +00004823
njneccf7c02009-01-19 23:42:45 +00004824 if (UNLIKELY( UNALIGNED_OR_HIGH(a,64) )) {
florian60042192015-08-04 15:58:41 +00004825 PROF_EVENT(MCPE_LOADV64_SLOW1);
njneccf7c02009-01-19 23:42:45 +00004826 return (ULong)mc_LOADVn_slow( a, 64, isBigEndian );
4827 }
njn1d0825f2006-03-27 11:37:07 +00004828
njneccf7c02009-01-19 23:42:45 +00004829 sm = get_secmap_for_reading_low(a);
4830 sm_off16 = SM_OFF_16(a);
4831 vabits16 = ((UShort*)(sm->vabits8))[sm_off16];
4832
4833 // Handle common case quickly: a is suitably aligned, is mapped, and
4834 // addressible.
4835 // Convert V bits from compact memory form to expanded register form.
4836 if (LIKELY(vabits16 == VA_BITS16_DEFINED)) {
4837 return V_BITS64_DEFINED;
4838 } else if (LIKELY(vabits16 == VA_BITS16_UNDEFINED)) {
4839 return V_BITS64_UNDEFINED;
4840 } else {
4841 /* Slow case: the 8 bytes are not all-defined or all-undefined. */
florian60042192015-08-04 15:58:41 +00004842 PROF_EVENT(MCPE_LOADV64_SLOW2);
njneccf7c02009-01-19 23:42:45 +00004843 return mc_LOADVn_slow( a, 64, isBigEndian );
4844 }
njn1d0825f2006-03-27 11:37:07 +00004845 }
4846#endif
4847}
4848
sewardj2ce9ac22015-07-20 09:59:25 +00004849// Generic for all platforms
njn1d0825f2006-03-27 11:37:07 +00004850VG_REGPARM(1) ULong MC_(helperc_LOADV64be) ( Addr a )
4851{
4852 return mc_LOADV64(a, True);
4853}
sewardj2ce9ac22015-07-20 09:59:25 +00004854
4855// Non-generic assembly for arm32-linux
4856#if ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \
4857 && defined(VGP_arm_linux)
4858__asm__( /* Derived from the 32 bit assembly helper */
4859".text \n"
4860".align 2 \n"
4861".global vgMemCheck_helperc_LOADV64le \n"
4862".type vgMemCheck_helperc_LOADV64le, %function \n"
4863"vgMemCheck_helperc_LOADV64le: \n"
4864" tst r0, #7 \n"
4865" movw r3, #:lower16:primary_map \n"
4866" bne .LLV64LEc4 \n" // if misaligned
4867" lsr r2, r0, #16 \n"
4868" movt r3, #:upper16:primary_map \n"
4869" ldr r2, [r3, r2, lsl #2] \n"
4870" uxth r1, r0 \n" // r1 is 0-(16)-0 X-(13)-X 000
4871" movw r3, #0xAAAA \n"
sewardj704f46b2015-07-21 15:38:43 +00004872" lsr r1, r1, #2 \n" // r1 is 0-(16)-0 00 X-(13)-X 0
sewardj2ce9ac22015-07-20 09:59:25 +00004873" ldrh r1, [r2, r1] \n"
4874" cmp r1, r3 \n" // 0xAAAA == VA_BITS16_DEFINED
4875" bne .LLV64LEc0 \n" // if !all_defined
4876" mov r1, #0x0 \n" // 0x0 == V_BITS32_DEFINED
4877" mov r0, #0x0 \n" // 0x0 == V_BITS32_DEFINED
4878" bx lr \n"
4879".LLV64LEc0: \n"
4880" movw r3, #0x5555 \n"
4881" cmp r1, r3 \n" // 0x5555 == VA_BITS16_UNDEFINED
4882" bne .LLV64LEc4 \n" // if !all_undefined
4883" mov r1, #0xFFFFFFFF \n" // 0xFFFFFFFF == V_BITS32_UNDEFINED
4884" mov r0, #0xFFFFFFFF \n" // 0xFFFFFFFF == V_BITS32_UNDEFINED
4885" bx lr \n"
4886".LLV64LEc4: \n"
4887" push {r4, lr} \n"
4888" mov r2, #0 \n"
4889" mov r1, #64 \n"
4890" bl mc_LOADVn_slow \n"
4891" pop {r4, pc} \n"
4892".size vgMemCheck_helperc_LOADV64le, .-vgMemCheck_helperc_LOADV64le \n"
4893".previous\n"
4894);
4895
sewardjb9437c52015-07-20 13:11:03 +00004896#elif ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \
iraisr0e654912015-07-31 16:12:44 +00004897 && (defined(VGP_x86_linux) || defined(VGP_x86_solaris))
sewardjb9437c52015-07-20 13:11:03 +00004898__asm__(
4899".text\n"
4900".align 16\n"
4901".global vgMemCheck_helperc_LOADV64le\n"
4902".type vgMemCheck_helperc_LOADV64le, @function\n"
4903"vgMemCheck_helperc_LOADV64le:\n"
4904" test $0x7, %eax\n"
4905" jne .LLV64LE2\n" /* jump if not aligned */
4906" mov %eax, %ecx\n"
4907" movzwl %ax, %edx\n"
4908" shr $0x10, %ecx\n"
4909" mov primary_map(,%ecx,4), %ecx\n"
4910" shr $0x3, %edx\n"
4911" movzwl (%ecx,%edx,2), %edx\n"
4912" cmp $0xaaaa, %edx\n"
4913" jne .LLV64LE1\n" /* jump if not all defined */
4914" xor %eax, %eax\n" /* return 0 in edx:eax */
4915" xor %edx, %edx\n"
4916" ret\n"
4917".LLV64LE1:\n"
4918" cmp $0x5555, %edx\n"
4919" jne .LLV64LE2\n" /* jump if not all undefined */
4920" or $0xffffffff, %eax\n" /* else return all bits set in edx:eax */
4921" or $0xffffffff, %edx\n"
4922" ret\n"
4923".LLV64LE2:\n"
4924" xor %ecx, %ecx\n" /* tail call to mc_LOADVn_slow(a, 64, 0) */
4925" mov $64, %edx\n"
4926" jmp mc_LOADVn_slow\n"
4927".size vgMemCheck_helperc_LOADV64le, .-vgMemCheck_helperc_LOADV64le\n"
4928".previous\n"
4929);
4930
sewardj2ce9ac22015-07-20 09:59:25 +00004931#else
iraisr0e654912015-07-31 16:12:44 +00004932// Generic for all platforms except {arm32,x86}-linux and x86-solaris
njn1d0825f2006-03-27 11:37:07 +00004933VG_REGPARM(1) ULong MC_(helperc_LOADV64le) ( Addr a )
4934{
4935 return mc_LOADV64(a, False);
4936}
sewardj2ce9ac22015-07-20 09:59:25 +00004937#endif
sewardjf9d81612005-04-23 23:25:49 +00004938
sewardjb9437c52015-07-20 13:11:03 +00004939/*------------------------------------------------------------*/
4940/*--- STOREV64 ---*/
4941/*------------------------------------------------------------*/
sewardjf9d81612005-04-23 23:25:49 +00004942
njn1d0825f2006-03-27 11:37:07 +00004943static INLINE
njn4cf530b2006-04-06 13:33:48 +00004944void mc_STOREV64 ( Addr a, ULong vbits64, Bool isBigEndian )
njn1d0825f2006-03-27 11:37:07 +00004945{
florian60042192015-08-04 15:58:41 +00004946 PROF_EVENT(MCPE_STOREV64);
njn1d0825f2006-03-27 11:37:07 +00004947
4948#ifndef PERF_FAST_STOREV
4949 // XXX: this slow case seems to be marginally faster than the fast case!
4950 // Investigate further.
njn4cf530b2006-04-06 13:33:48 +00004951 mc_STOREVn_slow( a, 64, vbits64, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00004952#else
njn1d0825f2006-03-27 11:37:07 +00004953 {
njneccf7c02009-01-19 23:42:45 +00004954 UWord sm_off16, vabits16;
4955 SecMap* sm;
4956
4957 if (UNLIKELY( UNALIGNED_OR_HIGH(a,64) )) {
florian60042192015-08-04 15:58:41 +00004958 PROF_EVENT(MCPE_STOREV64_SLOW1);
njneccf7c02009-01-19 23:42:45 +00004959 mc_STOREVn_slow( a, 64, vbits64, isBigEndian );
4960 return;
4961 }
4962
4963 sm = get_secmap_for_reading_low(a);
4964 sm_off16 = SM_OFF_16(a);
4965 vabits16 = ((UShort*)(sm->vabits8))[sm_off16];
4966
philippeb8ac5ac2014-04-22 22:07:01 +00004967 // To understand the below cleverness, see the extensive comments
4968 // in MC_(helperc_STOREV8).
4969 if (LIKELY(V_BITS64_DEFINED == vbits64)) {
4970 if (LIKELY(vabits16 == (UShort)VA_BITS16_DEFINED)) {
4971 return;
njneccf7c02009-01-19 23:42:45 +00004972 }
philippeb8ac5ac2014-04-22 22:07:01 +00004973 if (!is_distinguished_sm(sm) && VA_BITS16_UNDEFINED == vabits16) {
4974 ((UShort*)(sm->vabits8))[sm_off16] = (UShort)VA_BITS16_DEFINED;
4975 return;
4976 }
florian60042192015-08-04 15:58:41 +00004977 PROF_EVENT(MCPE_STOREV64_SLOW2);
njn4cf530b2006-04-06 13:33:48 +00004978 mc_STOREVn_slow( a, 64, vbits64, isBigEndian );
philippeb8ac5ac2014-04-22 22:07:01 +00004979 return;
njn1d0825f2006-03-27 11:37:07 +00004980 }
philippeb8ac5ac2014-04-22 22:07:01 +00004981 if (V_BITS64_UNDEFINED == vbits64) {
4982 if (vabits16 == (UShort)VA_BITS16_UNDEFINED) {
4983 return;
4984 }
4985 if (!is_distinguished_sm(sm) && VA_BITS16_DEFINED == vabits16) {
4986 ((UShort*)(sm->vabits8))[sm_off16] = (UShort)VA_BITS16_UNDEFINED;
4987 return;
4988 }
florian60042192015-08-04 15:58:41 +00004989 PROF_EVENT(MCPE_STOREV64_SLOW3);
philippeb8ac5ac2014-04-22 22:07:01 +00004990 mc_STOREVn_slow( a, 64, vbits64, isBigEndian );
4991 return;
4992 }
4993
florian60042192015-08-04 15:58:41 +00004994 PROF_EVENT(MCPE_STOREV64_SLOW4);
philippeb8ac5ac2014-04-22 22:07:01 +00004995 mc_STOREVn_slow( a, 64, vbits64, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00004996 }
4997#endif
4998}
4999
njn4cf530b2006-04-06 13:33:48 +00005000VG_REGPARM(1) void MC_(helperc_STOREV64be) ( Addr a, ULong vbits64 )
njn1d0825f2006-03-27 11:37:07 +00005001{
njn4cf530b2006-04-06 13:33:48 +00005002 mc_STOREV64(a, vbits64, True);
njn1d0825f2006-03-27 11:37:07 +00005003}
njn4cf530b2006-04-06 13:33:48 +00005004VG_REGPARM(1) void MC_(helperc_STOREV64le) ( Addr a, ULong vbits64 )
njn1d0825f2006-03-27 11:37:07 +00005005{
njn4cf530b2006-04-06 13:33:48 +00005006 mc_STOREV64(a, vbits64, False);
njn1d0825f2006-03-27 11:37:07 +00005007}
sewardj95448072004-11-22 20:19:51 +00005008
sewardjb9437c52015-07-20 13:11:03 +00005009/*------------------------------------------------------------*/
5010/*--- LOADV32 ---*/
5011/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00005012
njn1d0825f2006-03-27 11:37:07 +00005013static INLINE
5014UWord mc_LOADV32 ( Addr a, Bool isBigEndian )
5015{
florian60042192015-08-04 15:58:41 +00005016 PROF_EVENT(MCPE_LOADV32);
njn1d0825f2006-03-27 11:37:07 +00005017
5018#ifndef PERF_FAST_LOADV
njn45e81252006-03-28 12:35:08 +00005019 return (UWord)mc_LOADVn_slow( a, 32, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00005020#else
njneccf7c02009-01-19 23:42:45 +00005021 {
5022 UWord sm_off, vabits8;
5023 SecMap* sm;
sewardjc1a2cda2005-04-21 17:34:00 +00005024
njneccf7c02009-01-19 23:42:45 +00005025 if (UNLIKELY( UNALIGNED_OR_HIGH(a,32) )) {
florian60042192015-08-04 15:58:41 +00005026 PROF_EVENT(MCPE_LOADV32_SLOW1);
njneccf7c02009-01-19 23:42:45 +00005027 return (UWord)mc_LOADVn_slow( a, 32, isBigEndian );
5028 }
njn1d0825f2006-03-27 11:37:07 +00005029
njneccf7c02009-01-19 23:42:45 +00005030 sm = get_secmap_for_reading_low(a);
5031 sm_off = SM_OFF(a);
5032 vabits8 = sm->vabits8[sm_off];
5033
5034 // Handle common case quickly: a is suitably aligned, is mapped, and the
5035 // entire word32 it lives in is addressible.
5036 // Convert V bits from compact memory form to expanded register form.
5037 // For 64-bit platforms, set the high 32 bits of retval to 1 (undefined).
5038 // Almost certainly not necessary, but be paranoid.
5039 if (LIKELY(vabits8 == VA_BITS8_DEFINED)) {
5040 return ((UWord)0xFFFFFFFF00000000ULL | (UWord)V_BITS32_DEFINED);
5041 } else if (LIKELY(vabits8 == VA_BITS8_UNDEFINED)) {
5042 return ((UWord)0xFFFFFFFF00000000ULL | (UWord)V_BITS32_UNDEFINED);
5043 } else {
5044 /* Slow case: the 4 bytes are not all-defined or all-undefined. */
florian60042192015-08-04 15:58:41 +00005045 PROF_EVENT(MCPE_LOADV32_SLOW2);
njneccf7c02009-01-19 23:42:45 +00005046 return (UWord)mc_LOADVn_slow( a, 32, isBigEndian );
5047 }
njn1d0825f2006-03-27 11:37:07 +00005048 }
5049#endif
5050}
5051
sewardj7b1f9eb2015-06-05 13:33:46 +00005052// Generic for all platforms
njn1d0825f2006-03-27 11:37:07 +00005053VG_REGPARM(1) UWord MC_(helperc_LOADV32be) ( Addr a )
5054{
5055 return mc_LOADV32(a, True);
5056}
sewardj7b1f9eb2015-06-05 13:33:46 +00005057
5058// Non-generic assembly for arm32-linux
5059#if ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \
5060 && defined(VGP_arm_linux)
5061__asm__( /* Derived from NCode template */
5062".text \n"
5063".align 2 \n"
5064".global vgMemCheck_helperc_LOADV32le \n"
5065".type vgMemCheck_helperc_LOADV32le, %function \n"
5066"vgMemCheck_helperc_LOADV32le: \n"
5067" tst r0, #3 \n" // 1
5068" movw r3, #:lower16:primary_map \n" // 1
sewardj2ce9ac22015-07-20 09:59:25 +00005069" bne .LLV32LEc4 \n" // 2 if misaligned
sewardj7b1f9eb2015-06-05 13:33:46 +00005070" lsr r2, r0, #16 \n" // 3
5071" movt r3, #:upper16:primary_map \n" // 3
5072" ldr r2, [r3, r2, lsl #2] \n" // 4
5073" uxth r1, r0 \n" // 4
5074" ldrb r1, [r2, r1, lsr #2] \n" // 5
5075" cmp r1, #0xAA \n" // 6 0xAA == VA_BITS8_DEFINED
sewardj2ce9ac22015-07-20 09:59:25 +00005076" bne .LLV32LEc0 \n" // 7 if !all_defined
sewardj7b1f9eb2015-06-05 13:33:46 +00005077" mov r0, #0x0 \n" // 8 0x0 == V_BITS32_DEFINED
5078" bx lr \n" // 9
sewardj2ce9ac22015-07-20 09:59:25 +00005079".LLV32LEc0: \n"
sewardj7b1f9eb2015-06-05 13:33:46 +00005080" cmp r1, #0x55 \n" // 0x55 == VA_BITS8_UNDEFINED
sewardj2ce9ac22015-07-20 09:59:25 +00005081" bne .LLV32LEc4 \n" // if !all_undefined
sewardj7b1f9eb2015-06-05 13:33:46 +00005082" mov r0, #0xFFFFFFFF \n" // 0xFFFFFFFF == V_BITS32_UNDEFINED
5083" bx lr \n"
sewardj2ce9ac22015-07-20 09:59:25 +00005084".LLV32LEc4: \n"
sewardj7b1f9eb2015-06-05 13:33:46 +00005085" push {r4, lr} \n"
5086" mov r2, #0 \n"
5087" mov r1, #32 \n"
5088" bl mc_LOADVn_slow \n"
5089" pop {r4, pc} \n"
5090".size vgMemCheck_helperc_LOADV32le, .-vgMemCheck_helperc_LOADV32le \n"
5091".previous\n"
5092);
5093
sewardjb9437c52015-07-20 13:11:03 +00005094#elif ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \
iraisr0e654912015-07-31 16:12:44 +00005095 && (defined(VGP_x86_linux) || defined(VGP_x86_solaris))
sewardjb9437c52015-07-20 13:11:03 +00005096__asm__(
5097".text\n"
5098".align 16\n"
5099".global vgMemCheck_helperc_LOADV32le\n"
5100".type vgMemCheck_helperc_LOADV32le, @function\n"
5101"vgMemCheck_helperc_LOADV32le:\n"
5102" test $0x3, %eax\n"
5103" jnz .LLV32LE2\n" /* jump if misaligned */
5104" mov %eax, %edx\n"
5105" shr $16, %edx\n"
5106" mov primary_map(,%edx,4), %ecx\n"
5107" movzwl %ax, %edx\n"
5108" shr $2, %edx\n"
5109" movzbl (%ecx,%edx,1), %edx\n"
5110" cmp $0xaa, %edx\n" /* compare to VA_BITS8_DEFINED */
5111" jne .LLV32LE1\n" /* jump if not completely defined */
5112" xor %eax, %eax\n" /* else return V_BITS32_DEFINED */
5113" ret\n"
5114".LLV32LE1:\n"
5115" cmp $0x55, %edx\n" /* compare to VA_BITS8_UNDEFINED */
5116" jne .LLV32LE2\n" /* jump if not completely undefined */
5117" or $0xffffffff, %eax\n" /* else return V_BITS32_UNDEFINED */
5118" ret\n"
5119".LLV32LE2:\n"
5120" xor %ecx, %ecx\n" /* tail call mc_LOADVn_slow(a, 32, 0) */
5121" mov $32, %edx\n"
5122" jmp mc_LOADVn_slow\n"
5123".size vgMemCheck_helperc_LOADV32le, .-vgMemCheck_helperc_LOADV32le\n"
5124".previous\n"
5125);
5126
sewardj7b1f9eb2015-06-05 13:33:46 +00005127#else
iraisr0e654912015-07-31 16:12:44 +00005128// Generic for all platforms except {arm32,x86}-linux and x86-solaris
njn1d0825f2006-03-27 11:37:07 +00005129VG_REGPARM(1) UWord MC_(helperc_LOADV32le) ( Addr a )
5130{
5131 return mc_LOADV32(a, False);
5132}
sewardj7b1f9eb2015-06-05 13:33:46 +00005133#endif
sewardjc1a2cda2005-04-21 17:34:00 +00005134
sewardjb9437c52015-07-20 13:11:03 +00005135/*------------------------------------------------------------*/
5136/*--- STOREV32 ---*/
5137/*------------------------------------------------------------*/
sewardjc1a2cda2005-04-21 17:34:00 +00005138
njn1d0825f2006-03-27 11:37:07 +00005139static INLINE
njn4cf530b2006-04-06 13:33:48 +00005140void mc_STOREV32 ( Addr a, UWord vbits32, Bool isBigEndian )
njn1d0825f2006-03-27 11:37:07 +00005141{
florian60042192015-08-04 15:58:41 +00005142 PROF_EVENT(MCPE_STOREV32);
njn1d0825f2006-03-27 11:37:07 +00005143
5144#ifndef PERF_FAST_STOREV
njn4cf530b2006-04-06 13:33:48 +00005145 mc_STOREVn_slow( a, 32, (ULong)vbits32, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00005146#else
njneccf7c02009-01-19 23:42:45 +00005147 {
5148 UWord sm_off, vabits8;
5149 SecMap* sm;
sewardjc1a2cda2005-04-21 17:34:00 +00005150
njneccf7c02009-01-19 23:42:45 +00005151 if (UNLIKELY( UNALIGNED_OR_HIGH(a,32) )) {
florian60042192015-08-04 15:58:41 +00005152 PROF_EVENT(MCPE_STOREV32_SLOW1);
njneccf7c02009-01-19 23:42:45 +00005153 mc_STOREVn_slow( a, 32, (ULong)vbits32, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00005154 return;
njneccf7c02009-01-19 23:42:45 +00005155 }
5156
5157 sm = get_secmap_for_reading_low(a);
5158 sm_off = SM_OFF(a);
5159 vabits8 = sm->vabits8[sm_off];
5160
philippeb8ac5ac2014-04-22 22:07:01 +00005161 // To understand the below cleverness, see the extensive comments
5162 // in MC_(helperc_STOREV8).
5163 if (LIKELY(V_BITS32_DEFINED == vbits32)) {
5164 if (LIKELY(vabits8 == (UInt)VA_BITS8_DEFINED)) {
njneccf7c02009-01-19 23:42:45 +00005165 return;
njneccf7c02009-01-19 23:42:45 +00005166 }
philippeb8ac5ac2014-04-22 22:07:01 +00005167 if (!is_distinguished_sm(sm) && VA_BITS8_UNDEFINED == vabits8) {
5168 sm->vabits8[sm_off] = (UInt)VA_BITS8_DEFINED;
5169 return;
5170 }
florian60042192015-08-04 15:58:41 +00005171 PROF_EVENT(MCPE_STOREV32_SLOW2);
philippeb8ac5ac2014-04-22 22:07:01 +00005172 mc_STOREVn_slow( a, 32, (ULong)vbits32, isBigEndian );
5173 return;
5174 }
5175 if (V_BITS32_UNDEFINED == vbits32) {
njneccf7c02009-01-19 23:42:45 +00005176 if (vabits8 == (UInt)VA_BITS8_UNDEFINED) {
5177 return;
njneccf7c02009-01-19 23:42:45 +00005178 }
philippeb8ac5ac2014-04-22 22:07:01 +00005179 if (!is_distinguished_sm(sm) && VA_BITS8_DEFINED == vabits8) {
5180 sm->vabits8[sm_off] = (UInt)VA_BITS8_UNDEFINED;
5181 return;
5182 }
florian60042192015-08-04 15:58:41 +00005183 PROF_EVENT(MCPE_STOREV32_SLOW3);
njn4cf530b2006-04-06 13:33:48 +00005184 mc_STOREVn_slow( a, 32, (ULong)vbits32, isBigEndian );
philippeb8ac5ac2014-04-22 22:07:01 +00005185 return;
njn1d0825f2006-03-27 11:37:07 +00005186 }
philippeb8ac5ac2014-04-22 22:07:01 +00005187
florian60042192015-08-04 15:58:41 +00005188 PROF_EVENT(MCPE_STOREV32_SLOW4);
philippeb8ac5ac2014-04-22 22:07:01 +00005189 mc_STOREVn_slow( a, 32, (ULong)vbits32, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00005190 }
njn1d0825f2006-03-27 11:37:07 +00005191#endif
5192}
5193
njn4cf530b2006-04-06 13:33:48 +00005194VG_REGPARM(2) void MC_(helperc_STOREV32be) ( Addr a, UWord vbits32 )
njn1d0825f2006-03-27 11:37:07 +00005195{
njn4cf530b2006-04-06 13:33:48 +00005196 mc_STOREV32(a, vbits32, True);
njn1d0825f2006-03-27 11:37:07 +00005197}
njn4cf530b2006-04-06 13:33:48 +00005198VG_REGPARM(2) void MC_(helperc_STOREV32le) ( Addr a, UWord vbits32 )
njn1d0825f2006-03-27 11:37:07 +00005199{
njn4cf530b2006-04-06 13:33:48 +00005200 mc_STOREV32(a, vbits32, False);
njn1d0825f2006-03-27 11:37:07 +00005201}
njn25e49d8e72002-09-23 09:36:25 +00005202
sewardjb9437c52015-07-20 13:11:03 +00005203/*------------------------------------------------------------*/
5204/*--- LOADV16 ---*/
5205/*------------------------------------------------------------*/
sewardj95448072004-11-22 20:19:51 +00005206
njn1d0825f2006-03-27 11:37:07 +00005207static INLINE
5208UWord mc_LOADV16 ( Addr a, Bool isBigEndian )
5209{
florian60042192015-08-04 15:58:41 +00005210 PROF_EVENT(MCPE_LOADV16);
njn1d0825f2006-03-27 11:37:07 +00005211
5212#ifndef PERF_FAST_LOADV
njn45e81252006-03-28 12:35:08 +00005213 return (UWord)mc_LOADVn_slow( a, 16, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00005214#else
njneccf7c02009-01-19 23:42:45 +00005215 {
5216 UWord sm_off, vabits8;
5217 SecMap* sm;
sewardjc1a2cda2005-04-21 17:34:00 +00005218
njneccf7c02009-01-19 23:42:45 +00005219 if (UNLIKELY( UNALIGNED_OR_HIGH(a,16) )) {
florian60042192015-08-04 15:58:41 +00005220 PROF_EVENT(MCPE_LOADV16_SLOW1);
njn45e81252006-03-28 12:35:08 +00005221 return (UWord)mc_LOADVn_slow( a, 16, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00005222 }
njneccf7c02009-01-19 23:42:45 +00005223
5224 sm = get_secmap_for_reading_low(a);
5225 sm_off = SM_OFF(a);
5226 vabits8 = sm->vabits8[sm_off];
5227 // Handle common case quickly: a is suitably aligned, is mapped, and is
5228 // addressible.
5229 // Convert V bits from compact memory form to expanded register form
sewardj14a81782011-08-20 15:55:07 +00005230 if (LIKELY(vabits8 == VA_BITS8_DEFINED )) { return V_BITS16_DEFINED; }
5231 else if (LIKELY(vabits8 == VA_BITS8_UNDEFINED)) { return V_BITS16_UNDEFINED; }
njneccf7c02009-01-19 23:42:45 +00005232 else {
5233 // The 4 (yes, 4) bytes are not all-defined or all-undefined, check
5234 // the two sub-bytes.
5235 UChar vabits4 = extract_vabits4_from_vabits8(a, vabits8);
5236 if (vabits4 == VA_BITS4_DEFINED ) { return V_BITS16_DEFINED; }
5237 else if (vabits4 == VA_BITS4_UNDEFINED) { return V_BITS16_UNDEFINED; }
5238 else {
5239 /* Slow case: the two bytes are not all-defined or all-undefined. */
florian60042192015-08-04 15:58:41 +00005240 PROF_EVENT(MCPE_LOADV16_SLOW2);
njneccf7c02009-01-19 23:42:45 +00005241 return (UWord)mc_LOADVn_slow( a, 16, isBigEndian );
5242 }
5243 }
njn1d0825f2006-03-27 11:37:07 +00005244 }
5245#endif
5246}
5247
sewardj7b1f9eb2015-06-05 13:33:46 +00005248// Generic for all platforms
njn1d0825f2006-03-27 11:37:07 +00005249VG_REGPARM(1) UWord MC_(helperc_LOADV16be) ( Addr a )
5250{
5251 return mc_LOADV16(a, True);
5252}
sewardj7b1f9eb2015-06-05 13:33:46 +00005253
5254// Non-generic assembly for arm32-linux
5255#if ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \
5256 && defined(VGP_arm_linux)
5257__asm__( /* Derived from NCode template */
5258".text \n"
5259".align 2 \n"
5260".global vgMemCheck_helperc_LOADV16le \n"
5261".type vgMemCheck_helperc_LOADV16le, %function \n"
5262"vgMemCheck_helperc_LOADV16le: \n" //
5263" tst r0, #1 \n" //
sewardj2ce9ac22015-07-20 09:59:25 +00005264" bne .LLV16LEc12 \n" // if misaligned
sewardj7b1f9eb2015-06-05 13:33:46 +00005265" lsr r2, r0, #16 \n" // r2 = pri-map-ix
5266" movw r3, #:lower16:primary_map \n" //
5267" uxth r1, r0 \n" // r1 = sec-map-offB
5268" movt r3, #:upper16:primary_map \n" //
5269" ldr r2, [r3, r2, lsl #2] \n" // r2 = sec-map
5270" ldrb r1, [r2, r1, lsr #2] \n" // r1 = sec-map-VABITS8
5271" cmp r1, #0xAA \n" // r1 == VA_BITS8_DEFINED?
sewardj2ce9ac22015-07-20 09:59:25 +00005272" bne .LLV16LEc0 \n" // no, goto .LLV16LEc0
5273".LLV16LEh9: \n" //
sewardj7b1f9eb2015-06-05 13:33:46 +00005274" mov r0, #0xFFFFFFFF \n" //
5275" lsl r0, r0, #16 \n" // V_BITS16_DEFINED | top16safe
5276" bx lr \n" //
sewardj2ce9ac22015-07-20 09:59:25 +00005277".LLV16LEc0: \n" //
sewardj7b1f9eb2015-06-05 13:33:46 +00005278" cmp r1, #0x55 \n" // VA_BITS8_UNDEFINED
sewardj2ce9ac22015-07-20 09:59:25 +00005279" bne .LLV16LEc4 \n" //
5280".LLV16LEc2: \n" //
sewardj7b1f9eb2015-06-05 13:33:46 +00005281" mov r0, #0xFFFFFFFF \n" // V_BITS16_UNDEFINED | top16safe
5282" bx lr \n" //
sewardj2ce9ac22015-07-20 09:59:25 +00005283".LLV16LEc4: \n" //
sewardj7b1f9eb2015-06-05 13:33:46 +00005284 // r1 holds sec-map-VABITS8. r0 holds the address and is 2-aligned.
5285 // Extract the relevant 4 bits and inspect.
sewardj2ce9ac22015-07-20 09:59:25 +00005286" and r2, r0, #2 \n" // addr & 2
5287" add r2, r2, r2 \n" // 2 * (addr & 2)
5288" lsr r1, r1, r2 \n" // sec-map-VABITS8 >> (2 * (addr & 2))
5289" and r1, r1, #15 \n" // (sec-map-VABITS8 >> (2 * (addr & 2))) & 15
sewardj7b1f9eb2015-06-05 13:33:46 +00005290
5291" cmp r1, #0xA \n" // VA_BITS4_DEFINED
sewardj2ce9ac22015-07-20 09:59:25 +00005292" beq .LLV16LEh9 \n" //
sewardj7b1f9eb2015-06-05 13:33:46 +00005293
5294" cmp r1, #0x5 \n" // VA_BITS4_UNDEFINED
sewardj2ce9ac22015-07-20 09:59:25 +00005295" beq .LLV16LEc2 \n" //
sewardj7b1f9eb2015-06-05 13:33:46 +00005296
sewardj2ce9ac22015-07-20 09:59:25 +00005297".LLV16LEc12: \n" //
sewardj7b1f9eb2015-06-05 13:33:46 +00005298" push {r4, lr} \n" //
5299" mov r2, #0 \n" //
5300" mov r1, #16 \n" //
5301" bl mc_LOADVn_slow \n" //
5302" pop {r4, pc} \n" //
5303".size vgMemCheck_helperc_LOADV16le, .-vgMemCheck_helperc_LOADV16le \n"
5304".previous\n"
5305);
5306
sewardjb9437c52015-07-20 13:11:03 +00005307#elif ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \
iraisr0e654912015-07-31 16:12:44 +00005308 && (defined(VGP_x86_linux) || defined(VGP_x86_solaris))
sewardjb9437c52015-07-20 13:11:03 +00005309__asm__(
5310".text\n"
5311".align 16\n"
5312".global vgMemCheck_helperc_LOADV16le\n"
5313".type vgMemCheck_helperc_LOADV16le, @function\n"
5314"vgMemCheck_helperc_LOADV16le:\n"
5315" test $0x1, %eax\n"
5316" jne .LLV16LE5\n" /* jump if not aligned */
5317" mov %eax, %edx\n"
5318" shr $0x10, %edx\n"
5319" mov primary_map(,%edx,4), %ecx\n"
5320" movzwl %ax, %edx\n"
5321" shr $0x2, %edx\n"
5322" movzbl (%ecx,%edx,1), %edx\n"/* edx = VA bits for 32bit */
5323" cmp $0xaa, %edx\n" /* compare to VA_BITS8_DEFINED */
5324" jne .LLV16LE2\n" /* jump if not all 32bits defined */
5325".LLV16LE1:\n"
5326" mov $0xffff0000,%eax\n" /* V_BITS16_DEFINED | top16safe */
5327" ret\n"
5328".LLV16LE2:\n"
5329" cmp $0x55, %edx\n" /* compare to VA_BITS8_UNDEFINED */
5330" jne .LLV16LE4\n" /* jump if not all 32bits undefined */
5331".LLV16LE3:\n"
5332" or $0xffffffff,%eax\n" /* V_BITS16_UNDEFINED | top16safe */
5333" ret\n"
5334".LLV16LE4:\n"
5335" mov %eax, %ecx\n"
5336" and $0x2, %ecx\n"
5337" add %ecx, %ecx\n"
5338" sar %cl, %edx\n"
5339" and $0xf, %edx\n"
5340" cmp $0xa, %edx\n"
5341" je .LLV16LE1\n" /* jump if all 16bits are defined */
5342" cmp $0x5, %edx\n"
5343" je .LLV16LE3\n" /* jump if all 16bits are undefined */
5344".LLV16LE5:\n"
5345" xor %ecx, %ecx\n" /* tail call mc_LOADVn_slow(a, 16, 0) */
5346" mov $16, %edx\n"
5347" jmp mc_LOADVn_slow\n"
5348".size vgMemCheck_helperc_LOADV16le, .-vgMemCheck_helperc_LOADV16le \n"
5349".previous\n"
5350);
5351
sewardj7b1f9eb2015-06-05 13:33:46 +00005352#else
iraisr0e654912015-07-31 16:12:44 +00005353// Generic for all platforms except {arm32,x86}-linux and x86-solaris
njn1d0825f2006-03-27 11:37:07 +00005354VG_REGPARM(1) UWord MC_(helperc_LOADV16le) ( Addr a )
5355{
5356 return mc_LOADV16(a, False);
5357}
sewardj7b1f9eb2015-06-05 13:33:46 +00005358#endif
sewardjc1a2cda2005-04-21 17:34:00 +00005359
sewardjb9437c52015-07-20 13:11:03 +00005360/*------------------------------------------------------------*/
5361/*--- STOREV16 ---*/
5362/*------------------------------------------------------------*/
5363
philippeb8ac5ac2014-04-22 22:07:01 +00005364/* True if the vabits4 in vabits8 indicate a and a+1 are accessible. */
5365static INLINE
5366Bool accessible_vabits4_in_vabits8 ( Addr a, UChar vabits8 )
5367{
5368 UInt shift;
5369 tl_assert(VG_IS_2_ALIGNED(a)); // Must be 2-aligned
5370 shift = (a & 2) << 1; // shift by 0 or 4
5371 vabits8 >>= shift; // shift the four bits to the bottom
5372 // check 2 x vabits2 != VA_BITS2_NOACCESS
5373 return ((0x3 & vabits8) != VA_BITS2_NOACCESS)
5374 && ((0xc & vabits8) != VA_BITS2_NOACCESS << 2);
5375}
sewardjc1a2cda2005-04-21 17:34:00 +00005376
njn1d0825f2006-03-27 11:37:07 +00005377static INLINE
njn4cf530b2006-04-06 13:33:48 +00005378void mc_STOREV16 ( Addr a, UWord vbits16, Bool isBigEndian )
njn1d0825f2006-03-27 11:37:07 +00005379{
florian60042192015-08-04 15:58:41 +00005380 PROF_EVENT(MCPE_STOREV16);
njn1d0825f2006-03-27 11:37:07 +00005381
5382#ifndef PERF_FAST_STOREV
njn4cf530b2006-04-06 13:33:48 +00005383 mc_STOREVn_slow( a, 16, (ULong)vbits16, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00005384#else
njn1d0825f2006-03-27 11:37:07 +00005385 {
njneccf7c02009-01-19 23:42:45 +00005386 UWord sm_off, vabits8;
5387 SecMap* sm;
5388
5389 if (UNLIKELY( UNALIGNED_OR_HIGH(a,16) )) {
florian60042192015-08-04 15:58:41 +00005390 PROF_EVENT(MCPE_STOREV16_SLOW1);
njneccf7c02009-01-19 23:42:45 +00005391 mc_STOREVn_slow( a, 16, (ULong)vbits16, isBigEndian );
5392 return;
5393 }
5394
5395 sm = get_secmap_for_reading_low(a);
5396 sm_off = SM_OFF(a);
5397 vabits8 = sm->vabits8[sm_off];
philippeb8ac5ac2014-04-22 22:07:01 +00005398
5399 // To understand the below cleverness, see the extensive comments
5400 // in MC_(helperc_STOREV8).
5401 if (LIKELY(V_BITS16_DEFINED == vbits16)) {
5402 if (LIKELY(vabits8 == VA_BITS8_DEFINED)) {
5403 return;
njneccf7c02009-01-19 23:42:45 +00005404 }
philippeb8ac5ac2014-04-22 22:07:01 +00005405 if (!is_distinguished_sm(sm)
5406 && accessible_vabits4_in_vabits8(a, vabits8)) {
5407 insert_vabits4_into_vabits8( a, VA_BITS4_DEFINED,
5408 &(sm->vabits8[sm_off]) );
5409 return;
5410 }
florian60042192015-08-04 15:58:41 +00005411 PROF_EVENT(MCPE_STOREV16_SLOW2);
njn4cf530b2006-04-06 13:33:48 +00005412 mc_STOREVn_slow( a, 16, (ULong)vbits16, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00005413 }
philippeb8ac5ac2014-04-22 22:07:01 +00005414 if (V_BITS16_UNDEFINED == vbits16) {
5415 if (vabits8 == VA_BITS8_UNDEFINED) {
5416 return;
5417 }
5418 if (!is_distinguished_sm(sm)
5419 && accessible_vabits4_in_vabits8(a, vabits8)) {
5420 insert_vabits4_into_vabits8( a, VA_BITS4_UNDEFINED,
5421 &(sm->vabits8[sm_off]) );
5422 return;
5423 }
florian60042192015-08-04 15:58:41 +00005424 PROF_EVENT(MCPE_STOREV16_SLOW3);
philippeb8ac5ac2014-04-22 22:07:01 +00005425 mc_STOREVn_slow( a, 16, (ULong)vbits16, isBigEndian );
5426 return;
5427 }
5428
florian60042192015-08-04 15:58:41 +00005429 PROF_EVENT(MCPE_STOREV16_SLOW4);
philippeb8ac5ac2014-04-22 22:07:01 +00005430 mc_STOREVn_slow( a, 16, (ULong)vbits16, isBigEndian );
njn1d0825f2006-03-27 11:37:07 +00005431 }
5432#endif
5433}
njn25e49d8e72002-09-23 09:36:25 +00005434
sewardj7b1f9eb2015-06-05 13:33:46 +00005435
njn4cf530b2006-04-06 13:33:48 +00005436VG_REGPARM(2) void MC_(helperc_STOREV16be) ( Addr a, UWord vbits16 )
njn1d0825f2006-03-27 11:37:07 +00005437{
njn4cf530b2006-04-06 13:33:48 +00005438 mc_STOREV16(a, vbits16, True);
njn1d0825f2006-03-27 11:37:07 +00005439}
njn4cf530b2006-04-06 13:33:48 +00005440VG_REGPARM(2) void MC_(helperc_STOREV16le) ( Addr a, UWord vbits16 )
njn1d0825f2006-03-27 11:37:07 +00005441{
njn4cf530b2006-04-06 13:33:48 +00005442 mc_STOREV16(a, vbits16, False);
njn1d0825f2006-03-27 11:37:07 +00005443}
sewardj5d28efc2005-04-21 22:16:29 +00005444
sewardjb9437c52015-07-20 13:11:03 +00005445/*------------------------------------------------------------*/
5446/*--- LOADV8 ---*/
5447/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00005448
sewardj8cf88b72005-07-08 01:29:33 +00005449/* Note: endianness is irrelevant for size == 1 */
sewardj95448072004-11-22 20:19:51 +00005450
sewardj7b1f9eb2015-06-05 13:33:46 +00005451// Non-generic assembly for arm32-linux
5452#if ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \
5453 && defined(VGP_arm_linux)
5454__asm__( /* Derived from NCode template */
5455".text \n"
5456".align 2 \n"
5457".global vgMemCheck_helperc_LOADV8 \n"
5458".type vgMemCheck_helperc_LOADV8, %function \n"
5459"vgMemCheck_helperc_LOADV8: \n" //
5460" lsr r2, r0, #16 \n" // r2 = pri-map-ix
5461" movw r3, #:lower16:primary_map \n" //
5462" uxth r1, r0 \n" // r1 = sec-map-offB
5463" movt r3, #:upper16:primary_map \n" //
5464" ldr r2, [r3, r2, lsl #2] \n" // r2 = sec-map
5465" ldrb r1, [r2, r1, lsr #2] \n" // r1 = sec-map-VABITS8
5466" cmp r1, #0xAA \n" // r1 == VA_BITS8_DEFINED?
sewardj2ce9ac22015-07-20 09:59:25 +00005467" bne .LLV8c0 \n" // no, goto .LLV8c0
5468".LLV8h9: \n" //
sewardj7b1f9eb2015-06-05 13:33:46 +00005469" mov r0, #0xFFFFFF00 \n" // V_BITS8_DEFINED | top24safe
5470" bx lr \n" //
sewardj2ce9ac22015-07-20 09:59:25 +00005471".LLV8c0: \n" //
sewardj7b1f9eb2015-06-05 13:33:46 +00005472" cmp r1, #0x55 \n" // VA_BITS8_UNDEFINED
sewardj2ce9ac22015-07-20 09:59:25 +00005473" bne .LLV8c4 \n" //
5474".LLV8c2: \n" //
sewardj7b1f9eb2015-06-05 13:33:46 +00005475" mov r0, #0xFFFFFFFF \n" // V_BITS8_UNDEFINED | top24safe
5476" bx lr \n" //
sewardj2ce9ac22015-07-20 09:59:25 +00005477".LLV8c4: \n" //
sewardj7b1f9eb2015-06-05 13:33:46 +00005478 // r1 holds sec-map-VABITS8
5479 // r0 holds the address. Extract the relevant 2 bits and inspect.
sewardj2ce9ac22015-07-20 09:59:25 +00005480" and r2, r0, #3 \n" // addr & 3
5481" add r2, r2, r2 \n" // 2 * (addr & 3)
5482" lsr r1, r1, r2 \n" // sec-map-VABITS8 >> (2 * (addr & 3))
5483" and r1, r1, #3 \n" // (sec-map-VABITS8 >> (2 * (addr & 3))) & 3
sewardj7b1f9eb2015-06-05 13:33:46 +00005484
5485" cmp r1, #2 \n" // VA_BITS2_DEFINED
sewardj2ce9ac22015-07-20 09:59:25 +00005486" beq .LLV8h9 \n" //
sewardj7b1f9eb2015-06-05 13:33:46 +00005487
5488" cmp r1, #1 \n" // VA_BITS2_UNDEFINED
sewardj2ce9ac22015-07-20 09:59:25 +00005489" beq .LLV8c2 \n" //
sewardj7b1f9eb2015-06-05 13:33:46 +00005490
5491" push {r4, lr} \n" //
5492" mov r2, #0 \n" //
5493" mov r1, #8 \n" //
5494" bl mc_LOADVn_slow \n" //
5495" pop {r4, pc} \n" //
5496".size vgMemCheck_helperc_LOADV8, .-vgMemCheck_helperc_LOADV8 \n"
5497".previous\n"
5498);
5499
sewardjb9437c52015-07-20 13:11:03 +00005500/* Non-generic assembly for x86-linux */
5501#elif ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \
iraisr0e654912015-07-31 16:12:44 +00005502 && (defined(VGP_x86_linux) || defined(VGP_x86_solaris))
sewardjb9437c52015-07-20 13:11:03 +00005503__asm__(
5504".text\n"
5505".align 16\n"
5506".global vgMemCheck_helperc_LOADV8\n"
5507".type vgMemCheck_helperc_LOADV8, @function\n"
5508"vgMemCheck_helperc_LOADV8:\n"
5509" mov %eax, %edx\n"
5510" shr $0x10, %edx\n"
5511" mov primary_map(,%edx,4), %ecx\n"
5512" movzwl %ax, %edx\n"
5513" shr $0x2, %edx\n"
5514" movzbl (%ecx,%edx,1), %edx\n"/* edx = VA bits for 32bit */
5515" cmp $0xaa, %edx\n" /* compare to VA_BITS8_DEFINED? */
5516" jne .LLV8LE2\n" /* jump if not defined */
5517".LLV8LE1:\n"
5518" mov $0xffffff00, %eax\n" /* V_BITS8_DEFINED | top24safe */
5519" ret\n"
5520".LLV8LE2:\n"
5521" cmp $0x55, %edx\n" /* compare to VA_BITS8_UNDEFINED */
5522" jne .LLV8LE4\n" /* jump if not all 32bits are undefined */
5523".LLV8LE3:\n"
5524" or $0xffffffff, %eax\n" /* V_BITS8_UNDEFINED | top24safe */
5525" ret\n"
5526".LLV8LE4:\n"
5527" mov %eax, %ecx\n"
5528" and $0x3, %ecx\n"
5529" add %ecx, %ecx\n"
5530" sar %cl, %edx\n"
5531" and $0x3, %edx\n"
5532" cmp $0x2, %edx\n"
5533" je .LLV8LE1\n" /* jump if all 8bits are defined */
5534" cmp $0x1, %edx\n"
5535" je .LLV8LE3\n" /* jump if all 8bits are undefined */
5536" xor %ecx, %ecx\n" /* tail call to mc_LOADVn_slow(a, 8, 0) */
5537" mov $0x8, %edx\n"
5538" jmp mc_LOADVn_slow\n"
5539".size vgMemCheck_helperc_LOADV8, .-vgMemCheck_helperc_LOADV8\n"
5540".previous\n"
5541);
5542
sewardj7b1f9eb2015-06-05 13:33:46 +00005543#else
iraisr0e654912015-07-31 16:12:44 +00005544// Generic for all platforms except {arm32,x86}-linux and x86-solaris
njnaf839f52005-06-23 03:27:57 +00005545VG_REGPARM(1)
njn1d0825f2006-03-27 11:37:07 +00005546UWord MC_(helperc_LOADV8) ( Addr a )
njn25e49d8e72002-09-23 09:36:25 +00005547{
florian60042192015-08-04 15:58:41 +00005548 PROF_EVENT(MCPE_LOADV8);
sewardjc1a2cda2005-04-21 17:34:00 +00005549
njn1d0825f2006-03-27 11:37:07 +00005550#ifndef PERF_FAST_LOADV
njn45e81252006-03-28 12:35:08 +00005551 return (UWord)mc_LOADVn_slow( a, 8, False/*irrelevant*/ );
njn1d0825f2006-03-27 11:37:07 +00005552#else
njneccf7c02009-01-19 23:42:45 +00005553 {
5554 UWord sm_off, vabits8;
5555 SecMap* sm;
sewardjc1a2cda2005-04-21 17:34:00 +00005556
njneccf7c02009-01-19 23:42:45 +00005557 if (UNLIKELY( UNALIGNED_OR_HIGH(a,8) )) {
florian60042192015-08-04 15:58:41 +00005558 PROF_EVENT(MCPE_LOADV8_SLOW1);
njn45e81252006-03-28 12:35:08 +00005559 return (UWord)mc_LOADVn_slow( a, 8, False/*irrelevant*/ );
njn1d0825f2006-03-27 11:37:07 +00005560 }
njneccf7c02009-01-19 23:42:45 +00005561
5562 sm = get_secmap_for_reading_low(a);
5563 sm_off = SM_OFF(a);
5564 vabits8 = sm->vabits8[sm_off];
5565 // Convert V bits from compact memory form to expanded register form
5566 // Handle common case quickly: a is mapped, and the entire
5567 // word32 it lives in is addressible.
sewardj14a81782011-08-20 15:55:07 +00005568 if (LIKELY(vabits8 == VA_BITS8_DEFINED )) { return V_BITS8_DEFINED; }
5569 else if (LIKELY(vabits8 == VA_BITS8_UNDEFINED)) { return V_BITS8_UNDEFINED; }
njneccf7c02009-01-19 23:42:45 +00005570 else {
5571 // The 4 (yes, 4) bytes are not all-defined or all-undefined, check
5572 // the single byte.
5573 UChar vabits2 = extract_vabits2_from_vabits8(a, vabits8);
5574 if (vabits2 == VA_BITS2_DEFINED ) { return V_BITS8_DEFINED; }
5575 else if (vabits2 == VA_BITS2_UNDEFINED) { return V_BITS8_UNDEFINED; }
5576 else {
5577 /* Slow case: the byte is not all-defined or all-undefined. */
florian60042192015-08-04 15:58:41 +00005578 PROF_EVENT(MCPE_LOADV8_SLOW2);
njneccf7c02009-01-19 23:42:45 +00005579 return (UWord)mc_LOADVn_slow( a, 8, False/*irrelevant*/ );
5580 }
5581 }
sewardjc1a2cda2005-04-21 17:34:00 +00005582 }
njn1d0825f2006-03-27 11:37:07 +00005583#endif
njn25e49d8e72002-09-23 09:36:25 +00005584}
sewardj7b1f9eb2015-06-05 13:33:46 +00005585#endif
njn25e49d8e72002-09-23 09:36:25 +00005586
sewardjb9437c52015-07-20 13:11:03 +00005587/*------------------------------------------------------------*/
5588/*--- STOREV8 ---*/
5589/*------------------------------------------------------------*/
sewardjc1a2cda2005-04-21 17:34:00 +00005590
njnaf839f52005-06-23 03:27:57 +00005591VG_REGPARM(2)
njn4cf530b2006-04-06 13:33:48 +00005592void MC_(helperc_STOREV8) ( Addr a, UWord vbits8 )
njn25e49d8e72002-09-23 09:36:25 +00005593{
florian60042192015-08-04 15:58:41 +00005594 PROF_EVENT(MCPE_STOREV8);
sewardjc1a2cda2005-04-21 17:34:00 +00005595
njn1d0825f2006-03-27 11:37:07 +00005596#ifndef PERF_FAST_STOREV
njn4cf530b2006-04-06 13:33:48 +00005597 mc_STOREVn_slow( a, 8, (ULong)vbits8, False/*irrelevant*/ );
njn1d0825f2006-03-27 11:37:07 +00005598#else
njn1d0825f2006-03-27 11:37:07 +00005599 {
njneccf7c02009-01-19 23:42:45 +00005600 UWord sm_off, vabits8;
5601 SecMap* sm;
5602
5603 if (UNLIKELY( UNALIGNED_OR_HIGH(a,8) )) {
florian60042192015-08-04 15:58:41 +00005604 PROF_EVENT(MCPE_STOREV8_SLOW1);
njneccf7c02009-01-19 23:42:45 +00005605 mc_STOREVn_slow( a, 8, (ULong)vbits8, False/*irrelevant*/ );
5606 return;
5607 }
5608
5609 sm = get_secmap_for_reading_low(a);
5610 sm_off = SM_OFF(a);
5611 vabits8 = sm->vabits8[sm_off];
philippeb8ac5ac2014-04-22 22:07:01 +00005612
5613 // Clevernesses to speed up storing V bits.
5614 // The 64/32/16 bit cases also have similar clevernesses, but it
5615 // works a little differently to the code below.
5616 //
5617 // Cleverness 1: sometimes we don't have to write the shadow memory at
5618 // all, if we can tell that what we want to write is the same as what is
5619 // already there. These cases are marked below as "defined on defined" and
5620 // "undefined on undefined".
5621 //
5622 // Cleverness 2:
5623 // We also avoid to call mc_STOREVn_slow if the V bits can directly
5624 // be written in the secondary map. V bits can be directly written
5625 // if 4 conditions are respected:
5626 // * The address for which V bits are written is naturally aligned
5627 // on 1 byte for STOREV8 (this is always true)
5628 // on 2 bytes for STOREV16
5629 // on 4 bytes for STOREV32
5630 // on 8 bytes for STOREV64.
5631 // * V bits being written are either fully defined or fully undefined.
5632 // (for partially defined V bits, V bits cannot be directly written,
5633 // as the secondary vbits table must be maintained).
5634 // * the secmap is not distinguished (distinguished maps cannot be
5635 // modified).
5636 // * the memory corresponding to the V bits being written is
5637 // accessible (if one or more bytes are not accessible,
5638 // we must call mc_STOREVn_slow in order to report accessibility
5639 // errors).
5640 // Note that for STOREV32 and STOREV64, it is too expensive
5641 // to verify the accessibility of each byte for the benefit it
5642 // brings. Instead, a quicker check is done by comparing to
5643 // VA_BITS(8|16)_(UN)DEFINED. This guarantees accessibility,
5644 // but misses some opportunity of direct modifications.
5645 // Checking each byte accessibility was measured for
5646 // STOREV32+perf tests and was slowing down all perf tests.
5647 // The cases corresponding to cleverness 2 are marked below as
5648 // "direct mod".
5649 if (LIKELY(V_BITS8_DEFINED == vbits8)) {
5650 if (LIKELY(vabits8 == VA_BITS8_DEFINED)) {
5651 return; // defined on defined
njneccf7c02009-01-19 23:42:45 +00005652 }
philippeb8ac5ac2014-04-22 22:07:01 +00005653 if (!is_distinguished_sm(sm)
5654 && VA_BITS2_NOACCESS != extract_vabits2_from_vabits8(a, vabits8)) {
5655 // direct mod
5656 insert_vabits2_into_vabits8( a, VA_BITS2_DEFINED,
5657 &(sm->vabits8[sm_off]) );
5658 return;
5659 }
florian60042192015-08-04 15:58:41 +00005660 PROF_EVENT(MCPE_STOREV8_SLOW2);
njn4cf530b2006-04-06 13:33:48 +00005661 mc_STOREVn_slow( a, 8, (ULong)vbits8, False/*irrelevant*/ );
philippeb8ac5ac2014-04-22 22:07:01 +00005662 return;
njn1d0825f2006-03-27 11:37:07 +00005663 }
philippeb8ac5ac2014-04-22 22:07:01 +00005664 if (V_BITS8_UNDEFINED == vbits8) {
5665 if (vabits8 == VA_BITS8_UNDEFINED) {
5666 return; // undefined on undefined
5667 }
5668 if (!is_distinguished_sm(sm)
5669 && (VA_BITS2_NOACCESS
5670 != extract_vabits2_from_vabits8(a, vabits8))) {
5671 // direct mod
5672 insert_vabits2_into_vabits8( a, VA_BITS2_UNDEFINED,
5673 &(sm->vabits8[sm_off]) );
5674 return;
5675 }
florian60042192015-08-04 15:58:41 +00005676 PROF_EVENT(MCPE_STOREV8_SLOW3);
philippeb8ac5ac2014-04-22 22:07:01 +00005677 mc_STOREVn_slow( a, 8, (ULong)vbits8, False/*irrelevant*/ );
5678 return;
5679 }
5680
5681 // Partially defined word
florian60042192015-08-04 15:58:41 +00005682 PROF_EVENT(MCPE_STOREV8_SLOW4);
philippeb8ac5ac2014-04-22 22:07:01 +00005683 mc_STOREVn_slow( a, 8, (ULong)vbits8, False/*irrelevant*/ );
sewardjc1a2cda2005-04-21 17:34:00 +00005684 }
njn1d0825f2006-03-27 11:37:07 +00005685#endif
njn25e49d8e72002-09-23 09:36:25 +00005686}
5687
5688
sewardjc859fbf2005-04-22 21:10:28 +00005689/*------------------------------------------------------------*/
5690/*--- Functions called directly from generated code: ---*/
5691/*--- Value-check failure handlers. ---*/
5692/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00005693
sewardj7cf4e6b2008-05-01 20:24:26 +00005694/* Call these ones when an origin is available ... */
5695VG_REGPARM(1)
5696void MC_(helperc_value_check0_fail_w_o) ( UWord origin ) {
sewardj7ce71662008-05-02 10:33:15 +00005697 MC_(record_cond_error) ( VG_(get_running_tid)(), (UInt)origin );
njn25e49d8e72002-09-23 09:36:25 +00005698}
5699
sewardj7cf4e6b2008-05-01 20:24:26 +00005700VG_REGPARM(1)
5701void MC_(helperc_value_check1_fail_w_o) ( UWord origin ) {
sewardj7ce71662008-05-02 10:33:15 +00005702 MC_(record_value_error) ( VG_(get_running_tid)(), 1, (UInt)origin );
njn25e49d8e72002-09-23 09:36:25 +00005703}
5704
sewardj7cf4e6b2008-05-01 20:24:26 +00005705VG_REGPARM(1)
5706void MC_(helperc_value_check4_fail_w_o) ( UWord origin ) {
sewardj7ce71662008-05-02 10:33:15 +00005707 MC_(record_value_error) ( VG_(get_running_tid)(), 4, (UInt)origin );
njn25e49d8e72002-09-23 09:36:25 +00005708}
5709
sewardj7cf4e6b2008-05-01 20:24:26 +00005710VG_REGPARM(1)
5711void MC_(helperc_value_check8_fail_w_o) ( UWord origin ) {
sewardj7ce71662008-05-02 10:33:15 +00005712 MC_(record_value_error) ( VG_(get_running_tid)(), 8, (UInt)origin );
sewardj11bcc4e2005-04-23 22:38:38 +00005713}
5714
sewardj7cf4e6b2008-05-01 20:24:26 +00005715VG_REGPARM(2)
5716void MC_(helperc_value_checkN_fail_w_o) ( HWord sz, UWord origin ) {
sewardj7ce71662008-05-02 10:33:15 +00005717 MC_(record_value_error) ( VG_(get_running_tid)(), (Int)sz, (UInt)origin );
sewardj7cf4e6b2008-05-01 20:24:26 +00005718}
5719
5720/* ... and these when an origin isn't available. */
5721
5722VG_REGPARM(0)
5723void MC_(helperc_value_check0_fail_no_o) ( void ) {
sewardj7ce71662008-05-02 10:33:15 +00005724 MC_(record_cond_error) ( VG_(get_running_tid)(), 0/*origin*/ );
sewardj7cf4e6b2008-05-01 20:24:26 +00005725}
5726
5727VG_REGPARM(0)
5728void MC_(helperc_value_check1_fail_no_o) ( void ) {
sewardj7ce71662008-05-02 10:33:15 +00005729 MC_(record_value_error) ( VG_(get_running_tid)(), 1, 0/*origin*/ );
sewardj7cf4e6b2008-05-01 20:24:26 +00005730}
5731
5732VG_REGPARM(0)
5733void MC_(helperc_value_check4_fail_no_o) ( void ) {
sewardj7ce71662008-05-02 10:33:15 +00005734 MC_(record_value_error) ( VG_(get_running_tid)(), 4, 0/*origin*/ );
sewardj7cf4e6b2008-05-01 20:24:26 +00005735}
5736
5737VG_REGPARM(0)
5738void MC_(helperc_value_check8_fail_no_o) ( void ) {
sewardj7ce71662008-05-02 10:33:15 +00005739 MC_(record_value_error) ( VG_(get_running_tid)(), 8, 0/*origin*/ );
sewardj7cf4e6b2008-05-01 20:24:26 +00005740}
5741
5742VG_REGPARM(1)
5743void MC_(helperc_value_checkN_fail_no_o) ( HWord sz ) {
sewardj7ce71662008-05-02 10:33:15 +00005744 MC_(record_value_error) ( VG_(get_running_tid)(), (Int)sz, 0/*origin*/ );
sewardj95448072004-11-22 20:19:51 +00005745}
5746
njn25e49d8e72002-09-23 09:36:25 +00005747
sewardjc2c12c22006-03-08 13:20:09 +00005748/*------------------------------------------------------------*/
5749/*--- Metadata get/set functions, for client requests. ---*/
5750/*------------------------------------------------------------*/
5751
njn1d0825f2006-03-27 11:37:07 +00005752// Nb: this expands the V+A bits out into register-form V bits, even though
5753// they're in memory. This is for backward compatibility, and because it's
5754// probably what the user wants.
5755
5756/* Copy Vbits from/to address 'a'. Returns: 1 == OK, 2 == alignment
sewardjc2c12c22006-03-08 13:20:09 +00005757 error [no longer used], 3 == addressing error. */
njn718d3b12006-12-16 00:54:12 +00005758/* Nb: We used to issue various definedness/addressability errors from here,
5759 but we took them out because they ranged from not-very-helpful to
5760 downright annoying, and they complicated the error data structures. */
sewardjc2c12c22006-03-08 13:20:09 +00005761static Int mc_get_or_set_vbits_for_client (
njn1d0825f2006-03-27 11:37:07 +00005762 Addr a,
5763 Addr vbits,
5764 SizeT szB,
sewardj3b290482011-05-06 21:02:55 +00005765 Bool setting, /* True <=> set vbits, False <=> get vbits */
5766 Bool is_client_request /* True <=> real user request
5767 False <=> internal call from gdbserver */
sewardjc2c12c22006-03-08 13:20:09 +00005768)
5769{
sewardjc2c12c22006-03-08 13:20:09 +00005770 SizeT i;
njn1d0825f2006-03-27 11:37:07 +00005771 Bool ok;
5772 UChar vbits8;
sewardjc2c12c22006-03-08 13:20:09 +00005773
sewardj3b290482011-05-06 21:02:55 +00005774 /* Check that arrays are addressible before doing any getting/setting.
5775 vbits to be checked only for real user request. */
njn1d0825f2006-03-27 11:37:07 +00005776 for (i = 0; i < szB; i++) {
njn718d3b12006-12-16 00:54:12 +00005777 if (VA_BITS2_NOACCESS == get_vabits2(a + i) ||
sewardj3b290482011-05-06 21:02:55 +00005778 (is_client_request && VA_BITS2_NOACCESS == get_vabits2(vbits + i))) {
njn1d0825f2006-03-27 11:37:07 +00005779 return 3;
sewardjc2c12c22006-03-08 13:20:09 +00005780 }
5781 }
njn1d0825f2006-03-27 11:37:07 +00005782
sewardjc2c12c22006-03-08 13:20:09 +00005783 /* Do the copy */
5784 if (setting) {
njn1d0825f2006-03-27 11:37:07 +00005785 /* setting */
5786 for (i = 0; i < szB; i++) {
5787 ok = set_vbits8(a + i, ((UChar*)vbits)[i]);
5788 tl_assert(ok);
sewardjc2c12c22006-03-08 13:20:09 +00005789 }
5790 } else {
5791 /* getting */
njn1d0825f2006-03-27 11:37:07 +00005792 for (i = 0; i < szB; i++) {
5793 ok = get_vbits8(a + i, &vbits8);
5794 tl_assert(ok);
njn1d0825f2006-03-27 11:37:07 +00005795 ((UChar*)vbits)[i] = vbits8;
sewardjc2c12c22006-03-08 13:20:09 +00005796 }
sewardj3b290482011-05-06 21:02:55 +00005797 if (is_client_request)
5798 // The bytes in vbits[] have now been set, so mark them as such.
5799 MC_(make_mem_defined)(vbits, szB);
njn1d0825f2006-03-27 11:37:07 +00005800 }
sewardjc2c12c22006-03-08 13:20:09 +00005801
5802 return 1;
5803}
sewardj05fe85e2005-04-27 22:46:36 +00005804
5805
5806/*------------------------------------------------------------*/
5807/*--- Detecting leaked (unreachable) malloc'd blocks. ---*/
5808/*------------------------------------------------------------*/
5809
5810/* For the memory leak detector, say whether an entire 64k chunk of
5811 address space is possibly in use, or not. If in doubt return
5812 True.
5813*/
njn8225cc02009-03-09 22:52:24 +00005814Bool MC_(is_within_valid_secondary) ( Addr a )
sewardj05fe85e2005-04-27 22:46:36 +00005815{
5816 SecMap* sm = maybe_get_secmap_for ( a );
philippee1e8fce2012-07-11 23:06:07 +00005817 if (sm == NULL || sm == &sm_distinguished[SM_DIST_NOACCESS]) {
sewardj05fe85e2005-04-27 22:46:36 +00005818 /* Definitely not in use. */
5819 return False;
5820 } else {
5821 return True;
5822 }
5823}
5824
5825
5826/* For the memory leak detector, say whether or not a given word
5827 address is to be regarded as valid. */
njn8225cc02009-03-09 22:52:24 +00005828Bool MC_(is_valid_aligned_word) ( Addr a )
sewardj05fe85e2005-04-27 22:46:36 +00005829{
5830 tl_assert(sizeof(UWord) == 4 || sizeof(UWord) == 8);
njn8225cc02009-03-09 22:52:24 +00005831 tl_assert(VG_IS_WORD_ALIGNED(a));
philippe57a16a22012-07-18 22:26:51 +00005832 if (get_vabits8_for_aligned_word32 (a) != VA_BITS8_DEFINED)
sewardj05fe85e2005-04-27 22:46:36 +00005833 return False;
philippe57a16a22012-07-18 22:26:51 +00005834 if (sizeof(UWord) == 8) {
5835 if (get_vabits8_for_aligned_word32 (a + 4) != VA_BITS8_DEFINED)
5836 return False;
sewardj05fe85e2005-04-27 22:46:36 +00005837 }
philippe57a16a22012-07-18 22:26:51 +00005838 if (UNLIKELY(MC_(in_ignored_range)(a)))
5839 return False;
5840 else
5841 return True;
sewardj05fe85e2005-04-27 22:46:36 +00005842}
sewardja4495682002-10-21 07:29:59 +00005843
5844
sewardjc859fbf2005-04-22 21:10:28 +00005845/*------------------------------------------------------------*/
5846/*--- Initialisation ---*/
5847/*------------------------------------------------------------*/
5848
5849static void init_shadow_memory ( void )
5850{
5851 Int i;
5852 SecMap* sm;
5853
njn1d0825f2006-03-27 11:37:07 +00005854 tl_assert(V_BIT_UNDEFINED == 1);
5855 tl_assert(V_BIT_DEFINED == 0);
5856 tl_assert(V_BITS8_UNDEFINED == 0xFF);
5857 tl_assert(V_BITS8_DEFINED == 0);
5858
sewardjc859fbf2005-04-22 21:10:28 +00005859 /* Build the 3 distinguished secondaries */
sewardjc859fbf2005-04-22 21:10:28 +00005860 sm = &sm_distinguished[SM_DIST_NOACCESS];
njn1d0825f2006-03-27 11:37:07 +00005861 for (i = 0; i < SM_CHUNKS; i++) sm->vabits8[i] = VA_BITS8_NOACCESS;
sewardjc859fbf2005-04-22 21:10:28 +00005862
njndbf7ca72006-03-31 11:57:59 +00005863 sm = &sm_distinguished[SM_DIST_UNDEFINED];
5864 for (i = 0; i < SM_CHUNKS; i++) sm->vabits8[i] = VA_BITS8_UNDEFINED;
sewardjc859fbf2005-04-22 21:10:28 +00005865
njndbf7ca72006-03-31 11:57:59 +00005866 sm = &sm_distinguished[SM_DIST_DEFINED];
5867 for (i = 0; i < SM_CHUNKS; i++) sm->vabits8[i] = VA_BITS8_DEFINED;
sewardjc859fbf2005-04-22 21:10:28 +00005868
5869 /* Set up the primary map. */
5870 /* These entries gradually get overwritten as the used address
5871 space expands. */
5872 for (i = 0; i < N_PRIMARY_MAP; i++)
5873 primary_map[i] = &sm_distinguished[SM_DIST_NOACCESS];
5874
sewardj05a46732006-10-17 01:28:10 +00005875 /* Auxiliary primary maps */
5876 init_auxmap_L1_L2();
5877
sewardjc859fbf2005-04-22 21:10:28 +00005878 /* auxmap_size = auxmap_used = 0;
5879 no ... these are statically initialised */
njn1d0825f2006-03-27 11:37:07 +00005880
5881 /* Secondary V bit table */
5882 secVBitTable = createSecVBitTable();
sewardjc859fbf2005-04-22 21:10:28 +00005883}
5884
5885
5886/*------------------------------------------------------------*/
5887/*--- Sanity check machinery (permanently engaged) ---*/
5888/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +00005889
njn51d827b2005-05-09 01:02:08 +00005890static Bool mc_cheap_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00005891{
sewardj23eb2fd2005-04-22 16:29:19 +00005892 n_sanity_cheap++;
florian60042192015-08-04 15:58:41 +00005893 PROF_EVENT(MCPE_CHEAP_SANITY_CHECK);
sewardj7cf4e6b2008-05-01 20:24:26 +00005894 /* Check for sane operating level */
5895 if (MC_(clo_mc_level) < 1 || MC_(clo_mc_level) > 3)
5896 return False;
5897 /* nothing else useful we can rapidly check */
jseward9800fd32004-01-04 23:08:04 +00005898 return True;
njn25e49d8e72002-09-23 09:36:25 +00005899}
5900
njn51d827b2005-05-09 01:02:08 +00005901static Bool mc_expensive_sanity_check ( void )
njn25e49d8e72002-09-23 09:36:25 +00005902{
sewardj05a46732006-10-17 01:28:10 +00005903 Int i;
5904 Word n_secmaps_found;
sewardj45d94cc2005-04-20 14:44:11 +00005905 SecMap* sm;
florian19f91bb2012-11-10 22:29:54 +00005906 const HChar* errmsg;
sewardj23eb2fd2005-04-22 16:29:19 +00005907 Bool bad = False;
njn25e49d8e72002-09-23 09:36:25 +00005908
sewardj05a46732006-10-17 01:28:10 +00005909 if (0) VG_(printf)("expensive sanity check\n");
5910 if (0) return True;
5911
sewardj23eb2fd2005-04-22 16:29:19 +00005912 n_sanity_expensive++;
florian60042192015-08-04 15:58:41 +00005913 PROF_EVENT(MCPE_EXPENSIVE_SANITY_CHECK);
sewardjc1a2cda2005-04-21 17:34:00 +00005914
sewardj7cf4e6b2008-05-01 20:24:26 +00005915 /* Check for sane operating level */
5916 if (MC_(clo_mc_level) < 1 || MC_(clo_mc_level) > 3)
5917 return False;
5918
njn1d0825f2006-03-27 11:37:07 +00005919 /* Check that the 3 distinguished SMs are still as they should be. */
njn25e49d8e72002-09-23 09:36:25 +00005920
njndbf7ca72006-03-31 11:57:59 +00005921 /* Check noaccess DSM. */
sewardj45d94cc2005-04-20 14:44:11 +00005922 sm = &sm_distinguished[SM_DIST_NOACCESS];
njn1d0825f2006-03-27 11:37:07 +00005923 for (i = 0; i < SM_CHUNKS; i++)
5924 if (sm->vabits8[i] != VA_BITS8_NOACCESS)
sewardj23eb2fd2005-04-22 16:29:19 +00005925 bad = True;
njn25e49d8e72002-09-23 09:36:25 +00005926
njndbf7ca72006-03-31 11:57:59 +00005927 /* Check undefined DSM. */
5928 sm = &sm_distinguished[SM_DIST_UNDEFINED];
njn1d0825f2006-03-27 11:37:07 +00005929 for (i = 0; i < SM_CHUNKS; i++)
njndbf7ca72006-03-31 11:57:59 +00005930 if (sm->vabits8[i] != VA_BITS8_UNDEFINED)
sewardj23eb2fd2005-04-22 16:29:19 +00005931 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00005932
njndbf7ca72006-03-31 11:57:59 +00005933 /* Check defined DSM. */
5934 sm = &sm_distinguished[SM_DIST_DEFINED];
njn1d0825f2006-03-27 11:37:07 +00005935 for (i = 0; i < SM_CHUNKS; i++)
njndbf7ca72006-03-31 11:57:59 +00005936 if (sm->vabits8[i] != VA_BITS8_DEFINED)
sewardj23eb2fd2005-04-22 16:29:19 +00005937 bad = True;
sewardj45d94cc2005-04-20 14:44:11 +00005938
sewardj23eb2fd2005-04-22 16:29:19 +00005939 if (bad) {
5940 VG_(printf)("memcheck expensive sanity: "
5941 "distinguished_secondaries have changed\n");
5942 return False;
5943 }
5944
njn1d0825f2006-03-27 11:37:07 +00005945 /* If we're not checking for undefined value errors, the secondary V bit
5946 * table should be empty. */
sewardj7cf4e6b2008-05-01 20:24:26 +00005947 if (MC_(clo_mc_level) == 1) {
njne2a9ad32007-09-17 05:30:48 +00005948 if (0 != VG_(OSetGen_Size)(secVBitTable))
njn1d0825f2006-03-27 11:37:07 +00005949 return False;
5950 }
5951
sewardj05a46732006-10-17 01:28:10 +00005952 /* check the auxiliary maps, very thoroughly */
5953 n_secmaps_found = 0;
5954 errmsg = check_auxmap_L1_L2_sanity( &n_secmaps_found );
5955 if (errmsg) {
5956 VG_(printf)("memcheck expensive sanity, auxmaps:\n\t%s", errmsg);
sewardj23eb2fd2005-04-22 16:29:19 +00005957 return False;
5958 }
5959
sewardj05a46732006-10-17 01:28:10 +00005960 /* n_secmaps_found is now the number referred to by the auxiliary
5961 primary map. Now add on the ones referred to by the main
5962 primary map. */
sewardj23eb2fd2005-04-22 16:29:19 +00005963 for (i = 0; i < N_PRIMARY_MAP; i++) {
sewardj05a46732006-10-17 01:28:10 +00005964 if (primary_map[i] == NULL) {
sewardj23eb2fd2005-04-22 16:29:19 +00005965 bad = True;
5966 } else {
sewardj05a46732006-10-17 01:28:10 +00005967 if (!is_distinguished_sm(primary_map[i]))
sewardj23eb2fd2005-04-22 16:29:19 +00005968 n_secmaps_found++;
5969 }
5970 }
5971
sewardj05a46732006-10-17 01:28:10 +00005972 /* check that the number of secmaps issued matches the number that
5973 are reachable (iow, no secmap leaks) */
njn1d0825f2006-03-27 11:37:07 +00005974 if (n_secmaps_found != (n_issued_SMs - n_deissued_SMs))
sewardj23eb2fd2005-04-22 16:29:19 +00005975 bad = True;
5976
5977 if (bad) {
5978 VG_(printf)("memcheck expensive sanity: "
5979 "apparent secmap leakage\n");
5980 return False;
5981 }
5982
sewardj23eb2fd2005-04-22 16:29:19 +00005983 if (bad) {
5984 VG_(printf)("memcheck expensive sanity: "
5985 "auxmap covers wrong address space\n");
5986 return False;
5987 }
5988
5989 /* there is only one pointer to each secmap (expensive) */
njn25e49d8e72002-09-23 09:36:25 +00005990
5991 return True;
5992}
sewardj45d94cc2005-04-20 14:44:11 +00005993
njn25e49d8e72002-09-23 09:36:25 +00005994/*------------------------------------------------------------*/
njnd3040452003-05-19 15:04:06 +00005995/*--- Command line args ---*/
njn25e49d8e72002-09-23 09:36:25 +00005996/*------------------------------------------------------------*/
5997
sewardjadd95c82015-08-31 10:36:02 +00005998/* 31 Aug 2015: Vectorised code is now so widespread that
5999 --partial-loads-ok needs to be enabled by default on all platforms.
6000 Not doing so causes lots of false errors. */
sewardj0b392882014-07-08 09:36:06 +00006001Bool MC_(clo_partial_loads_ok) = True;
sewardja88fb0b2010-10-13 21:19:54 +00006002Long MC_(clo_freelist_vol) = 20*1000*1000LL;
sewardj403d8aa2011-10-22 19:48:57 +00006003Long MC_(clo_freelist_big_blocks) = 1*1000*1000LL;
njn1d0825f2006-03-27 11:37:07 +00006004LeakCheckMode MC_(clo_leak_check) = LC_Summary;
njn5daa2d32009-07-10 08:16:29 +00006005VgRes MC_(clo_leak_resolution) = Vg_HighRes;
philippe2193a7c2012-12-08 17:54:16 +00006006UInt MC_(clo_show_leak_kinds) = R2S(Possible) | R2S(Unreached);
6007UInt MC_(clo_error_for_leak_kinds) = R2S(Possible) | R2S(Unreached);
philippec22f5192015-09-02 21:57:53 +00006008UInt MC_(clo_leak_check_heuristics) = H2S(LchStdString)
6009 | H2S( LchLength64)
6010 | H2S( LchNewArray)
6011 | H2S( LchMultipleInheritance);
njn1d0825f2006-03-27 11:37:07 +00006012Bool MC_(clo_workaround_gcc296_bugs) = False;
sewardjeb0fa932007-11-30 21:41:40 +00006013Int MC_(clo_malloc_fill) = -1;
6014Int MC_(clo_free_fill) = -1;
philippe92cd8382015-08-29 10:45:26 +00006015KeepStacktraces MC_(clo_keep_stacktraces) = KS_alloc_and_free;
sewardj7cf4e6b2008-05-01 20:24:26 +00006016Int MC_(clo_mc_level) = 2;
sewardj021e6b62014-08-22 19:26:23 +00006017Bool MC_(clo_show_mismatched_frees) = True;
sewardj2672fae2015-09-01 08:48:04 +00006018Bool MC_(clo_expensive_definedness_checks) = False;
Elliott Hughesa0664b92017-04-18 17:46:52 -07006019Bool MC_(clo_ignore_range_below_sp) = False;
6020UInt MC_(clo_ignore_range_below_sp__first_offset) = 0;
6021UInt MC_(clo_ignore_range_below_sp__last_offset) = 0;
njn1d0825f2006-03-27 11:37:07 +00006022
philippeec905f72014-08-17 20:03:51 +00006023static const HChar * MC_(parse_leak_heuristics_tokens) =
6024 "-,stdstring,length64,newarray,multipleinheritance";
6025/* The first heuristic value (LchNone) has no keyword, as this is
6026 a fake heuristic used to collect the blocks found without any
6027 heuristic. */
philippeab1fce92013-09-29 13:47:32 +00006028
florian19f91bb2012-11-10 22:29:54 +00006029static Bool mc_process_cmd_line_options(const HChar* arg)
njn25e49d8e72002-09-23 09:36:25 +00006030{
florian19f91bb2012-11-10 22:29:54 +00006031 const HChar* tmp_str;
philippe2193a7c2012-12-08 17:54:16 +00006032 Int tmp_show;
njn83df0b62009-02-25 01:01:05 +00006033
sewardj7cf4e6b2008-05-01 20:24:26 +00006034 tl_assert( MC_(clo_mc_level) >= 1 && MC_(clo_mc_level) <= 3 );
6035
6036 /* Set MC_(clo_mc_level):
6037 1 = A bit tracking only
6038 2 = A and V bit tracking, but no V bit origins
6039 3 = A and V bit tracking, and V bit origins
6040
6041 Do this by inspecting --undef-value-errors= and
6042 --track-origins=. Reject the case --undef-value-errors=no
6043 --track-origins=yes as meaningless.
6044 */
6045 if (0 == VG_(strcmp)(arg, "--undef-value-errors=no")) {
njn83df0b62009-02-25 01:01:05 +00006046 if (MC_(clo_mc_level) == 3) {
njnb1cc5d62010-07-06 04:05:23 +00006047 goto bad_level;
njn83df0b62009-02-25 01:01:05 +00006048 } else {
6049 MC_(clo_mc_level) = 1;
6050 return True;
6051 }
sewardj7cf4e6b2008-05-01 20:24:26 +00006052 }
6053 if (0 == VG_(strcmp)(arg, "--undef-value-errors=yes")) {
6054 if (MC_(clo_mc_level) == 1)
6055 MC_(clo_mc_level) = 2;
6056 return True;
6057 }
6058 if (0 == VG_(strcmp)(arg, "--track-origins=no")) {
6059 if (MC_(clo_mc_level) == 3)
6060 MC_(clo_mc_level) = 2;
6061 return True;
6062 }
6063 if (0 == VG_(strcmp)(arg, "--track-origins=yes")) {
njn83df0b62009-02-25 01:01:05 +00006064 if (MC_(clo_mc_level) == 1) {
njnb1cc5d62010-07-06 04:05:23 +00006065 goto bad_level;
njn83df0b62009-02-25 01:01:05 +00006066 } else {
6067 MC_(clo_mc_level) = 3;
6068 return True;
6069 }
sewardj7cf4e6b2008-05-01 20:24:26 +00006070 }
6071
philippe2193a7c2012-12-08 17:54:16 +00006072 if VG_BOOL_CLO(arg, "--partial-loads-ok", MC_(clo_partial_loads_ok)) {}
philippeec905f72014-08-17 20:03:51 +00006073 else if VG_USET_CLO(arg, "--errors-for-leak-kinds",
6074 MC_(parse_leak_kinds_tokens),
6075 MC_(clo_error_for_leak_kinds)) {}
6076 else if VG_USET_CLO(arg, "--show-leak-kinds",
6077 MC_(parse_leak_kinds_tokens),
6078 MC_(clo_show_leak_kinds)) {}
6079 else if VG_USET_CLO(arg, "--leak-check-heuristics",
6080 MC_(parse_leak_heuristics_tokens),
6081 MC_(clo_leak_check_heuristics)) {}
philippe2193a7c2012-12-08 17:54:16 +00006082 else if (VG_BOOL_CLO(arg, "--show-reachable", tmp_show)) {
6083 if (tmp_show) {
philippeec905f72014-08-17 20:03:51 +00006084 MC_(clo_show_leak_kinds) = MC_(all_Reachedness)();
philippe2193a7c2012-12-08 17:54:16 +00006085 } else {
6086 MC_(clo_show_leak_kinds) &= ~R2S(Reachable);
6087 }
6088 }
6089 else if VG_BOOL_CLO(arg, "--show-possibly-lost", tmp_show) {
6090 if (tmp_show) {
6091 MC_(clo_show_leak_kinds) |= R2S(Possible);
6092 } else {
6093 MC_(clo_show_leak_kinds) &= ~R2S(Possible);
6094 }
6095 }
njn83df0b62009-02-25 01:01:05 +00006096 else if VG_BOOL_CLO(arg, "--workaround-gcc296-bugs",
6097 MC_(clo_workaround_gcc296_bugs)) {}
njn1d0825f2006-03-27 11:37:07 +00006098
njn83df0b62009-02-25 01:01:05 +00006099 else if VG_BINT_CLO(arg, "--freelist-vol", MC_(clo_freelist_vol),
6100 0, 10*1000*1000*1000LL) {}
sewardj403d8aa2011-10-22 19:48:57 +00006101
6102 else if VG_BINT_CLO(arg, "--freelist-big-blocks",
6103 MC_(clo_freelist_big_blocks),
6104 0, 10*1000*1000*1000LL) {}
6105
njn83df0b62009-02-25 01:01:05 +00006106 else if VG_XACT_CLO(arg, "--leak-check=no",
6107 MC_(clo_leak_check), LC_Off) {}
6108 else if VG_XACT_CLO(arg, "--leak-check=summary",
6109 MC_(clo_leak_check), LC_Summary) {}
6110 else if VG_XACT_CLO(arg, "--leak-check=yes",
6111 MC_(clo_leak_check), LC_Full) {}
6112 else if VG_XACT_CLO(arg, "--leak-check=full",
6113 MC_(clo_leak_check), LC_Full) {}
njn1d0825f2006-03-27 11:37:07 +00006114
njn83df0b62009-02-25 01:01:05 +00006115 else if VG_XACT_CLO(arg, "--leak-resolution=low",
6116 MC_(clo_leak_resolution), Vg_LowRes) {}
6117 else if VG_XACT_CLO(arg, "--leak-resolution=med",
6118 MC_(clo_leak_resolution), Vg_MedRes) {}
6119 else if VG_XACT_CLO(arg, "--leak-resolution=high",
6120 MC_(clo_leak_resolution), Vg_HighRes) {}
njn1d0825f2006-03-27 11:37:07 +00006121
njn83df0b62009-02-25 01:01:05 +00006122 else if VG_STR_CLO(arg, "--ignore-ranges", tmp_str) {
sewardjc5fc8662014-03-20 23:00:09 +00006123 Bool ok = parse_ignore_ranges(tmp_str);
6124 if (!ok) {
6125 VG_(message)(Vg_DebugMsg,
6126 "ERROR: --ignore-ranges: "
6127 "invalid syntax, or end <= start in range\n");
6128 return False;
6129 }
6130 if (gIgnoredAddressRanges) {
florianca631452015-08-05 13:23:11 +00006131 UInt i;
sewardjc5fc8662014-03-20 23:00:09 +00006132 for (i = 0; i < VG_(sizeRangeMap)(gIgnoredAddressRanges); i++) {
6133 UWord val = IAR_INVALID;
6134 UWord key_min = ~(UWord)0;
6135 UWord key_max = (UWord)0;
6136 VG_(indexRangeMap)( &key_min, &key_max, &val,
6137 gIgnoredAddressRanges, i );
6138 tl_assert(key_min <= key_max);
6139 UWord limit = 0x4000000; /* 64M - entirely arbitrary limit */
philippe1e6ed122015-06-11 19:57:42 +00006140 if (key_max - key_min > limit && val == IAR_CommandLine) {
sewardjc5fc8662014-03-20 23:00:09 +00006141 VG_(message)(Vg_DebugMsg,
6142 "ERROR: --ignore-ranges: suspiciously large range:\n");
6143 VG_(message)(Vg_DebugMsg,
philippe1e6ed122015-06-11 19:57:42 +00006144 " 0x%lx-0x%lx (size %lu)\n", key_min, key_max,
sewardjc5fc8662014-03-20 23:00:09 +00006145 key_max - key_min + 1);
6146 return False;
6147 }
sewardj05a46732006-10-17 01:28:10 +00006148 }
sewardj05a46732006-10-17 01:28:10 +00006149 }
6150 }
6151
Elliott Hughesa0664b92017-04-18 17:46:52 -07006152 else if VG_STR_CLO(arg, "--ignore-range-below-sp", tmp_str) {
6153 /* This seems at first a bit weird, but: in order to imply
6154 a non-wrapped-around address range, the first offset needs to be
6155 larger than the second one. For example
6156 --ignore-range-below-sp=8192,8189
6157 would cause accesses to in the range [SP-8192, SP-8189] to be
6158 ignored. */
6159 UInt offs1 = 0, offs2 = 0;
6160 Bool ok = parse_UInt_pair(&tmp_str, &offs1, &offs2);
6161 // Ensure we used all the text after the '=' sign.
6162 if (ok && *tmp_str != 0) ok = False;
6163 if (!ok) {
6164 VG_(message)(Vg_DebugMsg,
6165 "ERROR: --ignore-range-below-sp: invalid syntax. "
6166 " Expected \"...=decimalnumber-decimalnumber\".\n");
6167 return False;
6168 }
6169 if (offs1 > 1000*1000 /*arbitrary*/ || offs2 > 1000*1000 /*ditto*/) {
6170 VG_(message)(Vg_DebugMsg,
6171 "ERROR: --ignore-range-below-sp: suspiciously large "
6172 "offset(s): %u and %u\n", offs1, offs2);
6173 return False;
6174 }
6175 if (offs1 <= offs2) {
6176 VG_(message)(Vg_DebugMsg,
6177 "ERROR: --ignore-range-below-sp: invalid offsets "
6178 "(the first must be larger): %u and %u\n", offs1, offs2);
6179 return False;
6180 }
6181 tl_assert(offs1 > offs2);
6182 if (offs1 - offs2 > 4096 /*arbitrary*/) {
6183 VG_(message)(Vg_DebugMsg,
6184 "ERROR: --ignore-range-below-sp: suspiciously large "
6185 "range: %u-%u (size %u)\n", offs1, offs2, offs1 - offs2);
6186 return False;
6187 }
6188 MC_(clo_ignore_range_below_sp) = True;
6189 MC_(clo_ignore_range_below_sp__first_offset) = offs1;
6190 MC_(clo_ignore_range_below_sp__last_offset) = offs2;
6191 return True;
6192 }
6193
njn83df0b62009-02-25 01:01:05 +00006194 else if VG_BHEX_CLO(arg, "--malloc-fill", MC_(clo_malloc_fill), 0x00,0xFF) {}
6195 else if VG_BHEX_CLO(arg, "--free-fill", MC_(clo_free_fill), 0x00,0xFF) {}
sewardjeb0fa932007-11-30 21:41:40 +00006196
philippe8617b5b2013-01-12 19:53:08 +00006197 else if VG_XACT_CLO(arg, "--keep-stacktraces=alloc",
6198 MC_(clo_keep_stacktraces), KS_alloc) {}
6199 else if VG_XACT_CLO(arg, "--keep-stacktraces=free",
6200 MC_(clo_keep_stacktraces), KS_free) {}
6201 else if VG_XACT_CLO(arg, "--keep-stacktraces=alloc-and-free",
6202 MC_(clo_keep_stacktraces), KS_alloc_and_free) {}
6203 else if VG_XACT_CLO(arg, "--keep-stacktraces=alloc-then-free",
6204 MC_(clo_keep_stacktraces), KS_alloc_then_free) {}
6205 else if VG_XACT_CLO(arg, "--keep-stacktraces=none",
6206 MC_(clo_keep_stacktraces), KS_none) {}
6207
sewardj021e6b62014-08-22 19:26:23 +00006208 else if VG_BOOL_CLO(arg, "--show-mismatched-frees",
6209 MC_(clo_show_mismatched_frees)) {}
sewardj2672fae2015-09-01 08:48:04 +00006210 else if VG_BOOL_CLO(arg, "--expensive-definedness-checks",
6211 MC_(clo_expensive_definedness_checks)) {}
sewardj021e6b62014-08-22 19:26:23 +00006212
njn1d0825f2006-03-27 11:37:07 +00006213 else
6214 return VG_(replacement_malloc_process_cmd_line_option)(arg);
6215
6216 return True;
njnb1cc5d62010-07-06 04:05:23 +00006217
6218
6219 bad_level:
6220 VG_(fmsg_bad_option)(arg,
6221 "--track-origins=yes has no effect when --undef-value-errors=no.\n");
njn25e49d8e72002-09-23 09:36:25 +00006222}
6223
njn51d827b2005-05-09 01:02:08 +00006224static void mc_print_usage(void)
sewardj0b392882014-07-08 09:36:06 +00006225{
njn1d0825f2006-03-27 11:37:07 +00006226 VG_(printf)(
6227" --leak-check=no|summary|full search for memory leaks at exit? [summary]\n"
njn5daa2d32009-07-10 08:16:29 +00006228" --leak-resolution=low|med|high differentiation of leak stack traces [high]\n"
philippe2193a7c2012-12-08 17:54:16 +00006229" --show-leak-kinds=kind1,kind2,.. which leak kinds to show?\n"
6230" [definite,possible]\n"
6231" --errors-for-leak-kinds=kind1,kind2,.. which leak kinds are errors?\n"
6232" [definite,possible]\n"
sewardj122f6af2014-09-03 21:58:54 +00006233" where kind is one of:\n"
6234" definite indirect possible reachable all none\n"
philippeab1fce92013-09-29 13:47:32 +00006235" --leak-check-heuristics=heur1,heur2,... which heuristics to use for\n"
philippec22f5192015-09-02 21:57:53 +00006236" improving leak search false positive [all]\n"
sewardj122f6af2014-09-03 21:58:54 +00006237" where heur is one of:\n"
6238" stdstring length64 newarray multipleinheritance all none\n"
philippe2193a7c2012-12-08 17:54:16 +00006239" --show-reachable=yes same as --show-leak-kinds=all\n"
6240" --show-reachable=no --show-possibly-lost=yes\n"
6241" same as --show-leak-kinds=definite,possible\n"
6242" --show-reachable=no --show-possibly-lost=no\n"
6243" same as --show-leak-kinds=definite\n"
njn1d0825f2006-03-27 11:37:07 +00006244" --undef-value-errors=no|yes check for undefined value errors [yes]\n"
sewardj7cf4e6b2008-05-01 20:24:26 +00006245" --track-origins=no|yes show origins of undefined values? [no]\n"
sewardjadd95c82015-08-31 10:36:02 +00006246" --partial-loads-ok=no|yes too hard to explain here; see manual [yes]\n"
sewardj2672fae2015-09-01 08:48:04 +00006247" --expensive-definedness-checks=no|yes\n"
6248" Use extra-precise definedness tracking [no]\n"
philippe2193a7c2012-12-08 17:54:16 +00006249" --freelist-vol=<number> volume of freed blocks queue [20000000]\n"
6250" --freelist-big-blocks=<number> releases first blocks with size>= [1000000]\n"
Elliott Hughesa0664b92017-04-18 17:46:52 -07006251" --workaround-gcc296-bugs=no|yes self explanatory [no]. Deprecated.\n"
6252" Use --ignore-range-below-sp instead.\n"
sewardj05a46732006-10-17 01:28:10 +00006253" --ignore-ranges=0xPP-0xQQ[,0xRR-0xSS] assume given addresses are OK\n"
Elliott Hughesa0664b92017-04-18 17:46:52 -07006254" --ignore-range-below-sp=<number>-<number> do not report errors for\n"
6255" accesses at the given offsets below SP\n"
sewardjeb0fa932007-11-30 21:41:40 +00006256" --malloc-fill=<hexnumber> fill malloc'd areas with given value\n"
6257" --free-fill=<hexnumber> fill free'd areas with given value\n"
philippe8617b5b2013-01-12 19:53:08 +00006258" --keep-stacktraces=alloc|free|alloc-and-free|alloc-then-free|none\n"
philippe92cd8382015-08-29 10:45:26 +00006259" stack trace(s) to keep for malloc'd/free'd areas [alloc-and-free]\n"
sewardj021e6b62014-08-22 19:26:23 +00006260" --show-mismatched-frees=no|yes show frees that don't match the allocator? [yes]\n"
njn1d0825f2006-03-27 11:37:07 +00006261 );
njn3e884182003-04-15 13:03:23 +00006262}
6263
njn51d827b2005-05-09 01:02:08 +00006264static void mc_print_debug_usage(void)
njn3e884182003-04-15 13:03:23 +00006265{
njn97db7612009-08-04 02:32:55 +00006266 VG_(printf)(
6267" (none)\n"
6268 );
njn25e49d8e72002-09-23 09:36:25 +00006269}
6270
sewardjf3418c02005-11-08 14:10:24 +00006271
nethercote8b76fe52004-11-08 19:20:09 +00006272/*------------------------------------------------------------*/
sewardj7ce71662008-05-02 10:33:15 +00006273/*--- Client blocks ---*/
nethercote8b76fe52004-11-08 19:20:09 +00006274/*------------------------------------------------------------*/
6275
6276/* Client block management:
6277
6278 This is managed as an expanding array of client block descriptors.
6279 Indices of live descriptors are issued to the client, so it can ask
6280 to free them later. Therefore we cannot slide live entries down
6281 over dead ones. Instead we must use free/inuse flags and scan for
6282 an empty slot at allocation time. This in turn means allocation is
6283 relatively expensive, so we hope this does not happen too often.
nethercote8b76fe52004-11-08 19:20:09 +00006284
sewardjedc75ab2005-03-15 23:30:32 +00006285 An unused block has start == size == 0
6286*/
nethercote8b76fe52004-11-08 19:20:09 +00006287
sewardj7ce71662008-05-02 10:33:15 +00006288/* type CGenBlock is defined in mc_include.h */
nethercote8b76fe52004-11-08 19:20:09 +00006289
6290/* This subsystem is self-initialising. */
sewardj56adc352008-05-02 11:25:17 +00006291static UWord cgb_size = 0;
6292static UWord cgb_used = 0;
njn695c16e2005-03-27 03:40:28 +00006293static CGenBlock* cgbs = NULL;
nethercote8b76fe52004-11-08 19:20:09 +00006294
6295/* Stats for this subsystem. */
sewardj56adc352008-05-02 11:25:17 +00006296static ULong cgb_used_MAX = 0; /* Max in use. */
6297static ULong cgb_allocs = 0; /* Number of allocs. */
6298static ULong cgb_discards = 0; /* Number of discards. */
6299static ULong cgb_search = 0; /* Number of searches. */
nethercote8b76fe52004-11-08 19:20:09 +00006300
6301
sewardj7ce71662008-05-02 10:33:15 +00006302/* Get access to the client block array. */
6303void MC_(get_ClientBlock_array)( /*OUT*/CGenBlock** blocks,
6304 /*OUT*/UWord* nBlocks )
6305{
6306 *blocks = cgbs;
6307 *nBlocks = cgb_used;
6308}
6309
6310
nethercote8b76fe52004-11-08 19:20:09 +00006311static
njn695c16e2005-03-27 03:40:28 +00006312Int alloc_client_block ( void )
nethercote8b76fe52004-11-08 19:20:09 +00006313{
sewardj56adc352008-05-02 11:25:17 +00006314 UWord i, sz_new;
nethercote8b76fe52004-11-08 19:20:09 +00006315 CGenBlock* cgbs_new;
6316
njn695c16e2005-03-27 03:40:28 +00006317 cgb_allocs++;
nethercote8b76fe52004-11-08 19:20:09 +00006318
njn695c16e2005-03-27 03:40:28 +00006319 for (i = 0; i < cgb_used; i++) {
6320 cgb_search++;
6321 if (cgbs[i].start == 0 && cgbs[i].size == 0)
nethercote8b76fe52004-11-08 19:20:09 +00006322 return i;
6323 }
6324
6325 /* Not found. Try to allocate one at the end. */
njn695c16e2005-03-27 03:40:28 +00006326 if (cgb_used < cgb_size) {
6327 cgb_used++;
6328 return cgb_used-1;
nethercote8b76fe52004-11-08 19:20:09 +00006329 }
6330
6331 /* Ok, we have to allocate a new one. */
njn695c16e2005-03-27 03:40:28 +00006332 tl_assert(cgb_used == cgb_size);
6333 sz_new = (cgbs == NULL) ? 10 : (2 * cgb_size);
nethercote8b76fe52004-11-08 19:20:09 +00006334
sewardj9c606bd2008-09-18 18:12:50 +00006335 cgbs_new = VG_(malloc)( "mc.acb.1", sz_new * sizeof(CGenBlock) );
njn695c16e2005-03-27 03:40:28 +00006336 for (i = 0; i < cgb_used; i++)
6337 cgbs_new[i] = cgbs[i];
nethercote8b76fe52004-11-08 19:20:09 +00006338
njn695c16e2005-03-27 03:40:28 +00006339 if (cgbs != NULL)
6340 VG_(free)( cgbs );
6341 cgbs = cgbs_new;
nethercote8b76fe52004-11-08 19:20:09 +00006342
njn695c16e2005-03-27 03:40:28 +00006343 cgb_size = sz_new;
6344 cgb_used++;
6345 if (cgb_used > cgb_used_MAX)
6346 cgb_used_MAX = cgb_used;
6347 return cgb_used-1;
nethercote8b76fe52004-11-08 19:20:09 +00006348}
6349
6350
6351static void show_client_block_stats ( void )
6352{
6353 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00006354 "general CBs: %llu allocs, %llu discards, %llu maxinuse, %llu search\n",
njn695c16e2005-03-27 03:40:28 +00006355 cgb_allocs, cgb_discards, cgb_used_MAX, cgb_search
nethercote8b76fe52004-11-08 19:20:09 +00006356 );
6357}
sewardj3b290482011-05-06 21:02:55 +00006358static void print_monitor_help ( void )
6359{
6360 VG_(gdb_printf)
6361 (
6362"\n"
6363"memcheck monitor commands:\n"
philippeb92e6322015-08-04 19:11:03 +00006364" xb <addr> [<len>]\n"
6365" prints validity bits for <len> (or 1) bytes at <addr>\n"
sewardj3b290482011-05-06 21:02:55 +00006366" bit values 0 = valid, 1 = invalid, __ = unaddressable byte\n"
philippeb92e6322015-08-04 19:11:03 +00006367" Then prints the bytes values below the corresponding validity bits\n"
6368" in a layout similar to the gdb command 'x /<len>xb <addr>'\n"
6369" Example: xb 0x8049c78 10\n"
6370" get_vbits <addr> [<len>]\n"
6371" Similar to xb, but only prints the validity bytes by group of 4.\n"
sewardj30b3eca2011-06-28 08:20:39 +00006372" make_memory [noaccess|undefined\n"
6373" |defined|Definedifaddressable] <addr> [<len>]\n"
sewardj3b290482011-05-06 21:02:55 +00006374" mark <len> (or 1) bytes at <addr> with the given accessibility\n"
sewardj30b3eca2011-06-28 08:20:39 +00006375" check_memory [addressable|defined] <addr> [<len>]\n"
sewardj3b290482011-05-06 21:02:55 +00006376" check that <len> (or 1) bytes at <addr> have the given accessibility\n"
6377" and outputs a description of <addr>\n"
philippe2193a7c2012-12-08 17:54:16 +00006378" leak_check [full*|summary]\n"
6379" [kinds kind1,kind2,...|reachable|possibleleak*|definiteleak]\n"
philippeab1fce92013-09-29 13:47:32 +00006380" [heuristics heur1,heur2,...]\n"
sewardjc8bd1df2011-06-26 12:41:33 +00006381" [increased*|changed|any]\n"
philippe84234902012-01-14 13:53:13 +00006382" [unlimited*|limited <max_loss_records_output>]\n"
sewardj3b290482011-05-06 21:02:55 +00006383" * = defaults\n"
sewardj122f6af2014-09-03 21:58:54 +00006384" where kind is one of:\n"
6385" definite indirect possible reachable all none\n"
6386" where heur is one of:\n"
6387" stdstring length64 newarray multipleinheritance all none*\n"
6388" Examples: leak_check\n"
6389" leak_check summary any\n"
6390" leak_check full kinds indirect,possible\n"
6391" leak_check full reachable any limited 100\n"
philippece3b04c2015-09-02 21:26:34 +00006392" block_list <loss_record_nr>|<loss_record_nr_from>..<loss_record_nr_to>\n"
6393" [unlimited*|limited <max_blocks>]\n"
6394" [heuristics heur1,heur2,...]\n"
philippea22f59d2012-01-26 23:13:52 +00006395" after a leak search, shows the list of blocks of <loss_record_nr>\n"
philippece3b04c2015-09-02 21:26:34 +00006396" (or of the range <loss_record_nr_from>..<loss_record_nr_to>).\n"
6397" With heuristics, only shows the blocks found via heur1,heur2,...\n"
philippe6d3cb492015-08-13 22:49:32 +00006398" * = defaults\n"
philippea22f59d2012-01-26 23:13:52 +00006399" who_points_at <addr> [<len>]\n"
6400" shows places pointing inside <len> (default 1) bytes at <addr>\n"
6401" (with len 1, only shows \"start pointers\" pointing exactly to <addr>,\n"
6402" with len > 1, will also show \"interior pointers\")\n"
sewardj3b290482011-05-06 21:02:55 +00006403"\n");
6404}
6405
philippeb92e6322015-08-04 19:11:03 +00006406/* Print szB bytes at address, with a format similar to the gdb command
6407 x /<szB>xb address.
6408 res[i] == 1 indicates the corresponding byte is addressable. */
6409static void gdb_xb (Addr address, SizeT szB, Int res[])
6410{
6411 UInt i;
6412
6413 for (i = 0; i < szB; i++) {
6414 UInt bnr = i % 8;
6415 if (bnr == 0) {
6416 if (i != 0)
6417 VG_(printf) ("\n"); // Terminate previous line
6418 VG_(printf) ("%p:", (void*)(address+i));
6419 }
6420 if (res[i] == 1)
6421 VG_(printf) ("\t0x%02x", *(UChar*)(address+i));
6422 else
6423 VG_(printf) ("\t0x??");
6424 }
6425 VG_(printf) ("\n"); // Terminate previous line
6426}
6427
philippece3b04c2015-09-02 21:26:34 +00006428
6429/* Returns the address of the next non space character,
6430 or address of the string terminator. */
6431static HChar* next_non_space (HChar *s)
6432{
6433 while (*s && *s == ' ')
6434 s++;
6435 return s;
6436}
6437
6438/* Parse an integer slice, i.e. a single integer or a range of integer.
6439 Syntax is:
6440 <integer>[..<integer> ]
6441 (spaces are allowed before and/or after ..).
6442 Return True if range correctly parsed, False otherwise. */
6443static Bool VG_(parse_slice) (HChar* s, HChar** saveptr,
6444 UInt *from, UInt *to)
6445{
6446 HChar* wl;
6447 HChar *endptr;
6448 endptr = NULL;////
6449 wl = VG_(strtok_r) (s, " ", saveptr);
6450
6451 /* slice must start with an integer. */
6452 if (wl == NULL) {
6453 VG_(gdb_printf) ("expecting integer or slice <from>..<to>\n");
6454 return False;
6455 }
6456 *from = VG_(strtoull10) (wl, &endptr);
6457 if (endptr == wl) {
6458 VG_(gdb_printf) ("invalid integer or slice <from>..<to>\n");
6459 return False;
6460 }
6461
6462 if (*endptr == '\0' && *next_non_space(*saveptr) != '.') {
6463 /* wl token is an integer terminating the string
6464 or else next token does not start with .
6465 In both cases, the slice is a single integer. */
6466 *to = *from;
6467 return True;
6468 }
6469
6470 if (*endptr == '\0') {
6471 // iii .. => get the next token
6472 wl = VG_(strtok_r) (NULL, " .", saveptr);
6473 } else {
6474 // It must be iii..
6475 if (*endptr != '.' && *(endptr+1) != '.') {
6476 VG_(gdb_printf) ("expecting slice <from>..<to>\n");
6477 return False;
6478 }
6479 if ( *(endptr+2) == ' ') {
6480 // It must be iii.. jjj => get the next token
6481 wl = VG_(strtok_r) (NULL, " .", saveptr);
6482 } else {
6483 // It must be iii..jjj
6484 wl = endptr+2;
6485 }
6486 }
6487
6488 *to = VG_(strtoull10) (wl, &endptr);
6489 if (*endptr != '\0') {
6490 VG_(gdb_printf) ("missing/wrong 'to' of slice <from>..<to>\n");
6491 return False;
6492 }
6493
6494 if (*from > *to) {
6495 VG_(gdb_printf) ("<from> cannot be bigger than <to> "
6496 "in slice <from>..<to>\n");
6497 return False;
6498 }
6499
6500 return True;
6501}
6502
sewardj3b290482011-05-06 21:02:55 +00006503/* return True if request recognised, False otherwise */
florian19f91bb2012-11-10 22:29:54 +00006504static Bool handle_gdb_monitor_command (ThreadId tid, HChar *req)
sewardj3b290482011-05-06 21:02:55 +00006505{
florian19f91bb2012-11-10 22:29:54 +00006506 HChar* wcmd;
Elliott Hughesa0664b92017-04-18 17:46:52 -07006507 HChar s[VG_(strlen)(req) + 1]; /* copy for strtok_r */
florian19f91bb2012-11-10 22:29:54 +00006508 HChar *ssaveptr;
sewardj3b290482011-05-06 21:02:55 +00006509
6510 VG_(strcpy) (s, req);
6511
6512 wcmd = VG_(strtok_r) (s, " ", &ssaveptr);
6513 /* NB: if possible, avoid introducing a new command below which
sewardj30b3eca2011-06-28 08:20:39 +00006514 starts with the same first letter(s) as an already existing
sewardj3b290482011-05-06 21:02:55 +00006515 command. This ensures a shorter abbreviation for the user. */
6516 switch (VG_(keyword_id)
philippea22f59d2012-01-26 23:13:52 +00006517 ("help get_vbits leak_check make_memory check_memory "
philippeb92e6322015-08-04 19:11:03 +00006518 "block_list who_points_at xb",
sewardj3b290482011-05-06 21:02:55 +00006519 wcmd, kwd_report_duplicated_matches)) {
6520 case -2: /* multiple matches */
6521 return True;
6522 case -1: /* not found */
6523 return False;
6524 case 0: /* help */
6525 print_monitor_help();
6526 return True;
sewardj30b3eca2011-06-28 08:20:39 +00006527 case 1: { /* get_vbits */
sewardj3b290482011-05-06 21:02:55 +00006528 Addr address;
6529 SizeT szB = 1;
philippe07c08522014-05-14 20:39:27 +00006530 if (VG_(strtok_get_address_and_size) (&address, &szB, &ssaveptr)) {
sewardj3b290482011-05-06 21:02:55 +00006531 UChar vbits;
6532 Int i;
6533 Int unaddressable = 0;
6534 for (i = 0; i < szB; i++) {
6535 Int res = mc_get_or_set_vbits_for_client
6536 (address+i, (Addr) &vbits, 1,
6537 False, /* get them */
6538 False /* is client request */ );
philippe8d674252012-03-20 19:04:39 +00006539 /* we are before the first character on next line, print a \n. */
sewardj3b290482011-05-06 21:02:55 +00006540 if ((i % 32) == 0 && i != 0)
philippe02ea4132013-09-04 21:42:43 +00006541 VG_(printf) ("\n");
philippe8d674252012-03-20 19:04:39 +00006542 /* we are before the next block of 4 starts, print a space. */
sewardj3b290482011-05-06 21:02:55 +00006543 else if ((i % 4) == 0 && i != 0)
philippe02ea4132013-09-04 21:42:43 +00006544 VG_(printf) (" ");
sewardj3b290482011-05-06 21:02:55 +00006545 if (res == 1) {
philippe02ea4132013-09-04 21:42:43 +00006546 VG_(printf) ("%02x", vbits);
sewardj3b290482011-05-06 21:02:55 +00006547 } else {
6548 tl_assert(3 == res);
6549 unaddressable++;
philippe02ea4132013-09-04 21:42:43 +00006550 VG_(printf) ("__");
sewardj3b290482011-05-06 21:02:55 +00006551 }
6552 }
philippe02ea4132013-09-04 21:42:43 +00006553 VG_(printf) ("\n");
sewardj3b290482011-05-06 21:02:55 +00006554 if (unaddressable) {
philippe02ea4132013-09-04 21:42:43 +00006555 VG_(printf)
floriande3df032015-08-04 21:26:10 +00006556 ("Address %p len %lu has %d bytes unaddressable\n",
sewardj3b290482011-05-06 21:02:55 +00006557 (void *)address, szB, unaddressable);
6558 }
6559 }
6560 return True;
6561 }
sewardj30b3eca2011-06-28 08:20:39 +00006562 case 2: { /* leak_check */
sewardj3b290482011-05-06 21:02:55 +00006563 Int err = 0;
sewardjc8bd1df2011-06-26 12:41:33 +00006564 LeakCheckParams lcp;
florian19f91bb2012-11-10 22:29:54 +00006565 HChar* kw;
sewardj3b290482011-05-06 21:02:55 +00006566
sewardjc8bd1df2011-06-26 12:41:33 +00006567 lcp.mode = LC_Full;
philippe2193a7c2012-12-08 17:54:16 +00006568 lcp.show_leak_kinds = R2S(Possible) | R2S(Unreached);
philippe278b2a32013-10-09 20:12:39 +00006569 lcp.errors_for_leak_kinds = 0; // no errors for interactive leak search.
6570 lcp.heuristics = 0;
sewardjc8bd1df2011-06-26 12:41:33 +00006571 lcp.deltamode = LCD_Increased;
philippe84234902012-01-14 13:53:13 +00006572 lcp.max_loss_records_output = 999999999;
sewardjc8bd1df2011-06-26 12:41:33 +00006573 lcp.requested_by_monitor_command = True;
sewardj3b290482011-05-06 21:02:55 +00006574
6575 for (kw = VG_(strtok_r) (NULL, " ", &ssaveptr);
6576 kw != NULL;
6577 kw = VG_(strtok_r) (NULL, " ", &ssaveptr)) {
6578 switch (VG_(keyword_id)
6579 ("full summary "
philippe2193a7c2012-12-08 17:54:16 +00006580 "kinds reachable possibleleak definiteleak "
philippeab1fce92013-09-29 13:47:32 +00006581 "heuristics "
philippe84234902012-01-14 13:53:13 +00006582 "increased changed any "
6583 "unlimited limited ",
sewardj3b290482011-05-06 21:02:55 +00006584 kw, kwd_report_all)) {
6585 case -2: err++; break;
6586 case -1: err++; break;
sewardjc8bd1df2011-06-26 12:41:33 +00006587 case 0: /* full */
6588 lcp.mode = LC_Full; break;
6589 case 1: /* summary */
6590 lcp.mode = LC_Summary; break;
philippe2193a7c2012-12-08 17:54:16 +00006591 case 2: { /* kinds */
6592 wcmd = VG_(strtok_r) (NULL, " ", &ssaveptr);
philippeec905f72014-08-17 20:03:51 +00006593 if (wcmd == NULL
6594 || !VG_(parse_enum_set)(MC_(parse_leak_kinds_tokens),
6595 True/*allow_all*/,
6596 wcmd,
6597 &lcp.show_leak_kinds)) {
philippe2193a7c2012-12-08 17:54:16 +00006598 VG_(gdb_printf) ("missing or malformed leak kinds set\n");
6599 err++;
6600 }
6601 break;
6602 }
6603 case 3: /* reachable */
philippeec905f72014-08-17 20:03:51 +00006604 lcp.show_leak_kinds = MC_(all_Reachedness)();
philippe2193a7c2012-12-08 17:54:16 +00006605 break;
6606 case 4: /* possibleleak */
6607 lcp.show_leak_kinds
6608 = R2S(Possible) | R2S(IndirectLeak) | R2S(Unreached);
6609 break;
6610 case 5: /* definiteleak */
6611 lcp.show_leak_kinds = R2S(Unreached);
6612 break;
philippeab1fce92013-09-29 13:47:32 +00006613 case 6: { /* heuristics */
6614 wcmd = VG_(strtok_r) (NULL, " ", &ssaveptr);
philippeec905f72014-08-17 20:03:51 +00006615 if (wcmd == NULL
6616 || !VG_(parse_enum_set)(MC_(parse_leak_heuristics_tokens),
6617 True,/*allow_all*/
6618 wcmd,
6619 &lcp.heuristics)) {
philippeab1fce92013-09-29 13:47:32 +00006620 VG_(gdb_printf) ("missing or malformed heuristics set\n");
6621 err++;
6622 }
6623 break;
6624 }
6625 case 7: /* increased */
sewardjc8bd1df2011-06-26 12:41:33 +00006626 lcp.deltamode = LCD_Increased; break;
philippeab1fce92013-09-29 13:47:32 +00006627 case 8: /* changed */
sewardjc8bd1df2011-06-26 12:41:33 +00006628 lcp.deltamode = LCD_Changed; break;
philippeab1fce92013-09-29 13:47:32 +00006629 case 9: /* any */
sewardjc8bd1df2011-06-26 12:41:33 +00006630 lcp.deltamode = LCD_Any; break;
philippeab1fce92013-09-29 13:47:32 +00006631 case 10: /* unlimited */
philippe84234902012-01-14 13:53:13 +00006632 lcp.max_loss_records_output = 999999999; break;
philippeab1fce92013-09-29 13:47:32 +00006633 case 11: { /* limited */
florian19f91bb2012-11-10 22:29:54 +00006634 Int int_value;
florian6bd9dc12012-11-23 16:17:43 +00006635 const HChar* endptr;
philippe84234902012-01-14 13:53:13 +00006636
6637 wcmd = VG_(strtok_r) (NULL, " ", &ssaveptr);
6638 if (wcmd == NULL) {
6639 int_value = 0;
6640 endptr = "empty"; /* to report an error below */
6641 } else {
florian6bd9dc12012-11-23 16:17:43 +00006642 HChar *the_end;
6643 int_value = VG_(strtoll10) (wcmd, &the_end);
6644 endptr = the_end;
philippe84234902012-01-14 13:53:13 +00006645 }
6646 if (*endptr != '\0')
6647 VG_(gdb_printf) ("missing or malformed integer value\n");
6648 else if (int_value > 0)
6649 lcp.max_loss_records_output = (UInt) int_value;
6650 else
philippeb92e6322015-08-04 19:11:03 +00006651 VG_(gdb_printf) ("max_loss_records_output must be >= 1,"
6652 " got %d\n", int_value);
philippe84234902012-01-14 13:53:13 +00006653 break;
6654 }
sewardjc8bd1df2011-06-26 12:41:33 +00006655 default:
6656 tl_assert (0);
sewardj3b290482011-05-06 21:02:55 +00006657 }
6658 }
6659 if (!err)
philippe84234902012-01-14 13:53:13 +00006660 MC_(detect_memory_leaks)(tid, &lcp);
sewardj3b290482011-05-06 21:02:55 +00006661 return True;
6662 }
6663
sewardj30b3eca2011-06-28 08:20:39 +00006664 case 3: { /* make_memory */
sewardj3b290482011-05-06 21:02:55 +00006665 Addr address;
6666 SizeT szB = 1;
florian19f91bb2012-11-10 22:29:54 +00006667 Int kwdid = VG_(keyword_id)
sewardj30b3eca2011-06-28 08:20:39 +00006668 ("noaccess undefined defined Definedifaddressable",
sewardj3b290482011-05-06 21:02:55 +00006669 VG_(strtok_r) (NULL, " ", &ssaveptr), kwd_report_all);
philippe07c08522014-05-14 20:39:27 +00006670 if (!VG_(strtok_get_address_and_size) (&address, &szB, &ssaveptr))
6671 return True;
sewardj3b290482011-05-06 21:02:55 +00006672 switch (kwdid) {
6673 case -2: break;
6674 case -1: break;
6675 case 0: MC_(make_mem_noaccess) (address, szB); break;
6676 case 1: make_mem_undefined_w_tid_and_okind ( address, szB, tid,
6677 MC_OKIND_USER ); break;
6678 case 2: MC_(make_mem_defined) ( address, szB ); break;
6679 case 3: make_mem_defined_if_addressable ( address, szB ); break;;
6680 default: tl_assert(0);
6681 }
6682 return True;
6683 }
6684
sewardj30b3eca2011-06-28 08:20:39 +00006685 case 4: { /* check_memory */
sewardj3b290482011-05-06 21:02:55 +00006686 Addr address;
6687 SizeT szB = 1;
6688 Addr bad_addr;
6689 UInt okind;
florian6bd9dc12012-11-23 16:17:43 +00006690 const HChar* src;
sewardj3b290482011-05-06 21:02:55 +00006691 UInt otag;
6692 UInt ecu;
6693 ExeContext* origin_ec;
6694 MC_ReadResult res;
6695
florian19f91bb2012-11-10 22:29:54 +00006696 Int kwdid = VG_(keyword_id)
sewardj3b290482011-05-06 21:02:55 +00006697 ("addressable defined",
6698 VG_(strtok_r) (NULL, " ", &ssaveptr), kwd_report_all);
philippe07c08522014-05-14 20:39:27 +00006699 if (!VG_(strtok_get_address_and_size) (&address, &szB, &ssaveptr))
6700 return True;
sewardj3b290482011-05-06 21:02:55 +00006701 switch (kwdid) {
6702 case -2: break;
6703 case -1: break;
philippeab1fce92013-09-29 13:47:32 +00006704 case 0: /* addressable */
sewardj3b290482011-05-06 21:02:55 +00006705 if (is_mem_addressable ( address, szB, &bad_addr ))
floriande3df032015-08-04 21:26:10 +00006706 VG_(printf) ("Address %p len %lu addressable\n",
sewardj3b290482011-05-06 21:02:55 +00006707 (void *)address, szB);
6708 else
philippe02ea4132013-09-04 21:42:43 +00006709 VG_(printf)
floriande3df032015-08-04 21:26:10 +00006710 ("Address %p len %lu not addressable:\nbad address %p\n",
sewardj3b290482011-05-06 21:02:55 +00006711 (void *)address, szB, (void *) bad_addr);
6712 MC_(pp_describe_addr) (address);
6713 break;
philippeab1fce92013-09-29 13:47:32 +00006714 case 1: /* defined */
6715 res = is_mem_defined ( address, szB, &bad_addr, &otag );
sewardj3b290482011-05-06 21:02:55 +00006716 if (MC_AddrErr == res)
philippe02ea4132013-09-04 21:42:43 +00006717 VG_(printf)
floriande3df032015-08-04 21:26:10 +00006718 ("Address %p len %lu not addressable:\nbad address %p\n",
sewardj3b290482011-05-06 21:02:55 +00006719 (void *)address, szB, (void *) bad_addr);
6720 else if (MC_ValueErr == res) {
6721 okind = otag & 3;
6722 switch (okind) {
6723 case MC_OKIND_STACK:
6724 src = " was created by a stack allocation"; break;
6725 case MC_OKIND_HEAP:
6726 src = " was created by a heap allocation"; break;
6727 case MC_OKIND_USER:
6728 src = " was created by a client request"; break;
6729 case MC_OKIND_UNKNOWN:
6730 src = ""; break;
6731 default: tl_assert(0);
6732 }
philippe02ea4132013-09-04 21:42:43 +00006733 VG_(printf)
floriande3df032015-08-04 21:26:10 +00006734 ("Address %p len %lu not defined:\n"
sewardj3b290482011-05-06 21:02:55 +00006735 "Uninitialised value at %p%s\n",
6736 (void *)address, szB, (void *) bad_addr, src);
6737 ecu = otag & ~3;
6738 if (VG_(is_plausible_ECU)(ecu)) {
6739 origin_ec = VG_(get_ExeContext_from_ECU)( ecu );
6740 VG_(pp_ExeContext)( origin_ec );
6741 }
6742 }
6743 else
floriande3df032015-08-04 21:26:10 +00006744 VG_(printf) ("Address %p len %lu defined\n",
philippe02ea4132013-09-04 21:42:43 +00006745 (void *)address, szB);
sewardj3b290482011-05-06 21:02:55 +00006746 MC_(pp_describe_addr) (address);
6747 break;
6748 default: tl_assert(0);
6749 }
6750 return True;
6751 }
6752
philippea22f59d2012-01-26 23:13:52 +00006753 case 5: { /* block_list */
florian19f91bb2012-11-10 22:29:54 +00006754 HChar* wl;
philippe6d3cb492015-08-13 22:49:32 +00006755 HChar *the_end;
philippece3b04c2015-09-02 21:26:34 +00006756 UInt lr_nr_from = 0;
6757 UInt lr_nr_to = 0;
philippe6d3cb492015-08-13 22:49:32 +00006758
philippece3b04c2015-09-02 21:26:34 +00006759 if (VG_(parse_slice) (NULL, &ssaveptr, &lr_nr_from, &lr_nr_to)) {
6760 UInt limit_blocks = 999999999;
philippe6d3cb492015-08-13 22:49:32 +00006761 Int int_value;
philippece3b04c2015-09-02 21:26:34 +00006762 UInt heuristics = 0;
6763
6764 for (wl = VG_(strtok_r) (NULL, " ", &ssaveptr);
6765 wl != NULL;
6766 wl = VG_(strtok_r) (NULL, " ", &ssaveptr)) {
6767 switch (VG_(keyword_id) ("unlimited limited heuristics ",
philippe6d3cb492015-08-13 22:49:32 +00006768 wl, kwd_report_all)) {
6769 case -2: return True;
6770 case -1: return True;
6771 case 0: /* unlimited */
6772 limit_blocks = 999999999; break;
6773 case 1: /* limited */
6774 wcmd = VG_(strtok_r) (NULL, " ", &ssaveptr);
6775 if (wcmd == NULL) {
6776 VG_(gdb_printf) ("missing integer value\n");
6777 return True;
6778 }
6779 int_value = VG_(strtoll10) (wcmd, &the_end);
6780 if (*the_end != '\0') {
6781 VG_(gdb_printf) ("malformed integer value\n");
6782 return True;
6783 }
6784 if (int_value <= 0) {
6785 VG_(gdb_printf) ("max_blocks must be >= 1,"
6786 " got %d\n", int_value);
6787 return True;
6788 }
6789 limit_blocks = (UInt) int_value;
6790 break;
philippece3b04c2015-09-02 21:26:34 +00006791 case 2: /* heuristics */
6792 wcmd = VG_(strtok_r) (NULL, " ", &ssaveptr);
6793 if (wcmd == NULL
6794 || !VG_(parse_enum_set)(MC_(parse_leak_heuristics_tokens),
6795 True,/*allow_all*/
6796 wcmd,
6797 &heuristics)) {
6798 VG_(gdb_printf) ("missing or malformed heuristics set\n");
6799 return True;
6800 }
6801 break;
philippe6d3cb492015-08-13 22:49:32 +00006802 default:
6803 tl_assert (0);
6804 }
philippe6d3cb492015-08-13 22:49:32 +00006805 }
philippece3b04c2015-09-02 21:26:34 +00006806 /* substract 1 from lr_nr_from/lr_nr_to as what is shown to the user
6807 is 1 more than the index in lr_array. */
6808 if (lr_nr_from == 0 || ! MC_(print_block_list) (lr_nr_from-1,
6809 lr_nr_to-1,
6810 limit_blocks,
6811 heuristics))
philippea22f59d2012-01-26 23:13:52 +00006812 VG_(gdb_printf) ("invalid loss record nr\n");
6813 }
6814 return True;
6815 }
6816
6817 case 6: { /* who_points_at */
6818 Addr address;
6819 SizeT szB = 1;
6820
philippe07c08522014-05-14 20:39:27 +00006821 if (!VG_(strtok_get_address_and_size) (&address, &szB, &ssaveptr))
6822 return True;
philippea22f59d2012-01-26 23:13:52 +00006823 if (address == (Addr) 0) {
6824 VG_(gdb_printf) ("Cannot search who points at 0x0\n");
6825 return True;
6826 }
6827 MC_(who_points_at) (address, szB);
6828 return True;
6829 }
6830
philippeb92e6322015-08-04 19:11:03 +00006831 case 7: { /* xb */
6832 Addr address;
6833 SizeT szB = 1;
6834 if (VG_(strtok_get_address_and_size) (&address, &szB, &ssaveptr)) {
6835 UChar vbits[8];
6836 Int res[8];
6837 Int i;
6838 Int unaddressable = 0;
6839 for (i = 0; i < szB; i++) {
6840 Int bnr = i % 8;
6841 res[bnr] = mc_get_or_set_vbits_for_client
6842 (address+i, (Addr) &vbits[bnr], 1,
6843 False, /* get them */
6844 False /* is client request */ );
6845 /* We going to print the first vabits of a new line.
6846 Terminate the previous line if needed: prints a line with the
6847 address and the data. */
6848 if (bnr == 0) {
6849 if (i != 0) {
6850 VG_(printf) ("\n");
6851 gdb_xb (address + i - 8, 8, res);
6852 }
6853 VG_(printf) ("\t"); // To align VABITS with gdb_xb layout
6854 }
6855 if (res[bnr] == 1) {
6856 VG_(printf) ("\t %02x", vbits[bnr]);
6857 } else {
6858 tl_assert(3 == res[bnr]);
6859 unaddressable++;
6860 VG_(printf) ("\t __");
6861 }
6862 }
6863 VG_(printf) ("\n");
6864 if (szB % 8 == 0 && szB > 0)
6865 gdb_xb (address + szB - 8, 8, res);
6866 else
6867 gdb_xb (address + szB - szB % 8, szB % 8, res);
6868 if (unaddressable) {
6869 VG_(printf)
floriande3df032015-08-04 21:26:10 +00006870 ("Address %p len %lu has %d bytes unaddressable\n",
philippeb92e6322015-08-04 19:11:03 +00006871 (void *)address, szB, unaddressable);
6872 }
6873 }
6874 return True;
6875 }
6876
sewardj3b290482011-05-06 21:02:55 +00006877 default:
6878 tl_assert(0);
6879 return False;
6880 }
6881}
nethercote8b76fe52004-11-08 19:20:09 +00006882
sewardj7ce71662008-05-02 10:33:15 +00006883/*------------------------------------------------------------*/
6884/*--- Client requests ---*/
6885/*------------------------------------------------------------*/
nethercote8b76fe52004-11-08 19:20:09 +00006886
njn51d827b2005-05-09 01:02:08 +00006887static Bool mc_handle_client_request ( ThreadId tid, UWord* arg, UWord* ret )
nethercote8b76fe52004-11-08 19:20:09 +00006888{
6889 Int i;
nethercote8b76fe52004-11-08 19:20:09 +00006890 Addr bad_addr;
6891
njnfc26ff92004-11-22 19:12:49 +00006892 if (!VG_IS_TOOL_USERREQ('M','C',arg[0])
sewardj7ce71662008-05-02 10:33:15 +00006893 && VG_USERREQ__MALLOCLIKE_BLOCK != arg[0]
bart91347382011-03-25 20:07:25 +00006894 && VG_USERREQ__RESIZEINPLACE_BLOCK != arg[0]
sewardj7ce71662008-05-02 10:33:15 +00006895 && VG_USERREQ__FREELIKE_BLOCK != arg[0]
6896 && VG_USERREQ__CREATE_MEMPOOL != arg[0]
6897 && VG_USERREQ__DESTROY_MEMPOOL != arg[0]
6898 && VG_USERREQ__MEMPOOL_ALLOC != arg[0]
6899 && VG_USERREQ__MEMPOOL_FREE != arg[0]
6900 && VG_USERREQ__MEMPOOL_TRIM != arg[0]
6901 && VG_USERREQ__MOVE_MEMPOOL != arg[0]
6902 && VG_USERREQ__MEMPOOL_CHANGE != arg[0]
sewardj3b290482011-05-06 21:02:55 +00006903 && VG_USERREQ__MEMPOOL_EXISTS != arg[0]
sewardjc5fc8662014-03-20 23:00:09 +00006904 && VG_USERREQ__GDB_MONITOR_COMMAND != arg[0]
6905 && VG_USERREQ__ENABLE_ADDR_ERROR_REPORTING_IN_RANGE != arg[0]
6906 && VG_USERREQ__DISABLE_ADDR_ERROR_REPORTING_IN_RANGE != arg[0])
nethercote8b76fe52004-11-08 19:20:09 +00006907 return False;
6908
6909 switch (arg[0]) {
sewardjc5fc8662014-03-20 23:00:09 +00006910 case VG_USERREQ__CHECK_MEM_IS_ADDRESSABLE: {
6911 Bool ok = is_mem_addressable ( arg[1], arg[2], &bad_addr );
nethercote8b76fe52004-11-08 19:20:09 +00006912 if (!ok)
sewardj7ce71662008-05-02 10:33:15 +00006913 MC_(record_user_error) ( tid, bad_addr, /*isAddrErr*/True, 0 );
nethercote8b76fe52004-11-08 19:20:09 +00006914 *ret = ok ? (UWord)NULL : bad_addr;
sewardj8cf88b72005-07-08 01:29:33 +00006915 break;
sewardjc5fc8662014-03-20 23:00:09 +00006916 }
nethercote8b76fe52004-11-08 19:20:09 +00006917
njndbf7ca72006-03-31 11:57:59 +00006918 case VG_USERREQ__CHECK_MEM_IS_DEFINED: {
sewardj4ef552a2011-10-24 05:59:54 +00006919 Bool errorV = False;
6920 Addr bad_addrV = 0;
6921 UInt otagV = 0;
6922 Bool errorA = False;
6923 Addr bad_addrA = 0;
6924 is_mem_defined_comprehensive(
6925 arg[1], arg[2],
6926 &errorV, &bad_addrV, &otagV, &errorA, &bad_addrA
6927 );
6928 if (errorV) {
6929 MC_(record_user_error) ( tid, bad_addrV,
6930 /*isAddrErr*/False, otagV );
6931 }
6932 if (errorA) {
6933 MC_(record_user_error) ( tid, bad_addrA,
6934 /*isAddrErr*/True, 0 );
6935 }
6936 /* Return the lower of the two erring addresses, if any. */
6937 *ret = 0;
6938 if (errorV && !errorA) {
6939 *ret = bad_addrV;
6940 }
6941 if (!errorV && errorA) {
6942 *ret = bad_addrA;
6943 }
6944 if (errorV && errorA) {
6945 *ret = bad_addrV < bad_addrA ? bad_addrV : bad_addrA;
6946 }
sewardj8cf88b72005-07-08 01:29:33 +00006947 break;
nethercote8b76fe52004-11-08 19:20:09 +00006948 }
6949
sewardjc8bd1df2011-06-26 12:41:33 +00006950 case VG_USERREQ__DO_LEAK_CHECK: {
6951 LeakCheckParams lcp;
6952
6953 if (arg[1] == 0)
6954 lcp.mode = LC_Full;
6955 else if (arg[1] == 1)
6956 lcp.mode = LC_Summary;
6957 else {
6958 VG_(message)(Vg_UserMsg,
6959 "Warning: unknown memcheck leak search mode\n");
6960 lcp.mode = LC_Full;
6961 }
6962
philippe2193a7c2012-12-08 17:54:16 +00006963 lcp.show_leak_kinds = MC_(clo_show_leak_kinds);
6964 lcp.errors_for_leak_kinds = MC_(clo_error_for_leak_kinds);
philippeab1fce92013-09-29 13:47:32 +00006965 lcp.heuristics = MC_(clo_leak_check_heuristics);
sewardjc8bd1df2011-06-26 12:41:33 +00006966
6967 if (arg[2] == 0)
6968 lcp.deltamode = LCD_Any;
6969 else if (arg[2] == 1)
6970 lcp.deltamode = LCD_Increased;
6971 else if (arg[2] == 2)
6972 lcp.deltamode = LCD_Changed;
6973 else {
6974 VG_(message)
6975 (Vg_UserMsg,
6976 "Warning: unknown memcheck leak search deltamode\n");
6977 lcp.deltamode = LCD_Any;
6978 }
philippe84234902012-01-14 13:53:13 +00006979 lcp.max_loss_records_output = 999999999;
sewardjc8bd1df2011-06-26 12:41:33 +00006980 lcp.requested_by_monitor_command = False;
6981
philippe84234902012-01-14 13:53:13 +00006982 MC_(detect_memory_leaks)(tid, &lcp);
sewardj8cf88b72005-07-08 01:29:33 +00006983 *ret = 0; /* return value is meaningless */
6984 break;
sewardjc8bd1df2011-06-26 12:41:33 +00006985 }
nethercote8b76fe52004-11-08 19:20:09 +00006986
njndbf7ca72006-03-31 11:57:59 +00006987 case VG_USERREQ__MAKE_MEM_NOACCESS:
6988 MC_(make_mem_noaccess) ( arg[1], arg[2] );
sewardj8cf88b72005-07-08 01:29:33 +00006989 *ret = -1;
6990 break;
nethercote8b76fe52004-11-08 19:20:09 +00006991
njndbf7ca72006-03-31 11:57:59 +00006992 case VG_USERREQ__MAKE_MEM_UNDEFINED:
sewardj7ce71662008-05-02 10:33:15 +00006993 make_mem_undefined_w_tid_and_okind ( arg[1], arg[2], tid,
6994 MC_OKIND_USER );
sewardjedc75ab2005-03-15 23:30:32 +00006995 *ret = -1;
sewardj8cf88b72005-07-08 01:29:33 +00006996 break;
nethercote8b76fe52004-11-08 19:20:09 +00006997
njndbf7ca72006-03-31 11:57:59 +00006998 case VG_USERREQ__MAKE_MEM_DEFINED:
6999 MC_(make_mem_defined) ( arg[1], arg[2] );
sewardj8cf88b72005-07-08 01:29:33 +00007000 *ret = -1;
nethercote8b76fe52004-11-08 19:20:09 +00007001 break;
7002
njndbf7ca72006-03-31 11:57:59 +00007003 case VG_USERREQ__MAKE_MEM_DEFINED_IF_ADDRESSABLE:
7004 make_mem_defined_if_addressable ( arg[1], arg[2] );
sewardjfb1e9ad2006-03-10 13:41:58 +00007005 *ret = -1;
7006 break;
7007
sewardjedc75ab2005-03-15 23:30:32 +00007008 case VG_USERREQ__CREATE_BLOCK: /* describe a block */
sewardj8cf88b72005-07-08 01:29:33 +00007009 if (arg[1] != 0 && arg[2] != 0) {
7010 i = alloc_client_block();
7011 /* VG_(printf)("allocated %d %p\n", i, cgbs); */
7012 cgbs[i].start = arg[1];
7013 cgbs[i].size = arg[2];
florian19f91bb2012-11-10 22:29:54 +00007014 cgbs[i].desc = VG_(strdup)("mc.mhcr.1", (HChar *)arg[3]);
sewardj39f34232007-11-09 23:02:28 +00007015 cgbs[i].where = VG_(record_ExeContext) ( tid, 0/*first_ip_delta*/ );
sewardj8cf88b72005-07-08 01:29:33 +00007016 *ret = i;
7017 } else
7018 *ret = -1;
7019 break;
sewardjedc75ab2005-03-15 23:30:32 +00007020
nethercote8b76fe52004-11-08 19:20:09 +00007021 case VG_USERREQ__DISCARD: /* discard */
njn695c16e2005-03-27 03:40:28 +00007022 if (cgbs == NULL
7023 || arg[2] >= cgb_used ||
sewardj8cf88b72005-07-08 01:29:33 +00007024 (cgbs[arg[2]].start == 0 && cgbs[arg[2]].size == 0)) {
sewardjedc75ab2005-03-15 23:30:32 +00007025 *ret = 1;
sewardj8cf88b72005-07-08 01:29:33 +00007026 } else {
7027 tl_assert(arg[2] >= 0 && arg[2] < cgb_used);
7028 cgbs[arg[2]].start = cgbs[arg[2]].size = 0;
7029 VG_(free)(cgbs[arg[2]].desc);
7030 cgb_discards++;
7031 *ret = 0;
7032 }
7033 break;
nethercote8b76fe52004-11-08 19:20:09 +00007034
sewardjc2c12c22006-03-08 13:20:09 +00007035 case VG_USERREQ__GET_VBITS:
sewardjc2c12c22006-03-08 13:20:09 +00007036 *ret = mc_get_or_set_vbits_for_client
sewardj3b290482011-05-06 21:02:55 +00007037 ( arg[1], arg[2], arg[3],
7038 False /* get them */,
7039 True /* is client request */ );
sewardjc2c12c22006-03-08 13:20:09 +00007040 break;
7041
7042 case VG_USERREQ__SET_VBITS:
sewardjc2c12c22006-03-08 13:20:09 +00007043 *ret = mc_get_or_set_vbits_for_client
sewardj3b290482011-05-06 21:02:55 +00007044 ( arg[1], arg[2], arg[3],
7045 True /* set them */,
7046 True /* is client request */ );
sewardjc2c12c22006-03-08 13:20:09 +00007047 break;
nethercote8b76fe52004-11-08 19:20:09 +00007048
njn1d0825f2006-03-27 11:37:07 +00007049 case VG_USERREQ__COUNT_LEAKS: { /* count leaked bytes */
7050 UWord** argp = (UWord**)arg;
7051 // MC_(bytes_leaked) et al were set by the last leak check (or zero
7052 // if no prior leak checks performed).
7053 *argp[1] = MC_(bytes_leaked) + MC_(bytes_indirect);
7054 *argp[2] = MC_(bytes_dubious);
7055 *argp[3] = MC_(bytes_reachable);
7056 *argp[4] = MC_(bytes_suppressed);
7057 // there is no argp[5]
7058 //*argp[5] = MC_(bytes_indirect);
njn8df80b22009-03-02 05:11:06 +00007059 // XXX need to make *argp[1-4] defined; currently done in the
7060 // VALGRIND_COUNT_LEAKS_MACRO by initialising them to zero.
7061 *ret = 0;
7062 return True;
7063 }
7064 case VG_USERREQ__COUNT_LEAK_BLOCKS: { /* count leaked blocks */
7065 UWord** argp = (UWord**)arg;
7066 // MC_(blocks_leaked) et al were set by the last leak check (or zero
7067 // if no prior leak checks performed).
7068 *argp[1] = MC_(blocks_leaked) + MC_(blocks_indirect);
7069 *argp[2] = MC_(blocks_dubious);
7070 *argp[3] = MC_(blocks_reachable);
7071 *argp[4] = MC_(blocks_suppressed);
7072 // there is no argp[5]
7073 //*argp[5] = MC_(blocks_indirect);
7074 // XXX need to make *argp[1-4] defined; currently done in the
7075 // VALGRIND_COUNT_LEAK_BLOCKS_MACRO by initialising them to zero.
njn1d0825f2006-03-27 11:37:07 +00007076 *ret = 0;
7077 return True;
7078 }
7079 case VG_USERREQ__MALLOCLIKE_BLOCK: {
7080 Addr p = (Addr)arg[1];
7081 SizeT sizeB = arg[2];
philippe11cc9ce2012-03-11 17:59:00 +00007082 UInt rzB = arg[3];
njn1d0825f2006-03-27 11:37:07 +00007083 Bool is_zeroed = (Bool)arg[4];
7084
njn1dcee092009-02-24 03:07:37 +00007085 MC_(new_block) ( tid, p, sizeB, /*ignored*/0, is_zeroed,
njn1d0825f2006-03-27 11:37:07 +00007086 MC_AllocCustom, MC_(malloc_list) );
philippe11cc9ce2012-03-11 17:59:00 +00007087 if (rzB > 0) {
7088 MC_(make_mem_noaccess) ( p - rzB, rzB);
7089 MC_(make_mem_noaccess) ( p + sizeB, rzB);
7090 }
njn1d0825f2006-03-27 11:37:07 +00007091 return True;
7092 }
bart91347382011-03-25 20:07:25 +00007093 case VG_USERREQ__RESIZEINPLACE_BLOCK: {
7094 Addr p = (Addr)arg[1];
7095 SizeT oldSizeB = arg[2];
7096 SizeT newSizeB = arg[3];
7097 UInt rzB = arg[4];
7098
7099 MC_(handle_resizeInPlace) ( tid, p, oldSizeB, newSizeB, rzB );
7100 return True;
7101 }
njn1d0825f2006-03-27 11:37:07 +00007102 case VG_USERREQ__FREELIKE_BLOCK: {
7103 Addr p = (Addr)arg[1];
7104 UInt rzB = arg[2];
7105
7106 MC_(handle_free) ( tid, p, rzB, MC_AllocCustom );
7107 return True;
7108 }
7109
7110 case _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR: {
florian19f91bb2012-11-10 22:29:54 +00007111 HChar* s = (HChar*)arg[1];
njn718d3b12006-12-16 00:54:12 +00007112 Addr dst = (Addr) arg[2];
7113 Addr src = (Addr) arg[3];
7114 SizeT len = (SizeT)arg[4];
sewardj7ce71662008-05-02 10:33:15 +00007115 MC_(record_overlap_error)(tid, s, src, dst, len);
njn1d0825f2006-03-27 11:37:07 +00007116 return True;
7117 }
7118
7119 case VG_USERREQ__CREATE_MEMPOOL: {
7120 Addr pool = (Addr)arg[1];
7121 UInt rzB = arg[2];
7122 Bool is_zeroed = (Bool)arg[3];
Elliott Hughesa0664b92017-04-18 17:46:52 -07007123 UInt flags = arg[4];
njn1d0825f2006-03-27 11:37:07 +00007124
Elliott Hughesa0664b92017-04-18 17:46:52 -07007125 // The create_mempool function does not know these mempool flags,
7126 // pass as booleans.
7127 MC_(create_mempool) ( pool, rzB, is_zeroed,
7128 (flags & VALGRIND_MEMPOOL_AUTO_FREE),
7129 (flags & VALGRIND_MEMPOOL_METAPOOL) );
njn1d0825f2006-03-27 11:37:07 +00007130 return True;
7131 }
7132
7133 case VG_USERREQ__DESTROY_MEMPOOL: {
7134 Addr pool = (Addr)arg[1];
7135
7136 MC_(destroy_mempool) ( pool );
7137 return True;
7138 }
7139
7140 case VG_USERREQ__MEMPOOL_ALLOC: {
7141 Addr pool = (Addr)arg[1];
7142 Addr addr = (Addr)arg[2];
7143 UInt size = arg[3];
7144
7145 MC_(mempool_alloc) ( tid, pool, addr, size );
7146 return True;
7147 }
7148
7149 case VG_USERREQ__MEMPOOL_FREE: {
7150 Addr pool = (Addr)arg[1];
7151 Addr addr = (Addr)arg[2];
7152
7153 MC_(mempool_free) ( pool, addr );
7154 return True;
7155 }
7156
sewardj2c1c9df2006-07-28 00:06:37 +00007157 case VG_USERREQ__MEMPOOL_TRIM: {
7158 Addr pool = (Addr)arg[1];
7159 Addr addr = (Addr)arg[2];
7160 UInt size = arg[3];
7161
7162 MC_(mempool_trim) ( pool, addr, size );
7163 return True;
7164 }
7165
sewardjc740d762006-10-05 17:59:23 +00007166 case VG_USERREQ__MOVE_MEMPOOL: {
7167 Addr poolA = (Addr)arg[1];
7168 Addr poolB = (Addr)arg[2];
7169
7170 MC_(move_mempool) ( poolA, poolB );
7171 return True;
7172 }
7173
7174 case VG_USERREQ__MEMPOOL_CHANGE: {
7175 Addr pool = (Addr)arg[1];
7176 Addr addrA = (Addr)arg[2];
7177 Addr addrB = (Addr)arg[3];
7178 UInt size = arg[4];
7179
7180 MC_(mempool_change) ( pool, addrA, addrB, size );
7181 return True;
7182 }
7183
7184 case VG_USERREQ__MEMPOOL_EXISTS: {
7185 Addr pool = (Addr)arg[1];
7186
7187 *ret = (UWord) MC_(mempool_exists) ( pool );
7188 return True;
7189 }
7190
sewardj3b290482011-05-06 21:02:55 +00007191 case VG_USERREQ__GDB_MONITOR_COMMAND: {
florian19f91bb2012-11-10 22:29:54 +00007192 Bool handled = handle_gdb_monitor_command (tid, (HChar*)arg[1]);
sewardj3b290482011-05-06 21:02:55 +00007193 if (handled)
7194 *ret = 1;
7195 else
7196 *ret = 0;
7197 return handled;
7198 }
sewardjc740d762006-10-05 17:59:23 +00007199
sewardjc5fc8662014-03-20 23:00:09 +00007200 case VG_USERREQ__DISABLE_ADDR_ERROR_REPORTING_IN_RANGE:
7201 case VG_USERREQ__ENABLE_ADDR_ERROR_REPORTING_IN_RANGE: {
7202 Bool addRange
7203 = arg[0] == VG_USERREQ__DISABLE_ADDR_ERROR_REPORTING_IN_RANGE;
7204 Bool ok
7205 = modify_ignore_ranges(addRange, arg[1], arg[2]);
7206 *ret = ok ? 1 : 0;
7207 return True;
7208 }
7209
nethercote8b76fe52004-11-08 19:20:09 +00007210 default:
sewardj6b523cd2009-07-15 14:49:40 +00007211 VG_(message)(
7212 Vg_UserMsg,
7213 "Warning: unknown memcheck client request code %llx\n",
7214 (ULong)arg[0]
7215 );
njn1d0825f2006-03-27 11:37:07 +00007216 return False;
nethercote8b76fe52004-11-08 19:20:09 +00007217 }
7218 return True;
7219}
njn25e49d8e72002-09-23 09:36:25 +00007220
njnf76d27a2009-05-28 01:53:07 +00007221
njn25e49d8e72002-09-23 09:36:25 +00007222/*------------------------------------------------------------*/
njn1d0825f2006-03-27 11:37:07 +00007223/*--- Crude profiling machinery. ---*/
7224/*------------------------------------------------------------*/
7225
7226// We track a number of interesting events (using PROF_EVENT)
7227// if MC_PROFILE_MEMORY is defined.
7228
7229#ifdef MC_PROFILE_MEMORY
7230
florianed59b702015-08-09 20:55:39 +00007231ULong MC_(event_ctr)[MCPE_LAST];
florian60042192015-08-04 15:58:41 +00007232
7233/* Event counter names. Use the name of the function that increases the
7234 event counter. Drop any MC_() and mc_ prefices. */
7235static const HChar* MC_(event_ctr_name)[MCPE_LAST] = {
7236 [MCPE_LOADVN_SLOW] = "LOADVn_slow",
7237 [MCPE_LOADVN_SLOW_LOOP] = "LOADVn_slow_loop",
7238 [MCPE_STOREVN_SLOW] = "STOREVn_slow",
7239 [MCPE_STOREVN_SLOW_LOOP] = "STOREVn_slow(loop)",
7240 [MCPE_MAKE_ALIGNED_WORD32_UNDEFINED] = "make_aligned_word32_undefined",
7241 [MCPE_MAKE_ALIGNED_WORD32_UNDEFINED_SLOW] =
7242 "make_aligned_word32_undefined_slow",
7243 [MCPE_MAKE_ALIGNED_WORD64_UNDEFINED] = "make_aligned_word64_undefined",
7244 [MCPE_MAKE_ALIGNED_WORD64_UNDEFINED_SLOW] =
7245 "make_aligned_word64_undefined_slow",
7246 [MCPE_MAKE_ALIGNED_WORD32_NOACCESS] = "make_aligned_word32_noaccess",
7247 [MCPE_MAKE_ALIGNED_WORD32_NOACCESS_SLOW] =
7248 "make_aligned_word32_noaccess_slow",
7249 [MCPE_MAKE_ALIGNED_WORD64_NOACCESS] = "make_aligned_word64_noaccess",
7250 [MCPE_MAKE_ALIGNED_WORD64_NOACCESS_SLOW] =
7251 "make_aligned_word64_noaccess_slow",
7252 [MCPE_MAKE_MEM_NOACCESS] = "make_mem_noaccess",
7253 [MCPE_MAKE_MEM_UNDEFINED] = "make_mem_undefined",
7254 [MCPE_MAKE_MEM_UNDEFINED_W_OTAG] = "make_mem_undefined_w_otag",
7255 [MCPE_MAKE_MEM_DEFINED] = "make_mem_defined",
7256 [MCPE_CHEAP_SANITY_CHECK] = "cheap_sanity_check",
7257 [MCPE_EXPENSIVE_SANITY_CHECK] = "expensive_sanity_check",
7258 [MCPE_COPY_ADDRESS_RANGE_STATE] = "copy_address_range_state",
7259 [MCPE_COPY_ADDRESS_RANGE_STATE_LOOP1] = "copy_address_range_state(loop1)",
7260 [MCPE_COPY_ADDRESS_RANGE_STATE_LOOP2] = "copy_address_range_state(loop2)",
7261 [MCPE_CHECK_MEM_IS_NOACCESS] = "check_mem_is_noaccess",
7262 [MCPE_CHECK_MEM_IS_NOACCESS_LOOP] = "check_mem_is_noaccess(loop)",
7263 [MCPE_IS_MEM_ADDRESSABLE] = "is_mem_addressable",
7264 [MCPE_IS_MEM_ADDRESSABLE_LOOP] = "is_mem_addressable(loop)",
7265 [MCPE_IS_MEM_DEFINED] = "is_mem_defined",
7266 [MCPE_IS_MEM_DEFINED_LOOP] = "is_mem_defined(loop)",
7267 [MCPE_IS_MEM_DEFINED_COMPREHENSIVE] = "is_mem_defined_comprehensive",
7268 [MCPE_IS_MEM_DEFINED_COMPREHENSIVE_LOOP] =
7269 "is_mem_defined_comprehensive(loop)",
7270 [MCPE_IS_DEFINED_ASCIIZ] = "is_defined_asciiz",
7271 [MCPE_IS_DEFINED_ASCIIZ_LOOP] = "is_defined_asciiz(loop)",
7272 [MCPE_FIND_CHUNK_FOR_OLD] = "find_chunk_for_OLD",
7273 [MCPE_FIND_CHUNK_FOR_OLD_LOOP] = "find_chunk_for_OLD(loop)",
7274 [MCPE_SET_ADDRESS_RANGE_PERMS] = "set_address_range_perms",
7275 [MCPE_SET_ADDRESS_RANGE_PERMS_SINGLE_SECMAP] =
7276 "set_address_range_perms(single-secmap)",
7277 [MCPE_SET_ADDRESS_RANGE_PERMS_STARTOF_SECMAP] =
7278 "set_address_range_perms(startof-secmap)",
7279 [MCPE_SET_ADDRESS_RANGE_PERMS_MULTIPLE_SECMAPS] =
7280 "set_address_range_perms(multiple-secmaps)",
7281 [MCPE_SET_ADDRESS_RANGE_PERMS_DIST_SM1] =
7282 "set_address_range_perms(dist-sm1)",
7283 [MCPE_SET_ADDRESS_RANGE_PERMS_DIST_SM2] =
7284 "set_address_range_perms(dist-sm2)",
7285 [MCPE_SET_ADDRESS_RANGE_PERMS_DIST_SM1_QUICK] =
7286 "set_address_range_perms(dist-sm1-quick)",
7287 [MCPE_SET_ADDRESS_RANGE_PERMS_DIST_SM2_QUICK] =
7288 "set_address_range_perms(dist-sm2-quick)",
7289 [MCPE_SET_ADDRESS_RANGE_PERMS_LOOP1A] = "set_address_range_perms(loop1a)",
7290 [MCPE_SET_ADDRESS_RANGE_PERMS_LOOP1B] = "set_address_range_perms(loop1b)",
7291 [MCPE_SET_ADDRESS_RANGE_PERMS_LOOP1C] = "set_address_range_perms(loop1c)",
7292 [MCPE_SET_ADDRESS_RANGE_PERMS_LOOP8A] = "set_address_range_perms(loop8a)",
7293 [MCPE_SET_ADDRESS_RANGE_PERMS_LOOP8B] = "set_address_range_perms(loop8b)",
7294 [MCPE_SET_ADDRESS_RANGE_PERMS_LOOP64K] = "set_address_range_perms(loop64K)",
7295 [MCPE_SET_ADDRESS_RANGE_PERMS_LOOP64K_FREE_DIST_SM] =
7296 "set_address_range_perms(loop64K-free-dist-sm)",
7297 [MCPE_LOADV_128_OR_256_SLOW_LOOP] = "LOADV_128_or_256_slow(loop)",
7298 [MCPE_LOADV_128_OR_256] = "LOADV_128_or_256",
7299 [MCPE_LOADV_128_OR_256_SLOW1] = "LOADV_128_or_256-slow1",
7300 [MCPE_LOADV_128_OR_256_SLOW2] = "LOADV_128_or_256-slow2",
7301 [MCPE_LOADV64] = "LOADV64",
7302 [MCPE_LOADV64_SLOW1] = "LOADV64-slow1",
7303 [MCPE_LOADV64_SLOW2] = "LOADV64-slow2",
7304 [MCPE_STOREV64] = "STOREV64",
7305 [MCPE_STOREV64_SLOW1] = "STOREV64-slow1",
7306 [MCPE_STOREV64_SLOW2] = "STOREV64-slow2",
7307 [MCPE_STOREV64_SLOW3] = "STOREV64-slow3",
7308 [MCPE_STOREV64_SLOW4] = "STOREV64-slow4",
7309 [MCPE_LOADV32] = "LOADV32",
7310 [MCPE_LOADV32_SLOW1] = "LOADV32-slow1",
7311 [MCPE_LOADV32_SLOW2] = "LOADV32-slow2",
7312 [MCPE_STOREV32] = "STOREV32",
7313 [MCPE_STOREV32_SLOW1] = "STOREV32-slow1",
7314 [MCPE_STOREV32_SLOW2] = "STOREV32-slow2",
7315 [MCPE_STOREV32_SLOW3] = "STOREV32-slow3",
7316 [MCPE_STOREV32_SLOW4] = "STOREV32-slow4",
7317 [MCPE_LOADV16] = "LOADV16",
7318 [MCPE_LOADV16_SLOW1] = "LOADV16-slow1",
7319 [MCPE_LOADV16_SLOW2] = "LOADV16-slow2",
7320 [MCPE_STOREV16] = "STOREV16",
7321 [MCPE_STOREV16_SLOW1] = "STOREV16-slow1",
7322 [MCPE_STOREV16_SLOW2] = "STOREV16-slow2",
7323 [MCPE_STOREV16_SLOW3] = "STOREV16-slow3",
7324 [MCPE_STOREV16_SLOW4] = "STOREV16-slow4",
7325 [MCPE_LOADV8] = "LOADV8",
7326 [MCPE_LOADV8_SLOW1] = "LOADV8-slow1",
7327 [MCPE_LOADV8_SLOW2] = "LOADV8-slow2",
7328 [MCPE_STOREV8] = "STOREV8",
7329 [MCPE_STOREV8_SLOW1] = "STOREV8-slow1",
7330 [MCPE_STOREV8_SLOW2] = "STOREV8-slow2",
7331 [MCPE_STOREV8_SLOW3] = "STOREV8-slow3",
7332 [MCPE_STOREV8_SLOW4] = "STOREV8-slow4",
7333 [MCPE_NEW_MEM_STACK_4] = "new_mem_stack_4",
7334 [MCPE_NEW_MEM_STACK_8] = "new_mem_stack_8",
7335 [MCPE_NEW_MEM_STACK_12] = "new_mem_stack_12",
7336 [MCPE_NEW_MEM_STACK_16] = "new_mem_stack_16",
7337 [MCPE_NEW_MEM_STACK_32] = "new_mem_stack_32",
7338 [MCPE_NEW_MEM_STACK_112] = "new_mem_stack_112",
7339 [MCPE_NEW_MEM_STACK_128] = "new_mem_stack_128",
7340 [MCPE_NEW_MEM_STACK_144] = "new_mem_stack_144",
7341 [MCPE_NEW_MEM_STACK_160] = "new_mem_stack_160",
7342 [MCPE_DIE_MEM_STACK_4] = "die_mem_stack_4",
7343 [MCPE_DIE_MEM_STACK_8] = "die_mem_stack_8",
7344 [MCPE_DIE_MEM_STACK_12] = "die_mem_stack_12",
7345 [MCPE_DIE_MEM_STACK_16] = "die_mem_stack_16",
7346 [MCPE_DIE_MEM_STACK_32] = "die_mem_stack_32",
7347 [MCPE_DIE_MEM_STACK_112] = "die_mem_stack_112",
7348 [MCPE_DIE_MEM_STACK_128] = "die_mem_stack_128",
7349 [MCPE_DIE_MEM_STACK_144] = "die_mem_stack_144",
7350 [MCPE_DIE_MEM_STACK_160] = "die_mem_stack_160",
7351 [MCPE_NEW_MEM_STACK] = "new_mem_stack",
7352 [MCPE_DIE_MEM_STACK] = "die_mem_stack",
Elliott Hughesa0664b92017-04-18 17:46:52 -07007353 [MCPE_MAKE_STACK_UNINIT_W_O] = "MAKE_STACK_UNINIT_w_o",
7354 [MCPE_MAKE_STACK_UNINIT_NO_O] = "MAKE_STACK_UNINIT_no_o",
7355 [MCPE_MAKE_STACK_UNINIT_128_NO_O] = "MAKE_STACK_UNINIT_128_no_o",
7356 [MCPE_MAKE_STACK_UNINIT_128_NO_O_ALIGNED_16]
7357 = "MAKE_STACK_UNINIT_128_no_o_aligned_16",
7358 [MCPE_MAKE_STACK_UNINIT_128_NO_O_ALIGNED_8]
7359 = "MAKE_STACK_UNINIT_128_no_o_aligned_8",
7360 [MCPE_MAKE_STACK_UNINIT_128_NO_O_SLOWCASE]
7361 = "MAKE_STACK_UNINIT_128_no_o_slowcase",
florian60042192015-08-04 15:58:41 +00007362};
njn1d0825f2006-03-27 11:37:07 +00007363
7364static void init_prof_mem ( void )
7365{
florian60042192015-08-04 15:58:41 +00007366 Int i, name_count = 0;
7367
7368 for (i = 0; i < MCPE_LAST; i++) {
njn1d0825f2006-03-27 11:37:07 +00007369 MC_(event_ctr)[i] = 0;
florian60042192015-08-04 15:58:41 +00007370 if (MC_(event_ctr_name)[i] != NULL)
7371 ++name_count;
njn1d0825f2006-03-27 11:37:07 +00007372 }
florian60042192015-08-04 15:58:41 +00007373
7374 /* Make sure every profiling event has a name */
7375 tl_assert(name_count == MCPE_LAST);
njn1d0825f2006-03-27 11:37:07 +00007376}
7377
7378static void done_prof_mem ( void )
7379{
florian60042192015-08-04 15:58:41 +00007380 Int i, n;
njn1d0825f2006-03-27 11:37:07 +00007381 Bool spaced = False;
florian60042192015-08-04 15:58:41 +00007382 for (i = n = 0; i < MCPE_LAST; i++) {
7383 if (!spaced && (n % 10) == 0) {
njn1d0825f2006-03-27 11:37:07 +00007384 VG_(printf)("\n");
7385 spaced = True;
7386 }
7387 if (MC_(event_ctr)[i] > 0) {
7388 spaced = False;
florian60042192015-08-04 15:58:41 +00007389 ++n;
florianed59b702015-08-09 20:55:39 +00007390 VG_(printf)( "prof mem event %3d: %11llu %s\n",
njn1d0825f2006-03-27 11:37:07 +00007391 i, MC_(event_ctr)[i],
florian60042192015-08-04 15:58:41 +00007392 MC_(event_ctr_name)[i]);
njn1d0825f2006-03-27 11:37:07 +00007393 }
7394 }
7395}
7396
7397#else
7398
7399static void init_prof_mem ( void ) { }
7400static void done_prof_mem ( void ) { }
7401
7402#endif
7403
sewardj7cf4e6b2008-05-01 20:24:26 +00007404
7405/*------------------------------------------------------------*/
7406/*--- Origin tracking stuff ---*/
7407/*------------------------------------------------------------*/
7408
7409/*--------------------------------------------*/
7410/*--- Origin tracking: load handlers ---*/
7411/*--------------------------------------------*/
7412
7413static INLINE UInt merge_origins ( UInt or1, UInt or2 ) {
7414 return or1 > or2 ? or1 : or2;
7415}
7416
7417UWord VG_REGPARM(1) MC_(helperc_b_load1)( Addr a ) {
7418 OCacheLine* line;
7419 UChar descr;
7420 UWord lineoff = oc_line_offset(a);
7421 UWord byteoff = a & 3; /* 0, 1, 2 or 3 */
7422
7423 if (OC_ENABLE_ASSERTIONS) {
7424 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
7425 }
7426
7427 line = find_OCacheLine( a );
7428
7429 descr = line->descr[lineoff];
7430 if (OC_ENABLE_ASSERTIONS) {
7431 tl_assert(descr < 0x10);
7432 }
7433
7434 if (LIKELY(0 == (descr & (1 << byteoff)))) {
7435 return 0;
7436 } else {
7437 return line->w32[lineoff];
7438 }
7439}
7440
7441UWord VG_REGPARM(1) MC_(helperc_b_load2)( Addr a ) {
7442 OCacheLine* line;
7443 UChar descr;
7444 UWord lineoff, byteoff;
7445
7446 if (UNLIKELY(a & 1)) {
7447 /* Handle misaligned case, slowly. */
7448 UInt oLo = (UInt)MC_(helperc_b_load1)( a + 0 );
7449 UInt oHi = (UInt)MC_(helperc_b_load1)( a + 1 );
7450 return merge_origins(oLo, oHi);
7451 }
7452
7453 lineoff = oc_line_offset(a);
7454 byteoff = a & 3; /* 0 or 2 */
7455
7456 if (OC_ENABLE_ASSERTIONS) {
7457 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
7458 }
7459 line = find_OCacheLine( a );
7460
7461 descr = line->descr[lineoff];
7462 if (OC_ENABLE_ASSERTIONS) {
7463 tl_assert(descr < 0x10);
7464 }
7465
7466 if (LIKELY(0 == (descr & (3 << byteoff)))) {
7467 return 0;
7468 } else {
7469 return line->w32[lineoff];
7470 }
7471}
7472
7473UWord VG_REGPARM(1) MC_(helperc_b_load4)( Addr a ) {
7474 OCacheLine* line;
7475 UChar descr;
7476 UWord lineoff;
7477
7478 if (UNLIKELY(a & 3)) {
7479 /* Handle misaligned case, slowly. */
7480 UInt oLo = (UInt)MC_(helperc_b_load2)( a + 0 );
7481 UInt oHi = (UInt)MC_(helperc_b_load2)( a + 2 );
7482 return merge_origins(oLo, oHi);
7483 }
7484
7485 lineoff = oc_line_offset(a);
7486 if (OC_ENABLE_ASSERTIONS) {
7487 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
7488 }
7489
7490 line = find_OCacheLine( a );
7491
7492 descr = line->descr[lineoff];
7493 if (OC_ENABLE_ASSERTIONS) {
7494 tl_assert(descr < 0x10);
7495 }
7496
7497 if (LIKELY(0 == descr)) {
7498 return 0;
7499 } else {
7500 return line->w32[lineoff];
7501 }
7502}
7503
7504UWord VG_REGPARM(1) MC_(helperc_b_load8)( Addr a ) {
7505 OCacheLine* line;
7506 UChar descrLo, descrHi, descr;
7507 UWord lineoff;
7508
7509 if (UNLIKELY(a & 7)) {
7510 /* Handle misaligned case, slowly. */
7511 UInt oLo = (UInt)MC_(helperc_b_load4)( a + 0 );
7512 UInt oHi = (UInt)MC_(helperc_b_load4)( a + 4 );
7513 return merge_origins(oLo, oHi);
7514 }
7515
7516 lineoff = oc_line_offset(a);
7517 if (OC_ENABLE_ASSERTIONS) {
7518 tl_assert(lineoff == (lineoff & 6)); /*0,2,4,6*//*since 8-aligned*/
7519 }
7520
7521 line = find_OCacheLine( a );
7522
7523 descrLo = line->descr[lineoff + 0];
7524 descrHi = line->descr[lineoff + 1];
7525 descr = descrLo | descrHi;
7526 if (OC_ENABLE_ASSERTIONS) {
7527 tl_assert(descr < 0x10);
7528 }
7529
7530 if (LIKELY(0 == descr)) {
7531 return 0; /* both 32-bit chunks are defined */
7532 } else {
7533 UInt oLo = descrLo == 0 ? 0 : line->w32[lineoff + 0];
7534 UInt oHi = descrHi == 0 ? 0 : line->w32[lineoff + 1];
7535 return merge_origins(oLo, oHi);
7536 }
7537}
7538
7539UWord VG_REGPARM(1) MC_(helperc_b_load16)( Addr a ) {
7540 UInt oLo = (UInt)MC_(helperc_b_load8)( a + 0 );
7541 UInt oHi = (UInt)MC_(helperc_b_load8)( a + 8 );
7542 UInt oBoth = merge_origins(oLo, oHi);
7543 return (UWord)oBoth;
7544}
7545
sewardj45fa9f42012-05-21 10:18:10 +00007546UWord VG_REGPARM(1) MC_(helperc_b_load32)( Addr a ) {
7547 UInt oQ0 = (UInt)MC_(helperc_b_load8)( a + 0 );
7548 UInt oQ1 = (UInt)MC_(helperc_b_load8)( a + 8 );
7549 UInt oQ2 = (UInt)MC_(helperc_b_load8)( a + 16 );
7550 UInt oQ3 = (UInt)MC_(helperc_b_load8)( a + 24 );
7551 UInt oAll = merge_origins(merge_origins(oQ0, oQ1),
7552 merge_origins(oQ2, oQ3));
7553 return (UWord)oAll;
7554}
7555
sewardj7cf4e6b2008-05-01 20:24:26 +00007556
7557/*--------------------------------------------*/
7558/*--- Origin tracking: store handlers ---*/
7559/*--------------------------------------------*/
7560
7561void VG_REGPARM(2) MC_(helperc_b_store1)( Addr a, UWord d32 ) {
7562 OCacheLine* line;
7563 UWord lineoff = oc_line_offset(a);
7564 UWord byteoff = a & 3; /* 0, 1, 2 or 3 */
7565
7566 if (OC_ENABLE_ASSERTIONS) {
7567 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
7568 }
7569
7570 line = find_OCacheLine( a );
7571
7572 if (d32 == 0) {
7573 line->descr[lineoff] &= ~(1 << byteoff);
7574 } else {
7575 line->descr[lineoff] |= (1 << byteoff);
7576 line->w32[lineoff] = d32;
7577 }
7578}
7579
7580void VG_REGPARM(2) MC_(helperc_b_store2)( Addr a, UWord d32 ) {
7581 OCacheLine* line;
7582 UWord lineoff, byteoff;
7583
7584 if (UNLIKELY(a & 1)) {
7585 /* Handle misaligned case, slowly. */
7586 MC_(helperc_b_store1)( a + 0, d32 );
7587 MC_(helperc_b_store1)( a + 1, d32 );
7588 return;
7589 }
7590
7591 lineoff = oc_line_offset(a);
7592 byteoff = a & 3; /* 0 or 2 */
7593
7594 if (OC_ENABLE_ASSERTIONS) {
7595 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
7596 }
7597
7598 line = find_OCacheLine( a );
7599
7600 if (d32 == 0) {
7601 line->descr[lineoff] &= ~(3 << byteoff);
7602 } else {
7603 line->descr[lineoff] |= (3 << byteoff);
7604 line->w32[lineoff] = d32;
7605 }
7606}
7607
7608void VG_REGPARM(2) MC_(helperc_b_store4)( Addr a, UWord d32 ) {
7609 OCacheLine* line;
7610 UWord lineoff;
7611
7612 if (UNLIKELY(a & 3)) {
7613 /* Handle misaligned case, slowly. */
7614 MC_(helperc_b_store2)( a + 0, d32 );
7615 MC_(helperc_b_store2)( a + 2, d32 );
7616 return;
7617 }
7618
7619 lineoff = oc_line_offset(a);
7620 if (OC_ENABLE_ASSERTIONS) {
7621 tl_assert(lineoff >= 0 && lineoff < OC_W32S_PER_LINE);
7622 }
7623
7624 line = find_OCacheLine( a );
7625
7626 if (d32 == 0) {
7627 line->descr[lineoff] = 0;
7628 } else {
7629 line->descr[lineoff] = 0xF;
7630 line->w32[lineoff] = d32;
7631 }
7632}
7633
7634void VG_REGPARM(2) MC_(helperc_b_store8)( Addr a, UWord d32 ) {
7635 OCacheLine* line;
7636 UWord lineoff;
7637
7638 if (UNLIKELY(a & 7)) {
7639 /* Handle misaligned case, slowly. */
7640 MC_(helperc_b_store4)( a + 0, d32 );
7641 MC_(helperc_b_store4)( a + 4, d32 );
7642 return;
7643 }
7644
7645 lineoff = oc_line_offset(a);
7646 if (OC_ENABLE_ASSERTIONS) {
7647 tl_assert(lineoff == (lineoff & 6)); /*0,2,4,6*//*since 8-aligned*/
7648 }
7649
7650 line = find_OCacheLine( a );
7651
7652 if (d32 == 0) {
7653 line->descr[lineoff + 0] = 0;
7654 line->descr[lineoff + 1] = 0;
7655 } else {
7656 line->descr[lineoff + 0] = 0xF;
7657 line->descr[lineoff + 1] = 0xF;
7658 line->w32[lineoff + 0] = d32;
7659 line->w32[lineoff + 1] = d32;
7660 }
7661}
7662
7663void VG_REGPARM(2) MC_(helperc_b_store16)( Addr a, UWord d32 ) {
7664 MC_(helperc_b_store8)( a + 0, d32 );
7665 MC_(helperc_b_store8)( a + 8, d32 );
7666}
7667
sewardj45fa9f42012-05-21 10:18:10 +00007668void VG_REGPARM(2) MC_(helperc_b_store32)( Addr a, UWord d32 ) {
7669 MC_(helperc_b_store8)( a + 0, d32 );
7670 MC_(helperc_b_store8)( a + 8, d32 );
7671 MC_(helperc_b_store8)( a + 16, d32 );
7672 MC_(helperc_b_store8)( a + 24, d32 );
7673}
7674
sewardj7cf4e6b2008-05-01 20:24:26 +00007675
7676/*--------------------------------------------*/
7677/*--- Origin tracking: sarp handlers ---*/
7678/*--------------------------------------------*/
7679
7680__attribute__((noinline))
7681static void ocache_sarp_Set_Origins ( Addr a, UWord len, UInt otag ) {
7682 if ((a & 1) && len >= 1) {
7683 MC_(helperc_b_store1)( a, otag );
7684 a++;
7685 len--;
7686 }
7687 if ((a & 2) && len >= 2) {
7688 MC_(helperc_b_store2)( a, otag );
7689 a += 2;
7690 len -= 2;
7691 }
7692 if (len >= 4)
7693 tl_assert(0 == (a & 3));
7694 while (len >= 4) {
7695 MC_(helperc_b_store4)( a, otag );
7696 a += 4;
7697 len -= 4;
7698 }
7699 if (len >= 2) {
7700 MC_(helperc_b_store2)( a, otag );
7701 a += 2;
7702 len -= 2;
7703 }
7704 if (len >= 1) {
7705 MC_(helperc_b_store1)( a, otag );
njn4c245e52009-03-15 23:25:38 +00007706 //a++;
sewardj7cf4e6b2008-05-01 20:24:26 +00007707 len--;
7708 }
7709 tl_assert(len == 0);
7710}
7711
7712__attribute__((noinline))
7713static void ocache_sarp_Clear_Origins ( Addr a, UWord len ) {
7714 if ((a & 1) && len >= 1) {
7715 MC_(helperc_b_store1)( a, 0 );
7716 a++;
7717 len--;
7718 }
7719 if ((a & 2) && len >= 2) {
7720 MC_(helperc_b_store2)( a, 0 );
7721 a += 2;
7722 len -= 2;
7723 }
7724 if (len >= 4)
7725 tl_assert(0 == (a & 3));
7726 while (len >= 4) {
7727 MC_(helperc_b_store4)( a, 0 );
7728 a += 4;
7729 len -= 4;
7730 }
7731 if (len >= 2) {
7732 MC_(helperc_b_store2)( a, 0 );
7733 a += 2;
7734 len -= 2;
7735 }
7736 if (len >= 1) {
7737 MC_(helperc_b_store1)( a, 0 );
njn4c245e52009-03-15 23:25:38 +00007738 //a++;
sewardj7cf4e6b2008-05-01 20:24:26 +00007739 len--;
7740 }
7741 tl_assert(len == 0);
7742}
7743
7744
njn1d0825f2006-03-27 11:37:07 +00007745/*------------------------------------------------------------*/
njn51d827b2005-05-09 01:02:08 +00007746/*--- Setup and finalisation ---*/
njn25e49d8e72002-09-23 09:36:25 +00007747/*------------------------------------------------------------*/
7748
njn51d827b2005-05-09 01:02:08 +00007749static void mc_post_clo_init ( void )
njn5c004e42002-11-18 11:04:50 +00007750{
sewardj71bc3cb2005-05-19 00:25:45 +00007751 /* If we've been asked to emit XML, mash around various other
7752 options so as to constrain the output somewhat. */
7753 if (VG_(clo_xml)) {
7754 /* Extract as much info as possible from the leak checker. */
njn1d0825f2006-03-27 11:37:07 +00007755 MC_(clo_leak_check) = LC_Full;
sewardj71bc3cb2005-05-19 00:25:45 +00007756 }
sewardj7cf4e6b2008-05-01 20:24:26 +00007757
Elliott Hughesa0664b92017-04-18 17:46:52 -07007758 if (MC_(clo_freelist_big_blocks) >= MC_(clo_freelist_vol)
7759 && VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
sewardj403d8aa2011-10-22 19:48:57 +00007760 VG_(message)(Vg_UserMsg,
7761 "Warning: --freelist-big-blocks value %lld has no effect\n"
7762 "as it is >= to --freelist-vol value %lld\n",
7763 MC_(clo_freelist_big_blocks),
7764 MC_(clo_freelist_vol));
Elliott Hughesa0664b92017-04-18 17:46:52 -07007765 }
7766
7767 if (MC_(clo_workaround_gcc296_bugs)
7768 && VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
7769 VG_(umsg)(
7770 "Warning: --workaround-gcc296-bugs=yes is deprecated.\n"
7771 "Warning: Instead use: --ignore-range-below-sp=1024-1\n"
7772 "\n"
7773 );
7774 }
sewardj403d8aa2011-10-22 19:48:57 +00007775
sewardj7cf4e6b2008-05-01 20:24:26 +00007776 tl_assert( MC_(clo_mc_level) >= 1 && MC_(clo_mc_level) <= 3 );
7777
7778 if (MC_(clo_mc_level) == 3) {
7779 /* We're doing origin tracking. */
7780# ifdef PERF_FAST_STACK
7781 VG_(track_new_mem_stack_4_w_ECU) ( mc_new_mem_stack_4_w_ECU );
7782 VG_(track_new_mem_stack_8_w_ECU) ( mc_new_mem_stack_8_w_ECU );
7783 VG_(track_new_mem_stack_12_w_ECU) ( mc_new_mem_stack_12_w_ECU );
7784 VG_(track_new_mem_stack_16_w_ECU) ( mc_new_mem_stack_16_w_ECU );
7785 VG_(track_new_mem_stack_32_w_ECU) ( mc_new_mem_stack_32_w_ECU );
7786 VG_(track_new_mem_stack_112_w_ECU) ( mc_new_mem_stack_112_w_ECU );
7787 VG_(track_new_mem_stack_128_w_ECU) ( mc_new_mem_stack_128_w_ECU );
7788 VG_(track_new_mem_stack_144_w_ECU) ( mc_new_mem_stack_144_w_ECU );
7789 VG_(track_new_mem_stack_160_w_ECU) ( mc_new_mem_stack_160_w_ECU );
7790# endif
7791 VG_(track_new_mem_stack_w_ECU) ( mc_new_mem_stack_w_ECU );
philippe5db022b2013-01-13 15:01:21 +00007792 VG_(track_new_mem_stack_signal) ( mc_new_mem_w_tid_make_ECU );
sewardj7cf4e6b2008-05-01 20:24:26 +00007793 } else {
7794 /* Not doing origin tracking */
7795# ifdef PERF_FAST_STACK
7796 VG_(track_new_mem_stack_4) ( mc_new_mem_stack_4 );
7797 VG_(track_new_mem_stack_8) ( mc_new_mem_stack_8 );
7798 VG_(track_new_mem_stack_12) ( mc_new_mem_stack_12 );
7799 VG_(track_new_mem_stack_16) ( mc_new_mem_stack_16 );
7800 VG_(track_new_mem_stack_32) ( mc_new_mem_stack_32 );
7801 VG_(track_new_mem_stack_112) ( mc_new_mem_stack_112 );
7802 VG_(track_new_mem_stack_128) ( mc_new_mem_stack_128 );
7803 VG_(track_new_mem_stack_144) ( mc_new_mem_stack_144 );
7804 VG_(track_new_mem_stack_160) ( mc_new_mem_stack_160 );
7805# endif
7806 VG_(track_new_mem_stack) ( mc_new_mem_stack );
philippe5db022b2013-01-13 15:01:21 +00007807 VG_(track_new_mem_stack_signal) ( mc_new_mem_w_tid_no_ECU );
sewardj7cf4e6b2008-05-01 20:24:26 +00007808 }
sewardj9d624d12008-05-02 13:35:29 +00007809
philippe5db022b2013-01-13 15:01:21 +00007810 // We assume that brk()/sbrk() does not initialise new memory. Is this
7811 // accurate? John Reiser says:
7812 //
7813 // 0) sbrk() can *decrease* process address space. No zero fill is done
7814 // for a decrease, not even the fragment on the high end of the last page
7815 // that is beyond the new highest address. For maximum safety and
7816 // portability, then the bytes in the last page that reside above [the
7817 // new] sbrk(0) should be considered to be uninitialized, but in practice
7818 // it is exceedingly likely that they will retain their previous
7819 // contents.
7820 //
7821 // 1) If an increase is large enough to require new whole pages, then
7822 // those new whole pages (like all new pages) are zero-filled by the
7823 // operating system. So if sbrk(0) already is page aligned, then
7824 // sbrk(PAGE_SIZE) *does* zero-fill the new memory.
7825 //
7826 // 2) Any increase that lies within an existing allocated page is not
7827 // changed. So if (x = sbrk(0)) is not page aligned, then
7828 // sbrk(PAGE_SIZE) yields ((PAGE_SIZE -1) & -x) bytes which keep their
7829 // existing contents, and an additional PAGE_SIZE bytes which are zeroed.
7830 // ((PAGE_SIZE -1) & x) of them are "covered" by the sbrk(), and the rest
7831 // of them come along for the ride because the operating system deals
7832 // only in whole pages. Again, for maximum safety and portability, then
7833 // anything that lives above [the new] sbrk(0) should be considered
7834 // uninitialized, but in practice will retain previous contents [zero in
7835 // this case.]"
7836 //
7837 // In short:
7838 //
7839 // A key property of sbrk/brk is that new whole pages that are supplied
7840 // by the operating system *do* get initialized to zero.
7841 //
7842 // As for the portability of all this:
7843 //
7844 // sbrk and brk are not POSIX. However, any system that is a derivative
7845 // of *nix has sbrk and brk because there are too many softwares (such as
7846 // the Bourne shell) which rely on the traditional memory map (.text,
7847 // .data+.bss, stack) and the existence of sbrk/brk.
7848 //
7849 // So we should arguably observe all this. However:
7850 // - The current inaccuracy has caused maybe one complaint in seven years(?)
7851 // - Relying on the zeroed-ness of whole brk'd pages is pretty grotty... I
7852 // doubt most programmers know the above information.
7853 // So I'm not terribly unhappy with marking it as undefined. --njn.
7854 //
7855 // [More: I think most of what John said only applies to sbrk(). It seems
7856 // that brk() always deals in whole pages. And since this event deals
7857 // directly with brk(), not with sbrk(), perhaps it would be reasonable to
7858 // just mark all memory it allocates as defined.]
7859 //
sewardj8eb8bab2015-07-21 14:44:28 +00007860# if !defined(VGO_solaris)
philippe5db022b2013-01-13 15:01:21 +00007861 if (MC_(clo_mc_level) == 3)
7862 VG_(track_new_mem_brk) ( mc_new_mem_w_tid_make_ECU );
7863 else
7864 VG_(track_new_mem_brk) ( mc_new_mem_w_tid_no_ECU );
sewardj8eb8bab2015-07-21 14:44:28 +00007865# else
7866 // On Solaris, brk memory has to be marked as defined, otherwise we get
7867 // many false positives.
7868 VG_(track_new_mem_brk) ( make_mem_defined_w_tid );
7869# endif
philippe5db022b2013-01-13 15:01:21 +00007870
sewardj9d624d12008-05-02 13:35:29 +00007871 /* This origin tracking cache is huge (~100M), so only initialise
7872 if we need it. */
7873 if (MC_(clo_mc_level) >= 3) {
7874 init_OCache();
sewardj77139802008-05-05 09:48:56 +00007875 tl_assert(ocacheL1 != NULL);
sewardj9d624d12008-05-02 13:35:29 +00007876 tl_assert(ocacheL2 != NULL);
7877 } else {
sewardj77139802008-05-05 09:48:56 +00007878 tl_assert(ocacheL1 == NULL);
sewardj9d624d12008-05-02 13:35:29 +00007879 tl_assert(ocacheL2 == NULL);
7880 }
florian971ab8f2012-05-12 18:06:35 +00007881
philippe8617b5b2013-01-12 19:53:08 +00007882 MC_(chunk_poolalloc) = VG_(newPA)
7883 (sizeof(MC_Chunk) + MC_(n_where_pointers)() * sizeof(ExeContext*),
7884 1000,
7885 VG_(malloc),
7886 "mc.cMC.1 (MC_Chunk pools)",
7887 VG_(free));
7888
florian971ab8f2012-05-12 18:06:35 +00007889 /* Do not check definedness of guest state if --undef-value-errors=no */
7890 if (MC_(clo_mc_level) >= 2)
7891 VG_(track_pre_reg_read) ( mc_pre_reg_read );
njn5c004e42002-11-18 11:04:50 +00007892}
7893
florian19f91bb2012-11-10 22:29:54 +00007894static void print_SM_info(const HChar* type, Int n_SMs)
njn1d0825f2006-03-27 11:37:07 +00007895{
7896 VG_(message)(Vg_DebugMsg,
floriande3df032015-08-04 21:26:10 +00007897 " memcheck: SMs: %s = %d (%luk, %luM)\n",
njn1d0825f2006-03-27 11:37:07 +00007898 type,
7899 n_SMs,
barta0b6b2c2008-07-07 06:49:24 +00007900 n_SMs * sizeof(SecMap) / 1024UL,
7901 n_SMs * sizeof(SecMap) / (1024 * 1024UL) );
njn1d0825f2006-03-27 11:37:07 +00007902}
7903
philippe8587b542013-12-15 20:24:43 +00007904static void mc_print_stats (void)
7905{
7906 SizeT max_secVBit_szB, max_SMs_szB, max_shmem_szB;
7907
philippe0c2923f2014-04-19 09:52:32 +00007908 VG_(message)(Vg_DebugMsg, " memcheck: freelist: vol %lld length %lld\n",
7909 VG_(free_queue_volume), VG_(free_queue_length));
philippe8587b542013-12-15 20:24:43 +00007910 VG_(message)(Vg_DebugMsg,
7911 " memcheck: sanity checks: %d cheap, %d expensive\n",
7912 n_sanity_cheap, n_sanity_expensive );
7913 VG_(message)(Vg_DebugMsg,
floriande3df032015-08-04 21:26:10 +00007914 " memcheck: auxmaps: %llu auxmap entries (%lluk, %lluM) in use\n",
philippe8587b542013-12-15 20:24:43 +00007915 n_auxmap_L2_nodes,
7916 n_auxmap_L2_nodes * 64,
7917 n_auxmap_L2_nodes / 16 );
7918 VG_(message)(Vg_DebugMsg,
floriande3df032015-08-04 21:26:10 +00007919 " memcheck: auxmaps_L1: %llu searches, %llu cmps, ratio %llu:10\n",
philippe8587b542013-12-15 20:24:43 +00007920 n_auxmap_L1_searches, n_auxmap_L1_cmps,
7921 (10ULL * n_auxmap_L1_cmps)
7922 / (n_auxmap_L1_searches ? n_auxmap_L1_searches : 1)
7923 );
7924 VG_(message)(Vg_DebugMsg,
floriande3df032015-08-04 21:26:10 +00007925 " memcheck: auxmaps_L2: %llu searches, %llu nodes\n",
philippe8587b542013-12-15 20:24:43 +00007926 n_auxmap_L2_searches, n_auxmap_L2_nodes
7927 );
7928
7929 print_SM_info("n_issued ", n_issued_SMs);
7930 print_SM_info("n_deissued ", n_deissued_SMs);
7931 print_SM_info("max_noaccess ", max_noaccess_SMs);
7932 print_SM_info("max_undefined", max_undefined_SMs);
7933 print_SM_info("max_defined ", max_defined_SMs);
7934 print_SM_info("max_non_DSM ", max_non_DSM_SMs);
7935
7936 // Three DSMs, plus the non-DSM ones
7937 max_SMs_szB = (3 + max_non_DSM_SMs) * sizeof(SecMap);
7938 // The 3*sizeof(Word) bytes is the AVL node metadata size.
7939 // The VG_ROUNDUP is because the OSet pool allocator will/must align
7940 // the elements on pointer size.
7941 // Note that the pool allocator has some additional small overhead
7942 // which is not counted in the below.
7943 // Hardwiring this logic sucks, but I don't see how else to do it.
7944 max_secVBit_szB = max_secVBit_nodes *
7945 (3*sizeof(Word) + VG_ROUNDUP(sizeof(SecVBitNode), sizeof(void*)));
7946 max_shmem_szB = sizeof(primary_map) + max_SMs_szB + max_secVBit_szB;
7947
7948 VG_(message)(Vg_DebugMsg,
floriande3df032015-08-04 21:26:10 +00007949 " memcheck: max sec V bit nodes: %d (%luk, %luM)\n",
philippe8587b542013-12-15 20:24:43 +00007950 max_secVBit_nodes, max_secVBit_szB / 1024,
7951 max_secVBit_szB / (1024 * 1024));
7952 VG_(message)(Vg_DebugMsg,
7953 " memcheck: set_sec_vbits8 calls: %llu (new: %llu, updates: %llu)\n",
7954 sec_vbits_new_nodes + sec_vbits_updates,
7955 sec_vbits_new_nodes, sec_vbits_updates );
7956 VG_(message)(Vg_DebugMsg,
floriande3df032015-08-04 21:26:10 +00007957 " memcheck: max shadow mem size: %luk, %luM\n",
philippe8587b542013-12-15 20:24:43 +00007958 max_shmem_szB / 1024, max_shmem_szB / (1024 * 1024));
7959
7960 if (MC_(clo_mc_level) >= 3) {
7961 VG_(message)(Vg_DebugMsg,
7962 " ocacheL1: %'12lu refs %'12lu misses (%'lu lossage)\n",
7963 stats_ocacheL1_find,
7964 stats_ocacheL1_misses,
7965 stats_ocacheL1_lossage );
7966 VG_(message)(Vg_DebugMsg,
7967 " ocacheL1: %'12lu at 0 %'12lu at 1\n",
7968 stats_ocacheL1_find - stats_ocacheL1_misses
7969 - stats_ocacheL1_found_at_1
7970 - stats_ocacheL1_found_at_N,
7971 stats_ocacheL1_found_at_1 );
7972 VG_(message)(Vg_DebugMsg,
7973 " ocacheL1: %'12lu at 2+ %'12lu move-fwds\n",
7974 stats_ocacheL1_found_at_N,
7975 stats_ocacheL1_movefwds );
7976 VG_(message)(Vg_DebugMsg,
floriande3df032015-08-04 21:26:10 +00007977 " ocacheL1: %'12lu sizeB %'12d useful\n",
7978 (SizeT)sizeof(OCache),
philippe8587b542013-12-15 20:24:43 +00007979 4 * OC_W32S_PER_LINE * OC_LINES_PER_SET * OC_N_SETS );
7980 VG_(message)(Vg_DebugMsg,
7981 " ocacheL2: %'12lu refs %'12lu misses\n",
7982 stats__ocacheL2_refs,
7983 stats__ocacheL2_misses );
7984 VG_(message)(Vg_DebugMsg,
7985 " ocacheL2: %'9lu max nodes %'9lu curr nodes\n",
7986 stats__ocacheL2_n_nodes_max,
7987 stats__ocacheL2_n_nodes );
7988 VG_(message)(Vg_DebugMsg,
7989 " niacache: %'12lu refs %'12lu misses\n",
7990 stats__nia_cache_queries, stats__nia_cache_misses);
7991 } else {
7992 tl_assert(ocacheL1 == NULL);
7993 tl_assert(ocacheL2 == NULL);
7994 }
7995}
7996
7997
njn51d827b2005-05-09 01:02:08 +00007998static void mc_fini ( Int exitcode )
njn5c004e42002-11-18 11:04:50 +00007999{
njn1d0825f2006-03-27 11:37:07 +00008000 MC_(print_malloc_stats)();
sewardj23eb2fd2005-04-22 16:29:19 +00008001
sewardj2d9e8742009-08-07 15:46:56 +00008002 if (MC_(clo_leak_check) != LC_Off) {
sewardjc8bd1df2011-06-26 12:41:33 +00008003 LeakCheckParams lcp;
8004 lcp.mode = MC_(clo_leak_check);
philippe2193a7c2012-12-08 17:54:16 +00008005 lcp.show_leak_kinds = MC_(clo_show_leak_kinds);
philippeab1fce92013-09-29 13:47:32 +00008006 lcp.heuristics = MC_(clo_leak_check_heuristics);
philippe2193a7c2012-12-08 17:54:16 +00008007 lcp.errors_for_leak_kinds = MC_(clo_error_for_leak_kinds);
sewardjc8bd1df2011-06-26 12:41:33 +00008008 lcp.deltamode = LCD_Any;
philippe84234902012-01-14 13:53:13 +00008009 lcp.max_loss_records_output = 999999999;
sewardjc8bd1df2011-06-26 12:41:33 +00008010 lcp.requested_by_monitor_command = False;
philippe84234902012-01-14 13:53:13 +00008011 MC_(detect_memory_leaks)(1/*bogus ThreadId*/, &lcp);
njnb6267bd2009-08-12 00:14:16 +00008012 } else {
8013 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
8014 VG_(umsg)(
8015 "For a detailed leak analysis, rerun with: --leak-check=full\n"
8016 "\n"
8017 );
8018 }
sewardj2d9e8742009-08-07 15:46:56 +00008019 }
8020
8021 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
8022 VG_(message)(Vg_UserMsg,
8023 "For counts of detected and suppressed errors, rerun with: -v\n");
8024 }
sewardj7cf4e6b2008-05-01 20:24:26 +00008025
sewardj7ce71662008-05-02 10:33:15 +00008026 if (MC_(any_value_errors) && !VG_(clo_xml) && VG_(clo_verbosity) >= 1
sewardj7cf4e6b2008-05-01 20:24:26 +00008027 && MC_(clo_mc_level) == 2) {
8028 VG_(message)(Vg_UserMsg,
8029 "Use --track-origins=yes to see where "
sewardj6b523cd2009-07-15 14:49:40 +00008030 "uninitialised values come from\n");
sewardj7cf4e6b2008-05-01 20:24:26 +00008031 }
8032
sewardjc5fc8662014-03-20 23:00:09 +00008033 /* Print a warning if any client-request generated ignore-ranges
8034 still exist. It would be reasonable to expect that a properly
8035 written program would remove any such ranges before exiting, and
8036 since they are a bit on the dangerous side, let's comment. By
8037 contrast ranges which are specified on the command line normally
8038 pertain to hardware mapped into the address space, and so we
8039 can't expect the client to have got rid of them. */
8040 if (gIgnoredAddressRanges) {
florianca631452015-08-05 13:23:11 +00008041 UInt i, nBad = 0;
sewardjc5fc8662014-03-20 23:00:09 +00008042 for (i = 0; i < VG_(sizeRangeMap)(gIgnoredAddressRanges); i++) {
8043 UWord val = IAR_INVALID;
8044 UWord key_min = ~(UWord)0;
8045 UWord key_max = (UWord)0;
8046 VG_(indexRangeMap)( &key_min, &key_max, &val,
8047 gIgnoredAddressRanges, i );
8048 if (val != IAR_ClientReq)
8049 continue;
8050 /* Print the offending range. Also, if it is the first,
8051 print a banner before it. */
8052 nBad++;
8053 if (nBad == 1) {
8054 VG_(umsg)(
8055 "WARNING: exiting program has the following client-requested\n"
8056 "WARNING: address error disablement range(s) still in force,\n"
8057 "WARNING: "
8058 "possibly as a result of some mistake in the use of the\n"
8059 "WARNING: "
8060 "VALGRIND_{DISABLE,ENABLE}_ERROR_REPORTING_IN_RANGE macros.\n"
8061 );
8062 }
florianca631452015-08-05 13:23:11 +00008063 VG_(umsg)(" [%u] 0x%016lx-0x%016lx %s\n",
8064 i, key_min, key_max, showIARKind(val));
sewardjc5fc8662014-03-20 23:00:09 +00008065 }
8066 }
8067
njn1d0825f2006-03-27 11:37:07 +00008068 done_prof_mem();
sewardjae986ca2005-10-12 12:53:20 +00008069
philippe8587b542013-12-15 20:24:43 +00008070 if (VG_(clo_stats))
8071 mc_print_stats();
sewardj45d94cc2005-04-20 14:44:11 +00008072
njn5c004e42002-11-18 11:04:50 +00008073 if (0) {
8074 VG_(message)(Vg_DebugMsg,
sewardj6b523cd2009-07-15 14:49:40 +00008075 "------ Valgrind's client block stats follow ---------------\n" );
nethercote8b76fe52004-11-08 19:20:09 +00008076 show_client_block_stats();
njn5c004e42002-11-18 11:04:50 +00008077 }
njn25e49d8e72002-09-23 09:36:25 +00008078}
8079
sewardj3b290482011-05-06 21:02:55 +00008080/* mark the given addr/len unaddressable for watchpoint implementation
8081 The PointKind will be handled at access time */
8082static Bool mc_mark_unaddressable_for_watchpoint (PointKind kind, Bool insert,
8083 Addr addr, SizeT len)
8084{
8085 /* GDBTD this is somewhat fishy. We might rather have to save the previous
8086 accessibility and definedness in gdbserver so as to allow restoring it
8087 properly. Currently, we assume that the user only watches things
8088 which are properly addressable and defined */
8089 if (insert)
8090 MC_(make_mem_noaccess) (addr, len);
8091 else
8092 MC_(make_mem_defined) (addr, len);
8093 return True;
8094}
8095
njn51d827b2005-05-09 01:02:08 +00008096static void mc_pre_clo_init(void)
8097{
8098 VG_(details_name) ("Memcheck");
8099 VG_(details_version) (NULL);
8100 VG_(details_description) ("a memory error detector");
8101 VG_(details_copyright_author)(
sewardjb3a1e4b2015-08-21 11:32:26 +00008102 "Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.");
njn51d827b2005-05-09 01:02:08 +00008103 VG_(details_bug_reports_to) (VG_BUGS_TO);
sewardj1e0fff62011-01-10 15:01:03 +00008104 VG_(details_avg_translation_sizeB) ( 640 );
njn51d827b2005-05-09 01:02:08 +00008105
8106 VG_(basic_tool_funcs) (mc_post_clo_init,
8107 MC_(instrument),
8108 mc_fini);
8109
sewardj81651dc2007-08-28 06:05:20 +00008110 VG_(needs_final_IR_tidy_pass) ( MC_(final_tidy) );
8111
8112
njn51d827b2005-05-09 01:02:08 +00008113 VG_(needs_core_errors) ();
sewardj7ce71662008-05-02 10:33:15 +00008114 VG_(needs_tool_errors) (MC_(eq_Error),
sewardj6b523cd2009-07-15 14:49:40 +00008115 MC_(before_pp_Error),
sewardj7ce71662008-05-02 10:33:15 +00008116 MC_(pp_Error),
sewardj39f34232007-11-09 23:02:28 +00008117 True,/*show TIDs for errors*/
sewardj7ce71662008-05-02 10:33:15 +00008118 MC_(update_Error_extra),
8119 MC_(is_recognised_suppression),
8120 MC_(read_extra_suppression_info),
8121 MC_(error_matches_suppression),
8122 MC_(get_error_name),
philippe4e32d672013-10-17 22:10:41 +00008123 MC_(get_extra_suppression_info),
8124 MC_(print_extra_suppression_use),
8125 MC_(update_extra_suppression_use));
njn51d827b2005-05-09 01:02:08 +00008126 VG_(needs_libc_freeres) ();
Elliott Hughesa0664b92017-04-18 17:46:52 -07008127 VG_(needs_cxx_freeres) ();
njn1d0825f2006-03-27 11:37:07 +00008128 VG_(needs_command_line_options)(mc_process_cmd_line_options,
njn51d827b2005-05-09 01:02:08 +00008129 mc_print_usage,
8130 mc_print_debug_usage);
8131 VG_(needs_client_requests) (mc_handle_client_request);
8132 VG_(needs_sanity_checks) (mc_cheap_sanity_check,
8133 mc_expensive_sanity_check);
philippe8587b542013-12-15 20:24:43 +00008134 VG_(needs_print_stats) (mc_print_stats);
philippe07c08522014-05-14 20:39:27 +00008135 VG_(needs_info_location) (MC_(pp_describe_addr));
njn1d0825f2006-03-27 11:37:07 +00008136 VG_(needs_malloc_replacement) (MC_(malloc),
8137 MC_(__builtin_new),
8138 MC_(__builtin_vec_new),
8139 MC_(memalign),
8140 MC_(calloc),
8141 MC_(free),
8142 MC_(__builtin_delete),
8143 MC_(__builtin_vec_delete),
8144 MC_(realloc),
njn8b140de2009-02-17 04:31:18 +00008145 MC_(malloc_usable_size),
philipped99c26a2012-07-31 22:17:28 +00008146 MC_MALLOC_DEFAULT_REDZONE_SZB );
8147 MC_(Malloc_Redzone_SzB) = VG_(malloc_effective_client_redzone_size)();
sewardj6b523cd2009-07-15 14:49:40 +00008148
njnca54af32006-04-16 10:25:43 +00008149 VG_(needs_xml_output) ();
njn51d827b2005-05-09 01:02:08 +00008150
njn1d0825f2006-03-27 11:37:07 +00008151 VG_(track_new_mem_startup) ( mc_new_mem_startup );
sewardj6f95e7e2010-01-27 10:28:00 +00008152
8153 // Handling of mmap and mprotect isn't simple (well, it is simple,
8154 // but the justification isn't.) See comments above, just prior to
8155 // mc_new_mem_mmap.
njn1d0825f2006-03-27 11:37:07 +00008156 VG_(track_new_mem_mmap) ( mc_new_mem_mmap );
sewardj6f95e7e2010-01-27 10:28:00 +00008157 VG_(track_change_mem_mprotect) ( mc_new_mem_mprotect );
njn51d827b2005-05-09 01:02:08 +00008158
njn1d0825f2006-03-27 11:37:07 +00008159 VG_(track_copy_mem_remap) ( MC_(copy_address_range_state) );
njn81623712005-10-07 04:48:37 +00008160
njndbf7ca72006-03-31 11:57:59 +00008161 VG_(track_die_mem_stack_signal)( MC_(make_mem_noaccess) );
8162 VG_(track_die_mem_brk) ( MC_(make_mem_noaccess) );
8163 VG_(track_die_mem_munmap) ( MC_(make_mem_noaccess) );
njn51d827b2005-05-09 01:02:08 +00008164
sewardj7cf4e6b2008-05-01 20:24:26 +00008165 /* Defer the specification of the new_mem_stack functions to the
8166 post_clo_init function, since we need to first parse the command
8167 line before deciding which set to use. */
njn51d827b2005-05-09 01:02:08 +00008168
sewardj7cf4e6b2008-05-01 20:24:26 +00008169# ifdef PERF_FAST_STACK
njn1d0825f2006-03-27 11:37:07 +00008170 VG_(track_die_mem_stack_4) ( mc_die_mem_stack_4 );
8171 VG_(track_die_mem_stack_8) ( mc_die_mem_stack_8 );
8172 VG_(track_die_mem_stack_12) ( mc_die_mem_stack_12 );
8173 VG_(track_die_mem_stack_16) ( mc_die_mem_stack_16 );
8174 VG_(track_die_mem_stack_32) ( mc_die_mem_stack_32 );
8175 VG_(track_die_mem_stack_112) ( mc_die_mem_stack_112 );
8176 VG_(track_die_mem_stack_128) ( mc_die_mem_stack_128 );
8177 VG_(track_die_mem_stack_144) ( mc_die_mem_stack_144 );
8178 VG_(track_die_mem_stack_160) ( mc_die_mem_stack_160 );
sewardj7cf4e6b2008-05-01 20:24:26 +00008179# endif
njn1d0825f2006-03-27 11:37:07 +00008180 VG_(track_die_mem_stack) ( mc_die_mem_stack );
njn51d827b2005-05-09 01:02:08 +00008181
njndbf7ca72006-03-31 11:57:59 +00008182 VG_(track_ban_mem_stack) ( MC_(make_mem_noaccess) );
njn51d827b2005-05-09 01:02:08 +00008183
njndbf7ca72006-03-31 11:57:59 +00008184 VG_(track_pre_mem_read) ( check_mem_is_defined );
8185 VG_(track_pre_mem_read_asciiz) ( check_mem_is_defined_asciiz );
8186 VG_(track_pre_mem_write) ( check_mem_is_addressable );
njn1d0825f2006-03-27 11:37:07 +00008187 VG_(track_post_mem_write) ( mc_post_mem_write );
njn51d827b2005-05-09 01:02:08 +00008188
njn1d0825f2006-03-27 11:37:07 +00008189 VG_(track_post_reg_write) ( mc_post_reg_write );
8190 VG_(track_post_reg_write_clientcall_return)( mc_post_reg_write_clientcall );
njn51d827b2005-05-09 01:02:08 +00008191
sewardj8eb8bab2015-07-21 14:44:28 +00008192 if (MC_(clo_mc_level) >= 2) {
8193 VG_(track_copy_mem_to_reg) ( mc_copy_mem_to_reg );
8194 VG_(track_copy_reg_to_mem) ( mc_copy_reg_to_mem );
8195 }
8196
sewardj3b290482011-05-06 21:02:55 +00008197 VG_(needs_watchpoint) ( mc_mark_unaddressable_for_watchpoint );
8198
njn51d827b2005-05-09 01:02:08 +00008199 init_shadow_memory();
philippe8617b5b2013-01-12 19:53:08 +00008200 // MC_(chunk_poolalloc) must be allocated in post_clo_init
8201 tl_assert(MC_(chunk_poolalloc) == NULL);
sewardj3f94a7d2007-08-25 07:19:08 +00008202 MC_(malloc_list) = VG_(HT_construct)( "MC_(malloc_list)" );
8203 MC_(mempool_list) = VG_(HT_construct)( "MC_(mempool_list)" );
njn1d0825f2006-03-27 11:37:07 +00008204 init_prof_mem();
njn51d827b2005-05-09 01:02:08 +00008205
8206 tl_assert( mc_expensive_sanity_check() );
njn1d0825f2006-03-27 11:37:07 +00008207
8208 // {LOADV,STOREV}[8421] will all fail horribly if this isn't true.
8209 tl_assert(sizeof(UWord) == sizeof(Addr));
sewardj05a46732006-10-17 01:28:10 +00008210 // Call me paranoid. I don't care.
8211 tl_assert(sizeof(void*) == sizeof(Addr));
njn1d0825f2006-03-27 11:37:07 +00008212
8213 // BYTES_PER_SEC_VBIT_NODE must be a power of two.
8214 tl_assert(-1 != VG_(log2)(BYTES_PER_SEC_VBIT_NODE));
sewardj7cf4e6b2008-05-01 20:24:26 +00008215
sewardj9d624d12008-05-02 13:35:29 +00008216 /* This is small. Always initialise it. */
sewardj7cf4e6b2008-05-01 20:24:26 +00008217 init_nia_to_ecu_cache();
sewardj7244e712008-05-02 12:35:48 +00008218
sewardj77139802008-05-05 09:48:56 +00008219 /* We can't initialise ocacheL1/ocacheL2 yet, since we don't know
8220 if we need to, since the command line args haven't been
8221 processed yet. Hence defer it to mc_post_clo_init. */
8222 tl_assert(ocacheL1 == NULL);
sewardj9d624d12008-05-02 13:35:29 +00008223 tl_assert(ocacheL2 == NULL);
8224
sewardj7244e712008-05-02 12:35:48 +00008225 /* Check some important stuff. See extensive comments above
8226 re UNALIGNED_OR_HIGH for background. */
8227# if VG_WORDSIZE == 4
8228 tl_assert(sizeof(void*) == 4);
8229 tl_assert(sizeof(Addr) == 4);
8230 tl_assert(sizeof(UWord) == 4);
8231 tl_assert(sizeof(Word) == 4);
8232 tl_assert(MAX_PRIMARY_ADDRESS == 0xFFFFFFFFUL);
8233 tl_assert(MASK(1) == 0UL);
8234 tl_assert(MASK(2) == 1UL);
8235 tl_assert(MASK(4) == 3UL);
8236 tl_assert(MASK(8) == 7UL);
8237# else
8238 tl_assert(VG_WORDSIZE == 8);
8239 tl_assert(sizeof(void*) == 8);
8240 tl_assert(sizeof(Addr) == 8);
8241 tl_assert(sizeof(UWord) == 8);
8242 tl_assert(sizeof(Word) == 8);
sewardj6805a4a2013-01-29 21:14:46 +00008243 tl_assert(MAX_PRIMARY_ADDRESS == 0xFFFFFFFFFULL);
8244 tl_assert(MASK(1) == 0xFFFFFFF000000000ULL);
8245 tl_assert(MASK(2) == 0xFFFFFFF000000001ULL);
8246 tl_assert(MASK(4) == 0xFFFFFFF000000003ULL);
8247 tl_assert(MASK(8) == 0xFFFFFFF000000007ULL);
sewardj7244e712008-05-02 12:35:48 +00008248# endif
Elliott Hughesa0664b92017-04-18 17:46:52 -07008249
8250 /* Check some assertions to do with the instrumentation machinery. */
8251 MC_(do_instrumentation_startup_checks)();
njn51d827b2005-05-09 01:02:08 +00008252}
8253
Elliott Hughesa0664b92017-04-18 17:46:52 -07008254STATIC_ASSERT(sizeof(UWord) == sizeof(SizeT));
8255
sewardj45f4e7c2005-09-27 19:20:21 +00008256VG_DETERMINE_INTERFACE_VERSION(mc_pre_clo_init)
fitzhardinge98abfc72003-12-16 02:05:15 +00008257
njn25e49d8e72002-09-23 09:36:25 +00008258/*--------------------------------------------------------------------*/
sewardj7ce71662008-05-02 10:33:15 +00008259/*--- end mc_main.c ---*/
njn25e49d8e72002-09-23 09:36:25 +00008260/*--------------------------------------------------------------------*/