blob: daec93849387c71b16ac47f27d70ad4282242aaf [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
njn34419c12003-05-02 17:24:29 +0000210 case OverlapErr:
211 return True;
212
njn43c799e2003-04-08 00:08:52 +0000213 case LeakErr:
214 VG_(skin_panic)("Shouldn't get LeakErr in SK_(eq_SkinError),\n"
215 "since it's handled with VG_(unique_error)()!");
216
njn5c004e42002-11-18 11:04:50 +0000217 default:
218 VG_(printf)("Error:\n unknown error code %d\n",
219 VG_(get_error_kind)(e1));
220 VG_(skin_panic)("unknown error code in SK_(eq_SkinError)");
221 }
222}
223
njn43c799e2003-04-08 00:08:52 +0000224void MAC_(pp_AddrInfo) ( Addr a, AddrInfo* ai )
njn5c004e42002-11-18 11:04:50 +0000225{
226 switch (ai->akind) {
227 case Stack:
228 VG_(message)(Vg_UserMsg,
229 " Address 0x%x is on thread %d's stack",
230 a, ai->stack_tid);
231 break;
232 case Unknown:
233 if (ai->maybe_gcc) {
234 VG_(message)(Vg_UserMsg,
235 " Address 0x%x is just below %%esp. Possibly a bug in GCC/G++",
236 a);
237 VG_(message)(Vg_UserMsg,
238 " v 2.96 or 3.0.X. To suppress, use: --workaround-gcc296-bugs=yes");
239 } else {
240 VG_(message)(Vg_UserMsg,
241 " Address 0x%x is not stack'd, malloc'd or free'd", a);
242 }
243 break;
sewardja81709d2002-12-28 12:55:48 +0000244 case Freed: case Mallocd: case UserG: {
njn5c004e42002-11-18 11:04:50 +0000245 UInt delta;
246 UChar* relative;
247 if (ai->rwoffset < 0) {
248 delta = (UInt)(- ai->rwoffset);
249 relative = "before";
250 } else if (ai->rwoffset >= ai->blksize) {
251 delta = ai->rwoffset - ai->blksize;
252 relative = "after";
253 } else {
254 delta = ai->rwoffset;
255 relative = "inside";
256 }
sewardja81709d2002-12-28 12:55:48 +0000257 VG_(message)(Vg_UserMsg,
258 " Address 0x%x is %d bytes %s a block of size %d %s",
259 a, delta, relative,
260 ai->blksize,
261 ai->akind==Mallocd ? "alloc'd"
262 : ai->akind==Freed ? "free'd"
263 : "client-defined");
njn5c004e42002-11-18 11:04:50 +0000264 VG_(pp_ExeContext)(ai->lastchange);
265 break;
266 }
267 default:
njn43c799e2003-04-08 00:08:52 +0000268 VG_(skin_panic)("MAC_(pp_AddrInfo)");
269 }
270}
271
272/* This prints out the message for the error types where Memcheck and
273 Addrcheck have identical messages */
274void MAC_(pp_shared_SkinError) ( Error* err )
275{
276 MAC_Error* err_extra = VG_(get_error_extra)(err);
277
278 switch (VG_(get_error_kind)(err)) {
279 case FreeErr:
njn10785452003-05-20 16:38:24 +0000280 VG_(message)(Vg_UserMsg, "Invalid free() / delete / delete[]");
njn43c799e2003-04-08 00:08:52 +0000281 /* fall through */
282 case FreeMismatchErr:
283 if (VG_(get_error_kind)(err) == FreeMismatchErr)
284 VG_(message)(Vg_UserMsg,
285 "Mismatched free() / delete / delete []");
286 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
287 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
288 break;
289
290 case LeakErr: {
291 /* Totally abusing the types of these spare fields... oh well. */
292 UInt n_this_record = (UInt)VG_(get_error_address)(err);
293 UInt n_total_records = (UInt)VG_(get_error_string) (err);
294
295 MAC_(pp_LeakError)(err_extra, n_this_record, n_total_records);
296 break;
297 }
298
299 default:
300 VG_(printf)("Error:\n unknown Memcheck/Addrcheck error code %d\n",
301 VG_(get_error_kind)(err));
302 VG_(skin_panic)("unknown error code in MAC_(pp_shared_SkinError)");
njn5c004e42002-11-18 11:04:50 +0000303 }
304}
305
306/*------------------------------------------------------------*/
307/*--- Recording errors ---*/
308/*------------------------------------------------------------*/
309
njn43c799e2003-04-08 00:08:52 +0000310/* Additional description function for describe_addr(); used by
311 MemCheck for user blocks, which Addrcheck doesn't support. */
312Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL;
313
njn43c799e2003-04-08 00:08:52 +0000314/* Describe an address as best you can, for error messages,
315 putting the result in ai. */
316static void describe_addr ( Addr a, AddrInfo* ai )
317{
njn3e884182003-04-15 13:03:23 +0000318 MAC_Chunk* sc;
319 ThreadId tid;
njn43c799e2003-04-08 00:08:52 +0000320
321 /* Nested functions, yeah. Need the lexical scoping of 'a'. */
njn3e884182003-04-15 13:03:23 +0000322
njn43c799e2003-04-08 00:08:52 +0000323 /* Closure for searching thread stacks */
324 Bool addr_is_in_bounds(Addr stack_min, Addr stack_max)
325 {
326 return (stack_min <= a && a <= stack_max);
327 }
njn3e884182003-04-15 13:03:23 +0000328 /* Closure for searching free'd list */
329 Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc)
njn43c799e2003-04-08 00:08:52 +0000330 {
njn3e884182003-04-15 13:03:23 +0000331 return VG_(addr_is_in_block)( a, mc->data, mc->size );
332 }
333 /* Closure for searching malloc'd lists */
334 Bool addr_is_in_HashNode(VgHashNode* sh_ch)
335 {
336 return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch );
njn43c799e2003-04-08 00:08:52 +0000337 }
338
339 /* Perhaps it's a user-def'd block ? (only check if requested, though) */
340 if (NULL != MAC_(describe_addr_supp)) {
341 if (MAC_(describe_addr_supp)( a, ai ))
342 return;
343 }
344 /* Perhaps it's on a thread's stack? */
345 tid = VG_(first_matching_thread_stack)(addr_is_in_bounds);
346 if (tid != VG_INVALID_THREADID) {
347 ai->akind = Stack;
348 ai->stack_tid = tid;
349 return;
350 }
351 /* Search for a recently freed block which might bracket it. */
njn3e884182003-04-15 13:03:23 +0000352 sc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk);
353 if (NULL != sc) {
njn43c799e2003-04-08 00:08:52 +0000354 ai->akind = Freed;
njn3e884182003-04-15 13:03:23 +0000355 ai->blksize = sc->size;
356 ai->rwoffset = (Int)a - (Int)sc->data;
357 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000358 return;
359 }
360 /* Search for a currently malloc'd block which might bracket it. */
njn3e884182003-04-15 13:03:23 +0000361 sc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode);
njn43c799e2003-04-08 00:08:52 +0000362 if (NULL != sc) {
363 ai->akind = Mallocd;
njn3e884182003-04-15 13:03:23 +0000364 ai->blksize = sc->size;
365 ai->rwoffset = (Int)(a) - (Int)sc->data;
366 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000367 return;
368 }
369 /* Clueless ... */
370 ai->akind = Unknown;
371 return;
372}
373
njn5c004e42002-11-18 11:04:50 +0000374/* Is this address within some small distance below %ESP? Used only
375 for the --workaround-gcc296-bugs kludge. */
376static Bool is_just_below_ESP( Addr esp, Addr aa )
377{
378 if ((UInt)esp > (UInt)aa
379 && ((UInt)esp - (UInt)aa) <= VG_GCC296_BUG_STACK_SLOP)
380 return True;
381 else
382 return False;
383}
384
sewardjaf48a602003-07-06 00:54:47 +0000385/* This one called from generated code and non-generated code. */
njn5c004e42002-11-18 11:04:50 +0000386
sewardjaf48a602003-07-06 00:54:47 +0000387void MAC_(record_address_error) ( ThreadState* tst, Addr a, Int size,
388 Bool isWrite )
njn5c004e42002-11-18 11:04:50 +0000389{
njn43c799e2003-04-08 00:08:52 +0000390 MAC_Error err_extra;
391 Bool just_below_esp;
njn5c004e42002-11-18 11:04:50 +0000392
393 just_below_esp = is_just_below_ESP( VG_(get_stack_pointer)(), a );
394
395 /* If this is caused by an access immediately below %ESP, and the
396 user asks nicely, we just ignore it. */
njn43c799e2003-04-08 00:08:52 +0000397 if (MAC_(clo_workaround_gcc296_bugs) && just_below_esp)
njn5c004e42002-11-18 11:04:50 +0000398 return;
399
njn43c799e2003-04-08 00:08:52 +0000400 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000401 err_extra.axskind = isWrite ? WriteAxs : ReadAxs;
402 err_extra.size = size;
403 err_extra.addrinfo.akind = Undescribed;
404 err_extra.addrinfo.maybe_gcc = just_below_esp;
sewardjaf48a602003-07-06 00:54:47 +0000405 VG_(maybe_record_error)( tst, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000406}
407
408/* These ones are called from non-generated code */
409
410/* This is for memory errors in pthread functions, as opposed to pthread API
411 errors which are found by the core. */
njn43c799e2003-04-08 00:08:52 +0000412void MAC_(record_core_mem_error) ( ThreadState* tst, Bool isWrite, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000413{
njn43c799e2003-04-08 00:08:52 +0000414 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000415
njn43c799e2003-04-08 00:08:52 +0000416 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000417 err_extra.isWrite = isWrite;
418 VG_(maybe_record_error)( tst, CoreMemErr, /*addr*/0, msg, &err_extra );
419}
420
njn43c799e2003-04-08 00:08:52 +0000421void MAC_(record_param_error) ( ThreadState* tst, Addr a, Bool isWrite,
njn5c004e42002-11-18 11:04:50 +0000422 Char* msg )
423{
njn43c799e2003-04-08 00:08:52 +0000424 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000425
426 sk_assert(NULL != tst);
njn43c799e2003-04-08 00:08:52 +0000427 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000428 err_extra.addrinfo.akind = Undescribed;
429 err_extra.isWrite = isWrite;
430 VG_(maybe_record_error)( tst, ParamErr, a, msg, &err_extra );
431}
432
njn43c799e2003-04-08 00:08:52 +0000433void MAC_(record_jump_error) ( ThreadState* tst, Addr a )
njn5c004e42002-11-18 11:04:50 +0000434{
njn43c799e2003-04-08 00:08:52 +0000435 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000436
437 sk_assert(NULL != tst);
438
njn43c799e2003-04-08 00:08:52 +0000439 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000440 err_extra.axskind = ExecAxs;
441 err_extra.addrinfo.akind = Undescribed;
442 VG_(maybe_record_error)( tst, AddrErr, a, /*s*/NULL, &err_extra );
443}
444
njn43c799e2003-04-08 00:08:52 +0000445void MAC_(record_free_error) ( ThreadState* tst, Addr a )
njn5c004e42002-11-18 11:04:50 +0000446{
njn43c799e2003-04-08 00:08:52 +0000447 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000448
449 sk_assert(NULL != tst);
450
njn43c799e2003-04-08 00:08:52 +0000451 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000452 err_extra.addrinfo.akind = Undescribed;
453 VG_(maybe_record_error)( tst, FreeErr, a, /*s*/NULL, &err_extra );
454}
455
njn43c799e2003-04-08 00:08:52 +0000456void MAC_(record_freemismatch_error) ( ThreadState* tst, Addr a )
njn5c004e42002-11-18 11:04:50 +0000457{
njn43c799e2003-04-08 00:08:52 +0000458 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000459
460 sk_assert(NULL != tst);
461
njn43c799e2003-04-08 00:08:52 +0000462 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000463 err_extra.addrinfo.akind = Undescribed;
464 VG_(maybe_record_error)( tst, FreeMismatchErr, a, /*s*/NULL, &err_extra );
465}
466
njn43c799e2003-04-08 00:08:52 +0000467/* Updates the copy with address info if necessary (but not for LeakErrs). */
468UInt SK_(update_extra)( Error* err )
469{
470 MAC_Error* extra;
471
472 /* Don't need to return the correct size -- LeakErrs are always shown with
473 VG_(unique_error)() so they're not copied anyway. */
474 if (LeakErr == VG_(get_error_kind)(err))
475 return 0;
476
477 extra = (MAC_Error*)VG_(get_error_extra)(err);
478
479 if (extra != NULL && Undescribed == extra->addrinfo.akind) {
480 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
481 }
482
483 return sizeof(MAC_Error);
484}
485
486
njn5c004e42002-11-18 11:04:50 +0000487/*------------------------------------------------------------*/
488/*--- Suppressions ---*/
489/*------------------------------------------------------------*/
490
njn43c799e2003-04-08 00:08:52 +0000491Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
492{
493 SuppKind skind;
494
495 if (VG_STREQ(name, "Param")) skind = ParamSupp;
496 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
497 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
498 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
499 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
500 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
njnc0616662003-06-12 09:58:41 +0000501 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
njn43c799e2003-04-08 00:08:52 +0000502 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
503 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
504 else
505 return False;
506
507 VG_(set_supp_kind)(su, skind);
508 return True;
509}
510
njn5c004e42002-11-18 11:04:50 +0000511Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
512{
513 Bool eof;
514
515 if (VG_(get_supp_kind)(su) == ParamSupp) {
516 eof = VG_(get_line) ( fd, buf, nBuf );
517 if (eof) return False;
518 VG_(set_supp_string)(su, VG_(strdup)(buf));
519 }
520 return True;
521}
522
sewardj99aac972002-12-26 01:53:45 +0000523Bool SK_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000524{
sewardj05bcdcb2003-05-18 10:05:38 +0000525 Int su_size;
njn43c799e2003-04-08 00:08:52 +0000526 MAC_Error* err_extra = VG_(get_error_extra)(err);
527 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000528
529 switch (VG_(get_supp_kind)(su)) {
530 case ParamSupp:
531 return (ekind == ParamErr
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 CoreMemSupp:
536 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000537 && VG_STREQ(VG_(get_error_string)(err),
538 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000539
540 case Value0Supp: su_size = 0; goto value_case;
541 case Value1Supp: su_size = 1; goto value_case;
542 case Value2Supp: su_size = 2; goto value_case;
543 case Value4Supp: su_size = 4; goto value_case;
544 case Value8Supp: su_size = 8; goto value_case;
njnc0616662003-06-12 09:58:41 +0000545 case Value16Supp:su_size =16; goto value_case;
njn5c004e42002-11-18 11:04:50 +0000546 value_case:
547 return (ekind == ValueErr && err_extra->size == su_size);
548
549 case Addr1Supp: su_size = 1; goto addr_case;
550 case Addr2Supp: su_size = 2; goto addr_case;
551 case Addr4Supp: su_size = 4; goto addr_case;
552 case Addr8Supp: su_size = 8; goto addr_case;
njnc0616662003-06-12 09:58:41 +0000553 case Addr16Supp:su_size =16; goto addr_case;
njn5c004e42002-11-18 11:04:50 +0000554 addr_case:
555 return (ekind == AddrErr && err_extra->size == su_size);
556
557 case FreeSupp:
558 return (ekind == FreeErr || ekind == FreeMismatchErr);
559
njn34419c12003-05-02 17:24:29 +0000560 case OverlapSupp:
561 return (ekind = OverlapErr);
562
sewardj4a19e2f2002-12-26 11:50:21 +0000563 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000564 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000565
njn5c004e42002-11-18 11:04:50 +0000566 default:
567 VG_(printf)("Error:\n"
568 " unknown suppression type %d\n",
569 VG_(get_supp_kind)(su));
570 VG_(skin_panic)("unknown suppression type in "
571 "SK_(error_matches_suppression)");
572 }
573}
574
njn43c799e2003-04-08 00:08:52 +0000575Char* SK_(get_error_name) ( Error* err )
576{
577 Char* s;
578 switch (VG_(get_error_kind)(err)) {
579 case ParamErr: return "Param";
580 case UserErr: return NULL; /* Can't suppress User errors */
581 case FreeMismatchErr: return "Free";
582 case FreeErr: return "Free";
583 case AddrErr:
584 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
585 case 1: return "Addr1";
586 case 2: return "Addr2";
587 case 4: return "Addr4";
588 case 8: return "Addr8";
njnc0616662003-06-12 09:58:41 +0000589 case 16: return "Addr16";
njn43c799e2003-04-08 00:08:52 +0000590 default: VG_(skin_panic)("unexpected size for Addr");
591 }
592
593 case ValueErr:
594 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
595 case 0: return "Cond";
596 case 1: return "Value1";
597 case 2: return "Value2";
598 case 4: return "Value4";
599 case 8: return "Value8";
njnc0616662003-06-12 09:58:41 +0000600 case 16: return "Value16";
njn43c799e2003-04-08 00:08:52 +0000601 default: VG_(skin_panic)("unexpected size for Value");
602 }
603 case CoreMemErr: return "CoreMem";
njn34419c12003-05-02 17:24:29 +0000604 case OverlapErr: return "Overlap";
njn43c799e2003-04-08 00:08:52 +0000605 case LeakErr: return "Leak";
606 default: VG_(skin_panic)("get_error_name: unexpected type");
607 }
608 VG_(printf)(s);
609}
610
611void SK_(print_extra_suppression_info) ( Error* err )
612{
613 if (ParamErr == VG_(get_error_kind)(err)) {
614 VG_(printf)(" %s\n", VG_(get_error_string)(err));
615 }
616}
njn5c004e42002-11-18 11:04:50 +0000617
618/*------------------------------------------------------------*/
619/*--- Crude profiling machinery. ---*/
620/*------------------------------------------------------------*/
621
622/* Event index. If just the name of the fn is given, this means the
623 number of calls to the fn. Otherwise it is the specified event.
624 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
625 The rest are shared.
626
627 10 alloc_secondary_map
628
629 20 get_abit
630M 21 get_vbyte
631 22 set_abit
632M 23 set_vbyte
633 24 get_abits4_ALIGNED
634M 25 get_vbytes4_ALIGNED
635
636 30 set_address_range_perms
637 31 set_address_range_perms(lower byte loop)
638 32 set_address_range_perms(quadword loop)
639 33 set_address_range_perms(upper byte loop)
640
641 35 make_noaccess
642 36 make_writable
643 37 make_readable
644A 38 make_accessible
645
646 40 copy_address_range_state
647 41 copy_address_range_state(byte loop)
648 42 check_writable
649 43 check_writable(byte loop)
650 44 check_readable
651 45 check_readable(byte loop)
652 46 check_readable_asciiz
653 47 check_readable_asciiz(byte loop)
654A 48 check_accessible
655A 49 check_accessible(byte loop)
656
657 50 make_noaccess_aligned
658 51 make_writable_aligned
659
660M 60 helperc_LOADV4
661M 61 helperc_STOREV4
662M 62 helperc_LOADV2
663M 63 helperc_STOREV2
664M 64 helperc_LOADV1
665M 65 helperc_STOREV1
666
667A 66 helperc_ACCESS4
668A 67 helperc_ACCESS2
669A 68 helperc_ACCESS1
670
671M 70 rim_rd_V4_SLOWLY
672M 71 rim_wr_V4_SLOWLY
673M 72 rim_rd_V2_SLOWLY
674M 73 rim_wr_V2_SLOWLY
675M 74 rim_rd_V1_SLOWLY
676M 75 rim_wr_V1_SLOWLY
677
678A 76 ACCESS4_SLOWLY
679A 77 ACCESS2_SLOWLY
680A 78 ACCESS1_SLOWLY
681
682 80 fpu_read
683 81 fpu_read aligned 4
684 82 fpu_read aligned 8
685 83 fpu_read 2
686 84 fpu_read 10/28/108
687
688M 85 fpu_write
689M 86 fpu_write aligned 4
690M 87 fpu_write aligned 8
691M 88 fpu_write 2
692M 89 fpu_write 10/28/108
693
694 90 fpu_access
695 91 fpu_access aligned 4
696 92 fpu_access aligned 8
697 93 fpu_access 2
698 94 fpu_access 10/28/108
699
700 100 fpu_access_check_SLOWLY
701 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000702
703 110 new_mem_stack_4
704 111 new_mem_stack_8
705 112 new_mem_stack_12
706 113 new_mem_stack_16
707 114 new_mem_stack_32
708 115 new_mem_stack
709
710 120 die_mem_stack_4
711 121 die_mem_stack_8
712 122 die_mem_stack_12
713 123 die_mem_stack_16
714 124 die_mem_stack_32
715 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000716*/
717
njn43c799e2003-04-08 00:08:52 +0000718#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000719
njn43c799e2003-04-08 00:08:52 +0000720UInt MAC_(event_ctr)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000721
njnb4aee052003-04-15 14:09:58 +0000722static void init_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000723{
724 Int i;
725 for (i = 0; i < N_PROF_EVENTS; i++)
njn43c799e2003-04-08 00:08:52 +0000726 MAC_(event_ctr)[i] = 0;
njn5c004e42002-11-18 11:04:50 +0000727}
728
njnb4aee052003-04-15 14:09:58 +0000729static void done_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000730{
731 Int i;
732 for (i = 0; i < N_PROF_EVENTS; i++) {
733 if ((i % 10) == 0)
734 VG_(printf)("\n");
njn43c799e2003-04-08 00:08:52 +0000735 if (MAC_(event_ctr)[i] > 0)
736 VG_(printf)( "prof mem event %2d: %d\n", i, MAC_(event_ctr)[i] );
njn5c004e42002-11-18 11:04:50 +0000737 }
738 VG_(printf)("\n");
739}
740
741#else
742
njnb4aee052003-04-15 14:09:58 +0000743static void init_prof_mem ( void ) { }
744static void done_prof_mem ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000745
njn5c004e42002-11-18 11:04:50 +0000746#endif
747
748/*------------------------------------------------------------*/
njn3e884182003-04-15 13:03:23 +0000749/*--- Common initialisation + finalisation ---*/
750/*------------------------------------------------------------*/
751
752void MAC_(common_pre_clo_init)(void)
753{
754 MAC_(malloc_list) = VG_(HT_construct)();
755 init_prof_mem();
756}
757
758void MAC_(common_fini)(void (*leak_check)(void))
759{
760 MAC_(print_malloc_stats)();
761
762 if (VG_(clo_verbosity) == 1) {
763 if (!MAC_(clo_leak_check))
764 VG_(message)(Vg_UserMsg,
765 "For a detailed leak analysis, rerun with: --leak-check=yes");
766
767 VG_(message)(Vg_UserMsg,
768 "For counts of detected errors, rerun with: -v");
769 }
770 if (MAC_(clo_leak_check)) leak_check();
771
772 done_prof_mem();
773}
774
775/*------------------------------------------------------------*/
njn47363ab2003-04-21 13:24:40 +0000776/*--- Common client request handling ---*/
777/*------------------------------------------------------------*/
778
779Bool MAC_(handle_common_client_requests)(ThreadState* tst, UInt* arg,
780 UInt* ret )
781{
njn10785452003-05-20 16:38:24 +0000782 UInt* argv = (UInt*)arg;
njn47363ab2003-04-21 13:24:40 +0000783
784 switch (arg[0]) {
njn10785452003-05-20 16:38:24 +0000785 case VG_USERREQ__COUNT_LEAKS: { /* count leaked bytes */
786 UInt** argp = (UInt**)arg;
njn47363ab2003-04-21 13:24:40 +0000787 *argp[1] = MAC_(total_bytes_leaked);
788 *argp[2] = MAC_(total_bytes_dubious);
789 *argp[3] = MAC_(total_bytes_reachable);
790 *argp[4] = MAC_(total_bytes_suppressed);
791 *ret = 0;
792 return True;
njn10785452003-05-20 16:38:24 +0000793 }
794 case VG_USERREQ__MALLOCLIKE_BLOCK: {
795 Addr p = (Addr)argv[1];
796 UInt sizeB = argv[2];
797 UInt rzB = argv[3];
798 Bool is_zeroed = (Bool)argv[4];
njn47363ab2003-04-21 13:24:40 +0000799
njn10785452003-05-20 16:38:24 +0000800 MAC_(new_block) ( tst, p, sizeB, rzB, is_zeroed, MAC_AllocCustom );
801 return True;
802 }
803 case VG_USERREQ__FREELIKE_BLOCK: {
804 Addr p = (Addr)argv[1];
805 UInt rzB = argv[2];
806
807 MAC_(handle_free) ( tst, p, rzB, MAC_AllocCustom );
808 return True;
809 }
njn47363ab2003-04-21 13:24:40 +0000810 default:
811 return False;
812 }
813}
814
815/*------------------------------------------------------------*/
njn5c004e42002-11-18 11:04:50 +0000816/*--- Syscall wrappers ---*/
817/*------------------------------------------------------------*/
818
819void* SK_(pre_syscall) ( ThreadId tid, UInt syscallno, Bool isBlocking )
820{
821 Int sane = SK_(cheap_sanity_check)();
822 return (void*)sane;
823}
824
825void SK_(post_syscall) ( ThreadId tid, UInt syscallno,
826 void* pre_result, Int res, Bool isBlocking )
827{
828 Int sane_before_call = (Int)pre_result;
829 Bool sane_after_call = SK_(cheap_sanity_check)();
830
831 if ((Int)sane_before_call && (!sane_after_call)) {
832 VG_(message)(Vg_DebugMsg, "post-syscall: ");
833 VG_(message)(Vg_DebugMsg,
834 "probable sanity check failure for syscall number %d\n",
835 syscallno );
836 VG_(skin_panic)("aborting due to the above ... bye!");
837 }
838}
839
njn5c004e42002-11-18 11:04:50 +0000840/*--------------------------------------------------------------------*/
njn43c799e2003-04-08 00:08:52 +0000841/*--- end mac_needs.c ---*/
njn5c004e42002-11-18 11:04:50 +0000842/*--------------------------------------------------------------------*/