blob: 2fc4b319114f6a7ad2537f57a8621f384ab045f9 [file] [log] [blame]
njn5c004e42002-11-18 11:04:50 +00001
2/*--------------------------------------------------------------------*/
3/*--- Code that is shared between MemCheck and AddrCheck. ---*/
njn00cae242005-05-09 01:13:44 +00004/*--- mac_shared.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
njn53612422005-03-12 16:22:54 +000012 Copyright (C) 2000-2005 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
sewardjb5f6f512005-03-10 23:59:00 +000050Bool MAC_(clo_partial_loads_ok) = True;
51Int MAC_(clo_freelist_vol) = 1000000;
njn6a329422005-03-12 20:38:13 +000052LeakCheckMode MAC_(clo_leak_check) = LC_Summary;
sewardjb5f6f512005-03-10 23:59:00 +000053VgRes 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{
njn45270a22005-03-27 01:00:11 +000059 VG_BOOL_CLO(arg, "--partial-loads-ok", MAC_(clo_partial_loads_ok))
60 else VG_BOOL_CLO(arg, "--show-reachable", MAC_(clo_show_reachable))
61 else VG_BOOL_CLO(arg, "--workaround-gcc296-bugs",MAC_(clo_workaround_gcc296_bugs))
nethercote27fec902004-06-16 21:26:32 +000062
njn45270a22005-03-27 01:00:11 +000063 else VG_BNUM_CLO(arg, "--freelist-vol", MAC_(clo_freelist_vol), 0, 1000000000)
nethercote27fec902004-06-16 21:26:32 +000064
sewardjb5f6f512005-03-10 23:59:00 +000065 else if (VG_CLO_STREQ(arg, "--leak-check=no"))
66 MAC_(clo_leak_check) = LC_Off;
67 else if (VG_CLO_STREQ(arg, "--leak-check=summary"))
68 MAC_(clo_leak_check) = LC_Summary;
69 else if (VG_CLO_STREQ(arg, "--leak-check=yes") ||
70 VG_CLO_STREQ(arg, "--leak-check=full"))
71 MAC_(clo_leak_check) = LC_Full;
72
njn43c799e2003-04-08 00:08:52 +000073 else if (VG_CLO_STREQ(arg, "--leak-resolution=low"))
74 MAC_(clo_leak_resolution) = Vg_LowRes;
75 else if (VG_CLO_STREQ(arg, "--leak-resolution=med"))
76 MAC_(clo_leak_resolution) = Vg_MedRes;
77 else if (VG_CLO_STREQ(arg, "--leak-resolution=high"))
78 MAC_(clo_leak_resolution) = Vg_HighRes;
njn5c004e42002-11-18 11:04:50 +000079
80 else
njn3e884182003-04-15 13:03:23 +000081 return VG_(replacement_malloc_process_cmd_line_option)(arg);
njn5c004e42002-11-18 11:04:50 +000082
83 return True;
njn43c799e2003-04-08 00:08:52 +000084}
njn5c004e42002-11-18 11:04:50 +000085
njn3e884182003-04-15 13:03:23 +000086void MAC_(print_common_usage)(void)
njn43c799e2003-04-08 00:08:52 +000087{
njn3e884182003-04-15 13:03:23 +000088 VG_(printf)(
sewardjb5f6f512005-03-10 23:59:00 +000089" --partial-loads-ok=no|yes too hard to explain here; see manual [yes]\n"
90" --freelist-vol=<number> volume of freed blocks queue [1000000]\n"
njn6a329422005-03-12 20:38:13 +000091" --leak-check=no|summary|full search for memory leaks at exit? [summary]\n"
sewardjb5f6f512005-03-10 23:59:00 +000092" --leak-resolution=low|med|high how much bt merging in leak check [low]\n"
93" --show-reachable=no|yes show reachable blocks in leak check? [no]\n"
njn3e884182003-04-15 13:03:23 +000094" --workaround-gcc296-bugs=no|yes self explanatory [no]\n"
95 );
96 VG_(replacement_malloc_print_usage)();
njn43c799e2003-04-08 00:08:52 +000097}
98
njn3e884182003-04-15 13:03:23 +000099void MAC_(print_common_debug_usage)(void)
njn43c799e2003-04-08 00:08:52 +0000100{
njn3e884182003-04-15 13:03:23 +0000101 VG_(replacement_malloc_print_debug_usage)();
njn5c004e42002-11-18 11:04:50 +0000102}
103
104/*------------------------------------------------------------*/
105/*--- Comparing and printing errors ---*/
106/*------------------------------------------------------------*/
107
108static __inline__
109void clear_AddrInfo ( AddrInfo* ai )
110{
111 ai->akind = Unknown;
112 ai->blksize = 0;
113 ai->rwoffset = 0;
114 ai->lastchange = NULL;
115 ai->stack_tid = VG_INVALID_THREADID;
116 ai->maybe_gcc = False;
sewardjb5f6f512005-03-10 23:59:00 +0000117 ai->desc = NULL;
njn5c004e42002-11-18 11:04:50 +0000118}
119
njn43c799e2003-04-08 00:08:52 +0000120void MAC_(clear_MAC_Error) ( MAC_Error* err_extra )
njn5c004e42002-11-18 11:04:50 +0000121{
122 err_extra->axskind = ReadAxs;
123 err_extra->size = 0;
124 clear_AddrInfo ( &err_extra->addrinfo );
nethercote8b76fe52004-11-08 19:20:09 +0000125 err_extra->isUnaddr = True;
njn5c004e42002-11-18 11:04:50 +0000126}
127
128__attribute__ ((unused))
129static Bool eq_AddrInfo ( VgRes res, AddrInfo* ai1, AddrInfo* ai2 )
130{
131 if (ai1->akind != Undescribed
132 && ai2->akind != Undescribed
133 && ai1->akind != ai2->akind)
134 return False;
135 if (ai1->akind == Freed || ai1->akind == Mallocd) {
136 if (ai1->blksize != ai2->blksize)
137 return False;
138 if (!VG_(eq_ExeContext)(res, ai1->lastchange, ai2->lastchange))
139 return False;
140 }
141 return True;
142}
143
144/* Compare error contexts, to detect duplicates. Note that if they
145 are otherwise the same, the faulting addrs and associated rwoffsets
146 are allowed to be different. */
147
njn51d827b2005-05-09 01:02:08 +0000148Bool MAC_(eq_Error) ( VgRes res, Error* e1, Error* e2 )
njn5c004e42002-11-18 11:04:50 +0000149{
njn43c799e2003-04-08 00:08:52 +0000150 MAC_Error* e1_extra = VG_(get_error_extra)(e1);
151 MAC_Error* e2_extra = VG_(get_error_extra)(e2);
njn7cc53a82002-11-19 16:19:32 +0000152
153 /* Guaranteed by calling function */
njnca82cc02004-11-22 17:18:48 +0000154 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
njn5c004e42002-11-18 11:04:50 +0000155
156 switch (VG_(get_error_kind)(e1)) {
157 case CoreMemErr: {
158 Char *e1s, *e2s;
nethercote8b76fe52004-11-08 19:20:09 +0000159 if (e1_extra->isUnaddr != e2_extra->isUnaddr) return False;
njn5c004e42002-11-18 11:04:50 +0000160 e1s = VG_(get_error_string)(e1);
161 e2s = VG_(get_error_string)(e2);
162 if (e1s == e2s) return True;
163 if (0 == VG_(strcmp)(e1s, e2s)) return True;
164 return False;
165 }
166
njn16390462005-05-08 15:26:00 +0000167 // Perhaps we should also check the addrinfo.akinds for equality.
168 // That would result in more error reports, but only in cases where
169 // a register contains uninitialised bytes and points to memory
170 // containing uninitialised bytes. Currently, the 2nd of those to be
171 // detected won't be reported. That is (nearly?) always the memory
172 // error, which is good.
njn5c004e42002-11-18 11:04:50 +0000173 case ParamErr:
njn16390462005-05-08 15:26:00 +0000174 if (0 != VG_(strcmp)(VG_(get_error_string)(e1),
175 VG_(get_error_string)(e2))) return False;
176 // fall through
177 case UserErr:
178 if (e1_extra->isUnaddr != e2_extra->isUnaddr) return False;
njn5c004e42002-11-18 11:04:50 +0000179 return True;
180
181 case FreeErr:
182 case FreeMismatchErr:
183 /* JRS 2002-Aug-26: comparing addrs seems overkill and can
184 cause excessive duplication of errors. Not even AddrErr
185 below does that. So don't compare either the .addr field
186 or the .addrinfo fields. */
187 /* if (e1->addr != e2->addr) return False; */
188 /* if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
189 return False;
190 */
191 return True;
192
193 case AddrErr:
194 /* if (e1_extra->axskind != e2_extra->axskind) return False; */
195 if (e1_extra->size != e2_extra->size) return False;
196 /*
197 if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
198 return False;
199 */
200 return True;
201
202 case ValueErr:
203 if (e1_extra->size != e2_extra->size) return False;
204 return True;
205
njn34419c12003-05-02 17:24:29 +0000206 case OverlapErr:
207 return True;
208
njn43c799e2003-04-08 00:08:52 +0000209 case LeakErr:
njn51d827b2005-05-09 01:02:08 +0000210 VG_(tool_panic)("Shouldn't get LeakErr in MAC_(eq_Error),\n"
njn43c799e2003-04-08 00:08:52 +0000211 "since it's handled with VG_(unique_error)()!");
212
rjwalshbc0bb832004-06-19 18:12:36 +0000213 case IllegalMempoolErr:
214 return True;
215
njn5c004e42002-11-18 11:04:50 +0000216 default:
217 VG_(printf)("Error:\n unknown error code %d\n",
218 VG_(get_error_kind)(e1));
njn51d827b2005-05-09 01:02:08 +0000219 VG_(tool_panic)("unknown error code in MAC_(eq_Error)");
njn5c004e42002-11-18 11:04:50 +0000220 }
221}
222
njn43c799e2003-04-08 00:08:52 +0000223void MAC_(pp_AddrInfo) ( Addr a, AddrInfo* ai )
njn5c004e42002-11-18 11:04:50 +0000224{
225 switch (ai->akind) {
226 case Stack:
227 VG_(message)(Vg_UserMsg,
tom14ea6852005-05-03 18:16:12 +0000228 " Address 0x%lx is on thread %d's stack",
229 (ULong)a, ai->stack_tid);
njn5c004e42002-11-18 11:04:50 +0000230 break;
231 case Unknown:
232 if (ai->maybe_gcc) {
233 VG_(message)(Vg_UserMsg,
tom14ea6852005-05-03 18:16:12 +0000234 " Address 0x%lx is just below %%esp. Possibly a bug in GCC/G++",
235 (ULong)a);
njn5c004e42002-11-18 11:04:50 +0000236 VG_(message)(Vg_UserMsg,
nethercote3b390c72003-11-13 17:53:43 +0000237 " v 2.96 or 3.0.X. To suppress, use: --workaround-gcc296-bugs=yes");
njn5c004e42002-11-18 11:04:50 +0000238 } else {
239 VG_(message)(Vg_UserMsg,
tom14ea6852005-05-03 18:16:12 +0000240 " Address 0x%lx is not stack'd, malloc'd or (recently) free'd",
241 (ULong)a);
njn5c004e42002-11-18 11:04:50 +0000242 }
243 break;
rjwalshbc0bb832004-06-19 18:12:36 +0000244 case Freed: case Mallocd: case UserG: case Mempool: {
nethercote50397c22004-11-04 18:03:06 +0000245 SizeT delta;
sewardjb5f6f512005-03-10 23:59:00 +0000246 const Char* relative;
247 const Char* kind;
rjwalshbc0bb832004-06-19 18:12:36 +0000248 if (ai->akind == Mempool) {
249 kind = "mempool";
250 } else {
251 kind = "block";
252 }
sewardjb5f6f512005-03-10 23:59:00 +0000253 if (ai->desc != NULL)
254 kind = ai->desc;
255
njn5c004e42002-11-18 11:04:50 +0000256 if (ai->rwoffset < 0) {
nethercote50397c22004-11-04 18:03:06 +0000257 delta = (SizeT)(- ai->rwoffset);
njn5c004e42002-11-18 11:04:50 +0000258 relative = "before";
259 } else if (ai->rwoffset >= ai->blksize) {
260 delta = ai->rwoffset - ai->blksize;
261 relative = "after";
262 } else {
263 delta = ai->rwoffset;
264 relative = "inside";
265 }
sewardja81709d2002-12-28 12:55:48 +0000266 VG_(message)(Vg_UserMsg,
tom14ea6852005-05-03 18:16:12 +0000267 " Address 0x%lx is %llu bytes %s a %s of size %d %s",
268 (ULong)a, (ULong)delta, relative, kind,
sewardja81709d2002-12-28 12:55:48 +0000269 ai->blksize,
270 ai->akind==Mallocd ? "alloc'd"
271 : ai->akind==Freed ? "free'd"
272 : "client-defined");
njn5c004e42002-11-18 11:04:50 +0000273 VG_(pp_ExeContext)(ai->lastchange);
274 break;
275 }
nethercote8b76fe52004-11-08 19:20:09 +0000276 case Register:
277 // print nothing
njnca82cc02004-11-22 17:18:48 +0000278 tl_assert(0 == a);
nethercote8b76fe52004-11-08 19:20:09 +0000279 break;
njn5c004e42002-11-18 11:04:50 +0000280 default:
njn67993252004-11-22 18:02:32 +0000281 VG_(tool_panic)("MAC_(pp_AddrInfo)");
njn43c799e2003-04-08 00:08:52 +0000282 }
283}
284
285/* This prints out the message for the error types where Memcheck and
286 Addrcheck have identical messages */
njnb126f732004-11-22 17:57:07 +0000287void MAC_(pp_shared_Error) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000288{
289 MAC_Error* err_extra = VG_(get_error_extra)(err);
290
291 switch (VG_(get_error_kind)(err)) {
292 case FreeErr:
njn10785452003-05-20 16:38:24 +0000293 VG_(message)(Vg_UserMsg, "Invalid free() / delete / delete[]");
njn43c799e2003-04-08 00:08:52 +0000294 /* fall through */
295 case FreeMismatchErr:
296 if (VG_(get_error_kind)(err) == FreeMismatchErr)
297 VG_(message)(Vg_UserMsg,
298 "Mismatched free() / delete / delete []");
299 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
300 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
301 break;
302
njn89409f82003-09-26 14:55:31 +0000303 case AddrErr:
304 switch (err_extra->axskind) {
305 case ReadAxs:
306 VG_(message)(Vg_UserMsg, "Invalid read of size %d",
307 err_extra->size );
308 break;
309 case WriteAxs:
310 VG_(message)(Vg_UserMsg, "Invalid write of size %d",
311 err_extra->size );
312 break;
313 case ExecAxs:
314 VG_(message)(Vg_UserMsg, "Jump to the invalid address "
315 "stated on the next line");
316 break;
317 default:
njn51d827b2005-05-09 01:02:08 +0000318 VG_(tool_panic)("MAC_(pp_shared_Error)(axskind)");
njn89409f82003-09-26 14:55:31 +0000319 }
320 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
321 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
322 break;
323
njnb6cae9f2003-09-04 20:50:47 +0000324 case OverlapErr: {
325 OverlapExtra* ov_extra = (OverlapExtra*)VG_(get_error_extra)(err);
326 if (ov_extra->len == -1)
327 VG_(message)(Vg_UserMsg,
328 "Source and destination overlap in %s(%p, %p)",
329 VG_(get_error_string)(err),
330 ov_extra->dst, ov_extra->src);
331 else
332 VG_(message)(Vg_UserMsg,
333 "Source and destination overlap in %s(%p, %p, %d)",
334 VG_(get_error_string)(err),
335 ov_extra->dst, ov_extra->src, ov_extra->len);
njn66fe05a2003-07-22 09:12:33 +0000336 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
337 break;
njnb6cae9f2003-09-04 20:50:47 +0000338 }
njn43c799e2003-04-08 00:08:52 +0000339 case LeakErr: {
njn02977032005-05-17 04:00:11 +0000340 MAC_(pp_LeakError)(err_extra);
njn43c799e2003-04-08 00:08:52 +0000341 break;
342 }
343
rjwalshbc0bb832004-06-19 18:12:36 +0000344 case IllegalMempoolErr:
345 VG_(message)(Vg_UserMsg, "Illegal memory pool address");
346 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
347 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
348 break;
349
njn43c799e2003-04-08 00:08:52 +0000350 default:
351 VG_(printf)("Error:\n unknown Memcheck/Addrcheck error code %d\n",
352 VG_(get_error_kind)(err));
njn67993252004-11-22 18:02:32 +0000353 VG_(tool_panic)("unknown error code in MAC_(pp_shared_Error)");
njn5c004e42002-11-18 11:04:50 +0000354 }
355}
356
357/*------------------------------------------------------------*/
358/*--- Recording errors ---*/
359/*------------------------------------------------------------*/
360
njn43c799e2003-04-08 00:08:52 +0000361/* Additional description function for describe_addr(); used by
362 MemCheck for user blocks, which Addrcheck doesn't support. */
363Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL;
thughes4ad52d02004-06-27 17:37:21 +0000364
365/* Callback for searching thread stacks */
366static Bool addr_is_in_bounds(Addr stack_min, Addr stack_max, void *ap)
367{
368 Addr a = *(Addr *)ap;
369
370 return (stack_min <= a && a <= stack_max);
371}
372
373/* Callback for searching free'd list */
374static Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc, void *ap)
375{
376 Addr a = *(Addr *)ap;
377
njn717cde52005-05-10 02:47:21 +0000378 return VG_(addr_is_in_block)( a, mc->data, mc->size,
379 MAC_MALLOC_REDZONE_SZB );
thughes4ad52d02004-06-27 17:37:21 +0000380}
381
382/* Callback for searching malloc'd lists */
383static Bool addr_is_in_HashNode(VgHashNode* sh_ch, void *ap)
384{
385 return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch, ap );
386}
387
njn43c799e2003-04-08 00:08:52 +0000388/* Describe an address as best you can, for error messages,
389 putting the result in ai. */
390static void describe_addr ( Addr a, AddrInfo* ai )
391{
njn3e884182003-04-15 13:03:23 +0000392 MAC_Chunk* sc;
393 ThreadId tid;
njn43c799e2003-04-08 00:08:52 +0000394
njn43c799e2003-04-08 00:08:52 +0000395 /* Perhaps it's a user-def'd block ? (only check if requested, though) */
396 if (NULL != MAC_(describe_addr_supp)) {
397 if (MAC_(describe_addr_supp)( a, ai ))
398 return;
399 }
400 /* Perhaps it's on a thread's stack? */
thughes4ad52d02004-06-27 17:37:21 +0000401 tid = VG_(first_matching_thread_stack)(addr_is_in_bounds, &a);
njn43c799e2003-04-08 00:08:52 +0000402 if (tid != VG_INVALID_THREADID) {
403 ai->akind = Stack;
404 ai->stack_tid = tid;
405 return;
406 }
407 /* Search for a recently freed block which might bracket it. */
thughes4ad52d02004-06-27 17:37:21 +0000408 sc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk, &a);
njn3e884182003-04-15 13:03:23 +0000409 if (NULL != sc) {
njn43c799e2003-04-08 00:08:52 +0000410 ai->akind = Freed;
njn3e884182003-04-15 13:03:23 +0000411 ai->blksize = sc->size;
412 ai->rwoffset = (Int)a - (Int)sc->data;
413 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000414 return;
415 }
416 /* Search for a currently malloc'd block which might bracket it. */
thughes4ad52d02004-06-27 17:37:21 +0000417 sc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode, &a);
njn43c799e2003-04-08 00:08:52 +0000418 if (NULL != sc) {
419 ai->akind = Mallocd;
njn3e884182003-04-15 13:03:23 +0000420 ai->blksize = sc->size;
421 ai->rwoffset = (Int)(a) - (Int)sc->data;
422 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000423 return;
424 }
425 /* Clueless ... */
426 ai->akind = Unknown;
427 return;
428}
429
njn5c004e42002-11-18 11:04:50 +0000430/* Is this address within some small distance below %ESP? Used only
431 for the --workaround-gcc296-bugs kludge. */
432static Bool is_just_below_ESP( Addr esp, Addr aa )
433{
nethercote50397c22004-11-04 18:03:06 +0000434 if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
njn5c004e42002-11-18 11:04:50 +0000435 return True;
436 else
437 return False;
438}
439
sewardjaf48a602003-07-06 00:54:47 +0000440/* This one called from generated code and non-generated code. */
njn5c004e42002-11-18 11:04:50 +0000441
njn72718642003-07-24 08:45:32 +0000442void MAC_(record_address_error) ( ThreadId tid, Addr a, Int size,
sewardjaf48a602003-07-06 00:54:47 +0000443 Bool isWrite )
njn5c004e42002-11-18 11:04:50 +0000444{
njn43c799e2003-04-08 00:08:52 +0000445 MAC_Error err_extra;
446 Bool just_below_esp;
njn5c004e42002-11-18 11:04:50 +0000447
njn67516132005-03-22 04:02:43 +0000448 just_below_esp = is_just_below_ESP( VG_(get_SP)(tid), a );
njn5c004e42002-11-18 11:04:50 +0000449
450 /* If this is caused by an access immediately below %ESP, and the
451 user asks nicely, we just ignore it. */
njn43c799e2003-04-08 00:08:52 +0000452 if (MAC_(clo_workaround_gcc296_bugs) && just_below_esp)
njn5c004e42002-11-18 11:04:50 +0000453 return;
454
njn43c799e2003-04-08 00:08:52 +0000455 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000456 err_extra.axskind = isWrite ? WriteAxs : ReadAxs;
457 err_extra.size = size;
458 err_extra.addrinfo.akind = Undescribed;
459 err_extra.addrinfo.maybe_gcc = just_below_esp;
njn72718642003-07-24 08:45:32 +0000460 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000461}
462
463/* These ones are called from non-generated code */
464
465/* This is for memory errors in pthread functions, as opposed to pthread API
466 errors which are found by the core. */
nethercote8b76fe52004-11-08 19:20:09 +0000467void MAC_(record_core_mem_error) ( ThreadId tid, Bool isUnaddr, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000468{
njn43c799e2003-04-08 00:08:52 +0000469 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000470
njn43c799e2003-04-08 00:08:52 +0000471 MAC_(clear_MAC_Error)( &err_extra );
nethercote8b76fe52004-11-08 19:20:09 +0000472 err_extra.isUnaddr = isUnaddr;
njn72718642003-07-24 08:45:32 +0000473 VG_(maybe_record_error)( tid, CoreMemErr, /*addr*/0, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000474}
475
njn16390462005-05-08 15:26:00 +0000476// Three kinds of param errors:
477// - register arg contains undefined bytes
478// - memory arg is unaddressable
479// - memory arg contains undefined bytes
480// 'isReg' and 'isUnaddr' dictate which of these it is.
nethercote8b76fe52004-11-08 19:20:09 +0000481void MAC_(record_param_error) ( ThreadId tid, Addr a, Bool isReg,
482 Bool isUnaddr, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000483{
njn43c799e2003-04-08 00:08:52 +0000484 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000485
njnca82cc02004-11-22 17:18:48 +0000486 tl_assert(VG_INVALID_THREADID != tid);
njn16390462005-05-08 15:26:00 +0000487 if (isUnaddr) tl_assert(!isReg); // unaddressable register is impossible
njn43c799e2003-04-08 00:08:52 +0000488 MAC_(clear_MAC_Error)( &err_extra );
nethercote8b76fe52004-11-08 19:20:09 +0000489 err_extra.addrinfo.akind = ( isReg ? Register : Undescribed );
490 err_extra.isUnaddr = isUnaddr;
njn72718642003-07-24 08:45:32 +0000491 VG_(maybe_record_error)( tid, ParamErr, a, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000492}
493
njn72718642003-07-24 08:45:32 +0000494void MAC_(record_jump_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000495{
njn43c799e2003-04-08 00:08:52 +0000496 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000497
njnca82cc02004-11-22 17:18:48 +0000498 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000499 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000500 err_extra.axskind = ExecAxs;
nethercote7250b8f2004-04-13 08:47:35 +0000501 err_extra.size = 1; // size only used for suppressions
njn5c004e42002-11-18 11:04:50 +0000502 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000503 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000504}
505
njn72718642003-07-24 08:45:32 +0000506void MAC_(record_free_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000507{
njn43c799e2003-04-08 00:08:52 +0000508 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000509
njnca82cc02004-11-22 17:18:48 +0000510 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000511 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000512 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000513 VG_(maybe_record_error)( tid, FreeErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000514}
515
rjwalshbc0bb832004-06-19 18:12:36 +0000516void MAC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )
517{
518 MAC_Error err_extra;
519
njnca82cc02004-11-22 17:18:48 +0000520 tl_assert(VG_INVALID_THREADID != tid);
rjwalshbc0bb832004-06-19 18:12:36 +0000521 MAC_(clear_MAC_Error)( &err_extra );
522 err_extra.addrinfo.akind = Undescribed;
523 VG_(maybe_record_error)( tid, IllegalMempoolErr, a, /*s*/NULL, &err_extra );
524}
525
njn72718642003-07-24 08:45:32 +0000526void MAC_(record_freemismatch_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000527{
njn43c799e2003-04-08 00:08:52 +0000528 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000529
njnca82cc02004-11-22 17:18:48 +0000530 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000531 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000532 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000533 VG_(maybe_record_error)( tid, FreeMismatchErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000534}
535
sewardj2a99cf62004-11-24 10:44:19 +0000536void MAC_(record_overlap_error) ( ThreadId tid,
537 Char* function, OverlapExtra* ov_extra )
njn66fe05a2003-07-22 09:12:33 +0000538{
sewardj2a99cf62004-11-24 10:44:19 +0000539 VG_(maybe_record_error)(
540 tid, OverlapErr, /*addr*/0, /*s*/function, ov_extra );
njn66fe05a2003-07-22 09:12:33 +0000541}
542
543
njnb6cae9f2003-09-04 20:50:47 +0000544/* Updates the copy with address info if necessary (but not for all errors). */
njn51d827b2005-05-09 01:02:08 +0000545UInt MAC_(update_extra)( Error* err )
njn43c799e2003-04-08 00:08:52 +0000546{
njnb6cae9f2003-09-04 20:50:47 +0000547 switch (VG_(get_error_kind)(err)) {
548 case ValueErr:
549 case CoreMemErr:
550 case AddrErr:
551 case ParamErr:
552 case UserErr:
553 case FreeErr:
rjwalshbc0bb832004-06-19 18:12:36 +0000554 case IllegalMempoolErr:
njnb6cae9f2003-09-04 20:50:47 +0000555 case FreeMismatchErr: {
nethercote8b76fe52004-11-08 19:20:09 +0000556 MAC_Error* extra = VG_(get_error_extra)(err);
njnb6cae9f2003-09-04 20:50:47 +0000557 if (extra != NULL && Undescribed == extra->addrinfo.akind) {
558 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
559 }
560 return sizeof(MAC_Error);
561 }
njn43c799e2003-04-08 00:08:52 +0000562 /* Don't need to return the correct size -- LeakErrs are always shown with
563 VG_(unique_error)() so they're not copied anyway. */
njnb6cae9f2003-09-04 20:50:47 +0000564 case LeakErr: return 0;
565 case OverlapErr: return sizeof(OverlapExtra);
njn67993252004-11-22 18:02:32 +0000566 default: VG_(tool_panic)("update_extra: bad errkind");
njn43c799e2003-04-08 00:08:52 +0000567 }
njn43c799e2003-04-08 00:08:52 +0000568}
569
570
njn5c004e42002-11-18 11:04:50 +0000571/*------------------------------------------------------------*/
572/*--- Suppressions ---*/
573/*------------------------------------------------------------*/
574
njn43c799e2003-04-08 00:08:52 +0000575Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
576{
577 SuppKind skind;
578
579 if (VG_STREQ(name, "Param")) skind = ParamSupp;
580 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
581 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
582 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
583 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
584 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
njnc0616662003-06-12 09:58:41 +0000585 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
njn43c799e2003-04-08 00:08:52 +0000586 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
587 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
njne9cab142003-09-19 08:10:07 +0000588 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
rjwalshbc0bb832004-06-19 18:12:36 +0000589 else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
njn43c799e2003-04-08 00:08:52 +0000590 else
591 return False;
592
593 VG_(set_supp_kind)(su, skind);
594 return True;
595}
596
njn51d827b2005-05-09 01:02:08 +0000597Bool MAC_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
njn5c004e42002-11-18 11:04:50 +0000598{
599 Bool eof;
600
601 if (VG_(get_supp_kind)(su) == ParamSupp) {
602 eof = VG_(get_line) ( fd, buf, nBuf );
603 if (eof) return False;
604 VG_(set_supp_string)(su, VG_(strdup)(buf));
605 }
606 return True;
607}
608
njn51d827b2005-05-09 01:02:08 +0000609Bool MAC_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000610{
sewardj05bcdcb2003-05-18 10:05:38 +0000611 Int su_size;
njn43c799e2003-04-08 00:08:52 +0000612 MAC_Error* err_extra = VG_(get_error_extra)(err);
613 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000614
615 switch (VG_(get_supp_kind)(su)) {
616 case ParamSupp:
617 return (ekind == ParamErr
njn43c799e2003-04-08 00:08:52 +0000618 && VG_STREQ(VG_(get_error_string)(err),
619 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000620
621 case CoreMemSupp:
622 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000623 && VG_STREQ(VG_(get_error_string)(err),
624 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000625
626 case Value0Supp: su_size = 0; goto value_case;
627 case Value1Supp: su_size = 1; goto value_case;
628 case Value2Supp: su_size = 2; goto value_case;
629 case Value4Supp: su_size = 4; goto value_case;
630 case Value8Supp: su_size = 8; goto value_case;
njnc0616662003-06-12 09:58:41 +0000631 case Value16Supp:su_size =16; goto value_case;
njn5c004e42002-11-18 11:04:50 +0000632 value_case:
633 return (ekind == ValueErr && err_extra->size == su_size);
634
635 case Addr1Supp: su_size = 1; goto addr_case;
636 case Addr2Supp: su_size = 2; goto addr_case;
637 case Addr4Supp: su_size = 4; goto addr_case;
638 case Addr8Supp: su_size = 8; goto addr_case;
njnc0616662003-06-12 09:58:41 +0000639 case Addr16Supp:su_size =16; goto addr_case;
njn5c004e42002-11-18 11:04:50 +0000640 addr_case:
641 return (ekind == AddrErr && err_extra->size == su_size);
642
643 case FreeSupp:
644 return (ekind == FreeErr || ekind == FreeMismatchErr);
645
njn34419c12003-05-02 17:24:29 +0000646 case OverlapSupp:
647 return (ekind = OverlapErr);
648
sewardj4a19e2f2002-12-26 11:50:21 +0000649 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000650 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000651
rjwalshbc0bb832004-06-19 18:12:36 +0000652 case MempoolSupp:
653 return (ekind == IllegalMempoolErr);
654
njn5c004e42002-11-18 11:04:50 +0000655 default:
656 VG_(printf)("Error:\n"
657 " unknown suppression type %d\n",
658 VG_(get_supp_kind)(su));
njn67993252004-11-22 18:02:32 +0000659 VG_(tool_panic)("unknown suppression type in "
njn51d827b2005-05-09 01:02:08 +0000660 "MAC_(error_matches_suppression)");
njn5c004e42002-11-18 11:04:50 +0000661 }
662}
663
njn51d827b2005-05-09 01:02:08 +0000664Char* MAC_(get_error_name) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000665{
666 Char* s;
667 switch (VG_(get_error_kind)(err)) {
668 case ParamErr: return "Param";
669 case UserErr: return NULL; /* Can't suppress User errors */
670 case FreeMismatchErr: return "Free";
rjwalshbc0bb832004-06-19 18:12:36 +0000671 case IllegalMempoolErr: return "Mempool";
njn43c799e2003-04-08 00:08:52 +0000672 case FreeErr: return "Free";
673 case AddrErr:
674 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
675 case 1: return "Addr1";
676 case 2: return "Addr2";
677 case 4: return "Addr4";
678 case 8: return "Addr8";
njnc0616662003-06-12 09:58:41 +0000679 case 16: return "Addr16";
njn67993252004-11-22 18:02:32 +0000680 default: VG_(tool_panic)("unexpected size for Addr");
njn43c799e2003-04-08 00:08:52 +0000681 }
682
683 case ValueErr:
684 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
685 case 0: return "Cond";
686 case 1: return "Value1";
687 case 2: return "Value2";
688 case 4: return "Value4";
689 case 8: return "Value8";
njnc0616662003-06-12 09:58:41 +0000690 case 16: return "Value16";
njn67993252004-11-22 18:02:32 +0000691 default: VG_(tool_panic)("unexpected size for Value");
njn43c799e2003-04-08 00:08:52 +0000692 }
693 case CoreMemErr: return "CoreMem";
njn34419c12003-05-02 17:24:29 +0000694 case OverlapErr: return "Overlap";
njn43c799e2003-04-08 00:08:52 +0000695 case LeakErr: return "Leak";
njn67993252004-11-22 18:02:32 +0000696 default: VG_(tool_panic)("get_error_name: unexpected type");
njn43c799e2003-04-08 00:08:52 +0000697 }
698 VG_(printf)(s);
699}
700
njn51d827b2005-05-09 01:02:08 +0000701void MAC_(print_extra_suppression_info) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000702{
703 if (ParamErr == VG_(get_error_kind)(err)) {
704 VG_(printf)(" %s\n", VG_(get_error_string)(err));
705 }
706}
njn5c004e42002-11-18 11:04:50 +0000707
708/*------------------------------------------------------------*/
709/*--- Crude profiling machinery. ---*/
710/*------------------------------------------------------------*/
711
712/* Event index. If just the name of the fn is given, this means the
713 number of calls to the fn. Otherwise it is the specified event.
714 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
715 The rest are shared.
716
717 10 alloc_secondary_map
718
719 20 get_abit
720M 21 get_vbyte
721 22 set_abit
722M 23 set_vbyte
723 24 get_abits4_ALIGNED
724M 25 get_vbytes4_ALIGNED
725
726 30 set_address_range_perms
727 31 set_address_range_perms(lower byte loop)
728 32 set_address_range_perms(quadword loop)
729 33 set_address_range_perms(upper byte loop)
730
731 35 make_noaccess
732 36 make_writable
733 37 make_readable
734A 38 make_accessible
735
736 40 copy_address_range_state
737 41 copy_address_range_state(byte loop)
738 42 check_writable
739 43 check_writable(byte loop)
740 44 check_readable
741 45 check_readable(byte loop)
742 46 check_readable_asciiz
743 47 check_readable_asciiz(byte loop)
744A 48 check_accessible
745A 49 check_accessible(byte loop)
746
747 50 make_noaccess_aligned
748 51 make_writable_aligned
749
750M 60 helperc_LOADV4
751M 61 helperc_STOREV4
752M 62 helperc_LOADV2
753M 63 helperc_STOREV2
754M 64 helperc_LOADV1
755M 65 helperc_STOREV1
756
757A 66 helperc_ACCESS4
758A 67 helperc_ACCESS2
759A 68 helperc_ACCESS1
760
761M 70 rim_rd_V4_SLOWLY
762M 71 rim_wr_V4_SLOWLY
763M 72 rim_rd_V2_SLOWLY
764M 73 rim_wr_V2_SLOWLY
765M 74 rim_rd_V1_SLOWLY
766M 75 rim_wr_V1_SLOWLY
767
768A 76 ACCESS4_SLOWLY
769A 77 ACCESS2_SLOWLY
770A 78 ACCESS1_SLOWLY
771
772 80 fpu_read
773 81 fpu_read aligned 4
774 82 fpu_read aligned 8
775 83 fpu_read 2
jsewardfca60182004-01-04 23:30:55 +0000776 84 fpu_read 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000777
778M 85 fpu_write
779M 86 fpu_write aligned 4
780M 87 fpu_write aligned 8
781M 88 fpu_write 2
jsewardfca60182004-01-04 23:30:55 +0000782M 89 fpu_write 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000783
784 90 fpu_access
785 91 fpu_access aligned 4
786 92 fpu_access aligned 8
787 93 fpu_access 2
jsewardfca60182004-01-04 23:30:55 +0000788 94 fpu_access 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000789
790 100 fpu_access_check_SLOWLY
791 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000792
793 110 new_mem_stack_4
794 111 new_mem_stack_8
795 112 new_mem_stack_12
796 113 new_mem_stack_16
797 114 new_mem_stack_32
798 115 new_mem_stack
799
800 120 die_mem_stack_4
801 121 die_mem_stack_8
802 122 die_mem_stack_12
803 123 die_mem_stack_16
804 124 die_mem_stack_32
805 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000806*/
807
njn43c799e2003-04-08 00:08:52 +0000808#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000809
sewardjc1a2cda2005-04-21 17:34:00 +0000810UInt MAC_(event_ctr)[N_PROF_EVENTS];
811HChar* MAC_(event_ctr_name)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000812
njnb4aee052003-04-15 14:09:58 +0000813static void init_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000814{
815 Int i;
sewardjc1a2cda2005-04-21 17:34:00 +0000816 for (i = 0; i < N_PROF_EVENTS; i++) {
njn43c799e2003-04-08 00:08:52 +0000817 MAC_(event_ctr)[i] = 0;
sewardjc1a2cda2005-04-21 17:34:00 +0000818 MAC_(event_ctr_name)[i] = NULL;
819 }
njn5c004e42002-11-18 11:04:50 +0000820}
821
njnb4aee052003-04-15 14:09:58 +0000822static void done_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000823{
sewardjc1a2cda2005-04-21 17:34:00 +0000824 Int i;
825 Bool spaced = False;
njn5c004e42002-11-18 11:04:50 +0000826 for (i = 0; i < N_PROF_EVENTS; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +0000827 if (!spaced && (i % 10) == 0) {
njn5c004e42002-11-18 11:04:50 +0000828 VG_(printf)("\n");
sewardjc1a2cda2005-04-21 17:34:00 +0000829 spaced = True;
830 }
831 if (MAC_(event_ctr)[i] > 0) {
832 spaced = False;
833 VG_(printf)( "prof mem event %3d: %9d %s\n",
834 i, MAC_(event_ctr)[i],
835 MAC_(event_ctr_name)[i]
836 ? MAC_(event_ctr_name)[i] : "unnamed");
837 }
njn5c004e42002-11-18 11:04:50 +0000838 }
njn5c004e42002-11-18 11:04:50 +0000839}
840
841#else
842
njnb4aee052003-04-15 14:09:58 +0000843static void init_prof_mem ( void ) { }
844static void done_prof_mem ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000845
njn5c004e42002-11-18 11:04:50 +0000846#endif
847
848/*------------------------------------------------------------*/
njn3e884182003-04-15 13:03:23 +0000849/*--- Common initialisation + finalisation ---*/
850/*------------------------------------------------------------*/
851
852void MAC_(common_pre_clo_init)(void)
853{
854 MAC_(malloc_list) = VG_(HT_construct)();
rjwalshbc0bb832004-06-19 18:12:36 +0000855 MAC_(mempool_list) = VG_(HT_construct)();
njn3e884182003-04-15 13:03:23 +0000856 init_prof_mem();
857}
858
njnb8dca862005-03-14 02:42:44 +0000859void MAC_(common_fini)(void (*leak_check)(ThreadId tid, LeakCheckMode mode))
njn3e884182003-04-15 13:03:23 +0000860{
njn86f12dc2005-03-14 01:16:05 +0000861 MAC_(print_malloc_stats)();
njn3e884182003-04-15 13:03:23 +0000862
863 if (VG_(clo_verbosity) == 1) {
sewardjb5f6f512005-03-10 23:59:00 +0000864 if (MAC_(clo_leak_check) == LC_Off)
njn3e884182003-04-15 13:03:23 +0000865 VG_(message)(Vg_UserMsg,
866 "For a detailed leak analysis, rerun with: --leak-check=yes");
867
868 VG_(message)(Vg_UserMsg,
869 "For counts of detected errors, rerun with: -v");
870 }
sewardjb5f6f512005-03-10 23:59:00 +0000871 if (MAC_(clo_leak_check) != LC_Off)
njnb8dca862005-03-14 02:42:44 +0000872 leak_check(1/*bogus ThreadId*/, MAC_(clo_leak_check));
njn3e884182003-04-15 13:03:23 +0000873
874 done_prof_mem();
875}
876
877/*------------------------------------------------------------*/
njn47363ab2003-04-21 13:24:40 +0000878/*--- Common client request handling ---*/
879/*------------------------------------------------------------*/
880
nethercoted1b64b22004-11-04 18:22:28 +0000881Bool MAC_(handle_common_client_requests)(ThreadId tid, UWord* arg, UWord* ret )
njn47363ab2003-04-21 13:24:40 +0000882{
njnd7994182003-10-02 13:44:04 +0000883 Char* err =
884 "The client requests VALGRIND_MALLOCLIKE_BLOCK and\n"
885 " VALGRIND_FREELIKE_BLOCK have moved. Please recompile your\n"
886 " program to incorporate the updates in the Valgrind header files.\n"
887 " You shouldn't need to change the text of your program at all.\n"
888 " Everything should then work as before. Sorry for the bother.\n";
njn47363ab2003-04-21 13:24:40 +0000889
890 switch (arg[0]) {
njn10785452003-05-20 16:38:24 +0000891 case VG_USERREQ__COUNT_LEAKS: { /* count leaked bytes */
nethercoted1b64b22004-11-04 18:22:28 +0000892 UWord** argp = (UWord**)arg;
njne8b5c052003-07-22 22:03:58 +0000893 // MAC_(bytes_leaked) et al were set by the last leak check (or zero
894 // if no prior leak checks performed).
sewardjb5f6f512005-03-10 23:59:00 +0000895 *argp[1] = MAC_(bytes_leaked) + MAC_(bytes_indirect);
njne8b5c052003-07-22 22:03:58 +0000896 *argp[2] = MAC_(bytes_dubious);
897 *argp[3] = MAC_(bytes_reachable);
898 *argp[4] = MAC_(bytes_suppressed);
sewardjb5f6f512005-03-10 23:59:00 +0000899 // there is no argp[5]
900 //*argp[5] = MAC_(bytes_indirect);
901 // XXX need to make *argp[1-4] readable
njn47363ab2003-04-21 13:24:40 +0000902 *ret = 0;
903 return True;
njn10785452003-05-20 16:38:24 +0000904 }
njnd7994182003-10-02 13:44:04 +0000905 case VG_USERREQ__MALLOCLIKE_BLOCK__OLD_DO_NOT_USE:
906 case VG_USERREQ__FREELIKE_BLOCK__OLD_DO_NOT_USE:
njn67993252004-11-22 18:02:32 +0000907 VG_(tool_panic)(err);
njnd7994182003-10-02 13:44:04 +0000908
njn10785452003-05-20 16:38:24 +0000909 case VG_USERREQ__MALLOCLIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000910 Addr p = (Addr)arg[1];
nethercote928a5f72004-11-03 18:10:37 +0000911 SizeT sizeB = arg[2];
njnd7994182003-10-02 13:44:04 +0000912 UInt rzB = arg[3];
913 Bool is_zeroed = (Bool)arg[4];
njn47363ab2003-04-21 13:24:40 +0000914
sewardj2a99cf62004-11-24 10:44:19 +0000915 MAC_(new_block) ( tid, p, sizeB, /*ignored*/0, rzB, is_zeroed,
nethercote57e36b32004-07-10 14:56:28 +0000916 MAC_AllocCustom, MAC_(malloc_list) );
njn10785452003-05-20 16:38:24 +0000917 return True;
918 }
919 case VG_USERREQ__FREELIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000920 Addr p = (Addr)arg[1];
921 UInt rzB = arg[2];
njn10785452003-05-20 16:38:24 +0000922
sewardj2a99cf62004-11-24 10:44:19 +0000923 MAC_(handle_free) ( tid, p, rzB, MAC_AllocCustom );
njn10785452003-05-20 16:38:24 +0000924 return True;
925 }
njnd7994182003-10-02 13:44:04 +0000926
njn1f8b3e72005-03-22 04:27:14 +0000927 case _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR: {
928 Char* s = (Char*) arg[1];
929 OverlapExtra* extra = (OverlapExtra*)arg[2];
930 MAC_(record_overlap_error)(tid, s, extra);
nethercotee3a53722004-05-05 10:46:22 +0000931 return True;
njn1f8b3e72005-03-22 04:27:14 +0000932 }
nethercotee3a53722004-05-05 10:46:22 +0000933
rjwalshbc0bb832004-06-19 18:12:36 +0000934 case VG_USERREQ__CREATE_MEMPOOL: {
935 Addr pool = (Addr)arg[1];
936 UInt rzB = arg[2];
937 Bool is_zeroed = (Bool)arg[3];
938
939 MAC_(create_mempool) ( pool, rzB, is_zeroed );
940 return True;
941 }
942
943 case VG_USERREQ__DESTROY_MEMPOOL: {
944 Addr pool = (Addr)arg[1];
945
946 MAC_(destroy_mempool) ( pool );
947 return True;
948 }
949
950 case VG_USERREQ__MEMPOOL_ALLOC: {
951 Addr pool = (Addr)arg[1];
952 Addr addr = (Addr)arg[2];
953 UInt size = arg[3];
954
sewardj2a99cf62004-11-24 10:44:19 +0000955 MAC_(mempool_alloc) ( tid, pool, addr, size );
rjwalshbc0bb832004-06-19 18:12:36 +0000956 return True;
957 }
958
959 case VG_USERREQ__MEMPOOL_FREE: {
960 Addr pool = (Addr)arg[1];
961 Addr addr = (Addr)arg[2];
962
963 MAC_(mempool_free) ( pool, addr );
964 return True;
965 }
966
njn47363ab2003-04-21 13:24:40 +0000967 default:
968 return False;
969 }
970}
971
njn5c004e42002-11-18 11:04:50 +0000972/*--------------------------------------------------------------------*/
njn00cae242005-05-09 01:13:44 +0000973/*--- end ---*/
njn5c004e42002-11-18 11:04:50 +0000974/*--------------------------------------------------------------------*/