blob: 0f9c33e1045799b682af8437a5e3fecb4e65227e [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)(
njn6a329422005-03-12 20:38:13 +0000100" --leak-check=no|summary|full search for memory leaks at exit? [summary]\n"
sewardjb5f6f512005-03-10 23:59:00 +0000101" --leak-resolution=low|med|high how much bt merging in leak check [low]\n"
102" --show-reachable=no|yes show reachable blocks in leak check? [no]\n"
njn4d056022005-07-25 23:18:04 +0000103" --partial-loads-ok=no|yes too hard to explain here; see manual [yes]\n"
104" --freelist-vol=<number> volume of freed blocks queue [1000000]\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{
njn34582fb2005-08-11 00:06:36 +0000440 MAC_Chunk* mc;
njn3e884182003-04-15 13:03:23 +0000441 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. */
njn34582fb2005-08-11 00:06:36 +0000456 mc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk, &a);
457 if (NULL != mc) {
njn43c799e2003-04-08 00:08:52 +0000458 ai->akind = Freed;
njn34582fb2005-08-11 00:06:36 +0000459 ai->blksize = mc->size;
460 ai->rwoffset = (Int)a - (Int)mc->data;
461 ai->lastchange = mc->where;
njn43c799e2003-04-08 00:08:52 +0000462 return;
463 }
464 /* Search for a currently malloc'd block which might bracket it. */
njn34582fb2005-08-11 00:06:36 +0000465 mc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode, &a);
466 if (NULL != mc) {
njn43c799e2003-04-08 00:08:52 +0000467 ai->akind = Mallocd;
njn34582fb2005-08-11 00:06:36 +0000468 ai->blksize = mc->size;
469 ai->rwoffset = (Int)(a) - (Int)mc->data;
470 ai->lastchange = mc->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
njn4bd67b52005-08-11 00:47:10 +0000574void MAC_(record_freemismatch_error) ( ThreadId tid, Addr a, MAC_Chunk* mc )
njn5c004e42002-11-18 11:04:50 +0000575{
njn43c799e2003-04-08 00:08:52 +0000576 MAC_Error err_extra;
njn4bd67b52005-08-11 00:47:10 +0000577 AddrInfo* ai;
njn5c004e42002-11-18 11:04:50 +0000578
njnca82cc02004-11-22 17:18:48 +0000579 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000580 MAC_(clear_MAC_Error)( &err_extra );
njn4bd67b52005-08-11 00:47:10 +0000581 ai = &err_extra.addrinfo;
582 ai->akind = Mallocd; // Nb: not 'Freed'
583 ai->blksize = mc->size;
584 ai->rwoffset = (Int)a - (Int)mc->data;
585 ai->lastchange = mc->where;
njn72718642003-07-24 08:45:32 +0000586 VG_(maybe_record_error)( tid, FreeMismatchErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000587}
588
sewardj2a99cf62004-11-24 10:44:19 +0000589void MAC_(record_overlap_error) ( ThreadId tid,
590 Char* function, OverlapExtra* ov_extra )
njn66fe05a2003-07-22 09:12:33 +0000591{
sewardj2a99cf62004-11-24 10:44:19 +0000592 VG_(maybe_record_error)(
593 tid, OverlapErr, /*addr*/0, /*s*/function, ov_extra );
njn66fe05a2003-07-22 09:12:33 +0000594}
595
596
njnb6cae9f2003-09-04 20:50:47 +0000597/* Updates the copy with address info if necessary (but not for all errors). */
njn51d827b2005-05-09 01:02:08 +0000598UInt MAC_(update_extra)( Error* err )
njn43c799e2003-04-08 00:08:52 +0000599{
njnb6cae9f2003-09-04 20:50:47 +0000600 switch (VG_(get_error_kind)(err)) {
njn84c91232005-08-11 02:46:54 +0000601 // These two don't have addresses associated with them, and so don't
602 // need any updating.
njnb6cae9f2003-09-04 20:50:47 +0000603 case CoreMemErr:
njn84c91232005-08-11 02:46:54 +0000604 case ValueErr: {
605 MAC_Error* extra = VG_(get_error_extra)(err);
606 tl_assert(Unknown == extra->addrinfo.akind);
607 return sizeof(MAC_Error);
608 }
609
610 // ParamErrs sometimes involve a memory address; call describe_addr() in
611 // this case.
612 case ParamErr: {
613 MAC_Error* extra = VG_(get_error_extra)(err);
614 tl_assert(Undescribed == extra->addrinfo.akind ||
615 Register == extra->addrinfo.akind);
616 if (Undescribed == extra->addrinfo.akind)
617 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
618 return sizeof(MAC_Error);
619 }
620
621 // These four always involve a memory address.
njnb6cae9f2003-09-04 20:50:47 +0000622 case AddrErr:
njnb6cae9f2003-09-04 20:50:47 +0000623 case UserErr:
624 case FreeErr:
njn4bd67b52005-08-11 00:47:10 +0000625 case IllegalMempoolErr: {
nethercote8b76fe52004-11-08 19:20:09 +0000626 MAC_Error* extra = VG_(get_error_extra)(err);
njn84c91232005-08-11 02:46:54 +0000627 tl_assert(Undescribed == extra->addrinfo.akind);
628 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
njnb6cae9f2003-09-04 20:50:47 +0000629 return sizeof(MAC_Error);
630 }
njn4bd67b52005-08-11 00:47:10 +0000631
njn84c91232005-08-11 02:46:54 +0000632 // FreeMismatchErrs have already had their address described; this is
633 // possible because we have the MAC_Chunk on hand when the error is
634 // detected. However, the address may be part of a user block, and if so
635 // we override the pre-determined description with a user block one.
njn4bd67b52005-08-11 00:47:10 +0000636 case FreeMismatchErr: {
637 MAC_Error* extra = VG_(get_error_extra)(err);
638 tl_assert(extra && Mallocd == extra->addrinfo.akind);
njn84c91232005-08-11 02:46:54 +0000639 if (NULL != MAC_(describe_addr_supp))
640 (void)MAC_(describe_addr_supp)( VG_(get_error_address)(err),
641 &(extra->addrinfo) );
njn4bd67b52005-08-11 00:47:10 +0000642 return sizeof(MAC_Error);
643 }
644
njn84c91232005-08-11 02:46:54 +0000645 // No memory address involved with these ones. Nb: for LeakErrs the
646 // returned size does not matter -- LeakErrs are always shown with
647 // VG_(unique_error)() so they're not copied.
njnb6cae9f2003-09-04 20:50:47 +0000648 case LeakErr: return 0;
649 case OverlapErr: return sizeof(OverlapExtra);
njn84c91232005-08-11 02:46:54 +0000650
njn67993252004-11-22 18:02:32 +0000651 default: VG_(tool_panic)("update_extra: bad errkind");
njn43c799e2003-04-08 00:08:52 +0000652 }
njn43c799e2003-04-08 00:08:52 +0000653}
654
655
njn5c004e42002-11-18 11:04:50 +0000656/*------------------------------------------------------------*/
657/*--- Suppressions ---*/
658/*------------------------------------------------------------*/
659
njn43c799e2003-04-08 00:08:52 +0000660Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
661{
662 SuppKind skind;
663
664 if (VG_STREQ(name, "Param")) skind = ParamSupp;
665 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
666 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
667 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
668 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
669 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
njnc0616662003-06-12 09:58:41 +0000670 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
njn43c799e2003-04-08 00:08:52 +0000671 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
672 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
njne9cab142003-09-19 08:10:07 +0000673 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
rjwalshbc0bb832004-06-19 18:12:36 +0000674 else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
njn43c799e2003-04-08 00:08:52 +0000675 else
676 return False;
677
678 VG_(set_supp_kind)(su, skind);
679 return True;
680}
681
njn51d827b2005-05-09 01:02:08 +0000682Bool MAC_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
njn5c004e42002-11-18 11:04:50 +0000683{
684 Bool eof;
685
686 if (VG_(get_supp_kind)(su) == ParamSupp) {
687 eof = VG_(get_line) ( fd, buf, nBuf );
688 if (eof) return False;
689 VG_(set_supp_string)(su, VG_(strdup)(buf));
690 }
691 return True;
692}
693
njn51d827b2005-05-09 01:02:08 +0000694Bool MAC_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000695{
sewardj05bcdcb2003-05-18 10:05:38 +0000696 Int su_size;
njn43c799e2003-04-08 00:08:52 +0000697 MAC_Error* err_extra = VG_(get_error_extra)(err);
698 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000699
700 switch (VG_(get_supp_kind)(su)) {
701 case ParamSupp:
702 return (ekind == ParamErr
njn43c799e2003-04-08 00:08:52 +0000703 && VG_STREQ(VG_(get_error_string)(err),
704 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000705
706 case CoreMemSupp:
707 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000708 && VG_STREQ(VG_(get_error_string)(err),
709 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000710
711 case Value0Supp: su_size = 0; goto value_case;
712 case Value1Supp: su_size = 1; goto value_case;
713 case Value2Supp: su_size = 2; goto value_case;
714 case Value4Supp: su_size = 4; goto value_case;
715 case Value8Supp: su_size = 8; goto value_case;
njnc0616662003-06-12 09:58:41 +0000716 case Value16Supp:su_size =16; goto value_case;
njn5c004e42002-11-18 11:04:50 +0000717 value_case:
718 return (ekind == ValueErr && err_extra->size == su_size);
719
720 case Addr1Supp: su_size = 1; goto addr_case;
721 case Addr2Supp: su_size = 2; goto addr_case;
722 case Addr4Supp: su_size = 4; goto addr_case;
723 case Addr8Supp: su_size = 8; goto addr_case;
njnc0616662003-06-12 09:58:41 +0000724 case Addr16Supp:su_size =16; goto addr_case;
njn5c004e42002-11-18 11:04:50 +0000725 addr_case:
726 return (ekind == AddrErr && err_extra->size == su_size);
727
728 case FreeSupp:
729 return (ekind == FreeErr || ekind == FreeMismatchErr);
730
njn34419c12003-05-02 17:24:29 +0000731 case OverlapSupp:
732 return (ekind = OverlapErr);
733
sewardj4a19e2f2002-12-26 11:50:21 +0000734 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000735 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000736
rjwalshbc0bb832004-06-19 18:12:36 +0000737 case MempoolSupp:
738 return (ekind == IllegalMempoolErr);
739
njn5c004e42002-11-18 11:04:50 +0000740 default:
741 VG_(printf)("Error:\n"
742 " unknown suppression type %d\n",
743 VG_(get_supp_kind)(su));
njn67993252004-11-22 18:02:32 +0000744 VG_(tool_panic)("unknown suppression type in "
njn51d827b2005-05-09 01:02:08 +0000745 "MAC_(error_matches_suppression)");
njn5c004e42002-11-18 11:04:50 +0000746 }
747}
748
njn51d827b2005-05-09 01:02:08 +0000749Char* MAC_(get_error_name) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000750{
751 Char* s;
752 switch (VG_(get_error_kind)(err)) {
753 case ParamErr: return "Param";
754 case UserErr: return NULL; /* Can't suppress User errors */
755 case FreeMismatchErr: return "Free";
rjwalshbc0bb832004-06-19 18:12:36 +0000756 case IllegalMempoolErr: return "Mempool";
njn43c799e2003-04-08 00:08:52 +0000757 case FreeErr: return "Free";
758 case AddrErr:
759 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
760 case 1: return "Addr1";
761 case 2: return "Addr2";
762 case 4: return "Addr4";
763 case 8: return "Addr8";
njnc0616662003-06-12 09:58:41 +0000764 case 16: return "Addr16";
njn67993252004-11-22 18:02:32 +0000765 default: VG_(tool_panic)("unexpected size for Addr");
njn43c799e2003-04-08 00:08:52 +0000766 }
767
768 case ValueErr:
769 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
770 case 0: return "Cond";
771 case 1: return "Value1";
772 case 2: return "Value2";
773 case 4: return "Value4";
774 case 8: return "Value8";
njnc0616662003-06-12 09:58:41 +0000775 case 16: return "Value16";
njn67993252004-11-22 18:02:32 +0000776 default: VG_(tool_panic)("unexpected size for Value");
njn43c799e2003-04-08 00:08:52 +0000777 }
778 case CoreMemErr: return "CoreMem";
njn34419c12003-05-02 17:24:29 +0000779 case OverlapErr: return "Overlap";
njn43c799e2003-04-08 00:08:52 +0000780 case LeakErr: return "Leak";
njn67993252004-11-22 18:02:32 +0000781 default: VG_(tool_panic)("get_error_name: unexpected type");
njn43c799e2003-04-08 00:08:52 +0000782 }
783 VG_(printf)(s);
784}
785
njn51d827b2005-05-09 01:02:08 +0000786void MAC_(print_extra_suppression_info) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000787{
788 if (ParamErr == VG_(get_error_kind)(err)) {
789 VG_(printf)(" %s\n", VG_(get_error_string)(err));
790 }
791}
njn5c004e42002-11-18 11:04:50 +0000792
793/*------------------------------------------------------------*/
794/*--- Crude profiling machinery. ---*/
795/*------------------------------------------------------------*/
796
797/* Event index. If just the name of the fn is given, this means the
798 number of calls to the fn. Otherwise it is the specified event.
799 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
800 The rest are shared.
801
802 10 alloc_secondary_map
803
804 20 get_abit
805M 21 get_vbyte
806 22 set_abit
807M 23 set_vbyte
808 24 get_abits4_ALIGNED
809M 25 get_vbytes4_ALIGNED
810
811 30 set_address_range_perms
812 31 set_address_range_perms(lower byte loop)
813 32 set_address_range_perms(quadword loop)
814 33 set_address_range_perms(upper byte loop)
815
816 35 make_noaccess
817 36 make_writable
818 37 make_readable
819A 38 make_accessible
820
821 40 copy_address_range_state
822 41 copy_address_range_state(byte loop)
823 42 check_writable
824 43 check_writable(byte loop)
825 44 check_readable
826 45 check_readable(byte loop)
827 46 check_readable_asciiz
828 47 check_readable_asciiz(byte loop)
829A 48 check_accessible
830A 49 check_accessible(byte loop)
831
832 50 make_noaccess_aligned
833 51 make_writable_aligned
834
835M 60 helperc_LOADV4
836M 61 helperc_STOREV4
837M 62 helperc_LOADV2
838M 63 helperc_STOREV2
839M 64 helperc_LOADV1
840M 65 helperc_STOREV1
841
842A 66 helperc_ACCESS4
843A 67 helperc_ACCESS2
844A 68 helperc_ACCESS1
845
846M 70 rim_rd_V4_SLOWLY
847M 71 rim_wr_V4_SLOWLY
848M 72 rim_rd_V2_SLOWLY
849M 73 rim_wr_V2_SLOWLY
850M 74 rim_rd_V1_SLOWLY
851M 75 rim_wr_V1_SLOWLY
852
853A 76 ACCESS4_SLOWLY
854A 77 ACCESS2_SLOWLY
855A 78 ACCESS1_SLOWLY
856
857 80 fpu_read
858 81 fpu_read aligned 4
859 82 fpu_read aligned 8
860 83 fpu_read 2
jsewardfca60182004-01-04 23:30:55 +0000861 84 fpu_read 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000862
863M 85 fpu_write
864M 86 fpu_write aligned 4
865M 87 fpu_write aligned 8
866M 88 fpu_write 2
jsewardfca60182004-01-04 23:30:55 +0000867M 89 fpu_write 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000868
869 90 fpu_access
870 91 fpu_access aligned 4
871 92 fpu_access aligned 8
872 93 fpu_access 2
jsewardfca60182004-01-04 23:30:55 +0000873 94 fpu_access 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000874
875 100 fpu_access_check_SLOWLY
876 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000877
878 110 new_mem_stack_4
879 111 new_mem_stack_8
880 112 new_mem_stack_12
881 113 new_mem_stack_16
882 114 new_mem_stack_32
883 115 new_mem_stack
884
885 120 die_mem_stack_4
886 121 die_mem_stack_8
887 122 die_mem_stack_12
888 123 die_mem_stack_16
889 124 die_mem_stack_32
890 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000891*/
892
njn43c799e2003-04-08 00:08:52 +0000893#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000894
sewardjc1a2cda2005-04-21 17:34:00 +0000895UInt MAC_(event_ctr)[N_PROF_EVENTS];
896HChar* MAC_(event_ctr_name)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000897
njnb4aee052003-04-15 14:09:58 +0000898static void init_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000899{
900 Int i;
sewardjc1a2cda2005-04-21 17:34:00 +0000901 for (i = 0; i < N_PROF_EVENTS; i++) {
njn43c799e2003-04-08 00:08:52 +0000902 MAC_(event_ctr)[i] = 0;
sewardjc1a2cda2005-04-21 17:34:00 +0000903 MAC_(event_ctr_name)[i] = NULL;
904 }
njn5c004e42002-11-18 11:04:50 +0000905}
906
njnb4aee052003-04-15 14:09:58 +0000907static void done_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000908{
sewardjc1a2cda2005-04-21 17:34:00 +0000909 Int i;
910 Bool spaced = False;
njn5c004e42002-11-18 11:04:50 +0000911 for (i = 0; i < N_PROF_EVENTS; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +0000912 if (!spaced && (i % 10) == 0) {
njn5c004e42002-11-18 11:04:50 +0000913 VG_(printf)("\n");
sewardjc1a2cda2005-04-21 17:34:00 +0000914 spaced = True;
915 }
916 if (MAC_(event_ctr)[i] > 0) {
917 spaced = False;
918 VG_(printf)( "prof mem event %3d: %9d %s\n",
919 i, MAC_(event_ctr)[i],
920 MAC_(event_ctr_name)[i]
921 ? MAC_(event_ctr_name)[i] : "unnamed");
922 }
njn5c004e42002-11-18 11:04:50 +0000923 }
njn5c004e42002-11-18 11:04:50 +0000924}
925
926#else
927
njnb4aee052003-04-15 14:09:58 +0000928static void init_prof_mem ( void ) { }
929static void done_prof_mem ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000930
njn5c004e42002-11-18 11:04:50 +0000931#endif
932
933/*------------------------------------------------------------*/
njn3e884182003-04-15 13:03:23 +0000934/*--- Common initialisation + finalisation ---*/
935/*------------------------------------------------------------*/
936
937void MAC_(common_pre_clo_init)(void)
938{
njnf69f9452005-07-03 17:53:11 +0000939 MAC_(malloc_list) = VG_(HT_construct)( 80021 ); // prime, big
940 MAC_(mempool_list) = VG_(HT_construct)( 1009 ); // prime, not so big
njn3e884182003-04-15 13:03:23 +0000941 init_prof_mem();
942}
943
njnb8dca862005-03-14 02:42:44 +0000944void MAC_(common_fini)(void (*leak_check)(ThreadId tid, LeakCheckMode mode))
njn3e884182003-04-15 13:03:23 +0000945{
njn86f12dc2005-03-14 01:16:05 +0000946 MAC_(print_malloc_stats)();
njn3e884182003-04-15 13:03:23 +0000947
sewardj71bc3cb2005-05-19 00:25:45 +0000948 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
sewardjb5f6f512005-03-10 23:59:00 +0000949 if (MAC_(clo_leak_check) == LC_Off)
njn3e884182003-04-15 13:03:23 +0000950 VG_(message)(Vg_UserMsg,
951 "For a detailed leak analysis, rerun with: --leak-check=yes");
952
953 VG_(message)(Vg_UserMsg,
954 "For counts of detected errors, rerun with: -v");
955 }
sewardjb5f6f512005-03-10 23:59:00 +0000956 if (MAC_(clo_leak_check) != LC_Off)
njnb8dca862005-03-14 02:42:44 +0000957 leak_check(1/*bogus ThreadId*/, MAC_(clo_leak_check));
njn3e884182003-04-15 13:03:23 +0000958
959 done_prof_mem();
960}
961
962/*------------------------------------------------------------*/
njn47363ab2003-04-21 13:24:40 +0000963/*--- Common client request handling ---*/
964/*------------------------------------------------------------*/
965
nethercoted1b64b22004-11-04 18:22:28 +0000966Bool MAC_(handle_common_client_requests)(ThreadId tid, UWord* arg, UWord* ret )
njn47363ab2003-04-21 13:24:40 +0000967{
njnd7994182003-10-02 13:44:04 +0000968 Char* err =
969 "The client requests VALGRIND_MALLOCLIKE_BLOCK and\n"
970 " VALGRIND_FREELIKE_BLOCK have moved. Please recompile your\n"
971 " program to incorporate the updates in the Valgrind header files.\n"
972 " You shouldn't need to change the text of your program at all.\n"
973 " Everything should then work as before. Sorry for the bother.\n";
njn47363ab2003-04-21 13:24:40 +0000974
975 switch (arg[0]) {
njn10785452003-05-20 16:38:24 +0000976 case VG_USERREQ__COUNT_LEAKS: { /* count leaked bytes */
nethercoted1b64b22004-11-04 18:22:28 +0000977 UWord** argp = (UWord**)arg;
njne8b5c052003-07-22 22:03:58 +0000978 // MAC_(bytes_leaked) et al were set by the last leak check (or zero
979 // if no prior leak checks performed).
sewardjb5f6f512005-03-10 23:59:00 +0000980 *argp[1] = MAC_(bytes_leaked) + MAC_(bytes_indirect);
njne8b5c052003-07-22 22:03:58 +0000981 *argp[2] = MAC_(bytes_dubious);
982 *argp[3] = MAC_(bytes_reachable);
983 *argp[4] = MAC_(bytes_suppressed);
sewardjb5f6f512005-03-10 23:59:00 +0000984 // there is no argp[5]
985 //*argp[5] = MAC_(bytes_indirect);
986 // XXX need to make *argp[1-4] readable
njn47363ab2003-04-21 13:24:40 +0000987 *ret = 0;
988 return True;
njn10785452003-05-20 16:38:24 +0000989 }
njnd7994182003-10-02 13:44:04 +0000990 case VG_USERREQ__MALLOCLIKE_BLOCK__OLD_DO_NOT_USE:
991 case VG_USERREQ__FREELIKE_BLOCK__OLD_DO_NOT_USE:
njn67993252004-11-22 18:02:32 +0000992 VG_(tool_panic)(err);
njnd7994182003-10-02 13:44:04 +0000993
njn10785452003-05-20 16:38:24 +0000994 case VG_USERREQ__MALLOCLIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000995 Addr p = (Addr)arg[1];
nethercote928a5f72004-11-03 18:10:37 +0000996 SizeT sizeB = arg[2];
njnd7994182003-10-02 13:44:04 +0000997 UInt rzB = arg[3];
998 Bool is_zeroed = (Bool)arg[4];
njn47363ab2003-04-21 13:24:40 +0000999
sewardj2a99cf62004-11-24 10:44:19 +00001000 MAC_(new_block) ( tid, p, sizeB, /*ignored*/0, rzB, is_zeroed,
nethercote57e36b32004-07-10 14:56:28 +00001001 MAC_AllocCustom, MAC_(malloc_list) );
njn10785452003-05-20 16:38:24 +00001002 return True;
1003 }
1004 case VG_USERREQ__FREELIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +00001005 Addr p = (Addr)arg[1];
1006 UInt rzB = arg[2];
njn10785452003-05-20 16:38:24 +00001007
sewardj2a99cf62004-11-24 10:44:19 +00001008 MAC_(handle_free) ( tid, p, rzB, MAC_AllocCustom );
njn10785452003-05-20 16:38:24 +00001009 return True;
1010 }
njnd7994182003-10-02 13:44:04 +00001011
njn1f8b3e72005-03-22 04:27:14 +00001012 case _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR: {
1013 Char* s = (Char*) arg[1];
1014 OverlapExtra* extra = (OverlapExtra*)arg[2];
1015 MAC_(record_overlap_error)(tid, s, extra);
nethercotee3a53722004-05-05 10:46:22 +00001016 return True;
njn1f8b3e72005-03-22 04:27:14 +00001017 }
nethercotee3a53722004-05-05 10:46:22 +00001018
rjwalshbc0bb832004-06-19 18:12:36 +00001019 case VG_USERREQ__CREATE_MEMPOOL: {
1020 Addr pool = (Addr)arg[1];
1021 UInt rzB = arg[2];
1022 Bool is_zeroed = (Bool)arg[3];
1023
1024 MAC_(create_mempool) ( pool, rzB, is_zeroed );
1025 return True;
1026 }
1027
1028 case VG_USERREQ__DESTROY_MEMPOOL: {
1029 Addr pool = (Addr)arg[1];
1030
1031 MAC_(destroy_mempool) ( pool );
1032 return True;
1033 }
1034
1035 case VG_USERREQ__MEMPOOL_ALLOC: {
1036 Addr pool = (Addr)arg[1];
1037 Addr addr = (Addr)arg[2];
1038 UInt size = arg[3];
1039
sewardj2a99cf62004-11-24 10:44:19 +00001040 MAC_(mempool_alloc) ( tid, pool, addr, size );
rjwalshbc0bb832004-06-19 18:12:36 +00001041 return True;
1042 }
1043
1044 case VG_USERREQ__MEMPOOL_FREE: {
1045 Addr pool = (Addr)arg[1];
1046 Addr addr = (Addr)arg[2];
1047
1048 MAC_(mempool_free) ( pool, addr );
1049 return True;
1050 }
1051
njn47363ab2003-04-21 13:24:40 +00001052 default:
1053 return False;
1054 }
1055}
1056
njn5c004e42002-11-18 11:04:50 +00001057/*--------------------------------------------------------------------*/
njn00cae242005-05-09 01:13:44 +00001058/*--- end ---*/
njn5c004e42002-11-18 11:04:50 +00001059/*--------------------------------------------------------------------*/