blob: ebd698c994541e49f19cba6ef7df2293d62d823b [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
njn43c799e2003-04-08 00:08:52 +000033#include "mac_shared.h"
njn132bfcc2005-06-04 19:16:06 +000034#include "pub_tool_libcassert.h"
njn97405b22005-06-02 03:39:33 +000035#include "pub_tool_libcbase.h"
njn36a20fa2005-06-03 03:08:39 +000036#include "pub_tool_libcprint.h"
njnf536bbb2005-06-13 04:21:38 +000037#include "pub_tool_machine.h"
njn47363ab2003-04-21 13:24:40 +000038#include "memcheck.h" /* for VG_USERREQ__* */
39
njn5c004e42002-11-18 11:04:50 +000040/*------------------------------------------------------------*/
41/*--- Defns ---*/
42/*------------------------------------------------------------*/
43
44/* These many bytes below %ESP are considered addressible if we're
45 doing the --workaround-gcc296-bugs hack. */
46#define VG_GCC296_BUG_STACK_SLOP 1024
47
48/*------------------------------------------------------------*/
49/*--- Command line options ---*/
50/*------------------------------------------------------------*/
51
sewardjb5f6f512005-03-10 23:59:00 +000052Bool MAC_(clo_partial_loads_ok) = True;
53Int MAC_(clo_freelist_vol) = 1000000;
njn6a329422005-03-12 20:38:13 +000054LeakCheckMode MAC_(clo_leak_check) = LC_Summary;
sewardjb5f6f512005-03-10 23:59:00 +000055VgRes MAC_(clo_leak_resolution) = Vg_LowRes;
56Bool MAC_(clo_show_reachable) = False;
57Bool MAC_(clo_workaround_gcc296_bugs) = False;
njn5c004e42002-11-18 11:04:50 +000058
njn43c799e2003-04-08 00:08:52 +000059Bool MAC_(process_common_cmd_line_option)(Char* arg)
njn5c004e42002-11-18 11:04:50 +000060{
njn45270a22005-03-27 01:00:11 +000061 VG_BOOL_CLO(arg, "--partial-loads-ok", MAC_(clo_partial_loads_ok))
62 else VG_BOOL_CLO(arg, "--show-reachable", MAC_(clo_show_reachable))
63 else VG_BOOL_CLO(arg, "--workaround-gcc296-bugs",MAC_(clo_workaround_gcc296_bugs))
nethercote27fec902004-06-16 21:26:32 +000064
njn45270a22005-03-27 01:00:11 +000065 else VG_BNUM_CLO(arg, "--freelist-vol", MAC_(clo_freelist_vol), 0, 1000000000)
nethercote27fec902004-06-16 21:26:32 +000066
sewardjb5f6f512005-03-10 23:59:00 +000067 else if (VG_CLO_STREQ(arg, "--leak-check=no"))
68 MAC_(clo_leak_check) = LC_Off;
69 else if (VG_CLO_STREQ(arg, "--leak-check=summary"))
70 MAC_(clo_leak_check) = LC_Summary;
71 else if (VG_CLO_STREQ(arg, "--leak-check=yes") ||
72 VG_CLO_STREQ(arg, "--leak-check=full"))
73 MAC_(clo_leak_check) = LC_Full;
74
njn43c799e2003-04-08 00:08:52 +000075 else if (VG_CLO_STREQ(arg, "--leak-resolution=low"))
76 MAC_(clo_leak_resolution) = Vg_LowRes;
77 else if (VG_CLO_STREQ(arg, "--leak-resolution=med"))
78 MAC_(clo_leak_resolution) = Vg_MedRes;
79 else if (VG_CLO_STREQ(arg, "--leak-resolution=high"))
80 MAC_(clo_leak_resolution) = Vg_HighRes;
njn5c004e42002-11-18 11:04:50 +000081
82 else
njn3e884182003-04-15 13:03:23 +000083 return VG_(replacement_malloc_process_cmd_line_option)(arg);
njn5c004e42002-11-18 11:04:50 +000084
85 return True;
njn43c799e2003-04-08 00:08:52 +000086}
njn5c004e42002-11-18 11:04:50 +000087
njn3e884182003-04-15 13:03:23 +000088void MAC_(print_common_usage)(void)
njn43c799e2003-04-08 00:08:52 +000089{
njn3e884182003-04-15 13:03:23 +000090 VG_(printf)(
sewardjb5f6f512005-03-10 23:59:00 +000091" --partial-loads-ok=no|yes too hard to explain here; see manual [yes]\n"
92" --freelist-vol=<number> volume of freed blocks queue [1000000]\n"
njn6a329422005-03-12 20:38:13 +000093" --leak-check=no|summary|full search for memory leaks at exit? [summary]\n"
sewardjb5f6f512005-03-10 23:59:00 +000094" --leak-resolution=low|med|high how much bt merging in leak check [low]\n"
95" --show-reachable=no|yes show reachable blocks in leak check? [no]\n"
njn3e884182003-04-15 13:03:23 +000096" --workaround-gcc296-bugs=no|yes self explanatory [no]\n"
97 );
98 VG_(replacement_malloc_print_usage)();
njn43c799e2003-04-08 00:08:52 +000099}
100
njn3e884182003-04-15 13:03:23 +0000101void MAC_(print_common_debug_usage)(void)
njn43c799e2003-04-08 00:08:52 +0000102{
njn3e884182003-04-15 13:03:23 +0000103 VG_(replacement_malloc_print_debug_usage)();
njn5c004e42002-11-18 11:04:50 +0000104}
105
106/*------------------------------------------------------------*/
107/*--- Comparing and printing errors ---*/
108/*------------------------------------------------------------*/
109
110static __inline__
111void clear_AddrInfo ( AddrInfo* ai )
112{
113 ai->akind = Unknown;
114 ai->blksize = 0;
115 ai->rwoffset = 0;
116 ai->lastchange = NULL;
117 ai->stack_tid = VG_INVALID_THREADID;
118 ai->maybe_gcc = False;
sewardjb5f6f512005-03-10 23:59:00 +0000119 ai->desc = NULL;
njn5c004e42002-11-18 11:04:50 +0000120}
121
njn43c799e2003-04-08 00:08:52 +0000122void MAC_(clear_MAC_Error) ( MAC_Error* err_extra )
njn5c004e42002-11-18 11:04:50 +0000123{
124 err_extra->axskind = ReadAxs;
125 err_extra->size = 0;
126 clear_AddrInfo ( &err_extra->addrinfo );
nethercote8b76fe52004-11-08 19:20:09 +0000127 err_extra->isUnaddr = True;
njn5c004e42002-11-18 11:04:50 +0000128}
129
130__attribute__ ((unused))
131static Bool eq_AddrInfo ( VgRes res, AddrInfo* ai1, AddrInfo* ai2 )
132{
133 if (ai1->akind != Undescribed
134 && ai2->akind != Undescribed
135 && ai1->akind != ai2->akind)
136 return False;
137 if (ai1->akind == Freed || ai1->akind == Mallocd) {
138 if (ai1->blksize != ai2->blksize)
139 return False;
140 if (!VG_(eq_ExeContext)(res, ai1->lastchange, ai2->lastchange))
141 return False;
142 }
143 return True;
144}
145
146/* Compare error contexts, to detect duplicates. Note that if they
147 are otherwise the same, the faulting addrs and associated rwoffsets
148 are allowed to be different. */
149
njn51d827b2005-05-09 01:02:08 +0000150Bool MAC_(eq_Error) ( VgRes res, Error* e1, Error* e2 )
njn5c004e42002-11-18 11:04:50 +0000151{
njn43c799e2003-04-08 00:08:52 +0000152 MAC_Error* e1_extra = VG_(get_error_extra)(e1);
153 MAC_Error* e2_extra = VG_(get_error_extra)(e2);
njn7cc53a82002-11-19 16:19:32 +0000154
155 /* Guaranteed by calling function */
njnca82cc02004-11-22 17:18:48 +0000156 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
njn5c004e42002-11-18 11:04:50 +0000157
158 switch (VG_(get_error_kind)(e1)) {
159 case CoreMemErr: {
160 Char *e1s, *e2s;
nethercote8b76fe52004-11-08 19:20:09 +0000161 if (e1_extra->isUnaddr != e2_extra->isUnaddr) return False;
njn5c004e42002-11-18 11:04:50 +0000162 e1s = VG_(get_error_string)(e1);
163 e2s = VG_(get_error_string)(e2);
164 if (e1s == e2s) return True;
165 if (0 == VG_(strcmp)(e1s, e2s)) return True;
166 return False;
167 }
168
njn16390462005-05-08 15:26:00 +0000169 // Perhaps we should also check the addrinfo.akinds for equality.
170 // That would result in more error reports, but only in cases where
171 // a register contains uninitialised bytes and points to memory
172 // containing uninitialised bytes. Currently, the 2nd of those to be
173 // detected won't be reported. That is (nearly?) always the memory
174 // error, which is good.
njn5c004e42002-11-18 11:04:50 +0000175 case ParamErr:
njn16390462005-05-08 15:26:00 +0000176 if (0 != VG_(strcmp)(VG_(get_error_string)(e1),
177 VG_(get_error_string)(e2))) return False;
178 // fall through
179 case UserErr:
180 if (e1_extra->isUnaddr != e2_extra->isUnaddr) return False;
njn5c004e42002-11-18 11:04:50 +0000181 return True;
182
183 case FreeErr:
184 case FreeMismatchErr:
185 /* JRS 2002-Aug-26: comparing addrs seems overkill and can
186 cause excessive duplication of errors. Not even AddrErr
187 below does that. So don't compare either the .addr field
188 or the .addrinfo fields. */
189 /* if (e1->addr != e2->addr) return False; */
190 /* if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
191 return False;
192 */
193 return True;
194
195 case AddrErr:
196 /* if (e1_extra->axskind != e2_extra->axskind) return False; */
197 if (e1_extra->size != e2_extra->size) return False;
198 /*
199 if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
200 return False;
201 */
202 return True;
203
204 case ValueErr:
205 if (e1_extra->size != e2_extra->size) return False;
206 return True;
207
njn34419c12003-05-02 17:24:29 +0000208 case OverlapErr:
209 return True;
210
njn43c799e2003-04-08 00:08:52 +0000211 case LeakErr:
njn51d827b2005-05-09 01:02:08 +0000212 VG_(tool_panic)("Shouldn't get LeakErr in MAC_(eq_Error),\n"
njn43c799e2003-04-08 00:08:52 +0000213 "since it's handled with VG_(unique_error)()!");
214
rjwalshbc0bb832004-06-19 18:12:36 +0000215 case IllegalMempoolErr:
216 return True;
217
njn5c004e42002-11-18 11:04:50 +0000218 default:
219 VG_(printf)("Error:\n unknown error code %d\n",
220 VG_(get_error_kind)(e1));
njn51d827b2005-05-09 01:02:08 +0000221 VG_(tool_panic)("unknown error code in MAC_(eq_Error)");
njn5c004e42002-11-18 11:04:50 +0000222 }
223}
224
njn43c799e2003-04-08 00:08:52 +0000225void MAC_(pp_AddrInfo) ( Addr a, AddrInfo* ai )
njn5c004e42002-11-18 11:04:50 +0000226{
sewardj71bc3cb2005-05-19 00:25:45 +0000227 HChar* xpre = VG_(clo_xml) ? " <auxwhat>" : " ";
228 HChar* xpost = VG_(clo_xml) ? "</auxwhat>" : "";
229
njn5c004e42002-11-18 11:04:50 +0000230 switch (ai->akind) {
231 case Stack:
232 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000233 "%sAddress 0x%llx is on thread %d's stack%s",
234 xpre, (ULong)a, ai->stack_tid, xpost);
njn5c004e42002-11-18 11:04:50 +0000235 break;
236 case Unknown:
237 if (ai->maybe_gcc) {
238 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000239 "%sAddress 0x%llx is just below the stack ptr. "
240 "To suppress, use: --workaround-gcc296-bugs=yes%s",
241 xpre, (ULong)a, xpost
242 );
njn5c004e42002-11-18 11:04:50 +0000243 } else {
244 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000245 "%sAddress 0x%llx "
246 "is not stack'd, malloc'd or (recently) free'd%s",
247 xpre, (ULong)a, xpost);
njn5c004e42002-11-18 11:04:50 +0000248 }
249 break;
rjwalshbc0bb832004-06-19 18:12:36 +0000250 case Freed: case Mallocd: case UserG: case Mempool: {
nethercote50397c22004-11-04 18:03:06 +0000251 SizeT delta;
sewardjb5f6f512005-03-10 23:59:00 +0000252 const Char* relative;
253 const Char* kind;
rjwalshbc0bb832004-06-19 18:12:36 +0000254 if (ai->akind == Mempool) {
255 kind = "mempool";
256 } else {
257 kind = "block";
258 }
sewardjb5f6f512005-03-10 23:59:00 +0000259 if (ai->desc != NULL)
260 kind = ai->desc;
261
njn5c004e42002-11-18 11:04:50 +0000262 if (ai->rwoffset < 0) {
nethercote50397c22004-11-04 18:03:06 +0000263 delta = (SizeT)(- ai->rwoffset);
njn5c004e42002-11-18 11:04:50 +0000264 relative = "before";
265 } else if (ai->rwoffset >= ai->blksize) {
266 delta = ai->rwoffset - ai->blksize;
267 relative = "after";
268 } else {
269 delta = ai->rwoffset;
270 relative = "inside";
271 }
sewardja81709d2002-12-28 12:55:48 +0000272 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000273 "%sAddress 0x%llx is %llu bytes %s a %s of size %d %s%s",
274 xpre,
tom14ea6852005-05-03 18:16:12 +0000275 (ULong)a, (ULong)delta, relative, kind,
sewardja81709d2002-12-28 12:55:48 +0000276 ai->blksize,
277 ai->akind==Mallocd ? "alloc'd"
278 : ai->akind==Freed ? "free'd"
sewardj71bc3cb2005-05-19 00:25:45 +0000279 : "client-defined",
280 xpost);
njn5c004e42002-11-18 11:04:50 +0000281 VG_(pp_ExeContext)(ai->lastchange);
282 break;
283 }
nethercote8b76fe52004-11-08 19:20:09 +0000284 case Register:
285 // print nothing
njnca82cc02004-11-22 17:18:48 +0000286 tl_assert(0 == a);
nethercote8b76fe52004-11-08 19:20:09 +0000287 break;
njn5c004e42002-11-18 11:04:50 +0000288 default:
njn67993252004-11-22 18:02:32 +0000289 VG_(tool_panic)("MAC_(pp_AddrInfo)");
njn43c799e2003-04-08 00:08:52 +0000290 }
291}
292
293/* This prints out the message for the error types where Memcheck and
294 Addrcheck have identical messages */
njnb126f732004-11-22 17:57:07 +0000295void MAC_(pp_shared_Error) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000296{
297 MAC_Error* err_extra = VG_(get_error_extra)(err);
298
sewardj71bc3cb2005-05-19 00:25:45 +0000299 HChar* xpre = VG_(clo_xml) ? " <what>" : "";
300 HChar* xpost = VG_(clo_xml) ? "</what>" : "";
301
njn43c799e2003-04-08 00:08:52 +0000302 switch (VG_(get_error_kind)(err)) {
303 case FreeErr:
sewardj71bc3cb2005-05-19 00:25:45 +0000304 if (VG_(clo_xml))
305 VG_(message)(Vg_UserMsg, " <kind>InvalidFree</kind>");
306 VG_(message)(Vg_UserMsg,
307 "%sInvalid free() / delete / delete[]%s",
308 xpre, xpost);
309 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
310 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
311 break;
312
njn43c799e2003-04-08 00:08:52 +0000313 case FreeMismatchErr:
sewardj71bc3cb2005-05-19 00:25:45 +0000314 if (VG_(clo_xml))
315 VG_(message)(Vg_UserMsg, " <kind>MismatchedFree</kind>");
316 VG_(message)(Vg_UserMsg,
317 "%sMismatched free() / delete / delete []%s",
318 xpre, xpost);
njn43c799e2003-04-08 00:08:52 +0000319 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
320 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
321 break;
322
njn89409f82003-09-26 14:55:31 +0000323 case AddrErr:
324 switch (err_extra->axskind) {
325 case ReadAxs:
sewardj71bc3cb2005-05-19 00:25:45 +0000326 if (VG_(clo_xml))
327 VG_(message)(Vg_UserMsg, " <kind>InvalidRead</kind>");
328 VG_(message)(Vg_UserMsg,
329 "%sInvalid read of size %d%s",
330 xpre, err_extra->size, xpost );
njn89409f82003-09-26 14:55:31 +0000331 break;
332 case WriteAxs:
sewardj71bc3cb2005-05-19 00:25:45 +0000333 if (VG_(clo_xml))
334 VG_(message)(Vg_UserMsg, " <kind>InvalidWrite</kind>");
335 VG_(message)(Vg_UserMsg,
336 "%sInvalid write of size %d%s",
337 xpre, err_extra->size, xpost );
njn89409f82003-09-26 14:55:31 +0000338 break;
339 case ExecAxs:
sewardj71bc3cb2005-05-19 00:25:45 +0000340 if (VG_(clo_xml))
341 VG_(message)(Vg_UserMsg, " <kind>InvalidJump</kind>");
342 VG_(message)(Vg_UserMsg,
343 "%sJump to the invalid address "
344 "stated on the next line%s",
345 xpre, xpost);
njn89409f82003-09-26 14:55:31 +0000346 break;
347 default:
njn51d827b2005-05-09 01:02:08 +0000348 VG_(tool_panic)("MAC_(pp_shared_Error)(axskind)");
njn89409f82003-09-26 14:55:31 +0000349 }
350 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
351 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
352 break;
353
njnb6cae9f2003-09-04 20:50:47 +0000354 case OverlapErr: {
355 OverlapExtra* ov_extra = (OverlapExtra*)VG_(get_error_extra)(err);
sewardj71bc3cb2005-05-19 00:25:45 +0000356 if (VG_(clo_xml))
357 VG_(message)(Vg_UserMsg, " <kind>Overlap</kind>");
njnb6cae9f2003-09-04 20:50:47 +0000358 if (ov_extra->len == -1)
359 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000360 "%sSource and destination overlap in %s(%p, %p)%s",
361 xpre,
njnb6cae9f2003-09-04 20:50:47 +0000362 VG_(get_error_string)(err),
sewardj71bc3cb2005-05-19 00:25:45 +0000363 ov_extra->dst, ov_extra->src,
364 xpost);
njnb6cae9f2003-09-04 20:50:47 +0000365 else
366 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000367 "%sSource and destination overlap in %s(%p, %p, %d)%s",
368 xpre,
njnb6cae9f2003-09-04 20:50:47 +0000369 VG_(get_error_string)(err),
sewardj71bc3cb2005-05-19 00:25:45 +0000370 ov_extra->dst, ov_extra->src, ov_extra->len,
371 xpost);
njn66fe05a2003-07-22 09:12:33 +0000372 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
373 break;
njnb6cae9f2003-09-04 20:50:47 +0000374 }
njn43c799e2003-04-08 00:08:52 +0000375 case LeakErr: {
njn02977032005-05-17 04:00:11 +0000376 MAC_(pp_LeakError)(err_extra);
njn43c799e2003-04-08 00:08:52 +0000377 break;
378 }
379
rjwalshbc0bb832004-06-19 18:12:36 +0000380 case IllegalMempoolErr:
sewardj71bc3cb2005-05-19 00:25:45 +0000381 if (VG_(clo_xml))
382 VG_(message)(Vg_UserMsg, " <kind>InvalidMemPool</kind>");
383 VG_(message)(Vg_UserMsg, "%sIllegal memory pool address%s",
384 xpre, xpost);
rjwalshbc0bb832004-06-19 18:12:36 +0000385 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
386 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
387 break;
388
njn43c799e2003-04-08 00:08:52 +0000389 default:
390 VG_(printf)("Error:\n unknown Memcheck/Addrcheck error code %d\n",
391 VG_(get_error_kind)(err));
njn67993252004-11-22 18:02:32 +0000392 VG_(tool_panic)("unknown error code in MAC_(pp_shared_Error)");
njn5c004e42002-11-18 11:04:50 +0000393 }
394}
395
396/*------------------------------------------------------------*/
397/*--- Recording errors ---*/
398/*------------------------------------------------------------*/
399
njn43c799e2003-04-08 00:08:52 +0000400/* Additional description function for describe_addr(); used by
401 MemCheck for user blocks, which Addrcheck doesn't support. */
402Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL;
thughes4ad52d02004-06-27 17:37:21 +0000403
404/* Callback for searching thread stacks */
405static Bool addr_is_in_bounds(Addr stack_min, Addr stack_max, void *ap)
406{
407 Addr a = *(Addr *)ap;
408
409 return (stack_min <= a && a <= stack_max);
410}
411
412/* Callback for searching free'd list */
413static Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc, void *ap)
414{
415 Addr a = *(Addr *)ap;
416
njn717cde52005-05-10 02:47:21 +0000417 return VG_(addr_is_in_block)( a, mc->data, mc->size,
418 MAC_MALLOC_REDZONE_SZB );
thughes4ad52d02004-06-27 17:37:21 +0000419}
420
421/* Callback for searching malloc'd lists */
422static Bool addr_is_in_HashNode(VgHashNode* sh_ch, void *ap)
423{
424 return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch, ap );
425}
426
njn43c799e2003-04-08 00:08:52 +0000427/* Describe an address as best you can, for error messages,
428 putting the result in ai. */
429static void describe_addr ( Addr a, AddrInfo* ai )
430{
njn3e884182003-04-15 13:03:23 +0000431 MAC_Chunk* sc;
432 ThreadId tid;
njn43c799e2003-04-08 00:08:52 +0000433
njn43c799e2003-04-08 00:08:52 +0000434 /* Perhaps it's a user-def'd block ? (only check if requested, though) */
435 if (NULL != MAC_(describe_addr_supp)) {
436 if (MAC_(describe_addr_supp)( a, ai ))
437 return;
438 }
439 /* Perhaps it's on a thread's stack? */
thughes4ad52d02004-06-27 17:37:21 +0000440 tid = VG_(first_matching_thread_stack)(addr_is_in_bounds, &a);
njn43c799e2003-04-08 00:08:52 +0000441 if (tid != VG_INVALID_THREADID) {
442 ai->akind = Stack;
443 ai->stack_tid = tid;
444 return;
445 }
446 /* Search for a recently freed block which might bracket it. */
thughes4ad52d02004-06-27 17:37:21 +0000447 sc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk, &a);
njn3e884182003-04-15 13:03:23 +0000448 if (NULL != sc) {
njn43c799e2003-04-08 00:08:52 +0000449 ai->akind = Freed;
njn3e884182003-04-15 13:03:23 +0000450 ai->blksize = sc->size;
451 ai->rwoffset = (Int)a - (Int)sc->data;
452 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000453 return;
454 }
455 /* Search for a currently malloc'd block which might bracket it. */
thughes4ad52d02004-06-27 17:37:21 +0000456 sc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode, &a);
njn43c799e2003-04-08 00:08:52 +0000457 if (NULL != sc) {
458 ai->akind = Mallocd;
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 /* Clueless ... */
465 ai->akind = Unknown;
466 return;
467}
468
njn5c004e42002-11-18 11:04:50 +0000469/* Is this address within some small distance below %ESP? Used only
470 for the --workaround-gcc296-bugs kludge. */
471static Bool is_just_below_ESP( Addr esp, Addr aa )
472{
nethercote50397c22004-11-04 18:03:06 +0000473 if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
njn5c004e42002-11-18 11:04:50 +0000474 return True;
475 else
476 return False;
477}
478
sewardjaf48a602003-07-06 00:54:47 +0000479/* This one called from generated code and non-generated code. */
njn5c004e42002-11-18 11:04:50 +0000480
njn72718642003-07-24 08:45:32 +0000481void MAC_(record_address_error) ( ThreadId tid, Addr a, Int size,
sewardjaf48a602003-07-06 00:54:47 +0000482 Bool isWrite )
njn5c004e42002-11-18 11:04:50 +0000483{
njn43c799e2003-04-08 00:08:52 +0000484 MAC_Error err_extra;
485 Bool just_below_esp;
njn5c004e42002-11-18 11:04:50 +0000486
njn67516132005-03-22 04:02:43 +0000487 just_below_esp = is_just_below_ESP( VG_(get_SP)(tid), a );
njn5c004e42002-11-18 11:04:50 +0000488
489 /* If this is caused by an access immediately below %ESP, and the
490 user asks nicely, we just ignore it. */
njn43c799e2003-04-08 00:08:52 +0000491 if (MAC_(clo_workaround_gcc296_bugs) && just_below_esp)
njn5c004e42002-11-18 11:04:50 +0000492 return;
493
njn43c799e2003-04-08 00:08:52 +0000494 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000495 err_extra.axskind = isWrite ? WriteAxs : ReadAxs;
496 err_extra.size = size;
497 err_extra.addrinfo.akind = Undescribed;
498 err_extra.addrinfo.maybe_gcc = just_below_esp;
njn72718642003-07-24 08:45:32 +0000499 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000500}
501
502/* These ones are called from non-generated code */
503
504/* This is for memory errors in pthread functions, as opposed to pthread API
505 errors which are found by the core. */
nethercote8b76fe52004-11-08 19:20:09 +0000506void MAC_(record_core_mem_error) ( ThreadId tid, Bool isUnaddr, Char* msg )
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
njn43c799e2003-04-08 00:08:52 +0000510 MAC_(clear_MAC_Error)( &err_extra );
nethercote8b76fe52004-11-08 19:20:09 +0000511 err_extra.isUnaddr = isUnaddr;
njn72718642003-07-24 08:45:32 +0000512 VG_(maybe_record_error)( tid, CoreMemErr, /*addr*/0, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000513}
514
njn16390462005-05-08 15:26:00 +0000515// Three kinds of param errors:
516// - register arg contains undefined bytes
517// - memory arg is unaddressable
518// - memory arg contains undefined bytes
519// 'isReg' and 'isUnaddr' dictate which of these it is.
nethercote8b76fe52004-11-08 19:20:09 +0000520void MAC_(record_param_error) ( ThreadId tid, Addr a, Bool isReg,
521 Bool isUnaddr, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000522{
njn43c799e2003-04-08 00:08:52 +0000523 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000524
njnca82cc02004-11-22 17:18:48 +0000525 tl_assert(VG_INVALID_THREADID != tid);
njn16390462005-05-08 15:26:00 +0000526 if (isUnaddr) tl_assert(!isReg); // unaddressable register is impossible
njn43c799e2003-04-08 00:08:52 +0000527 MAC_(clear_MAC_Error)( &err_extra );
nethercote8b76fe52004-11-08 19:20:09 +0000528 err_extra.addrinfo.akind = ( isReg ? Register : Undescribed );
529 err_extra.isUnaddr = isUnaddr;
njn72718642003-07-24 08:45:32 +0000530 VG_(maybe_record_error)( tid, ParamErr, a, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000531}
532
njn72718642003-07-24 08:45:32 +0000533void MAC_(record_jump_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000534{
njn43c799e2003-04-08 00:08:52 +0000535 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000536
njnca82cc02004-11-22 17:18:48 +0000537 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000538 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000539 err_extra.axskind = ExecAxs;
nethercote7250b8f2004-04-13 08:47:35 +0000540 err_extra.size = 1; // size only used for suppressions
njn5c004e42002-11-18 11:04:50 +0000541 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000542 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000543}
544
njn72718642003-07-24 08:45:32 +0000545void MAC_(record_free_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000546{
njn43c799e2003-04-08 00:08:52 +0000547 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000548
njnca82cc02004-11-22 17:18:48 +0000549 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000550 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000551 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000552 VG_(maybe_record_error)( tid, FreeErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000553}
554
rjwalshbc0bb832004-06-19 18:12:36 +0000555void MAC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )
556{
557 MAC_Error err_extra;
558
njnca82cc02004-11-22 17:18:48 +0000559 tl_assert(VG_INVALID_THREADID != tid);
rjwalshbc0bb832004-06-19 18:12:36 +0000560 MAC_(clear_MAC_Error)( &err_extra );
561 err_extra.addrinfo.akind = Undescribed;
562 VG_(maybe_record_error)( tid, IllegalMempoolErr, a, /*s*/NULL, &err_extra );
563}
564
njn72718642003-07-24 08:45:32 +0000565void MAC_(record_freemismatch_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000566{
njn43c799e2003-04-08 00:08:52 +0000567 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000568
njnca82cc02004-11-22 17:18:48 +0000569 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000570 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000571 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000572 VG_(maybe_record_error)( tid, FreeMismatchErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000573}
574
sewardj2a99cf62004-11-24 10:44:19 +0000575void MAC_(record_overlap_error) ( ThreadId tid,
576 Char* function, OverlapExtra* ov_extra )
njn66fe05a2003-07-22 09:12:33 +0000577{
sewardj2a99cf62004-11-24 10:44:19 +0000578 VG_(maybe_record_error)(
579 tid, OverlapErr, /*addr*/0, /*s*/function, ov_extra );
njn66fe05a2003-07-22 09:12:33 +0000580}
581
582
njnb6cae9f2003-09-04 20:50:47 +0000583/* Updates the copy with address info if necessary (but not for all errors). */
njn51d827b2005-05-09 01:02:08 +0000584UInt MAC_(update_extra)( Error* err )
njn43c799e2003-04-08 00:08:52 +0000585{
njnb6cae9f2003-09-04 20:50:47 +0000586 switch (VG_(get_error_kind)(err)) {
587 case ValueErr:
588 case CoreMemErr:
589 case AddrErr:
590 case ParamErr:
591 case UserErr:
592 case FreeErr:
rjwalshbc0bb832004-06-19 18:12:36 +0000593 case IllegalMempoolErr:
njnb6cae9f2003-09-04 20:50:47 +0000594 case FreeMismatchErr: {
nethercote8b76fe52004-11-08 19:20:09 +0000595 MAC_Error* extra = VG_(get_error_extra)(err);
njnb6cae9f2003-09-04 20:50:47 +0000596 if (extra != NULL && Undescribed == extra->addrinfo.akind) {
597 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
598 }
599 return sizeof(MAC_Error);
600 }
njn43c799e2003-04-08 00:08:52 +0000601 /* Don't need to return the correct size -- LeakErrs are always shown with
602 VG_(unique_error)() so they're not copied anyway. */
njnb6cae9f2003-09-04 20:50:47 +0000603 case LeakErr: return 0;
604 case OverlapErr: return sizeof(OverlapExtra);
njn67993252004-11-22 18:02:32 +0000605 default: VG_(tool_panic)("update_extra: bad errkind");
njn43c799e2003-04-08 00:08:52 +0000606 }
njn43c799e2003-04-08 00:08:52 +0000607}
608
609
njn5c004e42002-11-18 11:04:50 +0000610/*------------------------------------------------------------*/
611/*--- Suppressions ---*/
612/*------------------------------------------------------------*/
613
njn43c799e2003-04-08 00:08:52 +0000614Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
615{
616 SuppKind skind;
617
618 if (VG_STREQ(name, "Param")) skind = ParamSupp;
619 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
620 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
621 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
622 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
623 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
njnc0616662003-06-12 09:58:41 +0000624 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
njn43c799e2003-04-08 00:08:52 +0000625 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
626 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
njne9cab142003-09-19 08:10:07 +0000627 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
rjwalshbc0bb832004-06-19 18:12:36 +0000628 else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
njn43c799e2003-04-08 00:08:52 +0000629 else
630 return False;
631
632 VG_(set_supp_kind)(su, skind);
633 return True;
634}
635
njn51d827b2005-05-09 01:02:08 +0000636Bool MAC_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
njn5c004e42002-11-18 11:04:50 +0000637{
638 Bool eof;
639
640 if (VG_(get_supp_kind)(su) == ParamSupp) {
641 eof = VG_(get_line) ( fd, buf, nBuf );
642 if (eof) return False;
643 VG_(set_supp_string)(su, VG_(strdup)(buf));
644 }
645 return True;
646}
647
njn51d827b2005-05-09 01:02:08 +0000648Bool MAC_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000649{
sewardj05bcdcb2003-05-18 10:05:38 +0000650 Int su_size;
njn43c799e2003-04-08 00:08:52 +0000651 MAC_Error* err_extra = VG_(get_error_extra)(err);
652 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000653
654 switch (VG_(get_supp_kind)(su)) {
655 case ParamSupp:
656 return (ekind == ParamErr
njn43c799e2003-04-08 00:08:52 +0000657 && VG_STREQ(VG_(get_error_string)(err),
658 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000659
660 case CoreMemSupp:
661 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000662 && VG_STREQ(VG_(get_error_string)(err),
663 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000664
665 case Value0Supp: su_size = 0; goto value_case;
666 case Value1Supp: su_size = 1; goto value_case;
667 case Value2Supp: su_size = 2; goto value_case;
668 case Value4Supp: su_size = 4; goto value_case;
669 case Value8Supp: su_size = 8; goto value_case;
njnc0616662003-06-12 09:58:41 +0000670 case Value16Supp:su_size =16; goto value_case;
njn5c004e42002-11-18 11:04:50 +0000671 value_case:
672 return (ekind == ValueErr && err_extra->size == su_size);
673
674 case Addr1Supp: su_size = 1; goto addr_case;
675 case Addr2Supp: su_size = 2; goto addr_case;
676 case Addr4Supp: su_size = 4; goto addr_case;
677 case Addr8Supp: su_size = 8; goto addr_case;
njnc0616662003-06-12 09:58:41 +0000678 case Addr16Supp:su_size =16; goto addr_case;
njn5c004e42002-11-18 11:04:50 +0000679 addr_case:
680 return (ekind == AddrErr && err_extra->size == su_size);
681
682 case FreeSupp:
683 return (ekind == FreeErr || ekind == FreeMismatchErr);
684
njn34419c12003-05-02 17:24:29 +0000685 case OverlapSupp:
686 return (ekind = OverlapErr);
687
sewardj4a19e2f2002-12-26 11:50:21 +0000688 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000689 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000690
rjwalshbc0bb832004-06-19 18:12:36 +0000691 case MempoolSupp:
692 return (ekind == IllegalMempoolErr);
693
njn5c004e42002-11-18 11:04:50 +0000694 default:
695 VG_(printf)("Error:\n"
696 " unknown suppression type %d\n",
697 VG_(get_supp_kind)(su));
njn67993252004-11-22 18:02:32 +0000698 VG_(tool_panic)("unknown suppression type in "
njn51d827b2005-05-09 01:02:08 +0000699 "MAC_(error_matches_suppression)");
njn5c004e42002-11-18 11:04:50 +0000700 }
701}
702
njn51d827b2005-05-09 01:02:08 +0000703Char* MAC_(get_error_name) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000704{
705 Char* s;
706 switch (VG_(get_error_kind)(err)) {
707 case ParamErr: return "Param";
708 case UserErr: return NULL; /* Can't suppress User errors */
709 case FreeMismatchErr: return "Free";
rjwalshbc0bb832004-06-19 18:12:36 +0000710 case IllegalMempoolErr: return "Mempool";
njn43c799e2003-04-08 00:08:52 +0000711 case FreeErr: return "Free";
712 case AddrErr:
713 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
714 case 1: return "Addr1";
715 case 2: return "Addr2";
716 case 4: return "Addr4";
717 case 8: return "Addr8";
njnc0616662003-06-12 09:58:41 +0000718 case 16: return "Addr16";
njn67993252004-11-22 18:02:32 +0000719 default: VG_(tool_panic)("unexpected size for Addr");
njn43c799e2003-04-08 00:08:52 +0000720 }
721
722 case ValueErr:
723 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
724 case 0: return "Cond";
725 case 1: return "Value1";
726 case 2: return "Value2";
727 case 4: return "Value4";
728 case 8: return "Value8";
njnc0616662003-06-12 09:58:41 +0000729 case 16: return "Value16";
njn67993252004-11-22 18:02:32 +0000730 default: VG_(tool_panic)("unexpected size for Value");
njn43c799e2003-04-08 00:08:52 +0000731 }
732 case CoreMemErr: return "CoreMem";
njn34419c12003-05-02 17:24:29 +0000733 case OverlapErr: return "Overlap";
njn43c799e2003-04-08 00:08:52 +0000734 case LeakErr: return "Leak";
njn67993252004-11-22 18:02:32 +0000735 default: VG_(tool_panic)("get_error_name: unexpected type");
njn43c799e2003-04-08 00:08:52 +0000736 }
737 VG_(printf)(s);
738}
739
njn51d827b2005-05-09 01:02:08 +0000740void MAC_(print_extra_suppression_info) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000741{
742 if (ParamErr == VG_(get_error_kind)(err)) {
743 VG_(printf)(" %s\n", VG_(get_error_string)(err));
744 }
745}
njn5c004e42002-11-18 11:04:50 +0000746
747/*------------------------------------------------------------*/
748/*--- Crude profiling machinery. ---*/
749/*------------------------------------------------------------*/
750
751/* Event index. If just the name of the fn is given, this means the
752 number of calls to the fn. Otherwise it is the specified event.
753 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
754 The rest are shared.
755
756 10 alloc_secondary_map
757
758 20 get_abit
759M 21 get_vbyte
760 22 set_abit
761M 23 set_vbyte
762 24 get_abits4_ALIGNED
763M 25 get_vbytes4_ALIGNED
764
765 30 set_address_range_perms
766 31 set_address_range_perms(lower byte loop)
767 32 set_address_range_perms(quadword loop)
768 33 set_address_range_perms(upper byte loop)
769
770 35 make_noaccess
771 36 make_writable
772 37 make_readable
773A 38 make_accessible
774
775 40 copy_address_range_state
776 41 copy_address_range_state(byte loop)
777 42 check_writable
778 43 check_writable(byte loop)
779 44 check_readable
780 45 check_readable(byte loop)
781 46 check_readable_asciiz
782 47 check_readable_asciiz(byte loop)
783A 48 check_accessible
784A 49 check_accessible(byte loop)
785
786 50 make_noaccess_aligned
787 51 make_writable_aligned
788
789M 60 helperc_LOADV4
790M 61 helperc_STOREV4
791M 62 helperc_LOADV2
792M 63 helperc_STOREV2
793M 64 helperc_LOADV1
794M 65 helperc_STOREV1
795
796A 66 helperc_ACCESS4
797A 67 helperc_ACCESS2
798A 68 helperc_ACCESS1
799
800M 70 rim_rd_V4_SLOWLY
801M 71 rim_wr_V4_SLOWLY
802M 72 rim_rd_V2_SLOWLY
803M 73 rim_wr_V2_SLOWLY
804M 74 rim_rd_V1_SLOWLY
805M 75 rim_wr_V1_SLOWLY
806
807A 76 ACCESS4_SLOWLY
808A 77 ACCESS2_SLOWLY
809A 78 ACCESS1_SLOWLY
810
811 80 fpu_read
812 81 fpu_read aligned 4
813 82 fpu_read aligned 8
814 83 fpu_read 2
jsewardfca60182004-01-04 23:30:55 +0000815 84 fpu_read 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000816
817M 85 fpu_write
818M 86 fpu_write aligned 4
819M 87 fpu_write aligned 8
820M 88 fpu_write 2
jsewardfca60182004-01-04 23:30:55 +0000821M 89 fpu_write 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000822
823 90 fpu_access
824 91 fpu_access aligned 4
825 92 fpu_access aligned 8
826 93 fpu_access 2
jsewardfca60182004-01-04 23:30:55 +0000827 94 fpu_access 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000828
829 100 fpu_access_check_SLOWLY
830 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000831
832 110 new_mem_stack_4
833 111 new_mem_stack_8
834 112 new_mem_stack_12
835 113 new_mem_stack_16
836 114 new_mem_stack_32
837 115 new_mem_stack
838
839 120 die_mem_stack_4
840 121 die_mem_stack_8
841 122 die_mem_stack_12
842 123 die_mem_stack_16
843 124 die_mem_stack_32
844 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000845*/
846
njn43c799e2003-04-08 00:08:52 +0000847#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000848
sewardjc1a2cda2005-04-21 17:34:00 +0000849UInt MAC_(event_ctr)[N_PROF_EVENTS];
850HChar* MAC_(event_ctr_name)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000851
njnb4aee052003-04-15 14:09:58 +0000852static void init_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000853{
854 Int i;
sewardjc1a2cda2005-04-21 17:34:00 +0000855 for (i = 0; i < N_PROF_EVENTS; i++) {
njn43c799e2003-04-08 00:08:52 +0000856 MAC_(event_ctr)[i] = 0;
sewardjc1a2cda2005-04-21 17:34:00 +0000857 MAC_(event_ctr_name)[i] = NULL;
858 }
njn5c004e42002-11-18 11:04:50 +0000859}
860
njnb4aee052003-04-15 14:09:58 +0000861static void done_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000862{
sewardjc1a2cda2005-04-21 17:34:00 +0000863 Int i;
864 Bool spaced = False;
njn5c004e42002-11-18 11:04:50 +0000865 for (i = 0; i < N_PROF_EVENTS; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +0000866 if (!spaced && (i % 10) == 0) {
njn5c004e42002-11-18 11:04:50 +0000867 VG_(printf)("\n");
sewardjc1a2cda2005-04-21 17:34:00 +0000868 spaced = True;
869 }
870 if (MAC_(event_ctr)[i] > 0) {
871 spaced = False;
872 VG_(printf)( "prof mem event %3d: %9d %s\n",
873 i, MAC_(event_ctr)[i],
874 MAC_(event_ctr_name)[i]
875 ? MAC_(event_ctr_name)[i] : "unnamed");
876 }
njn5c004e42002-11-18 11:04:50 +0000877 }
njn5c004e42002-11-18 11:04:50 +0000878}
879
880#else
881
njnb4aee052003-04-15 14:09:58 +0000882static void init_prof_mem ( void ) { }
883static void done_prof_mem ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000884
njn5c004e42002-11-18 11:04:50 +0000885#endif
886
887/*------------------------------------------------------------*/
njn3e884182003-04-15 13:03:23 +0000888/*--- Common initialisation + finalisation ---*/
889/*------------------------------------------------------------*/
890
891void MAC_(common_pre_clo_init)(void)
892{
893 MAC_(malloc_list) = VG_(HT_construct)();
rjwalshbc0bb832004-06-19 18:12:36 +0000894 MAC_(mempool_list) = VG_(HT_construct)();
njn3e884182003-04-15 13:03:23 +0000895 init_prof_mem();
896}
897
njnb8dca862005-03-14 02:42:44 +0000898void MAC_(common_fini)(void (*leak_check)(ThreadId tid, LeakCheckMode mode))
njn3e884182003-04-15 13:03:23 +0000899{
njn86f12dc2005-03-14 01:16:05 +0000900 MAC_(print_malloc_stats)();
njn3e884182003-04-15 13:03:23 +0000901
sewardj71bc3cb2005-05-19 00:25:45 +0000902 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
sewardjb5f6f512005-03-10 23:59:00 +0000903 if (MAC_(clo_leak_check) == LC_Off)
njn3e884182003-04-15 13:03:23 +0000904 VG_(message)(Vg_UserMsg,
905 "For a detailed leak analysis, rerun with: --leak-check=yes");
906
907 VG_(message)(Vg_UserMsg,
908 "For counts of detected errors, rerun with: -v");
909 }
sewardjb5f6f512005-03-10 23:59:00 +0000910 if (MAC_(clo_leak_check) != LC_Off)
njnb8dca862005-03-14 02:42:44 +0000911 leak_check(1/*bogus ThreadId*/, MAC_(clo_leak_check));
njn3e884182003-04-15 13:03:23 +0000912
913 done_prof_mem();
914}
915
916/*------------------------------------------------------------*/
njn47363ab2003-04-21 13:24:40 +0000917/*--- Common client request handling ---*/
918/*------------------------------------------------------------*/
919
nethercoted1b64b22004-11-04 18:22:28 +0000920Bool MAC_(handle_common_client_requests)(ThreadId tid, UWord* arg, UWord* ret )
njn47363ab2003-04-21 13:24:40 +0000921{
njnd7994182003-10-02 13:44:04 +0000922 Char* err =
923 "The client requests VALGRIND_MALLOCLIKE_BLOCK and\n"
924 " VALGRIND_FREELIKE_BLOCK have moved. Please recompile your\n"
925 " program to incorporate the updates in the Valgrind header files.\n"
926 " You shouldn't need to change the text of your program at all.\n"
927 " Everything should then work as before. Sorry for the bother.\n";
njn47363ab2003-04-21 13:24:40 +0000928
929 switch (arg[0]) {
njn10785452003-05-20 16:38:24 +0000930 case VG_USERREQ__COUNT_LEAKS: { /* count leaked bytes */
nethercoted1b64b22004-11-04 18:22:28 +0000931 UWord** argp = (UWord**)arg;
njne8b5c052003-07-22 22:03:58 +0000932 // MAC_(bytes_leaked) et al were set by the last leak check (or zero
933 // if no prior leak checks performed).
sewardjb5f6f512005-03-10 23:59:00 +0000934 *argp[1] = MAC_(bytes_leaked) + MAC_(bytes_indirect);
njne8b5c052003-07-22 22:03:58 +0000935 *argp[2] = MAC_(bytes_dubious);
936 *argp[3] = MAC_(bytes_reachable);
937 *argp[4] = MAC_(bytes_suppressed);
sewardjb5f6f512005-03-10 23:59:00 +0000938 // there is no argp[5]
939 //*argp[5] = MAC_(bytes_indirect);
940 // XXX need to make *argp[1-4] readable
njn47363ab2003-04-21 13:24:40 +0000941 *ret = 0;
942 return True;
njn10785452003-05-20 16:38:24 +0000943 }
njnd7994182003-10-02 13:44:04 +0000944 case VG_USERREQ__MALLOCLIKE_BLOCK__OLD_DO_NOT_USE:
945 case VG_USERREQ__FREELIKE_BLOCK__OLD_DO_NOT_USE:
njn67993252004-11-22 18:02:32 +0000946 VG_(tool_panic)(err);
njnd7994182003-10-02 13:44:04 +0000947
njn10785452003-05-20 16:38:24 +0000948 case VG_USERREQ__MALLOCLIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000949 Addr p = (Addr)arg[1];
nethercote928a5f72004-11-03 18:10:37 +0000950 SizeT sizeB = arg[2];
njnd7994182003-10-02 13:44:04 +0000951 UInt rzB = arg[3];
952 Bool is_zeroed = (Bool)arg[4];
njn47363ab2003-04-21 13:24:40 +0000953
sewardj2a99cf62004-11-24 10:44:19 +0000954 MAC_(new_block) ( tid, p, sizeB, /*ignored*/0, rzB, is_zeroed,
nethercote57e36b32004-07-10 14:56:28 +0000955 MAC_AllocCustom, MAC_(malloc_list) );
njn10785452003-05-20 16:38:24 +0000956 return True;
957 }
958 case VG_USERREQ__FREELIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000959 Addr p = (Addr)arg[1];
960 UInt rzB = arg[2];
njn10785452003-05-20 16:38:24 +0000961
sewardj2a99cf62004-11-24 10:44:19 +0000962 MAC_(handle_free) ( tid, p, rzB, MAC_AllocCustom );
njn10785452003-05-20 16:38:24 +0000963 return True;
964 }
njnd7994182003-10-02 13:44:04 +0000965
njn1f8b3e72005-03-22 04:27:14 +0000966 case _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR: {
967 Char* s = (Char*) arg[1];
968 OverlapExtra* extra = (OverlapExtra*)arg[2];
969 MAC_(record_overlap_error)(tid, s, extra);
nethercotee3a53722004-05-05 10:46:22 +0000970 return True;
njn1f8b3e72005-03-22 04:27:14 +0000971 }
nethercotee3a53722004-05-05 10:46:22 +0000972
rjwalshbc0bb832004-06-19 18:12:36 +0000973 case VG_USERREQ__CREATE_MEMPOOL: {
974 Addr pool = (Addr)arg[1];
975 UInt rzB = arg[2];
976 Bool is_zeroed = (Bool)arg[3];
977
978 MAC_(create_mempool) ( pool, rzB, is_zeroed );
979 return True;
980 }
981
982 case VG_USERREQ__DESTROY_MEMPOOL: {
983 Addr pool = (Addr)arg[1];
984
985 MAC_(destroy_mempool) ( pool );
986 return True;
987 }
988
989 case VG_USERREQ__MEMPOOL_ALLOC: {
990 Addr pool = (Addr)arg[1];
991 Addr addr = (Addr)arg[2];
992 UInt size = arg[3];
993
sewardj2a99cf62004-11-24 10:44:19 +0000994 MAC_(mempool_alloc) ( tid, pool, addr, size );
rjwalshbc0bb832004-06-19 18:12:36 +0000995 return True;
996 }
997
998 case VG_USERREQ__MEMPOOL_FREE: {
999 Addr pool = (Addr)arg[1];
1000 Addr addr = (Addr)arg[2];
1001
1002 MAC_(mempool_free) ( pool, addr );
1003 return True;
1004 }
1005
njn47363ab2003-04-21 13:24:40 +00001006 default:
1007 return False;
1008 }
1009}
1010
njn5c004e42002-11-18 11:04:50 +00001011/*--------------------------------------------------------------------*/
njn00cae242005-05-09 01:13:44 +00001012/*--- end ---*/
njn5c004e42002-11-18 11:04:50 +00001013/*--------------------------------------------------------------------*/