blob: bcd440a743d8215fe57f9c182aad4525c0e2094a [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{
sewardj71bc3cb2005-05-19 00:25:45 +0000225 HChar* xpre = VG_(clo_xml) ? " <auxwhat>" : " ";
226 HChar* xpost = VG_(clo_xml) ? "</auxwhat>" : "";
227
njn5c004e42002-11-18 11:04:50 +0000228 switch (ai->akind) {
229 case Stack:
230 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000231 "%sAddress 0x%llx is on thread %d's stack%s",
232 xpre, (ULong)a, ai->stack_tid, xpost);
njn5c004e42002-11-18 11:04:50 +0000233 break;
234 case Unknown:
235 if (ai->maybe_gcc) {
236 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000237 "%sAddress 0x%llx is just below the stack ptr. "
238 "To suppress, use: --workaround-gcc296-bugs=yes%s",
239 xpre, (ULong)a, xpost
240 );
njn5c004e42002-11-18 11:04:50 +0000241 } else {
242 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000243 "%sAddress 0x%llx "
244 "is not stack'd, malloc'd or (recently) free'd%s",
245 xpre, (ULong)a, xpost);
njn5c004e42002-11-18 11:04:50 +0000246 }
247 break;
rjwalshbc0bb832004-06-19 18:12:36 +0000248 case Freed: case Mallocd: case UserG: case Mempool: {
nethercote50397c22004-11-04 18:03:06 +0000249 SizeT delta;
sewardjb5f6f512005-03-10 23:59:00 +0000250 const Char* relative;
251 const Char* kind;
rjwalshbc0bb832004-06-19 18:12:36 +0000252 if (ai->akind == Mempool) {
253 kind = "mempool";
254 } else {
255 kind = "block";
256 }
sewardjb5f6f512005-03-10 23:59:00 +0000257 if (ai->desc != NULL)
258 kind = ai->desc;
259
njn5c004e42002-11-18 11:04:50 +0000260 if (ai->rwoffset < 0) {
nethercote50397c22004-11-04 18:03:06 +0000261 delta = (SizeT)(- ai->rwoffset);
njn5c004e42002-11-18 11:04:50 +0000262 relative = "before";
263 } else if (ai->rwoffset >= ai->blksize) {
264 delta = ai->rwoffset - ai->blksize;
265 relative = "after";
266 } else {
267 delta = ai->rwoffset;
268 relative = "inside";
269 }
sewardja81709d2002-12-28 12:55:48 +0000270 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000271 "%sAddress 0x%llx is %llu bytes %s a %s of size %d %s%s",
272 xpre,
tom14ea6852005-05-03 18:16:12 +0000273 (ULong)a, (ULong)delta, relative, kind,
sewardja81709d2002-12-28 12:55:48 +0000274 ai->blksize,
275 ai->akind==Mallocd ? "alloc'd"
276 : ai->akind==Freed ? "free'd"
sewardj71bc3cb2005-05-19 00:25:45 +0000277 : "client-defined",
278 xpost);
njn5c004e42002-11-18 11:04:50 +0000279 VG_(pp_ExeContext)(ai->lastchange);
280 break;
281 }
nethercote8b76fe52004-11-08 19:20:09 +0000282 case Register:
283 // print nothing
njnca82cc02004-11-22 17:18:48 +0000284 tl_assert(0 == a);
nethercote8b76fe52004-11-08 19:20:09 +0000285 break;
njn5c004e42002-11-18 11:04:50 +0000286 default:
njn67993252004-11-22 18:02:32 +0000287 VG_(tool_panic)("MAC_(pp_AddrInfo)");
njn43c799e2003-04-08 00:08:52 +0000288 }
289}
290
291/* This prints out the message for the error types where Memcheck and
292 Addrcheck have identical messages */
njnb126f732004-11-22 17:57:07 +0000293void MAC_(pp_shared_Error) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000294{
295 MAC_Error* err_extra = VG_(get_error_extra)(err);
296
sewardj71bc3cb2005-05-19 00:25:45 +0000297 HChar* xpre = VG_(clo_xml) ? " <what>" : "";
298 HChar* xpost = VG_(clo_xml) ? "</what>" : "";
299
njn43c799e2003-04-08 00:08:52 +0000300 switch (VG_(get_error_kind)(err)) {
301 case FreeErr:
sewardj71bc3cb2005-05-19 00:25:45 +0000302 if (VG_(clo_xml))
303 VG_(message)(Vg_UserMsg, " <kind>InvalidFree</kind>");
304 VG_(message)(Vg_UserMsg,
305 "%sInvalid free() / delete / delete[]%s",
306 xpre, xpost);
307 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
308 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
309 break;
310
njn43c799e2003-04-08 00:08:52 +0000311 case FreeMismatchErr:
sewardj71bc3cb2005-05-19 00:25:45 +0000312 if (VG_(clo_xml))
313 VG_(message)(Vg_UserMsg, " <kind>MismatchedFree</kind>");
314 VG_(message)(Vg_UserMsg,
315 "%sMismatched free() / delete / delete []%s",
316 xpre, xpost);
njn43c799e2003-04-08 00:08:52 +0000317 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
318 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
319 break;
320
njn89409f82003-09-26 14:55:31 +0000321 case AddrErr:
322 switch (err_extra->axskind) {
323 case ReadAxs:
sewardj71bc3cb2005-05-19 00:25:45 +0000324 if (VG_(clo_xml))
325 VG_(message)(Vg_UserMsg, " <kind>InvalidRead</kind>");
326 VG_(message)(Vg_UserMsg,
327 "%sInvalid read of size %d%s",
328 xpre, err_extra->size, xpost );
njn89409f82003-09-26 14:55:31 +0000329 break;
330 case WriteAxs:
sewardj71bc3cb2005-05-19 00:25:45 +0000331 if (VG_(clo_xml))
332 VG_(message)(Vg_UserMsg, " <kind>InvalidWrite</kind>");
333 VG_(message)(Vg_UserMsg,
334 "%sInvalid write of size %d%s",
335 xpre, err_extra->size, xpost );
njn89409f82003-09-26 14:55:31 +0000336 break;
337 case ExecAxs:
sewardj71bc3cb2005-05-19 00:25:45 +0000338 if (VG_(clo_xml))
339 VG_(message)(Vg_UserMsg, " <kind>InvalidJump</kind>");
340 VG_(message)(Vg_UserMsg,
341 "%sJump to the invalid address "
342 "stated on the next line%s",
343 xpre, xpost);
njn89409f82003-09-26 14:55:31 +0000344 break;
345 default:
njn51d827b2005-05-09 01:02:08 +0000346 VG_(tool_panic)("MAC_(pp_shared_Error)(axskind)");
njn89409f82003-09-26 14:55:31 +0000347 }
348 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
349 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
350 break;
351
njnb6cae9f2003-09-04 20:50:47 +0000352 case OverlapErr: {
353 OverlapExtra* ov_extra = (OverlapExtra*)VG_(get_error_extra)(err);
sewardj71bc3cb2005-05-19 00:25:45 +0000354 if (VG_(clo_xml))
355 VG_(message)(Vg_UserMsg, " <kind>Overlap</kind>");
njnb6cae9f2003-09-04 20:50:47 +0000356 if (ov_extra->len == -1)
357 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000358 "%sSource and destination overlap in %s(%p, %p)%s",
359 xpre,
njnb6cae9f2003-09-04 20:50:47 +0000360 VG_(get_error_string)(err),
sewardj71bc3cb2005-05-19 00:25:45 +0000361 ov_extra->dst, ov_extra->src,
362 xpost);
njnb6cae9f2003-09-04 20:50:47 +0000363 else
364 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000365 "%sSource and destination overlap in %s(%p, %p, %d)%s",
366 xpre,
njnb6cae9f2003-09-04 20:50:47 +0000367 VG_(get_error_string)(err),
sewardj71bc3cb2005-05-19 00:25:45 +0000368 ov_extra->dst, ov_extra->src, ov_extra->len,
369 xpost);
njn66fe05a2003-07-22 09:12:33 +0000370 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
371 break;
njnb6cae9f2003-09-04 20:50:47 +0000372 }
njn43c799e2003-04-08 00:08:52 +0000373 case LeakErr: {
njn02977032005-05-17 04:00:11 +0000374 MAC_(pp_LeakError)(err_extra);
njn43c799e2003-04-08 00:08:52 +0000375 break;
376 }
377
rjwalshbc0bb832004-06-19 18:12:36 +0000378 case IllegalMempoolErr:
sewardj71bc3cb2005-05-19 00:25:45 +0000379 if (VG_(clo_xml))
380 VG_(message)(Vg_UserMsg, " <kind>InvalidMemPool</kind>");
381 VG_(message)(Vg_UserMsg, "%sIllegal memory pool address%s",
382 xpre, xpost);
rjwalshbc0bb832004-06-19 18:12:36 +0000383 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
384 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
385 break;
386
njn43c799e2003-04-08 00:08:52 +0000387 default:
388 VG_(printf)("Error:\n unknown Memcheck/Addrcheck error code %d\n",
389 VG_(get_error_kind)(err));
njn67993252004-11-22 18:02:32 +0000390 VG_(tool_panic)("unknown error code in MAC_(pp_shared_Error)");
njn5c004e42002-11-18 11:04:50 +0000391 }
392}
393
394/*------------------------------------------------------------*/
395/*--- Recording errors ---*/
396/*------------------------------------------------------------*/
397
njn43c799e2003-04-08 00:08:52 +0000398/* Additional description function for describe_addr(); used by
399 MemCheck for user blocks, which Addrcheck doesn't support. */
400Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL;
thughes4ad52d02004-06-27 17:37:21 +0000401
402/* Callback for searching thread stacks */
403static Bool addr_is_in_bounds(Addr stack_min, Addr stack_max, void *ap)
404{
405 Addr a = *(Addr *)ap;
406
407 return (stack_min <= a && a <= stack_max);
408}
409
410/* Callback for searching free'd list */
411static Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc, void *ap)
412{
413 Addr a = *(Addr *)ap;
414
njn717cde52005-05-10 02:47:21 +0000415 return VG_(addr_is_in_block)( a, mc->data, mc->size,
416 MAC_MALLOC_REDZONE_SZB );
thughes4ad52d02004-06-27 17:37:21 +0000417}
418
419/* Callback for searching malloc'd lists */
420static Bool addr_is_in_HashNode(VgHashNode* sh_ch, void *ap)
421{
422 return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch, ap );
423}
424
njn43c799e2003-04-08 00:08:52 +0000425/* Describe an address as best you can, for error messages,
426 putting the result in ai. */
427static void describe_addr ( Addr a, AddrInfo* ai )
428{
njn3e884182003-04-15 13:03:23 +0000429 MAC_Chunk* sc;
430 ThreadId tid;
njn43c799e2003-04-08 00:08:52 +0000431
njn43c799e2003-04-08 00:08:52 +0000432 /* Perhaps it's a user-def'd block ? (only check if requested, though) */
433 if (NULL != MAC_(describe_addr_supp)) {
434 if (MAC_(describe_addr_supp)( a, ai ))
435 return;
436 }
437 /* Perhaps it's on a thread's stack? */
thughes4ad52d02004-06-27 17:37:21 +0000438 tid = VG_(first_matching_thread_stack)(addr_is_in_bounds, &a);
njn43c799e2003-04-08 00:08:52 +0000439 if (tid != VG_INVALID_THREADID) {
440 ai->akind = Stack;
441 ai->stack_tid = tid;
442 return;
443 }
444 /* Search for a recently freed block which might bracket it. */
thughes4ad52d02004-06-27 17:37:21 +0000445 sc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk, &a);
njn3e884182003-04-15 13:03:23 +0000446 if (NULL != sc) {
njn43c799e2003-04-08 00:08:52 +0000447 ai->akind = Freed;
njn3e884182003-04-15 13:03:23 +0000448 ai->blksize = sc->size;
449 ai->rwoffset = (Int)a - (Int)sc->data;
450 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000451 return;
452 }
453 /* Search for a currently malloc'd block which might bracket it. */
thughes4ad52d02004-06-27 17:37:21 +0000454 sc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode, &a);
njn43c799e2003-04-08 00:08:52 +0000455 if (NULL != sc) {
456 ai->akind = Mallocd;
njn3e884182003-04-15 13:03:23 +0000457 ai->blksize = sc->size;
458 ai->rwoffset = (Int)(a) - (Int)sc->data;
459 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000460 return;
461 }
462 /* Clueless ... */
463 ai->akind = Unknown;
464 return;
465}
466
njn5c004e42002-11-18 11:04:50 +0000467/* Is this address within some small distance below %ESP? Used only
468 for the --workaround-gcc296-bugs kludge. */
469static Bool is_just_below_ESP( Addr esp, Addr aa )
470{
nethercote50397c22004-11-04 18:03:06 +0000471 if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
njn5c004e42002-11-18 11:04:50 +0000472 return True;
473 else
474 return False;
475}
476
sewardjaf48a602003-07-06 00:54:47 +0000477/* This one called from generated code and non-generated code. */
njn5c004e42002-11-18 11:04:50 +0000478
njn72718642003-07-24 08:45:32 +0000479void MAC_(record_address_error) ( ThreadId tid, Addr a, Int size,
sewardjaf48a602003-07-06 00:54:47 +0000480 Bool isWrite )
njn5c004e42002-11-18 11:04:50 +0000481{
njn43c799e2003-04-08 00:08:52 +0000482 MAC_Error err_extra;
483 Bool just_below_esp;
njn5c004e42002-11-18 11:04:50 +0000484
njn67516132005-03-22 04:02:43 +0000485 just_below_esp = is_just_below_ESP( VG_(get_SP)(tid), a );
njn5c004e42002-11-18 11:04:50 +0000486
487 /* If this is caused by an access immediately below %ESP, and the
488 user asks nicely, we just ignore it. */
njn43c799e2003-04-08 00:08:52 +0000489 if (MAC_(clo_workaround_gcc296_bugs) && just_below_esp)
njn5c004e42002-11-18 11:04:50 +0000490 return;
491
njn43c799e2003-04-08 00:08:52 +0000492 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000493 err_extra.axskind = isWrite ? WriteAxs : ReadAxs;
494 err_extra.size = size;
495 err_extra.addrinfo.akind = Undescribed;
496 err_extra.addrinfo.maybe_gcc = just_below_esp;
njn72718642003-07-24 08:45:32 +0000497 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000498}
499
500/* These ones are called from non-generated code */
501
502/* This is for memory errors in pthread functions, as opposed to pthread API
503 errors which are found by the core. */
nethercote8b76fe52004-11-08 19:20:09 +0000504void MAC_(record_core_mem_error) ( ThreadId tid, Bool isUnaddr, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000505{
njn43c799e2003-04-08 00:08:52 +0000506 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000507
njn43c799e2003-04-08 00:08:52 +0000508 MAC_(clear_MAC_Error)( &err_extra );
nethercote8b76fe52004-11-08 19:20:09 +0000509 err_extra.isUnaddr = isUnaddr;
njn72718642003-07-24 08:45:32 +0000510 VG_(maybe_record_error)( tid, CoreMemErr, /*addr*/0, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000511}
512
njn16390462005-05-08 15:26:00 +0000513// Three kinds of param errors:
514// - register arg contains undefined bytes
515// - memory arg is unaddressable
516// - memory arg contains undefined bytes
517// 'isReg' and 'isUnaddr' dictate which of these it is.
nethercote8b76fe52004-11-08 19:20:09 +0000518void MAC_(record_param_error) ( ThreadId tid, Addr a, Bool isReg,
519 Bool isUnaddr, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000520{
njn43c799e2003-04-08 00:08:52 +0000521 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000522
njnca82cc02004-11-22 17:18:48 +0000523 tl_assert(VG_INVALID_THREADID != tid);
njn16390462005-05-08 15:26:00 +0000524 if (isUnaddr) tl_assert(!isReg); // unaddressable register is impossible
njn43c799e2003-04-08 00:08:52 +0000525 MAC_(clear_MAC_Error)( &err_extra );
nethercote8b76fe52004-11-08 19:20:09 +0000526 err_extra.addrinfo.akind = ( isReg ? Register : Undescribed );
527 err_extra.isUnaddr = isUnaddr;
njn72718642003-07-24 08:45:32 +0000528 VG_(maybe_record_error)( tid, ParamErr, a, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000529}
530
njn72718642003-07-24 08:45:32 +0000531void MAC_(record_jump_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000532{
njn43c799e2003-04-08 00:08:52 +0000533 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000534
njnca82cc02004-11-22 17:18:48 +0000535 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000536 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000537 err_extra.axskind = ExecAxs;
nethercote7250b8f2004-04-13 08:47:35 +0000538 err_extra.size = 1; // size only used for suppressions
njn5c004e42002-11-18 11:04:50 +0000539 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000540 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000541}
542
njn72718642003-07-24 08:45:32 +0000543void MAC_(record_free_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000544{
njn43c799e2003-04-08 00:08:52 +0000545 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000546
njnca82cc02004-11-22 17:18:48 +0000547 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000548 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000549 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000550 VG_(maybe_record_error)( tid, FreeErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000551}
552
rjwalshbc0bb832004-06-19 18:12:36 +0000553void MAC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )
554{
555 MAC_Error err_extra;
556
njnca82cc02004-11-22 17:18:48 +0000557 tl_assert(VG_INVALID_THREADID != tid);
rjwalshbc0bb832004-06-19 18:12:36 +0000558 MAC_(clear_MAC_Error)( &err_extra );
559 err_extra.addrinfo.akind = Undescribed;
560 VG_(maybe_record_error)( tid, IllegalMempoolErr, a, /*s*/NULL, &err_extra );
561}
562
njn72718642003-07-24 08:45:32 +0000563void MAC_(record_freemismatch_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000564{
njn43c799e2003-04-08 00:08:52 +0000565 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000566
njnca82cc02004-11-22 17:18:48 +0000567 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000568 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000569 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000570 VG_(maybe_record_error)( tid, FreeMismatchErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000571}
572
sewardj2a99cf62004-11-24 10:44:19 +0000573void MAC_(record_overlap_error) ( ThreadId tid,
574 Char* function, OverlapExtra* ov_extra )
njn66fe05a2003-07-22 09:12:33 +0000575{
sewardj2a99cf62004-11-24 10:44:19 +0000576 VG_(maybe_record_error)(
577 tid, OverlapErr, /*addr*/0, /*s*/function, ov_extra );
njn66fe05a2003-07-22 09:12:33 +0000578}
579
580
njnb6cae9f2003-09-04 20:50:47 +0000581/* Updates the copy with address info if necessary (but not for all errors). */
njn51d827b2005-05-09 01:02:08 +0000582UInt MAC_(update_extra)( Error* err )
njn43c799e2003-04-08 00:08:52 +0000583{
njnb6cae9f2003-09-04 20:50:47 +0000584 switch (VG_(get_error_kind)(err)) {
585 case ValueErr:
586 case CoreMemErr:
587 case AddrErr:
588 case ParamErr:
589 case UserErr:
590 case FreeErr:
rjwalshbc0bb832004-06-19 18:12:36 +0000591 case IllegalMempoolErr:
njnb6cae9f2003-09-04 20:50:47 +0000592 case FreeMismatchErr: {
nethercote8b76fe52004-11-08 19:20:09 +0000593 MAC_Error* extra = VG_(get_error_extra)(err);
njnb6cae9f2003-09-04 20:50:47 +0000594 if (extra != NULL && Undescribed == extra->addrinfo.akind) {
595 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
596 }
597 return sizeof(MAC_Error);
598 }
njn43c799e2003-04-08 00:08:52 +0000599 /* Don't need to return the correct size -- LeakErrs are always shown with
600 VG_(unique_error)() so they're not copied anyway. */
njnb6cae9f2003-09-04 20:50:47 +0000601 case LeakErr: return 0;
602 case OverlapErr: return sizeof(OverlapExtra);
njn67993252004-11-22 18:02:32 +0000603 default: VG_(tool_panic)("update_extra: bad errkind");
njn43c799e2003-04-08 00:08:52 +0000604 }
njn43c799e2003-04-08 00:08:52 +0000605}
606
607
njn5c004e42002-11-18 11:04:50 +0000608/*------------------------------------------------------------*/
609/*--- Suppressions ---*/
610/*------------------------------------------------------------*/
611
njn43c799e2003-04-08 00:08:52 +0000612Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
613{
614 SuppKind skind;
615
616 if (VG_STREQ(name, "Param")) skind = ParamSupp;
617 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
618 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
619 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
620 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
621 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
njnc0616662003-06-12 09:58:41 +0000622 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
njn43c799e2003-04-08 00:08:52 +0000623 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
624 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
njne9cab142003-09-19 08:10:07 +0000625 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
rjwalshbc0bb832004-06-19 18:12:36 +0000626 else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
njn43c799e2003-04-08 00:08:52 +0000627 else
628 return False;
629
630 VG_(set_supp_kind)(su, skind);
631 return True;
632}
633
njn51d827b2005-05-09 01:02:08 +0000634Bool MAC_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
njn5c004e42002-11-18 11:04:50 +0000635{
636 Bool eof;
637
638 if (VG_(get_supp_kind)(su) == ParamSupp) {
639 eof = VG_(get_line) ( fd, buf, nBuf );
640 if (eof) return False;
641 VG_(set_supp_string)(su, VG_(strdup)(buf));
642 }
643 return True;
644}
645
njn51d827b2005-05-09 01:02:08 +0000646Bool MAC_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000647{
sewardj05bcdcb2003-05-18 10:05:38 +0000648 Int su_size;
njn43c799e2003-04-08 00:08:52 +0000649 MAC_Error* err_extra = VG_(get_error_extra)(err);
650 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000651
652 switch (VG_(get_supp_kind)(su)) {
653 case ParamSupp:
654 return (ekind == ParamErr
njn43c799e2003-04-08 00:08:52 +0000655 && VG_STREQ(VG_(get_error_string)(err),
656 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000657
658 case CoreMemSupp:
659 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000660 && VG_STREQ(VG_(get_error_string)(err),
661 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000662
663 case Value0Supp: su_size = 0; goto value_case;
664 case Value1Supp: su_size = 1; goto value_case;
665 case Value2Supp: su_size = 2; goto value_case;
666 case Value4Supp: su_size = 4; goto value_case;
667 case Value8Supp: su_size = 8; goto value_case;
njnc0616662003-06-12 09:58:41 +0000668 case Value16Supp:su_size =16; goto value_case;
njn5c004e42002-11-18 11:04:50 +0000669 value_case:
670 return (ekind == ValueErr && err_extra->size == su_size);
671
672 case Addr1Supp: su_size = 1; goto addr_case;
673 case Addr2Supp: su_size = 2; goto addr_case;
674 case Addr4Supp: su_size = 4; goto addr_case;
675 case Addr8Supp: su_size = 8; goto addr_case;
njnc0616662003-06-12 09:58:41 +0000676 case Addr16Supp:su_size =16; goto addr_case;
njn5c004e42002-11-18 11:04:50 +0000677 addr_case:
678 return (ekind == AddrErr && err_extra->size == su_size);
679
680 case FreeSupp:
681 return (ekind == FreeErr || ekind == FreeMismatchErr);
682
njn34419c12003-05-02 17:24:29 +0000683 case OverlapSupp:
684 return (ekind = OverlapErr);
685
sewardj4a19e2f2002-12-26 11:50:21 +0000686 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000687 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000688
rjwalshbc0bb832004-06-19 18:12:36 +0000689 case MempoolSupp:
690 return (ekind == IllegalMempoolErr);
691
njn5c004e42002-11-18 11:04:50 +0000692 default:
693 VG_(printf)("Error:\n"
694 " unknown suppression type %d\n",
695 VG_(get_supp_kind)(su));
njn67993252004-11-22 18:02:32 +0000696 VG_(tool_panic)("unknown suppression type in "
njn51d827b2005-05-09 01:02:08 +0000697 "MAC_(error_matches_suppression)");
njn5c004e42002-11-18 11:04:50 +0000698 }
699}
700
njn51d827b2005-05-09 01:02:08 +0000701Char* MAC_(get_error_name) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000702{
703 Char* s;
704 switch (VG_(get_error_kind)(err)) {
705 case ParamErr: return "Param";
706 case UserErr: return NULL; /* Can't suppress User errors */
707 case FreeMismatchErr: return "Free";
rjwalshbc0bb832004-06-19 18:12:36 +0000708 case IllegalMempoolErr: return "Mempool";
njn43c799e2003-04-08 00:08:52 +0000709 case FreeErr: return "Free";
710 case AddrErr:
711 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
712 case 1: return "Addr1";
713 case 2: return "Addr2";
714 case 4: return "Addr4";
715 case 8: return "Addr8";
njnc0616662003-06-12 09:58:41 +0000716 case 16: return "Addr16";
njn67993252004-11-22 18:02:32 +0000717 default: VG_(tool_panic)("unexpected size for Addr");
njn43c799e2003-04-08 00:08:52 +0000718 }
719
720 case ValueErr:
721 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
722 case 0: return "Cond";
723 case 1: return "Value1";
724 case 2: return "Value2";
725 case 4: return "Value4";
726 case 8: return "Value8";
njnc0616662003-06-12 09:58:41 +0000727 case 16: return "Value16";
njn67993252004-11-22 18:02:32 +0000728 default: VG_(tool_panic)("unexpected size for Value");
njn43c799e2003-04-08 00:08:52 +0000729 }
730 case CoreMemErr: return "CoreMem";
njn34419c12003-05-02 17:24:29 +0000731 case OverlapErr: return "Overlap";
njn43c799e2003-04-08 00:08:52 +0000732 case LeakErr: return "Leak";
njn67993252004-11-22 18:02:32 +0000733 default: VG_(tool_panic)("get_error_name: unexpected type");
njn43c799e2003-04-08 00:08:52 +0000734 }
735 VG_(printf)(s);
736}
737
njn51d827b2005-05-09 01:02:08 +0000738void MAC_(print_extra_suppression_info) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000739{
740 if (ParamErr == VG_(get_error_kind)(err)) {
741 VG_(printf)(" %s\n", VG_(get_error_string)(err));
742 }
743}
njn5c004e42002-11-18 11:04:50 +0000744
745/*------------------------------------------------------------*/
746/*--- Crude profiling machinery. ---*/
747/*------------------------------------------------------------*/
748
749/* Event index. If just the name of the fn is given, this means the
750 number of calls to the fn. Otherwise it is the specified event.
751 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
752 The rest are shared.
753
754 10 alloc_secondary_map
755
756 20 get_abit
757M 21 get_vbyte
758 22 set_abit
759M 23 set_vbyte
760 24 get_abits4_ALIGNED
761M 25 get_vbytes4_ALIGNED
762
763 30 set_address_range_perms
764 31 set_address_range_perms(lower byte loop)
765 32 set_address_range_perms(quadword loop)
766 33 set_address_range_perms(upper byte loop)
767
768 35 make_noaccess
769 36 make_writable
770 37 make_readable
771A 38 make_accessible
772
773 40 copy_address_range_state
774 41 copy_address_range_state(byte loop)
775 42 check_writable
776 43 check_writable(byte loop)
777 44 check_readable
778 45 check_readable(byte loop)
779 46 check_readable_asciiz
780 47 check_readable_asciiz(byte loop)
781A 48 check_accessible
782A 49 check_accessible(byte loop)
783
784 50 make_noaccess_aligned
785 51 make_writable_aligned
786
787M 60 helperc_LOADV4
788M 61 helperc_STOREV4
789M 62 helperc_LOADV2
790M 63 helperc_STOREV2
791M 64 helperc_LOADV1
792M 65 helperc_STOREV1
793
794A 66 helperc_ACCESS4
795A 67 helperc_ACCESS2
796A 68 helperc_ACCESS1
797
798M 70 rim_rd_V4_SLOWLY
799M 71 rim_wr_V4_SLOWLY
800M 72 rim_rd_V2_SLOWLY
801M 73 rim_wr_V2_SLOWLY
802M 74 rim_rd_V1_SLOWLY
803M 75 rim_wr_V1_SLOWLY
804
805A 76 ACCESS4_SLOWLY
806A 77 ACCESS2_SLOWLY
807A 78 ACCESS1_SLOWLY
808
809 80 fpu_read
810 81 fpu_read aligned 4
811 82 fpu_read aligned 8
812 83 fpu_read 2
jsewardfca60182004-01-04 23:30:55 +0000813 84 fpu_read 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000814
815M 85 fpu_write
816M 86 fpu_write aligned 4
817M 87 fpu_write aligned 8
818M 88 fpu_write 2
jsewardfca60182004-01-04 23:30:55 +0000819M 89 fpu_write 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000820
821 90 fpu_access
822 91 fpu_access aligned 4
823 92 fpu_access aligned 8
824 93 fpu_access 2
jsewardfca60182004-01-04 23:30:55 +0000825 94 fpu_access 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000826
827 100 fpu_access_check_SLOWLY
828 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000829
830 110 new_mem_stack_4
831 111 new_mem_stack_8
832 112 new_mem_stack_12
833 113 new_mem_stack_16
834 114 new_mem_stack_32
835 115 new_mem_stack
836
837 120 die_mem_stack_4
838 121 die_mem_stack_8
839 122 die_mem_stack_12
840 123 die_mem_stack_16
841 124 die_mem_stack_32
842 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000843*/
844
njn43c799e2003-04-08 00:08:52 +0000845#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000846
sewardjc1a2cda2005-04-21 17:34:00 +0000847UInt MAC_(event_ctr)[N_PROF_EVENTS];
848HChar* MAC_(event_ctr_name)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000849
njnb4aee052003-04-15 14:09:58 +0000850static void init_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000851{
852 Int i;
sewardjc1a2cda2005-04-21 17:34:00 +0000853 for (i = 0; i < N_PROF_EVENTS; i++) {
njn43c799e2003-04-08 00:08:52 +0000854 MAC_(event_ctr)[i] = 0;
sewardjc1a2cda2005-04-21 17:34:00 +0000855 MAC_(event_ctr_name)[i] = NULL;
856 }
njn5c004e42002-11-18 11:04:50 +0000857}
858
njnb4aee052003-04-15 14:09:58 +0000859static void done_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000860{
sewardjc1a2cda2005-04-21 17:34:00 +0000861 Int i;
862 Bool spaced = False;
njn5c004e42002-11-18 11:04:50 +0000863 for (i = 0; i < N_PROF_EVENTS; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +0000864 if (!spaced && (i % 10) == 0) {
njn5c004e42002-11-18 11:04:50 +0000865 VG_(printf)("\n");
sewardjc1a2cda2005-04-21 17:34:00 +0000866 spaced = True;
867 }
868 if (MAC_(event_ctr)[i] > 0) {
869 spaced = False;
870 VG_(printf)( "prof mem event %3d: %9d %s\n",
871 i, MAC_(event_ctr)[i],
872 MAC_(event_ctr_name)[i]
873 ? MAC_(event_ctr_name)[i] : "unnamed");
874 }
njn5c004e42002-11-18 11:04:50 +0000875 }
njn5c004e42002-11-18 11:04:50 +0000876}
877
878#else
879
njnb4aee052003-04-15 14:09:58 +0000880static void init_prof_mem ( void ) { }
881static void done_prof_mem ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000882
njn5c004e42002-11-18 11:04:50 +0000883#endif
884
885/*------------------------------------------------------------*/
njn3e884182003-04-15 13:03:23 +0000886/*--- Common initialisation + finalisation ---*/
887/*------------------------------------------------------------*/
888
889void MAC_(common_pre_clo_init)(void)
890{
891 MAC_(malloc_list) = VG_(HT_construct)();
rjwalshbc0bb832004-06-19 18:12:36 +0000892 MAC_(mempool_list) = VG_(HT_construct)();
njn3e884182003-04-15 13:03:23 +0000893 init_prof_mem();
894}
895
njnb8dca862005-03-14 02:42:44 +0000896void MAC_(common_fini)(void (*leak_check)(ThreadId tid, LeakCheckMode mode))
njn3e884182003-04-15 13:03:23 +0000897{
njn86f12dc2005-03-14 01:16:05 +0000898 MAC_(print_malloc_stats)();
njn3e884182003-04-15 13:03:23 +0000899
sewardj71bc3cb2005-05-19 00:25:45 +0000900 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
sewardjb5f6f512005-03-10 23:59:00 +0000901 if (MAC_(clo_leak_check) == LC_Off)
njn3e884182003-04-15 13:03:23 +0000902 VG_(message)(Vg_UserMsg,
903 "For a detailed leak analysis, rerun with: --leak-check=yes");
904
905 VG_(message)(Vg_UserMsg,
906 "For counts of detected errors, rerun with: -v");
907 }
sewardjb5f6f512005-03-10 23:59:00 +0000908 if (MAC_(clo_leak_check) != LC_Off)
njnb8dca862005-03-14 02:42:44 +0000909 leak_check(1/*bogus ThreadId*/, MAC_(clo_leak_check));
njn3e884182003-04-15 13:03:23 +0000910
911 done_prof_mem();
912}
913
914/*------------------------------------------------------------*/
njn47363ab2003-04-21 13:24:40 +0000915/*--- Common client request handling ---*/
916/*------------------------------------------------------------*/
917
nethercoted1b64b22004-11-04 18:22:28 +0000918Bool MAC_(handle_common_client_requests)(ThreadId tid, UWord* arg, UWord* ret )
njn47363ab2003-04-21 13:24:40 +0000919{
njnd7994182003-10-02 13:44:04 +0000920 Char* err =
921 "The client requests VALGRIND_MALLOCLIKE_BLOCK and\n"
922 " VALGRIND_FREELIKE_BLOCK have moved. Please recompile your\n"
923 " program to incorporate the updates in the Valgrind header files.\n"
924 " You shouldn't need to change the text of your program at all.\n"
925 " Everything should then work as before. Sorry for the bother.\n";
njn47363ab2003-04-21 13:24:40 +0000926
927 switch (arg[0]) {
njn10785452003-05-20 16:38:24 +0000928 case VG_USERREQ__COUNT_LEAKS: { /* count leaked bytes */
nethercoted1b64b22004-11-04 18:22:28 +0000929 UWord** argp = (UWord**)arg;
njne8b5c052003-07-22 22:03:58 +0000930 // MAC_(bytes_leaked) et al were set by the last leak check (or zero
931 // if no prior leak checks performed).
sewardjb5f6f512005-03-10 23:59:00 +0000932 *argp[1] = MAC_(bytes_leaked) + MAC_(bytes_indirect);
njne8b5c052003-07-22 22:03:58 +0000933 *argp[2] = MAC_(bytes_dubious);
934 *argp[3] = MAC_(bytes_reachable);
935 *argp[4] = MAC_(bytes_suppressed);
sewardjb5f6f512005-03-10 23:59:00 +0000936 // there is no argp[5]
937 //*argp[5] = MAC_(bytes_indirect);
938 // XXX need to make *argp[1-4] readable
njn47363ab2003-04-21 13:24:40 +0000939 *ret = 0;
940 return True;
njn10785452003-05-20 16:38:24 +0000941 }
njnd7994182003-10-02 13:44:04 +0000942 case VG_USERREQ__MALLOCLIKE_BLOCK__OLD_DO_NOT_USE:
943 case VG_USERREQ__FREELIKE_BLOCK__OLD_DO_NOT_USE:
njn67993252004-11-22 18:02:32 +0000944 VG_(tool_panic)(err);
njnd7994182003-10-02 13:44:04 +0000945
njn10785452003-05-20 16:38:24 +0000946 case VG_USERREQ__MALLOCLIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000947 Addr p = (Addr)arg[1];
nethercote928a5f72004-11-03 18:10:37 +0000948 SizeT sizeB = arg[2];
njnd7994182003-10-02 13:44:04 +0000949 UInt rzB = arg[3];
950 Bool is_zeroed = (Bool)arg[4];
njn47363ab2003-04-21 13:24:40 +0000951
sewardj2a99cf62004-11-24 10:44:19 +0000952 MAC_(new_block) ( tid, p, sizeB, /*ignored*/0, rzB, is_zeroed,
nethercote57e36b32004-07-10 14:56:28 +0000953 MAC_AllocCustom, MAC_(malloc_list) );
njn10785452003-05-20 16:38:24 +0000954 return True;
955 }
956 case VG_USERREQ__FREELIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000957 Addr p = (Addr)arg[1];
958 UInt rzB = arg[2];
njn10785452003-05-20 16:38:24 +0000959
sewardj2a99cf62004-11-24 10:44:19 +0000960 MAC_(handle_free) ( tid, p, rzB, MAC_AllocCustom );
njn10785452003-05-20 16:38:24 +0000961 return True;
962 }
njnd7994182003-10-02 13:44:04 +0000963
njn1f8b3e72005-03-22 04:27:14 +0000964 case _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR: {
965 Char* s = (Char*) arg[1];
966 OverlapExtra* extra = (OverlapExtra*)arg[2];
967 MAC_(record_overlap_error)(tid, s, extra);
nethercotee3a53722004-05-05 10:46:22 +0000968 return True;
njn1f8b3e72005-03-22 04:27:14 +0000969 }
nethercotee3a53722004-05-05 10:46:22 +0000970
rjwalshbc0bb832004-06-19 18:12:36 +0000971 case VG_USERREQ__CREATE_MEMPOOL: {
972 Addr pool = (Addr)arg[1];
973 UInt rzB = arg[2];
974 Bool is_zeroed = (Bool)arg[3];
975
976 MAC_(create_mempool) ( pool, rzB, is_zeroed );
977 return True;
978 }
979
980 case VG_USERREQ__DESTROY_MEMPOOL: {
981 Addr pool = (Addr)arg[1];
982
983 MAC_(destroy_mempool) ( pool );
984 return True;
985 }
986
987 case VG_USERREQ__MEMPOOL_ALLOC: {
988 Addr pool = (Addr)arg[1];
989 Addr addr = (Addr)arg[2];
990 UInt size = arg[3];
991
sewardj2a99cf62004-11-24 10:44:19 +0000992 MAC_(mempool_alloc) ( tid, pool, addr, size );
rjwalshbc0bb832004-06-19 18:12:36 +0000993 return True;
994 }
995
996 case VG_USERREQ__MEMPOOL_FREE: {
997 Addr pool = (Addr)arg[1];
998 Addr addr = (Addr)arg[2];
999
1000 MAC_(mempool_free) ( pool, addr );
1001 return True;
1002 }
1003
njn47363ab2003-04-21 13:24:40 +00001004 default:
1005 return False;
1006 }
1007}
1008
njn5c004e42002-11-18 11:04:50 +00001009/*--------------------------------------------------------------------*/
njn00cae242005-05-09 01:13:44 +00001010/*--- end ---*/
njn5c004e42002-11-18 11:04:50 +00001011/*--------------------------------------------------------------------*/