blob: 1440645fe49e13f5eae626d2301c56321ef230b8 [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
njn3e884182003-04-15 13:03:23 +000090 return VG_(replacement_malloc_process_cmd_line_option)(arg);
njn5c004e42002-11-18 11:04:50 +000091
92 return True;
njn43c799e2003-04-08 00:08:52 +000093}
njn5c004e42002-11-18 11:04:50 +000094
njn3e884182003-04-15 13:03:23 +000095void MAC_(print_common_usage)(void)
njn43c799e2003-04-08 00:08:52 +000096{
njn3e884182003-04-15 13:03:23 +000097 VG_(printf)(
98" --partial-loads-ok=no|yes too hard to explain here; see manual [yes]\n"
99" --freelist-vol=<number> volume of freed blocks queue [1000000]\n"
100" --leak-check=no|yes search for memory leaks at exit? [no]\n"
101" --leak-resolution=low|med|high how much bt merging in leak check [low]\n"
102" --show-reachable=no|yes show reachable blocks in leak check? [no]\n"
103" --workaround-gcc296-bugs=no|yes self explanatory [no]\n"
104 );
105 VG_(replacement_malloc_print_usage)();
njn43c799e2003-04-08 00:08:52 +0000106}
107
njn3e884182003-04-15 13:03:23 +0000108void MAC_(print_common_debug_usage)(void)
njn43c799e2003-04-08 00:08:52 +0000109{
njn3e884182003-04-15 13:03:23 +0000110 VG_(replacement_malloc_print_debug_usage)();
njn5c004e42002-11-18 11:04:50 +0000111}
112
113/*------------------------------------------------------------*/
114/*--- Comparing and printing errors ---*/
115/*------------------------------------------------------------*/
116
117static __inline__
118void clear_AddrInfo ( AddrInfo* ai )
119{
120 ai->akind = Unknown;
121 ai->blksize = 0;
122 ai->rwoffset = 0;
123 ai->lastchange = NULL;
124 ai->stack_tid = VG_INVALID_THREADID;
125 ai->maybe_gcc = False;
126}
127
njn43c799e2003-04-08 00:08:52 +0000128void MAC_(clear_MAC_Error) ( MAC_Error* err_extra )
njn5c004e42002-11-18 11:04:50 +0000129{
130 err_extra->axskind = ReadAxs;
131 err_extra->size = 0;
132 clear_AddrInfo ( &err_extra->addrinfo );
133 err_extra->isWrite = False;
134}
135
136__attribute__ ((unused))
137static Bool eq_AddrInfo ( VgRes res, AddrInfo* ai1, AddrInfo* ai2 )
138{
139 if (ai1->akind != Undescribed
140 && ai2->akind != Undescribed
141 && ai1->akind != ai2->akind)
142 return False;
143 if (ai1->akind == Freed || ai1->akind == Mallocd) {
144 if (ai1->blksize != ai2->blksize)
145 return False;
146 if (!VG_(eq_ExeContext)(res, ai1->lastchange, ai2->lastchange))
147 return False;
148 }
149 return True;
150}
151
152/* Compare error contexts, to detect duplicates. Note that if they
153 are otherwise the same, the faulting addrs and associated rwoffsets
154 are allowed to be different. */
155
156Bool SK_(eq_SkinError) ( VgRes res, Error* e1, Error* e2 )
157{
njn43c799e2003-04-08 00:08:52 +0000158 MAC_Error* e1_extra = VG_(get_error_extra)(e1);
159 MAC_Error* e2_extra = VG_(get_error_extra)(e2);
njn7cc53a82002-11-19 16:19:32 +0000160
161 /* Guaranteed by calling function */
162 sk_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
njn5c004e42002-11-18 11:04:50 +0000163
164 switch (VG_(get_error_kind)(e1)) {
165 case CoreMemErr: {
166 Char *e1s, *e2s;
167 if (e1_extra->isWrite != e2_extra->isWrite) return False;
njn5c004e42002-11-18 11:04:50 +0000168 e1s = VG_(get_error_string)(e1);
169 e2s = VG_(get_error_string)(e2);
170 if (e1s == e2s) return True;
171 if (0 == VG_(strcmp)(e1s, e2s)) return True;
172 return False;
173 }
174
175 case UserErr:
176 case ParamErr:
177 if (e1_extra->isWrite != e2_extra->isWrite) return False;
178 if (VG_(get_error_kind)(e1) == ParamErr
179 && 0 != VG_(strcmp)(VG_(get_error_string)(e1),
180 VG_(get_error_string)(e2))) return False;
181 return True;
182
183 case FreeErr:
184 case FreeMismatchErr:
185 /* JRS 2002-Aug-26: comparing addrs seems overkill and can
186 cause excessive duplication of errors. Not even AddrErr
187 below does that. So don't compare either the .addr field
188 or the .addrinfo fields. */
189 /* if (e1->addr != e2->addr) return False; */
190 /* if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
191 return False;
192 */
193 return True;
194
195 case AddrErr:
196 /* if (e1_extra->axskind != e2_extra->axskind) return False; */
197 if (e1_extra->size != e2_extra->size) return False;
198 /*
199 if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
200 return False;
201 */
202 return True;
203
204 case ValueErr:
205 if (e1_extra->size != e2_extra->size) return False;
206 return True;
207
njn43c799e2003-04-08 00:08:52 +0000208 case LeakErr:
209 VG_(skin_panic)("Shouldn't get LeakErr in SK_(eq_SkinError),\n"
210 "since it's handled with VG_(unique_error)()!");
211
njn5c004e42002-11-18 11:04:50 +0000212 default:
213 VG_(printf)("Error:\n unknown error code %d\n",
214 VG_(get_error_kind)(e1));
215 VG_(skin_panic)("unknown error code in SK_(eq_SkinError)");
216 }
217}
218
njn43c799e2003-04-08 00:08:52 +0000219void MAC_(pp_AddrInfo) ( Addr a, AddrInfo* ai )
njn5c004e42002-11-18 11:04:50 +0000220{
221 switch (ai->akind) {
222 case Stack:
223 VG_(message)(Vg_UserMsg,
224 " Address 0x%x is on thread %d's stack",
225 a, ai->stack_tid);
226 break;
227 case Unknown:
228 if (ai->maybe_gcc) {
229 VG_(message)(Vg_UserMsg,
230 " Address 0x%x is just below %%esp. Possibly a bug in GCC/G++",
231 a);
232 VG_(message)(Vg_UserMsg,
233 " v 2.96 or 3.0.X. To suppress, use: --workaround-gcc296-bugs=yes");
234 } else {
235 VG_(message)(Vg_UserMsg,
236 " Address 0x%x is not stack'd, malloc'd or free'd", a);
237 }
238 break;
sewardja81709d2002-12-28 12:55:48 +0000239 case Freed: case Mallocd: case UserG: {
njn5c004e42002-11-18 11:04:50 +0000240 UInt delta;
241 UChar* relative;
242 if (ai->rwoffset < 0) {
243 delta = (UInt)(- ai->rwoffset);
244 relative = "before";
245 } else if (ai->rwoffset >= ai->blksize) {
246 delta = ai->rwoffset - ai->blksize;
247 relative = "after";
248 } else {
249 delta = ai->rwoffset;
250 relative = "inside";
251 }
sewardja81709d2002-12-28 12:55:48 +0000252 VG_(message)(Vg_UserMsg,
253 " Address 0x%x is %d bytes %s a block of size %d %s",
254 a, delta, relative,
255 ai->blksize,
256 ai->akind==Mallocd ? "alloc'd"
257 : ai->akind==Freed ? "free'd"
258 : "client-defined");
njn5c004e42002-11-18 11:04:50 +0000259 VG_(pp_ExeContext)(ai->lastchange);
260 break;
261 }
262 default:
njn43c799e2003-04-08 00:08:52 +0000263 VG_(skin_panic)("MAC_(pp_AddrInfo)");
264 }
265}
266
267/* This prints out the message for the error types where Memcheck and
268 Addrcheck have identical messages */
269void MAC_(pp_shared_SkinError) ( Error* err )
270{
271 MAC_Error* err_extra = VG_(get_error_extra)(err);
272
273 switch (VG_(get_error_kind)(err)) {
274 case FreeErr:
275 VG_(message)(Vg_UserMsg,"Invalid free() / delete / delete[]");
276 /* fall through */
277 case FreeMismatchErr:
278 if (VG_(get_error_kind)(err) == FreeMismatchErr)
279 VG_(message)(Vg_UserMsg,
280 "Mismatched free() / delete / delete []");
281 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
282 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
283 break;
284
285 case LeakErr: {
286 /* Totally abusing the types of these spare fields... oh well. */
287 UInt n_this_record = (UInt)VG_(get_error_address)(err);
288 UInt n_total_records = (UInt)VG_(get_error_string) (err);
289
290 MAC_(pp_LeakError)(err_extra, n_this_record, n_total_records);
291 break;
292 }
293
294 default:
295 VG_(printf)("Error:\n unknown Memcheck/Addrcheck error code %d\n",
296 VG_(get_error_kind)(err));
297 VG_(skin_panic)("unknown error code in MAC_(pp_shared_SkinError)");
njn5c004e42002-11-18 11:04:50 +0000298 }
299}
300
301/*------------------------------------------------------------*/
302/*--- Recording errors ---*/
303/*------------------------------------------------------------*/
304
njn43c799e2003-04-08 00:08:52 +0000305/* Additional description function for describe_addr(); used by
306 MemCheck for user blocks, which Addrcheck doesn't support. */
307Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL;
308
njn43c799e2003-04-08 00:08:52 +0000309/* Describe an address as best you can, for error messages,
310 putting the result in ai. */
311static void describe_addr ( Addr a, AddrInfo* ai )
312{
njn3e884182003-04-15 13:03:23 +0000313 MAC_Chunk* sc;
314 ThreadId tid;
njn43c799e2003-04-08 00:08:52 +0000315
316 /* Nested functions, yeah. Need the lexical scoping of 'a'. */
njn3e884182003-04-15 13:03:23 +0000317
njn43c799e2003-04-08 00:08:52 +0000318 /* Closure for searching thread stacks */
319 Bool addr_is_in_bounds(Addr stack_min, Addr stack_max)
320 {
321 return (stack_min <= a && a <= stack_max);
322 }
njn3e884182003-04-15 13:03:23 +0000323 /* Closure for searching free'd list */
324 Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc)
njn43c799e2003-04-08 00:08:52 +0000325 {
njn3e884182003-04-15 13:03:23 +0000326 return VG_(addr_is_in_block)( a, mc->data, mc->size );
327 }
328 /* Closure for searching malloc'd lists */
329 Bool addr_is_in_HashNode(VgHashNode* sh_ch)
330 {
331 return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch );
njn43c799e2003-04-08 00:08:52 +0000332 }
333
334 /* Perhaps it's a user-def'd block ? (only check if requested, though) */
335 if (NULL != MAC_(describe_addr_supp)) {
336 if (MAC_(describe_addr_supp)( a, ai ))
337 return;
338 }
339 /* Perhaps it's on a thread's stack? */
340 tid = VG_(first_matching_thread_stack)(addr_is_in_bounds);
341 if (tid != VG_INVALID_THREADID) {
342 ai->akind = Stack;
343 ai->stack_tid = tid;
344 return;
345 }
346 /* Search for a recently freed block which might bracket it. */
njn3e884182003-04-15 13:03:23 +0000347 sc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk);
348 if (NULL != sc) {
njn43c799e2003-04-08 00:08:52 +0000349 ai->akind = Freed;
njn3e884182003-04-15 13:03:23 +0000350 ai->blksize = sc->size;
351 ai->rwoffset = (Int)a - (Int)sc->data;
352 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000353 return;
354 }
355 /* Search for a currently malloc'd block which might bracket it. */
njn3e884182003-04-15 13:03:23 +0000356 sc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode);
njn43c799e2003-04-08 00:08:52 +0000357 if (NULL != sc) {
358 ai->akind = Mallocd;
njn3e884182003-04-15 13:03:23 +0000359 ai->blksize = sc->size;
360 ai->rwoffset = (Int)(a) - (Int)sc->data;
361 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000362 return;
363 }
364 /* Clueless ... */
365 ai->akind = Unknown;
366 return;
367}
368
njn5c004e42002-11-18 11:04:50 +0000369/* Is this address within some small distance below %ESP? Used only
370 for the --workaround-gcc296-bugs kludge. */
371static Bool is_just_below_ESP( Addr esp, Addr aa )
372{
373 if ((UInt)esp > (UInt)aa
374 && ((UInt)esp - (UInt)aa) <= VG_GCC296_BUG_STACK_SLOP)
375 return True;
376 else
377 return False;
378}
379
380/* This one called from generated code. */
381
njn43c799e2003-04-08 00:08:52 +0000382void MAC_(record_address_error) ( Addr a, Int size, Bool isWrite )
njn5c004e42002-11-18 11:04:50 +0000383{
njn43c799e2003-04-08 00:08:52 +0000384 MAC_Error err_extra;
385 Bool just_below_esp;
njn5c004e42002-11-18 11:04:50 +0000386
387 just_below_esp = is_just_below_ESP( VG_(get_stack_pointer)(), a );
388
389 /* If this is caused by an access immediately below %ESP, and the
390 user asks nicely, we just ignore it. */
njn43c799e2003-04-08 00:08:52 +0000391 if (MAC_(clo_workaround_gcc296_bugs) && just_below_esp)
njn5c004e42002-11-18 11:04:50 +0000392 return;
393
njn43c799e2003-04-08 00:08:52 +0000394 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000395 err_extra.axskind = isWrite ? WriteAxs : ReadAxs;
396 err_extra.size = size;
397 err_extra.addrinfo.akind = Undescribed;
398 err_extra.addrinfo.maybe_gcc = just_below_esp;
399 VG_(maybe_record_error)( NULL, AddrErr, a, /*s*/NULL, &err_extra );
400}
401
402/* These ones are called from non-generated code */
403
404/* This is for memory errors in pthread functions, as opposed to pthread API
405 errors which are found by the core. */
njn43c799e2003-04-08 00:08:52 +0000406void MAC_(record_core_mem_error) ( ThreadState* tst, Bool isWrite, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000407{
njn43c799e2003-04-08 00:08:52 +0000408 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000409
njn43c799e2003-04-08 00:08:52 +0000410 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000411 err_extra.isWrite = isWrite;
412 VG_(maybe_record_error)( tst, CoreMemErr, /*addr*/0, msg, &err_extra );
413}
414
njn43c799e2003-04-08 00:08:52 +0000415void MAC_(record_param_error) ( ThreadState* tst, Addr a, Bool isWrite,
njn5c004e42002-11-18 11:04:50 +0000416 Char* msg )
417{
njn43c799e2003-04-08 00:08:52 +0000418 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000419
420 sk_assert(NULL != tst);
njn43c799e2003-04-08 00:08:52 +0000421 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000422 err_extra.addrinfo.akind = Undescribed;
423 err_extra.isWrite = isWrite;
424 VG_(maybe_record_error)( tst, ParamErr, a, msg, &err_extra );
425}
426
njn43c799e2003-04-08 00:08:52 +0000427void MAC_(record_jump_error) ( ThreadState* tst, Addr a )
njn5c004e42002-11-18 11:04:50 +0000428{
njn43c799e2003-04-08 00:08:52 +0000429 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000430
431 sk_assert(NULL != tst);
432
njn43c799e2003-04-08 00:08:52 +0000433 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000434 err_extra.axskind = ExecAxs;
435 err_extra.addrinfo.akind = Undescribed;
436 VG_(maybe_record_error)( tst, AddrErr, a, /*s*/NULL, &err_extra );
437}
438
njn43c799e2003-04-08 00:08:52 +0000439void MAC_(record_free_error) ( ThreadState* tst, Addr a )
njn5c004e42002-11-18 11:04:50 +0000440{
njn43c799e2003-04-08 00:08:52 +0000441 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000442
443 sk_assert(NULL != tst);
444
njn43c799e2003-04-08 00:08:52 +0000445 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000446 err_extra.addrinfo.akind = Undescribed;
447 VG_(maybe_record_error)( tst, FreeErr, a, /*s*/NULL, &err_extra );
448}
449
njn43c799e2003-04-08 00:08:52 +0000450void MAC_(record_freemismatch_error) ( ThreadState* tst, Addr a )
njn5c004e42002-11-18 11:04:50 +0000451{
njn43c799e2003-04-08 00:08:52 +0000452 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000453
454 sk_assert(NULL != tst);
455
njn43c799e2003-04-08 00:08:52 +0000456 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000457 err_extra.addrinfo.akind = Undescribed;
458 VG_(maybe_record_error)( tst, FreeMismatchErr, a, /*s*/NULL, &err_extra );
459}
460
njn43c799e2003-04-08 00:08:52 +0000461/* Updates the copy with address info if necessary (but not for LeakErrs). */
462UInt SK_(update_extra)( Error* err )
463{
464 MAC_Error* extra;
465
466 /* Don't need to return the correct size -- LeakErrs are always shown with
467 VG_(unique_error)() so they're not copied anyway. */
468 if (LeakErr == VG_(get_error_kind)(err))
469 return 0;
470
471 extra = (MAC_Error*)VG_(get_error_extra)(err);
472
473 if (extra != NULL && Undescribed == extra->addrinfo.akind) {
474 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
475 }
476
477 return sizeof(MAC_Error);
478}
479
480
njn5c004e42002-11-18 11:04:50 +0000481/*------------------------------------------------------------*/
482/*--- Suppressions ---*/
483/*------------------------------------------------------------*/
484
njn43c799e2003-04-08 00:08:52 +0000485Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
486{
487 SuppKind skind;
488
489 if (VG_STREQ(name, "Param")) skind = ParamSupp;
490 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
491 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
492 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
493 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
494 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
495 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
496 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
497 else
498 return False;
499
500 VG_(set_supp_kind)(su, skind);
501 return True;
502}
503
njn5c004e42002-11-18 11:04:50 +0000504Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
505{
506 Bool eof;
507
508 if (VG_(get_supp_kind)(su) == ParamSupp) {
509 eof = VG_(get_line) ( fd, buf, nBuf );
510 if (eof) return False;
511 VG_(set_supp_string)(su, VG_(strdup)(buf));
512 }
513 return True;
514}
515
sewardj99aac972002-12-26 01:53:45 +0000516Bool SK_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000517{
njn43c799e2003-04-08 00:08:52 +0000518 UInt su_size;
519 MAC_Error* err_extra = VG_(get_error_extra)(err);
520 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000521
522 switch (VG_(get_supp_kind)(su)) {
523 case ParamSupp:
524 return (ekind == ParamErr
njn43c799e2003-04-08 00:08:52 +0000525 && VG_STREQ(VG_(get_error_string)(err),
526 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000527
528 case CoreMemSupp:
529 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000530 && VG_STREQ(VG_(get_error_string)(err),
531 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000532
533 case Value0Supp: su_size = 0; goto value_case;
534 case Value1Supp: su_size = 1; goto value_case;
535 case Value2Supp: su_size = 2; goto value_case;
536 case Value4Supp: su_size = 4; goto value_case;
537 case Value8Supp: su_size = 8; goto value_case;
538 value_case:
539 return (ekind == ValueErr && err_extra->size == su_size);
540
541 case Addr1Supp: su_size = 1; goto addr_case;
542 case Addr2Supp: su_size = 2; goto addr_case;
543 case Addr4Supp: su_size = 4; goto addr_case;
544 case Addr8Supp: su_size = 8; goto addr_case;
545 addr_case:
546 return (ekind == AddrErr && err_extra->size == su_size);
547
548 case FreeSupp:
549 return (ekind == FreeErr || ekind == FreeMismatchErr);
550
sewardj4a19e2f2002-12-26 11:50:21 +0000551 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000552 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000553
njn5c004e42002-11-18 11:04:50 +0000554 default:
555 VG_(printf)("Error:\n"
556 " unknown suppression type %d\n",
557 VG_(get_supp_kind)(su));
558 VG_(skin_panic)("unknown suppression type in "
559 "SK_(error_matches_suppression)");
560 }
561}
562
njn43c799e2003-04-08 00:08:52 +0000563Char* SK_(get_error_name) ( Error* err )
564{
565 Char* s;
566 switch (VG_(get_error_kind)(err)) {
567 case ParamErr: return "Param";
568 case UserErr: return NULL; /* Can't suppress User errors */
569 case FreeMismatchErr: return "Free";
570 case FreeErr: return "Free";
571 case AddrErr:
572 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
573 case 1: return "Addr1";
574 case 2: return "Addr2";
575 case 4: return "Addr4";
576 case 8: return "Addr8";
577 default: VG_(skin_panic)("unexpected size for Addr");
578 }
579
580 case ValueErr:
581 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
582 case 0: return "Cond";
583 case 1: return "Value1";
584 case 2: return "Value2";
585 case 4: return "Value4";
586 case 8: return "Value8";
587 default: VG_(skin_panic)("unexpected size for Value");
588 }
589 case CoreMemErr: return "CoreMem";
590 case LeakErr: return "Leak";
591 default: VG_(skin_panic)("get_error_name: unexpected type");
592 }
593 VG_(printf)(s);
594}
595
596void SK_(print_extra_suppression_info) ( Error* err )
597{
598 if (ParamErr == VG_(get_error_kind)(err)) {
599 VG_(printf)(" %s\n", VG_(get_error_string)(err));
600 }
601}
njn5c004e42002-11-18 11:04:50 +0000602
603/*------------------------------------------------------------*/
604/*--- Crude profiling machinery. ---*/
605/*------------------------------------------------------------*/
606
607/* Event index. If just the name of the fn is given, this means the
608 number of calls to the fn. Otherwise it is the specified event.
609 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
610 The rest are shared.
611
612 10 alloc_secondary_map
613
614 20 get_abit
615M 21 get_vbyte
616 22 set_abit
617M 23 set_vbyte
618 24 get_abits4_ALIGNED
619M 25 get_vbytes4_ALIGNED
620
621 30 set_address_range_perms
622 31 set_address_range_perms(lower byte loop)
623 32 set_address_range_perms(quadword loop)
624 33 set_address_range_perms(upper byte loop)
625
626 35 make_noaccess
627 36 make_writable
628 37 make_readable
629A 38 make_accessible
630
631 40 copy_address_range_state
632 41 copy_address_range_state(byte loop)
633 42 check_writable
634 43 check_writable(byte loop)
635 44 check_readable
636 45 check_readable(byte loop)
637 46 check_readable_asciiz
638 47 check_readable_asciiz(byte loop)
639A 48 check_accessible
640A 49 check_accessible(byte loop)
641
642 50 make_noaccess_aligned
643 51 make_writable_aligned
644
645M 60 helperc_LOADV4
646M 61 helperc_STOREV4
647M 62 helperc_LOADV2
648M 63 helperc_STOREV2
649M 64 helperc_LOADV1
650M 65 helperc_STOREV1
651
652A 66 helperc_ACCESS4
653A 67 helperc_ACCESS2
654A 68 helperc_ACCESS1
655
656M 70 rim_rd_V4_SLOWLY
657M 71 rim_wr_V4_SLOWLY
658M 72 rim_rd_V2_SLOWLY
659M 73 rim_wr_V2_SLOWLY
660M 74 rim_rd_V1_SLOWLY
661M 75 rim_wr_V1_SLOWLY
662
663A 76 ACCESS4_SLOWLY
664A 77 ACCESS2_SLOWLY
665A 78 ACCESS1_SLOWLY
666
667 80 fpu_read
668 81 fpu_read aligned 4
669 82 fpu_read aligned 8
670 83 fpu_read 2
671 84 fpu_read 10/28/108
672
673M 85 fpu_write
674M 86 fpu_write aligned 4
675M 87 fpu_write aligned 8
676M 88 fpu_write 2
677M 89 fpu_write 10/28/108
678
679 90 fpu_access
680 91 fpu_access aligned 4
681 92 fpu_access aligned 8
682 93 fpu_access 2
683 94 fpu_access 10/28/108
684
685 100 fpu_access_check_SLOWLY
686 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000687
688 110 new_mem_stack_4
689 111 new_mem_stack_8
690 112 new_mem_stack_12
691 113 new_mem_stack_16
692 114 new_mem_stack_32
693 115 new_mem_stack
694
695 120 die_mem_stack_4
696 121 die_mem_stack_8
697 122 die_mem_stack_12
698 123 die_mem_stack_16
699 124 die_mem_stack_32
700 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000701*/
702
njn43c799e2003-04-08 00:08:52 +0000703#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000704
njn43c799e2003-04-08 00:08:52 +0000705UInt MAC_(event_ctr)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000706
njnb4aee052003-04-15 14:09:58 +0000707static void init_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000708{
709 Int i;
710 for (i = 0; i < N_PROF_EVENTS; i++)
njn43c799e2003-04-08 00:08:52 +0000711 MAC_(event_ctr)[i] = 0;
njn5c004e42002-11-18 11:04:50 +0000712}
713
njnb4aee052003-04-15 14:09:58 +0000714static void done_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000715{
716 Int i;
717 for (i = 0; i < N_PROF_EVENTS; i++) {
718 if ((i % 10) == 0)
719 VG_(printf)("\n");
njn43c799e2003-04-08 00:08:52 +0000720 if (MAC_(event_ctr)[i] > 0)
721 VG_(printf)( "prof mem event %2d: %d\n", i, MAC_(event_ctr)[i] );
njn5c004e42002-11-18 11:04:50 +0000722 }
723 VG_(printf)("\n");
724}
725
726#else
727
njnb4aee052003-04-15 14:09:58 +0000728static void init_prof_mem ( void ) { }
729static void done_prof_mem ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000730
njn5c004e42002-11-18 11:04:50 +0000731#endif
732
733/*------------------------------------------------------------*/
njn3e884182003-04-15 13:03:23 +0000734/*--- Common initialisation + finalisation ---*/
735/*------------------------------------------------------------*/
736
737void MAC_(common_pre_clo_init)(void)
738{
739 MAC_(malloc_list) = VG_(HT_construct)();
740 init_prof_mem();
741}
742
743void MAC_(common_fini)(void (*leak_check)(void))
744{
745 MAC_(print_malloc_stats)();
746
747 if (VG_(clo_verbosity) == 1) {
748 if (!MAC_(clo_leak_check))
749 VG_(message)(Vg_UserMsg,
750 "For a detailed leak analysis, rerun with: --leak-check=yes");
751
752 VG_(message)(Vg_UserMsg,
753 "For counts of detected errors, rerun with: -v");
754 }
755 if (MAC_(clo_leak_check)) leak_check();
756
757 done_prof_mem();
758}
759
760/*------------------------------------------------------------*/
njn5c004e42002-11-18 11:04:50 +0000761/*--- Syscall wrappers ---*/
762/*------------------------------------------------------------*/
763
764void* SK_(pre_syscall) ( ThreadId tid, UInt syscallno, Bool isBlocking )
765{
766 Int sane = SK_(cheap_sanity_check)();
767 return (void*)sane;
768}
769
770void SK_(post_syscall) ( ThreadId tid, UInt syscallno,
771 void* pre_result, Int res, Bool isBlocking )
772{
773 Int sane_before_call = (Int)pre_result;
774 Bool sane_after_call = SK_(cheap_sanity_check)();
775
776 if ((Int)sane_before_call && (!sane_after_call)) {
777 VG_(message)(Vg_DebugMsg, "post-syscall: ");
778 VG_(message)(Vg_DebugMsg,
779 "probable sanity check failure for syscall number %d\n",
780 syscallno );
781 VG_(skin_panic)("aborting due to the above ... bye!");
782 }
783}
784
njn5c004e42002-11-18 11:04:50 +0000785/*--------------------------------------------------------------------*/
njn43c799e2003-04-08 00:08:52 +0000786/*--- end mac_needs.c ---*/
njn5c004e42002-11-18 11:04:50 +0000787/*--------------------------------------------------------------------*/