blob: 6c56ca2442436ec97b847b6da23db3669c335b8d [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
njnc7561b92005-06-19 01:24:32 +000033#include "pub_tool_basics.h"
34#include "pub_tool_errormgr.h" // For mac_shared.h
35#include "pub_tool_execontext.h" // For mac_shared.h
36#include "pub_tool_hashtable.h" // For mac_shared.h
njn132bfcc2005-06-04 19:16:06 +000037#include "pub_tool_libcassert.h"
njn97405b22005-06-02 03:39:33 +000038#include "pub_tool_libcbase.h"
njn36a20fa2005-06-03 03:08:39 +000039#include "pub_tool_libcprint.h"
njnc7561b92005-06-19 01:24:32 +000040#include "pub_tool_mallocfree.h"
njnf536bbb2005-06-13 04:21:38 +000041#include "pub_tool_machine.h"
njnc7561b92005-06-19 01:24:32 +000042#include "pub_tool_options.h"
43#include "pub_tool_profile.h" // For mac_shared.h
44#include "pub_tool_replacemalloc.h"
45#include "pub_tool_threadstate.h"
46#include "mac_shared.h"
njn47363ab2003-04-21 13:24:40 +000047#include "memcheck.h" /* for VG_USERREQ__* */
48
njn5c004e42002-11-18 11:04:50 +000049/*------------------------------------------------------------*/
50/*--- Defns ---*/
51/*------------------------------------------------------------*/
52
53/* These many bytes below %ESP are considered addressible if we're
54 doing the --workaround-gcc296-bugs hack. */
55#define VG_GCC296_BUG_STACK_SLOP 1024
56
57/*------------------------------------------------------------*/
58/*--- Command line options ---*/
59/*------------------------------------------------------------*/
60
sewardjb5f6f512005-03-10 23:59:00 +000061Bool MAC_(clo_partial_loads_ok) = True;
62Int MAC_(clo_freelist_vol) = 1000000;
njn6a329422005-03-12 20:38:13 +000063LeakCheckMode MAC_(clo_leak_check) = LC_Summary;
sewardjb5f6f512005-03-10 23:59:00 +000064VgRes MAC_(clo_leak_resolution) = Vg_LowRes;
65Bool MAC_(clo_show_reachable) = False;
66Bool MAC_(clo_workaround_gcc296_bugs) = False;
njn5c004e42002-11-18 11:04:50 +000067
njn43c799e2003-04-08 00:08:52 +000068Bool MAC_(process_common_cmd_line_option)(Char* arg)
njn5c004e42002-11-18 11:04:50 +000069{
njn45270a22005-03-27 01:00:11 +000070 VG_BOOL_CLO(arg, "--partial-loads-ok", MAC_(clo_partial_loads_ok))
71 else VG_BOOL_CLO(arg, "--show-reachable", MAC_(clo_show_reachable))
72 else VG_BOOL_CLO(arg, "--workaround-gcc296-bugs",MAC_(clo_workaround_gcc296_bugs))
nethercote27fec902004-06-16 21:26:32 +000073
njn45270a22005-03-27 01:00:11 +000074 else VG_BNUM_CLO(arg, "--freelist-vol", MAC_(clo_freelist_vol), 0, 1000000000)
nethercote27fec902004-06-16 21:26:32 +000075
sewardjb5f6f512005-03-10 23:59:00 +000076 else if (VG_CLO_STREQ(arg, "--leak-check=no"))
77 MAC_(clo_leak_check) = LC_Off;
78 else if (VG_CLO_STREQ(arg, "--leak-check=summary"))
79 MAC_(clo_leak_check) = LC_Summary;
80 else if (VG_CLO_STREQ(arg, "--leak-check=yes") ||
81 VG_CLO_STREQ(arg, "--leak-check=full"))
82 MAC_(clo_leak_check) = LC_Full;
83
njn43c799e2003-04-08 00:08:52 +000084 else if (VG_CLO_STREQ(arg, "--leak-resolution=low"))
85 MAC_(clo_leak_resolution) = Vg_LowRes;
86 else if (VG_CLO_STREQ(arg, "--leak-resolution=med"))
87 MAC_(clo_leak_resolution) = Vg_MedRes;
88 else if (VG_CLO_STREQ(arg, "--leak-resolution=high"))
89 MAC_(clo_leak_resolution) = Vg_HighRes;
njn5c004e42002-11-18 11:04:50 +000090
91 else
njn3e884182003-04-15 13:03:23 +000092 return VG_(replacement_malloc_process_cmd_line_option)(arg);
njn5c004e42002-11-18 11:04:50 +000093
94 return True;
njn43c799e2003-04-08 00:08:52 +000095}
njn5c004e42002-11-18 11:04:50 +000096
njn3e884182003-04-15 13:03:23 +000097void MAC_(print_common_usage)(void)
njn43c799e2003-04-08 00:08:52 +000098{
njn3e884182003-04-15 13:03:23 +000099 VG_(printf)(
sewardjb5f6f512005-03-10 23:59:00 +0000100" --partial-loads-ok=no|yes too hard to explain here; see manual [yes]\n"
101" --freelist-vol=<number> volume of freed blocks queue [1000000]\n"
njn6a329422005-03-12 20:38:13 +0000102" --leak-check=no|summary|full search for memory leaks at exit? [summary]\n"
sewardjb5f6f512005-03-10 23:59:00 +0000103" --leak-resolution=low|med|high how much bt merging in leak check [low]\n"
104" --show-reachable=no|yes show reachable blocks in leak check? [no]\n"
njn3e884182003-04-15 13:03:23 +0000105" --workaround-gcc296-bugs=no|yes self explanatory [no]\n"
106 );
107 VG_(replacement_malloc_print_usage)();
njn43c799e2003-04-08 00:08:52 +0000108}
109
njn3e884182003-04-15 13:03:23 +0000110void MAC_(print_common_debug_usage)(void)
njn43c799e2003-04-08 00:08:52 +0000111{
njn3e884182003-04-15 13:03:23 +0000112 VG_(replacement_malloc_print_debug_usage)();
njn5c004e42002-11-18 11:04:50 +0000113}
114
115/*------------------------------------------------------------*/
116/*--- Comparing and printing errors ---*/
117/*------------------------------------------------------------*/
118
119static __inline__
120void clear_AddrInfo ( AddrInfo* ai )
121{
122 ai->akind = Unknown;
123 ai->blksize = 0;
124 ai->rwoffset = 0;
125 ai->lastchange = NULL;
126 ai->stack_tid = VG_INVALID_THREADID;
127 ai->maybe_gcc = False;
sewardjb5f6f512005-03-10 23:59:00 +0000128 ai->desc = NULL;
njn5c004e42002-11-18 11:04:50 +0000129}
130
njn43c799e2003-04-08 00:08:52 +0000131void MAC_(clear_MAC_Error) ( MAC_Error* err_extra )
njn5c004e42002-11-18 11:04:50 +0000132{
133 err_extra->axskind = ReadAxs;
134 err_extra->size = 0;
135 clear_AddrInfo ( &err_extra->addrinfo );
nethercote8b76fe52004-11-08 19:20:09 +0000136 err_extra->isUnaddr = True;
njn5c004e42002-11-18 11:04:50 +0000137}
138
139__attribute__ ((unused))
140static Bool eq_AddrInfo ( VgRes res, AddrInfo* ai1, AddrInfo* ai2 )
141{
142 if (ai1->akind != Undescribed
143 && ai2->akind != Undescribed
144 && ai1->akind != ai2->akind)
145 return False;
146 if (ai1->akind == Freed || ai1->akind == Mallocd) {
147 if (ai1->blksize != ai2->blksize)
148 return False;
149 if (!VG_(eq_ExeContext)(res, ai1->lastchange, ai2->lastchange))
150 return False;
151 }
152 return True;
153}
154
155/* Compare error contexts, to detect duplicates. Note that if they
156 are otherwise the same, the faulting addrs and associated rwoffsets
157 are allowed to be different. */
158
njn51d827b2005-05-09 01:02:08 +0000159Bool MAC_(eq_Error) ( VgRes res, Error* e1, Error* e2 )
njn5c004e42002-11-18 11:04:50 +0000160{
njn43c799e2003-04-08 00:08:52 +0000161 MAC_Error* e1_extra = VG_(get_error_extra)(e1);
162 MAC_Error* e2_extra = VG_(get_error_extra)(e2);
njn7cc53a82002-11-19 16:19:32 +0000163
164 /* Guaranteed by calling function */
njnca82cc02004-11-22 17:18:48 +0000165 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
njn5c004e42002-11-18 11:04:50 +0000166
167 switch (VG_(get_error_kind)(e1)) {
168 case CoreMemErr: {
169 Char *e1s, *e2s;
nethercote8b76fe52004-11-08 19:20:09 +0000170 if (e1_extra->isUnaddr != e2_extra->isUnaddr) return False;
njn5c004e42002-11-18 11:04:50 +0000171 e1s = VG_(get_error_string)(e1);
172 e2s = VG_(get_error_string)(e2);
173 if (e1s == e2s) return True;
174 if (0 == VG_(strcmp)(e1s, e2s)) return True;
175 return False;
176 }
177
njn16390462005-05-08 15:26:00 +0000178 // Perhaps we should also check the addrinfo.akinds for equality.
179 // That would result in more error reports, but only in cases where
180 // a register contains uninitialised bytes and points to memory
181 // containing uninitialised bytes. Currently, the 2nd of those to be
182 // detected won't be reported. That is (nearly?) always the memory
183 // error, which is good.
njn5c004e42002-11-18 11:04:50 +0000184 case ParamErr:
njn16390462005-05-08 15:26:00 +0000185 if (0 != VG_(strcmp)(VG_(get_error_string)(e1),
186 VG_(get_error_string)(e2))) return False;
187 // fall through
188 case UserErr:
189 if (e1_extra->isUnaddr != e2_extra->isUnaddr) return False;
njn5c004e42002-11-18 11:04:50 +0000190 return True;
191
192 case FreeErr:
193 case FreeMismatchErr:
194 /* JRS 2002-Aug-26: comparing addrs seems overkill and can
195 cause excessive duplication of errors. Not even AddrErr
196 below does that. So don't compare either the .addr field
197 or the .addrinfo fields. */
198 /* if (e1->addr != e2->addr) return False; */
199 /* if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
200 return False;
201 */
202 return True;
203
204 case AddrErr:
205 /* if (e1_extra->axskind != e2_extra->axskind) return False; */
206 if (e1_extra->size != e2_extra->size) return False;
207 /*
208 if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
209 return False;
210 */
211 return True;
212
213 case ValueErr:
214 if (e1_extra->size != e2_extra->size) return False;
215 return True;
216
njn34419c12003-05-02 17:24:29 +0000217 case OverlapErr:
218 return True;
219
njn43c799e2003-04-08 00:08:52 +0000220 case LeakErr:
njn51d827b2005-05-09 01:02:08 +0000221 VG_(tool_panic)("Shouldn't get LeakErr in MAC_(eq_Error),\n"
njn43c799e2003-04-08 00:08:52 +0000222 "since it's handled with VG_(unique_error)()!");
223
rjwalshbc0bb832004-06-19 18:12:36 +0000224 case IllegalMempoolErr:
225 return True;
226
njn5c004e42002-11-18 11:04:50 +0000227 default:
228 VG_(printf)("Error:\n unknown error code %d\n",
229 VG_(get_error_kind)(e1));
njn51d827b2005-05-09 01:02:08 +0000230 VG_(tool_panic)("unknown error code in MAC_(eq_Error)");
njn5c004e42002-11-18 11:04:50 +0000231 }
232}
233
njn43c799e2003-04-08 00:08:52 +0000234void MAC_(pp_AddrInfo) ( Addr a, AddrInfo* ai )
njn5c004e42002-11-18 11:04:50 +0000235{
sewardj71bc3cb2005-05-19 00:25:45 +0000236 HChar* xpre = VG_(clo_xml) ? " <auxwhat>" : " ";
237 HChar* xpost = VG_(clo_xml) ? "</auxwhat>" : "";
238
njn5c004e42002-11-18 11:04:50 +0000239 switch (ai->akind) {
240 case Stack:
241 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000242 "%sAddress 0x%llx is on thread %d's stack%s",
243 xpre, (ULong)a, ai->stack_tid, xpost);
njn5c004e42002-11-18 11:04:50 +0000244 break;
245 case Unknown:
246 if (ai->maybe_gcc) {
247 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000248 "%sAddress 0x%llx is just below the stack ptr. "
249 "To suppress, use: --workaround-gcc296-bugs=yes%s",
250 xpre, (ULong)a, xpost
251 );
njn5c004e42002-11-18 11:04:50 +0000252 } else {
253 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000254 "%sAddress 0x%llx "
255 "is not stack'd, malloc'd or (recently) free'd%s",
256 xpre, (ULong)a, xpost);
njn5c004e42002-11-18 11:04:50 +0000257 }
258 break;
rjwalshbc0bb832004-06-19 18:12:36 +0000259 case Freed: case Mallocd: case UserG: case Mempool: {
nethercote50397c22004-11-04 18:03:06 +0000260 SizeT delta;
sewardjb5f6f512005-03-10 23:59:00 +0000261 const Char* relative;
262 const Char* kind;
rjwalshbc0bb832004-06-19 18:12:36 +0000263 if (ai->akind == Mempool) {
264 kind = "mempool";
265 } else {
266 kind = "block";
267 }
sewardjb5f6f512005-03-10 23:59:00 +0000268 if (ai->desc != NULL)
269 kind = ai->desc;
270
njn5c004e42002-11-18 11:04:50 +0000271 if (ai->rwoffset < 0) {
nethercote50397c22004-11-04 18:03:06 +0000272 delta = (SizeT)(- ai->rwoffset);
njn5c004e42002-11-18 11:04:50 +0000273 relative = "before";
274 } else if (ai->rwoffset >= ai->blksize) {
275 delta = ai->rwoffset - ai->blksize;
276 relative = "after";
277 } else {
278 delta = ai->rwoffset;
279 relative = "inside";
280 }
sewardja81709d2002-12-28 12:55:48 +0000281 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000282 "%sAddress 0x%llx is %llu bytes %s a %s of size %d %s%s",
283 xpre,
tom14ea6852005-05-03 18:16:12 +0000284 (ULong)a, (ULong)delta, relative, kind,
sewardja81709d2002-12-28 12:55:48 +0000285 ai->blksize,
286 ai->akind==Mallocd ? "alloc'd"
287 : ai->akind==Freed ? "free'd"
sewardj71bc3cb2005-05-19 00:25:45 +0000288 : "client-defined",
289 xpost);
njn5c004e42002-11-18 11:04:50 +0000290 VG_(pp_ExeContext)(ai->lastchange);
291 break;
292 }
nethercote8b76fe52004-11-08 19:20:09 +0000293 case Register:
294 // print nothing
njnca82cc02004-11-22 17:18:48 +0000295 tl_assert(0 == a);
nethercote8b76fe52004-11-08 19:20:09 +0000296 break;
njn5c004e42002-11-18 11:04:50 +0000297 default:
njn67993252004-11-22 18:02:32 +0000298 VG_(tool_panic)("MAC_(pp_AddrInfo)");
njn43c799e2003-04-08 00:08:52 +0000299 }
300}
301
302/* This prints out the message for the error types where Memcheck and
303 Addrcheck have identical messages */
njnb126f732004-11-22 17:57:07 +0000304void MAC_(pp_shared_Error) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000305{
306 MAC_Error* err_extra = VG_(get_error_extra)(err);
307
sewardj71bc3cb2005-05-19 00:25:45 +0000308 HChar* xpre = VG_(clo_xml) ? " <what>" : "";
309 HChar* xpost = VG_(clo_xml) ? "</what>" : "";
310
njn43c799e2003-04-08 00:08:52 +0000311 switch (VG_(get_error_kind)(err)) {
312 case FreeErr:
sewardj71bc3cb2005-05-19 00:25:45 +0000313 if (VG_(clo_xml))
314 VG_(message)(Vg_UserMsg, " <kind>InvalidFree</kind>");
315 VG_(message)(Vg_UserMsg,
316 "%sInvalid free() / delete / delete[]%s",
317 xpre, xpost);
318 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
319 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
320 break;
321
njn43c799e2003-04-08 00:08:52 +0000322 case FreeMismatchErr:
sewardj71bc3cb2005-05-19 00:25:45 +0000323 if (VG_(clo_xml))
324 VG_(message)(Vg_UserMsg, " <kind>MismatchedFree</kind>");
325 VG_(message)(Vg_UserMsg,
326 "%sMismatched free() / delete / delete []%s",
327 xpre, xpost);
njn43c799e2003-04-08 00:08:52 +0000328 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
329 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
330 break;
331
njn89409f82003-09-26 14:55:31 +0000332 case AddrErr:
333 switch (err_extra->axskind) {
334 case ReadAxs:
sewardj71bc3cb2005-05-19 00:25:45 +0000335 if (VG_(clo_xml))
336 VG_(message)(Vg_UserMsg, " <kind>InvalidRead</kind>");
337 VG_(message)(Vg_UserMsg,
338 "%sInvalid read of size %d%s",
339 xpre, err_extra->size, xpost );
njn89409f82003-09-26 14:55:31 +0000340 break;
341 case WriteAxs:
sewardj71bc3cb2005-05-19 00:25:45 +0000342 if (VG_(clo_xml))
343 VG_(message)(Vg_UserMsg, " <kind>InvalidWrite</kind>");
344 VG_(message)(Vg_UserMsg,
345 "%sInvalid write of size %d%s",
346 xpre, err_extra->size, xpost );
njn89409f82003-09-26 14:55:31 +0000347 break;
348 case ExecAxs:
sewardj71bc3cb2005-05-19 00:25:45 +0000349 if (VG_(clo_xml))
350 VG_(message)(Vg_UserMsg, " <kind>InvalidJump</kind>");
351 VG_(message)(Vg_UserMsg,
352 "%sJump to the invalid address "
353 "stated on the next line%s",
354 xpre, xpost);
njn89409f82003-09-26 14:55:31 +0000355 break;
356 default:
njn51d827b2005-05-09 01:02:08 +0000357 VG_(tool_panic)("MAC_(pp_shared_Error)(axskind)");
njn89409f82003-09-26 14:55:31 +0000358 }
359 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
360 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
361 break;
362
njnb6cae9f2003-09-04 20:50:47 +0000363 case OverlapErr: {
364 OverlapExtra* ov_extra = (OverlapExtra*)VG_(get_error_extra)(err);
sewardj71bc3cb2005-05-19 00:25:45 +0000365 if (VG_(clo_xml))
366 VG_(message)(Vg_UserMsg, " <kind>Overlap</kind>");
njnb6cae9f2003-09-04 20:50:47 +0000367 if (ov_extra->len == -1)
368 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000369 "%sSource and destination overlap in %s(%p, %p)%s",
370 xpre,
njnb6cae9f2003-09-04 20:50:47 +0000371 VG_(get_error_string)(err),
sewardj71bc3cb2005-05-19 00:25:45 +0000372 ov_extra->dst, ov_extra->src,
373 xpost);
njnb6cae9f2003-09-04 20:50:47 +0000374 else
375 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000376 "%sSource and destination overlap in %s(%p, %p, %d)%s",
377 xpre,
njnb6cae9f2003-09-04 20:50:47 +0000378 VG_(get_error_string)(err),
sewardj71bc3cb2005-05-19 00:25:45 +0000379 ov_extra->dst, ov_extra->src, ov_extra->len,
380 xpost);
njn66fe05a2003-07-22 09:12:33 +0000381 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
382 break;
njnb6cae9f2003-09-04 20:50:47 +0000383 }
njn43c799e2003-04-08 00:08:52 +0000384 case LeakErr: {
njn02977032005-05-17 04:00:11 +0000385 MAC_(pp_LeakError)(err_extra);
njn43c799e2003-04-08 00:08:52 +0000386 break;
387 }
388
rjwalshbc0bb832004-06-19 18:12:36 +0000389 case IllegalMempoolErr:
sewardj71bc3cb2005-05-19 00:25:45 +0000390 if (VG_(clo_xml))
391 VG_(message)(Vg_UserMsg, " <kind>InvalidMemPool</kind>");
392 VG_(message)(Vg_UserMsg, "%sIllegal memory pool address%s",
393 xpre, xpost);
rjwalshbc0bb832004-06-19 18:12:36 +0000394 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
395 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
396 break;
397
njn43c799e2003-04-08 00:08:52 +0000398 default:
399 VG_(printf)("Error:\n unknown Memcheck/Addrcheck error code %d\n",
400 VG_(get_error_kind)(err));
njn67993252004-11-22 18:02:32 +0000401 VG_(tool_panic)("unknown error code in MAC_(pp_shared_Error)");
njn5c004e42002-11-18 11:04:50 +0000402 }
403}
404
405/*------------------------------------------------------------*/
406/*--- Recording errors ---*/
407/*------------------------------------------------------------*/
408
njn43c799e2003-04-08 00:08:52 +0000409/* Additional description function for describe_addr(); used by
410 MemCheck for user blocks, which Addrcheck doesn't support. */
411Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL;
thughes4ad52d02004-06-27 17:37:21 +0000412
413/* Callback for searching thread stacks */
414static Bool addr_is_in_bounds(Addr stack_min, Addr stack_max, void *ap)
415{
416 Addr a = *(Addr *)ap;
417
418 return (stack_min <= a && a <= stack_max);
419}
420
421/* Callback for searching free'd list */
422static Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc, void *ap)
423{
424 Addr a = *(Addr *)ap;
425
njn717cde52005-05-10 02:47:21 +0000426 return VG_(addr_is_in_block)( a, mc->data, mc->size,
427 MAC_MALLOC_REDZONE_SZB );
thughes4ad52d02004-06-27 17:37:21 +0000428}
429
430/* Callback for searching malloc'd lists */
431static Bool addr_is_in_HashNode(VgHashNode* sh_ch, void *ap)
432{
433 return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch, ap );
434}
435
njn43c799e2003-04-08 00:08:52 +0000436/* Describe an address as best you can, for error messages,
437 putting the result in ai. */
438static void describe_addr ( Addr a, AddrInfo* ai )
439{
njn3e884182003-04-15 13:03:23 +0000440 MAC_Chunk* sc;
441 ThreadId tid;
njn43c799e2003-04-08 00:08:52 +0000442
njn43c799e2003-04-08 00:08:52 +0000443 /* Perhaps it's a user-def'd block ? (only check if requested, though) */
444 if (NULL != MAC_(describe_addr_supp)) {
445 if (MAC_(describe_addr_supp)( a, ai ))
446 return;
447 }
448 /* Perhaps it's on a thread's stack? */
thughes4ad52d02004-06-27 17:37:21 +0000449 tid = VG_(first_matching_thread_stack)(addr_is_in_bounds, &a);
njn43c799e2003-04-08 00:08:52 +0000450 if (tid != VG_INVALID_THREADID) {
451 ai->akind = Stack;
452 ai->stack_tid = tid;
453 return;
454 }
455 /* Search for a recently freed block which might bracket it. */
thughes4ad52d02004-06-27 17:37:21 +0000456 sc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk, &a);
njn3e884182003-04-15 13:03:23 +0000457 if (NULL != sc) {
njn43c799e2003-04-08 00:08:52 +0000458 ai->akind = Freed;
njn3e884182003-04-15 13:03:23 +0000459 ai->blksize = sc->size;
460 ai->rwoffset = (Int)a - (Int)sc->data;
461 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000462 return;
463 }
464 /* Search for a currently malloc'd block which might bracket it. */
thughes4ad52d02004-06-27 17:37:21 +0000465 sc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode, &a);
njn43c799e2003-04-08 00:08:52 +0000466 if (NULL != sc) {
467 ai->akind = Mallocd;
njn3e884182003-04-15 13:03:23 +0000468 ai->blksize = sc->size;
469 ai->rwoffset = (Int)(a) - (Int)sc->data;
470 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000471 return;
472 }
473 /* Clueless ... */
474 ai->akind = Unknown;
475 return;
476}
477
njn5c004e42002-11-18 11:04:50 +0000478/* Is this address within some small distance below %ESP? Used only
479 for the --workaround-gcc296-bugs kludge. */
480static Bool is_just_below_ESP( Addr esp, Addr aa )
481{
nethercote50397c22004-11-04 18:03:06 +0000482 if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
njn5c004e42002-11-18 11:04:50 +0000483 return True;
484 else
485 return False;
486}
487
sewardjaf48a602003-07-06 00:54:47 +0000488/* This one called from generated code and non-generated code. */
njn5c004e42002-11-18 11:04:50 +0000489
njn72718642003-07-24 08:45:32 +0000490void MAC_(record_address_error) ( ThreadId tid, Addr a, Int size,
sewardjaf48a602003-07-06 00:54:47 +0000491 Bool isWrite )
njn5c004e42002-11-18 11:04:50 +0000492{
njn43c799e2003-04-08 00:08:52 +0000493 MAC_Error err_extra;
494 Bool just_below_esp;
njn5c004e42002-11-18 11:04:50 +0000495
njn67516132005-03-22 04:02:43 +0000496 just_below_esp = is_just_below_ESP( VG_(get_SP)(tid), a );
njn5c004e42002-11-18 11:04:50 +0000497
498 /* If this is caused by an access immediately below %ESP, and the
499 user asks nicely, we just ignore it. */
njn43c799e2003-04-08 00:08:52 +0000500 if (MAC_(clo_workaround_gcc296_bugs) && just_below_esp)
njn5c004e42002-11-18 11:04:50 +0000501 return;
502
njn43c799e2003-04-08 00:08:52 +0000503 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000504 err_extra.axskind = isWrite ? WriteAxs : ReadAxs;
505 err_extra.size = size;
506 err_extra.addrinfo.akind = Undescribed;
507 err_extra.addrinfo.maybe_gcc = just_below_esp;
njn72718642003-07-24 08:45:32 +0000508 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000509}
510
511/* These ones are called from non-generated code */
512
513/* This is for memory errors in pthread functions, as opposed to pthread API
514 errors which are found by the core. */
nethercote8b76fe52004-11-08 19:20:09 +0000515void MAC_(record_core_mem_error) ( ThreadId tid, Bool isUnaddr, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000516{
njn43c799e2003-04-08 00:08:52 +0000517 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000518
njn43c799e2003-04-08 00:08:52 +0000519 MAC_(clear_MAC_Error)( &err_extra );
nethercote8b76fe52004-11-08 19:20:09 +0000520 err_extra.isUnaddr = isUnaddr;
njn72718642003-07-24 08:45:32 +0000521 VG_(maybe_record_error)( tid, CoreMemErr, /*addr*/0, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000522}
523
njn16390462005-05-08 15:26:00 +0000524// Three kinds of param errors:
525// - register arg contains undefined bytes
526// - memory arg is unaddressable
527// - memory arg contains undefined bytes
528// 'isReg' and 'isUnaddr' dictate which of these it is.
nethercote8b76fe52004-11-08 19:20:09 +0000529void MAC_(record_param_error) ( ThreadId tid, Addr a, Bool isReg,
530 Bool isUnaddr, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000531{
njn43c799e2003-04-08 00:08:52 +0000532 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000533
njnca82cc02004-11-22 17:18:48 +0000534 tl_assert(VG_INVALID_THREADID != tid);
njn16390462005-05-08 15:26:00 +0000535 if (isUnaddr) tl_assert(!isReg); // unaddressable register is impossible
njn43c799e2003-04-08 00:08:52 +0000536 MAC_(clear_MAC_Error)( &err_extra );
nethercote8b76fe52004-11-08 19:20:09 +0000537 err_extra.addrinfo.akind = ( isReg ? Register : Undescribed );
538 err_extra.isUnaddr = isUnaddr;
njn72718642003-07-24 08:45:32 +0000539 VG_(maybe_record_error)( tid, ParamErr, a, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000540}
541
njn72718642003-07-24 08:45:32 +0000542void MAC_(record_jump_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000543{
njn43c799e2003-04-08 00:08:52 +0000544 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000545
njnca82cc02004-11-22 17:18:48 +0000546 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000547 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000548 err_extra.axskind = ExecAxs;
nethercote7250b8f2004-04-13 08:47:35 +0000549 err_extra.size = 1; // size only used for suppressions
njn5c004e42002-11-18 11:04:50 +0000550 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000551 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000552}
553
njn72718642003-07-24 08:45:32 +0000554void MAC_(record_free_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000555{
njn43c799e2003-04-08 00:08:52 +0000556 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000557
njnca82cc02004-11-22 17:18:48 +0000558 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000559 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000560 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000561 VG_(maybe_record_error)( tid, FreeErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000562}
563
rjwalshbc0bb832004-06-19 18:12:36 +0000564void MAC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )
565{
566 MAC_Error err_extra;
567
njnca82cc02004-11-22 17:18:48 +0000568 tl_assert(VG_INVALID_THREADID != tid);
rjwalshbc0bb832004-06-19 18:12:36 +0000569 MAC_(clear_MAC_Error)( &err_extra );
570 err_extra.addrinfo.akind = Undescribed;
571 VG_(maybe_record_error)( tid, IllegalMempoolErr, a, /*s*/NULL, &err_extra );
572}
573
njn72718642003-07-24 08:45:32 +0000574void MAC_(record_freemismatch_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000575{
njn43c799e2003-04-08 00:08:52 +0000576 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000577
njnca82cc02004-11-22 17:18:48 +0000578 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000579 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000580 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000581 VG_(maybe_record_error)( tid, FreeMismatchErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000582}
583
sewardj2a99cf62004-11-24 10:44:19 +0000584void MAC_(record_overlap_error) ( ThreadId tid,
585 Char* function, OverlapExtra* ov_extra )
njn66fe05a2003-07-22 09:12:33 +0000586{
sewardj2a99cf62004-11-24 10:44:19 +0000587 VG_(maybe_record_error)(
588 tid, OverlapErr, /*addr*/0, /*s*/function, ov_extra );
njn66fe05a2003-07-22 09:12:33 +0000589}
590
591
njnb6cae9f2003-09-04 20:50:47 +0000592/* Updates the copy with address info if necessary (but not for all errors). */
njn51d827b2005-05-09 01:02:08 +0000593UInt MAC_(update_extra)( Error* err )
njn43c799e2003-04-08 00:08:52 +0000594{
njnb6cae9f2003-09-04 20:50:47 +0000595 switch (VG_(get_error_kind)(err)) {
596 case ValueErr:
597 case CoreMemErr:
598 case AddrErr:
599 case ParamErr:
600 case UserErr:
601 case FreeErr:
rjwalshbc0bb832004-06-19 18:12:36 +0000602 case IllegalMempoolErr:
njnb6cae9f2003-09-04 20:50:47 +0000603 case FreeMismatchErr: {
nethercote8b76fe52004-11-08 19:20:09 +0000604 MAC_Error* extra = VG_(get_error_extra)(err);
njnb6cae9f2003-09-04 20:50:47 +0000605 if (extra != NULL && Undescribed == extra->addrinfo.akind) {
606 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
607 }
608 return sizeof(MAC_Error);
609 }
njn43c799e2003-04-08 00:08:52 +0000610 /* Don't need to return the correct size -- LeakErrs are always shown with
611 VG_(unique_error)() so they're not copied anyway. */
njnb6cae9f2003-09-04 20:50:47 +0000612 case LeakErr: return 0;
613 case OverlapErr: return sizeof(OverlapExtra);
njn67993252004-11-22 18:02:32 +0000614 default: VG_(tool_panic)("update_extra: bad errkind");
njn43c799e2003-04-08 00:08:52 +0000615 }
njn43c799e2003-04-08 00:08:52 +0000616}
617
618
njn5c004e42002-11-18 11:04:50 +0000619/*------------------------------------------------------------*/
620/*--- Suppressions ---*/
621/*------------------------------------------------------------*/
622
njn43c799e2003-04-08 00:08:52 +0000623Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
624{
625 SuppKind skind;
626
627 if (VG_STREQ(name, "Param")) skind = ParamSupp;
628 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
629 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
630 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
631 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
632 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
njnc0616662003-06-12 09:58:41 +0000633 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
njn43c799e2003-04-08 00:08:52 +0000634 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
635 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
njne9cab142003-09-19 08:10:07 +0000636 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
rjwalshbc0bb832004-06-19 18:12:36 +0000637 else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
njn43c799e2003-04-08 00:08:52 +0000638 else
639 return False;
640
641 VG_(set_supp_kind)(su, skind);
642 return True;
643}
644
njn51d827b2005-05-09 01:02:08 +0000645Bool MAC_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
njn5c004e42002-11-18 11:04:50 +0000646{
647 Bool eof;
648
649 if (VG_(get_supp_kind)(su) == ParamSupp) {
650 eof = VG_(get_line) ( fd, buf, nBuf );
651 if (eof) return False;
652 VG_(set_supp_string)(su, VG_(strdup)(buf));
653 }
654 return True;
655}
656
njn51d827b2005-05-09 01:02:08 +0000657Bool MAC_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000658{
sewardj05bcdcb2003-05-18 10:05:38 +0000659 Int su_size;
njn43c799e2003-04-08 00:08:52 +0000660 MAC_Error* err_extra = VG_(get_error_extra)(err);
661 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000662
663 switch (VG_(get_supp_kind)(su)) {
664 case ParamSupp:
665 return (ekind == ParamErr
njn43c799e2003-04-08 00:08:52 +0000666 && VG_STREQ(VG_(get_error_string)(err),
667 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000668
669 case CoreMemSupp:
670 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000671 && VG_STREQ(VG_(get_error_string)(err),
672 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000673
674 case Value0Supp: su_size = 0; goto value_case;
675 case Value1Supp: su_size = 1; goto value_case;
676 case Value2Supp: su_size = 2; goto value_case;
677 case Value4Supp: su_size = 4; goto value_case;
678 case Value8Supp: su_size = 8; goto value_case;
njnc0616662003-06-12 09:58:41 +0000679 case Value16Supp:su_size =16; goto value_case;
njn5c004e42002-11-18 11:04:50 +0000680 value_case:
681 return (ekind == ValueErr && err_extra->size == su_size);
682
683 case Addr1Supp: su_size = 1; goto addr_case;
684 case Addr2Supp: su_size = 2; goto addr_case;
685 case Addr4Supp: su_size = 4; goto addr_case;
686 case Addr8Supp: su_size = 8; goto addr_case;
njnc0616662003-06-12 09:58:41 +0000687 case Addr16Supp:su_size =16; goto addr_case;
njn5c004e42002-11-18 11:04:50 +0000688 addr_case:
689 return (ekind == AddrErr && err_extra->size == su_size);
690
691 case FreeSupp:
692 return (ekind == FreeErr || ekind == FreeMismatchErr);
693
njn34419c12003-05-02 17:24:29 +0000694 case OverlapSupp:
695 return (ekind = OverlapErr);
696
sewardj4a19e2f2002-12-26 11:50:21 +0000697 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000698 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000699
rjwalshbc0bb832004-06-19 18:12:36 +0000700 case MempoolSupp:
701 return (ekind == IllegalMempoolErr);
702
njn5c004e42002-11-18 11:04:50 +0000703 default:
704 VG_(printf)("Error:\n"
705 " unknown suppression type %d\n",
706 VG_(get_supp_kind)(su));
njn67993252004-11-22 18:02:32 +0000707 VG_(tool_panic)("unknown suppression type in "
njn51d827b2005-05-09 01:02:08 +0000708 "MAC_(error_matches_suppression)");
njn5c004e42002-11-18 11:04:50 +0000709 }
710}
711
njn51d827b2005-05-09 01:02:08 +0000712Char* MAC_(get_error_name) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000713{
714 Char* s;
715 switch (VG_(get_error_kind)(err)) {
716 case ParamErr: return "Param";
717 case UserErr: return NULL; /* Can't suppress User errors */
718 case FreeMismatchErr: return "Free";
rjwalshbc0bb832004-06-19 18:12:36 +0000719 case IllegalMempoolErr: return "Mempool";
njn43c799e2003-04-08 00:08:52 +0000720 case FreeErr: return "Free";
721 case AddrErr:
722 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
723 case 1: return "Addr1";
724 case 2: return "Addr2";
725 case 4: return "Addr4";
726 case 8: return "Addr8";
njnc0616662003-06-12 09:58:41 +0000727 case 16: return "Addr16";
njn67993252004-11-22 18:02:32 +0000728 default: VG_(tool_panic)("unexpected size for Addr");
njn43c799e2003-04-08 00:08:52 +0000729 }
730
731 case ValueErr:
732 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
733 case 0: return "Cond";
734 case 1: return "Value1";
735 case 2: return "Value2";
736 case 4: return "Value4";
737 case 8: return "Value8";
njnc0616662003-06-12 09:58:41 +0000738 case 16: return "Value16";
njn67993252004-11-22 18:02:32 +0000739 default: VG_(tool_panic)("unexpected size for Value");
njn43c799e2003-04-08 00:08:52 +0000740 }
741 case CoreMemErr: return "CoreMem";
njn34419c12003-05-02 17:24:29 +0000742 case OverlapErr: return "Overlap";
njn43c799e2003-04-08 00:08:52 +0000743 case LeakErr: return "Leak";
njn67993252004-11-22 18:02:32 +0000744 default: VG_(tool_panic)("get_error_name: unexpected type");
njn43c799e2003-04-08 00:08:52 +0000745 }
746 VG_(printf)(s);
747}
748
njn51d827b2005-05-09 01:02:08 +0000749void MAC_(print_extra_suppression_info) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000750{
751 if (ParamErr == VG_(get_error_kind)(err)) {
752 VG_(printf)(" %s\n", VG_(get_error_string)(err));
753 }
754}
njn5c004e42002-11-18 11:04:50 +0000755
756/*------------------------------------------------------------*/
757/*--- Crude profiling machinery. ---*/
758/*------------------------------------------------------------*/
759
760/* Event index. If just the name of the fn is given, this means the
761 number of calls to the fn. Otherwise it is the specified event.
762 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
763 The rest are shared.
764
765 10 alloc_secondary_map
766
767 20 get_abit
768M 21 get_vbyte
769 22 set_abit
770M 23 set_vbyte
771 24 get_abits4_ALIGNED
772M 25 get_vbytes4_ALIGNED
773
774 30 set_address_range_perms
775 31 set_address_range_perms(lower byte loop)
776 32 set_address_range_perms(quadword loop)
777 33 set_address_range_perms(upper byte loop)
778
779 35 make_noaccess
780 36 make_writable
781 37 make_readable
782A 38 make_accessible
783
784 40 copy_address_range_state
785 41 copy_address_range_state(byte loop)
786 42 check_writable
787 43 check_writable(byte loop)
788 44 check_readable
789 45 check_readable(byte loop)
790 46 check_readable_asciiz
791 47 check_readable_asciiz(byte loop)
792A 48 check_accessible
793A 49 check_accessible(byte loop)
794
795 50 make_noaccess_aligned
796 51 make_writable_aligned
797
798M 60 helperc_LOADV4
799M 61 helperc_STOREV4
800M 62 helperc_LOADV2
801M 63 helperc_STOREV2
802M 64 helperc_LOADV1
803M 65 helperc_STOREV1
804
805A 66 helperc_ACCESS4
806A 67 helperc_ACCESS2
807A 68 helperc_ACCESS1
808
809M 70 rim_rd_V4_SLOWLY
810M 71 rim_wr_V4_SLOWLY
811M 72 rim_rd_V2_SLOWLY
812M 73 rim_wr_V2_SLOWLY
813M 74 rim_rd_V1_SLOWLY
814M 75 rim_wr_V1_SLOWLY
815
816A 76 ACCESS4_SLOWLY
817A 77 ACCESS2_SLOWLY
818A 78 ACCESS1_SLOWLY
819
820 80 fpu_read
821 81 fpu_read aligned 4
822 82 fpu_read aligned 8
823 83 fpu_read 2
jsewardfca60182004-01-04 23:30:55 +0000824 84 fpu_read 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000825
826M 85 fpu_write
827M 86 fpu_write aligned 4
828M 87 fpu_write aligned 8
829M 88 fpu_write 2
jsewardfca60182004-01-04 23:30:55 +0000830M 89 fpu_write 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000831
832 90 fpu_access
833 91 fpu_access aligned 4
834 92 fpu_access aligned 8
835 93 fpu_access 2
jsewardfca60182004-01-04 23:30:55 +0000836 94 fpu_access 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000837
838 100 fpu_access_check_SLOWLY
839 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000840
841 110 new_mem_stack_4
842 111 new_mem_stack_8
843 112 new_mem_stack_12
844 113 new_mem_stack_16
845 114 new_mem_stack_32
846 115 new_mem_stack
847
848 120 die_mem_stack_4
849 121 die_mem_stack_8
850 122 die_mem_stack_12
851 123 die_mem_stack_16
852 124 die_mem_stack_32
853 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000854*/
855
njn43c799e2003-04-08 00:08:52 +0000856#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000857
sewardjc1a2cda2005-04-21 17:34:00 +0000858UInt MAC_(event_ctr)[N_PROF_EVENTS];
859HChar* MAC_(event_ctr_name)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000860
njnb4aee052003-04-15 14:09:58 +0000861static void init_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000862{
863 Int i;
sewardjc1a2cda2005-04-21 17:34:00 +0000864 for (i = 0; i < N_PROF_EVENTS; i++) {
njn43c799e2003-04-08 00:08:52 +0000865 MAC_(event_ctr)[i] = 0;
sewardjc1a2cda2005-04-21 17:34:00 +0000866 MAC_(event_ctr_name)[i] = NULL;
867 }
njn5c004e42002-11-18 11:04:50 +0000868}
869
njnb4aee052003-04-15 14:09:58 +0000870static void done_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000871{
sewardjc1a2cda2005-04-21 17:34:00 +0000872 Int i;
873 Bool spaced = False;
njn5c004e42002-11-18 11:04:50 +0000874 for (i = 0; i < N_PROF_EVENTS; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +0000875 if (!spaced && (i % 10) == 0) {
njn5c004e42002-11-18 11:04:50 +0000876 VG_(printf)("\n");
sewardjc1a2cda2005-04-21 17:34:00 +0000877 spaced = True;
878 }
879 if (MAC_(event_ctr)[i] > 0) {
880 spaced = False;
881 VG_(printf)( "prof mem event %3d: %9d %s\n",
882 i, MAC_(event_ctr)[i],
883 MAC_(event_ctr_name)[i]
884 ? MAC_(event_ctr_name)[i] : "unnamed");
885 }
njn5c004e42002-11-18 11:04:50 +0000886 }
njn5c004e42002-11-18 11:04:50 +0000887}
888
889#else
890
njnb4aee052003-04-15 14:09:58 +0000891static void init_prof_mem ( void ) { }
892static void done_prof_mem ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000893
njn5c004e42002-11-18 11:04:50 +0000894#endif
895
896/*------------------------------------------------------------*/
njn3e884182003-04-15 13:03:23 +0000897/*--- Common initialisation + finalisation ---*/
898/*------------------------------------------------------------*/
899
900void MAC_(common_pre_clo_init)(void)
901{
902 MAC_(malloc_list) = VG_(HT_construct)();
rjwalshbc0bb832004-06-19 18:12:36 +0000903 MAC_(mempool_list) = VG_(HT_construct)();
njn3e884182003-04-15 13:03:23 +0000904 init_prof_mem();
905}
906
njnb8dca862005-03-14 02:42:44 +0000907void MAC_(common_fini)(void (*leak_check)(ThreadId tid, LeakCheckMode mode))
njn3e884182003-04-15 13:03:23 +0000908{
njn86f12dc2005-03-14 01:16:05 +0000909 MAC_(print_malloc_stats)();
njn3e884182003-04-15 13:03:23 +0000910
sewardj71bc3cb2005-05-19 00:25:45 +0000911 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
sewardjb5f6f512005-03-10 23:59:00 +0000912 if (MAC_(clo_leak_check) == LC_Off)
njn3e884182003-04-15 13:03:23 +0000913 VG_(message)(Vg_UserMsg,
914 "For a detailed leak analysis, rerun with: --leak-check=yes");
915
916 VG_(message)(Vg_UserMsg,
917 "For counts of detected errors, rerun with: -v");
918 }
sewardjb5f6f512005-03-10 23:59:00 +0000919 if (MAC_(clo_leak_check) != LC_Off)
njnb8dca862005-03-14 02:42:44 +0000920 leak_check(1/*bogus ThreadId*/, MAC_(clo_leak_check));
njn3e884182003-04-15 13:03:23 +0000921
922 done_prof_mem();
923}
924
925/*------------------------------------------------------------*/
njn47363ab2003-04-21 13:24:40 +0000926/*--- Common client request handling ---*/
927/*------------------------------------------------------------*/
928
nethercoted1b64b22004-11-04 18:22:28 +0000929Bool MAC_(handle_common_client_requests)(ThreadId tid, UWord* arg, UWord* ret )
njn47363ab2003-04-21 13:24:40 +0000930{
njnd7994182003-10-02 13:44:04 +0000931 Char* err =
932 "The client requests VALGRIND_MALLOCLIKE_BLOCK and\n"
933 " VALGRIND_FREELIKE_BLOCK have moved. Please recompile your\n"
934 " program to incorporate the updates in the Valgrind header files.\n"
935 " You shouldn't need to change the text of your program at all.\n"
936 " Everything should then work as before. Sorry for the bother.\n";
njn47363ab2003-04-21 13:24:40 +0000937
938 switch (arg[0]) {
njn10785452003-05-20 16:38:24 +0000939 case VG_USERREQ__COUNT_LEAKS: { /* count leaked bytes */
nethercoted1b64b22004-11-04 18:22:28 +0000940 UWord** argp = (UWord**)arg;
njne8b5c052003-07-22 22:03:58 +0000941 // MAC_(bytes_leaked) et al were set by the last leak check (or zero
942 // if no prior leak checks performed).
sewardjb5f6f512005-03-10 23:59:00 +0000943 *argp[1] = MAC_(bytes_leaked) + MAC_(bytes_indirect);
njne8b5c052003-07-22 22:03:58 +0000944 *argp[2] = MAC_(bytes_dubious);
945 *argp[3] = MAC_(bytes_reachable);
946 *argp[4] = MAC_(bytes_suppressed);
sewardjb5f6f512005-03-10 23:59:00 +0000947 // there is no argp[5]
948 //*argp[5] = MAC_(bytes_indirect);
949 // XXX need to make *argp[1-4] readable
njn47363ab2003-04-21 13:24:40 +0000950 *ret = 0;
951 return True;
njn10785452003-05-20 16:38:24 +0000952 }
njnd7994182003-10-02 13:44:04 +0000953 case VG_USERREQ__MALLOCLIKE_BLOCK__OLD_DO_NOT_USE:
954 case VG_USERREQ__FREELIKE_BLOCK__OLD_DO_NOT_USE:
njn67993252004-11-22 18:02:32 +0000955 VG_(tool_panic)(err);
njnd7994182003-10-02 13:44:04 +0000956
njn10785452003-05-20 16:38:24 +0000957 case VG_USERREQ__MALLOCLIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000958 Addr p = (Addr)arg[1];
nethercote928a5f72004-11-03 18:10:37 +0000959 SizeT sizeB = arg[2];
njnd7994182003-10-02 13:44:04 +0000960 UInt rzB = arg[3];
961 Bool is_zeroed = (Bool)arg[4];
njn47363ab2003-04-21 13:24:40 +0000962
sewardj2a99cf62004-11-24 10:44:19 +0000963 MAC_(new_block) ( tid, p, sizeB, /*ignored*/0, rzB, is_zeroed,
nethercote57e36b32004-07-10 14:56:28 +0000964 MAC_AllocCustom, MAC_(malloc_list) );
njn10785452003-05-20 16:38:24 +0000965 return True;
966 }
967 case VG_USERREQ__FREELIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000968 Addr p = (Addr)arg[1];
969 UInt rzB = arg[2];
njn10785452003-05-20 16:38:24 +0000970
sewardj2a99cf62004-11-24 10:44:19 +0000971 MAC_(handle_free) ( tid, p, rzB, MAC_AllocCustom );
njn10785452003-05-20 16:38:24 +0000972 return True;
973 }
njnd7994182003-10-02 13:44:04 +0000974
njn1f8b3e72005-03-22 04:27:14 +0000975 case _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR: {
976 Char* s = (Char*) arg[1];
977 OverlapExtra* extra = (OverlapExtra*)arg[2];
978 MAC_(record_overlap_error)(tid, s, extra);
nethercotee3a53722004-05-05 10:46:22 +0000979 return True;
njn1f8b3e72005-03-22 04:27:14 +0000980 }
nethercotee3a53722004-05-05 10:46:22 +0000981
rjwalshbc0bb832004-06-19 18:12:36 +0000982 case VG_USERREQ__CREATE_MEMPOOL: {
983 Addr pool = (Addr)arg[1];
984 UInt rzB = arg[2];
985 Bool is_zeroed = (Bool)arg[3];
986
987 MAC_(create_mempool) ( pool, rzB, is_zeroed );
988 return True;
989 }
990
991 case VG_USERREQ__DESTROY_MEMPOOL: {
992 Addr pool = (Addr)arg[1];
993
994 MAC_(destroy_mempool) ( pool );
995 return True;
996 }
997
998 case VG_USERREQ__MEMPOOL_ALLOC: {
999 Addr pool = (Addr)arg[1];
1000 Addr addr = (Addr)arg[2];
1001 UInt size = arg[3];
1002
sewardj2a99cf62004-11-24 10:44:19 +00001003 MAC_(mempool_alloc) ( tid, pool, addr, size );
rjwalshbc0bb832004-06-19 18:12:36 +00001004 return True;
1005 }
1006
1007 case VG_USERREQ__MEMPOOL_FREE: {
1008 Addr pool = (Addr)arg[1];
1009 Addr addr = (Addr)arg[2];
1010
1011 MAC_(mempool_free) ( pool, addr );
1012 return True;
1013 }
1014
njn47363ab2003-04-21 13:24:40 +00001015 default:
1016 return False;
1017 }
1018}
1019
njn5c004e42002-11-18 11:04:50 +00001020/*--------------------------------------------------------------------*/
njn00cae242005-05-09 01:13:44 +00001021/*--- end ---*/
njn5c004e42002-11-18 11:04:50 +00001022/*--------------------------------------------------------------------*/