blob: 17ad8a6ba58a595ca02ca20bb5d60802dbc317bf [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
njn66fe05a2003-07-22 09:12:33 +0000290 case OverlapErr:
291 VG_(message)(Vg_UserMsg,
292 "Source and destination overlap in %s",
293 VG_(get_error_string)(err));
294 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
295 break;
296
njn43c799e2003-04-08 00:08:52 +0000297 case LeakErr: {
298 /* Totally abusing the types of these spare fields... oh well. */
299 UInt n_this_record = (UInt)VG_(get_error_address)(err);
300 UInt n_total_records = (UInt)VG_(get_error_string) (err);
301
302 MAC_(pp_LeakError)(err_extra, n_this_record, n_total_records);
303 break;
304 }
305
306 default:
307 VG_(printf)("Error:\n unknown Memcheck/Addrcheck error code %d\n",
308 VG_(get_error_kind)(err));
309 VG_(skin_panic)("unknown error code in MAC_(pp_shared_SkinError)");
njn5c004e42002-11-18 11:04:50 +0000310 }
311}
312
313/*------------------------------------------------------------*/
314/*--- Recording errors ---*/
315/*------------------------------------------------------------*/
316
njn43c799e2003-04-08 00:08:52 +0000317/* Additional description function for describe_addr(); used by
318 MemCheck for user blocks, which Addrcheck doesn't support. */
319Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL;
320
njn43c799e2003-04-08 00:08:52 +0000321/* Describe an address as best you can, for error messages,
322 putting the result in ai. */
323static void describe_addr ( Addr a, AddrInfo* ai )
324{
njn3e884182003-04-15 13:03:23 +0000325 MAC_Chunk* sc;
326 ThreadId tid;
njn43c799e2003-04-08 00:08:52 +0000327
328 /* Nested functions, yeah. Need the lexical scoping of 'a'. */
njn3e884182003-04-15 13:03:23 +0000329
njn43c799e2003-04-08 00:08:52 +0000330 /* Closure for searching thread stacks */
331 Bool addr_is_in_bounds(Addr stack_min, Addr stack_max)
332 {
333 return (stack_min <= a && a <= stack_max);
334 }
njn3e884182003-04-15 13:03:23 +0000335 /* Closure for searching free'd list */
336 Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc)
njn43c799e2003-04-08 00:08:52 +0000337 {
njn3e884182003-04-15 13:03:23 +0000338 return VG_(addr_is_in_block)( a, mc->data, mc->size );
339 }
340 /* Closure for searching malloc'd lists */
341 Bool addr_is_in_HashNode(VgHashNode* sh_ch)
342 {
343 return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch );
njn43c799e2003-04-08 00:08:52 +0000344 }
345
346 /* Perhaps it's a user-def'd block ? (only check if requested, though) */
347 if (NULL != MAC_(describe_addr_supp)) {
348 if (MAC_(describe_addr_supp)( a, ai ))
349 return;
350 }
351 /* Perhaps it's on a thread's stack? */
352 tid = VG_(first_matching_thread_stack)(addr_is_in_bounds);
353 if (tid != VG_INVALID_THREADID) {
354 ai->akind = Stack;
355 ai->stack_tid = tid;
356 return;
357 }
358 /* Search for a recently freed block which might bracket it. */
njn3e884182003-04-15 13:03:23 +0000359 sc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk);
360 if (NULL != sc) {
njn43c799e2003-04-08 00:08:52 +0000361 ai->akind = Freed;
njn3e884182003-04-15 13:03:23 +0000362 ai->blksize = sc->size;
363 ai->rwoffset = (Int)a - (Int)sc->data;
364 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000365 return;
366 }
367 /* Search for a currently malloc'd block which might bracket it. */
njn3e884182003-04-15 13:03:23 +0000368 sc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode);
njn43c799e2003-04-08 00:08:52 +0000369 if (NULL != sc) {
370 ai->akind = Mallocd;
njn3e884182003-04-15 13:03:23 +0000371 ai->blksize = sc->size;
372 ai->rwoffset = (Int)(a) - (Int)sc->data;
373 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000374 return;
375 }
376 /* Clueless ... */
377 ai->akind = Unknown;
378 return;
379}
380
njn5c004e42002-11-18 11:04:50 +0000381/* Is this address within some small distance below %ESP? Used only
382 for the --workaround-gcc296-bugs kludge. */
383static Bool is_just_below_ESP( Addr esp, Addr aa )
384{
385 if ((UInt)esp > (UInt)aa
386 && ((UInt)esp - (UInt)aa) <= VG_GCC296_BUG_STACK_SLOP)
387 return True;
388 else
389 return False;
390}
391
sewardjaf48a602003-07-06 00:54:47 +0000392/* This one called from generated code and non-generated code. */
njn5c004e42002-11-18 11:04:50 +0000393
njn72718642003-07-24 08:45:32 +0000394void MAC_(record_address_error) ( ThreadId tid, Addr a, Int size,
sewardjaf48a602003-07-06 00:54:47 +0000395 Bool isWrite )
njn5c004e42002-11-18 11:04:50 +0000396{
njn43c799e2003-04-08 00:08:52 +0000397 MAC_Error err_extra;
398 Bool just_below_esp;
njn5c004e42002-11-18 11:04:50 +0000399
400 just_below_esp = is_just_below_ESP( VG_(get_stack_pointer)(), a );
401
402 /* If this is caused by an access immediately below %ESP, and the
403 user asks nicely, we just ignore it. */
njn43c799e2003-04-08 00:08:52 +0000404 if (MAC_(clo_workaround_gcc296_bugs) && just_below_esp)
njn5c004e42002-11-18 11:04:50 +0000405 return;
406
njn43c799e2003-04-08 00:08:52 +0000407 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000408 err_extra.axskind = isWrite ? WriteAxs : ReadAxs;
409 err_extra.size = size;
410 err_extra.addrinfo.akind = Undescribed;
411 err_extra.addrinfo.maybe_gcc = just_below_esp;
njn72718642003-07-24 08:45:32 +0000412 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000413}
414
415/* These ones are called from non-generated code */
416
417/* This is for memory errors in pthread functions, as opposed to pthread API
418 errors which are found by the core. */
njn72718642003-07-24 08:45:32 +0000419void MAC_(record_core_mem_error) ( ThreadId tid, Bool isWrite, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000420{
njn43c799e2003-04-08 00:08:52 +0000421 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000422
njn43c799e2003-04-08 00:08:52 +0000423 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000424 err_extra.isWrite = isWrite;
njn72718642003-07-24 08:45:32 +0000425 VG_(maybe_record_error)( tid, CoreMemErr, /*addr*/0, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000426}
427
njn72718642003-07-24 08:45:32 +0000428void MAC_(record_param_error) ( ThreadId tid, Addr a, Bool isWrite,
njn5c004e42002-11-18 11:04:50 +0000429 Char* msg )
430{
njn43c799e2003-04-08 00:08:52 +0000431 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000432
njn72718642003-07-24 08:45:32 +0000433 sk_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000434 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000435 err_extra.addrinfo.akind = Undescribed;
436 err_extra.isWrite = isWrite;
njn72718642003-07-24 08:45:32 +0000437 VG_(maybe_record_error)( tid, ParamErr, a, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000438}
439
njn72718642003-07-24 08:45:32 +0000440void MAC_(record_jump_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000441{
njn43c799e2003-04-08 00:08:52 +0000442 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000443
njn72718642003-07-24 08:45:32 +0000444 sk_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000445 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000446 err_extra.axskind = ExecAxs;
447 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000448 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000449}
450
njn72718642003-07-24 08:45:32 +0000451void MAC_(record_free_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000452{
njn43c799e2003-04-08 00:08:52 +0000453 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000454
njn72718642003-07-24 08:45:32 +0000455 sk_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000456 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000457 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000458 VG_(maybe_record_error)( tid, FreeErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000459}
460
njn72718642003-07-24 08:45:32 +0000461void MAC_(record_freemismatch_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000462{
njn43c799e2003-04-08 00:08:52 +0000463 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000464
njn72718642003-07-24 08:45:32 +0000465 sk_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000466 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000467 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000468 VG_(maybe_record_error)( tid, FreeMismatchErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000469}
470
njn66fe05a2003-07-22 09:12:33 +0000471
njn72718642003-07-24 08:45:32 +0000472// This one not passed a ThreadId, so it grabs it itself.
473void MAC_(record_overlap_error) ( Char* function )
njn66fe05a2003-07-22 09:12:33 +0000474{
475 MAC_Error err_extra;
476
477 MAC_(clear_MAC_Error)( &err_extra );
njn72718642003-07-24 08:45:32 +0000478 VG_(maybe_record_error)( VG_(get_current_or_recent_tid)(),
479 OverlapErr, /*addr*/0, function, &err_extra );
njn66fe05a2003-07-22 09:12:33 +0000480}
481
482
njn43c799e2003-04-08 00:08:52 +0000483/* Updates the copy with address info if necessary (but not for LeakErrs). */
484UInt SK_(update_extra)( Error* err )
485{
486 MAC_Error* extra;
487
488 /* Don't need to return the correct size -- LeakErrs are always shown with
489 VG_(unique_error)() so they're not copied anyway. */
490 if (LeakErr == VG_(get_error_kind)(err))
491 return 0;
492
493 extra = (MAC_Error*)VG_(get_error_extra)(err);
494
495 if (extra != NULL && Undescribed == extra->addrinfo.akind) {
496 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
497 }
498
499 return sizeof(MAC_Error);
500}
501
502
njn5c004e42002-11-18 11:04:50 +0000503/*------------------------------------------------------------*/
504/*--- Suppressions ---*/
505/*------------------------------------------------------------*/
506
njn43c799e2003-04-08 00:08:52 +0000507Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
508{
509 SuppKind skind;
510
511 if (VG_STREQ(name, "Param")) skind = ParamSupp;
512 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
513 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
514 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
515 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
516 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
njnc0616662003-06-12 09:58:41 +0000517 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
njn43c799e2003-04-08 00:08:52 +0000518 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
519 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
520 else
521 return False;
522
523 VG_(set_supp_kind)(su, skind);
524 return True;
525}
526
njn5c004e42002-11-18 11:04:50 +0000527Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
528{
529 Bool eof;
530
531 if (VG_(get_supp_kind)(su) == ParamSupp) {
532 eof = VG_(get_line) ( fd, buf, nBuf );
533 if (eof) return False;
534 VG_(set_supp_string)(su, VG_(strdup)(buf));
535 }
536 return True;
537}
538
sewardj99aac972002-12-26 01:53:45 +0000539Bool SK_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000540{
sewardj05bcdcb2003-05-18 10:05:38 +0000541 Int su_size;
njn43c799e2003-04-08 00:08:52 +0000542 MAC_Error* err_extra = VG_(get_error_extra)(err);
543 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000544
545 switch (VG_(get_supp_kind)(su)) {
546 case ParamSupp:
547 return (ekind == ParamErr
njn43c799e2003-04-08 00:08:52 +0000548 && VG_STREQ(VG_(get_error_string)(err),
549 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000550
551 case CoreMemSupp:
552 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000553 && VG_STREQ(VG_(get_error_string)(err),
554 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000555
556 case Value0Supp: su_size = 0; goto value_case;
557 case Value1Supp: su_size = 1; goto value_case;
558 case Value2Supp: su_size = 2; goto value_case;
559 case Value4Supp: su_size = 4; goto value_case;
560 case Value8Supp: su_size = 8; goto value_case;
njnc0616662003-06-12 09:58:41 +0000561 case Value16Supp:su_size =16; goto value_case;
njn5c004e42002-11-18 11:04:50 +0000562 value_case:
563 return (ekind == ValueErr && err_extra->size == su_size);
564
565 case Addr1Supp: su_size = 1; goto addr_case;
566 case Addr2Supp: su_size = 2; goto addr_case;
567 case Addr4Supp: su_size = 4; goto addr_case;
568 case Addr8Supp: su_size = 8; goto addr_case;
njnc0616662003-06-12 09:58:41 +0000569 case Addr16Supp:su_size =16; goto addr_case;
njn5c004e42002-11-18 11:04:50 +0000570 addr_case:
571 return (ekind == AddrErr && err_extra->size == su_size);
572
573 case FreeSupp:
574 return (ekind == FreeErr || ekind == FreeMismatchErr);
575
njn34419c12003-05-02 17:24:29 +0000576 case OverlapSupp:
577 return (ekind = OverlapErr);
578
sewardj4a19e2f2002-12-26 11:50:21 +0000579 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000580 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000581
njn5c004e42002-11-18 11:04:50 +0000582 default:
583 VG_(printf)("Error:\n"
584 " unknown suppression type %d\n",
585 VG_(get_supp_kind)(su));
586 VG_(skin_panic)("unknown suppression type in "
587 "SK_(error_matches_suppression)");
588 }
589}
590
njn43c799e2003-04-08 00:08:52 +0000591Char* SK_(get_error_name) ( Error* err )
592{
593 Char* s;
594 switch (VG_(get_error_kind)(err)) {
595 case ParamErr: return "Param";
596 case UserErr: return NULL; /* Can't suppress User errors */
597 case FreeMismatchErr: return "Free";
598 case FreeErr: return "Free";
599 case AddrErr:
600 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
601 case 1: return "Addr1";
602 case 2: return "Addr2";
603 case 4: return "Addr4";
604 case 8: return "Addr8";
njnc0616662003-06-12 09:58:41 +0000605 case 16: return "Addr16";
njn43c799e2003-04-08 00:08:52 +0000606 default: VG_(skin_panic)("unexpected size for Addr");
607 }
608
609 case ValueErr:
610 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
611 case 0: return "Cond";
612 case 1: return "Value1";
613 case 2: return "Value2";
614 case 4: return "Value4";
615 case 8: return "Value8";
njnc0616662003-06-12 09:58:41 +0000616 case 16: return "Value16";
njn43c799e2003-04-08 00:08:52 +0000617 default: VG_(skin_panic)("unexpected size for Value");
618 }
619 case CoreMemErr: return "CoreMem";
njn34419c12003-05-02 17:24:29 +0000620 case OverlapErr: return "Overlap";
njn43c799e2003-04-08 00:08:52 +0000621 case LeakErr: return "Leak";
622 default: VG_(skin_panic)("get_error_name: unexpected type");
623 }
624 VG_(printf)(s);
625}
626
627void SK_(print_extra_suppression_info) ( Error* err )
628{
629 if (ParamErr == VG_(get_error_kind)(err)) {
630 VG_(printf)(" %s\n", VG_(get_error_string)(err));
631 }
632}
njn5c004e42002-11-18 11:04:50 +0000633
634/*------------------------------------------------------------*/
635/*--- Crude profiling machinery. ---*/
636/*------------------------------------------------------------*/
637
638/* Event index. If just the name of the fn is given, this means the
639 number of calls to the fn. Otherwise it is the specified event.
640 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
641 The rest are shared.
642
643 10 alloc_secondary_map
644
645 20 get_abit
646M 21 get_vbyte
647 22 set_abit
648M 23 set_vbyte
649 24 get_abits4_ALIGNED
650M 25 get_vbytes4_ALIGNED
651
652 30 set_address_range_perms
653 31 set_address_range_perms(lower byte loop)
654 32 set_address_range_perms(quadword loop)
655 33 set_address_range_perms(upper byte loop)
656
657 35 make_noaccess
658 36 make_writable
659 37 make_readable
660A 38 make_accessible
661
662 40 copy_address_range_state
663 41 copy_address_range_state(byte loop)
664 42 check_writable
665 43 check_writable(byte loop)
666 44 check_readable
667 45 check_readable(byte loop)
668 46 check_readable_asciiz
669 47 check_readable_asciiz(byte loop)
670A 48 check_accessible
671A 49 check_accessible(byte loop)
672
673 50 make_noaccess_aligned
674 51 make_writable_aligned
675
676M 60 helperc_LOADV4
677M 61 helperc_STOREV4
678M 62 helperc_LOADV2
679M 63 helperc_STOREV2
680M 64 helperc_LOADV1
681M 65 helperc_STOREV1
682
683A 66 helperc_ACCESS4
684A 67 helperc_ACCESS2
685A 68 helperc_ACCESS1
686
687M 70 rim_rd_V4_SLOWLY
688M 71 rim_wr_V4_SLOWLY
689M 72 rim_rd_V2_SLOWLY
690M 73 rim_wr_V2_SLOWLY
691M 74 rim_rd_V1_SLOWLY
692M 75 rim_wr_V1_SLOWLY
693
694A 76 ACCESS4_SLOWLY
695A 77 ACCESS2_SLOWLY
696A 78 ACCESS1_SLOWLY
697
698 80 fpu_read
699 81 fpu_read aligned 4
700 82 fpu_read aligned 8
701 83 fpu_read 2
702 84 fpu_read 10/28/108
703
704M 85 fpu_write
705M 86 fpu_write aligned 4
706M 87 fpu_write aligned 8
707M 88 fpu_write 2
708M 89 fpu_write 10/28/108
709
710 90 fpu_access
711 91 fpu_access aligned 4
712 92 fpu_access aligned 8
713 93 fpu_access 2
714 94 fpu_access 10/28/108
715
716 100 fpu_access_check_SLOWLY
717 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000718
719 110 new_mem_stack_4
720 111 new_mem_stack_8
721 112 new_mem_stack_12
722 113 new_mem_stack_16
723 114 new_mem_stack_32
724 115 new_mem_stack
725
726 120 die_mem_stack_4
727 121 die_mem_stack_8
728 122 die_mem_stack_12
729 123 die_mem_stack_16
730 124 die_mem_stack_32
731 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000732*/
733
njn43c799e2003-04-08 00:08:52 +0000734#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000735
njn43c799e2003-04-08 00:08:52 +0000736UInt MAC_(event_ctr)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000737
njnb4aee052003-04-15 14:09:58 +0000738static void init_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000739{
740 Int i;
741 for (i = 0; i < N_PROF_EVENTS; i++)
njn43c799e2003-04-08 00:08:52 +0000742 MAC_(event_ctr)[i] = 0;
njn5c004e42002-11-18 11:04:50 +0000743}
744
njnb4aee052003-04-15 14:09:58 +0000745static void done_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000746{
747 Int i;
748 for (i = 0; i < N_PROF_EVENTS; i++) {
749 if ((i % 10) == 0)
750 VG_(printf)("\n");
njn43c799e2003-04-08 00:08:52 +0000751 if (MAC_(event_ctr)[i] > 0)
752 VG_(printf)( "prof mem event %2d: %d\n", i, MAC_(event_ctr)[i] );
njn5c004e42002-11-18 11:04:50 +0000753 }
754 VG_(printf)("\n");
755}
756
757#else
758
njnb4aee052003-04-15 14:09:58 +0000759static void init_prof_mem ( void ) { }
760static void done_prof_mem ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000761
njn5c004e42002-11-18 11:04:50 +0000762#endif
763
764/*------------------------------------------------------------*/
njn3e884182003-04-15 13:03:23 +0000765/*--- Common initialisation + finalisation ---*/
766/*------------------------------------------------------------*/
767
768void MAC_(common_pre_clo_init)(void)
769{
770 MAC_(malloc_list) = VG_(HT_construct)();
771 init_prof_mem();
772}
773
774void MAC_(common_fini)(void (*leak_check)(void))
775{
776 MAC_(print_malloc_stats)();
777
778 if (VG_(clo_verbosity) == 1) {
779 if (!MAC_(clo_leak_check))
780 VG_(message)(Vg_UserMsg,
781 "For a detailed leak analysis, rerun with: --leak-check=yes");
782
783 VG_(message)(Vg_UserMsg,
784 "For counts of detected errors, rerun with: -v");
785 }
786 if (MAC_(clo_leak_check)) leak_check();
787
788 done_prof_mem();
789}
790
791/*------------------------------------------------------------*/
njn47363ab2003-04-21 13:24:40 +0000792/*--- Common client request handling ---*/
793/*------------------------------------------------------------*/
794
njn72718642003-07-24 08:45:32 +0000795Bool MAC_(handle_common_client_requests)(ThreadId tid, UInt* arg, UInt* ret )
njn47363ab2003-04-21 13:24:40 +0000796{
njn10785452003-05-20 16:38:24 +0000797 UInt* argv = (UInt*)arg;
njn72718642003-07-24 08:45:32 +0000798
799 // Not using 'tid' here because MAC_(new_block)() and MAC_(handle_free)()
800 // grab it themselves. But what they grab should match 'tid', check
801 // this.
802 sk_assert(tid == VG_(get_current_or_recent_tid)());
njn47363ab2003-04-21 13:24:40 +0000803
804 switch (arg[0]) {
njn10785452003-05-20 16:38:24 +0000805 case VG_USERREQ__COUNT_LEAKS: { /* count leaked bytes */
806 UInt** argp = (UInt**)arg;
njne8b5c052003-07-22 22:03:58 +0000807 // MAC_(bytes_leaked) et al were set by the last leak check (or zero
808 // if no prior leak checks performed).
809 *argp[1] = MAC_(bytes_leaked);
810 *argp[2] = MAC_(bytes_dubious);
811 *argp[3] = MAC_(bytes_reachable);
812 *argp[4] = MAC_(bytes_suppressed);
njn47363ab2003-04-21 13:24:40 +0000813 *ret = 0;
814 return True;
njn10785452003-05-20 16:38:24 +0000815 }
816 case VG_USERREQ__MALLOCLIKE_BLOCK: {
817 Addr p = (Addr)argv[1];
818 UInt sizeB = argv[2];
819 UInt rzB = argv[3];
820 Bool is_zeroed = (Bool)argv[4];
njn47363ab2003-04-21 13:24:40 +0000821
njn72718642003-07-24 08:45:32 +0000822 MAC_(new_block) ( p, sizeB, rzB, is_zeroed, MAC_AllocCustom );
njn10785452003-05-20 16:38:24 +0000823 return True;
824 }
825 case VG_USERREQ__FREELIKE_BLOCK: {
826 Addr p = (Addr)argv[1];
827 UInt rzB = argv[2];
828
njn72718642003-07-24 08:45:32 +0000829 MAC_(handle_free) ( p, rzB, MAC_AllocCustom );
njn10785452003-05-20 16:38:24 +0000830 return True;
831 }
njn47363ab2003-04-21 13:24:40 +0000832 default:
833 return False;
834 }
835}
836
837/*------------------------------------------------------------*/
njn5c004e42002-11-18 11:04:50 +0000838/*--- Syscall wrappers ---*/
839/*------------------------------------------------------------*/
840
841void* SK_(pre_syscall) ( ThreadId tid, UInt syscallno, Bool isBlocking )
842{
843 Int sane = SK_(cheap_sanity_check)();
844 return (void*)sane;
845}
846
847void SK_(post_syscall) ( ThreadId tid, UInt syscallno,
848 void* pre_result, Int res, Bool isBlocking )
849{
850 Int sane_before_call = (Int)pre_result;
851 Bool sane_after_call = SK_(cheap_sanity_check)();
852
853 if ((Int)sane_before_call && (!sane_after_call)) {
854 VG_(message)(Vg_DebugMsg, "post-syscall: ");
855 VG_(message)(Vg_DebugMsg,
856 "probable sanity check failure for syscall number %d\n",
857 syscallno );
858 VG_(skin_panic)("aborting due to the above ... bye!");
859 }
860}
861
njn5c004e42002-11-18 11:04:50 +0000862/*--------------------------------------------------------------------*/
njn43c799e2003-04-08 00:08:52 +0000863/*--- end mac_needs.c ---*/
njn5c004e42002-11-18 11:04:50 +0000864/*--------------------------------------------------------------------*/