blob: e1ef58a8f1414e4e3c90f17dd57db16c31369573 [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{
nethercote27fec902004-06-16 21:26:32 +000059 VG_BOOL_CLO("--leak-check", MAC_(clo_leak_check))
60 else VG_BOOL_CLO("--partial-loads-ok", MAC_(clo_partial_loads_ok))
61 else VG_BOOL_CLO("--show-reachable", MAC_(clo_show_reachable))
62 else VG_BOOL_CLO("--workaround-gcc296-bugs",MAC_(clo_workaround_gcc296_bugs))
63
64 else VG_BNUM_CLO("--freelist-vol", MAC_(clo_freelist_vol), 0, 1000000000)
65
njn43c799e2003-04-08 00:08:52 +000066 else if (VG_CLO_STREQ(arg, "--leak-resolution=low"))
67 MAC_(clo_leak_resolution) = Vg_LowRes;
68 else if (VG_CLO_STREQ(arg, "--leak-resolution=med"))
69 MAC_(clo_leak_resolution) = Vg_MedRes;
70 else if (VG_CLO_STREQ(arg, "--leak-resolution=high"))
71 MAC_(clo_leak_resolution) = Vg_HighRes;
njn5c004e42002-11-18 11:04:50 +000072
73 else
njn3e884182003-04-15 13:03:23 +000074 return VG_(replacement_malloc_process_cmd_line_option)(arg);
njn5c004e42002-11-18 11:04:50 +000075
76 return True;
njn43c799e2003-04-08 00:08:52 +000077}
njn5c004e42002-11-18 11:04:50 +000078
njn3e884182003-04-15 13:03:23 +000079void MAC_(print_common_usage)(void)
njn43c799e2003-04-08 00:08:52 +000080{
njn3e884182003-04-15 13:03:23 +000081 VG_(printf)(
82" --partial-loads-ok=no|yes too hard to explain here; see manual [yes]\n"
83" --freelist-vol=<number> volume of freed blocks queue [1000000]\n"
84" --leak-check=no|yes search for memory leaks at exit? [no]\n"
85" --leak-resolution=low|med|high how much bt merging in leak check [low]\n"
86" --show-reachable=no|yes show reachable blocks in leak check? [no]\n"
87" --workaround-gcc296-bugs=no|yes self explanatory [no]\n"
88 );
89 VG_(replacement_malloc_print_usage)();
njn43c799e2003-04-08 00:08:52 +000090}
91
njn3e884182003-04-15 13:03:23 +000092void MAC_(print_common_debug_usage)(void)
njn43c799e2003-04-08 00:08:52 +000093{
njn3e884182003-04-15 13:03:23 +000094 VG_(replacement_malloc_print_debug_usage)();
njn5c004e42002-11-18 11:04:50 +000095}
96
97/*------------------------------------------------------------*/
98/*--- Comparing and printing errors ---*/
99/*------------------------------------------------------------*/
100
101static __inline__
102void clear_AddrInfo ( AddrInfo* ai )
103{
104 ai->akind = Unknown;
105 ai->blksize = 0;
106 ai->rwoffset = 0;
107 ai->lastchange = NULL;
108 ai->stack_tid = VG_INVALID_THREADID;
109 ai->maybe_gcc = False;
110}
111
njn43c799e2003-04-08 00:08:52 +0000112void MAC_(clear_MAC_Error) ( MAC_Error* err_extra )
njn5c004e42002-11-18 11:04:50 +0000113{
114 err_extra->axskind = ReadAxs;
115 err_extra->size = 0;
116 clear_AddrInfo ( &err_extra->addrinfo );
117 err_extra->isWrite = False;
118}
119
120__attribute__ ((unused))
121static Bool eq_AddrInfo ( VgRes res, AddrInfo* ai1, AddrInfo* ai2 )
122{
123 if (ai1->akind != Undescribed
124 && ai2->akind != Undescribed
125 && ai1->akind != ai2->akind)
126 return False;
127 if (ai1->akind == Freed || ai1->akind == Mallocd) {
128 if (ai1->blksize != ai2->blksize)
129 return False;
130 if (!VG_(eq_ExeContext)(res, ai1->lastchange, ai2->lastchange))
131 return False;
132 }
133 return True;
134}
135
136/* Compare error contexts, to detect duplicates. Note that if they
137 are otherwise the same, the faulting addrs and associated rwoffsets
138 are allowed to be different. */
139
140Bool SK_(eq_SkinError) ( VgRes res, Error* e1, Error* e2 )
141{
njn43c799e2003-04-08 00:08:52 +0000142 MAC_Error* e1_extra = VG_(get_error_extra)(e1);
143 MAC_Error* e2_extra = VG_(get_error_extra)(e2);
njn7cc53a82002-11-19 16:19:32 +0000144
145 /* Guaranteed by calling function */
146 sk_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
njn5c004e42002-11-18 11:04:50 +0000147
148 switch (VG_(get_error_kind)(e1)) {
149 case CoreMemErr: {
150 Char *e1s, *e2s;
151 if (e1_extra->isWrite != e2_extra->isWrite) return False;
njn5c004e42002-11-18 11:04:50 +0000152 e1s = VG_(get_error_string)(e1);
153 e2s = VG_(get_error_string)(e2);
154 if (e1s == e2s) return True;
155 if (0 == VG_(strcmp)(e1s, e2s)) return True;
156 return False;
157 }
158
159 case UserErr:
160 case ParamErr:
161 if (e1_extra->isWrite != e2_extra->isWrite) return False;
162 if (VG_(get_error_kind)(e1) == ParamErr
163 && 0 != VG_(strcmp)(VG_(get_error_string)(e1),
164 VG_(get_error_string)(e2))) return False;
165 return True;
166
167 case FreeErr:
168 case FreeMismatchErr:
169 /* JRS 2002-Aug-26: comparing addrs seems overkill and can
170 cause excessive duplication of errors. Not even AddrErr
171 below does that. So don't compare either the .addr field
172 or the .addrinfo fields. */
173 /* if (e1->addr != e2->addr) return False; */
174 /* if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
175 return False;
176 */
177 return True;
178
179 case AddrErr:
180 /* if (e1_extra->axskind != e2_extra->axskind) return False; */
181 if (e1_extra->size != e2_extra->size) return False;
182 /*
183 if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
184 return False;
185 */
186 return True;
187
188 case ValueErr:
189 if (e1_extra->size != e2_extra->size) return False;
190 return True;
191
njn34419c12003-05-02 17:24:29 +0000192 case OverlapErr:
193 return True;
194
njn43c799e2003-04-08 00:08:52 +0000195 case LeakErr:
196 VG_(skin_panic)("Shouldn't get LeakErr in SK_(eq_SkinError),\n"
197 "since it's handled with VG_(unique_error)()!");
198
rjwalshbc0bb832004-06-19 18:12:36 +0000199 case IllegalMempoolErr:
200 return True;
201
njn5c004e42002-11-18 11:04:50 +0000202 default:
203 VG_(printf)("Error:\n unknown error code %d\n",
204 VG_(get_error_kind)(e1));
205 VG_(skin_panic)("unknown error code in SK_(eq_SkinError)");
206 }
207}
208
njn43c799e2003-04-08 00:08:52 +0000209void MAC_(pp_AddrInfo) ( Addr a, AddrInfo* ai )
njn5c004e42002-11-18 11:04:50 +0000210{
211 switch (ai->akind) {
212 case Stack:
213 VG_(message)(Vg_UserMsg,
nethercote3b390c72003-11-13 17:53:43 +0000214 " Address 0x%x is on thread %d's stack",
njn5c004e42002-11-18 11:04:50 +0000215 a, ai->stack_tid);
216 break;
217 case Unknown:
218 if (ai->maybe_gcc) {
219 VG_(message)(Vg_UserMsg,
nethercote3b390c72003-11-13 17:53:43 +0000220 " Address 0x%x is just below %%esp. Possibly a bug in GCC/G++",
njn5c004e42002-11-18 11:04:50 +0000221 a);
222 VG_(message)(Vg_UserMsg,
nethercote3b390c72003-11-13 17:53:43 +0000223 " v 2.96 or 3.0.X. To suppress, use: --workaround-gcc296-bugs=yes");
njn5c004e42002-11-18 11:04:50 +0000224 } else {
225 VG_(message)(Vg_UserMsg,
nethercotef798eee2004-04-13 08:36:35 +0000226 " Address 0x%x is not stack'd, malloc'd or (recently) free'd",a);
njn5c004e42002-11-18 11:04:50 +0000227 }
228 break;
rjwalshbc0bb832004-06-19 18:12:36 +0000229 case Freed: case Mallocd: case UserG: case Mempool: {
nethercote50397c22004-11-04 18:03:06 +0000230 SizeT delta;
njn5c004e42002-11-18 11:04:50 +0000231 UChar* relative;
rjwalshbc0bb832004-06-19 18:12:36 +0000232 UChar* kind;
233 if (ai->akind == Mempool) {
234 kind = "mempool";
235 } else {
236 kind = "block";
237 }
njn5c004e42002-11-18 11:04:50 +0000238 if (ai->rwoffset < 0) {
nethercote50397c22004-11-04 18:03:06 +0000239 delta = (SizeT)(- ai->rwoffset);
njn5c004e42002-11-18 11:04:50 +0000240 relative = "before";
241 } else if (ai->rwoffset >= ai->blksize) {
242 delta = ai->rwoffset - ai->blksize;
243 relative = "after";
244 } else {
245 delta = ai->rwoffset;
246 relative = "inside";
247 }
sewardja81709d2002-12-28 12:55:48 +0000248 VG_(message)(Vg_UserMsg,
nethercote50397c22004-11-04 18:03:06 +0000249 " Address 0x%x is %llu bytes %s a %s of size %d %s",
250 a, (ULong)delta, relative, kind,
sewardja81709d2002-12-28 12:55:48 +0000251 ai->blksize,
252 ai->akind==Mallocd ? "alloc'd"
253 : ai->akind==Freed ? "free'd"
254 : "client-defined");
njn5c004e42002-11-18 11:04:50 +0000255 VG_(pp_ExeContext)(ai->lastchange);
256 break;
257 }
258 default:
njn43c799e2003-04-08 00:08:52 +0000259 VG_(skin_panic)("MAC_(pp_AddrInfo)");
260 }
261}
262
263/* This prints out the message for the error types where Memcheck and
264 Addrcheck have identical messages */
265void MAC_(pp_shared_SkinError) ( Error* err )
266{
267 MAC_Error* err_extra = VG_(get_error_extra)(err);
268
269 switch (VG_(get_error_kind)(err)) {
270 case FreeErr:
njn10785452003-05-20 16:38:24 +0000271 VG_(message)(Vg_UserMsg, "Invalid free() / delete / delete[]");
njn43c799e2003-04-08 00:08:52 +0000272 /* fall through */
273 case FreeMismatchErr:
274 if (VG_(get_error_kind)(err) == FreeMismatchErr)
275 VG_(message)(Vg_UserMsg,
276 "Mismatched free() / delete / delete []");
277 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
278 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
279 break;
280
njn89409f82003-09-26 14:55:31 +0000281 case AddrErr:
282 switch (err_extra->axskind) {
283 case ReadAxs:
284 VG_(message)(Vg_UserMsg, "Invalid read of size %d",
285 err_extra->size );
286 break;
287 case WriteAxs:
288 VG_(message)(Vg_UserMsg, "Invalid write of size %d",
289 err_extra->size );
290 break;
291 case ExecAxs:
292 VG_(message)(Vg_UserMsg, "Jump to the invalid address "
293 "stated on the next line");
294 break;
295 default:
296 VG_(skin_panic)("SK_(pp_SkinError)(axskind)");
297 }
298 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
299 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
300 break;
301
njnb6cae9f2003-09-04 20:50:47 +0000302 case OverlapErr: {
303 OverlapExtra* ov_extra = (OverlapExtra*)VG_(get_error_extra)(err);
304 if (ov_extra->len == -1)
305 VG_(message)(Vg_UserMsg,
306 "Source and destination overlap in %s(%p, %p)",
307 VG_(get_error_string)(err),
308 ov_extra->dst, ov_extra->src);
309 else
310 VG_(message)(Vg_UserMsg,
311 "Source and destination overlap in %s(%p, %p, %d)",
312 VG_(get_error_string)(err),
313 ov_extra->dst, ov_extra->src, ov_extra->len);
njn66fe05a2003-07-22 09:12:33 +0000314 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
315 break;
njnb6cae9f2003-09-04 20:50:47 +0000316 }
njn43c799e2003-04-08 00:08:52 +0000317 case LeakErr: {
318 /* Totally abusing the types of these spare fields... oh well. */
319 UInt n_this_record = (UInt)VG_(get_error_address)(err);
320 UInt n_total_records = (UInt)VG_(get_error_string) (err);
321
322 MAC_(pp_LeakError)(err_extra, n_this_record, n_total_records);
323 break;
324 }
325
rjwalshbc0bb832004-06-19 18:12:36 +0000326 case IllegalMempoolErr:
327 VG_(message)(Vg_UserMsg, "Illegal memory pool address");
328 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
329 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
330 break;
331
njn43c799e2003-04-08 00:08:52 +0000332 default:
333 VG_(printf)("Error:\n unknown Memcheck/Addrcheck error code %d\n",
334 VG_(get_error_kind)(err));
335 VG_(skin_panic)("unknown error code in MAC_(pp_shared_SkinError)");
njn5c004e42002-11-18 11:04:50 +0000336 }
337}
338
339/*------------------------------------------------------------*/
340/*--- Recording errors ---*/
341/*------------------------------------------------------------*/
342
njn43c799e2003-04-08 00:08:52 +0000343/* Additional description function for describe_addr(); used by
344 MemCheck for user blocks, which Addrcheck doesn't support. */
345Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL;
thughes4ad52d02004-06-27 17:37:21 +0000346
347/* Callback for searching thread stacks */
348static Bool addr_is_in_bounds(Addr stack_min, Addr stack_max, void *ap)
349{
350 Addr a = *(Addr *)ap;
351
352 return (stack_min <= a && a <= stack_max);
353}
354
355/* Callback for searching free'd list */
356static Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc, void *ap)
357{
358 Addr a = *(Addr *)ap;
359
360 return VG_(addr_is_in_block)( a, mc->data, mc->size );
361}
362
363/* Callback for searching malloc'd lists */
364static Bool addr_is_in_HashNode(VgHashNode* sh_ch, void *ap)
365{
366 return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch, ap );
367}
368
njn43c799e2003-04-08 00:08:52 +0000369/* Describe an address as best you can, for error messages,
370 putting the result in ai. */
371static void describe_addr ( Addr a, AddrInfo* ai )
372{
njn3e884182003-04-15 13:03:23 +0000373 MAC_Chunk* sc;
374 ThreadId tid;
njn43c799e2003-04-08 00:08:52 +0000375
njn43c799e2003-04-08 00:08:52 +0000376 /* Perhaps it's a user-def'd block ? (only check if requested, though) */
377 if (NULL != MAC_(describe_addr_supp)) {
378 if (MAC_(describe_addr_supp)( a, ai ))
379 return;
380 }
381 /* Perhaps it's on a thread's stack? */
thughes4ad52d02004-06-27 17:37:21 +0000382 tid = VG_(first_matching_thread_stack)(addr_is_in_bounds, &a);
njn43c799e2003-04-08 00:08:52 +0000383 if (tid != VG_INVALID_THREADID) {
384 ai->akind = Stack;
385 ai->stack_tid = tid;
386 return;
387 }
388 /* Search for a recently freed block which might bracket it. */
thughes4ad52d02004-06-27 17:37:21 +0000389 sc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk, &a);
njn3e884182003-04-15 13:03:23 +0000390 if (NULL != sc) {
njn43c799e2003-04-08 00:08:52 +0000391 ai->akind = Freed;
njn3e884182003-04-15 13:03:23 +0000392 ai->blksize = sc->size;
393 ai->rwoffset = (Int)a - (Int)sc->data;
394 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000395 return;
396 }
397 /* Search for a currently malloc'd block which might bracket it. */
thughes4ad52d02004-06-27 17:37:21 +0000398 sc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode, &a);
njn43c799e2003-04-08 00:08:52 +0000399 if (NULL != sc) {
400 ai->akind = Mallocd;
njn3e884182003-04-15 13:03:23 +0000401 ai->blksize = sc->size;
402 ai->rwoffset = (Int)(a) - (Int)sc->data;
403 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000404 return;
405 }
406 /* Clueless ... */
407 ai->akind = Unknown;
408 return;
409}
410
njn5c004e42002-11-18 11:04:50 +0000411/* Is this address within some small distance below %ESP? Used only
412 for the --workaround-gcc296-bugs kludge. */
413static Bool is_just_below_ESP( Addr esp, Addr aa )
414{
nethercote50397c22004-11-04 18:03:06 +0000415 if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
njn5c004e42002-11-18 11:04:50 +0000416 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
rjwalshbc0bb832004-06-19 18:12:36 +0000491void MAC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )
492{
493 MAC_Error err_extra;
494
495 sk_assert(VG_INVALID_THREADID != tid);
496 MAC_(clear_MAC_Error)( &err_extra );
497 err_extra.addrinfo.akind = Undescribed;
498 VG_(maybe_record_error)( tid, IllegalMempoolErr, a, /*s*/NULL, &err_extra );
499}
500
njn72718642003-07-24 08:45:32 +0000501void MAC_(record_freemismatch_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000502{
njn43c799e2003-04-08 00:08:52 +0000503 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000504
njn72718642003-07-24 08:45:32 +0000505 sk_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000506 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000507 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000508 VG_(maybe_record_error)( tid, FreeMismatchErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000509}
510
njn66fe05a2003-07-22 09:12:33 +0000511
njn72718642003-07-24 08:45:32 +0000512// This one not passed a ThreadId, so it grabs it itself.
njnb6cae9f2003-09-04 20:50:47 +0000513void MAC_(record_overlap_error) ( Char* function, OverlapExtra* ov_extra )
njn66fe05a2003-07-22 09:12:33 +0000514{
njn72718642003-07-24 08:45:32 +0000515 VG_(maybe_record_error)( VG_(get_current_or_recent_tid)(),
njnb6cae9f2003-09-04 20:50:47 +0000516 OverlapErr, /*addr*/0, /*s*/function, ov_extra );
njn66fe05a2003-07-22 09:12:33 +0000517}
518
519
njnb6cae9f2003-09-04 20:50:47 +0000520/* Updates the copy with address info if necessary (but not for all errors). */
njn43c799e2003-04-08 00:08:52 +0000521UInt SK_(update_extra)( Error* err )
522{
njnb6cae9f2003-09-04 20:50:47 +0000523 switch (VG_(get_error_kind)(err)) {
524 case ValueErr:
525 case CoreMemErr:
526 case AddrErr:
527 case ParamErr:
528 case UserErr:
529 case FreeErr:
rjwalshbc0bb832004-06-19 18:12:36 +0000530 case IllegalMempoolErr:
njnb6cae9f2003-09-04 20:50:47 +0000531 case FreeMismatchErr: {
532 MAC_Error* extra = (MAC_Error*)VG_(get_error_extra)(err);
533 if (extra != NULL && Undescribed == extra->addrinfo.akind) {
534 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
535 }
536 return sizeof(MAC_Error);
537 }
njn43c799e2003-04-08 00:08:52 +0000538 /* Don't need to return the correct size -- LeakErrs are always shown with
539 VG_(unique_error)() so they're not copied anyway. */
njnb6cae9f2003-09-04 20:50:47 +0000540 case LeakErr: return 0;
541 case OverlapErr: return sizeof(OverlapExtra);
542 default: VG_(skin_panic)("update_extra: bad errkind");
njn43c799e2003-04-08 00:08:52 +0000543 }
njn43c799e2003-04-08 00:08:52 +0000544}
545
546
njn5c004e42002-11-18 11:04:50 +0000547/*------------------------------------------------------------*/
548/*--- Suppressions ---*/
549/*------------------------------------------------------------*/
550
njn43c799e2003-04-08 00:08:52 +0000551Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
552{
553 SuppKind skind;
554
555 if (VG_STREQ(name, "Param")) skind = ParamSupp;
556 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
557 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
558 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
559 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
560 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
njnc0616662003-06-12 09:58:41 +0000561 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
njn43c799e2003-04-08 00:08:52 +0000562 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
563 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
njne9cab142003-09-19 08:10:07 +0000564 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
rjwalshbc0bb832004-06-19 18:12:36 +0000565 else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
njn43c799e2003-04-08 00:08:52 +0000566 else
567 return False;
568
569 VG_(set_supp_kind)(su, skind);
570 return True;
571}
572
njn5c004e42002-11-18 11:04:50 +0000573Bool SK_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
574{
575 Bool eof;
576
577 if (VG_(get_supp_kind)(su) == ParamSupp) {
578 eof = VG_(get_line) ( fd, buf, nBuf );
579 if (eof) return False;
580 VG_(set_supp_string)(su, VG_(strdup)(buf));
581 }
582 return True;
583}
584
sewardj99aac972002-12-26 01:53:45 +0000585Bool SK_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000586{
sewardj05bcdcb2003-05-18 10:05:38 +0000587 Int su_size;
njn43c799e2003-04-08 00:08:52 +0000588 MAC_Error* err_extra = VG_(get_error_extra)(err);
589 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000590
591 switch (VG_(get_supp_kind)(su)) {
592 case ParamSupp:
593 return (ekind == ParamErr
njn43c799e2003-04-08 00:08:52 +0000594 && VG_STREQ(VG_(get_error_string)(err),
595 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000596
597 case CoreMemSupp:
598 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000599 && VG_STREQ(VG_(get_error_string)(err),
600 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000601
602 case Value0Supp: su_size = 0; goto value_case;
603 case Value1Supp: su_size = 1; goto value_case;
604 case Value2Supp: su_size = 2; goto value_case;
605 case Value4Supp: su_size = 4; goto value_case;
606 case Value8Supp: su_size = 8; goto value_case;
njnc0616662003-06-12 09:58:41 +0000607 case Value16Supp:su_size =16; goto value_case;
njn5c004e42002-11-18 11:04:50 +0000608 value_case:
609 return (ekind == ValueErr && err_extra->size == su_size);
610
611 case Addr1Supp: su_size = 1; goto addr_case;
612 case Addr2Supp: su_size = 2; goto addr_case;
613 case Addr4Supp: su_size = 4; goto addr_case;
614 case Addr8Supp: su_size = 8; goto addr_case;
njnc0616662003-06-12 09:58:41 +0000615 case Addr16Supp:su_size =16; goto addr_case;
njn5c004e42002-11-18 11:04:50 +0000616 addr_case:
617 return (ekind == AddrErr && err_extra->size == su_size);
618
619 case FreeSupp:
620 return (ekind == FreeErr || ekind == FreeMismatchErr);
621
njn34419c12003-05-02 17:24:29 +0000622 case OverlapSupp:
623 return (ekind = OverlapErr);
624
sewardj4a19e2f2002-12-26 11:50:21 +0000625 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000626 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000627
rjwalshbc0bb832004-06-19 18:12:36 +0000628 case MempoolSupp:
629 return (ekind == IllegalMempoolErr);
630
njn5c004e42002-11-18 11:04:50 +0000631 default:
632 VG_(printf)("Error:\n"
633 " unknown suppression type %d\n",
634 VG_(get_supp_kind)(su));
635 VG_(skin_panic)("unknown suppression type in "
636 "SK_(error_matches_suppression)");
637 }
638}
639
njn43c799e2003-04-08 00:08:52 +0000640Char* SK_(get_error_name) ( Error* err )
641{
642 Char* s;
643 switch (VG_(get_error_kind)(err)) {
644 case ParamErr: return "Param";
645 case UserErr: return NULL; /* Can't suppress User errors */
646 case FreeMismatchErr: return "Free";
rjwalshbc0bb832004-06-19 18:12:36 +0000647 case IllegalMempoolErr: return "Mempool";
njn43c799e2003-04-08 00:08:52 +0000648 case FreeErr: return "Free";
649 case AddrErr:
650 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
651 case 1: return "Addr1";
652 case 2: return "Addr2";
653 case 4: return "Addr4";
654 case 8: return "Addr8";
njnc0616662003-06-12 09:58:41 +0000655 case 16: return "Addr16";
njn43c799e2003-04-08 00:08:52 +0000656 default: VG_(skin_panic)("unexpected size for Addr");
657 }
658
659 case ValueErr:
660 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
661 case 0: return "Cond";
662 case 1: return "Value1";
663 case 2: return "Value2";
664 case 4: return "Value4";
665 case 8: return "Value8";
njnc0616662003-06-12 09:58:41 +0000666 case 16: return "Value16";
njn43c799e2003-04-08 00:08:52 +0000667 default: VG_(skin_panic)("unexpected size for Value");
668 }
669 case CoreMemErr: return "CoreMem";
njn34419c12003-05-02 17:24:29 +0000670 case OverlapErr: return "Overlap";
njn43c799e2003-04-08 00:08:52 +0000671 case LeakErr: return "Leak";
672 default: VG_(skin_panic)("get_error_name: unexpected type");
673 }
674 VG_(printf)(s);
675}
676
677void SK_(print_extra_suppression_info) ( Error* err )
678{
679 if (ParamErr == VG_(get_error_kind)(err)) {
680 VG_(printf)(" %s\n", VG_(get_error_string)(err));
681 }
682}
njn5c004e42002-11-18 11:04:50 +0000683
684/*------------------------------------------------------------*/
685/*--- Crude profiling machinery. ---*/
686/*------------------------------------------------------------*/
687
688/* Event index. If just the name of the fn is given, this means the
689 number of calls to the fn. Otherwise it is the specified event.
690 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
691 The rest are shared.
692
693 10 alloc_secondary_map
694
695 20 get_abit
696M 21 get_vbyte
697 22 set_abit
698M 23 set_vbyte
699 24 get_abits4_ALIGNED
700M 25 get_vbytes4_ALIGNED
701
702 30 set_address_range_perms
703 31 set_address_range_perms(lower byte loop)
704 32 set_address_range_perms(quadword loop)
705 33 set_address_range_perms(upper byte loop)
706
707 35 make_noaccess
708 36 make_writable
709 37 make_readable
710A 38 make_accessible
711
712 40 copy_address_range_state
713 41 copy_address_range_state(byte loop)
714 42 check_writable
715 43 check_writable(byte loop)
716 44 check_readable
717 45 check_readable(byte loop)
718 46 check_readable_asciiz
719 47 check_readable_asciiz(byte loop)
720A 48 check_accessible
721A 49 check_accessible(byte loop)
722
723 50 make_noaccess_aligned
724 51 make_writable_aligned
725
726M 60 helperc_LOADV4
727M 61 helperc_STOREV4
728M 62 helperc_LOADV2
729M 63 helperc_STOREV2
730M 64 helperc_LOADV1
731M 65 helperc_STOREV1
732
733A 66 helperc_ACCESS4
734A 67 helperc_ACCESS2
735A 68 helperc_ACCESS1
736
737M 70 rim_rd_V4_SLOWLY
738M 71 rim_wr_V4_SLOWLY
739M 72 rim_rd_V2_SLOWLY
740M 73 rim_wr_V2_SLOWLY
741M 74 rim_rd_V1_SLOWLY
742M 75 rim_wr_V1_SLOWLY
743
744A 76 ACCESS4_SLOWLY
745A 77 ACCESS2_SLOWLY
746A 78 ACCESS1_SLOWLY
747
748 80 fpu_read
749 81 fpu_read aligned 4
750 82 fpu_read aligned 8
751 83 fpu_read 2
jsewardfca60182004-01-04 23:30:55 +0000752 84 fpu_read 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000753
754M 85 fpu_write
755M 86 fpu_write aligned 4
756M 87 fpu_write aligned 8
757M 88 fpu_write 2
jsewardfca60182004-01-04 23:30:55 +0000758M 89 fpu_write 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000759
760 90 fpu_access
761 91 fpu_access aligned 4
762 92 fpu_access aligned 8
763 93 fpu_access 2
jsewardfca60182004-01-04 23:30:55 +0000764 94 fpu_access 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000765
766 100 fpu_access_check_SLOWLY
767 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000768
769 110 new_mem_stack_4
770 111 new_mem_stack_8
771 112 new_mem_stack_12
772 113 new_mem_stack_16
773 114 new_mem_stack_32
774 115 new_mem_stack
775
776 120 die_mem_stack_4
777 121 die_mem_stack_8
778 122 die_mem_stack_12
779 123 die_mem_stack_16
780 124 die_mem_stack_32
781 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000782*/
783
njn43c799e2003-04-08 00:08:52 +0000784#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000785
njn43c799e2003-04-08 00:08:52 +0000786UInt MAC_(event_ctr)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000787
njnb4aee052003-04-15 14:09:58 +0000788static void init_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000789{
790 Int i;
791 for (i = 0; i < N_PROF_EVENTS; i++)
njn43c799e2003-04-08 00:08:52 +0000792 MAC_(event_ctr)[i] = 0;
njn5c004e42002-11-18 11:04:50 +0000793}
794
njnb4aee052003-04-15 14:09:58 +0000795static void done_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000796{
797 Int i;
798 for (i = 0; i < N_PROF_EVENTS; i++) {
799 if ((i % 10) == 0)
800 VG_(printf)("\n");
njn43c799e2003-04-08 00:08:52 +0000801 if (MAC_(event_ctr)[i] > 0)
802 VG_(printf)( "prof mem event %2d: %d\n", i, MAC_(event_ctr)[i] );
njn5c004e42002-11-18 11:04:50 +0000803 }
804 VG_(printf)("\n");
805}
806
807#else
808
njnb4aee052003-04-15 14:09:58 +0000809static void init_prof_mem ( void ) { }
810static void done_prof_mem ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000811
njn5c004e42002-11-18 11:04:50 +0000812#endif
813
814/*------------------------------------------------------------*/
njn3e884182003-04-15 13:03:23 +0000815/*--- Common initialisation + finalisation ---*/
816/*------------------------------------------------------------*/
817
818void MAC_(common_pre_clo_init)(void)
819{
820 MAC_(malloc_list) = VG_(HT_construct)();
rjwalshbc0bb832004-06-19 18:12:36 +0000821 MAC_(mempool_list) = VG_(HT_construct)();
njn3e884182003-04-15 13:03:23 +0000822 init_prof_mem();
823}
824
825void MAC_(common_fini)(void (*leak_check)(void))
826{
827 MAC_(print_malloc_stats)();
828
829 if (VG_(clo_verbosity) == 1) {
830 if (!MAC_(clo_leak_check))
831 VG_(message)(Vg_UserMsg,
832 "For a detailed leak analysis, rerun with: --leak-check=yes");
833
834 VG_(message)(Vg_UserMsg,
835 "For counts of detected errors, rerun with: -v");
836 }
837 if (MAC_(clo_leak_check)) leak_check();
838
839 done_prof_mem();
840}
841
842/*------------------------------------------------------------*/
njn47363ab2003-04-21 13:24:40 +0000843/*--- Common client request handling ---*/
844/*------------------------------------------------------------*/
845
nethercoted1b64b22004-11-04 18:22:28 +0000846Bool MAC_(handle_common_client_requests)(ThreadId tid, UWord* arg, UWord* ret )
njn47363ab2003-04-21 13:24:40 +0000847{
njnd7994182003-10-02 13:44:04 +0000848 Char* err =
849 "The client requests VALGRIND_MALLOCLIKE_BLOCK and\n"
850 " VALGRIND_FREELIKE_BLOCK have moved. Please recompile your\n"
851 " program to incorporate the updates in the Valgrind header files.\n"
852 " You shouldn't need to change the text of your program at all.\n"
853 " Everything should then work as before. Sorry for the bother.\n";
njn72718642003-07-24 08:45:32 +0000854
855 // Not using 'tid' here because MAC_(new_block)() and MAC_(handle_free)()
856 // grab it themselves. But what they grab should match 'tid', check
857 // this.
858 sk_assert(tid == VG_(get_current_or_recent_tid)());
njn47363ab2003-04-21 13:24:40 +0000859
860 switch (arg[0]) {
njn10785452003-05-20 16:38:24 +0000861 case VG_USERREQ__COUNT_LEAKS: { /* count leaked bytes */
nethercoted1b64b22004-11-04 18:22:28 +0000862 UWord** argp = (UWord**)arg;
njne8b5c052003-07-22 22:03:58 +0000863 // MAC_(bytes_leaked) et al were set by the last leak check (or zero
864 // if no prior leak checks performed).
865 *argp[1] = MAC_(bytes_leaked);
866 *argp[2] = MAC_(bytes_dubious);
867 *argp[3] = MAC_(bytes_reachable);
868 *argp[4] = MAC_(bytes_suppressed);
njn47363ab2003-04-21 13:24:40 +0000869 *ret = 0;
870 return True;
njn10785452003-05-20 16:38:24 +0000871 }
njnd7994182003-10-02 13:44:04 +0000872 case VG_USERREQ__MALLOCLIKE_BLOCK__OLD_DO_NOT_USE:
873 case VG_USERREQ__FREELIKE_BLOCK__OLD_DO_NOT_USE:
874 VG_(skin_panic)(err);
875
njn10785452003-05-20 16:38:24 +0000876 case VG_USERREQ__MALLOCLIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000877 Addr p = (Addr)arg[1];
nethercote928a5f72004-11-03 18:10:37 +0000878 SizeT sizeB = arg[2];
njnd7994182003-10-02 13:44:04 +0000879 UInt rzB = arg[3];
880 Bool is_zeroed = (Bool)arg[4];
njn47363ab2003-04-21 13:24:40 +0000881
nethercote57e36b32004-07-10 14:56:28 +0000882 MAC_(new_block) ( p, sizeB, /*ignored*/0, rzB, is_zeroed,
883 MAC_AllocCustom, MAC_(malloc_list) );
njn10785452003-05-20 16:38:24 +0000884 return True;
885 }
886 case VG_USERREQ__FREELIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000887 Addr p = (Addr)arg[1];
888 UInt rzB = arg[2];
njn10785452003-05-20 16:38:24 +0000889
njn72718642003-07-24 08:45:32 +0000890 MAC_(handle_free) ( p, rzB, MAC_AllocCustom );
njn10785452003-05-20 16:38:24 +0000891 return True;
892 }
njnd7994182003-10-02 13:44:04 +0000893
nethercotee3a53722004-05-05 10:46:22 +0000894 case _VG_USERREQ__MEMCHECK_GET_RECORD_OVERLAP:
895 *ret = (Addr)MAC_(record_overlap_error);
896 return True;
897
rjwalshbc0bb832004-06-19 18:12:36 +0000898 case VG_USERREQ__CREATE_MEMPOOL: {
899 Addr pool = (Addr)arg[1];
900 UInt rzB = arg[2];
901 Bool is_zeroed = (Bool)arg[3];
902
903 MAC_(create_mempool) ( pool, rzB, is_zeroed );
904 return True;
905 }
906
907 case VG_USERREQ__DESTROY_MEMPOOL: {
908 Addr pool = (Addr)arg[1];
909
910 MAC_(destroy_mempool) ( pool );
911 return True;
912 }
913
914 case VG_USERREQ__MEMPOOL_ALLOC: {
915 Addr pool = (Addr)arg[1];
916 Addr addr = (Addr)arg[2];
917 UInt size = arg[3];
918
919 MAC_(mempool_alloc) ( pool, addr, size );
920 return True;
921 }
922
923 case VG_USERREQ__MEMPOOL_FREE: {
924 Addr pool = (Addr)arg[1];
925 Addr addr = (Addr)arg[2];
926
927 MAC_(mempool_free) ( pool, addr );
928 return True;
929 }
930
njn47363ab2003-04-21 13:24:40 +0000931 default:
932 return False;
933 }
934}
935
936/*------------------------------------------------------------*/
njn5c004e42002-11-18 11:04:50 +0000937/*--- Syscall wrappers ---*/
938/*------------------------------------------------------------*/
939
940void* SK_(pre_syscall) ( ThreadId tid, UInt syscallno, Bool isBlocking )
941{
942 Int sane = SK_(cheap_sanity_check)();
943 return (void*)sane;
944}
945
946void SK_(post_syscall) ( ThreadId tid, UInt syscallno,
947 void* pre_result, Int res, Bool isBlocking )
948{
949 Int sane_before_call = (Int)pre_result;
950 Bool sane_after_call = SK_(cheap_sanity_check)();
951
952 if ((Int)sane_before_call && (!sane_after_call)) {
953 VG_(message)(Vg_DebugMsg, "post-syscall: ");
954 VG_(message)(Vg_DebugMsg,
955 "probable sanity check failure for syscall number %d\n",
956 syscallno );
957 VG_(skin_panic)("aborting due to the above ... bye!");
958 }
959}
960
njn5c004e42002-11-18 11:04:50 +0000961/*--------------------------------------------------------------------*/
njn43c799e2003-04-08 00:08:52 +0000962/*--- end mac_needs.c ---*/
njn5c004e42002-11-18 11:04:50 +0000963/*--------------------------------------------------------------------*/