blob: ec486502674281b7ceb89f4b8e9a5a18c9fe82c6 [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
njn1d0cb0d2005-08-15 01:52:02 +0000413/* Function used when searching MAC_Chunk lists */
414static Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc, Addr a)
thughes4ad52d02004-06-27 17:37:21 +0000415{
njn717cde52005-05-10 02:47:21 +0000416 return VG_(addr_is_in_block)( a, mc->data, mc->size,
417 MAC_MALLOC_REDZONE_SZB );
thughes4ad52d02004-06-27 17:37:21 +0000418}
419
njn43c799e2003-04-08 00:08:52 +0000420/* Describe an address as best you can, for error messages,
421 putting the result in ai. */
422static void describe_addr ( Addr a, AddrInfo* ai )
423{
njn34582fb2005-08-11 00:06:36 +0000424 MAC_Chunk* mc;
njn3e884182003-04-15 13:03:23 +0000425 ThreadId tid;
njn1d0cb0d2005-08-15 01:52:02 +0000426 Addr stack_min, stack_max;
njn43c799e2003-04-08 00:08:52 +0000427
njn43c799e2003-04-08 00:08:52 +0000428 /* Perhaps it's a user-def'd block ? (only check if requested, though) */
429 if (NULL != MAC_(describe_addr_supp)) {
430 if (MAC_(describe_addr_supp)( a, ai ))
431 return;
432 }
433 /* Perhaps it's on a thread's stack? */
njn1d0cb0d2005-08-15 01:52:02 +0000434 VG_(thread_stack_reset_iter)();
435 while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
436 if (stack_min <= a && a <= stack_max) {
437 ai->akind = Stack;
438 ai->stack_tid = tid;
439 return;
440 }
njn43c799e2003-04-08 00:08:52 +0000441 }
442 /* Search for a recently freed block which might bracket it. */
njn1d0cb0d2005-08-15 01:52:02 +0000443 mc = MAC_(get_freed_list_head)();
444 while (mc) {
445 if (addr_is_in_MAC_Chunk(mc, a)) {
446 ai->akind = Freed;
447 ai->blksize = mc->size;
448 ai->rwoffset = (Int)a - (Int)mc->data;
449 ai->lastchange = mc->where;
450 return;
451 }
452 mc = mc->next;
njn43c799e2003-04-08 00:08:52 +0000453 }
454 /* Search for a currently malloc'd block which might bracket it. */
njn1d0cb0d2005-08-15 01:52:02 +0000455 VG_(HT_ResetIter)(MAC_(malloc_list));
456 while ( (mc = VG_(HT_Next)(MAC_(malloc_list))) ) {
457 if (addr_is_in_MAC_Chunk(mc, a)) {
458 ai->akind = Mallocd;
459 ai->blksize = mc->size;
460 ai->rwoffset = (Int)(a) - (Int)mc->data;
461 ai->lastchange = mc->where;
462 return;
463 }
njn43c799e2003-04-08 00:08:52 +0000464 }
465 /* Clueless ... */
466 ai->akind = Unknown;
467 return;
468}
469
njn5c004e42002-11-18 11:04:50 +0000470/* Is this address within some small distance below %ESP? Used only
471 for the --workaround-gcc296-bugs kludge. */
472static Bool is_just_below_ESP( Addr esp, Addr aa )
473{
nethercote50397c22004-11-04 18:03:06 +0000474 if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
njn5c004e42002-11-18 11:04:50 +0000475 return True;
476 else
477 return False;
478}
479
sewardjaf48a602003-07-06 00:54:47 +0000480/* This one called from generated code and non-generated code. */
njn5c004e42002-11-18 11:04:50 +0000481
njn72718642003-07-24 08:45:32 +0000482void MAC_(record_address_error) ( ThreadId tid, Addr a, Int size,
sewardjaf48a602003-07-06 00:54:47 +0000483 Bool isWrite )
njn5c004e42002-11-18 11:04:50 +0000484{
njn43c799e2003-04-08 00:08:52 +0000485 MAC_Error err_extra;
486 Bool just_below_esp;
njn5c004e42002-11-18 11:04:50 +0000487
njn67516132005-03-22 04:02:43 +0000488 just_below_esp = is_just_below_ESP( VG_(get_SP)(tid), a );
njn5c004e42002-11-18 11:04:50 +0000489
490 /* If this is caused by an access immediately below %ESP, and the
491 user asks nicely, we just ignore it. */
njn43c799e2003-04-08 00:08:52 +0000492 if (MAC_(clo_workaround_gcc296_bugs) && just_below_esp)
njn5c004e42002-11-18 11:04:50 +0000493 return;
494
njn43c799e2003-04-08 00:08:52 +0000495 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000496 err_extra.axskind = isWrite ? WriteAxs : ReadAxs;
497 err_extra.size = size;
498 err_extra.addrinfo.akind = Undescribed;
499 err_extra.addrinfo.maybe_gcc = just_below_esp;
njn72718642003-07-24 08:45:32 +0000500 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000501}
502
503/* These ones are called from non-generated code */
504
505/* This is for memory errors in pthread functions, as opposed to pthread API
506 errors which are found by the core. */
nethercote8b76fe52004-11-08 19:20:09 +0000507void MAC_(record_core_mem_error) ( ThreadId tid, Bool isUnaddr, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000508{
njn43c799e2003-04-08 00:08:52 +0000509 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000510
njn43c799e2003-04-08 00:08:52 +0000511 MAC_(clear_MAC_Error)( &err_extra );
nethercote8b76fe52004-11-08 19:20:09 +0000512 err_extra.isUnaddr = isUnaddr;
njn72718642003-07-24 08:45:32 +0000513 VG_(maybe_record_error)( tid, CoreMemErr, /*addr*/0, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000514}
515
njn16390462005-05-08 15:26:00 +0000516// Three kinds of param errors:
517// - register arg contains undefined bytes
518// - memory arg is unaddressable
519// - memory arg contains undefined bytes
520// 'isReg' and 'isUnaddr' dictate which of these it is.
nethercote8b76fe52004-11-08 19:20:09 +0000521void MAC_(record_param_error) ( ThreadId tid, Addr a, Bool isReg,
522 Bool isUnaddr, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000523{
njn43c799e2003-04-08 00:08:52 +0000524 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000525
njnca82cc02004-11-22 17:18:48 +0000526 tl_assert(VG_INVALID_THREADID != tid);
njn16390462005-05-08 15:26:00 +0000527 if (isUnaddr) tl_assert(!isReg); // unaddressable register is impossible
njn43c799e2003-04-08 00:08:52 +0000528 MAC_(clear_MAC_Error)( &err_extra );
nethercote8b76fe52004-11-08 19:20:09 +0000529 err_extra.addrinfo.akind = ( isReg ? Register : Undescribed );
530 err_extra.isUnaddr = isUnaddr;
njn72718642003-07-24 08:45:32 +0000531 VG_(maybe_record_error)( tid, ParamErr, a, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000532}
533
njn72718642003-07-24 08:45:32 +0000534void MAC_(record_jump_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000535{
njn43c799e2003-04-08 00:08:52 +0000536 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000537
njnca82cc02004-11-22 17:18:48 +0000538 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000539 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000540 err_extra.axskind = ExecAxs;
nethercote7250b8f2004-04-13 08:47:35 +0000541 err_extra.size = 1; // size only used for suppressions
njn5c004e42002-11-18 11:04:50 +0000542 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000543 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000544}
545
njn72718642003-07-24 08:45:32 +0000546void MAC_(record_free_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000547{
njn43c799e2003-04-08 00:08:52 +0000548 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000549
njnca82cc02004-11-22 17:18:48 +0000550 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000551 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000552 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000553 VG_(maybe_record_error)( tid, FreeErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000554}
555
rjwalshbc0bb832004-06-19 18:12:36 +0000556void MAC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )
557{
558 MAC_Error err_extra;
559
njnca82cc02004-11-22 17:18:48 +0000560 tl_assert(VG_INVALID_THREADID != tid);
rjwalshbc0bb832004-06-19 18:12:36 +0000561 MAC_(clear_MAC_Error)( &err_extra );
562 err_extra.addrinfo.akind = Undescribed;
563 VG_(maybe_record_error)( tid, IllegalMempoolErr, a, /*s*/NULL, &err_extra );
564}
565
njn4bd67b52005-08-11 00:47:10 +0000566void MAC_(record_freemismatch_error) ( ThreadId tid, Addr a, MAC_Chunk* mc )
njn5c004e42002-11-18 11:04:50 +0000567{
njn43c799e2003-04-08 00:08:52 +0000568 MAC_Error err_extra;
njn4bd67b52005-08-11 00:47:10 +0000569 AddrInfo* ai;
njn5c004e42002-11-18 11:04:50 +0000570
njnca82cc02004-11-22 17:18:48 +0000571 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000572 MAC_(clear_MAC_Error)( &err_extra );
njn4bd67b52005-08-11 00:47:10 +0000573 ai = &err_extra.addrinfo;
574 ai->akind = Mallocd; // Nb: not 'Freed'
575 ai->blksize = mc->size;
576 ai->rwoffset = (Int)a - (Int)mc->data;
577 ai->lastchange = mc->where;
njn72718642003-07-24 08:45:32 +0000578 VG_(maybe_record_error)( tid, FreeMismatchErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000579}
580
sewardj2a99cf62004-11-24 10:44:19 +0000581void MAC_(record_overlap_error) ( ThreadId tid,
582 Char* function, OverlapExtra* ov_extra )
njn66fe05a2003-07-22 09:12:33 +0000583{
sewardj2a99cf62004-11-24 10:44:19 +0000584 VG_(maybe_record_error)(
585 tid, OverlapErr, /*addr*/0, /*s*/function, ov_extra );
njn66fe05a2003-07-22 09:12:33 +0000586}
587
588
njnb6cae9f2003-09-04 20:50:47 +0000589/* Updates the copy with address info if necessary (but not for all errors). */
njn51d827b2005-05-09 01:02:08 +0000590UInt MAC_(update_extra)( Error* err )
njn43c799e2003-04-08 00:08:52 +0000591{
njnb6cae9f2003-09-04 20:50:47 +0000592 switch (VG_(get_error_kind)(err)) {
njn84c91232005-08-11 02:46:54 +0000593 // These two don't have addresses associated with them, and so don't
594 // need any updating.
njnb6cae9f2003-09-04 20:50:47 +0000595 case CoreMemErr:
njn84c91232005-08-11 02:46:54 +0000596 case ValueErr: {
597 MAC_Error* extra = VG_(get_error_extra)(err);
598 tl_assert(Unknown == extra->addrinfo.akind);
599 return sizeof(MAC_Error);
600 }
601
602 // ParamErrs sometimes involve a memory address; call describe_addr() in
603 // this case.
604 case ParamErr: {
605 MAC_Error* extra = VG_(get_error_extra)(err);
606 tl_assert(Undescribed == extra->addrinfo.akind ||
607 Register == extra->addrinfo.akind);
608 if (Undescribed == extra->addrinfo.akind)
609 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
610 return sizeof(MAC_Error);
611 }
612
613 // These four always involve a memory address.
njnb6cae9f2003-09-04 20:50:47 +0000614 case AddrErr:
njnb6cae9f2003-09-04 20:50:47 +0000615 case UserErr:
616 case FreeErr:
njn4bd67b52005-08-11 00:47:10 +0000617 case IllegalMempoolErr: {
nethercote8b76fe52004-11-08 19:20:09 +0000618 MAC_Error* extra = VG_(get_error_extra)(err);
njn84c91232005-08-11 02:46:54 +0000619 tl_assert(Undescribed == extra->addrinfo.akind);
620 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
njnb6cae9f2003-09-04 20:50:47 +0000621 return sizeof(MAC_Error);
622 }
njn4bd67b52005-08-11 00:47:10 +0000623
njn84c91232005-08-11 02:46:54 +0000624 // FreeMismatchErrs have already had their address described; this is
625 // possible because we have the MAC_Chunk on hand when the error is
626 // detected. However, the address may be part of a user block, and if so
627 // we override the pre-determined description with a user block one.
njn4bd67b52005-08-11 00:47:10 +0000628 case FreeMismatchErr: {
629 MAC_Error* extra = VG_(get_error_extra)(err);
630 tl_assert(extra && Mallocd == extra->addrinfo.akind);
njn84c91232005-08-11 02:46:54 +0000631 if (NULL != MAC_(describe_addr_supp))
632 (void)MAC_(describe_addr_supp)( VG_(get_error_address)(err),
633 &(extra->addrinfo) );
njn4bd67b52005-08-11 00:47:10 +0000634 return sizeof(MAC_Error);
635 }
636
njn84c91232005-08-11 02:46:54 +0000637 // No memory address involved with these ones. Nb: for LeakErrs the
638 // returned size does not matter -- LeakErrs are always shown with
639 // VG_(unique_error)() so they're not copied.
njnb6cae9f2003-09-04 20:50:47 +0000640 case LeakErr: return 0;
641 case OverlapErr: return sizeof(OverlapExtra);
njn84c91232005-08-11 02:46:54 +0000642
njn67993252004-11-22 18:02:32 +0000643 default: VG_(tool_panic)("update_extra: bad errkind");
njn43c799e2003-04-08 00:08:52 +0000644 }
njn43c799e2003-04-08 00:08:52 +0000645}
646
647
njn5c004e42002-11-18 11:04:50 +0000648/*------------------------------------------------------------*/
649/*--- Suppressions ---*/
650/*------------------------------------------------------------*/
651
njn43c799e2003-04-08 00:08:52 +0000652Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
653{
654 SuppKind skind;
655
656 if (VG_STREQ(name, "Param")) skind = ParamSupp;
657 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
658 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
659 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
660 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
661 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
njnc0616662003-06-12 09:58:41 +0000662 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
njn43c799e2003-04-08 00:08:52 +0000663 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
664 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
njne9cab142003-09-19 08:10:07 +0000665 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
rjwalshbc0bb832004-06-19 18:12:36 +0000666 else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
njn43c799e2003-04-08 00:08:52 +0000667 else
668 return False;
669
670 VG_(set_supp_kind)(su, skind);
671 return True;
672}
673
njn51d827b2005-05-09 01:02:08 +0000674Bool MAC_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
njn5c004e42002-11-18 11:04:50 +0000675{
676 Bool eof;
677
678 if (VG_(get_supp_kind)(su) == ParamSupp) {
679 eof = VG_(get_line) ( fd, buf, nBuf );
680 if (eof) return False;
681 VG_(set_supp_string)(su, VG_(strdup)(buf));
682 }
683 return True;
684}
685
njn51d827b2005-05-09 01:02:08 +0000686Bool MAC_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000687{
sewardj05bcdcb2003-05-18 10:05:38 +0000688 Int su_size;
njn43c799e2003-04-08 00:08:52 +0000689 MAC_Error* err_extra = VG_(get_error_extra)(err);
690 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000691
692 switch (VG_(get_supp_kind)(su)) {
693 case ParamSupp:
694 return (ekind == ParamErr
njn43c799e2003-04-08 00:08:52 +0000695 && VG_STREQ(VG_(get_error_string)(err),
696 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000697
698 case CoreMemSupp:
699 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000700 && VG_STREQ(VG_(get_error_string)(err),
701 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000702
703 case Value0Supp: su_size = 0; goto value_case;
704 case Value1Supp: su_size = 1; goto value_case;
705 case Value2Supp: su_size = 2; goto value_case;
706 case Value4Supp: su_size = 4; goto value_case;
707 case Value8Supp: su_size = 8; goto value_case;
njnc0616662003-06-12 09:58:41 +0000708 case Value16Supp:su_size =16; goto value_case;
njn5c004e42002-11-18 11:04:50 +0000709 value_case:
710 return (ekind == ValueErr && err_extra->size == su_size);
711
712 case Addr1Supp: su_size = 1; goto addr_case;
713 case Addr2Supp: su_size = 2; goto addr_case;
714 case Addr4Supp: su_size = 4; goto addr_case;
715 case Addr8Supp: su_size = 8; goto addr_case;
njnc0616662003-06-12 09:58:41 +0000716 case Addr16Supp:su_size =16; goto addr_case;
njn5c004e42002-11-18 11:04:50 +0000717 addr_case:
718 return (ekind == AddrErr && err_extra->size == su_size);
719
720 case FreeSupp:
721 return (ekind == FreeErr || ekind == FreeMismatchErr);
722
njn34419c12003-05-02 17:24:29 +0000723 case OverlapSupp:
724 return (ekind = OverlapErr);
725
sewardj4a19e2f2002-12-26 11:50:21 +0000726 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000727 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000728
rjwalshbc0bb832004-06-19 18:12:36 +0000729 case MempoolSupp:
730 return (ekind == IllegalMempoolErr);
731
njn5c004e42002-11-18 11:04:50 +0000732 default:
733 VG_(printf)("Error:\n"
734 " unknown suppression type %d\n",
735 VG_(get_supp_kind)(su));
njn67993252004-11-22 18:02:32 +0000736 VG_(tool_panic)("unknown suppression type in "
njn51d827b2005-05-09 01:02:08 +0000737 "MAC_(error_matches_suppression)");
njn5c004e42002-11-18 11:04:50 +0000738 }
739}
740
njn51d827b2005-05-09 01:02:08 +0000741Char* MAC_(get_error_name) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000742{
743 Char* s;
744 switch (VG_(get_error_kind)(err)) {
745 case ParamErr: return "Param";
746 case UserErr: return NULL; /* Can't suppress User errors */
747 case FreeMismatchErr: return "Free";
rjwalshbc0bb832004-06-19 18:12:36 +0000748 case IllegalMempoolErr: return "Mempool";
njn43c799e2003-04-08 00:08:52 +0000749 case FreeErr: return "Free";
750 case AddrErr:
751 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
752 case 1: return "Addr1";
753 case 2: return "Addr2";
754 case 4: return "Addr4";
755 case 8: return "Addr8";
njnc0616662003-06-12 09:58:41 +0000756 case 16: return "Addr16";
njn67993252004-11-22 18:02:32 +0000757 default: VG_(tool_panic)("unexpected size for Addr");
njn43c799e2003-04-08 00:08:52 +0000758 }
759
760 case ValueErr:
761 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
762 case 0: return "Cond";
763 case 1: return "Value1";
764 case 2: return "Value2";
765 case 4: return "Value4";
766 case 8: return "Value8";
njnc0616662003-06-12 09:58:41 +0000767 case 16: return "Value16";
njn67993252004-11-22 18:02:32 +0000768 default: VG_(tool_panic)("unexpected size for Value");
njn43c799e2003-04-08 00:08:52 +0000769 }
770 case CoreMemErr: return "CoreMem";
njn34419c12003-05-02 17:24:29 +0000771 case OverlapErr: return "Overlap";
njn43c799e2003-04-08 00:08:52 +0000772 case LeakErr: return "Leak";
njn67993252004-11-22 18:02:32 +0000773 default: VG_(tool_panic)("get_error_name: unexpected type");
njn43c799e2003-04-08 00:08:52 +0000774 }
775 VG_(printf)(s);
776}
777
njn51d827b2005-05-09 01:02:08 +0000778void MAC_(print_extra_suppression_info) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000779{
780 if (ParamErr == VG_(get_error_kind)(err)) {
781 VG_(printf)(" %s\n", VG_(get_error_string)(err));
782 }
783}
njn5c004e42002-11-18 11:04:50 +0000784
785/*------------------------------------------------------------*/
786/*--- Crude profiling machinery. ---*/
787/*------------------------------------------------------------*/
788
789/* Event index. If just the name of the fn is given, this means the
790 number of calls to the fn. Otherwise it is the specified event.
791 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
792 The rest are shared.
793
794 10 alloc_secondary_map
795
796 20 get_abit
797M 21 get_vbyte
798 22 set_abit
799M 23 set_vbyte
800 24 get_abits4_ALIGNED
801M 25 get_vbytes4_ALIGNED
802
803 30 set_address_range_perms
804 31 set_address_range_perms(lower byte loop)
805 32 set_address_range_perms(quadword loop)
806 33 set_address_range_perms(upper byte loop)
807
808 35 make_noaccess
809 36 make_writable
810 37 make_readable
811A 38 make_accessible
812
813 40 copy_address_range_state
814 41 copy_address_range_state(byte loop)
815 42 check_writable
816 43 check_writable(byte loop)
817 44 check_readable
818 45 check_readable(byte loop)
819 46 check_readable_asciiz
820 47 check_readable_asciiz(byte loop)
821A 48 check_accessible
822A 49 check_accessible(byte loop)
823
824 50 make_noaccess_aligned
825 51 make_writable_aligned
826
827M 60 helperc_LOADV4
828M 61 helperc_STOREV4
829M 62 helperc_LOADV2
830M 63 helperc_STOREV2
831M 64 helperc_LOADV1
832M 65 helperc_STOREV1
833
834A 66 helperc_ACCESS4
835A 67 helperc_ACCESS2
836A 68 helperc_ACCESS1
837
838M 70 rim_rd_V4_SLOWLY
839M 71 rim_wr_V4_SLOWLY
840M 72 rim_rd_V2_SLOWLY
841M 73 rim_wr_V2_SLOWLY
842M 74 rim_rd_V1_SLOWLY
843M 75 rim_wr_V1_SLOWLY
844
845A 76 ACCESS4_SLOWLY
846A 77 ACCESS2_SLOWLY
847A 78 ACCESS1_SLOWLY
848
849 80 fpu_read
850 81 fpu_read aligned 4
851 82 fpu_read aligned 8
852 83 fpu_read 2
jsewardfca60182004-01-04 23:30:55 +0000853 84 fpu_read 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000854
855M 85 fpu_write
856M 86 fpu_write aligned 4
857M 87 fpu_write aligned 8
858M 88 fpu_write 2
jsewardfca60182004-01-04 23:30:55 +0000859M 89 fpu_write 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000860
861 90 fpu_access
862 91 fpu_access aligned 4
863 92 fpu_access aligned 8
864 93 fpu_access 2
jsewardfca60182004-01-04 23:30:55 +0000865 94 fpu_access 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000866
867 100 fpu_access_check_SLOWLY
868 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000869
870 110 new_mem_stack_4
871 111 new_mem_stack_8
872 112 new_mem_stack_12
873 113 new_mem_stack_16
874 114 new_mem_stack_32
875 115 new_mem_stack
876
877 120 die_mem_stack_4
878 121 die_mem_stack_8
879 122 die_mem_stack_12
880 123 die_mem_stack_16
881 124 die_mem_stack_32
882 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000883*/
884
njn43c799e2003-04-08 00:08:52 +0000885#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000886
sewardjc1a2cda2005-04-21 17:34:00 +0000887UInt MAC_(event_ctr)[N_PROF_EVENTS];
888HChar* MAC_(event_ctr_name)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000889
njnb4aee052003-04-15 14:09:58 +0000890static void init_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000891{
892 Int i;
sewardjc1a2cda2005-04-21 17:34:00 +0000893 for (i = 0; i < N_PROF_EVENTS; i++) {
njn43c799e2003-04-08 00:08:52 +0000894 MAC_(event_ctr)[i] = 0;
sewardjc1a2cda2005-04-21 17:34:00 +0000895 MAC_(event_ctr_name)[i] = NULL;
896 }
njn5c004e42002-11-18 11:04:50 +0000897}
898
njnb4aee052003-04-15 14:09:58 +0000899static void done_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000900{
sewardjc1a2cda2005-04-21 17:34:00 +0000901 Int i;
902 Bool spaced = False;
njn5c004e42002-11-18 11:04:50 +0000903 for (i = 0; i < N_PROF_EVENTS; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +0000904 if (!spaced && (i % 10) == 0) {
njn5c004e42002-11-18 11:04:50 +0000905 VG_(printf)("\n");
sewardjc1a2cda2005-04-21 17:34:00 +0000906 spaced = True;
907 }
908 if (MAC_(event_ctr)[i] > 0) {
909 spaced = False;
910 VG_(printf)( "prof mem event %3d: %9d %s\n",
911 i, MAC_(event_ctr)[i],
912 MAC_(event_ctr_name)[i]
913 ? MAC_(event_ctr_name)[i] : "unnamed");
914 }
njn5c004e42002-11-18 11:04:50 +0000915 }
njn5c004e42002-11-18 11:04:50 +0000916}
917
918#else
919
njnb4aee052003-04-15 14:09:58 +0000920static void init_prof_mem ( void ) { }
921static void done_prof_mem ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000922
njn5c004e42002-11-18 11:04:50 +0000923#endif
924
925/*------------------------------------------------------------*/
njn3e884182003-04-15 13:03:23 +0000926/*--- Common initialisation + finalisation ---*/
927/*------------------------------------------------------------*/
928
929void MAC_(common_pre_clo_init)(void)
930{
njnf69f9452005-07-03 17:53:11 +0000931 MAC_(malloc_list) = VG_(HT_construct)( 80021 ); // prime, big
932 MAC_(mempool_list) = VG_(HT_construct)( 1009 ); // prime, not so big
njn3e884182003-04-15 13:03:23 +0000933 init_prof_mem();
934}
935
njnb8dca862005-03-14 02:42:44 +0000936void MAC_(common_fini)(void (*leak_check)(ThreadId tid, LeakCheckMode mode))
njn3e884182003-04-15 13:03:23 +0000937{
njn86f12dc2005-03-14 01:16:05 +0000938 MAC_(print_malloc_stats)();
njn3e884182003-04-15 13:03:23 +0000939
sewardj71bc3cb2005-05-19 00:25:45 +0000940 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
sewardjb5f6f512005-03-10 23:59:00 +0000941 if (MAC_(clo_leak_check) == LC_Off)
njn3e884182003-04-15 13:03:23 +0000942 VG_(message)(Vg_UserMsg,
943 "For a detailed leak analysis, rerun with: --leak-check=yes");
944
945 VG_(message)(Vg_UserMsg,
946 "For counts of detected errors, rerun with: -v");
947 }
sewardjb5f6f512005-03-10 23:59:00 +0000948 if (MAC_(clo_leak_check) != LC_Off)
njnb8dca862005-03-14 02:42:44 +0000949 leak_check(1/*bogus ThreadId*/, MAC_(clo_leak_check));
njn3e884182003-04-15 13:03:23 +0000950
951 done_prof_mem();
952}
953
954/*------------------------------------------------------------*/
njn47363ab2003-04-21 13:24:40 +0000955/*--- Common client request handling ---*/
956/*------------------------------------------------------------*/
957
nethercoted1b64b22004-11-04 18:22:28 +0000958Bool MAC_(handle_common_client_requests)(ThreadId tid, UWord* arg, UWord* ret )
njn47363ab2003-04-21 13:24:40 +0000959{
njn47363ab2003-04-21 13:24:40 +0000960 switch (arg[0]) {
njn10785452003-05-20 16:38:24 +0000961 case VG_USERREQ__COUNT_LEAKS: { /* count leaked bytes */
nethercoted1b64b22004-11-04 18:22:28 +0000962 UWord** argp = (UWord**)arg;
njne8b5c052003-07-22 22:03:58 +0000963 // MAC_(bytes_leaked) et al were set by the last leak check (or zero
964 // if no prior leak checks performed).
sewardjb5f6f512005-03-10 23:59:00 +0000965 *argp[1] = MAC_(bytes_leaked) + MAC_(bytes_indirect);
njne8b5c052003-07-22 22:03:58 +0000966 *argp[2] = MAC_(bytes_dubious);
967 *argp[3] = MAC_(bytes_reachable);
968 *argp[4] = MAC_(bytes_suppressed);
sewardjb5f6f512005-03-10 23:59:00 +0000969 // there is no argp[5]
970 //*argp[5] = MAC_(bytes_indirect);
971 // XXX need to make *argp[1-4] readable
njn47363ab2003-04-21 13:24:40 +0000972 *ret = 0;
973 return True;
njn10785452003-05-20 16:38:24 +0000974 }
975 case VG_USERREQ__MALLOCLIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000976 Addr p = (Addr)arg[1];
nethercote928a5f72004-11-03 18:10:37 +0000977 SizeT sizeB = arg[2];
njnd7994182003-10-02 13:44:04 +0000978 UInt rzB = arg[3];
979 Bool is_zeroed = (Bool)arg[4];
njn47363ab2003-04-21 13:24:40 +0000980
sewardj2a99cf62004-11-24 10:44:19 +0000981 MAC_(new_block) ( tid, p, sizeB, /*ignored*/0, rzB, is_zeroed,
nethercote57e36b32004-07-10 14:56:28 +0000982 MAC_AllocCustom, MAC_(malloc_list) );
njn10785452003-05-20 16:38:24 +0000983 return True;
984 }
985 case VG_USERREQ__FREELIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000986 Addr p = (Addr)arg[1];
987 UInt rzB = arg[2];
njn10785452003-05-20 16:38:24 +0000988
sewardj2a99cf62004-11-24 10:44:19 +0000989 MAC_(handle_free) ( tid, p, rzB, MAC_AllocCustom );
njn10785452003-05-20 16:38:24 +0000990 return True;
991 }
njnd7994182003-10-02 13:44:04 +0000992
njn1f8b3e72005-03-22 04:27:14 +0000993 case _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR: {
994 Char* s = (Char*) arg[1];
995 OverlapExtra* extra = (OverlapExtra*)arg[2];
996 MAC_(record_overlap_error)(tid, s, extra);
nethercotee3a53722004-05-05 10:46:22 +0000997 return True;
njn1f8b3e72005-03-22 04:27:14 +0000998 }
nethercotee3a53722004-05-05 10:46:22 +0000999
rjwalshbc0bb832004-06-19 18:12:36 +00001000 case VG_USERREQ__CREATE_MEMPOOL: {
1001 Addr pool = (Addr)arg[1];
1002 UInt rzB = arg[2];
1003 Bool is_zeroed = (Bool)arg[3];
1004
1005 MAC_(create_mempool) ( pool, rzB, is_zeroed );
1006 return True;
1007 }
1008
1009 case VG_USERREQ__DESTROY_MEMPOOL: {
1010 Addr pool = (Addr)arg[1];
1011
1012 MAC_(destroy_mempool) ( pool );
1013 return True;
1014 }
1015
1016 case VG_USERREQ__MEMPOOL_ALLOC: {
1017 Addr pool = (Addr)arg[1];
1018 Addr addr = (Addr)arg[2];
1019 UInt size = arg[3];
1020
sewardj2a99cf62004-11-24 10:44:19 +00001021 MAC_(mempool_alloc) ( tid, pool, addr, size );
rjwalshbc0bb832004-06-19 18:12:36 +00001022 return True;
1023 }
1024
1025 case VG_USERREQ__MEMPOOL_FREE: {
1026 Addr pool = (Addr)arg[1];
1027 Addr addr = (Addr)arg[2];
1028
1029 MAC_(mempool_free) ( pool, addr );
1030 return True;
1031 }
1032
njn47363ab2003-04-21 13:24:40 +00001033 default:
1034 return False;
1035 }
1036}
1037
njn5c004e42002-11-18 11:04:50 +00001038/*--------------------------------------------------------------------*/
njn00cae242005-05-09 01:13:44 +00001039/*--- end ---*/
njn5c004e42002-11-18 11:04:50 +00001040/*--------------------------------------------------------------------*/