blob: ad6b2f66520da1215d1b69cff942c9e86bd6c59f [file] [log] [blame]
njn5c004e42002-11-18 11:04:50 +00001
2/*--------------------------------------------------------------------*/
3/*--- Code that is shared between MemCheck and AddrCheck. ---*/
njn43c799e2003-04-08 00:08:52 +00004/*--- mac_needs.c ---*/
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
33
njn43c799e2003-04-08 00:08:52 +000034#include "mac_shared.h"
njn5c004e42002-11-18 11:04:50 +000035
36/*------------------------------------------------------------*/
37/*--- Defns ---*/
38/*------------------------------------------------------------*/
39
40/* These many bytes below %ESP are considered addressible if we're
41 doing the --workaround-gcc296-bugs hack. */
42#define VG_GCC296_BUG_STACK_SLOP 1024
43
44/*------------------------------------------------------------*/
45/*--- Command line options ---*/
46/*------------------------------------------------------------*/
47
njn43c799e2003-04-08 00:08:52 +000048Bool MAC_(clo_partial_loads_ok) = True;
49Int MAC_(clo_freelist_vol) = 1000000;
50Bool MAC_(clo_leak_check) = False;
51VgRes MAC_(clo_leak_resolution) = Vg_LowRes;
52Bool MAC_(clo_show_reachable) = False;
53Bool MAC_(clo_workaround_gcc296_bugs) = False;
njn5c004e42002-11-18 11:04:50 +000054
njn43c799e2003-04-08 00:08:52 +000055Bool MAC_(process_common_cmd_line_option)(Char* arg)
njn5c004e42002-11-18 11:04:50 +000056{
njn43c799e2003-04-08 00:08:52 +000057 if (VG_CLO_STREQ(arg, "--partial-loads-ok=yes"))
58 MAC_(clo_partial_loads_ok) = True;
59 else if (VG_CLO_STREQ(arg, "--partial-loads-ok=no"))
60 MAC_(clo_partial_loads_ok) = False;
njn5c004e42002-11-18 11:04:50 +000061
njn43c799e2003-04-08 00:08:52 +000062 else if (VG_CLO_STREQN(15, arg, "--freelist-vol=")) {
63 MAC_(clo_freelist_vol) = (Int)VG_(atoll)(&arg[15]);
64 if (MAC_(clo_freelist_vol) < 0) MAC_(clo_freelist_vol) = 0;
njn5c004e42002-11-18 11:04:50 +000065 }
66
njn43c799e2003-04-08 00:08:52 +000067 else if (VG_CLO_STREQ(arg, "--leak-check=yes"))
68 MAC_(clo_leak_check) = True;
69 else if (VG_CLO_STREQ(arg, "--leak-check=no"))
70 MAC_(clo_leak_check) = False;
njn5c004e42002-11-18 11:04:50 +000071
njn43c799e2003-04-08 00:08:52 +000072 else if (VG_CLO_STREQ(arg, "--leak-resolution=low"))
73 MAC_(clo_leak_resolution) = Vg_LowRes;
74 else if (VG_CLO_STREQ(arg, "--leak-resolution=med"))
75 MAC_(clo_leak_resolution) = Vg_MedRes;
76 else if (VG_CLO_STREQ(arg, "--leak-resolution=high"))
77 MAC_(clo_leak_resolution) = Vg_HighRes;
njn5c004e42002-11-18 11:04:50 +000078
njn43c799e2003-04-08 00:08:52 +000079 else if (VG_CLO_STREQ(arg, "--show-reachable=yes"))
80 MAC_(clo_show_reachable) = True;
81 else if (VG_CLO_STREQ(arg, "--show-reachable=no"))
82 MAC_(clo_show_reachable) = False;
njn5c004e42002-11-18 11:04:50 +000083
njn43c799e2003-04-08 00:08:52 +000084 else if (VG_CLO_STREQ(arg, "--workaround-gcc296-bugs=yes"))
85 MAC_(clo_workaround_gcc296_bugs) = True;
86 else if (VG_CLO_STREQ(arg, "--workaround-gcc296-bugs=no"))
87 MAC_(clo_workaround_gcc296_bugs) = False;
njn5c004e42002-11-18 11:04:50 +000088
89 else
90 return False;
91
92 return True;
njn43c799e2003-04-08 00:08:52 +000093}
njn5c004e42002-11-18 11:04:50 +000094
njn43c799e2003-04-08 00:08:52 +000095/*------------------------------------------------------------*/
96/*--- Shadow chunks info ---*/
97/*------------------------------------------------------------*/
98
99void MAC_(set_where)( ShadowChunk* sc, ExeContext* ec )
100{
101 VG_(set_sc_extra)( sc, 0, (UInt)ec );
102}
103
104ExeContext *MAC_(get_where)( ShadowChunk* sc )
105{
106 return (ExeContext*)VG_(get_sc_extra)(sc, 0);
107}
108
109void SK_(complete_shadow_chunk) ( ShadowChunk* sc, ThreadState* tst )
110{
111 VG_(set_sc_extra) ( sc, 0, (UInt)VG_(get_ExeContext)(tst) );
112}
113
114
115/*------------------------------------------------------------*/
116/*--- Postponing free()ing ---*/
117/*------------------------------------------------------------*/
118
119/* Holds blocks after freeing. */
120static ShadowChunk* freed_list_start = NULL;
121static ShadowChunk* freed_list_end = NULL;
122static Int freed_list_volume = 0;
123
124__attribute__ ((unused))
125Int MAC_(count_freelist) ( void )
126{
127 ShadowChunk* sc;
128 Int n = 0;
129 for (sc = freed_list_start; sc != NULL; sc = VG_(get_sc_next)(sc))
130 n++;
131 return n;
132}
133
134__attribute__ ((unused))
135void MAC_(freelist_sanity) ( void )
136{
137 ShadowChunk* sc;
138 Int n = 0;
139 /* VG_(printf)("freelist sanity\n"); */
140 for (sc = freed_list_start; sc != NULL; sc = VG_(get_sc_next)(sc))
141 n += VG_(get_sc_size)(sc);
142 sk_assert(n == freed_list_volume);
143}
144
145/* Put a shadow chunk on the freed blocks queue, possibly freeing up
146 some of the oldest blocks in the queue at the same time. */
147static void add_to_freed_queue ( ShadowChunk* sc )
148{
149 ShadowChunk* sc1;
150
151 /* Put it at the end of the freed list */
152 if (freed_list_end == NULL) {
153 sk_assert(freed_list_start == NULL);
154 freed_list_end = freed_list_start = sc;
155 freed_list_volume = VG_(get_sc_size)(sc);
156 } else {
157 sk_assert(VG_(get_sc_next)(freed_list_end) == NULL);
158 VG_(set_sc_next)(freed_list_end, sc);
159 freed_list_end = sc;
160 freed_list_volume += VG_(get_sc_size)(sc);
161 }
162 VG_(set_sc_next)(sc, NULL);
163
164 /* Release enough of the oldest blocks to bring the free queue
165 volume below vg_clo_freelist_vol. */
166
167 while (freed_list_volume > MAC_(clo_freelist_vol)) {
168 /* freelist_sanity(); */
169 sk_assert(freed_list_start != NULL);
170 sk_assert(freed_list_end != NULL);
171
172 sc1 = freed_list_start;
173 freed_list_volume -= VG_(get_sc_size)(sc1);
174 /* VG_(printf)("volume now %d\n", freed_list_volume); */
175 sk_assert(freed_list_volume >= 0);
176
177 if (freed_list_start == freed_list_end) {
178 freed_list_start = freed_list_end = NULL;
179 } else {
180 freed_list_start = VG_(get_sc_next)(sc1);
181 }
182 VG_(set_sc_next)(sc1, NULL); /* just paranoia */
183 VG_(free_ShadowChunk) ( sc1 );
184 }
185}
186
187void SK_(alt_free) ( ShadowChunk* sc, ThreadState* tst )
188{
189 /* Record where freed */
190 MAC_(set_where)( sc, VG_(get_ExeContext) ( tst ) );
191
192 /* Put it out of harm's way for a while. */
193 add_to_freed_queue ( sc );
njn5c004e42002-11-18 11:04:50 +0000194}
195
196/*------------------------------------------------------------*/
197/*--- Comparing and printing errors ---*/
198/*------------------------------------------------------------*/
199
200static __inline__
201void clear_AddrInfo ( AddrInfo* ai )
202{
203 ai->akind = Unknown;
204 ai->blksize = 0;
205 ai->rwoffset = 0;
206 ai->lastchange = NULL;
207 ai->stack_tid = VG_INVALID_THREADID;
208 ai->maybe_gcc = False;
209}
210
njn43c799e2003-04-08 00:08:52 +0000211void MAC_(clear_MAC_Error) ( MAC_Error* err_extra )
njn5c004e42002-11-18 11:04:50 +0000212{
213 err_extra->axskind = ReadAxs;
214 err_extra->size = 0;
215 clear_AddrInfo ( &err_extra->addrinfo );
216 err_extra->isWrite = False;
217}
218
219__attribute__ ((unused))
220static Bool eq_AddrInfo ( VgRes res, AddrInfo* ai1, AddrInfo* ai2 )
221{
222 if (ai1->akind != Undescribed
223 && ai2->akind != Undescribed
224 && ai1->akind != ai2->akind)
225 return False;
226 if (ai1->akind == Freed || ai1->akind == Mallocd) {
227 if (ai1->blksize != ai2->blksize)
228 return False;
229 if (!VG_(eq_ExeContext)(res, ai1->lastchange, ai2->lastchange))
230 return False;
231 }
232 return True;
233}
234
235/* Compare error contexts, to detect duplicates. Note that if they
236 are otherwise the same, the faulting addrs and associated rwoffsets
237 are allowed to be different. */
238
239Bool SK_(eq_SkinError) ( VgRes res, Error* e1, Error* e2 )
240{
njn43c799e2003-04-08 00:08:52 +0000241 MAC_Error* e1_extra = VG_(get_error_extra)(e1);
242 MAC_Error* e2_extra = VG_(get_error_extra)(e2);
njn7cc53a82002-11-19 16:19:32 +0000243
244 /* Guaranteed by calling function */
245 sk_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
njn5c004e42002-11-18 11:04:50 +0000246
247 switch (VG_(get_error_kind)(e1)) {
248 case CoreMemErr: {
249 Char *e1s, *e2s;
250 if (e1_extra->isWrite != e2_extra->isWrite) return False;
njn5c004e42002-11-18 11:04:50 +0000251 e1s = VG_(get_error_string)(e1);
252 e2s = VG_(get_error_string)(e2);
253 if (e1s == e2s) return True;
254 if (0 == VG_(strcmp)(e1s, e2s)) return True;
255 return False;
256 }
257
258 case UserErr:
259 case ParamErr:
260 if (e1_extra->isWrite != e2_extra->isWrite) return False;
261 if (VG_(get_error_kind)(e1) == ParamErr
262 && 0 != VG_(strcmp)(VG_(get_error_string)(e1),
263 VG_(get_error_string)(e2))) return False;
264 return True;
265
266 case FreeErr:
267 case FreeMismatchErr:
268 /* JRS 2002-Aug-26: comparing addrs seems overkill and can
269 cause excessive duplication of errors. Not even AddrErr
270 below does that. So don't compare either the .addr field
271 or the .addrinfo fields. */
272 /* if (e1->addr != e2->addr) return False; */
273 /* if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
274 return False;
275 */
276 return True;
277
278 case AddrErr:
279 /* if (e1_extra->axskind != e2_extra->axskind) return False; */
280 if (e1_extra->size != e2_extra->size) return False;
281 /*
282 if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
283 return False;
284 */
285 return True;
286
287 case ValueErr:
288 if (e1_extra->size != e2_extra->size) return False;
289 return True;
290
njn43c799e2003-04-08 00:08:52 +0000291 case LeakErr:
292 VG_(skin_panic)("Shouldn't get LeakErr in SK_(eq_SkinError),\n"
293 "since it's handled with VG_(unique_error)()!");
294
njn5c004e42002-11-18 11:04:50 +0000295 default:
296 VG_(printf)("Error:\n unknown error code %d\n",
297 VG_(get_error_kind)(e1));
298 VG_(skin_panic)("unknown error code in SK_(eq_SkinError)");
299 }
300}
301
njn43c799e2003-04-08 00:08:52 +0000302void MAC_(pp_AddrInfo) ( Addr a, AddrInfo* ai )
njn5c004e42002-11-18 11:04:50 +0000303{
304 switch (ai->akind) {
305 case Stack:
306 VG_(message)(Vg_UserMsg,
307 " Address 0x%x is on thread %d's stack",
308 a, ai->stack_tid);
309 break;
310 case Unknown:
311 if (ai->maybe_gcc) {
312 VG_(message)(Vg_UserMsg,
313 " Address 0x%x is just below %%esp. Possibly a bug in GCC/G++",
314 a);
315 VG_(message)(Vg_UserMsg,
316 " v 2.96 or 3.0.X. To suppress, use: --workaround-gcc296-bugs=yes");
317 } else {
318 VG_(message)(Vg_UserMsg,
319 " Address 0x%x is not stack'd, malloc'd or free'd", a);
320 }
321 break;
sewardja81709d2002-12-28 12:55:48 +0000322 case Freed: case Mallocd: case UserG: {
njn5c004e42002-11-18 11:04:50 +0000323 UInt delta;
324 UChar* relative;
325 if (ai->rwoffset < 0) {
326 delta = (UInt)(- ai->rwoffset);
327 relative = "before";
328 } else if (ai->rwoffset >= ai->blksize) {
329 delta = ai->rwoffset - ai->blksize;
330 relative = "after";
331 } else {
332 delta = ai->rwoffset;
333 relative = "inside";
334 }
sewardja81709d2002-12-28 12:55:48 +0000335 VG_(message)(Vg_UserMsg,
336 " Address 0x%x is %d bytes %s a block of size %d %s",
337 a, delta, relative,
338 ai->blksize,
339 ai->akind==Mallocd ? "alloc'd"
340 : ai->akind==Freed ? "free'd"
341 : "client-defined");
njn5c004e42002-11-18 11:04:50 +0000342 VG_(pp_ExeContext)(ai->lastchange);
343 break;
344 }
345 default:
njn43c799e2003-04-08 00:08:52 +0000346 VG_(skin_panic)("MAC_(pp_AddrInfo)");
347 }
348}
349
350/* This prints out the message for the error types where Memcheck and
351 Addrcheck have identical messages */
352void MAC_(pp_shared_SkinError) ( Error* err )
353{
354 MAC_Error* err_extra = VG_(get_error_extra)(err);
355
356 switch (VG_(get_error_kind)(err)) {
357 case FreeErr:
358 VG_(message)(Vg_UserMsg,"Invalid free() / delete / delete[]");
359 /* fall through */
360 case FreeMismatchErr:
361 if (VG_(get_error_kind)(err) == FreeMismatchErr)
362 VG_(message)(Vg_UserMsg,
363 "Mismatched free() / delete / delete []");
364 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
365 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
366 break;
367
368 case LeakErr: {
369 /* Totally abusing the types of these spare fields... oh well. */
370 UInt n_this_record = (UInt)VG_(get_error_address)(err);
371 UInt n_total_records = (UInt)VG_(get_error_string) (err);
372
373 MAC_(pp_LeakError)(err_extra, n_this_record, n_total_records);
374 break;
375 }
376
377 default:
378 VG_(printf)("Error:\n unknown Memcheck/Addrcheck error code %d\n",
379 VG_(get_error_kind)(err));
380 VG_(skin_panic)("unknown error code in MAC_(pp_shared_SkinError)");
njn5c004e42002-11-18 11:04:50 +0000381 }
382}
383
384/*------------------------------------------------------------*/
385/*--- Recording errors ---*/
386/*------------------------------------------------------------*/
387
njn43c799e2003-04-08 00:08:52 +0000388/* Additional description function for describe_addr(); used by
389 MemCheck for user blocks, which Addrcheck doesn't support. */
390Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL;
391
392/* Return the first shadow chunk satisfying the predicate p. */
393static ShadowChunk* first_matching_freed_ShadowChunk ( Bool (*p)(ShadowChunk*) )
394{
395 ShadowChunk* sc;
396
397 /* No point looking through freed blocks if we're not keeping
398 them around for a while... */
399 for (sc = freed_list_start; sc != NULL; sc = VG_(get_sc_next)(sc))
400 if (p(sc))
401 return sc;
402
403 return NULL;
404}
405
406/* Describe an address as best you can, for error messages,
407 putting the result in ai. */
408static void describe_addr ( Addr a, AddrInfo* ai )
409{
410 ShadowChunk* sc;
411 ThreadId tid;
412
413 /* Nested functions, yeah. Need the lexical scoping of 'a'. */
414
415 /* Closure for searching thread stacks */
416 Bool addr_is_in_bounds(Addr stack_min, Addr stack_max)
417 {
418 return (stack_min <= a && a <= stack_max);
419 }
420 /* Closure for searching malloc'd and free'd lists */
421 Bool addr_is_in_block(ShadowChunk *sh_ch)
422 {
423 return VG_(addr_is_in_block) ( a, VG_(get_sc_data)(sh_ch),
424 VG_(get_sc_size)(sh_ch) );
425 }
426
427 /* Perhaps it's a user-def'd block ? (only check if requested, though) */
428 if (NULL != MAC_(describe_addr_supp)) {
429 if (MAC_(describe_addr_supp)( a, ai ))
430 return;
431 }
432 /* Perhaps it's on a thread's stack? */
433 tid = VG_(first_matching_thread_stack)(addr_is_in_bounds);
434 if (tid != VG_INVALID_THREADID) {
435 ai->akind = Stack;
436 ai->stack_tid = tid;
437 return;
438 }
439 /* Search for a recently freed block which might bracket it. */
440 sc = first_matching_freed_ShadowChunk(addr_is_in_block);
441 if (NULL != sc) {
442 ai->akind = Freed;
443 ai->blksize = VG_(get_sc_size)(sc);
444 ai->rwoffset = (Int)a - (Int)VG_(get_sc_data)(sc);
445 ai->lastchange = MAC_(get_where)(sc);
446 return;
447 }
448 /* Search for a currently malloc'd block which might bracket it. */
449 sc = VG_(first_matching_mallocd_ShadowChunk)(addr_is_in_block);
450 if (NULL != sc) {
451 ai->akind = Mallocd;
452 ai->blksize = VG_(get_sc_size)(sc);
453 ai->rwoffset = (Int)a - (Int)VG_(get_sc_data)(sc);
454 ai->lastchange = MAC_(get_where)(sc);
455 return;
456 }
457 /* Clueless ... */
458 ai->akind = Unknown;
459 return;
460}
461
462
njn5c004e42002-11-18 11:04:50 +0000463/* Is this address within some small distance below %ESP? Used only
464 for the --workaround-gcc296-bugs kludge. */
465static Bool is_just_below_ESP( Addr esp, Addr aa )
466{
467 if ((UInt)esp > (UInt)aa
468 && ((UInt)esp - (UInt)aa) <= VG_GCC296_BUG_STACK_SLOP)
469 return True;
470 else
471 return False;
472}
473
474/* This one called from generated code. */
475
njn43c799e2003-04-08 00:08:52 +0000476void MAC_(record_address_error) ( Addr a, Int size, Bool isWrite )
njn5c004e42002-11-18 11:04:50 +0000477{
njn43c799e2003-04-08 00:08:52 +0000478 MAC_Error err_extra;
479 Bool just_below_esp;
njn5c004e42002-11-18 11:04:50 +0000480
481 just_below_esp = is_just_below_ESP( VG_(get_stack_pointer)(), a );
482
483 /* If this is caused by an access immediately below %ESP, and the
484 user asks nicely, we just ignore it. */
njn43c799e2003-04-08 00:08:52 +0000485 if (MAC_(clo_workaround_gcc296_bugs) && just_below_esp)
njn5c004e42002-11-18 11:04:50 +0000486 return;
487
njn43c799e2003-04-08 00:08:52 +0000488 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000489 err_extra.axskind = isWrite ? WriteAxs : ReadAxs;
490 err_extra.size = size;
491 err_extra.addrinfo.akind = Undescribed;
492 err_extra.addrinfo.maybe_gcc = just_below_esp;
493 VG_(maybe_record_error)( NULL, AddrErr, a, /*s*/NULL, &err_extra );
494}
495
496/* These ones are called from non-generated code */
497
498/* This is for memory errors in pthread functions, as opposed to pthread API
499 errors which are found by the core. */
njn43c799e2003-04-08 00:08:52 +0000500void MAC_(record_core_mem_error) ( ThreadState* tst, Bool isWrite, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000501{
njn43c799e2003-04-08 00:08:52 +0000502 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000503
njn43c799e2003-04-08 00:08:52 +0000504 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000505 err_extra.isWrite = isWrite;
506 VG_(maybe_record_error)( tst, CoreMemErr, /*addr*/0, msg, &err_extra );
507}
508
njn43c799e2003-04-08 00:08:52 +0000509void MAC_(record_param_error) ( ThreadState* tst, Addr a, Bool isWrite,
njn5c004e42002-11-18 11:04:50 +0000510 Char* msg )
511{
njn43c799e2003-04-08 00:08:52 +0000512 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000513
514 sk_assert(NULL != tst);
njn43c799e2003-04-08 00:08:52 +0000515 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000516 err_extra.addrinfo.akind = Undescribed;
517 err_extra.isWrite = isWrite;
518 VG_(maybe_record_error)( tst, ParamErr, a, msg, &err_extra );
519}
520
njn43c799e2003-04-08 00:08:52 +0000521void MAC_(record_jump_error) ( ThreadState* tst, Addr a )
njn5c004e42002-11-18 11:04:50 +0000522{
njn43c799e2003-04-08 00:08:52 +0000523 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000524
525 sk_assert(NULL != tst);
526
njn43c799e2003-04-08 00:08:52 +0000527 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000528 err_extra.axskind = ExecAxs;
529 err_extra.addrinfo.akind = Undescribed;
530 VG_(maybe_record_error)( tst, AddrErr, a, /*s*/NULL, &err_extra );
531}
532
njn43c799e2003-04-08 00:08:52 +0000533void MAC_(record_free_error) ( ThreadState* tst, Addr a )
njn5c004e42002-11-18 11:04:50 +0000534{
njn43c799e2003-04-08 00:08:52 +0000535 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000536
537 sk_assert(NULL != tst);
538
njn43c799e2003-04-08 00:08:52 +0000539 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000540 err_extra.addrinfo.akind = Undescribed;
541 VG_(maybe_record_error)( tst, FreeErr, a, /*s*/NULL, &err_extra );
542}
543
njn43c799e2003-04-08 00:08:52 +0000544void MAC_(record_freemismatch_error) ( ThreadState* tst, Addr a )
njn5c004e42002-11-18 11:04:50 +0000545{
njn43c799e2003-04-08 00:08:52 +0000546 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000547
548 sk_assert(NULL != tst);
549
njn43c799e2003-04-08 00:08:52 +0000550 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000551 err_extra.addrinfo.akind = Undescribed;
552 VG_(maybe_record_error)( tst, FreeMismatchErr, a, /*s*/NULL, &err_extra );
553}
554
njn43c799e2003-04-08 00:08:52 +0000555/* Updates the copy with address info if necessary (but not for LeakErrs). */
556UInt SK_(update_extra)( Error* err )
557{
558 MAC_Error* extra;
559
560 /* Don't need to return the correct size -- LeakErrs are always shown with
561 VG_(unique_error)() so they're not copied anyway. */
562 if (LeakErr == VG_(get_error_kind)(err))
563 return 0;
564
565 extra = (MAC_Error*)VG_(get_error_extra)(err);
566
567 if (extra != NULL && Undescribed == extra->addrinfo.akind) {
568 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
569 }
570
571 return sizeof(MAC_Error);
572}
573
574
njn5c004e42002-11-18 11:04:50 +0000575/*------------------------------------------------------------*/
576/*--- Suppressions ---*/
577/*------------------------------------------------------------*/
578
njn43c799e2003-04-08 00:08:52 +0000579Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
580{
581 SuppKind skind;
582
583 if (VG_STREQ(name, "Param")) skind = ParamSupp;
584 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
585 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
586 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
587 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
588 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
589 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
590 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
591 else
592 return False;
593
594 VG_(set_supp_kind)(su, skind);
595 return True;
596}
597
njn5c004e42002-11-18 11:04:50 +0000598Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
599{
600 Bool eof;
601
602 if (VG_(get_supp_kind)(su) == ParamSupp) {
603 eof = VG_(get_line) ( fd, buf, nBuf );
604 if (eof) return False;
605 VG_(set_supp_string)(su, VG_(strdup)(buf));
606 }
607 return True;
608}
609
sewardj99aac972002-12-26 01:53:45 +0000610Bool SK_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000611{
njn43c799e2003-04-08 00:08:52 +0000612 UInt su_size;
613 MAC_Error* err_extra = VG_(get_error_extra)(err);
614 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000615
616 switch (VG_(get_supp_kind)(su)) {
617 case ParamSupp:
618 return (ekind == ParamErr
njn43c799e2003-04-08 00:08:52 +0000619 && VG_STREQ(VG_(get_error_string)(err),
620 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000621
622 case CoreMemSupp:
623 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000624 && VG_STREQ(VG_(get_error_string)(err),
625 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000626
627 case Value0Supp: su_size = 0; goto value_case;
628 case Value1Supp: su_size = 1; goto value_case;
629 case Value2Supp: su_size = 2; goto value_case;
630 case Value4Supp: su_size = 4; goto value_case;
631 case Value8Supp: su_size = 8; goto value_case;
632 value_case:
633 return (ekind == ValueErr && err_extra->size == su_size);
634
635 case Addr1Supp: su_size = 1; goto addr_case;
636 case Addr2Supp: su_size = 2; goto addr_case;
637 case Addr4Supp: su_size = 4; goto addr_case;
638 case Addr8Supp: su_size = 8; goto addr_case;
639 addr_case:
640 return (ekind == AddrErr && err_extra->size == su_size);
641
642 case FreeSupp:
643 return (ekind == FreeErr || ekind == FreeMismatchErr);
644
sewardj4a19e2f2002-12-26 11:50:21 +0000645 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000646 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000647
njn5c004e42002-11-18 11:04:50 +0000648 default:
649 VG_(printf)("Error:\n"
650 " unknown suppression type %d\n",
651 VG_(get_supp_kind)(su));
652 VG_(skin_panic)("unknown suppression type in "
653 "SK_(error_matches_suppression)");
654 }
655}
656
njn43c799e2003-04-08 00:08:52 +0000657Char* SK_(get_error_name) ( Error* err )
658{
659 Char* s;
660 switch (VG_(get_error_kind)(err)) {
661 case ParamErr: return "Param";
662 case UserErr: return NULL; /* Can't suppress User errors */
663 case FreeMismatchErr: return "Free";
664 case FreeErr: return "Free";
665 case AddrErr:
666 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
667 case 1: return "Addr1";
668 case 2: return "Addr2";
669 case 4: return "Addr4";
670 case 8: return "Addr8";
671 default: VG_(skin_panic)("unexpected size for Addr");
672 }
673
674 case ValueErr:
675 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
676 case 0: return "Cond";
677 case 1: return "Value1";
678 case 2: return "Value2";
679 case 4: return "Value4";
680 case 8: return "Value8";
681 default: VG_(skin_panic)("unexpected size for Value");
682 }
683 case CoreMemErr: return "CoreMem";
684 case LeakErr: return "Leak";
685 default: VG_(skin_panic)("get_error_name: unexpected type");
686 }
687 VG_(printf)(s);
688}
689
690void SK_(print_extra_suppression_info) ( Error* err )
691{
692 if (ParamErr == VG_(get_error_kind)(err)) {
693 VG_(printf)(" %s\n", VG_(get_error_string)(err));
694 }
695}
njn5c004e42002-11-18 11:04:50 +0000696
697/*------------------------------------------------------------*/
698/*--- Crude profiling machinery. ---*/
699/*------------------------------------------------------------*/
700
701/* Event index. If just the name of the fn is given, this means the
702 number of calls to the fn. Otherwise it is the specified event.
703 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
704 The rest are shared.
705
706 10 alloc_secondary_map
707
708 20 get_abit
709M 21 get_vbyte
710 22 set_abit
711M 23 set_vbyte
712 24 get_abits4_ALIGNED
713M 25 get_vbytes4_ALIGNED
714
715 30 set_address_range_perms
716 31 set_address_range_perms(lower byte loop)
717 32 set_address_range_perms(quadword loop)
718 33 set_address_range_perms(upper byte loop)
719
720 35 make_noaccess
721 36 make_writable
722 37 make_readable
723A 38 make_accessible
724
725 40 copy_address_range_state
726 41 copy_address_range_state(byte loop)
727 42 check_writable
728 43 check_writable(byte loop)
729 44 check_readable
730 45 check_readable(byte loop)
731 46 check_readable_asciiz
732 47 check_readable_asciiz(byte loop)
733A 48 check_accessible
734A 49 check_accessible(byte loop)
735
736 50 make_noaccess_aligned
737 51 make_writable_aligned
738
739M 60 helperc_LOADV4
740M 61 helperc_STOREV4
741M 62 helperc_LOADV2
742M 63 helperc_STOREV2
743M 64 helperc_LOADV1
744M 65 helperc_STOREV1
745
746A 66 helperc_ACCESS4
747A 67 helperc_ACCESS2
748A 68 helperc_ACCESS1
749
750M 70 rim_rd_V4_SLOWLY
751M 71 rim_wr_V4_SLOWLY
752M 72 rim_rd_V2_SLOWLY
753M 73 rim_wr_V2_SLOWLY
754M 74 rim_rd_V1_SLOWLY
755M 75 rim_wr_V1_SLOWLY
756
757A 76 ACCESS4_SLOWLY
758A 77 ACCESS2_SLOWLY
759A 78 ACCESS1_SLOWLY
760
761 80 fpu_read
762 81 fpu_read aligned 4
763 82 fpu_read aligned 8
764 83 fpu_read 2
765 84 fpu_read 10/28/108
766
767M 85 fpu_write
768M 86 fpu_write aligned 4
769M 87 fpu_write aligned 8
770M 88 fpu_write 2
771M 89 fpu_write 10/28/108
772
773 90 fpu_access
774 91 fpu_access aligned 4
775 92 fpu_access aligned 8
776 93 fpu_access 2
777 94 fpu_access 10/28/108
778
779 100 fpu_access_check_SLOWLY
780 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000781
782 110 new_mem_stack_4
783 111 new_mem_stack_8
784 112 new_mem_stack_12
785 113 new_mem_stack_16
786 114 new_mem_stack_32
787 115 new_mem_stack
788
789 120 die_mem_stack_4
790 121 die_mem_stack_8
791 122 die_mem_stack_12
792 123 die_mem_stack_16
793 124 die_mem_stack_32
794 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000795*/
796
njn43c799e2003-04-08 00:08:52 +0000797#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000798
njn43c799e2003-04-08 00:08:52 +0000799UInt MAC_(event_ctr)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000800
njn43c799e2003-04-08 00:08:52 +0000801void MAC_(init_prof_mem) ( void )
njn5c004e42002-11-18 11:04:50 +0000802{
803 Int i;
804 for (i = 0; i < N_PROF_EVENTS; i++)
njn43c799e2003-04-08 00:08:52 +0000805 MAC_(event_ctr)[i] = 0;
njn5c004e42002-11-18 11:04:50 +0000806}
807
njn43c799e2003-04-08 00:08:52 +0000808void MAC_(done_prof_mem) ( void )
njn5c004e42002-11-18 11:04:50 +0000809{
810 Int i;
811 for (i = 0; i < N_PROF_EVENTS; i++) {
812 if ((i % 10) == 0)
813 VG_(printf)("\n");
njn43c799e2003-04-08 00:08:52 +0000814 if (MAC_(event_ctr)[i] > 0)
815 VG_(printf)( "prof mem event %2d: %d\n", i, MAC_(event_ctr)[i] );
njn5c004e42002-11-18 11:04:50 +0000816 }
817 VG_(printf)("\n");
818}
819
820#else
821
njn43c799e2003-04-08 00:08:52 +0000822void MAC_(init_prof_mem) ( void ) { }
823void MAC_(done_prof_mem) ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000824
njn5c004e42002-11-18 11:04:50 +0000825#endif
826
827/*------------------------------------------------------------*/
njn5c004e42002-11-18 11:04:50 +0000828/*--- Syscall wrappers ---*/
829/*------------------------------------------------------------*/
830
831void* SK_(pre_syscall) ( ThreadId tid, UInt syscallno, Bool isBlocking )
832{
833 Int sane = SK_(cheap_sanity_check)();
834 return (void*)sane;
835}
836
837void SK_(post_syscall) ( ThreadId tid, UInt syscallno,
838 void* pre_result, Int res, Bool isBlocking )
839{
840 Int sane_before_call = (Int)pre_result;
841 Bool sane_after_call = SK_(cheap_sanity_check)();
842
843 if ((Int)sane_before_call && (!sane_after_call)) {
844 VG_(message)(Vg_DebugMsg, "post-syscall: ");
845 VG_(message)(Vg_DebugMsg,
846 "probable sanity check failure for syscall number %d\n",
847 syscallno );
848 VG_(skin_panic)("aborting due to the above ... bye!");
849 }
850}
851
njn5c004e42002-11-18 11:04:50 +0000852/*--------------------------------------------------------------------*/
njn43c799e2003-04-08 00:08:52 +0000853/*--- end mac_needs.c ---*/
njn5c004e42002-11-18 11:04:50 +0000854/*--------------------------------------------------------------------*/