blob: 90203f8ae7ee5076d8b12655e71af25fb220e9e0 [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
njnb6cae9f2003-09-04 20:50:47 +0000290 case OverlapErr: {
291 OverlapExtra* ov_extra = (OverlapExtra*)VG_(get_error_extra)(err);
292 if (ov_extra->len == -1)
293 VG_(message)(Vg_UserMsg,
294 "Source and destination overlap in %s(%p, %p)",
295 VG_(get_error_string)(err),
296 ov_extra->dst, ov_extra->src);
297 else
298 VG_(message)(Vg_UserMsg,
299 "Source and destination overlap in %s(%p, %p, %d)",
300 VG_(get_error_string)(err),
301 ov_extra->dst, ov_extra->src, ov_extra->len);
njn66fe05a2003-07-22 09:12:33 +0000302 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
303 break;
njnb6cae9f2003-09-04 20:50:47 +0000304 }
njn43c799e2003-04-08 00:08:52 +0000305 case LeakErr: {
306 /* Totally abusing the types of these spare fields... oh well. */
307 UInt n_this_record = (UInt)VG_(get_error_address)(err);
308 UInt n_total_records = (UInt)VG_(get_error_string) (err);
309
310 MAC_(pp_LeakError)(err_extra, n_this_record, n_total_records);
311 break;
312 }
313
314 default:
315 VG_(printf)("Error:\n unknown Memcheck/Addrcheck error code %d\n",
316 VG_(get_error_kind)(err));
317 VG_(skin_panic)("unknown error code in MAC_(pp_shared_SkinError)");
njn5c004e42002-11-18 11:04:50 +0000318 }
319}
320
321/*------------------------------------------------------------*/
322/*--- Recording errors ---*/
323/*------------------------------------------------------------*/
324
njn43c799e2003-04-08 00:08:52 +0000325/* Additional description function for describe_addr(); used by
326 MemCheck for user blocks, which Addrcheck doesn't support. */
327Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL;
328
njn43c799e2003-04-08 00:08:52 +0000329/* Describe an address as best you can, for error messages,
330 putting the result in ai. */
331static void describe_addr ( Addr a, AddrInfo* ai )
332{
njn3e884182003-04-15 13:03:23 +0000333 MAC_Chunk* sc;
334 ThreadId tid;
njn43c799e2003-04-08 00:08:52 +0000335
336 /* Nested functions, yeah. Need the lexical scoping of 'a'. */
njn3e884182003-04-15 13:03:23 +0000337
njn43c799e2003-04-08 00:08:52 +0000338 /* Closure for searching thread stacks */
339 Bool addr_is_in_bounds(Addr stack_min, Addr stack_max)
340 {
341 return (stack_min <= a && a <= stack_max);
342 }
njn3e884182003-04-15 13:03:23 +0000343 /* Closure for searching free'd list */
344 Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc)
njn43c799e2003-04-08 00:08:52 +0000345 {
njn3e884182003-04-15 13:03:23 +0000346 return VG_(addr_is_in_block)( a, mc->data, mc->size );
347 }
348 /* Closure for searching malloc'd lists */
349 Bool addr_is_in_HashNode(VgHashNode* sh_ch)
350 {
351 return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch );
njn43c799e2003-04-08 00:08:52 +0000352 }
353
354 /* Perhaps it's a user-def'd block ? (only check if requested, though) */
355 if (NULL != MAC_(describe_addr_supp)) {
356 if (MAC_(describe_addr_supp)( a, ai ))
357 return;
358 }
359 /* Perhaps it's on a thread's stack? */
360 tid = VG_(first_matching_thread_stack)(addr_is_in_bounds);
361 if (tid != VG_INVALID_THREADID) {
362 ai->akind = Stack;
363 ai->stack_tid = tid;
364 return;
365 }
366 /* Search for a recently freed block which might bracket it. */
njn3e884182003-04-15 13:03:23 +0000367 sc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk);
368 if (NULL != sc) {
njn43c799e2003-04-08 00:08:52 +0000369 ai->akind = Freed;
njn3e884182003-04-15 13:03:23 +0000370 ai->blksize = sc->size;
371 ai->rwoffset = (Int)a - (Int)sc->data;
372 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000373 return;
374 }
375 /* Search for a currently malloc'd block which might bracket it. */
njn3e884182003-04-15 13:03:23 +0000376 sc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode);
njn43c799e2003-04-08 00:08:52 +0000377 if (NULL != sc) {
378 ai->akind = Mallocd;
njn3e884182003-04-15 13:03:23 +0000379 ai->blksize = sc->size;
380 ai->rwoffset = (Int)(a) - (Int)sc->data;
381 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000382 return;
383 }
384 /* Clueless ... */
385 ai->akind = Unknown;
386 return;
387}
388
njn5c004e42002-11-18 11:04:50 +0000389/* Is this address within some small distance below %ESP? Used only
390 for the --workaround-gcc296-bugs kludge. */
391static Bool is_just_below_ESP( Addr esp, Addr aa )
392{
393 if ((UInt)esp > (UInt)aa
394 && ((UInt)esp - (UInt)aa) <= VG_GCC296_BUG_STACK_SLOP)
395 return True;
396 else
397 return False;
398}
399
sewardjaf48a602003-07-06 00:54:47 +0000400/* This one called from generated code and non-generated code. */
njn5c004e42002-11-18 11:04:50 +0000401
njn72718642003-07-24 08:45:32 +0000402void MAC_(record_address_error) ( ThreadId tid, Addr a, Int size,
sewardjaf48a602003-07-06 00:54:47 +0000403 Bool isWrite )
njn5c004e42002-11-18 11:04:50 +0000404{
njn43c799e2003-04-08 00:08:52 +0000405 MAC_Error err_extra;
406 Bool just_below_esp;
njn5c004e42002-11-18 11:04:50 +0000407
408 just_below_esp = is_just_below_ESP( VG_(get_stack_pointer)(), a );
409
410 /* If this is caused by an access immediately below %ESP, and the
411 user asks nicely, we just ignore it. */
njn43c799e2003-04-08 00:08:52 +0000412 if (MAC_(clo_workaround_gcc296_bugs) && just_below_esp)
njn5c004e42002-11-18 11:04:50 +0000413 return;
414
njn43c799e2003-04-08 00:08:52 +0000415 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000416 err_extra.axskind = isWrite ? WriteAxs : ReadAxs;
417 err_extra.size = size;
418 err_extra.addrinfo.akind = Undescribed;
419 err_extra.addrinfo.maybe_gcc = just_below_esp;
njn72718642003-07-24 08:45:32 +0000420 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000421}
422
423/* These ones are called from non-generated code */
424
425/* This is for memory errors in pthread functions, as opposed to pthread API
426 errors which are found by the core. */
njn72718642003-07-24 08:45:32 +0000427void MAC_(record_core_mem_error) ( ThreadId tid, Bool isWrite, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000428{
njn43c799e2003-04-08 00:08:52 +0000429 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000430
njn43c799e2003-04-08 00:08:52 +0000431 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000432 err_extra.isWrite = isWrite;
njn72718642003-07-24 08:45:32 +0000433 VG_(maybe_record_error)( tid, CoreMemErr, /*addr*/0, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000434}
435
njn72718642003-07-24 08:45:32 +0000436void MAC_(record_param_error) ( ThreadId tid, Addr a, Bool isWrite,
njn5c004e42002-11-18 11:04:50 +0000437 Char* msg )
438{
njn43c799e2003-04-08 00:08:52 +0000439 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000440
njn72718642003-07-24 08:45:32 +0000441 sk_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000442 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000443 err_extra.addrinfo.akind = Undescribed;
444 err_extra.isWrite = isWrite;
njn72718642003-07-24 08:45:32 +0000445 VG_(maybe_record_error)( tid, ParamErr, a, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000446}
447
njn72718642003-07-24 08:45:32 +0000448void MAC_(record_jump_error) ( ThreadId tid, Addr a )
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
njn72718642003-07-24 08:45:32 +0000452 sk_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000453 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000454 err_extra.axskind = ExecAxs;
455 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000456 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000457}
458
njn72718642003-07-24 08:45:32 +0000459void MAC_(record_free_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000460{
njn43c799e2003-04-08 00:08:52 +0000461 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000462
njn72718642003-07-24 08:45:32 +0000463 sk_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000464 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000465 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000466 VG_(maybe_record_error)( tid, FreeErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000467}
468
njn72718642003-07-24 08:45:32 +0000469void MAC_(record_freemismatch_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.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000476 VG_(maybe_record_error)( tid, FreeMismatchErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000477}
478
njn66fe05a2003-07-22 09:12:33 +0000479
njn72718642003-07-24 08:45:32 +0000480// This one not passed a ThreadId, so it grabs it itself.
njnb6cae9f2003-09-04 20:50:47 +0000481void MAC_(record_overlap_error) ( Char* function, OverlapExtra* ov_extra )
njn66fe05a2003-07-22 09:12:33 +0000482{
njn72718642003-07-24 08:45:32 +0000483 VG_(maybe_record_error)( VG_(get_current_or_recent_tid)(),
njnb6cae9f2003-09-04 20:50:47 +0000484 OverlapErr, /*addr*/0, /*s*/function, ov_extra );
njn66fe05a2003-07-22 09:12:33 +0000485}
486
487
njnb6cae9f2003-09-04 20:50:47 +0000488/* Updates the copy with address info if necessary (but not for all errors). */
njn43c799e2003-04-08 00:08:52 +0000489UInt SK_(update_extra)( Error* err )
490{
njnb6cae9f2003-09-04 20:50:47 +0000491 switch (VG_(get_error_kind)(err)) {
492 case ValueErr:
493 case CoreMemErr:
494 case AddrErr:
495 case ParamErr:
496 case UserErr:
497 case FreeErr:
498 case FreeMismatchErr: {
499 MAC_Error* extra = (MAC_Error*)VG_(get_error_extra)(err);
500 if (extra != NULL && Undescribed == extra->addrinfo.akind) {
501 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
502 }
503 return sizeof(MAC_Error);
504 }
njn43c799e2003-04-08 00:08:52 +0000505 /* Don't need to return the correct size -- LeakErrs are always shown with
506 VG_(unique_error)() so they're not copied anyway. */
njnb6cae9f2003-09-04 20:50:47 +0000507 case LeakErr: return 0;
508 case OverlapErr: return sizeof(OverlapExtra);
509 default: VG_(skin_panic)("update_extra: bad errkind");
njn43c799e2003-04-08 00:08:52 +0000510 }
njn43c799e2003-04-08 00:08:52 +0000511}
512
513
njn5c004e42002-11-18 11:04:50 +0000514/*------------------------------------------------------------*/
515/*--- Suppressions ---*/
516/*------------------------------------------------------------*/
517
njn43c799e2003-04-08 00:08:52 +0000518Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
519{
520 SuppKind skind;
521
522 if (VG_STREQ(name, "Param")) skind = ParamSupp;
523 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
524 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
525 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
526 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
527 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
njnc0616662003-06-12 09:58:41 +0000528 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
njn43c799e2003-04-08 00:08:52 +0000529 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
530 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
njne9cab142003-09-19 08:10:07 +0000531 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
njn43c799e2003-04-08 00:08:52 +0000532 else
533 return False;
534
535 VG_(set_supp_kind)(su, skind);
536 return True;
537}
538
njn5c004e42002-11-18 11:04:50 +0000539Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
540{
541 Bool eof;
542
543 if (VG_(get_supp_kind)(su) == ParamSupp) {
544 eof = VG_(get_line) ( fd, buf, nBuf );
545 if (eof) return False;
546 VG_(set_supp_string)(su, VG_(strdup)(buf));
547 }
548 return True;
549}
550
sewardj99aac972002-12-26 01:53:45 +0000551Bool SK_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000552{
sewardj05bcdcb2003-05-18 10:05:38 +0000553 Int su_size;
njn43c799e2003-04-08 00:08:52 +0000554 MAC_Error* err_extra = VG_(get_error_extra)(err);
555 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000556
557 switch (VG_(get_supp_kind)(su)) {
558 case ParamSupp:
559 return (ekind == ParamErr
njn43c799e2003-04-08 00:08:52 +0000560 && VG_STREQ(VG_(get_error_string)(err),
561 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000562
563 case CoreMemSupp:
564 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000565 && VG_STREQ(VG_(get_error_string)(err),
566 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000567
568 case Value0Supp: su_size = 0; goto value_case;
569 case Value1Supp: su_size = 1; goto value_case;
570 case Value2Supp: su_size = 2; goto value_case;
571 case Value4Supp: su_size = 4; goto value_case;
572 case Value8Supp: su_size = 8; goto value_case;
njnc0616662003-06-12 09:58:41 +0000573 case Value16Supp:su_size =16; goto value_case;
njn5c004e42002-11-18 11:04:50 +0000574 value_case:
575 return (ekind == ValueErr && err_extra->size == su_size);
576
577 case Addr1Supp: su_size = 1; goto addr_case;
578 case Addr2Supp: su_size = 2; goto addr_case;
579 case Addr4Supp: su_size = 4; goto addr_case;
580 case Addr8Supp: su_size = 8; goto addr_case;
njnc0616662003-06-12 09:58:41 +0000581 case Addr16Supp:su_size =16; goto addr_case;
njn5c004e42002-11-18 11:04:50 +0000582 addr_case:
583 return (ekind == AddrErr && err_extra->size == su_size);
584
585 case FreeSupp:
586 return (ekind == FreeErr || ekind == FreeMismatchErr);
587
njn34419c12003-05-02 17:24:29 +0000588 case OverlapSupp:
589 return (ekind = OverlapErr);
590
sewardj4a19e2f2002-12-26 11:50:21 +0000591 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000592 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000593
njn5c004e42002-11-18 11:04:50 +0000594 default:
595 VG_(printf)("Error:\n"
596 " unknown suppression type %d\n",
597 VG_(get_supp_kind)(su));
598 VG_(skin_panic)("unknown suppression type in "
599 "SK_(error_matches_suppression)");
600 }
601}
602
njn43c799e2003-04-08 00:08:52 +0000603Char* SK_(get_error_name) ( Error* err )
604{
605 Char* s;
606 switch (VG_(get_error_kind)(err)) {
607 case ParamErr: return "Param";
608 case UserErr: return NULL; /* Can't suppress User errors */
609 case FreeMismatchErr: return "Free";
610 case FreeErr: return "Free";
611 case AddrErr:
612 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
613 case 1: return "Addr1";
614 case 2: return "Addr2";
615 case 4: return "Addr4";
616 case 8: return "Addr8";
njnc0616662003-06-12 09:58:41 +0000617 case 16: return "Addr16";
njn43c799e2003-04-08 00:08:52 +0000618 default: VG_(skin_panic)("unexpected size for Addr");
619 }
620
621 case ValueErr:
622 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
623 case 0: return "Cond";
624 case 1: return "Value1";
625 case 2: return "Value2";
626 case 4: return "Value4";
627 case 8: return "Value8";
njnc0616662003-06-12 09:58:41 +0000628 case 16: return "Value16";
njn43c799e2003-04-08 00:08:52 +0000629 default: VG_(skin_panic)("unexpected size for Value");
630 }
631 case CoreMemErr: return "CoreMem";
njn34419c12003-05-02 17:24:29 +0000632 case OverlapErr: return "Overlap";
njn43c799e2003-04-08 00:08:52 +0000633 case LeakErr: return "Leak";
634 default: VG_(skin_panic)("get_error_name: unexpected type");
635 }
636 VG_(printf)(s);
637}
638
639void SK_(print_extra_suppression_info) ( Error* err )
640{
641 if (ParamErr == VG_(get_error_kind)(err)) {
642 VG_(printf)(" %s\n", VG_(get_error_string)(err));
643 }
644}
njn5c004e42002-11-18 11:04:50 +0000645
646/*------------------------------------------------------------*/
647/*--- Crude profiling machinery. ---*/
648/*------------------------------------------------------------*/
649
650/* Event index. If just the name of the fn is given, this means the
651 number of calls to the fn. Otherwise it is the specified event.
652 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
653 The rest are shared.
654
655 10 alloc_secondary_map
656
657 20 get_abit
658M 21 get_vbyte
659 22 set_abit
660M 23 set_vbyte
661 24 get_abits4_ALIGNED
662M 25 get_vbytes4_ALIGNED
663
664 30 set_address_range_perms
665 31 set_address_range_perms(lower byte loop)
666 32 set_address_range_perms(quadword loop)
667 33 set_address_range_perms(upper byte loop)
668
669 35 make_noaccess
670 36 make_writable
671 37 make_readable
672A 38 make_accessible
673
674 40 copy_address_range_state
675 41 copy_address_range_state(byte loop)
676 42 check_writable
677 43 check_writable(byte loop)
678 44 check_readable
679 45 check_readable(byte loop)
680 46 check_readable_asciiz
681 47 check_readable_asciiz(byte loop)
682A 48 check_accessible
683A 49 check_accessible(byte loop)
684
685 50 make_noaccess_aligned
686 51 make_writable_aligned
687
688M 60 helperc_LOADV4
689M 61 helperc_STOREV4
690M 62 helperc_LOADV2
691M 63 helperc_STOREV2
692M 64 helperc_LOADV1
693M 65 helperc_STOREV1
694
695A 66 helperc_ACCESS4
696A 67 helperc_ACCESS2
697A 68 helperc_ACCESS1
698
699M 70 rim_rd_V4_SLOWLY
700M 71 rim_wr_V4_SLOWLY
701M 72 rim_rd_V2_SLOWLY
702M 73 rim_wr_V2_SLOWLY
703M 74 rim_rd_V1_SLOWLY
704M 75 rim_wr_V1_SLOWLY
705
706A 76 ACCESS4_SLOWLY
707A 77 ACCESS2_SLOWLY
708A 78 ACCESS1_SLOWLY
709
710 80 fpu_read
711 81 fpu_read aligned 4
712 82 fpu_read aligned 8
713 83 fpu_read 2
714 84 fpu_read 10/28/108
715
716M 85 fpu_write
717M 86 fpu_write aligned 4
718M 87 fpu_write aligned 8
719M 88 fpu_write 2
720M 89 fpu_write 10/28/108
721
722 90 fpu_access
723 91 fpu_access aligned 4
724 92 fpu_access aligned 8
725 93 fpu_access 2
726 94 fpu_access 10/28/108
727
728 100 fpu_access_check_SLOWLY
729 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000730
731 110 new_mem_stack_4
732 111 new_mem_stack_8
733 112 new_mem_stack_12
734 113 new_mem_stack_16
735 114 new_mem_stack_32
736 115 new_mem_stack
737
738 120 die_mem_stack_4
739 121 die_mem_stack_8
740 122 die_mem_stack_12
741 123 die_mem_stack_16
742 124 die_mem_stack_32
743 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000744*/
745
njn43c799e2003-04-08 00:08:52 +0000746#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000747
njn43c799e2003-04-08 00:08:52 +0000748UInt MAC_(event_ctr)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000749
njnb4aee052003-04-15 14:09:58 +0000750static void init_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000751{
752 Int i;
753 for (i = 0; i < N_PROF_EVENTS; i++)
njn43c799e2003-04-08 00:08:52 +0000754 MAC_(event_ctr)[i] = 0;
njn5c004e42002-11-18 11:04:50 +0000755}
756
njnb4aee052003-04-15 14:09:58 +0000757static void done_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000758{
759 Int i;
760 for (i = 0; i < N_PROF_EVENTS; i++) {
761 if ((i % 10) == 0)
762 VG_(printf)("\n");
njn43c799e2003-04-08 00:08:52 +0000763 if (MAC_(event_ctr)[i] > 0)
764 VG_(printf)( "prof mem event %2d: %d\n", i, MAC_(event_ctr)[i] );
njn5c004e42002-11-18 11:04:50 +0000765 }
766 VG_(printf)("\n");
767}
768
769#else
770
njnb4aee052003-04-15 14:09:58 +0000771static void init_prof_mem ( void ) { }
772static void done_prof_mem ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000773
njn5c004e42002-11-18 11:04:50 +0000774#endif
775
776/*------------------------------------------------------------*/
njn3e884182003-04-15 13:03:23 +0000777/*--- Common initialisation + finalisation ---*/
778/*------------------------------------------------------------*/
779
780void MAC_(common_pre_clo_init)(void)
781{
782 MAC_(malloc_list) = VG_(HT_construct)();
783 init_prof_mem();
784}
785
786void MAC_(common_fini)(void (*leak_check)(void))
787{
788 MAC_(print_malloc_stats)();
789
790 if (VG_(clo_verbosity) == 1) {
791 if (!MAC_(clo_leak_check))
792 VG_(message)(Vg_UserMsg,
793 "For a detailed leak analysis, rerun with: --leak-check=yes");
794
795 VG_(message)(Vg_UserMsg,
796 "For counts of detected errors, rerun with: -v");
797 }
798 if (MAC_(clo_leak_check)) leak_check();
799
800 done_prof_mem();
801}
802
803/*------------------------------------------------------------*/
njn47363ab2003-04-21 13:24:40 +0000804/*--- Common client request handling ---*/
805/*------------------------------------------------------------*/
806
njn72718642003-07-24 08:45:32 +0000807Bool MAC_(handle_common_client_requests)(ThreadId tid, UInt* arg, UInt* ret )
njn47363ab2003-04-21 13:24:40 +0000808{
njn10785452003-05-20 16:38:24 +0000809 UInt* argv = (UInt*)arg;
njn72718642003-07-24 08:45:32 +0000810
811 // Not using 'tid' here because MAC_(new_block)() and MAC_(handle_free)()
812 // grab it themselves. But what they grab should match 'tid', check
813 // this.
814 sk_assert(tid == VG_(get_current_or_recent_tid)());
njn47363ab2003-04-21 13:24:40 +0000815
816 switch (arg[0]) {
njn10785452003-05-20 16:38:24 +0000817 case VG_USERREQ__COUNT_LEAKS: { /* count leaked bytes */
818 UInt** argp = (UInt**)arg;
njne8b5c052003-07-22 22:03:58 +0000819 // MAC_(bytes_leaked) et al were set by the last leak check (or zero
820 // if no prior leak checks performed).
821 *argp[1] = MAC_(bytes_leaked);
822 *argp[2] = MAC_(bytes_dubious);
823 *argp[3] = MAC_(bytes_reachable);
824 *argp[4] = MAC_(bytes_suppressed);
njn47363ab2003-04-21 13:24:40 +0000825 *ret = 0;
826 return True;
njn10785452003-05-20 16:38:24 +0000827 }
828 case VG_USERREQ__MALLOCLIKE_BLOCK: {
829 Addr p = (Addr)argv[1];
830 UInt sizeB = argv[2];
831 UInt rzB = argv[3];
832 Bool is_zeroed = (Bool)argv[4];
njn47363ab2003-04-21 13:24:40 +0000833
njn72718642003-07-24 08:45:32 +0000834 MAC_(new_block) ( p, sizeB, rzB, is_zeroed, MAC_AllocCustom );
njn10785452003-05-20 16:38:24 +0000835 return True;
836 }
837 case VG_USERREQ__FREELIKE_BLOCK: {
838 Addr p = (Addr)argv[1];
839 UInt rzB = argv[2];
840
njn72718642003-07-24 08:45:32 +0000841 MAC_(handle_free) ( p, rzB, MAC_AllocCustom );
njn10785452003-05-20 16:38:24 +0000842 return True;
843 }
njn47363ab2003-04-21 13:24:40 +0000844 default:
845 return False;
846 }
847}
848
849/*------------------------------------------------------------*/
njn5c004e42002-11-18 11:04:50 +0000850/*--- Syscall wrappers ---*/
851/*------------------------------------------------------------*/
852
853void* SK_(pre_syscall) ( ThreadId tid, UInt syscallno, Bool isBlocking )
854{
855 Int sane = SK_(cheap_sanity_check)();
856 return (void*)sane;
857}
858
859void SK_(post_syscall) ( ThreadId tid, UInt syscallno,
860 void* pre_result, Int res, Bool isBlocking )
861{
862 Int sane_before_call = (Int)pre_result;
863 Bool sane_after_call = SK_(cheap_sanity_check)();
864
865 if ((Int)sane_before_call && (!sane_after_call)) {
866 VG_(message)(Vg_DebugMsg, "post-syscall: ");
867 VG_(message)(Vg_DebugMsg,
868 "probable sanity check failure for syscall number %d\n",
869 syscallno );
870 VG_(skin_panic)("aborting due to the above ... bye!");
871 }
872}
873
njn5c004e42002-11-18 11:04:50 +0000874/*--------------------------------------------------------------------*/
njn43c799e2003-04-08 00:08:52 +0000875/*--- end mac_needs.c ---*/
njn5c004e42002-11-18 11:04:50 +0000876/*--------------------------------------------------------------------*/