blob: 3c7c616a5f8e8408482714ff10ac713c582e02c0 [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/*
nethercote137bc552003-11-14 17:47:54 +00008 This file is part of MemCheck, a heavyweight Valgrind tool for
9 detecting memory errors, and AddrCheck, a lightweight Valgrind tool
njn5c004e42002-11-18 11:04:50 +000010 for detecting memory errors.
11
nethercotebb1c9912004-01-04 16:43:23 +000012 Copyright (C) 2000-2004 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,
nethercote3b390c72003-11-13 17:53:43 +0000229 " Address 0x%x is on thread %d's stack",
njn5c004e42002-11-18 11:04:50 +0000230 a, ai->stack_tid);
231 break;
232 case Unknown:
233 if (ai->maybe_gcc) {
234 VG_(message)(Vg_UserMsg,
nethercote3b390c72003-11-13 17:53:43 +0000235 " Address 0x%x is just below %%esp. Possibly a bug in GCC/G++",
njn5c004e42002-11-18 11:04:50 +0000236 a);
237 VG_(message)(Vg_UserMsg,
nethercote3b390c72003-11-13 17:53:43 +0000238 " v 2.96 or 3.0.X. To suppress, use: --workaround-gcc296-bugs=yes");
njn5c004e42002-11-18 11:04:50 +0000239 } else {
240 VG_(message)(Vg_UserMsg,
nethercotef798eee2004-04-13 08:36:35 +0000241 " Address 0x%x is not stack'd, malloc'd or (recently) free'd",a);
njn5c004e42002-11-18 11:04:50 +0000242 }
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,
nethercote3b390c72003-11-13 17:53:43 +0000258 " Address 0x%x is %d bytes %s a block of size %d %s",
sewardja81709d2002-12-28 12:55:48 +0000259 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
njn89409f82003-09-26 14:55:31 +0000290 case AddrErr:
291 switch (err_extra->axskind) {
292 case ReadAxs:
293 VG_(message)(Vg_UserMsg, "Invalid read of size %d",
294 err_extra->size );
295 break;
296 case WriteAxs:
297 VG_(message)(Vg_UserMsg, "Invalid write of size %d",
298 err_extra->size );
299 break;
300 case ExecAxs:
301 VG_(message)(Vg_UserMsg, "Jump to the invalid address "
302 "stated on the next line");
303 break;
304 default:
305 VG_(skin_panic)("SK_(pp_SkinError)(axskind)");
306 }
307 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
308 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
309 break;
310
njnb6cae9f2003-09-04 20:50:47 +0000311 case OverlapErr: {
312 OverlapExtra* ov_extra = (OverlapExtra*)VG_(get_error_extra)(err);
313 if (ov_extra->len == -1)
314 VG_(message)(Vg_UserMsg,
315 "Source and destination overlap in %s(%p, %p)",
316 VG_(get_error_string)(err),
317 ov_extra->dst, ov_extra->src);
318 else
319 VG_(message)(Vg_UserMsg,
320 "Source and destination overlap in %s(%p, %p, %d)",
321 VG_(get_error_string)(err),
322 ov_extra->dst, ov_extra->src, ov_extra->len);
njn66fe05a2003-07-22 09:12:33 +0000323 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
324 break;
njnb6cae9f2003-09-04 20:50:47 +0000325 }
njn43c799e2003-04-08 00:08:52 +0000326 case LeakErr: {
327 /* Totally abusing the types of these spare fields... oh well. */
328 UInt n_this_record = (UInt)VG_(get_error_address)(err);
329 UInt n_total_records = (UInt)VG_(get_error_string) (err);
330
331 MAC_(pp_LeakError)(err_extra, n_this_record, n_total_records);
332 break;
333 }
334
335 default:
336 VG_(printf)("Error:\n unknown Memcheck/Addrcheck error code %d\n",
337 VG_(get_error_kind)(err));
338 VG_(skin_panic)("unknown error code in MAC_(pp_shared_SkinError)");
njn5c004e42002-11-18 11:04:50 +0000339 }
340}
341
342/*------------------------------------------------------------*/
343/*--- Recording errors ---*/
344/*------------------------------------------------------------*/
345
njn43c799e2003-04-08 00:08:52 +0000346/* Additional description function for describe_addr(); used by
347 MemCheck for user blocks, which Addrcheck doesn't support. */
348Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL;
349
njn43c799e2003-04-08 00:08:52 +0000350/* Describe an address as best you can, for error messages,
351 putting the result in ai. */
352static void describe_addr ( Addr a, AddrInfo* ai )
353{
njn3e884182003-04-15 13:03:23 +0000354 MAC_Chunk* sc;
355 ThreadId tid;
njn43c799e2003-04-08 00:08:52 +0000356
357 /* Nested functions, yeah. Need the lexical scoping of 'a'. */
njn3e884182003-04-15 13:03:23 +0000358
njn43c799e2003-04-08 00:08:52 +0000359 /* Closure for searching thread stacks */
360 Bool addr_is_in_bounds(Addr stack_min, Addr stack_max)
361 {
362 return (stack_min <= a && a <= stack_max);
363 }
njn3e884182003-04-15 13:03:23 +0000364 /* Closure for searching free'd list */
365 Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc)
njn43c799e2003-04-08 00:08:52 +0000366 {
njn3e884182003-04-15 13:03:23 +0000367 return VG_(addr_is_in_block)( a, mc->data, mc->size );
368 }
369 /* Closure for searching malloc'd lists */
370 Bool addr_is_in_HashNode(VgHashNode* sh_ch)
371 {
372 return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch );
njn43c799e2003-04-08 00:08:52 +0000373 }
374
375 /* Perhaps it's a user-def'd block ? (only check if requested, though) */
376 if (NULL != MAC_(describe_addr_supp)) {
377 if (MAC_(describe_addr_supp)( a, ai ))
378 return;
379 }
380 /* Perhaps it's on a thread's stack? */
381 tid = VG_(first_matching_thread_stack)(addr_is_in_bounds);
382 if (tid != VG_INVALID_THREADID) {
383 ai->akind = Stack;
384 ai->stack_tid = tid;
385 return;
386 }
387 /* Search for a recently freed block which might bracket it. */
njn3e884182003-04-15 13:03:23 +0000388 sc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk);
389 if (NULL != sc) {
njn43c799e2003-04-08 00:08:52 +0000390 ai->akind = Freed;
njn3e884182003-04-15 13:03:23 +0000391 ai->blksize = sc->size;
392 ai->rwoffset = (Int)a - (Int)sc->data;
393 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000394 return;
395 }
396 /* Search for a currently malloc'd block which might bracket it. */
njn3e884182003-04-15 13:03:23 +0000397 sc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode);
njn43c799e2003-04-08 00:08:52 +0000398 if (NULL != sc) {
399 ai->akind = Mallocd;
njn3e884182003-04-15 13:03:23 +0000400 ai->blksize = sc->size;
401 ai->rwoffset = (Int)(a) - (Int)sc->data;
402 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000403 return;
404 }
405 /* Clueless ... */
406 ai->akind = Unknown;
407 return;
408}
409
njn5c004e42002-11-18 11:04:50 +0000410/* Is this address within some small distance below %ESP? Used only
411 for the --workaround-gcc296-bugs kludge. */
412static Bool is_just_below_ESP( Addr esp, Addr aa )
413{
414 if ((UInt)esp > (UInt)aa
415 && ((UInt)esp - (UInt)aa) <= VG_GCC296_BUG_STACK_SLOP)
416 return True;
417 else
418 return False;
419}
420
sewardjaf48a602003-07-06 00:54:47 +0000421/* This one called from generated code and non-generated code. */
njn5c004e42002-11-18 11:04:50 +0000422
njn72718642003-07-24 08:45:32 +0000423void MAC_(record_address_error) ( ThreadId tid, Addr a, Int size,
sewardjaf48a602003-07-06 00:54:47 +0000424 Bool isWrite )
njn5c004e42002-11-18 11:04:50 +0000425{
njn43c799e2003-04-08 00:08:52 +0000426 MAC_Error err_extra;
427 Bool just_below_esp;
njn5c004e42002-11-18 11:04:50 +0000428
429 just_below_esp = is_just_below_ESP( VG_(get_stack_pointer)(), a );
430
431 /* If this is caused by an access immediately below %ESP, and the
432 user asks nicely, we just ignore it. */
njn43c799e2003-04-08 00:08:52 +0000433 if (MAC_(clo_workaround_gcc296_bugs) && just_below_esp)
njn5c004e42002-11-18 11:04:50 +0000434 return;
435
njn43c799e2003-04-08 00:08:52 +0000436 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000437 err_extra.axskind = isWrite ? WriteAxs : ReadAxs;
438 err_extra.size = size;
439 err_extra.addrinfo.akind = Undescribed;
440 err_extra.addrinfo.maybe_gcc = just_below_esp;
njn72718642003-07-24 08:45:32 +0000441 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000442}
443
444/* These ones are called from non-generated code */
445
446/* This is for memory errors in pthread functions, as opposed to pthread API
447 errors which are found by the core. */
njn72718642003-07-24 08:45:32 +0000448void MAC_(record_core_mem_error) ( ThreadId tid, Bool isWrite, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000449{
njn43c799e2003-04-08 00:08:52 +0000450 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000451
njn43c799e2003-04-08 00:08:52 +0000452 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000453 err_extra.isWrite = isWrite;
njn72718642003-07-24 08:45:32 +0000454 VG_(maybe_record_error)( tid, CoreMemErr, /*addr*/0, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000455}
456
njn72718642003-07-24 08:45:32 +0000457void MAC_(record_param_error) ( ThreadId tid, Addr a, Bool isWrite,
njn5c004e42002-11-18 11:04:50 +0000458 Char* msg )
459{
njn43c799e2003-04-08 00:08:52 +0000460 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000461
njn72718642003-07-24 08:45:32 +0000462 sk_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000463 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000464 err_extra.addrinfo.akind = Undescribed;
465 err_extra.isWrite = isWrite;
njn72718642003-07-24 08:45:32 +0000466 VG_(maybe_record_error)( tid, ParamErr, a, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000467}
468
njn72718642003-07-24 08:45:32 +0000469void MAC_(record_jump_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000470{
njn43c799e2003-04-08 00:08:52 +0000471 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000472
njn72718642003-07-24 08:45:32 +0000473 sk_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000474 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000475 err_extra.axskind = ExecAxs;
nethercote7250b8f2004-04-13 08:47:35 +0000476 err_extra.size = 1; // size only used for suppressions
njn5c004e42002-11-18 11:04:50 +0000477 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000478 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000479}
480
njn72718642003-07-24 08:45:32 +0000481void MAC_(record_free_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000482{
njn43c799e2003-04-08 00:08:52 +0000483 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000484
njn72718642003-07-24 08:45:32 +0000485 sk_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000486 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000487 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000488 VG_(maybe_record_error)( tid, FreeErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000489}
490
njn72718642003-07-24 08:45:32 +0000491void MAC_(record_freemismatch_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000492{
njn43c799e2003-04-08 00:08:52 +0000493 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000494
njn72718642003-07-24 08:45:32 +0000495 sk_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000496 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000497 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000498 VG_(maybe_record_error)( tid, FreeMismatchErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000499}
500
njn66fe05a2003-07-22 09:12:33 +0000501
njn72718642003-07-24 08:45:32 +0000502// This one not passed a ThreadId, so it grabs it itself.
njnb6cae9f2003-09-04 20:50:47 +0000503void MAC_(record_overlap_error) ( Char* function, OverlapExtra* ov_extra )
njn66fe05a2003-07-22 09:12:33 +0000504{
njn72718642003-07-24 08:45:32 +0000505 VG_(maybe_record_error)( VG_(get_current_or_recent_tid)(),
njnb6cae9f2003-09-04 20:50:47 +0000506 OverlapErr, /*addr*/0, /*s*/function, ov_extra );
njn66fe05a2003-07-22 09:12:33 +0000507}
508
509
njnb6cae9f2003-09-04 20:50:47 +0000510/* Updates the copy with address info if necessary (but not for all errors). */
njn43c799e2003-04-08 00:08:52 +0000511UInt SK_(update_extra)( Error* err )
512{
njnb6cae9f2003-09-04 20:50:47 +0000513 switch (VG_(get_error_kind)(err)) {
514 case ValueErr:
515 case CoreMemErr:
516 case AddrErr:
517 case ParamErr:
518 case UserErr:
519 case FreeErr:
520 case FreeMismatchErr: {
521 MAC_Error* extra = (MAC_Error*)VG_(get_error_extra)(err);
522 if (extra != NULL && Undescribed == extra->addrinfo.akind) {
523 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
524 }
525 return sizeof(MAC_Error);
526 }
njn43c799e2003-04-08 00:08:52 +0000527 /* Don't need to return the correct size -- LeakErrs are always shown with
528 VG_(unique_error)() so they're not copied anyway. */
njnb6cae9f2003-09-04 20:50:47 +0000529 case LeakErr: return 0;
530 case OverlapErr: return sizeof(OverlapExtra);
531 default: VG_(skin_panic)("update_extra: bad errkind");
njn43c799e2003-04-08 00:08:52 +0000532 }
njn43c799e2003-04-08 00:08:52 +0000533}
534
535
njn5c004e42002-11-18 11:04:50 +0000536/*------------------------------------------------------------*/
537/*--- Suppressions ---*/
538/*------------------------------------------------------------*/
539
njn43c799e2003-04-08 00:08:52 +0000540Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
541{
542 SuppKind skind;
543
544 if (VG_STREQ(name, "Param")) skind = ParamSupp;
545 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
546 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
547 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
548 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
549 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
njnc0616662003-06-12 09:58:41 +0000550 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
njn43c799e2003-04-08 00:08:52 +0000551 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
552 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
njne9cab142003-09-19 08:10:07 +0000553 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
njn43c799e2003-04-08 00:08:52 +0000554 else
555 return False;
556
557 VG_(set_supp_kind)(su, skind);
558 return True;
559}
560
njn5c004e42002-11-18 11:04:50 +0000561Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
562{
563 Bool eof;
564
565 if (VG_(get_supp_kind)(su) == ParamSupp) {
566 eof = VG_(get_line) ( fd, buf, nBuf );
567 if (eof) return False;
568 VG_(set_supp_string)(su, VG_(strdup)(buf));
569 }
570 return True;
571}
572
sewardj99aac972002-12-26 01:53:45 +0000573Bool SK_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000574{
sewardj05bcdcb2003-05-18 10:05:38 +0000575 Int su_size;
njn43c799e2003-04-08 00:08:52 +0000576 MAC_Error* err_extra = VG_(get_error_extra)(err);
577 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000578
579 switch (VG_(get_supp_kind)(su)) {
580 case ParamSupp:
581 return (ekind == ParamErr
njn43c799e2003-04-08 00:08:52 +0000582 && VG_STREQ(VG_(get_error_string)(err),
583 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000584
585 case CoreMemSupp:
586 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000587 && VG_STREQ(VG_(get_error_string)(err),
588 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000589
590 case Value0Supp: su_size = 0; goto value_case;
591 case Value1Supp: su_size = 1; goto value_case;
592 case Value2Supp: su_size = 2; goto value_case;
593 case Value4Supp: su_size = 4; goto value_case;
594 case Value8Supp: su_size = 8; goto value_case;
njnc0616662003-06-12 09:58:41 +0000595 case Value16Supp:su_size =16; goto value_case;
njn5c004e42002-11-18 11:04:50 +0000596 value_case:
597 return (ekind == ValueErr && err_extra->size == su_size);
598
599 case Addr1Supp: su_size = 1; goto addr_case;
600 case Addr2Supp: su_size = 2; goto addr_case;
601 case Addr4Supp: su_size = 4; goto addr_case;
602 case Addr8Supp: su_size = 8; goto addr_case;
njnc0616662003-06-12 09:58:41 +0000603 case Addr16Supp:su_size =16; goto addr_case;
njn5c004e42002-11-18 11:04:50 +0000604 addr_case:
605 return (ekind == AddrErr && err_extra->size == su_size);
606
607 case FreeSupp:
608 return (ekind == FreeErr || ekind == FreeMismatchErr);
609
njn34419c12003-05-02 17:24:29 +0000610 case OverlapSupp:
611 return (ekind = OverlapErr);
612
sewardj4a19e2f2002-12-26 11:50:21 +0000613 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000614 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000615
njn5c004e42002-11-18 11:04:50 +0000616 default:
617 VG_(printf)("Error:\n"
618 " unknown suppression type %d\n",
619 VG_(get_supp_kind)(su));
620 VG_(skin_panic)("unknown suppression type in "
621 "SK_(error_matches_suppression)");
622 }
623}
624
njn43c799e2003-04-08 00:08:52 +0000625Char* SK_(get_error_name) ( Error* err )
626{
627 Char* s;
628 switch (VG_(get_error_kind)(err)) {
629 case ParamErr: return "Param";
630 case UserErr: return NULL; /* Can't suppress User errors */
631 case FreeMismatchErr: return "Free";
632 case FreeErr: return "Free";
633 case AddrErr:
634 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
635 case 1: return "Addr1";
636 case 2: return "Addr2";
637 case 4: return "Addr4";
638 case 8: return "Addr8";
njnc0616662003-06-12 09:58:41 +0000639 case 16: return "Addr16";
njn43c799e2003-04-08 00:08:52 +0000640 default: VG_(skin_panic)("unexpected size for Addr");
641 }
642
643 case ValueErr:
644 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
645 case 0: return "Cond";
646 case 1: return "Value1";
647 case 2: return "Value2";
648 case 4: return "Value4";
649 case 8: return "Value8";
njnc0616662003-06-12 09:58:41 +0000650 case 16: return "Value16";
njn43c799e2003-04-08 00:08:52 +0000651 default: VG_(skin_panic)("unexpected size for Value");
652 }
653 case CoreMemErr: return "CoreMem";
njn34419c12003-05-02 17:24:29 +0000654 case OverlapErr: return "Overlap";
njn43c799e2003-04-08 00:08:52 +0000655 case LeakErr: return "Leak";
656 default: VG_(skin_panic)("get_error_name: unexpected type");
657 }
658 VG_(printf)(s);
659}
660
661void SK_(print_extra_suppression_info) ( Error* err )
662{
663 if (ParamErr == VG_(get_error_kind)(err)) {
664 VG_(printf)(" %s\n", VG_(get_error_string)(err));
665 }
666}
njn5c004e42002-11-18 11:04:50 +0000667
668/*------------------------------------------------------------*/
669/*--- Crude profiling machinery. ---*/
670/*------------------------------------------------------------*/
671
672/* Event index. If just the name of the fn is given, this means the
673 number of calls to the fn. Otherwise it is the specified event.
674 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
675 The rest are shared.
676
677 10 alloc_secondary_map
678
679 20 get_abit
680M 21 get_vbyte
681 22 set_abit
682M 23 set_vbyte
683 24 get_abits4_ALIGNED
684M 25 get_vbytes4_ALIGNED
685
686 30 set_address_range_perms
687 31 set_address_range_perms(lower byte loop)
688 32 set_address_range_perms(quadword loop)
689 33 set_address_range_perms(upper byte loop)
690
691 35 make_noaccess
692 36 make_writable
693 37 make_readable
694A 38 make_accessible
695
696 40 copy_address_range_state
697 41 copy_address_range_state(byte loop)
698 42 check_writable
699 43 check_writable(byte loop)
700 44 check_readable
701 45 check_readable(byte loop)
702 46 check_readable_asciiz
703 47 check_readable_asciiz(byte loop)
704A 48 check_accessible
705A 49 check_accessible(byte loop)
706
707 50 make_noaccess_aligned
708 51 make_writable_aligned
709
710M 60 helperc_LOADV4
711M 61 helperc_STOREV4
712M 62 helperc_LOADV2
713M 63 helperc_STOREV2
714M 64 helperc_LOADV1
715M 65 helperc_STOREV1
716
717A 66 helperc_ACCESS4
718A 67 helperc_ACCESS2
719A 68 helperc_ACCESS1
720
721M 70 rim_rd_V4_SLOWLY
722M 71 rim_wr_V4_SLOWLY
723M 72 rim_rd_V2_SLOWLY
724M 73 rim_wr_V2_SLOWLY
725M 74 rim_rd_V1_SLOWLY
726M 75 rim_wr_V1_SLOWLY
727
728A 76 ACCESS4_SLOWLY
729A 77 ACCESS2_SLOWLY
730A 78 ACCESS1_SLOWLY
731
732 80 fpu_read
733 81 fpu_read aligned 4
734 82 fpu_read aligned 8
735 83 fpu_read 2
jsewardfca60182004-01-04 23:30:55 +0000736 84 fpu_read 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000737
738M 85 fpu_write
739M 86 fpu_write aligned 4
740M 87 fpu_write aligned 8
741M 88 fpu_write 2
jsewardfca60182004-01-04 23:30:55 +0000742M 89 fpu_write 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000743
744 90 fpu_access
745 91 fpu_access aligned 4
746 92 fpu_access aligned 8
747 93 fpu_access 2
jsewardfca60182004-01-04 23:30:55 +0000748 94 fpu_access 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000749
750 100 fpu_access_check_SLOWLY
751 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000752
753 110 new_mem_stack_4
754 111 new_mem_stack_8
755 112 new_mem_stack_12
756 113 new_mem_stack_16
757 114 new_mem_stack_32
758 115 new_mem_stack
759
760 120 die_mem_stack_4
761 121 die_mem_stack_8
762 122 die_mem_stack_12
763 123 die_mem_stack_16
764 124 die_mem_stack_32
765 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000766*/
767
njn43c799e2003-04-08 00:08:52 +0000768#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000769
njn43c799e2003-04-08 00:08:52 +0000770UInt MAC_(event_ctr)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000771
njnb4aee052003-04-15 14:09:58 +0000772static void init_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000773{
774 Int i;
775 for (i = 0; i < N_PROF_EVENTS; i++)
njn43c799e2003-04-08 00:08:52 +0000776 MAC_(event_ctr)[i] = 0;
njn5c004e42002-11-18 11:04:50 +0000777}
778
njnb4aee052003-04-15 14:09:58 +0000779static void done_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000780{
781 Int i;
782 for (i = 0; i < N_PROF_EVENTS; i++) {
783 if ((i % 10) == 0)
784 VG_(printf)("\n");
njn43c799e2003-04-08 00:08:52 +0000785 if (MAC_(event_ctr)[i] > 0)
786 VG_(printf)( "prof mem event %2d: %d\n", i, MAC_(event_ctr)[i] );
njn5c004e42002-11-18 11:04:50 +0000787 }
788 VG_(printf)("\n");
789}
790
791#else
792
njnb4aee052003-04-15 14:09:58 +0000793static void init_prof_mem ( void ) { }
794static void done_prof_mem ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000795
njn5c004e42002-11-18 11:04:50 +0000796#endif
797
798/*------------------------------------------------------------*/
njn3e884182003-04-15 13:03:23 +0000799/*--- Common initialisation + finalisation ---*/
800/*------------------------------------------------------------*/
801
802void MAC_(common_pre_clo_init)(void)
803{
804 MAC_(malloc_list) = VG_(HT_construct)();
805 init_prof_mem();
806}
807
808void MAC_(common_fini)(void (*leak_check)(void))
809{
810 MAC_(print_malloc_stats)();
811
812 if (VG_(clo_verbosity) == 1) {
813 if (!MAC_(clo_leak_check))
814 VG_(message)(Vg_UserMsg,
815 "For a detailed leak analysis, rerun with: --leak-check=yes");
816
817 VG_(message)(Vg_UserMsg,
818 "For counts of detected errors, rerun with: -v");
819 }
820 if (MAC_(clo_leak_check)) leak_check();
821
822 done_prof_mem();
823}
824
825/*------------------------------------------------------------*/
njn47363ab2003-04-21 13:24:40 +0000826/*--- Common client request handling ---*/
827/*------------------------------------------------------------*/
828
njn72718642003-07-24 08:45:32 +0000829Bool MAC_(handle_common_client_requests)(ThreadId tid, UInt* arg, UInt* ret )
njn47363ab2003-04-21 13:24:40 +0000830{
njnd7994182003-10-02 13:44:04 +0000831 Char* err =
832 "The client requests VALGRIND_MALLOCLIKE_BLOCK and\n"
833 " VALGRIND_FREELIKE_BLOCK have moved. Please recompile your\n"
834 " program to incorporate the updates in the Valgrind header files.\n"
835 " You shouldn't need to change the text of your program at all.\n"
836 " Everything should then work as before. Sorry for the bother.\n";
njn72718642003-07-24 08:45:32 +0000837
838 // Not using 'tid' here because MAC_(new_block)() and MAC_(handle_free)()
839 // grab it themselves. But what they grab should match 'tid', check
840 // this.
841 sk_assert(tid == VG_(get_current_or_recent_tid)());
njn47363ab2003-04-21 13:24:40 +0000842
843 switch (arg[0]) {
njn10785452003-05-20 16:38:24 +0000844 case VG_USERREQ__COUNT_LEAKS: { /* count leaked bytes */
845 UInt** argp = (UInt**)arg;
njne8b5c052003-07-22 22:03:58 +0000846 // MAC_(bytes_leaked) et al were set by the last leak check (or zero
847 // if no prior leak checks performed).
848 *argp[1] = MAC_(bytes_leaked);
849 *argp[2] = MAC_(bytes_dubious);
850 *argp[3] = MAC_(bytes_reachable);
851 *argp[4] = MAC_(bytes_suppressed);
njn47363ab2003-04-21 13:24:40 +0000852 *ret = 0;
853 return True;
njn10785452003-05-20 16:38:24 +0000854 }
njnd7994182003-10-02 13:44:04 +0000855 case VG_USERREQ__MALLOCLIKE_BLOCK__OLD_DO_NOT_USE:
856 case VG_USERREQ__FREELIKE_BLOCK__OLD_DO_NOT_USE:
857 VG_(skin_panic)(err);
858
njn10785452003-05-20 16:38:24 +0000859 case VG_USERREQ__MALLOCLIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000860 Addr p = (Addr)arg[1];
861 UInt sizeB = arg[2];
862 UInt rzB = arg[3];
863 Bool is_zeroed = (Bool)arg[4];
njn47363ab2003-04-21 13:24:40 +0000864
njn72718642003-07-24 08:45:32 +0000865 MAC_(new_block) ( p, sizeB, rzB, is_zeroed, MAC_AllocCustom );
njn10785452003-05-20 16:38:24 +0000866 return True;
867 }
868 case VG_USERREQ__FREELIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000869 Addr p = (Addr)arg[1];
870 UInt rzB = arg[2];
njn10785452003-05-20 16:38:24 +0000871
njn72718642003-07-24 08:45:32 +0000872 MAC_(handle_free) ( p, rzB, MAC_AllocCustom );
njn10785452003-05-20 16:38:24 +0000873 return True;
874 }
njnd7994182003-10-02 13:44:04 +0000875
nethercotee3a53722004-05-05 10:46:22 +0000876 case _VG_USERREQ__MEMCHECK_GET_RECORD_OVERLAP:
877 *ret = (Addr)MAC_(record_overlap_error);
878 return True;
879
njn47363ab2003-04-21 13:24:40 +0000880 default:
881 return False;
882 }
883}
884
885/*------------------------------------------------------------*/
njn5c004e42002-11-18 11:04:50 +0000886/*--- Syscall wrappers ---*/
887/*------------------------------------------------------------*/
888
889void* SK_(pre_syscall) ( ThreadId tid, UInt syscallno, Bool isBlocking )
890{
891 Int sane = SK_(cheap_sanity_check)();
892 return (void*)sane;
893}
894
895void SK_(post_syscall) ( ThreadId tid, UInt syscallno,
896 void* pre_result, Int res, Bool isBlocking )
897{
898 Int sane_before_call = (Int)pre_result;
899 Bool sane_after_call = SK_(cheap_sanity_check)();
900
901 if ((Int)sane_before_call && (!sane_after_call)) {
902 VG_(message)(Vg_DebugMsg, "post-syscall: ");
903 VG_(message)(Vg_DebugMsg,
904 "probable sanity check failure for syscall number %d\n",
905 syscallno );
906 VG_(skin_panic)("aborting due to the above ... bye!");
907 }
908}
909
njn5c004e42002-11-18 11:04:50 +0000910/*--------------------------------------------------------------------*/
njn43c799e2003-04-08 00:08:52 +0000911/*--- end mac_needs.c ---*/
njn5c004e42002-11-18 11:04:50 +0000912/*--------------------------------------------------------------------*/