blob: fc3d86bdf7164706a32bbedaa4c76545b5d97e7b [file] [log] [blame]
njn5c004e42002-11-18 11:04:50 +00001
2/*--------------------------------------------------------------------*/
njn43c799e2003-04-08 00:08:52 +00003/*--- Declarations shared between MemCheck and AddrCheck. ---*/
4/*--- mac_shared.h ---*/
njn5c004e42002-11-18 11:04:50 +00005/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of MemCheck, a heavyweight Valgrind skin for
9 detecting memory errors, and AddrCheck, a lightweight Valgrind skin
10 for detecting memory errors.
11
12 Copyright (C) 2000-2002 Julian Seward
13 jseward@acm.org
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file COPYING.
31*/
32
njn43c799e2003-04-08 00:08:52 +000033/* Note: This header contains the declarations shared between
34 Addrcheck and Memcheck, and is #included by both. */
35
36#ifndef __MAC_SHARED_H
37#define __MAC_SHARED_H
njn5c004e42002-11-18 11:04:50 +000038
39#include "vg_skin.h"
njn43c799e2003-04-08 00:08:52 +000040
41#define MAC_(str) VGAPPEND(vgMAC_,str)
njn5c004e42002-11-18 11:04:50 +000042
njn9b007f62003-04-07 14:40:25 +000043/*------------------------------------------------------------*/
44/*--- Errors and suppressions ---*/
45/*------------------------------------------------------------*/
46
njn5c004e42002-11-18 11:04:50 +000047/* The classification of a faulting address. */
48typedef
njn43c799e2003-04-08 00:08:52 +000049 enum {
50 Undescribed, /* as-yet unclassified */
51 Stack,
52 Unknown, /* classification yielded nothing useful */
53 Freed, Mallocd,
54 UserG /* in a user-defined block; Addrcheck & Memcheck only */
njn5c004e42002-11-18 11:04:50 +000055 }
56 AddrKind;
57
58/* Records info about a faulting address. */
59typedef
60 struct {
61 /* ALL */
62 AddrKind akind;
63 /* Freed, Mallocd */
64 Int blksize;
65 /* Freed, Mallocd */
66 Int rwoffset;
67 /* Freed, Mallocd */
68 ExeContext* lastchange;
69 /* Stack */
70 ThreadId stack_tid;
71 /* True if is just-below %esp -- could be a gcc bug. */
72 Bool maybe_gcc;
73 }
74 AddrInfo;
75
76typedef
77 enum {
78 /* Bad syscall params */
79 ParamSupp,
80 /* Memory errors in core (pthread ops, signal handling) */
81 CoreMemSupp,
82 /* Use of invalid values of given size (MemCheck only) */
83 Value0Supp, Value1Supp, Value2Supp, Value4Supp, Value8Supp,
84 /* Invalid read/write attempt at given size */
85 Addr1Supp, Addr2Supp, Addr4Supp, Addr8Supp,
86 /* Invalid or mismatching free */
sewardj99aac972002-12-26 01:53:45 +000087 FreeSupp,
88 /* Something to be suppressed in a leak check. */
89 LeakSupp
njn5c004e42002-11-18 11:04:50 +000090 }
njn43c799e2003-04-08 00:08:52 +000091 MAC_SuppKind;
njn5c004e42002-11-18 11:04:50 +000092
93/* What kind of error it is. */
94typedef
95 enum { ValueErr, /* Memcheck only */
96 CoreMemErr,
97 AddrErr,
98 ParamErr, UserErr, /* behaves like an anonymous ParamErr */
njn43c799e2003-04-08 00:08:52 +000099 FreeErr, FreeMismatchErr,
100 LeakErr
njn5c004e42002-11-18 11:04:50 +0000101 }
njn43c799e2003-04-08 00:08:52 +0000102 MAC_ErrorKind;
njn5c004e42002-11-18 11:04:50 +0000103
104/* What kind of memory access is involved in the error? */
105typedef
106 enum { ReadAxs, WriteAxs, ExecAxs }
107 AxsKind;
108
109/* Extra context for memory errors */
110typedef
111 struct {
112 /* AddrErr */
113 AxsKind axskind;
114 /* AddrErr, ValueErr */
115 Int size;
116 /* AddrErr, FreeErr, FreeMismatchErr, ParamErr, UserErr */
117 AddrInfo addrinfo;
118 /* ParamErr, UserErr, CoreMemErr */
119 Bool isWrite;
120 }
njn43c799e2003-04-08 00:08:52 +0000121 MAC_Error;
njn5c004e42002-11-18 11:04:50 +0000122
njn9b007f62003-04-07 14:40:25 +0000123/*------------------------------------------------------------*/
124/*--- Profiling of skins and memory events ---*/
125/*------------------------------------------------------------*/
126
127typedef
128 enum {
129 VgpCheckMem = VgpFini+1,
130 VgpSetMem,
131 VgpESPAdj
132 }
133 VgpSkinCC;
134
135/* Define to collect detailed performance info. */
njn43c799e2003-04-08 00:08:52 +0000136/* #define MAC_PROFILE_MEMORY */
njn5c004e42002-11-18 11:04:50 +0000137
njn43c799e2003-04-08 00:08:52 +0000138#ifdef MAC_PROFILE_MEMORY
njn9b007f62003-04-07 14:40:25 +0000139# define N_PROF_EVENTS 150
njn5c004e42002-11-18 11:04:50 +0000140
njn43c799e2003-04-08 00:08:52 +0000141extern UInt MAC_(event_ctr)[N_PROF_EVENTS];
njn9b007f62003-04-07 14:40:25 +0000142
njn43c799e2003-04-08 00:08:52 +0000143# define PROF_EVENT(ev) \
144 do { sk_assert((ev) >= 0 && (ev) < N_PROF_EVENTS); \
145 MAC_(event_ctr)[ev]++; \
njn5c004e42002-11-18 11:04:50 +0000146 } while (False);
147
148#else
149
njn9b007f62003-04-07 14:40:25 +0000150# define PROF_EVENT(ev) /* */
njn5c004e42002-11-18 11:04:50 +0000151
njn43c799e2003-04-08 00:08:52 +0000152#endif /* MAC_PROFILE_MEMORY */
njn5c004e42002-11-18 11:04:50 +0000153
njn9b007f62003-04-07 14:40:25 +0000154/*------------------------------------------------------------*/
155/*--- V and A bits ---*/
156/*------------------------------------------------------------*/
157
njn5c004e42002-11-18 11:04:50 +0000158#define IS_DISTINGUISHED_SM(smap) \
159 ((smap) == &distinguished_secondary_map)
160
njn43c799e2003-04-08 00:08:52 +0000161#define ENSURE_MAPPABLE(addr,caller) \
162 do { \
njn5c004e42002-11-18 11:04:50 +0000163 if (IS_DISTINGUISHED_SM(primary_map[(addr) >> 16])) { \
164 primary_map[(addr) >> 16] = alloc_secondary_map(caller); \
njn43c799e2003-04-08 00:08:52 +0000165 /* VG_(printf)("new 2map because of %p\n", addr); */ \
166 } \
njn5c004e42002-11-18 11:04:50 +0000167 } while(0)
168
169#define BITARR_SET(aaa_p,iii_p) \
170 do { \
171 UInt iii = (UInt)iii_p; \
172 UChar* aaa = (UChar*)aaa_p; \
173 aaa[iii >> 3] |= (1 << (iii & 7)); \
174 } while (0)
175
176#define BITARR_CLEAR(aaa_p,iii_p) \
177 do { \
178 UInt iii = (UInt)iii_p; \
179 UChar* aaa = (UChar*)aaa_p; \
180 aaa[iii >> 3] &= ~(1 << (iii & 7)); \
181 } while (0)
182
183#define BITARR_TEST(aaa_p,iii_p) \
184 (0 != (((UChar*)aaa_p)[ ((UInt)iii_p) >> 3 ] \
185 & (1 << (((UInt)iii_p) & 7)))) \
186
187
188#define VGM_BIT_VALID 0
189#define VGM_BIT_INVALID 1
190
191#define VGM_NIBBLE_VALID 0
192#define VGM_NIBBLE_INVALID 0xF
193
194#define VGM_BYTE_VALID 0
195#define VGM_BYTE_INVALID 0xFF
196
197#define VGM_WORD_VALID 0
198#define VGM_WORD_INVALID 0xFFFFFFFF
199
200#define VGM_EFLAGS_VALID 0xFFFFFFFE
201#define VGM_EFLAGS_INVALID 0xFFFFFFFF /* not used */
202
203/*------------------------------------------------------------*/
204/*--- Command line options + defaults ---*/
205/*------------------------------------------------------------*/
206
njn43c799e2003-04-08 00:08:52 +0000207/* Memcheck defines a couple more. */
njn5c004e42002-11-18 11:04:50 +0000208
209/* Allow loads from partially-valid addresses? default: YES */
njn43c799e2003-04-08 00:08:52 +0000210extern Bool MAC_(clo_partial_loads_ok);
njn5c004e42002-11-18 11:04:50 +0000211
212/* Max volume of the freed blocks queue. */
njn43c799e2003-04-08 00:08:52 +0000213extern Int MAC_(clo_freelist_vol);
njn5c004e42002-11-18 11:04:50 +0000214
215/* Do leak check at exit? default: NO */
njn43c799e2003-04-08 00:08:52 +0000216extern Bool MAC_(clo_leak_check);
njn5c004e42002-11-18 11:04:50 +0000217
218/* How closely should we compare ExeContexts in leak records? default: 2 */
njn43c799e2003-04-08 00:08:52 +0000219extern VgRes MAC_(clo_leak_resolution);
njn5c004e42002-11-18 11:04:50 +0000220
221/* In leak check, show reachable-but-not-freed blocks? default: NO */
njn43c799e2003-04-08 00:08:52 +0000222extern Bool MAC_(clo_show_reachable);
njn5c004e42002-11-18 11:04:50 +0000223
224/* Assume accesses immediately below %esp are due to gcc-2.96 bugs.
225 * default: NO*/
njn43c799e2003-04-08 00:08:52 +0000226extern Bool MAC_(clo_workaround_gcc296_bugs);
njn5c004e42002-11-18 11:04:50 +0000227
njn43c799e2003-04-08 00:08:52 +0000228extern Bool MAC_(process_common_cmd_line_option)(Char* arg);
njn5c004e42002-11-18 11:04:50 +0000229
sewardj99aac972002-12-26 01:53:45 +0000230
njn5c004e42002-11-18 11:04:50 +0000231/*------------------------------------------------------------*/
232/*--- Functions ---*/
233/*------------------------------------------------------------*/
234
njn43c799e2003-04-08 00:08:52 +0000235extern void MAC_(set_where) ( ShadowChunk* sc, ExeContext* ec );
236extern ExeContext *MAC_(get_where) ( ShadowChunk* sc );
njn5c004e42002-11-18 11:04:50 +0000237
njn43c799e2003-04-08 00:08:52 +0000238extern void MAC_(pp_AddrInfo) ( Addr a, AddrInfo* ai );
njn5c004e42002-11-18 11:04:50 +0000239
njn43c799e2003-04-08 00:08:52 +0000240extern void MAC_(clear_MAC_Error) ( MAC_Error* err_extra );
njn5c004e42002-11-18 11:04:50 +0000241
njn43c799e2003-04-08 00:08:52 +0000242extern Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai );
njn5c004e42002-11-18 11:04:50 +0000243
njn43c799e2003-04-08 00:08:52 +0000244extern Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su );
njn5c004e42002-11-18 11:04:50 +0000245
njn43c799e2003-04-08 00:08:52 +0000246extern void MAC_(record_address_error) ( Addr a, Int size, Bool isWrite );
247extern void MAC_(record_core_mem_error) ( ThreadState* tst, Bool isWrite,
248 Char* s );
249extern void MAC_(record_param_error) ( ThreadState* tst, Addr a,
250 Bool isWriteLack, Char* msg );
251extern void MAC_(record_jump_error) ( ThreadState* tst, Addr a );
252extern void MAC_(record_free_error) ( ThreadState* tst, Addr a );
253extern void MAC_(record_freemismatch_error)( ThreadState* tst, Addr a );
njn5c004e42002-11-18 11:04:50 +0000254
njn43c799e2003-04-08 00:08:52 +0000255extern void MAC_(pp_shared_SkinError) ( Error* err);
256
257extern void MAC_(init_prof_mem) ( void );
258extern void MAC_(done_prof_mem) ( void );
259
260extern Int MAC_(count_freelist) ( void ) __attribute__ ((unused));
261extern void MAC_(freelist_sanity) ( void ) __attribute__ ((unused));
262extern ShadowChunk* MAC_(any_matching_freed_ShadowChunks)
263 ( Bool (*p)(ShadowChunk*) );
264
265/* For leak checking */
266extern void MAC_(pp_LeakError)(void* vl, UInt n_this_record,
267 UInt n_total_records);
268
269extern void MAC_(do_detect_memory_leaks) (
270 Bool is_valid_64k_chunk ( UInt ),
271 Bool is_valid_address ( Addr )
272 );
273
274extern __attribute__((regparm(1))) void MAC_(new_mem_stack_4) ( Addr old_ESP );
275extern __attribute__((regparm(1))) void MAC_(die_mem_stack_4) ( Addr old_ESP );
276extern __attribute__((regparm(1))) void MAC_(new_mem_stack_8) ( Addr old_ESP );
277extern __attribute__((regparm(1))) void MAC_(die_mem_stack_8) ( Addr old_ESP );
278extern __attribute__((regparm(1))) void MAC_(new_mem_stack_12) ( Addr old_ESP );
279extern __attribute__((regparm(1))) void MAC_(die_mem_stack_12) ( Addr old_ESP );
280extern __attribute__((regparm(1))) void MAC_(new_mem_stack_16) ( Addr old_ESP );
281extern __attribute__((regparm(1))) void MAC_(die_mem_stack_16) ( Addr old_ESP );
282extern __attribute__((regparm(1))) void MAC_(new_mem_stack_32) ( Addr old_ESP );
283extern __attribute__((regparm(1))) void MAC_(die_mem_stack_32) ( Addr old_ESP );
284extern void MAC_(die_mem_stack) ( Addr a, UInt len );
285extern void MAC_(new_mem_stack) ( Addr a, UInt len );
njn9b007f62003-04-07 14:40:25 +0000286
287
288/*------------------------------------------------------------*/
289/*--- Stack pointer adjustment ---*/
290/*------------------------------------------------------------*/
291
292/* Some noble preprocessor abuse, to enable Memcheck and Addrcheck to
293 share this code, but not call the same functions.
294
295 Note that this code is executed very frequently and must be highly
296 optimised, which is why I resort to the preprocessor to achieve the
297 factoring, rather than eg. using function pointers.
298*/
299
300#define ESP_UPDATE_HANDLERS(ALIGNED4_NEW, ALIGNED4_DIE, \
301 ALIGNED8_NEW, ALIGNED8_DIE, \
302 UNALIGNED_NEW, UNALIGNED_DIE) \
303 \
njn43c799e2003-04-08 00:08:52 +0000304void __attribute__((regparm(1))) MAC_(new_mem_stack_4)(Addr new_ESP) \
njn9b007f62003-04-07 14:40:25 +0000305{ \
306 PROF_EVENT(110); \
307 if (IS_ALIGNED4_ADDR(new_ESP)) { \
308 ALIGNED4_NEW ( new_ESP ); \
309 } else { \
310 UNALIGNED_NEW ( new_ESP, 4 ); \
311 } \
312} \
313 \
njn43c799e2003-04-08 00:08:52 +0000314void __attribute__((regparm(1))) MAC_(die_mem_stack_4)(Addr new_ESP) \
njn9b007f62003-04-07 14:40:25 +0000315{ \
316 PROF_EVENT(120); \
317 if (IS_ALIGNED4_ADDR(new_ESP)) { \
318 ALIGNED4_DIE ( new_ESP-4 ); \
319 } else { \
320 UNALIGNED_DIE ( new_ESP-4, 4 ); \
321 } \
322} \
323 \
njn43c799e2003-04-08 00:08:52 +0000324void __attribute__((regparm(1))) MAC_(new_mem_stack_8)(Addr new_ESP) \
njn9b007f62003-04-07 14:40:25 +0000325{ \
326 PROF_EVENT(111); \
327 if (IS_ALIGNED8_ADDR(new_ESP)) { \
328 ALIGNED8_NEW ( new_ESP ); \
329 } else if (IS_ALIGNED4_ADDR(new_ESP)) { \
330 ALIGNED4_NEW ( new_ESP ); \
331 ALIGNED4_NEW ( new_ESP+4 ); \
332 } else { \
333 UNALIGNED_NEW ( new_ESP, 8 ); \
334 } \
335} \
336 \
njn43c799e2003-04-08 00:08:52 +0000337void __attribute__((regparm(1))) MAC_(die_mem_stack_8)(Addr new_ESP) \
njn9b007f62003-04-07 14:40:25 +0000338{ \
339 PROF_EVENT(121); \
340 if (IS_ALIGNED8_ADDR(new_ESP)) { \
341 ALIGNED8_DIE ( new_ESP-8 ); \
342 } else if (IS_ALIGNED4_ADDR(new_ESP)) { \
343 ALIGNED4_DIE ( new_ESP-8 ); \
344 ALIGNED4_DIE ( new_ESP-4 ); \
345 } else { \
346 UNALIGNED_DIE ( new_ESP-8, 8 ); \
347 } \
348} \
349 \
njn43c799e2003-04-08 00:08:52 +0000350void __attribute__((regparm(1))) MAC_(new_mem_stack_12)(Addr new_ESP) \
njn9b007f62003-04-07 14:40:25 +0000351{ \
352 PROF_EVENT(112); \
353 if (IS_ALIGNED8_ADDR(new_ESP)) { \
354 ALIGNED8_NEW ( new_ESP ); \
355 ALIGNED4_NEW ( new_ESP+8 ); \
356 } else if (IS_ALIGNED4_ADDR(new_ESP)) { \
357 ALIGNED4_NEW ( new_ESP ); \
358 ALIGNED8_NEW ( new_ESP+4 ); \
359 } else { \
360 UNALIGNED_NEW ( new_ESP, 12 ); \
361 } \
362} \
363 \
njn43c799e2003-04-08 00:08:52 +0000364void __attribute__((regparm(1))) MAC_(die_mem_stack_12)(Addr new_ESP) \
njn9b007f62003-04-07 14:40:25 +0000365{ \
366 PROF_EVENT(122); \
367 /* Note the -12 in the test */ \
368 if (IS_ALIGNED8_ADDR(new_ESP-12)) { \
369 ALIGNED8_DIE ( new_ESP-12 ); \
370 ALIGNED4_DIE ( new_ESP-4 ); \
371 } else if (IS_ALIGNED4_ADDR(new_ESP)) { \
372 ALIGNED4_DIE ( new_ESP-12 ); \
373 ALIGNED8_DIE ( new_ESP-8 ); \
374 } else { \
375 UNALIGNED_DIE ( new_ESP-12, 12 ); \
376 } \
377} \
378 \
njn43c799e2003-04-08 00:08:52 +0000379void __attribute__((regparm(1))) MAC_(new_mem_stack_16)(Addr new_ESP) \
njn9b007f62003-04-07 14:40:25 +0000380{ \
381 PROF_EVENT(113); \
382 if (IS_ALIGNED8_ADDR(new_ESP)) { \
383 ALIGNED8_NEW ( new_ESP ); \
384 ALIGNED8_NEW ( new_ESP+8 ); \
385 } else if (IS_ALIGNED4_ADDR(new_ESP)) { \
386 ALIGNED4_NEW ( new_ESP ); \
387 ALIGNED8_NEW ( new_ESP+4 ); \
388 ALIGNED4_NEW ( new_ESP+12 ); \
389 } else { \
390 UNALIGNED_NEW ( new_ESP, 16 ); \
391 } \
392} \
393 \
njn43c799e2003-04-08 00:08:52 +0000394void __attribute__((regparm(1))) MAC_(die_mem_stack_16)(Addr new_ESP) \
njn9b007f62003-04-07 14:40:25 +0000395{ \
396 PROF_EVENT(123); \
397 if (IS_ALIGNED8_ADDR(new_ESP)) { \
398 ALIGNED8_DIE ( new_ESP-16 ); \
399 ALIGNED8_DIE ( new_ESP-8 ); \
400 } else if (IS_ALIGNED4_ADDR(new_ESP)) { \
401 ALIGNED4_DIE ( new_ESP-16 ); \
402 ALIGNED8_DIE ( new_ESP-12 ); \
403 ALIGNED4_DIE ( new_ESP-4 ); \
404 } else { \
405 UNALIGNED_DIE ( new_ESP-16, 16 ); \
406 } \
407} \
408 \
njn43c799e2003-04-08 00:08:52 +0000409void __attribute__((regparm(1))) MAC_(new_mem_stack_32)(Addr new_ESP) \
njn9b007f62003-04-07 14:40:25 +0000410{ \
411 PROF_EVENT(114); \
412 if (IS_ALIGNED8_ADDR(new_ESP)) { \
413 ALIGNED8_NEW ( new_ESP ); \
414 ALIGNED8_NEW ( new_ESP+8 ); \
415 ALIGNED8_NEW ( new_ESP+16 ); \
416 ALIGNED8_NEW ( new_ESP+24 ); \
417 } else if (IS_ALIGNED4_ADDR(new_ESP)) { \
418 ALIGNED4_NEW ( new_ESP ); \
419 ALIGNED8_NEW ( new_ESP+4 ); \
420 ALIGNED8_NEW ( new_ESP+12 ); \
421 ALIGNED8_NEW ( new_ESP+20 ); \
422 ALIGNED4_NEW ( new_ESP+28 ); \
423 } else { \
424 UNALIGNED_NEW ( new_ESP, 32 ); \
425 } \
426} \
427 \
njn43c799e2003-04-08 00:08:52 +0000428void __attribute__((regparm(1))) MAC_(die_mem_stack_32)(Addr new_ESP) \
njn9b007f62003-04-07 14:40:25 +0000429{ \
430 PROF_EVENT(124); \
431 if (IS_ALIGNED8_ADDR(new_ESP)) { \
432 ALIGNED8_DIE ( new_ESP-32 ); \
433 ALIGNED8_DIE ( new_ESP-24 ); \
434 ALIGNED8_DIE ( new_ESP-16 ); \
435 ALIGNED8_DIE ( new_ESP- 8 ); \
436 } else if (IS_ALIGNED4_ADDR(new_ESP)) { \
437 ALIGNED4_DIE ( new_ESP-32 ); \
438 ALIGNED8_DIE ( new_ESP-28 ); \
439 ALIGNED8_DIE ( new_ESP-20 ); \
440 ALIGNED8_DIE ( new_ESP-12 ); \
441 ALIGNED4_DIE ( new_ESP-4 ); \
442 } else { \
443 UNALIGNED_DIE ( new_ESP-32, 32 ); \
444 } \
445} \
446 \
njn43c799e2003-04-08 00:08:52 +0000447void MAC_(new_mem_stack) ( Addr a, UInt len ) \
njn9b007f62003-04-07 14:40:25 +0000448{ \
449 PROF_EVENT(115); \
450 UNALIGNED_NEW ( a, len ); \
451} \
452 \
njn43c799e2003-04-08 00:08:52 +0000453void MAC_(die_mem_stack) ( Addr a, UInt len ) \
njn9b007f62003-04-07 14:40:25 +0000454{ \
455 PROF_EVENT(125); \
456 UNALIGNED_DIE ( a, len ); \
457}
458
njn43c799e2003-04-08 00:08:52 +0000459#endif /* __MAC_SHARED_H */
njn5c004e42002-11-18 11:04:50 +0000460
461/*--------------------------------------------------------------------*/
njn43c799e2003-04-08 00:08:52 +0000462/*--- end mac_shared.h ---*/
njn5c004e42002-11-18 11:04:50 +0000463/*--------------------------------------------------------------------*/