blob: bd0f5c6e891bfa2131bb5791508ceb14cbf9fcc6 [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
njn0e1b5142003-04-15 14:58:06 +000012 Copyright (C) 2000-2003 Julian Seward
njn5c004e42002-11-18 11:04:50 +000013 jseward@acm.org
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file COPYING.
31*/
32
33
njn43c799e2003-04-08 00:08:52 +000034#include "mac_shared.h"
njn5c004e42002-11-18 11:04:50 +000035
njn47363ab2003-04-21 13:24:40 +000036#include "memcheck.h" /* for VG_USERREQ__* */
37
njn5c004e42002-11-18 11:04:50 +000038/*------------------------------------------------------------*/
39/*--- Defns ---*/
40/*------------------------------------------------------------*/
41
42/* These many bytes below %ESP are considered addressible if we're
43 doing the --workaround-gcc296-bugs hack. */
44#define VG_GCC296_BUG_STACK_SLOP 1024
45
46/*------------------------------------------------------------*/
47/*--- Command line options ---*/
48/*------------------------------------------------------------*/
49
njn43c799e2003-04-08 00:08:52 +000050Bool MAC_(clo_partial_loads_ok) = True;
51Int MAC_(clo_freelist_vol) = 1000000;
52Bool MAC_(clo_leak_check) = False;
53VgRes MAC_(clo_leak_resolution) = Vg_LowRes;
54Bool MAC_(clo_show_reachable) = False;
55Bool MAC_(clo_workaround_gcc296_bugs) = False;
njn5c004e42002-11-18 11:04:50 +000056
njn43c799e2003-04-08 00:08:52 +000057Bool MAC_(process_common_cmd_line_option)(Char* arg)
njn5c004e42002-11-18 11:04:50 +000058{
njn43c799e2003-04-08 00:08:52 +000059 if (VG_CLO_STREQ(arg, "--partial-loads-ok=yes"))
60 MAC_(clo_partial_loads_ok) = True;
61 else if (VG_CLO_STREQ(arg, "--partial-loads-ok=no"))
62 MAC_(clo_partial_loads_ok) = False;
njn5c004e42002-11-18 11:04:50 +000063
njn43c799e2003-04-08 00:08:52 +000064 else if (VG_CLO_STREQN(15, arg, "--freelist-vol=")) {
65 MAC_(clo_freelist_vol) = (Int)VG_(atoll)(&arg[15]);
66 if (MAC_(clo_freelist_vol) < 0) MAC_(clo_freelist_vol) = 0;
njn5c004e42002-11-18 11:04:50 +000067 }
68
njn43c799e2003-04-08 00:08:52 +000069 else if (VG_CLO_STREQ(arg, "--leak-check=yes"))
70 MAC_(clo_leak_check) = True;
71 else if (VG_CLO_STREQ(arg, "--leak-check=no"))
72 MAC_(clo_leak_check) = False;
njn5c004e42002-11-18 11:04:50 +000073
njn43c799e2003-04-08 00:08:52 +000074 else if (VG_CLO_STREQ(arg, "--leak-resolution=low"))
75 MAC_(clo_leak_resolution) = Vg_LowRes;
76 else if (VG_CLO_STREQ(arg, "--leak-resolution=med"))
77 MAC_(clo_leak_resolution) = Vg_MedRes;
78 else if (VG_CLO_STREQ(arg, "--leak-resolution=high"))
79 MAC_(clo_leak_resolution) = Vg_HighRes;
njn5c004e42002-11-18 11:04:50 +000080
njn43c799e2003-04-08 00:08:52 +000081 else if (VG_CLO_STREQ(arg, "--show-reachable=yes"))
82 MAC_(clo_show_reachable) = True;
83 else if (VG_CLO_STREQ(arg, "--show-reachable=no"))
84 MAC_(clo_show_reachable) = False;
njn5c004e42002-11-18 11:04:50 +000085
njn43c799e2003-04-08 00:08:52 +000086 else if (VG_CLO_STREQ(arg, "--workaround-gcc296-bugs=yes"))
87 MAC_(clo_workaround_gcc296_bugs) = True;
88 else if (VG_CLO_STREQ(arg, "--workaround-gcc296-bugs=no"))
89 MAC_(clo_workaround_gcc296_bugs) = False;
njn5c004e42002-11-18 11:04:50 +000090
91 else
njn3e884182003-04-15 13:03:23 +000092 return VG_(replacement_malloc_process_cmd_line_option)(arg);
njn5c004e42002-11-18 11:04:50 +000093
94 return True;
njn43c799e2003-04-08 00:08:52 +000095}
njn5c004e42002-11-18 11:04:50 +000096
njn3e884182003-04-15 13:03:23 +000097void MAC_(print_common_usage)(void)
njn43c799e2003-04-08 00:08:52 +000098{
njn3e884182003-04-15 13:03:23 +000099 VG_(printf)(
100" --partial-loads-ok=no|yes too hard to explain here; see manual [yes]\n"
101" --freelist-vol=<number> volume of freed blocks queue [1000000]\n"
102" --leak-check=no|yes search for memory leaks at exit? [no]\n"
103" --leak-resolution=low|med|high how much bt merging in leak check [low]\n"
104" --show-reachable=no|yes show reachable blocks in leak check? [no]\n"
105" --workaround-gcc296-bugs=no|yes self explanatory [no]\n"
106 );
107 VG_(replacement_malloc_print_usage)();
njn43c799e2003-04-08 00:08:52 +0000108}
109
njn3e884182003-04-15 13:03:23 +0000110void MAC_(print_common_debug_usage)(void)
njn43c799e2003-04-08 00:08:52 +0000111{
njn3e884182003-04-15 13:03:23 +0000112 VG_(replacement_malloc_print_debug_usage)();
njn5c004e42002-11-18 11:04:50 +0000113}
114
115/*------------------------------------------------------------*/
116/*--- Comparing and printing errors ---*/
117/*------------------------------------------------------------*/
118
119static __inline__
120void clear_AddrInfo ( AddrInfo* ai )
121{
122 ai->akind = Unknown;
123 ai->blksize = 0;
124 ai->rwoffset = 0;
125 ai->lastchange = NULL;
126 ai->stack_tid = VG_INVALID_THREADID;
127 ai->maybe_gcc = False;
128}
129
njn43c799e2003-04-08 00:08:52 +0000130void MAC_(clear_MAC_Error) ( MAC_Error* err_extra )
njn5c004e42002-11-18 11:04:50 +0000131{
132 err_extra->axskind = ReadAxs;
133 err_extra->size = 0;
134 clear_AddrInfo ( &err_extra->addrinfo );
135 err_extra->isWrite = False;
136}
137
138__attribute__ ((unused))
139static Bool eq_AddrInfo ( VgRes res, AddrInfo* ai1, AddrInfo* ai2 )
140{
141 if (ai1->akind != Undescribed
142 && ai2->akind != Undescribed
143 && ai1->akind != ai2->akind)
144 return False;
145 if (ai1->akind == Freed || ai1->akind == Mallocd) {
146 if (ai1->blksize != ai2->blksize)
147 return False;
148 if (!VG_(eq_ExeContext)(res, ai1->lastchange, ai2->lastchange))
149 return False;
150 }
151 return True;
152}
153
154/* Compare error contexts, to detect duplicates. Note that if they
155 are otherwise the same, the faulting addrs and associated rwoffsets
156 are allowed to be different. */
157
158Bool SK_(eq_SkinError) ( VgRes res, Error* e1, Error* e2 )
159{
njn43c799e2003-04-08 00:08:52 +0000160 MAC_Error* e1_extra = VG_(get_error_extra)(e1);
161 MAC_Error* e2_extra = VG_(get_error_extra)(e2);
njn7cc53a82002-11-19 16:19:32 +0000162
163 /* Guaranteed by calling function */
164 sk_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
njn5c004e42002-11-18 11:04:50 +0000165
166 switch (VG_(get_error_kind)(e1)) {
167 case CoreMemErr: {
168 Char *e1s, *e2s;
169 if (e1_extra->isWrite != e2_extra->isWrite) return False;
njn5c004e42002-11-18 11:04:50 +0000170 e1s = VG_(get_error_string)(e1);
171 e2s = VG_(get_error_string)(e2);
172 if (e1s == e2s) return True;
173 if (0 == VG_(strcmp)(e1s, e2s)) return True;
174 return False;
175 }
176
177 case UserErr:
178 case ParamErr:
179 if (e1_extra->isWrite != e2_extra->isWrite) return False;
180 if (VG_(get_error_kind)(e1) == ParamErr
181 && 0 != VG_(strcmp)(VG_(get_error_string)(e1),
182 VG_(get_error_string)(e2))) return False;
183 return True;
184
185 case FreeErr:
186 case FreeMismatchErr:
187 /* JRS 2002-Aug-26: comparing addrs seems overkill and can
188 cause excessive duplication of errors. Not even AddrErr
189 below does that. So don't compare either the .addr field
190 or the .addrinfo fields. */
191 /* if (e1->addr != e2->addr) return False; */
192 /* if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
193 return False;
194 */
195 return True;
196
197 case AddrErr:
198 /* if (e1_extra->axskind != e2_extra->axskind) return False; */
199 if (e1_extra->size != e2_extra->size) return False;
200 /*
201 if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
202 return False;
203 */
204 return True;
205
206 case ValueErr:
207 if (e1_extra->size != e2_extra->size) return False;
208 return True;
209
njn43c799e2003-04-08 00:08:52 +0000210 case LeakErr:
211 VG_(skin_panic)("Shouldn't get LeakErr in SK_(eq_SkinError),\n"
212 "since it's handled with VG_(unique_error)()!");
213
njn5c004e42002-11-18 11:04:50 +0000214 default:
215 VG_(printf)("Error:\n unknown error code %d\n",
216 VG_(get_error_kind)(e1));
217 VG_(skin_panic)("unknown error code in SK_(eq_SkinError)");
218 }
219}
220
njn43c799e2003-04-08 00:08:52 +0000221void MAC_(pp_AddrInfo) ( Addr a, AddrInfo* ai )
njn5c004e42002-11-18 11:04:50 +0000222{
223 switch (ai->akind) {
224 case Stack:
225 VG_(message)(Vg_UserMsg,
226 " Address 0x%x is on thread %d's stack",
227 a, ai->stack_tid);
228 break;
229 case Unknown:
230 if (ai->maybe_gcc) {
231 VG_(message)(Vg_UserMsg,
232 " Address 0x%x is just below %%esp. Possibly a bug in GCC/G++",
233 a);
234 VG_(message)(Vg_UserMsg,
235 " v 2.96 or 3.0.X. To suppress, use: --workaround-gcc296-bugs=yes");
236 } else {
237 VG_(message)(Vg_UserMsg,
238 " Address 0x%x is not stack'd, malloc'd or free'd", a);
239 }
240 break;
sewardja81709d2002-12-28 12:55:48 +0000241 case Freed: case Mallocd: case UserG: {
njn5c004e42002-11-18 11:04:50 +0000242 UInt delta;
243 UChar* relative;
244 if (ai->rwoffset < 0) {
245 delta = (UInt)(- ai->rwoffset);
246 relative = "before";
247 } else if (ai->rwoffset >= ai->blksize) {
248 delta = ai->rwoffset - ai->blksize;
249 relative = "after";
250 } else {
251 delta = ai->rwoffset;
252 relative = "inside";
253 }
sewardja81709d2002-12-28 12:55:48 +0000254 VG_(message)(Vg_UserMsg,
255 " Address 0x%x is %d bytes %s a block of size %d %s",
256 a, delta, relative,
257 ai->blksize,
258 ai->akind==Mallocd ? "alloc'd"
259 : ai->akind==Freed ? "free'd"
260 : "client-defined");
njn5c004e42002-11-18 11:04:50 +0000261 VG_(pp_ExeContext)(ai->lastchange);
262 break;
263 }
264 default:
njn43c799e2003-04-08 00:08:52 +0000265 VG_(skin_panic)("MAC_(pp_AddrInfo)");
266 }
267}
268
269/* This prints out the message for the error types where Memcheck and
270 Addrcheck have identical messages */
271void MAC_(pp_shared_SkinError) ( Error* err )
272{
273 MAC_Error* err_extra = VG_(get_error_extra)(err);
274
275 switch (VG_(get_error_kind)(err)) {
276 case FreeErr:
277 VG_(message)(Vg_UserMsg,"Invalid free() / delete / delete[]");
278 /* fall through */
279 case FreeMismatchErr:
280 if (VG_(get_error_kind)(err) == FreeMismatchErr)
281 VG_(message)(Vg_UserMsg,
282 "Mismatched free() / delete / delete []");
283 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
284 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
285 break;
286
287 case LeakErr: {
288 /* Totally abusing the types of these spare fields... oh well. */
289 UInt n_this_record = (UInt)VG_(get_error_address)(err);
290 UInt n_total_records = (UInt)VG_(get_error_string) (err);
291
292 MAC_(pp_LeakError)(err_extra, n_this_record, n_total_records);
293 break;
294 }
295
296 default:
297 VG_(printf)("Error:\n unknown Memcheck/Addrcheck error code %d\n",
298 VG_(get_error_kind)(err));
299 VG_(skin_panic)("unknown error code in MAC_(pp_shared_SkinError)");
njn5c004e42002-11-18 11:04:50 +0000300 }
301}
302
303/*------------------------------------------------------------*/
304/*--- Recording errors ---*/
305/*------------------------------------------------------------*/
306
njn43c799e2003-04-08 00:08:52 +0000307/* Additional description function for describe_addr(); used by
308 MemCheck for user blocks, which Addrcheck doesn't support. */
309Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL;
310
njn43c799e2003-04-08 00:08:52 +0000311/* Describe an address as best you can, for error messages,
312 putting the result in ai. */
313static void describe_addr ( Addr a, AddrInfo* ai )
314{
njn3e884182003-04-15 13:03:23 +0000315 MAC_Chunk* sc;
316 ThreadId tid;
njn43c799e2003-04-08 00:08:52 +0000317
318 /* Nested functions, yeah. Need the lexical scoping of 'a'. */
njn3e884182003-04-15 13:03:23 +0000319
njn43c799e2003-04-08 00:08:52 +0000320 /* Closure for searching thread stacks */
321 Bool addr_is_in_bounds(Addr stack_min, Addr stack_max)
322 {
323 return (stack_min <= a && a <= stack_max);
324 }
njn3e884182003-04-15 13:03:23 +0000325 /* Closure for searching free'd list */
326 Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc)
njn43c799e2003-04-08 00:08:52 +0000327 {
njn3e884182003-04-15 13:03:23 +0000328 return VG_(addr_is_in_block)( a, mc->data, mc->size );
329 }
330 /* Closure for searching malloc'd lists */
331 Bool addr_is_in_HashNode(VgHashNode* sh_ch)
332 {
333 return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch );
njn43c799e2003-04-08 00:08:52 +0000334 }
335
336 /* Perhaps it's a user-def'd block ? (only check if requested, though) */
337 if (NULL != MAC_(describe_addr_supp)) {
338 if (MAC_(describe_addr_supp)( a, ai ))
339 return;
340 }
341 /* Perhaps it's on a thread's stack? */
342 tid = VG_(first_matching_thread_stack)(addr_is_in_bounds);
343 if (tid != VG_INVALID_THREADID) {
344 ai->akind = Stack;
345 ai->stack_tid = tid;
346 return;
347 }
348 /* Search for a recently freed block which might bracket it. */
njn3e884182003-04-15 13:03:23 +0000349 sc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk);
350 if (NULL != sc) {
njn43c799e2003-04-08 00:08:52 +0000351 ai->akind = Freed;
njn3e884182003-04-15 13:03:23 +0000352 ai->blksize = sc->size;
353 ai->rwoffset = (Int)a - (Int)sc->data;
354 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000355 return;
356 }
357 /* Search for a currently malloc'd block which might bracket it. */
njn3e884182003-04-15 13:03:23 +0000358 sc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode);
njn43c799e2003-04-08 00:08:52 +0000359 if (NULL != sc) {
360 ai->akind = Mallocd;
njn3e884182003-04-15 13:03:23 +0000361 ai->blksize = sc->size;
362 ai->rwoffset = (Int)(a) - (Int)sc->data;
363 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000364 return;
365 }
366 /* Clueless ... */
367 ai->akind = Unknown;
368 return;
369}
370
njn5c004e42002-11-18 11:04:50 +0000371/* Is this address within some small distance below %ESP? Used only
372 for the --workaround-gcc296-bugs kludge. */
373static Bool is_just_below_ESP( Addr esp, Addr aa )
374{
375 if ((UInt)esp > (UInt)aa
376 && ((UInt)esp - (UInt)aa) <= VG_GCC296_BUG_STACK_SLOP)
377 return True;
378 else
379 return False;
380}
381
382/* This one called from generated code. */
383
njn43c799e2003-04-08 00:08:52 +0000384void MAC_(record_address_error) ( Addr a, Int size, Bool isWrite )
njn5c004e42002-11-18 11:04:50 +0000385{
njn43c799e2003-04-08 00:08:52 +0000386 MAC_Error err_extra;
387 Bool just_below_esp;
njn5c004e42002-11-18 11:04:50 +0000388
389 just_below_esp = is_just_below_ESP( VG_(get_stack_pointer)(), a );
390
391 /* If this is caused by an access immediately below %ESP, and the
392 user asks nicely, we just ignore it. */
njn43c799e2003-04-08 00:08:52 +0000393 if (MAC_(clo_workaround_gcc296_bugs) && just_below_esp)
njn5c004e42002-11-18 11:04:50 +0000394 return;
395
njn43c799e2003-04-08 00:08:52 +0000396 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000397 err_extra.axskind = isWrite ? WriteAxs : ReadAxs;
398 err_extra.size = size;
399 err_extra.addrinfo.akind = Undescribed;
400 err_extra.addrinfo.maybe_gcc = just_below_esp;
401 VG_(maybe_record_error)( NULL, AddrErr, a, /*s*/NULL, &err_extra );
402}
403
404/* These ones are called from non-generated code */
405
406/* This is for memory errors in pthread functions, as opposed to pthread API
407 errors which are found by the core. */
njn43c799e2003-04-08 00:08:52 +0000408void MAC_(record_core_mem_error) ( ThreadState* tst, Bool isWrite, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000409{
njn43c799e2003-04-08 00:08:52 +0000410 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000411
njn43c799e2003-04-08 00:08:52 +0000412 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000413 err_extra.isWrite = isWrite;
414 VG_(maybe_record_error)( tst, CoreMemErr, /*addr*/0, msg, &err_extra );
415}
416
njn43c799e2003-04-08 00:08:52 +0000417void MAC_(record_param_error) ( ThreadState* tst, Addr a, Bool isWrite,
njn5c004e42002-11-18 11:04:50 +0000418 Char* msg )
419{
njn43c799e2003-04-08 00:08:52 +0000420 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000421
422 sk_assert(NULL != tst);
njn43c799e2003-04-08 00:08:52 +0000423 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000424 err_extra.addrinfo.akind = Undescribed;
425 err_extra.isWrite = isWrite;
426 VG_(maybe_record_error)( tst, ParamErr, a, msg, &err_extra );
427}
428
njn43c799e2003-04-08 00:08:52 +0000429void MAC_(record_jump_error) ( ThreadState* tst, Addr a )
njn5c004e42002-11-18 11:04:50 +0000430{
njn43c799e2003-04-08 00:08:52 +0000431 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000432
433 sk_assert(NULL != tst);
434
njn43c799e2003-04-08 00:08:52 +0000435 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000436 err_extra.axskind = ExecAxs;
437 err_extra.addrinfo.akind = Undescribed;
438 VG_(maybe_record_error)( tst, AddrErr, a, /*s*/NULL, &err_extra );
439}
440
njn43c799e2003-04-08 00:08:52 +0000441void MAC_(record_free_error) ( ThreadState* tst, Addr a )
njn5c004e42002-11-18 11:04:50 +0000442{
njn43c799e2003-04-08 00:08:52 +0000443 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000444
445 sk_assert(NULL != tst);
446
njn43c799e2003-04-08 00:08:52 +0000447 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000448 err_extra.addrinfo.akind = Undescribed;
449 VG_(maybe_record_error)( tst, FreeErr, a, /*s*/NULL, &err_extra );
450}
451
njn43c799e2003-04-08 00:08:52 +0000452void MAC_(record_freemismatch_error) ( ThreadState* tst, Addr a )
njn5c004e42002-11-18 11:04:50 +0000453{
njn43c799e2003-04-08 00:08:52 +0000454 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000455
456 sk_assert(NULL != tst);
457
njn43c799e2003-04-08 00:08:52 +0000458 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000459 err_extra.addrinfo.akind = Undescribed;
460 VG_(maybe_record_error)( tst, FreeMismatchErr, a, /*s*/NULL, &err_extra );
461}
462
njn43c799e2003-04-08 00:08:52 +0000463/* Updates the copy with address info if necessary (but not for LeakErrs). */
464UInt SK_(update_extra)( Error* err )
465{
466 MAC_Error* extra;
467
468 /* Don't need to return the correct size -- LeakErrs are always shown with
469 VG_(unique_error)() so they're not copied anyway. */
470 if (LeakErr == VG_(get_error_kind)(err))
471 return 0;
472
473 extra = (MAC_Error*)VG_(get_error_extra)(err);
474
475 if (extra != NULL && Undescribed == extra->addrinfo.akind) {
476 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
477 }
478
479 return sizeof(MAC_Error);
480}
481
482
njn5c004e42002-11-18 11:04:50 +0000483/*------------------------------------------------------------*/
484/*--- Suppressions ---*/
485/*------------------------------------------------------------*/
486
njn43c799e2003-04-08 00:08:52 +0000487Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
488{
489 SuppKind skind;
490
491 if (VG_STREQ(name, "Param")) skind = ParamSupp;
492 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
493 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
494 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
495 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
496 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
497 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
498 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
499 else
500 return False;
501
502 VG_(set_supp_kind)(su, skind);
503 return True;
504}
505
njn5c004e42002-11-18 11:04:50 +0000506Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
507{
508 Bool eof;
509
510 if (VG_(get_supp_kind)(su) == ParamSupp) {
511 eof = VG_(get_line) ( fd, buf, nBuf );
512 if (eof) return False;
513 VG_(set_supp_string)(su, VG_(strdup)(buf));
514 }
515 return True;
516}
517
sewardj99aac972002-12-26 01:53:45 +0000518Bool SK_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000519{
njn43c799e2003-04-08 00:08:52 +0000520 UInt su_size;
521 MAC_Error* err_extra = VG_(get_error_extra)(err);
522 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000523
524 switch (VG_(get_supp_kind)(su)) {
525 case ParamSupp:
526 return (ekind == ParamErr
njn43c799e2003-04-08 00:08:52 +0000527 && VG_STREQ(VG_(get_error_string)(err),
528 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000529
530 case CoreMemSupp:
531 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000532 && VG_STREQ(VG_(get_error_string)(err),
533 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000534
535 case Value0Supp: su_size = 0; goto value_case;
536 case Value1Supp: su_size = 1; goto value_case;
537 case Value2Supp: su_size = 2; goto value_case;
538 case Value4Supp: su_size = 4; goto value_case;
539 case Value8Supp: su_size = 8; goto value_case;
540 value_case:
541 return (ekind == ValueErr && err_extra->size == su_size);
542
543 case Addr1Supp: su_size = 1; goto addr_case;
544 case Addr2Supp: su_size = 2; goto addr_case;
545 case Addr4Supp: su_size = 4; goto addr_case;
546 case Addr8Supp: su_size = 8; goto addr_case;
547 addr_case:
548 return (ekind == AddrErr && err_extra->size == su_size);
549
550 case FreeSupp:
551 return (ekind == FreeErr || ekind == FreeMismatchErr);
552
sewardj4a19e2f2002-12-26 11:50:21 +0000553 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000554 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000555
njn5c004e42002-11-18 11:04:50 +0000556 default:
557 VG_(printf)("Error:\n"
558 " unknown suppression type %d\n",
559 VG_(get_supp_kind)(su));
560 VG_(skin_panic)("unknown suppression type in "
561 "SK_(error_matches_suppression)");
562 }
563}
564
njn43c799e2003-04-08 00:08:52 +0000565Char* SK_(get_error_name) ( Error* err )
566{
567 Char* s;
568 switch (VG_(get_error_kind)(err)) {
569 case ParamErr: return "Param";
570 case UserErr: return NULL; /* Can't suppress User errors */
571 case FreeMismatchErr: return "Free";
572 case FreeErr: return "Free";
573 case AddrErr:
574 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
575 case 1: return "Addr1";
576 case 2: return "Addr2";
577 case 4: return "Addr4";
578 case 8: return "Addr8";
579 default: VG_(skin_panic)("unexpected size for Addr");
580 }
581
582 case ValueErr:
583 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
584 case 0: return "Cond";
585 case 1: return "Value1";
586 case 2: return "Value2";
587 case 4: return "Value4";
588 case 8: return "Value8";
589 default: VG_(skin_panic)("unexpected size for Value");
590 }
591 case CoreMemErr: return "CoreMem";
592 case LeakErr: return "Leak";
593 default: VG_(skin_panic)("get_error_name: unexpected type");
594 }
595 VG_(printf)(s);
596}
597
598void SK_(print_extra_suppression_info) ( Error* err )
599{
600 if (ParamErr == VG_(get_error_kind)(err)) {
601 VG_(printf)(" %s\n", VG_(get_error_string)(err));
602 }
603}
njn5c004e42002-11-18 11:04:50 +0000604
605/*------------------------------------------------------------*/
606/*--- Crude profiling machinery. ---*/
607/*------------------------------------------------------------*/
608
609/* Event index. If just the name of the fn is given, this means the
610 number of calls to the fn. Otherwise it is the specified event.
611 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
612 The rest are shared.
613
614 10 alloc_secondary_map
615
616 20 get_abit
617M 21 get_vbyte
618 22 set_abit
619M 23 set_vbyte
620 24 get_abits4_ALIGNED
621M 25 get_vbytes4_ALIGNED
622
623 30 set_address_range_perms
624 31 set_address_range_perms(lower byte loop)
625 32 set_address_range_perms(quadword loop)
626 33 set_address_range_perms(upper byte loop)
627
628 35 make_noaccess
629 36 make_writable
630 37 make_readable
631A 38 make_accessible
632
633 40 copy_address_range_state
634 41 copy_address_range_state(byte loop)
635 42 check_writable
636 43 check_writable(byte loop)
637 44 check_readable
638 45 check_readable(byte loop)
639 46 check_readable_asciiz
640 47 check_readable_asciiz(byte loop)
641A 48 check_accessible
642A 49 check_accessible(byte loop)
643
644 50 make_noaccess_aligned
645 51 make_writable_aligned
646
647M 60 helperc_LOADV4
648M 61 helperc_STOREV4
649M 62 helperc_LOADV2
650M 63 helperc_STOREV2
651M 64 helperc_LOADV1
652M 65 helperc_STOREV1
653
654A 66 helperc_ACCESS4
655A 67 helperc_ACCESS2
656A 68 helperc_ACCESS1
657
658M 70 rim_rd_V4_SLOWLY
659M 71 rim_wr_V4_SLOWLY
660M 72 rim_rd_V2_SLOWLY
661M 73 rim_wr_V2_SLOWLY
662M 74 rim_rd_V1_SLOWLY
663M 75 rim_wr_V1_SLOWLY
664
665A 76 ACCESS4_SLOWLY
666A 77 ACCESS2_SLOWLY
667A 78 ACCESS1_SLOWLY
668
669 80 fpu_read
670 81 fpu_read aligned 4
671 82 fpu_read aligned 8
672 83 fpu_read 2
673 84 fpu_read 10/28/108
674
675M 85 fpu_write
676M 86 fpu_write aligned 4
677M 87 fpu_write aligned 8
678M 88 fpu_write 2
679M 89 fpu_write 10/28/108
680
681 90 fpu_access
682 91 fpu_access aligned 4
683 92 fpu_access aligned 8
684 93 fpu_access 2
685 94 fpu_access 10/28/108
686
687 100 fpu_access_check_SLOWLY
688 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000689
690 110 new_mem_stack_4
691 111 new_mem_stack_8
692 112 new_mem_stack_12
693 113 new_mem_stack_16
694 114 new_mem_stack_32
695 115 new_mem_stack
696
697 120 die_mem_stack_4
698 121 die_mem_stack_8
699 122 die_mem_stack_12
700 123 die_mem_stack_16
701 124 die_mem_stack_32
702 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000703*/
704
njn43c799e2003-04-08 00:08:52 +0000705#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000706
njn43c799e2003-04-08 00:08:52 +0000707UInt MAC_(event_ctr)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000708
njnb4aee052003-04-15 14:09:58 +0000709static void init_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000710{
711 Int i;
712 for (i = 0; i < N_PROF_EVENTS; i++)
njn43c799e2003-04-08 00:08:52 +0000713 MAC_(event_ctr)[i] = 0;
njn5c004e42002-11-18 11:04:50 +0000714}
715
njnb4aee052003-04-15 14:09:58 +0000716static void done_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000717{
718 Int i;
719 for (i = 0; i < N_PROF_EVENTS; i++) {
720 if ((i % 10) == 0)
721 VG_(printf)("\n");
njn43c799e2003-04-08 00:08:52 +0000722 if (MAC_(event_ctr)[i] > 0)
723 VG_(printf)( "prof mem event %2d: %d\n", i, MAC_(event_ctr)[i] );
njn5c004e42002-11-18 11:04:50 +0000724 }
725 VG_(printf)("\n");
726}
727
728#else
729
njnb4aee052003-04-15 14:09:58 +0000730static void init_prof_mem ( void ) { }
731static void done_prof_mem ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000732
njn5c004e42002-11-18 11:04:50 +0000733#endif
734
735/*------------------------------------------------------------*/
njn3e884182003-04-15 13:03:23 +0000736/*--- Common initialisation + finalisation ---*/
737/*------------------------------------------------------------*/
738
739void MAC_(common_pre_clo_init)(void)
740{
741 MAC_(malloc_list) = VG_(HT_construct)();
742 init_prof_mem();
743}
744
745void MAC_(common_fini)(void (*leak_check)(void))
746{
747 MAC_(print_malloc_stats)();
748
749 if (VG_(clo_verbosity) == 1) {
750 if (!MAC_(clo_leak_check))
751 VG_(message)(Vg_UserMsg,
752 "For a detailed leak analysis, rerun with: --leak-check=yes");
753
754 VG_(message)(Vg_UserMsg,
755 "For counts of detected errors, rerun with: -v");
756 }
757 if (MAC_(clo_leak_check)) leak_check();
758
759 done_prof_mem();
760}
761
762/*------------------------------------------------------------*/
njn47363ab2003-04-21 13:24:40 +0000763/*--- Common client request handling ---*/
764/*------------------------------------------------------------*/
765
766Bool MAC_(handle_common_client_requests)(ThreadState* tst, UInt* arg,
767 UInt* ret )
768{
769 UInt** argp = (UInt**)arg;
770
771 switch (arg[0]) {
772 case VG_USERREQ__COUNT_LEAKS: /* count leaked bytes */
773 *argp[1] = MAC_(total_bytes_leaked);
774 *argp[2] = MAC_(total_bytes_dubious);
775 *argp[3] = MAC_(total_bytes_reachable);
776 *argp[4] = MAC_(total_bytes_suppressed);
777 *ret = 0;
778 return True;
779
780 default:
781 return False;
782 }
783}
784
785/*------------------------------------------------------------*/
njn5c004e42002-11-18 11:04:50 +0000786/*--- Syscall wrappers ---*/
787/*------------------------------------------------------------*/
788
789void* SK_(pre_syscall) ( ThreadId tid, UInt syscallno, Bool isBlocking )
790{
791 Int sane = SK_(cheap_sanity_check)();
792 return (void*)sane;
793}
794
795void SK_(post_syscall) ( ThreadId tid, UInt syscallno,
796 void* pre_result, Int res, Bool isBlocking )
797{
798 Int sane_before_call = (Int)pre_result;
799 Bool sane_after_call = SK_(cheap_sanity_check)();
800
801 if ((Int)sane_before_call && (!sane_after_call)) {
802 VG_(message)(Vg_DebugMsg, "post-syscall: ");
803 VG_(message)(Vg_DebugMsg,
804 "probable sanity check failure for syscall number %d\n",
805 syscallno );
806 VG_(skin_panic)("aborting due to the above ... bye!");
807 }
808}
809
njn5c004e42002-11-18 11:04:50 +0000810/*--------------------------------------------------------------------*/
njn43c799e2003-04-08 00:08:52 +0000811/*--- end mac_needs.c ---*/
njn5c004e42002-11-18 11:04:50 +0000812/*--------------------------------------------------------------------*/