blob: 8ac8fe9e1e54a46a078f29373d312803263bcc9f [file] [log] [blame]
njn5c004e42002-11-18 11:04:50 +00001
2/*--------------------------------------------------------------------*/
3/*--- Code that is shared between MemCheck and AddrCheck. ---*/
njn00cae242005-05-09 01:13:44 +00004/*--- mac_shared.c ---*/
njn5c004e42002-11-18 11:04:50 +00005/*--------------------------------------------------------------------*/
6
7/*
nethercote137bc552003-11-14 17:47:54 +00008 This file is part of MemCheck, a heavyweight Valgrind tool for
9 detecting memory errors, and AddrCheck, a lightweight Valgrind tool
njn5c004e42002-11-18 11:04:50 +000010 for detecting memory errors.
11
njn53612422005-03-12 16:22:54 +000012 Copyright (C) 2000-2005 Julian Seward
njn5c004e42002-11-18 11:04:50 +000013 jseward@acm.org
14
15 This program is free software; you can redistribute it and/or
16 modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation; either version 2 of the
18 License, or (at your option) any later version.
19
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 02111-1307, USA.
29
30 The GNU General Public License is contained in the file COPYING.
31*/
32
njn43c799e2003-04-08 00:08:52 +000033#include "mac_shared.h"
njn132bfcc2005-06-04 19:16:06 +000034#include "pub_tool_libcassert.h"
njn97405b22005-06-02 03:39:33 +000035#include "pub_tool_libcbase.h"
njn36a20fa2005-06-03 03:08:39 +000036#include "pub_tool_libcprint.h"
njn47363ab2003-04-21 13:24:40 +000037#include "memcheck.h" /* for VG_USERREQ__* */
38
njn5c004e42002-11-18 11:04:50 +000039/*------------------------------------------------------------*/
40/*--- Defns ---*/
41/*------------------------------------------------------------*/
42
43/* These many bytes below %ESP are considered addressible if we're
44 doing the --workaround-gcc296-bugs hack. */
45#define VG_GCC296_BUG_STACK_SLOP 1024
46
47/*------------------------------------------------------------*/
48/*--- Command line options ---*/
49/*------------------------------------------------------------*/
50
sewardjb5f6f512005-03-10 23:59:00 +000051Bool MAC_(clo_partial_loads_ok) = True;
52Int MAC_(clo_freelist_vol) = 1000000;
njn6a329422005-03-12 20:38:13 +000053LeakCheckMode MAC_(clo_leak_check) = LC_Summary;
sewardjb5f6f512005-03-10 23:59:00 +000054VgRes MAC_(clo_leak_resolution) = Vg_LowRes;
55Bool MAC_(clo_show_reachable) = False;
56Bool MAC_(clo_workaround_gcc296_bugs) = False;
njn5c004e42002-11-18 11:04:50 +000057
njn43c799e2003-04-08 00:08:52 +000058Bool MAC_(process_common_cmd_line_option)(Char* arg)
njn5c004e42002-11-18 11:04:50 +000059{
njn45270a22005-03-27 01:00:11 +000060 VG_BOOL_CLO(arg, "--partial-loads-ok", MAC_(clo_partial_loads_ok))
61 else VG_BOOL_CLO(arg, "--show-reachable", MAC_(clo_show_reachable))
62 else VG_BOOL_CLO(arg, "--workaround-gcc296-bugs",MAC_(clo_workaround_gcc296_bugs))
nethercote27fec902004-06-16 21:26:32 +000063
njn45270a22005-03-27 01:00:11 +000064 else VG_BNUM_CLO(arg, "--freelist-vol", MAC_(clo_freelist_vol), 0, 1000000000)
nethercote27fec902004-06-16 21:26:32 +000065
sewardjb5f6f512005-03-10 23:59:00 +000066 else if (VG_CLO_STREQ(arg, "--leak-check=no"))
67 MAC_(clo_leak_check) = LC_Off;
68 else if (VG_CLO_STREQ(arg, "--leak-check=summary"))
69 MAC_(clo_leak_check) = LC_Summary;
70 else if (VG_CLO_STREQ(arg, "--leak-check=yes") ||
71 VG_CLO_STREQ(arg, "--leak-check=full"))
72 MAC_(clo_leak_check) = LC_Full;
73
njn43c799e2003-04-08 00:08:52 +000074 else if (VG_CLO_STREQ(arg, "--leak-resolution=low"))
75 MAC_(clo_leak_resolution) = Vg_LowRes;
76 else if (VG_CLO_STREQ(arg, "--leak-resolution=med"))
77 MAC_(clo_leak_resolution) = Vg_MedRes;
78 else if (VG_CLO_STREQ(arg, "--leak-resolution=high"))
79 MAC_(clo_leak_resolution) = Vg_HighRes;
njn5c004e42002-11-18 11:04:50 +000080
81 else
njn3e884182003-04-15 13:03:23 +000082 return VG_(replacement_malloc_process_cmd_line_option)(arg);
njn5c004e42002-11-18 11:04:50 +000083
84 return True;
njn43c799e2003-04-08 00:08:52 +000085}
njn5c004e42002-11-18 11:04:50 +000086
njn3e884182003-04-15 13:03:23 +000087void MAC_(print_common_usage)(void)
njn43c799e2003-04-08 00:08:52 +000088{
njn3e884182003-04-15 13:03:23 +000089 VG_(printf)(
sewardjb5f6f512005-03-10 23:59:00 +000090" --partial-loads-ok=no|yes too hard to explain here; see manual [yes]\n"
91" --freelist-vol=<number> volume of freed blocks queue [1000000]\n"
njn6a329422005-03-12 20:38:13 +000092" --leak-check=no|summary|full search for memory leaks at exit? [summary]\n"
sewardjb5f6f512005-03-10 23:59:00 +000093" --leak-resolution=low|med|high how much bt merging in leak check [low]\n"
94" --show-reachable=no|yes show reachable blocks in leak check? [no]\n"
njn3e884182003-04-15 13:03:23 +000095" --workaround-gcc296-bugs=no|yes self explanatory [no]\n"
96 );
97 VG_(replacement_malloc_print_usage)();
njn43c799e2003-04-08 00:08:52 +000098}
99
njn3e884182003-04-15 13:03:23 +0000100void MAC_(print_common_debug_usage)(void)
njn43c799e2003-04-08 00:08:52 +0000101{
njn3e884182003-04-15 13:03:23 +0000102 VG_(replacement_malloc_print_debug_usage)();
njn5c004e42002-11-18 11:04:50 +0000103}
104
105/*------------------------------------------------------------*/
106/*--- Comparing and printing errors ---*/
107/*------------------------------------------------------------*/
108
109static __inline__
110void clear_AddrInfo ( AddrInfo* ai )
111{
112 ai->akind = Unknown;
113 ai->blksize = 0;
114 ai->rwoffset = 0;
115 ai->lastchange = NULL;
116 ai->stack_tid = VG_INVALID_THREADID;
117 ai->maybe_gcc = False;
sewardjb5f6f512005-03-10 23:59:00 +0000118 ai->desc = NULL;
njn5c004e42002-11-18 11:04:50 +0000119}
120
njn43c799e2003-04-08 00:08:52 +0000121void MAC_(clear_MAC_Error) ( MAC_Error* err_extra )
njn5c004e42002-11-18 11:04:50 +0000122{
123 err_extra->axskind = ReadAxs;
124 err_extra->size = 0;
125 clear_AddrInfo ( &err_extra->addrinfo );
nethercote8b76fe52004-11-08 19:20:09 +0000126 err_extra->isUnaddr = True;
njn5c004e42002-11-18 11:04:50 +0000127}
128
129__attribute__ ((unused))
130static Bool eq_AddrInfo ( VgRes res, AddrInfo* ai1, AddrInfo* ai2 )
131{
132 if (ai1->akind != Undescribed
133 && ai2->akind != Undescribed
134 && ai1->akind != ai2->akind)
135 return False;
136 if (ai1->akind == Freed || ai1->akind == Mallocd) {
137 if (ai1->blksize != ai2->blksize)
138 return False;
139 if (!VG_(eq_ExeContext)(res, ai1->lastchange, ai2->lastchange))
140 return False;
141 }
142 return True;
143}
144
145/* Compare error contexts, to detect duplicates. Note that if they
146 are otherwise the same, the faulting addrs and associated rwoffsets
147 are allowed to be different. */
148
njn51d827b2005-05-09 01:02:08 +0000149Bool MAC_(eq_Error) ( VgRes res, Error* e1, Error* e2 )
njn5c004e42002-11-18 11:04:50 +0000150{
njn43c799e2003-04-08 00:08:52 +0000151 MAC_Error* e1_extra = VG_(get_error_extra)(e1);
152 MAC_Error* e2_extra = VG_(get_error_extra)(e2);
njn7cc53a82002-11-19 16:19:32 +0000153
154 /* Guaranteed by calling function */
njnca82cc02004-11-22 17:18:48 +0000155 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
njn5c004e42002-11-18 11:04:50 +0000156
157 switch (VG_(get_error_kind)(e1)) {
158 case CoreMemErr: {
159 Char *e1s, *e2s;
nethercote8b76fe52004-11-08 19:20:09 +0000160 if (e1_extra->isUnaddr != e2_extra->isUnaddr) return False;
njn5c004e42002-11-18 11:04:50 +0000161 e1s = VG_(get_error_string)(e1);
162 e2s = VG_(get_error_string)(e2);
163 if (e1s == e2s) return True;
164 if (0 == VG_(strcmp)(e1s, e2s)) return True;
165 return False;
166 }
167
njn16390462005-05-08 15:26:00 +0000168 // Perhaps we should also check the addrinfo.akinds for equality.
169 // That would result in more error reports, but only in cases where
170 // a register contains uninitialised bytes and points to memory
171 // containing uninitialised bytes. Currently, the 2nd of those to be
172 // detected won't be reported. That is (nearly?) always the memory
173 // error, which is good.
njn5c004e42002-11-18 11:04:50 +0000174 case ParamErr:
njn16390462005-05-08 15:26:00 +0000175 if (0 != VG_(strcmp)(VG_(get_error_string)(e1),
176 VG_(get_error_string)(e2))) return False;
177 // fall through
178 case UserErr:
179 if (e1_extra->isUnaddr != e2_extra->isUnaddr) return False;
njn5c004e42002-11-18 11:04:50 +0000180 return True;
181
182 case FreeErr:
183 case FreeMismatchErr:
184 /* JRS 2002-Aug-26: comparing addrs seems overkill and can
185 cause excessive duplication of errors. Not even AddrErr
186 below does that. So don't compare either the .addr field
187 or the .addrinfo fields. */
188 /* if (e1->addr != e2->addr) return False; */
189 /* if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
190 return False;
191 */
192 return True;
193
194 case AddrErr:
195 /* if (e1_extra->axskind != e2_extra->axskind) return False; */
196 if (e1_extra->size != e2_extra->size) return False;
197 /*
198 if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
199 return False;
200 */
201 return True;
202
203 case ValueErr:
204 if (e1_extra->size != e2_extra->size) return False;
205 return True;
206
njn34419c12003-05-02 17:24:29 +0000207 case OverlapErr:
208 return True;
209
njn43c799e2003-04-08 00:08:52 +0000210 case LeakErr:
njn51d827b2005-05-09 01:02:08 +0000211 VG_(tool_panic)("Shouldn't get LeakErr in MAC_(eq_Error),\n"
njn43c799e2003-04-08 00:08:52 +0000212 "since it's handled with VG_(unique_error)()!");
213
rjwalshbc0bb832004-06-19 18:12:36 +0000214 case IllegalMempoolErr:
215 return True;
216
njn5c004e42002-11-18 11:04:50 +0000217 default:
218 VG_(printf)("Error:\n unknown error code %d\n",
219 VG_(get_error_kind)(e1));
njn51d827b2005-05-09 01:02:08 +0000220 VG_(tool_panic)("unknown error code in MAC_(eq_Error)");
njn5c004e42002-11-18 11:04:50 +0000221 }
222}
223
njn43c799e2003-04-08 00:08:52 +0000224void MAC_(pp_AddrInfo) ( Addr a, AddrInfo* ai )
njn5c004e42002-11-18 11:04:50 +0000225{
sewardj71bc3cb2005-05-19 00:25:45 +0000226 HChar* xpre = VG_(clo_xml) ? " <auxwhat>" : " ";
227 HChar* xpost = VG_(clo_xml) ? "</auxwhat>" : "";
228
njn5c004e42002-11-18 11:04:50 +0000229 switch (ai->akind) {
230 case Stack:
231 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000232 "%sAddress 0x%llx is on thread %d's stack%s",
233 xpre, (ULong)a, ai->stack_tid, xpost);
njn5c004e42002-11-18 11:04:50 +0000234 break;
235 case Unknown:
236 if (ai->maybe_gcc) {
237 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000238 "%sAddress 0x%llx is just below the stack ptr. "
239 "To suppress, use: --workaround-gcc296-bugs=yes%s",
240 xpre, (ULong)a, xpost
241 );
njn5c004e42002-11-18 11:04:50 +0000242 } else {
243 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000244 "%sAddress 0x%llx "
245 "is not stack'd, malloc'd or (recently) free'd%s",
246 xpre, (ULong)a, xpost);
njn5c004e42002-11-18 11:04:50 +0000247 }
248 break;
rjwalshbc0bb832004-06-19 18:12:36 +0000249 case Freed: case Mallocd: case UserG: case Mempool: {
nethercote50397c22004-11-04 18:03:06 +0000250 SizeT delta;
sewardjb5f6f512005-03-10 23:59:00 +0000251 const Char* relative;
252 const Char* kind;
rjwalshbc0bb832004-06-19 18:12:36 +0000253 if (ai->akind == Mempool) {
254 kind = "mempool";
255 } else {
256 kind = "block";
257 }
sewardjb5f6f512005-03-10 23:59:00 +0000258 if (ai->desc != NULL)
259 kind = ai->desc;
260
njn5c004e42002-11-18 11:04:50 +0000261 if (ai->rwoffset < 0) {
nethercote50397c22004-11-04 18:03:06 +0000262 delta = (SizeT)(- ai->rwoffset);
njn5c004e42002-11-18 11:04:50 +0000263 relative = "before";
264 } else if (ai->rwoffset >= ai->blksize) {
265 delta = ai->rwoffset - ai->blksize;
266 relative = "after";
267 } else {
268 delta = ai->rwoffset;
269 relative = "inside";
270 }
sewardja81709d2002-12-28 12:55:48 +0000271 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000272 "%sAddress 0x%llx is %llu bytes %s a %s of size %d %s%s",
273 xpre,
tom14ea6852005-05-03 18:16:12 +0000274 (ULong)a, (ULong)delta, relative, kind,
sewardja81709d2002-12-28 12:55:48 +0000275 ai->blksize,
276 ai->akind==Mallocd ? "alloc'd"
277 : ai->akind==Freed ? "free'd"
sewardj71bc3cb2005-05-19 00:25:45 +0000278 : "client-defined",
279 xpost);
njn5c004e42002-11-18 11:04:50 +0000280 VG_(pp_ExeContext)(ai->lastchange);
281 break;
282 }
nethercote8b76fe52004-11-08 19:20:09 +0000283 case Register:
284 // print nothing
njnca82cc02004-11-22 17:18:48 +0000285 tl_assert(0 == a);
nethercote8b76fe52004-11-08 19:20:09 +0000286 break;
njn5c004e42002-11-18 11:04:50 +0000287 default:
njn67993252004-11-22 18:02:32 +0000288 VG_(tool_panic)("MAC_(pp_AddrInfo)");
njn43c799e2003-04-08 00:08:52 +0000289 }
290}
291
292/* This prints out the message for the error types where Memcheck and
293 Addrcheck have identical messages */
njnb126f732004-11-22 17:57:07 +0000294void MAC_(pp_shared_Error) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000295{
296 MAC_Error* err_extra = VG_(get_error_extra)(err);
297
sewardj71bc3cb2005-05-19 00:25:45 +0000298 HChar* xpre = VG_(clo_xml) ? " <what>" : "";
299 HChar* xpost = VG_(clo_xml) ? "</what>" : "";
300
njn43c799e2003-04-08 00:08:52 +0000301 switch (VG_(get_error_kind)(err)) {
302 case FreeErr:
sewardj71bc3cb2005-05-19 00:25:45 +0000303 if (VG_(clo_xml))
304 VG_(message)(Vg_UserMsg, " <kind>InvalidFree</kind>");
305 VG_(message)(Vg_UserMsg,
306 "%sInvalid free() / delete / delete[]%s",
307 xpre, xpost);
308 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
309 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
310 break;
311
njn43c799e2003-04-08 00:08:52 +0000312 case FreeMismatchErr:
sewardj71bc3cb2005-05-19 00:25:45 +0000313 if (VG_(clo_xml))
314 VG_(message)(Vg_UserMsg, " <kind>MismatchedFree</kind>");
315 VG_(message)(Vg_UserMsg,
316 "%sMismatched free() / delete / delete []%s",
317 xpre, xpost);
njn43c799e2003-04-08 00:08:52 +0000318 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
319 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
320 break;
321
njn89409f82003-09-26 14:55:31 +0000322 case AddrErr:
323 switch (err_extra->axskind) {
324 case ReadAxs:
sewardj71bc3cb2005-05-19 00:25:45 +0000325 if (VG_(clo_xml))
326 VG_(message)(Vg_UserMsg, " <kind>InvalidRead</kind>");
327 VG_(message)(Vg_UserMsg,
328 "%sInvalid read of size %d%s",
329 xpre, err_extra->size, xpost );
njn89409f82003-09-26 14:55:31 +0000330 break;
331 case WriteAxs:
sewardj71bc3cb2005-05-19 00:25:45 +0000332 if (VG_(clo_xml))
333 VG_(message)(Vg_UserMsg, " <kind>InvalidWrite</kind>");
334 VG_(message)(Vg_UserMsg,
335 "%sInvalid write of size %d%s",
336 xpre, err_extra->size, xpost );
njn89409f82003-09-26 14:55:31 +0000337 break;
338 case ExecAxs:
sewardj71bc3cb2005-05-19 00:25:45 +0000339 if (VG_(clo_xml))
340 VG_(message)(Vg_UserMsg, " <kind>InvalidJump</kind>");
341 VG_(message)(Vg_UserMsg,
342 "%sJump to the invalid address "
343 "stated on the next line%s",
344 xpre, xpost);
njn89409f82003-09-26 14:55:31 +0000345 break;
346 default:
njn51d827b2005-05-09 01:02:08 +0000347 VG_(tool_panic)("MAC_(pp_shared_Error)(axskind)");
njn89409f82003-09-26 14:55:31 +0000348 }
349 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
350 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
351 break;
352
njnb6cae9f2003-09-04 20:50:47 +0000353 case OverlapErr: {
354 OverlapExtra* ov_extra = (OverlapExtra*)VG_(get_error_extra)(err);
sewardj71bc3cb2005-05-19 00:25:45 +0000355 if (VG_(clo_xml))
356 VG_(message)(Vg_UserMsg, " <kind>Overlap</kind>");
njnb6cae9f2003-09-04 20:50:47 +0000357 if (ov_extra->len == -1)
358 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000359 "%sSource and destination overlap in %s(%p, %p)%s",
360 xpre,
njnb6cae9f2003-09-04 20:50:47 +0000361 VG_(get_error_string)(err),
sewardj71bc3cb2005-05-19 00:25:45 +0000362 ov_extra->dst, ov_extra->src,
363 xpost);
njnb6cae9f2003-09-04 20:50:47 +0000364 else
365 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000366 "%sSource and destination overlap in %s(%p, %p, %d)%s",
367 xpre,
njnb6cae9f2003-09-04 20:50:47 +0000368 VG_(get_error_string)(err),
sewardj71bc3cb2005-05-19 00:25:45 +0000369 ov_extra->dst, ov_extra->src, ov_extra->len,
370 xpost);
njn66fe05a2003-07-22 09:12:33 +0000371 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
372 break;
njnb6cae9f2003-09-04 20:50:47 +0000373 }
njn43c799e2003-04-08 00:08:52 +0000374 case LeakErr: {
njn02977032005-05-17 04:00:11 +0000375 MAC_(pp_LeakError)(err_extra);
njn43c799e2003-04-08 00:08:52 +0000376 break;
377 }
378
rjwalshbc0bb832004-06-19 18:12:36 +0000379 case IllegalMempoolErr:
sewardj71bc3cb2005-05-19 00:25:45 +0000380 if (VG_(clo_xml))
381 VG_(message)(Vg_UserMsg, " <kind>InvalidMemPool</kind>");
382 VG_(message)(Vg_UserMsg, "%sIllegal memory pool address%s",
383 xpre, xpost);
rjwalshbc0bb832004-06-19 18:12:36 +0000384 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
385 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
386 break;
387
njn43c799e2003-04-08 00:08:52 +0000388 default:
389 VG_(printf)("Error:\n unknown Memcheck/Addrcheck error code %d\n",
390 VG_(get_error_kind)(err));
njn67993252004-11-22 18:02:32 +0000391 VG_(tool_panic)("unknown error code in MAC_(pp_shared_Error)");
njn5c004e42002-11-18 11:04:50 +0000392 }
393}
394
395/*------------------------------------------------------------*/
396/*--- Recording errors ---*/
397/*------------------------------------------------------------*/
398
njn43c799e2003-04-08 00:08:52 +0000399/* Additional description function for describe_addr(); used by
400 MemCheck for user blocks, which Addrcheck doesn't support. */
401Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL;
thughes4ad52d02004-06-27 17:37:21 +0000402
403/* Callback for searching thread stacks */
404static Bool addr_is_in_bounds(Addr stack_min, Addr stack_max, void *ap)
405{
406 Addr a = *(Addr *)ap;
407
408 return (stack_min <= a && a <= stack_max);
409}
410
411/* Callback for searching free'd list */
412static Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc, void *ap)
413{
414 Addr a = *(Addr *)ap;
415
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
420/* Callback for searching malloc'd lists */
421static Bool addr_is_in_HashNode(VgHashNode* sh_ch, void *ap)
422{
423 return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch, ap );
424}
425
njn43c799e2003-04-08 00:08:52 +0000426/* Describe an address as best you can, for error messages,
427 putting the result in ai. */
428static void describe_addr ( Addr a, AddrInfo* ai )
429{
njn3e884182003-04-15 13:03:23 +0000430 MAC_Chunk* sc;
431 ThreadId tid;
njn43c799e2003-04-08 00:08:52 +0000432
njn43c799e2003-04-08 00:08:52 +0000433 /* Perhaps it's a user-def'd block ? (only check if requested, though) */
434 if (NULL != MAC_(describe_addr_supp)) {
435 if (MAC_(describe_addr_supp)( a, ai ))
436 return;
437 }
438 /* Perhaps it's on a thread's stack? */
thughes4ad52d02004-06-27 17:37:21 +0000439 tid = VG_(first_matching_thread_stack)(addr_is_in_bounds, &a);
njn43c799e2003-04-08 00:08:52 +0000440 if (tid != VG_INVALID_THREADID) {
441 ai->akind = Stack;
442 ai->stack_tid = tid;
443 return;
444 }
445 /* Search for a recently freed block which might bracket it. */
thughes4ad52d02004-06-27 17:37:21 +0000446 sc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk, &a);
njn3e884182003-04-15 13:03:23 +0000447 if (NULL != sc) {
njn43c799e2003-04-08 00:08:52 +0000448 ai->akind = Freed;
njn3e884182003-04-15 13:03:23 +0000449 ai->blksize = sc->size;
450 ai->rwoffset = (Int)a - (Int)sc->data;
451 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000452 return;
453 }
454 /* Search for a currently malloc'd block which might bracket it. */
thughes4ad52d02004-06-27 17:37:21 +0000455 sc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode, &a);
njn43c799e2003-04-08 00:08:52 +0000456 if (NULL != sc) {
457 ai->akind = Mallocd;
njn3e884182003-04-15 13:03:23 +0000458 ai->blksize = sc->size;
459 ai->rwoffset = (Int)(a) - (Int)sc->data;
460 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000461 return;
462 }
463 /* Clueless ... */
464 ai->akind = Unknown;
465 return;
466}
467
njn5c004e42002-11-18 11:04:50 +0000468/* Is this address within some small distance below %ESP? Used only
469 for the --workaround-gcc296-bugs kludge. */
470static Bool is_just_below_ESP( Addr esp, Addr aa )
471{
nethercote50397c22004-11-04 18:03:06 +0000472 if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
njn5c004e42002-11-18 11:04:50 +0000473 return True;
474 else
475 return False;
476}
477
sewardjaf48a602003-07-06 00:54:47 +0000478/* This one called from generated code and non-generated code. */
njn5c004e42002-11-18 11:04:50 +0000479
njn72718642003-07-24 08:45:32 +0000480void MAC_(record_address_error) ( ThreadId tid, Addr a, Int size,
sewardjaf48a602003-07-06 00:54:47 +0000481 Bool isWrite )
njn5c004e42002-11-18 11:04:50 +0000482{
njn43c799e2003-04-08 00:08:52 +0000483 MAC_Error err_extra;
484 Bool just_below_esp;
njn5c004e42002-11-18 11:04:50 +0000485
njn67516132005-03-22 04:02:43 +0000486 just_below_esp = is_just_below_ESP( VG_(get_SP)(tid), a );
njn5c004e42002-11-18 11:04:50 +0000487
488 /* If this is caused by an access immediately below %ESP, and the
489 user asks nicely, we just ignore it. */
njn43c799e2003-04-08 00:08:52 +0000490 if (MAC_(clo_workaround_gcc296_bugs) && just_below_esp)
njn5c004e42002-11-18 11:04:50 +0000491 return;
492
njn43c799e2003-04-08 00:08:52 +0000493 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000494 err_extra.axskind = isWrite ? WriteAxs : ReadAxs;
495 err_extra.size = size;
496 err_extra.addrinfo.akind = Undescribed;
497 err_extra.addrinfo.maybe_gcc = just_below_esp;
njn72718642003-07-24 08:45:32 +0000498 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000499}
500
501/* These ones are called from non-generated code */
502
503/* This is for memory errors in pthread functions, as opposed to pthread API
504 errors which are found by the core. */
nethercote8b76fe52004-11-08 19:20:09 +0000505void MAC_(record_core_mem_error) ( ThreadId tid, Bool isUnaddr, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000506{
njn43c799e2003-04-08 00:08:52 +0000507 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000508
njn43c799e2003-04-08 00:08:52 +0000509 MAC_(clear_MAC_Error)( &err_extra );
nethercote8b76fe52004-11-08 19:20:09 +0000510 err_extra.isUnaddr = isUnaddr;
njn72718642003-07-24 08:45:32 +0000511 VG_(maybe_record_error)( tid, CoreMemErr, /*addr*/0, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000512}
513
njn16390462005-05-08 15:26:00 +0000514// Three kinds of param errors:
515// - register arg contains undefined bytes
516// - memory arg is unaddressable
517// - memory arg contains undefined bytes
518// 'isReg' and 'isUnaddr' dictate which of these it is.
nethercote8b76fe52004-11-08 19:20:09 +0000519void MAC_(record_param_error) ( ThreadId tid, Addr a, Bool isReg,
520 Bool isUnaddr, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000521{
njn43c799e2003-04-08 00:08:52 +0000522 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000523
njnca82cc02004-11-22 17:18:48 +0000524 tl_assert(VG_INVALID_THREADID != tid);
njn16390462005-05-08 15:26:00 +0000525 if (isUnaddr) tl_assert(!isReg); // unaddressable register is impossible
njn43c799e2003-04-08 00:08:52 +0000526 MAC_(clear_MAC_Error)( &err_extra );
nethercote8b76fe52004-11-08 19:20:09 +0000527 err_extra.addrinfo.akind = ( isReg ? Register : Undescribed );
528 err_extra.isUnaddr = isUnaddr;
njn72718642003-07-24 08:45:32 +0000529 VG_(maybe_record_error)( tid, ParamErr, a, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000530}
531
njn72718642003-07-24 08:45:32 +0000532void MAC_(record_jump_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000533{
njn43c799e2003-04-08 00:08:52 +0000534 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000535
njnca82cc02004-11-22 17:18:48 +0000536 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000537 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000538 err_extra.axskind = ExecAxs;
nethercote7250b8f2004-04-13 08:47:35 +0000539 err_extra.size = 1; // size only used for suppressions
njn5c004e42002-11-18 11:04:50 +0000540 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000541 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000542}
543
njn72718642003-07-24 08:45:32 +0000544void MAC_(record_free_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000545{
njn43c799e2003-04-08 00:08:52 +0000546 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000547
njnca82cc02004-11-22 17:18:48 +0000548 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000549 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000550 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000551 VG_(maybe_record_error)( tid, FreeErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000552}
553
rjwalshbc0bb832004-06-19 18:12:36 +0000554void MAC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )
555{
556 MAC_Error err_extra;
557
njnca82cc02004-11-22 17:18:48 +0000558 tl_assert(VG_INVALID_THREADID != tid);
rjwalshbc0bb832004-06-19 18:12:36 +0000559 MAC_(clear_MAC_Error)( &err_extra );
560 err_extra.addrinfo.akind = Undescribed;
561 VG_(maybe_record_error)( tid, IllegalMempoolErr, a, /*s*/NULL, &err_extra );
562}
563
njn72718642003-07-24 08:45:32 +0000564void MAC_(record_freemismatch_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000565{
njn43c799e2003-04-08 00:08:52 +0000566 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000567
njnca82cc02004-11-22 17:18:48 +0000568 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000569 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000570 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000571 VG_(maybe_record_error)( tid, FreeMismatchErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000572}
573
sewardj2a99cf62004-11-24 10:44:19 +0000574void MAC_(record_overlap_error) ( ThreadId tid,
575 Char* function, OverlapExtra* ov_extra )
njn66fe05a2003-07-22 09:12:33 +0000576{
sewardj2a99cf62004-11-24 10:44:19 +0000577 VG_(maybe_record_error)(
578 tid, OverlapErr, /*addr*/0, /*s*/function, ov_extra );
njn66fe05a2003-07-22 09:12:33 +0000579}
580
581
njnb6cae9f2003-09-04 20:50:47 +0000582/* Updates the copy with address info if necessary (but not for all errors). */
njn51d827b2005-05-09 01:02:08 +0000583UInt MAC_(update_extra)( Error* err )
njn43c799e2003-04-08 00:08:52 +0000584{
njnb6cae9f2003-09-04 20:50:47 +0000585 switch (VG_(get_error_kind)(err)) {
586 case ValueErr:
587 case CoreMemErr:
588 case AddrErr:
589 case ParamErr:
590 case UserErr:
591 case FreeErr:
rjwalshbc0bb832004-06-19 18:12:36 +0000592 case IllegalMempoolErr:
njnb6cae9f2003-09-04 20:50:47 +0000593 case FreeMismatchErr: {
nethercote8b76fe52004-11-08 19:20:09 +0000594 MAC_Error* extra = VG_(get_error_extra)(err);
njnb6cae9f2003-09-04 20:50:47 +0000595 if (extra != NULL && Undescribed == extra->addrinfo.akind) {
596 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
597 }
598 return sizeof(MAC_Error);
599 }
njn43c799e2003-04-08 00:08:52 +0000600 /* Don't need to return the correct size -- LeakErrs are always shown with
601 VG_(unique_error)() so they're not copied anyway. */
njnb6cae9f2003-09-04 20:50:47 +0000602 case LeakErr: return 0;
603 case OverlapErr: return sizeof(OverlapExtra);
njn67993252004-11-22 18:02:32 +0000604 default: VG_(tool_panic)("update_extra: bad errkind");
njn43c799e2003-04-08 00:08:52 +0000605 }
njn43c799e2003-04-08 00:08:52 +0000606}
607
608
njn5c004e42002-11-18 11:04:50 +0000609/*------------------------------------------------------------*/
610/*--- Suppressions ---*/
611/*------------------------------------------------------------*/
612
njn43c799e2003-04-08 00:08:52 +0000613Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
614{
615 SuppKind skind;
616
617 if (VG_STREQ(name, "Param")) skind = ParamSupp;
618 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
619 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
620 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
621 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
622 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
njnc0616662003-06-12 09:58:41 +0000623 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
njn43c799e2003-04-08 00:08:52 +0000624 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
625 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
njne9cab142003-09-19 08:10:07 +0000626 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
rjwalshbc0bb832004-06-19 18:12:36 +0000627 else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
njn43c799e2003-04-08 00:08:52 +0000628 else
629 return False;
630
631 VG_(set_supp_kind)(su, skind);
632 return True;
633}
634
njn51d827b2005-05-09 01:02:08 +0000635Bool MAC_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
njn5c004e42002-11-18 11:04:50 +0000636{
637 Bool eof;
638
639 if (VG_(get_supp_kind)(su) == ParamSupp) {
640 eof = VG_(get_line) ( fd, buf, nBuf );
641 if (eof) return False;
642 VG_(set_supp_string)(su, VG_(strdup)(buf));
643 }
644 return True;
645}
646
njn51d827b2005-05-09 01:02:08 +0000647Bool MAC_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000648{
sewardj05bcdcb2003-05-18 10:05:38 +0000649 Int su_size;
njn43c799e2003-04-08 00:08:52 +0000650 MAC_Error* err_extra = VG_(get_error_extra)(err);
651 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000652
653 switch (VG_(get_supp_kind)(su)) {
654 case ParamSupp:
655 return (ekind == ParamErr
njn43c799e2003-04-08 00:08:52 +0000656 && VG_STREQ(VG_(get_error_string)(err),
657 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000658
659 case CoreMemSupp:
660 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000661 && VG_STREQ(VG_(get_error_string)(err),
662 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000663
664 case Value0Supp: su_size = 0; goto value_case;
665 case Value1Supp: su_size = 1; goto value_case;
666 case Value2Supp: su_size = 2; goto value_case;
667 case Value4Supp: su_size = 4; goto value_case;
668 case Value8Supp: su_size = 8; goto value_case;
njnc0616662003-06-12 09:58:41 +0000669 case Value16Supp:su_size =16; goto value_case;
njn5c004e42002-11-18 11:04:50 +0000670 value_case:
671 return (ekind == ValueErr && err_extra->size == su_size);
672
673 case Addr1Supp: su_size = 1; goto addr_case;
674 case Addr2Supp: su_size = 2; goto addr_case;
675 case Addr4Supp: su_size = 4; goto addr_case;
676 case Addr8Supp: su_size = 8; goto addr_case;
njnc0616662003-06-12 09:58:41 +0000677 case Addr16Supp:su_size =16; goto addr_case;
njn5c004e42002-11-18 11:04:50 +0000678 addr_case:
679 return (ekind == AddrErr && err_extra->size == su_size);
680
681 case FreeSupp:
682 return (ekind == FreeErr || ekind == FreeMismatchErr);
683
njn34419c12003-05-02 17:24:29 +0000684 case OverlapSupp:
685 return (ekind = OverlapErr);
686
sewardj4a19e2f2002-12-26 11:50:21 +0000687 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000688 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000689
rjwalshbc0bb832004-06-19 18:12:36 +0000690 case MempoolSupp:
691 return (ekind == IllegalMempoolErr);
692
njn5c004e42002-11-18 11:04:50 +0000693 default:
694 VG_(printf)("Error:\n"
695 " unknown suppression type %d\n",
696 VG_(get_supp_kind)(su));
njn67993252004-11-22 18:02:32 +0000697 VG_(tool_panic)("unknown suppression type in "
njn51d827b2005-05-09 01:02:08 +0000698 "MAC_(error_matches_suppression)");
njn5c004e42002-11-18 11:04:50 +0000699 }
700}
701
njn51d827b2005-05-09 01:02:08 +0000702Char* MAC_(get_error_name) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000703{
704 Char* s;
705 switch (VG_(get_error_kind)(err)) {
706 case ParamErr: return "Param";
707 case UserErr: return NULL; /* Can't suppress User errors */
708 case FreeMismatchErr: return "Free";
rjwalshbc0bb832004-06-19 18:12:36 +0000709 case IllegalMempoolErr: return "Mempool";
njn43c799e2003-04-08 00:08:52 +0000710 case FreeErr: return "Free";
711 case AddrErr:
712 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
713 case 1: return "Addr1";
714 case 2: return "Addr2";
715 case 4: return "Addr4";
716 case 8: return "Addr8";
njnc0616662003-06-12 09:58:41 +0000717 case 16: return "Addr16";
njn67993252004-11-22 18:02:32 +0000718 default: VG_(tool_panic)("unexpected size for Addr");
njn43c799e2003-04-08 00:08:52 +0000719 }
720
721 case ValueErr:
722 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
723 case 0: return "Cond";
724 case 1: return "Value1";
725 case 2: return "Value2";
726 case 4: return "Value4";
727 case 8: return "Value8";
njnc0616662003-06-12 09:58:41 +0000728 case 16: return "Value16";
njn67993252004-11-22 18:02:32 +0000729 default: VG_(tool_panic)("unexpected size for Value");
njn43c799e2003-04-08 00:08:52 +0000730 }
731 case CoreMemErr: return "CoreMem";
njn34419c12003-05-02 17:24:29 +0000732 case OverlapErr: return "Overlap";
njn43c799e2003-04-08 00:08:52 +0000733 case LeakErr: return "Leak";
njn67993252004-11-22 18:02:32 +0000734 default: VG_(tool_panic)("get_error_name: unexpected type");
njn43c799e2003-04-08 00:08:52 +0000735 }
736 VG_(printf)(s);
737}
738
njn51d827b2005-05-09 01:02:08 +0000739void MAC_(print_extra_suppression_info) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000740{
741 if (ParamErr == VG_(get_error_kind)(err)) {
742 VG_(printf)(" %s\n", VG_(get_error_string)(err));
743 }
744}
njn5c004e42002-11-18 11:04:50 +0000745
746/*------------------------------------------------------------*/
747/*--- Crude profiling machinery. ---*/
748/*------------------------------------------------------------*/
749
750/* Event index. If just the name of the fn is given, this means the
751 number of calls to the fn. Otherwise it is the specified event.
752 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
753 The rest are shared.
754
755 10 alloc_secondary_map
756
757 20 get_abit
758M 21 get_vbyte
759 22 set_abit
760M 23 set_vbyte
761 24 get_abits4_ALIGNED
762M 25 get_vbytes4_ALIGNED
763
764 30 set_address_range_perms
765 31 set_address_range_perms(lower byte loop)
766 32 set_address_range_perms(quadword loop)
767 33 set_address_range_perms(upper byte loop)
768
769 35 make_noaccess
770 36 make_writable
771 37 make_readable
772A 38 make_accessible
773
774 40 copy_address_range_state
775 41 copy_address_range_state(byte loop)
776 42 check_writable
777 43 check_writable(byte loop)
778 44 check_readable
779 45 check_readable(byte loop)
780 46 check_readable_asciiz
781 47 check_readable_asciiz(byte loop)
782A 48 check_accessible
783A 49 check_accessible(byte loop)
784
785 50 make_noaccess_aligned
786 51 make_writable_aligned
787
788M 60 helperc_LOADV4
789M 61 helperc_STOREV4
790M 62 helperc_LOADV2
791M 63 helperc_STOREV2
792M 64 helperc_LOADV1
793M 65 helperc_STOREV1
794
795A 66 helperc_ACCESS4
796A 67 helperc_ACCESS2
797A 68 helperc_ACCESS1
798
799M 70 rim_rd_V4_SLOWLY
800M 71 rim_wr_V4_SLOWLY
801M 72 rim_rd_V2_SLOWLY
802M 73 rim_wr_V2_SLOWLY
803M 74 rim_rd_V1_SLOWLY
804M 75 rim_wr_V1_SLOWLY
805
806A 76 ACCESS4_SLOWLY
807A 77 ACCESS2_SLOWLY
808A 78 ACCESS1_SLOWLY
809
810 80 fpu_read
811 81 fpu_read aligned 4
812 82 fpu_read aligned 8
813 83 fpu_read 2
jsewardfca60182004-01-04 23:30:55 +0000814 84 fpu_read 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000815
816M 85 fpu_write
817M 86 fpu_write aligned 4
818M 87 fpu_write aligned 8
819M 88 fpu_write 2
jsewardfca60182004-01-04 23:30:55 +0000820M 89 fpu_write 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000821
822 90 fpu_access
823 91 fpu_access aligned 4
824 92 fpu_access aligned 8
825 93 fpu_access 2
jsewardfca60182004-01-04 23:30:55 +0000826 94 fpu_access 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000827
828 100 fpu_access_check_SLOWLY
829 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000830
831 110 new_mem_stack_4
832 111 new_mem_stack_8
833 112 new_mem_stack_12
834 113 new_mem_stack_16
835 114 new_mem_stack_32
836 115 new_mem_stack
837
838 120 die_mem_stack_4
839 121 die_mem_stack_8
840 122 die_mem_stack_12
841 123 die_mem_stack_16
842 124 die_mem_stack_32
843 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000844*/
845
njn43c799e2003-04-08 00:08:52 +0000846#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000847
sewardjc1a2cda2005-04-21 17:34:00 +0000848UInt MAC_(event_ctr)[N_PROF_EVENTS];
849HChar* MAC_(event_ctr_name)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000850
njnb4aee052003-04-15 14:09:58 +0000851static void init_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000852{
853 Int i;
sewardjc1a2cda2005-04-21 17:34:00 +0000854 for (i = 0; i < N_PROF_EVENTS; i++) {
njn43c799e2003-04-08 00:08:52 +0000855 MAC_(event_ctr)[i] = 0;
sewardjc1a2cda2005-04-21 17:34:00 +0000856 MAC_(event_ctr_name)[i] = NULL;
857 }
njn5c004e42002-11-18 11:04:50 +0000858}
859
njnb4aee052003-04-15 14:09:58 +0000860static void done_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000861{
sewardjc1a2cda2005-04-21 17:34:00 +0000862 Int i;
863 Bool spaced = False;
njn5c004e42002-11-18 11:04:50 +0000864 for (i = 0; i < N_PROF_EVENTS; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +0000865 if (!spaced && (i % 10) == 0) {
njn5c004e42002-11-18 11:04:50 +0000866 VG_(printf)("\n");
sewardjc1a2cda2005-04-21 17:34:00 +0000867 spaced = True;
868 }
869 if (MAC_(event_ctr)[i] > 0) {
870 spaced = False;
871 VG_(printf)( "prof mem event %3d: %9d %s\n",
872 i, MAC_(event_ctr)[i],
873 MAC_(event_ctr_name)[i]
874 ? MAC_(event_ctr_name)[i] : "unnamed");
875 }
njn5c004e42002-11-18 11:04:50 +0000876 }
njn5c004e42002-11-18 11:04:50 +0000877}
878
879#else
880
njnb4aee052003-04-15 14:09:58 +0000881static void init_prof_mem ( void ) { }
882static void done_prof_mem ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000883
njn5c004e42002-11-18 11:04:50 +0000884#endif
885
886/*------------------------------------------------------------*/
njn3e884182003-04-15 13:03:23 +0000887/*--- Common initialisation + finalisation ---*/
888/*------------------------------------------------------------*/
889
890void MAC_(common_pre_clo_init)(void)
891{
892 MAC_(malloc_list) = VG_(HT_construct)();
rjwalshbc0bb832004-06-19 18:12:36 +0000893 MAC_(mempool_list) = VG_(HT_construct)();
njn3e884182003-04-15 13:03:23 +0000894 init_prof_mem();
895}
896
njnb8dca862005-03-14 02:42:44 +0000897void MAC_(common_fini)(void (*leak_check)(ThreadId tid, LeakCheckMode mode))
njn3e884182003-04-15 13:03:23 +0000898{
njn86f12dc2005-03-14 01:16:05 +0000899 MAC_(print_malloc_stats)();
njn3e884182003-04-15 13:03:23 +0000900
sewardj71bc3cb2005-05-19 00:25:45 +0000901 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
sewardjb5f6f512005-03-10 23:59:00 +0000902 if (MAC_(clo_leak_check) == LC_Off)
njn3e884182003-04-15 13:03:23 +0000903 VG_(message)(Vg_UserMsg,
904 "For a detailed leak analysis, rerun with: --leak-check=yes");
905
906 VG_(message)(Vg_UserMsg,
907 "For counts of detected errors, rerun with: -v");
908 }
sewardjb5f6f512005-03-10 23:59:00 +0000909 if (MAC_(clo_leak_check) != LC_Off)
njnb8dca862005-03-14 02:42:44 +0000910 leak_check(1/*bogus ThreadId*/, MAC_(clo_leak_check));
njn3e884182003-04-15 13:03:23 +0000911
912 done_prof_mem();
913}
914
915/*------------------------------------------------------------*/
njn47363ab2003-04-21 13:24:40 +0000916/*--- Common client request handling ---*/
917/*------------------------------------------------------------*/
918
nethercoted1b64b22004-11-04 18:22:28 +0000919Bool MAC_(handle_common_client_requests)(ThreadId tid, UWord* arg, UWord* ret )
njn47363ab2003-04-21 13:24:40 +0000920{
njnd7994182003-10-02 13:44:04 +0000921 Char* err =
922 "The client requests VALGRIND_MALLOCLIKE_BLOCK and\n"
923 " VALGRIND_FREELIKE_BLOCK have moved. Please recompile your\n"
924 " program to incorporate the updates in the Valgrind header files.\n"
925 " You shouldn't need to change the text of your program at all.\n"
926 " Everything should then work as before. Sorry for the bother.\n";
njn47363ab2003-04-21 13:24:40 +0000927
928 switch (arg[0]) {
njn10785452003-05-20 16:38:24 +0000929 case VG_USERREQ__COUNT_LEAKS: { /* count leaked bytes */
nethercoted1b64b22004-11-04 18:22:28 +0000930 UWord** argp = (UWord**)arg;
njne8b5c052003-07-22 22:03:58 +0000931 // MAC_(bytes_leaked) et al were set by the last leak check (or zero
932 // if no prior leak checks performed).
sewardjb5f6f512005-03-10 23:59:00 +0000933 *argp[1] = MAC_(bytes_leaked) + MAC_(bytes_indirect);
njne8b5c052003-07-22 22:03:58 +0000934 *argp[2] = MAC_(bytes_dubious);
935 *argp[3] = MAC_(bytes_reachable);
936 *argp[4] = MAC_(bytes_suppressed);
sewardjb5f6f512005-03-10 23:59:00 +0000937 // there is no argp[5]
938 //*argp[5] = MAC_(bytes_indirect);
939 // XXX need to make *argp[1-4] readable
njn47363ab2003-04-21 13:24:40 +0000940 *ret = 0;
941 return True;
njn10785452003-05-20 16:38:24 +0000942 }
njnd7994182003-10-02 13:44:04 +0000943 case VG_USERREQ__MALLOCLIKE_BLOCK__OLD_DO_NOT_USE:
944 case VG_USERREQ__FREELIKE_BLOCK__OLD_DO_NOT_USE:
njn67993252004-11-22 18:02:32 +0000945 VG_(tool_panic)(err);
njnd7994182003-10-02 13:44:04 +0000946
njn10785452003-05-20 16:38:24 +0000947 case VG_USERREQ__MALLOCLIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000948 Addr p = (Addr)arg[1];
nethercote928a5f72004-11-03 18:10:37 +0000949 SizeT sizeB = arg[2];
njnd7994182003-10-02 13:44:04 +0000950 UInt rzB = arg[3];
951 Bool is_zeroed = (Bool)arg[4];
njn47363ab2003-04-21 13:24:40 +0000952
sewardj2a99cf62004-11-24 10:44:19 +0000953 MAC_(new_block) ( tid, p, sizeB, /*ignored*/0, rzB, is_zeroed,
nethercote57e36b32004-07-10 14:56:28 +0000954 MAC_AllocCustom, MAC_(malloc_list) );
njn10785452003-05-20 16:38:24 +0000955 return True;
956 }
957 case VG_USERREQ__FREELIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000958 Addr p = (Addr)arg[1];
959 UInt rzB = arg[2];
njn10785452003-05-20 16:38:24 +0000960
sewardj2a99cf62004-11-24 10:44:19 +0000961 MAC_(handle_free) ( tid, p, rzB, MAC_AllocCustom );
njn10785452003-05-20 16:38:24 +0000962 return True;
963 }
njnd7994182003-10-02 13:44:04 +0000964
njn1f8b3e72005-03-22 04:27:14 +0000965 case _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR: {
966 Char* s = (Char*) arg[1];
967 OverlapExtra* extra = (OverlapExtra*)arg[2];
968 MAC_(record_overlap_error)(tid, s, extra);
nethercotee3a53722004-05-05 10:46:22 +0000969 return True;
njn1f8b3e72005-03-22 04:27:14 +0000970 }
nethercotee3a53722004-05-05 10:46:22 +0000971
rjwalshbc0bb832004-06-19 18:12:36 +0000972 case VG_USERREQ__CREATE_MEMPOOL: {
973 Addr pool = (Addr)arg[1];
974 UInt rzB = arg[2];
975 Bool is_zeroed = (Bool)arg[3];
976
977 MAC_(create_mempool) ( pool, rzB, is_zeroed );
978 return True;
979 }
980
981 case VG_USERREQ__DESTROY_MEMPOOL: {
982 Addr pool = (Addr)arg[1];
983
984 MAC_(destroy_mempool) ( pool );
985 return True;
986 }
987
988 case VG_USERREQ__MEMPOOL_ALLOC: {
989 Addr pool = (Addr)arg[1];
990 Addr addr = (Addr)arg[2];
991 UInt size = arg[3];
992
sewardj2a99cf62004-11-24 10:44:19 +0000993 MAC_(mempool_alloc) ( tid, pool, addr, size );
rjwalshbc0bb832004-06-19 18:12:36 +0000994 return True;
995 }
996
997 case VG_USERREQ__MEMPOOL_FREE: {
998 Addr pool = (Addr)arg[1];
999 Addr addr = (Addr)arg[2];
1000
1001 MAC_(mempool_free) ( pool, addr );
1002 return True;
1003 }
1004
njn47363ab2003-04-21 13:24:40 +00001005 default:
1006 return False;
1007 }
1008}
1009
njn5c004e42002-11-18 11:04:50 +00001010/*--------------------------------------------------------------------*/
njn00cae242005-05-09 01:13:44 +00001011/*--- end ---*/
njn5c004e42002-11-18 11:04:50 +00001012/*--------------------------------------------------------------------*/