blob: 2f9effd127f2b3094492875d0c2df8ab541618d0 [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"
njn97405b22005-06-02 03:39:33 +000034#include "pub_tool_libcbase.h"
njn47363ab2003-04-21 13:24:40 +000035#include "memcheck.h" /* for VG_USERREQ__* */
36
njn5c004e42002-11-18 11:04:50 +000037/*------------------------------------------------------------*/
38/*--- Defns ---*/
39/*------------------------------------------------------------*/
40
41/* These many bytes below %ESP are considered addressible if we're
42 doing the --workaround-gcc296-bugs hack. */
43#define VG_GCC296_BUG_STACK_SLOP 1024
44
45/*------------------------------------------------------------*/
46/*--- Command line options ---*/
47/*------------------------------------------------------------*/
48
sewardjb5f6f512005-03-10 23:59:00 +000049Bool MAC_(clo_partial_loads_ok) = True;
50Int MAC_(clo_freelist_vol) = 1000000;
njn6a329422005-03-12 20:38:13 +000051LeakCheckMode MAC_(clo_leak_check) = LC_Summary;
sewardjb5f6f512005-03-10 23:59:00 +000052VgRes MAC_(clo_leak_resolution) = Vg_LowRes;
53Bool MAC_(clo_show_reachable) = False;
54Bool MAC_(clo_workaround_gcc296_bugs) = False;
njn5c004e42002-11-18 11:04:50 +000055
njn43c799e2003-04-08 00:08:52 +000056Bool MAC_(process_common_cmd_line_option)(Char* arg)
njn5c004e42002-11-18 11:04:50 +000057{
njn45270a22005-03-27 01:00:11 +000058 VG_BOOL_CLO(arg, "--partial-loads-ok", MAC_(clo_partial_loads_ok))
59 else VG_BOOL_CLO(arg, "--show-reachable", MAC_(clo_show_reachable))
60 else VG_BOOL_CLO(arg, "--workaround-gcc296-bugs",MAC_(clo_workaround_gcc296_bugs))
nethercote27fec902004-06-16 21:26:32 +000061
njn45270a22005-03-27 01:00:11 +000062 else VG_BNUM_CLO(arg, "--freelist-vol", MAC_(clo_freelist_vol), 0, 1000000000)
nethercote27fec902004-06-16 21:26:32 +000063
sewardjb5f6f512005-03-10 23:59:00 +000064 else if (VG_CLO_STREQ(arg, "--leak-check=no"))
65 MAC_(clo_leak_check) = LC_Off;
66 else if (VG_CLO_STREQ(arg, "--leak-check=summary"))
67 MAC_(clo_leak_check) = LC_Summary;
68 else if (VG_CLO_STREQ(arg, "--leak-check=yes") ||
69 VG_CLO_STREQ(arg, "--leak-check=full"))
70 MAC_(clo_leak_check) = LC_Full;
71
njn43c799e2003-04-08 00:08:52 +000072 else if (VG_CLO_STREQ(arg, "--leak-resolution=low"))
73 MAC_(clo_leak_resolution) = Vg_LowRes;
74 else if (VG_CLO_STREQ(arg, "--leak-resolution=med"))
75 MAC_(clo_leak_resolution) = Vg_MedRes;
76 else if (VG_CLO_STREQ(arg, "--leak-resolution=high"))
77 MAC_(clo_leak_resolution) = Vg_HighRes;
njn5c004e42002-11-18 11:04:50 +000078
79 else
njn3e884182003-04-15 13:03:23 +000080 return VG_(replacement_malloc_process_cmd_line_option)(arg);
njn5c004e42002-11-18 11:04:50 +000081
82 return True;
njn43c799e2003-04-08 00:08:52 +000083}
njn5c004e42002-11-18 11:04:50 +000084
njn3e884182003-04-15 13:03:23 +000085void MAC_(print_common_usage)(void)
njn43c799e2003-04-08 00:08:52 +000086{
njn3e884182003-04-15 13:03:23 +000087 VG_(printf)(
sewardjb5f6f512005-03-10 23:59:00 +000088" --partial-loads-ok=no|yes too hard to explain here; see manual [yes]\n"
89" --freelist-vol=<number> volume of freed blocks queue [1000000]\n"
njn6a329422005-03-12 20:38:13 +000090" --leak-check=no|summary|full search for memory leaks at exit? [summary]\n"
sewardjb5f6f512005-03-10 23:59:00 +000091" --leak-resolution=low|med|high how much bt merging in leak check [low]\n"
92" --show-reachable=no|yes show reachable blocks in leak check? [no]\n"
njn3e884182003-04-15 13:03:23 +000093" --workaround-gcc296-bugs=no|yes self explanatory [no]\n"
94 );
95 VG_(replacement_malloc_print_usage)();
njn43c799e2003-04-08 00:08:52 +000096}
97
njn3e884182003-04-15 13:03:23 +000098void MAC_(print_common_debug_usage)(void)
njn43c799e2003-04-08 00:08:52 +000099{
njn3e884182003-04-15 13:03:23 +0000100 VG_(replacement_malloc_print_debug_usage)();
njn5c004e42002-11-18 11:04:50 +0000101}
102
103/*------------------------------------------------------------*/
104/*--- Comparing and printing errors ---*/
105/*------------------------------------------------------------*/
106
107static __inline__
108void clear_AddrInfo ( AddrInfo* ai )
109{
110 ai->akind = Unknown;
111 ai->blksize = 0;
112 ai->rwoffset = 0;
113 ai->lastchange = NULL;
114 ai->stack_tid = VG_INVALID_THREADID;
115 ai->maybe_gcc = False;
sewardjb5f6f512005-03-10 23:59:00 +0000116 ai->desc = NULL;
njn5c004e42002-11-18 11:04:50 +0000117}
118
njn43c799e2003-04-08 00:08:52 +0000119void MAC_(clear_MAC_Error) ( MAC_Error* err_extra )
njn5c004e42002-11-18 11:04:50 +0000120{
121 err_extra->axskind = ReadAxs;
122 err_extra->size = 0;
123 clear_AddrInfo ( &err_extra->addrinfo );
nethercote8b76fe52004-11-08 19:20:09 +0000124 err_extra->isUnaddr = True;
njn5c004e42002-11-18 11:04:50 +0000125}
126
127__attribute__ ((unused))
128static Bool eq_AddrInfo ( VgRes res, AddrInfo* ai1, AddrInfo* ai2 )
129{
130 if (ai1->akind != Undescribed
131 && ai2->akind != Undescribed
132 && ai1->akind != ai2->akind)
133 return False;
134 if (ai1->akind == Freed || ai1->akind == Mallocd) {
135 if (ai1->blksize != ai2->blksize)
136 return False;
137 if (!VG_(eq_ExeContext)(res, ai1->lastchange, ai2->lastchange))
138 return False;
139 }
140 return True;
141}
142
143/* Compare error contexts, to detect duplicates. Note that if they
144 are otherwise the same, the faulting addrs and associated rwoffsets
145 are allowed to be different. */
146
njn51d827b2005-05-09 01:02:08 +0000147Bool MAC_(eq_Error) ( VgRes res, Error* e1, Error* e2 )
njn5c004e42002-11-18 11:04:50 +0000148{
njn43c799e2003-04-08 00:08:52 +0000149 MAC_Error* e1_extra = VG_(get_error_extra)(e1);
150 MAC_Error* e2_extra = VG_(get_error_extra)(e2);
njn7cc53a82002-11-19 16:19:32 +0000151
152 /* Guaranteed by calling function */
njnca82cc02004-11-22 17:18:48 +0000153 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
njn5c004e42002-11-18 11:04:50 +0000154
155 switch (VG_(get_error_kind)(e1)) {
156 case CoreMemErr: {
157 Char *e1s, *e2s;
nethercote8b76fe52004-11-08 19:20:09 +0000158 if (e1_extra->isUnaddr != e2_extra->isUnaddr) return False;
njn5c004e42002-11-18 11:04:50 +0000159 e1s = VG_(get_error_string)(e1);
160 e2s = VG_(get_error_string)(e2);
161 if (e1s == e2s) return True;
162 if (0 == VG_(strcmp)(e1s, e2s)) return True;
163 return False;
164 }
165
njn16390462005-05-08 15:26:00 +0000166 // Perhaps we should also check the addrinfo.akinds for equality.
167 // That would result in more error reports, but only in cases where
168 // a register contains uninitialised bytes and points to memory
169 // containing uninitialised bytes. Currently, the 2nd of those to be
170 // detected won't be reported. That is (nearly?) always the memory
171 // error, which is good.
njn5c004e42002-11-18 11:04:50 +0000172 case ParamErr:
njn16390462005-05-08 15:26:00 +0000173 if (0 != VG_(strcmp)(VG_(get_error_string)(e1),
174 VG_(get_error_string)(e2))) return False;
175 // fall through
176 case UserErr:
177 if (e1_extra->isUnaddr != e2_extra->isUnaddr) return False;
njn5c004e42002-11-18 11:04:50 +0000178 return True;
179
180 case FreeErr:
181 case FreeMismatchErr:
182 /* JRS 2002-Aug-26: comparing addrs seems overkill and can
183 cause excessive duplication of errors. Not even AddrErr
184 below does that. So don't compare either the .addr field
185 or the .addrinfo fields. */
186 /* if (e1->addr != e2->addr) return False; */
187 /* if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
188 return False;
189 */
190 return True;
191
192 case AddrErr:
193 /* if (e1_extra->axskind != e2_extra->axskind) return False; */
194 if (e1_extra->size != e2_extra->size) return False;
195 /*
196 if (!eq_AddrInfo(res, &e1_extra->addrinfo, &e2_extra->addrinfo))
197 return False;
198 */
199 return True;
200
201 case ValueErr:
202 if (e1_extra->size != e2_extra->size) return False;
203 return True;
204
njn34419c12003-05-02 17:24:29 +0000205 case OverlapErr:
206 return True;
207
njn43c799e2003-04-08 00:08:52 +0000208 case LeakErr:
njn51d827b2005-05-09 01:02:08 +0000209 VG_(tool_panic)("Shouldn't get LeakErr in MAC_(eq_Error),\n"
njn43c799e2003-04-08 00:08:52 +0000210 "since it's handled with VG_(unique_error)()!");
211
rjwalshbc0bb832004-06-19 18:12:36 +0000212 case IllegalMempoolErr:
213 return True;
214
njn5c004e42002-11-18 11:04:50 +0000215 default:
216 VG_(printf)("Error:\n unknown error code %d\n",
217 VG_(get_error_kind)(e1));
njn51d827b2005-05-09 01:02:08 +0000218 VG_(tool_panic)("unknown error code in MAC_(eq_Error)");
njn5c004e42002-11-18 11:04:50 +0000219 }
220}
221
njn43c799e2003-04-08 00:08:52 +0000222void MAC_(pp_AddrInfo) ( Addr a, AddrInfo* ai )
njn5c004e42002-11-18 11:04:50 +0000223{
sewardj71bc3cb2005-05-19 00:25:45 +0000224 HChar* xpre = VG_(clo_xml) ? " <auxwhat>" : " ";
225 HChar* xpost = VG_(clo_xml) ? "</auxwhat>" : "";
226
njn5c004e42002-11-18 11:04:50 +0000227 switch (ai->akind) {
228 case Stack:
229 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000230 "%sAddress 0x%llx is on thread %d's stack%s",
231 xpre, (ULong)a, ai->stack_tid, xpost);
njn5c004e42002-11-18 11:04:50 +0000232 break;
233 case Unknown:
234 if (ai->maybe_gcc) {
235 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000236 "%sAddress 0x%llx is just below the stack ptr. "
237 "To suppress, use: --workaround-gcc296-bugs=yes%s",
238 xpre, (ULong)a, xpost
239 );
njn5c004e42002-11-18 11:04:50 +0000240 } else {
241 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000242 "%sAddress 0x%llx "
243 "is not stack'd, malloc'd or (recently) free'd%s",
244 xpre, (ULong)a, xpost);
njn5c004e42002-11-18 11:04:50 +0000245 }
246 break;
rjwalshbc0bb832004-06-19 18:12:36 +0000247 case Freed: case Mallocd: case UserG: case Mempool: {
nethercote50397c22004-11-04 18:03:06 +0000248 SizeT delta;
sewardjb5f6f512005-03-10 23:59:00 +0000249 const Char* relative;
250 const Char* kind;
rjwalshbc0bb832004-06-19 18:12:36 +0000251 if (ai->akind == Mempool) {
252 kind = "mempool";
253 } else {
254 kind = "block";
255 }
sewardjb5f6f512005-03-10 23:59:00 +0000256 if (ai->desc != NULL)
257 kind = ai->desc;
258
njn5c004e42002-11-18 11:04:50 +0000259 if (ai->rwoffset < 0) {
nethercote50397c22004-11-04 18:03:06 +0000260 delta = (SizeT)(- ai->rwoffset);
njn5c004e42002-11-18 11:04:50 +0000261 relative = "before";
262 } else if (ai->rwoffset >= ai->blksize) {
263 delta = ai->rwoffset - ai->blksize;
264 relative = "after";
265 } else {
266 delta = ai->rwoffset;
267 relative = "inside";
268 }
sewardja81709d2002-12-28 12:55:48 +0000269 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000270 "%sAddress 0x%llx is %llu bytes %s a %s of size %d %s%s",
271 xpre,
tom14ea6852005-05-03 18:16:12 +0000272 (ULong)a, (ULong)delta, relative, kind,
sewardja81709d2002-12-28 12:55:48 +0000273 ai->blksize,
274 ai->akind==Mallocd ? "alloc'd"
275 : ai->akind==Freed ? "free'd"
sewardj71bc3cb2005-05-19 00:25:45 +0000276 : "client-defined",
277 xpost);
njn5c004e42002-11-18 11:04:50 +0000278 VG_(pp_ExeContext)(ai->lastchange);
279 break;
280 }
nethercote8b76fe52004-11-08 19:20:09 +0000281 case Register:
282 // print nothing
njnca82cc02004-11-22 17:18:48 +0000283 tl_assert(0 == a);
nethercote8b76fe52004-11-08 19:20:09 +0000284 break;
njn5c004e42002-11-18 11:04:50 +0000285 default:
njn67993252004-11-22 18:02:32 +0000286 VG_(tool_panic)("MAC_(pp_AddrInfo)");
njn43c799e2003-04-08 00:08:52 +0000287 }
288}
289
290/* This prints out the message for the error types where Memcheck and
291 Addrcheck have identical messages */
njnb126f732004-11-22 17:57:07 +0000292void MAC_(pp_shared_Error) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000293{
294 MAC_Error* err_extra = VG_(get_error_extra)(err);
295
sewardj71bc3cb2005-05-19 00:25:45 +0000296 HChar* xpre = VG_(clo_xml) ? " <what>" : "";
297 HChar* xpost = VG_(clo_xml) ? "</what>" : "";
298
njn43c799e2003-04-08 00:08:52 +0000299 switch (VG_(get_error_kind)(err)) {
300 case FreeErr:
sewardj71bc3cb2005-05-19 00:25:45 +0000301 if (VG_(clo_xml))
302 VG_(message)(Vg_UserMsg, " <kind>InvalidFree</kind>");
303 VG_(message)(Vg_UserMsg,
304 "%sInvalid free() / delete / delete[]%s",
305 xpre, xpost);
306 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
307 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
308 break;
309
njn43c799e2003-04-08 00:08:52 +0000310 case FreeMismatchErr:
sewardj71bc3cb2005-05-19 00:25:45 +0000311 if (VG_(clo_xml))
312 VG_(message)(Vg_UserMsg, " <kind>MismatchedFree</kind>");
313 VG_(message)(Vg_UserMsg,
314 "%sMismatched free() / delete / delete []%s",
315 xpre, xpost);
njn43c799e2003-04-08 00:08:52 +0000316 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
317 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
318 break;
319
njn89409f82003-09-26 14:55:31 +0000320 case AddrErr:
321 switch (err_extra->axskind) {
322 case ReadAxs:
sewardj71bc3cb2005-05-19 00:25:45 +0000323 if (VG_(clo_xml))
324 VG_(message)(Vg_UserMsg, " <kind>InvalidRead</kind>");
325 VG_(message)(Vg_UserMsg,
326 "%sInvalid read of size %d%s",
327 xpre, err_extra->size, xpost );
njn89409f82003-09-26 14:55:31 +0000328 break;
329 case WriteAxs:
sewardj71bc3cb2005-05-19 00:25:45 +0000330 if (VG_(clo_xml))
331 VG_(message)(Vg_UserMsg, " <kind>InvalidWrite</kind>");
332 VG_(message)(Vg_UserMsg,
333 "%sInvalid write of size %d%s",
334 xpre, err_extra->size, xpost );
njn89409f82003-09-26 14:55:31 +0000335 break;
336 case ExecAxs:
sewardj71bc3cb2005-05-19 00:25:45 +0000337 if (VG_(clo_xml))
338 VG_(message)(Vg_UserMsg, " <kind>InvalidJump</kind>");
339 VG_(message)(Vg_UserMsg,
340 "%sJump to the invalid address "
341 "stated on the next line%s",
342 xpre, xpost);
njn89409f82003-09-26 14:55:31 +0000343 break;
344 default:
njn51d827b2005-05-09 01:02:08 +0000345 VG_(tool_panic)("MAC_(pp_shared_Error)(axskind)");
njn89409f82003-09-26 14:55:31 +0000346 }
347 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
348 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
349 break;
350
njnb6cae9f2003-09-04 20:50:47 +0000351 case OverlapErr: {
352 OverlapExtra* ov_extra = (OverlapExtra*)VG_(get_error_extra)(err);
sewardj71bc3cb2005-05-19 00:25:45 +0000353 if (VG_(clo_xml))
354 VG_(message)(Vg_UserMsg, " <kind>Overlap</kind>");
njnb6cae9f2003-09-04 20:50:47 +0000355 if (ov_extra->len == -1)
356 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000357 "%sSource and destination overlap in %s(%p, %p)%s",
358 xpre,
njnb6cae9f2003-09-04 20:50:47 +0000359 VG_(get_error_string)(err),
sewardj71bc3cb2005-05-19 00:25:45 +0000360 ov_extra->dst, ov_extra->src,
361 xpost);
njnb6cae9f2003-09-04 20:50:47 +0000362 else
363 VG_(message)(Vg_UserMsg,
sewardj71bc3cb2005-05-19 00:25:45 +0000364 "%sSource and destination overlap in %s(%p, %p, %d)%s",
365 xpre,
njnb6cae9f2003-09-04 20:50:47 +0000366 VG_(get_error_string)(err),
sewardj71bc3cb2005-05-19 00:25:45 +0000367 ov_extra->dst, ov_extra->src, ov_extra->len,
368 xpost);
njn66fe05a2003-07-22 09:12:33 +0000369 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
370 break;
njnb6cae9f2003-09-04 20:50:47 +0000371 }
njn43c799e2003-04-08 00:08:52 +0000372 case LeakErr: {
njn02977032005-05-17 04:00:11 +0000373 MAC_(pp_LeakError)(err_extra);
njn43c799e2003-04-08 00:08:52 +0000374 break;
375 }
376
rjwalshbc0bb832004-06-19 18:12:36 +0000377 case IllegalMempoolErr:
sewardj71bc3cb2005-05-19 00:25:45 +0000378 if (VG_(clo_xml))
379 VG_(message)(Vg_UserMsg, " <kind>InvalidMemPool</kind>");
380 VG_(message)(Vg_UserMsg, "%sIllegal memory pool address%s",
381 xpre, xpost);
rjwalshbc0bb832004-06-19 18:12:36 +0000382 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
383 MAC_(pp_AddrInfo)(VG_(get_error_address)(err), &err_extra->addrinfo);
384 break;
385
njn43c799e2003-04-08 00:08:52 +0000386 default:
387 VG_(printf)("Error:\n unknown Memcheck/Addrcheck error code %d\n",
388 VG_(get_error_kind)(err));
njn67993252004-11-22 18:02:32 +0000389 VG_(tool_panic)("unknown error code in MAC_(pp_shared_Error)");
njn5c004e42002-11-18 11:04:50 +0000390 }
391}
392
393/*------------------------------------------------------------*/
394/*--- Recording errors ---*/
395/*------------------------------------------------------------*/
396
njn43c799e2003-04-08 00:08:52 +0000397/* Additional description function for describe_addr(); used by
398 MemCheck for user blocks, which Addrcheck doesn't support. */
399Bool (*MAC_(describe_addr_supp)) ( Addr a, AddrInfo* ai ) = NULL;
thughes4ad52d02004-06-27 17:37:21 +0000400
401/* Callback for searching thread stacks */
402static Bool addr_is_in_bounds(Addr stack_min, Addr stack_max, void *ap)
403{
404 Addr a = *(Addr *)ap;
405
406 return (stack_min <= a && a <= stack_max);
407}
408
409/* Callback for searching free'd list */
410static Bool addr_is_in_MAC_Chunk(MAC_Chunk* mc, void *ap)
411{
412 Addr a = *(Addr *)ap;
413
njn717cde52005-05-10 02:47:21 +0000414 return VG_(addr_is_in_block)( a, mc->data, mc->size,
415 MAC_MALLOC_REDZONE_SZB );
thughes4ad52d02004-06-27 17:37:21 +0000416}
417
418/* Callback for searching malloc'd lists */
419static Bool addr_is_in_HashNode(VgHashNode* sh_ch, void *ap)
420{
421 return addr_is_in_MAC_Chunk( (MAC_Chunk*)sh_ch, ap );
422}
423
njn43c799e2003-04-08 00:08:52 +0000424/* Describe an address as best you can, for error messages,
425 putting the result in ai. */
426static void describe_addr ( Addr a, AddrInfo* ai )
427{
njn3e884182003-04-15 13:03:23 +0000428 MAC_Chunk* sc;
429 ThreadId tid;
njn43c799e2003-04-08 00:08:52 +0000430
njn43c799e2003-04-08 00:08:52 +0000431 /* Perhaps it's a user-def'd block ? (only check if requested, though) */
432 if (NULL != MAC_(describe_addr_supp)) {
433 if (MAC_(describe_addr_supp)( a, ai ))
434 return;
435 }
436 /* Perhaps it's on a thread's stack? */
thughes4ad52d02004-06-27 17:37:21 +0000437 tid = VG_(first_matching_thread_stack)(addr_is_in_bounds, &a);
njn43c799e2003-04-08 00:08:52 +0000438 if (tid != VG_INVALID_THREADID) {
439 ai->akind = Stack;
440 ai->stack_tid = tid;
441 return;
442 }
443 /* Search for a recently freed block which might bracket it. */
thughes4ad52d02004-06-27 17:37:21 +0000444 sc = MAC_(first_matching_freed_MAC_Chunk)(addr_is_in_MAC_Chunk, &a);
njn3e884182003-04-15 13:03:23 +0000445 if (NULL != sc) {
njn43c799e2003-04-08 00:08:52 +0000446 ai->akind = Freed;
njn3e884182003-04-15 13:03:23 +0000447 ai->blksize = sc->size;
448 ai->rwoffset = (Int)a - (Int)sc->data;
449 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000450 return;
451 }
452 /* Search for a currently malloc'd block which might bracket it. */
thughes4ad52d02004-06-27 17:37:21 +0000453 sc = (MAC_Chunk*)VG_(HT_first_match)(MAC_(malloc_list), addr_is_in_HashNode, &a);
njn43c799e2003-04-08 00:08:52 +0000454 if (NULL != sc) {
455 ai->akind = Mallocd;
njn3e884182003-04-15 13:03:23 +0000456 ai->blksize = sc->size;
457 ai->rwoffset = (Int)(a) - (Int)sc->data;
458 ai->lastchange = sc->where;
njn43c799e2003-04-08 00:08:52 +0000459 return;
460 }
461 /* Clueless ... */
462 ai->akind = Unknown;
463 return;
464}
465
njn5c004e42002-11-18 11:04:50 +0000466/* Is this address within some small distance below %ESP? Used only
467 for the --workaround-gcc296-bugs kludge. */
468static Bool is_just_below_ESP( Addr esp, Addr aa )
469{
nethercote50397c22004-11-04 18:03:06 +0000470 if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
njn5c004e42002-11-18 11:04:50 +0000471 return True;
472 else
473 return False;
474}
475
sewardjaf48a602003-07-06 00:54:47 +0000476/* This one called from generated code and non-generated code. */
njn5c004e42002-11-18 11:04:50 +0000477
njn72718642003-07-24 08:45:32 +0000478void MAC_(record_address_error) ( ThreadId tid, Addr a, Int size,
sewardjaf48a602003-07-06 00:54:47 +0000479 Bool isWrite )
njn5c004e42002-11-18 11:04:50 +0000480{
njn43c799e2003-04-08 00:08:52 +0000481 MAC_Error err_extra;
482 Bool just_below_esp;
njn5c004e42002-11-18 11:04:50 +0000483
njn67516132005-03-22 04:02:43 +0000484 just_below_esp = is_just_below_ESP( VG_(get_SP)(tid), a );
njn5c004e42002-11-18 11:04:50 +0000485
486 /* If this is caused by an access immediately below %ESP, and the
487 user asks nicely, we just ignore it. */
njn43c799e2003-04-08 00:08:52 +0000488 if (MAC_(clo_workaround_gcc296_bugs) && just_below_esp)
njn5c004e42002-11-18 11:04:50 +0000489 return;
490
njn43c799e2003-04-08 00:08:52 +0000491 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000492 err_extra.axskind = isWrite ? WriteAxs : ReadAxs;
493 err_extra.size = size;
494 err_extra.addrinfo.akind = Undescribed;
495 err_extra.addrinfo.maybe_gcc = just_below_esp;
njn72718642003-07-24 08:45:32 +0000496 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000497}
498
499/* These ones are called from non-generated code */
500
501/* This is for memory errors in pthread functions, as opposed to pthread API
502 errors which are found by the core. */
nethercote8b76fe52004-11-08 19:20:09 +0000503void MAC_(record_core_mem_error) ( ThreadId tid, Bool isUnaddr, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000504{
njn43c799e2003-04-08 00:08:52 +0000505 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000506
njn43c799e2003-04-08 00:08:52 +0000507 MAC_(clear_MAC_Error)( &err_extra );
nethercote8b76fe52004-11-08 19:20:09 +0000508 err_extra.isUnaddr = isUnaddr;
njn72718642003-07-24 08:45:32 +0000509 VG_(maybe_record_error)( tid, CoreMemErr, /*addr*/0, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000510}
511
njn16390462005-05-08 15:26:00 +0000512// Three kinds of param errors:
513// - register arg contains undefined bytes
514// - memory arg is unaddressable
515// - memory arg contains undefined bytes
516// 'isReg' and 'isUnaddr' dictate which of these it is.
nethercote8b76fe52004-11-08 19:20:09 +0000517void MAC_(record_param_error) ( ThreadId tid, Addr a, Bool isReg,
518 Bool isUnaddr, Char* msg )
njn5c004e42002-11-18 11:04:50 +0000519{
njn43c799e2003-04-08 00:08:52 +0000520 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000521
njnca82cc02004-11-22 17:18:48 +0000522 tl_assert(VG_INVALID_THREADID != tid);
njn16390462005-05-08 15:26:00 +0000523 if (isUnaddr) tl_assert(!isReg); // unaddressable register is impossible
njn43c799e2003-04-08 00:08:52 +0000524 MAC_(clear_MAC_Error)( &err_extra );
nethercote8b76fe52004-11-08 19:20:09 +0000525 err_extra.addrinfo.akind = ( isReg ? Register : Undescribed );
526 err_extra.isUnaddr = isUnaddr;
njn72718642003-07-24 08:45:32 +0000527 VG_(maybe_record_error)( tid, ParamErr, a, msg, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000528}
529
njn72718642003-07-24 08:45:32 +0000530void MAC_(record_jump_error) ( ThreadId tid, Addr a )
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);
njn43c799e2003-04-08 00:08:52 +0000535 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000536 err_extra.axskind = ExecAxs;
nethercote7250b8f2004-04-13 08:47:35 +0000537 err_extra.size = 1; // size only used for suppressions
njn5c004e42002-11-18 11:04:50 +0000538 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000539 VG_(maybe_record_error)( tid, AddrErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000540}
541
njn72718642003-07-24 08:45:32 +0000542void MAC_(record_free_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.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000549 VG_(maybe_record_error)( tid, FreeErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000550}
551
rjwalshbc0bb832004-06-19 18:12:36 +0000552void MAC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )
553{
554 MAC_Error err_extra;
555
njnca82cc02004-11-22 17:18:48 +0000556 tl_assert(VG_INVALID_THREADID != tid);
rjwalshbc0bb832004-06-19 18:12:36 +0000557 MAC_(clear_MAC_Error)( &err_extra );
558 err_extra.addrinfo.akind = Undescribed;
559 VG_(maybe_record_error)( tid, IllegalMempoolErr, a, /*s*/NULL, &err_extra );
560}
561
njn72718642003-07-24 08:45:32 +0000562void MAC_(record_freemismatch_error) ( ThreadId tid, Addr a )
njn5c004e42002-11-18 11:04:50 +0000563{
njn43c799e2003-04-08 00:08:52 +0000564 MAC_Error err_extra;
njn5c004e42002-11-18 11:04:50 +0000565
njnca82cc02004-11-22 17:18:48 +0000566 tl_assert(VG_INVALID_THREADID != tid);
njn43c799e2003-04-08 00:08:52 +0000567 MAC_(clear_MAC_Error)( &err_extra );
njn5c004e42002-11-18 11:04:50 +0000568 err_extra.addrinfo.akind = Undescribed;
njn72718642003-07-24 08:45:32 +0000569 VG_(maybe_record_error)( tid, FreeMismatchErr, a, /*s*/NULL, &err_extra );
njn5c004e42002-11-18 11:04:50 +0000570}
571
sewardj2a99cf62004-11-24 10:44:19 +0000572void MAC_(record_overlap_error) ( ThreadId tid,
573 Char* function, OverlapExtra* ov_extra )
njn66fe05a2003-07-22 09:12:33 +0000574{
sewardj2a99cf62004-11-24 10:44:19 +0000575 VG_(maybe_record_error)(
576 tid, OverlapErr, /*addr*/0, /*s*/function, ov_extra );
njn66fe05a2003-07-22 09:12:33 +0000577}
578
579
njnb6cae9f2003-09-04 20:50:47 +0000580/* Updates the copy with address info if necessary (but not for all errors). */
njn51d827b2005-05-09 01:02:08 +0000581UInt MAC_(update_extra)( Error* err )
njn43c799e2003-04-08 00:08:52 +0000582{
njnb6cae9f2003-09-04 20:50:47 +0000583 switch (VG_(get_error_kind)(err)) {
584 case ValueErr:
585 case CoreMemErr:
586 case AddrErr:
587 case ParamErr:
588 case UserErr:
589 case FreeErr:
rjwalshbc0bb832004-06-19 18:12:36 +0000590 case IllegalMempoolErr:
njnb6cae9f2003-09-04 20:50:47 +0000591 case FreeMismatchErr: {
nethercote8b76fe52004-11-08 19:20:09 +0000592 MAC_Error* extra = VG_(get_error_extra)(err);
njnb6cae9f2003-09-04 20:50:47 +0000593 if (extra != NULL && Undescribed == extra->addrinfo.akind) {
594 describe_addr ( VG_(get_error_address)(err), &(extra->addrinfo) );
595 }
596 return sizeof(MAC_Error);
597 }
njn43c799e2003-04-08 00:08:52 +0000598 /* Don't need to return the correct size -- LeakErrs are always shown with
599 VG_(unique_error)() so they're not copied anyway. */
njnb6cae9f2003-09-04 20:50:47 +0000600 case LeakErr: return 0;
601 case OverlapErr: return sizeof(OverlapExtra);
njn67993252004-11-22 18:02:32 +0000602 default: VG_(tool_panic)("update_extra: bad errkind");
njn43c799e2003-04-08 00:08:52 +0000603 }
njn43c799e2003-04-08 00:08:52 +0000604}
605
606
njn5c004e42002-11-18 11:04:50 +0000607/*------------------------------------------------------------*/
608/*--- Suppressions ---*/
609/*------------------------------------------------------------*/
610
njn43c799e2003-04-08 00:08:52 +0000611Bool MAC_(shared_recognised_suppression) ( Char* name, Supp* su )
612{
613 SuppKind skind;
614
615 if (VG_STREQ(name, "Param")) skind = ParamSupp;
616 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
617 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
618 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
619 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
620 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
njnc0616662003-06-12 09:58:41 +0000621 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
njn43c799e2003-04-08 00:08:52 +0000622 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
623 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
njne9cab142003-09-19 08:10:07 +0000624 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
rjwalshbc0bb832004-06-19 18:12:36 +0000625 else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
njn43c799e2003-04-08 00:08:52 +0000626 else
627 return False;
628
629 VG_(set_supp_kind)(su, skind);
630 return True;
631}
632
njn51d827b2005-05-09 01:02:08 +0000633Bool MAC_(read_extra_suppression_info) ( Int fd, Char* buf, Int nBuf, Supp *su )
njn5c004e42002-11-18 11:04:50 +0000634{
635 Bool eof;
636
637 if (VG_(get_supp_kind)(su) == ParamSupp) {
638 eof = VG_(get_line) ( fd, buf, nBuf );
639 if (eof) return False;
640 VG_(set_supp_string)(su, VG_(strdup)(buf));
641 }
642 return True;
643}
644
njn51d827b2005-05-09 01:02:08 +0000645Bool MAC_(error_matches_suppression)(Error* err, Supp* su)
njn5c004e42002-11-18 11:04:50 +0000646{
sewardj05bcdcb2003-05-18 10:05:38 +0000647 Int su_size;
njn43c799e2003-04-08 00:08:52 +0000648 MAC_Error* err_extra = VG_(get_error_extra)(err);
649 ErrorKind ekind = VG_(get_error_kind )(err);
njn5c004e42002-11-18 11:04:50 +0000650
651 switch (VG_(get_supp_kind)(su)) {
652 case ParamSupp:
653 return (ekind == ParamErr
njn43c799e2003-04-08 00:08:52 +0000654 && VG_STREQ(VG_(get_error_string)(err),
655 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000656
657 case CoreMemSupp:
658 return (ekind == CoreMemErr
njn43c799e2003-04-08 00:08:52 +0000659 && VG_STREQ(VG_(get_error_string)(err),
660 VG_(get_supp_string)(su)));
njn5c004e42002-11-18 11:04:50 +0000661
662 case Value0Supp: su_size = 0; goto value_case;
663 case Value1Supp: su_size = 1; goto value_case;
664 case Value2Supp: su_size = 2; goto value_case;
665 case Value4Supp: su_size = 4; goto value_case;
666 case Value8Supp: su_size = 8; goto value_case;
njnc0616662003-06-12 09:58:41 +0000667 case Value16Supp:su_size =16; goto value_case;
njn5c004e42002-11-18 11:04:50 +0000668 value_case:
669 return (ekind == ValueErr && err_extra->size == su_size);
670
671 case Addr1Supp: su_size = 1; goto addr_case;
672 case Addr2Supp: su_size = 2; goto addr_case;
673 case Addr4Supp: su_size = 4; goto addr_case;
674 case Addr8Supp: su_size = 8; goto addr_case;
njnc0616662003-06-12 09:58:41 +0000675 case Addr16Supp:su_size =16; goto addr_case;
njn5c004e42002-11-18 11:04:50 +0000676 addr_case:
677 return (ekind == AddrErr && err_extra->size == su_size);
678
679 case FreeSupp:
680 return (ekind == FreeErr || ekind == FreeMismatchErr);
681
njn34419c12003-05-02 17:24:29 +0000682 case OverlapSupp:
683 return (ekind = OverlapErr);
684
sewardj4a19e2f2002-12-26 11:50:21 +0000685 case LeakSupp:
njn43c799e2003-04-08 00:08:52 +0000686 return (ekind == LeakErr);
sewardj4a19e2f2002-12-26 11:50:21 +0000687
rjwalshbc0bb832004-06-19 18:12:36 +0000688 case MempoolSupp:
689 return (ekind == IllegalMempoolErr);
690
njn5c004e42002-11-18 11:04:50 +0000691 default:
692 VG_(printf)("Error:\n"
693 " unknown suppression type %d\n",
694 VG_(get_supp_kind)(su));
njn67993252004-11-22 18:02:32 +0000695 VG_(tool_panic)("unknown suppression type in "
njn51d827b2005-05-09 01:02:08 +0000696 "MAC_(error_matches_suppression)");
njn5c004e42002-11-18 11:04:50 +0000697 }
698}
699
njn51d827b2005-05-09 01:02:08 +0000700Char* MAC_(get_error_name) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000701{
702 Char* s;
703 switch (VG_(get_error_kind)(err)) {
704 case ParamErr: return "Param";
705 case UserErr: return NULL; /* Can't suppress User errors */
706 case FreeMismatchErr: return "Free";
rjwalshbc0bb832004-06-19 18:12:36 +0000707 case IllegalMempoolErr: return "Mempool";
njn43c799e2003-04-08 00:08:52 +0000708 case FreeErr: return "Free";
709 case AddrErr:
710 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
711 case 1: return "Addr1";
712 case 2: return "Addr2";
713 case 4: return "Addr4";
714 case 8: return "Addr8";
njnc0616662003-06-12 09:58:41 +0000715 case 16: return "Addr16";
njn67993252004-11-22 18:02:32 +0000716 default: VG_(tool_panic)("unexpected size for Addr");
njn43c799e2003-04-08 00:08:52 +0000717 }
718
719 case ValueErr:
720 switch ( ((MAC_Error*)VG_(get_error_extra)(err))->size ) {
721 case 0: return "Cond";
722 case 1: return "Value1";
723 case 2: return "Value2";
724 case 4: return "Value4";
725 case 8: return "Value8";
njnc0616662003-06-12 09:58:41 +0000726 case 16: return "Value16";
njn67993252004-11-22 18:02:32 +0000727 default: VG_(tool_panic)("unexpected size for Value");
njn43c799e2003-04-08 00:08:52 +0000728 }
729 case CoreMemErr: return "CoreMem";
njn34419c12003-05-02 17:24:29 +0000730 case OverlapErr: return "Overlap";
njn43c799e2003-04-08 00:08:52 +0000731 case LeakErr: return "Leak";
njn67993252004-11-22 18:02:32 +0000732 default: VG_(tool_panic)("get_error_name: unexpected type");
njn43c799e2003-04-08 00:08:52 +0000733 }
734 VG_(printf)(s);
735}
736
njn51d827b2005-05-09 01:02:08 +0000737void MAC_(print_extra_suppression_info) ( Error* err )
njn43c799e2003-04-08 00:08:52 +0000738{
739 if (ParamErr == VG_(get_error_kind)(err)) {
740 VG_(printf)(" %s\n", VG_(get_error_string)(err));
741 }
742}
njn5c004e42002-11-18 11:04:50 +0000743
744/*------------------------------------------------------------*/
745/*--- Crude profiling machinery. ---*/
746/*------------------------------------------------------------*/
747
748/* Event index. If just the name of the fn is given, this means the
749 number of calls to the fn. Otherwise it is the specified event.
750 Ones marked 'M' are MemCheck only. Ones marked 'A' are AddrCheck only.
751 The rest are shared.
752
753 10 alloc_secondary_map
754
755 20 get_abit
756M 21 get_vbyte
757 22 set_abit
758M 23 set_vbyte
759 24 get_abits4_ALIGNED
760M 25 get_vbytes4_ALIGNED
761
762 30 set_address_range_perms
763 31 set_address_range_perms(lower byte loop)
764 32 set_address_range_perms(quadword loop)
765 33 set_address_range_perms(upper byte loop)
766
767 35 make_noaccess
768 36 make_writable
769 37 make_readable
770A 38 make_accessible
771
772 40 copy_address_range_state
773 41 copy_address_range_state(byte loop)
774 42 check_writable
775 43 check_writable(byte loop)
776 44 check_readable
777 45 check_readable(byte loop)
778 46 check_readable_asciiz
779 47 check_readable_asciiz(byte loop)
780A 48 check_accessible
781A 49 check_accessible(byte loop)
782
783 50 make_noaccess_aligned
784 51 make_writable_aligned
785
786M 60 helperc_LOADV4
787M 61 helperc_STOREV4
788M 62 helperc_LOADV2
789M 63 helperc_STOREV2
790M 64 helperc_LOADV1
791M 65 helperc_STOREV1
792
793A 66 helperc_ACCESS4
794A 67 helperc_ACCESS2
795A 68 helperc_ACCESS1
796
797M 70 rim_rd_V4_SLOWLY
798M 71 rim_wr_V4_SLOWLY
799M 72 rim_rd_V2_SLOWLY
800M 73 rim_wr_V2_SLOWLY
801M 74 rim_rd_V1_SLOWLY
802M 75 rim_wr_V1_SLOWLY
803
804A 76 ACCESS4_SLOWLY
805A 77 ACCESS2_SLOWLY
806A 78 ACCESS1_SLOWLY
807
808 80 fpu_read
809 81 fpu_read aligned 4
810 82 fpu_read aligned 8
811 83 fpu_read 2
jsewardfca60182004-01-04 23:30:55 +0000812 84 fpu_read 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000813
814M 85 fpu_write
815M 86 fpu_write aligned 4
816M 87 fpu_write aligned 8
817M 88 fpu_write 2
jsewardfca60182004-01-04 23:30:55 +0000818M 89 fpu_write 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000819
820 90 fpu_access
821 91 fpu_access aligned 4
822 92 fpu_access aligned 8
823 93 fpu_access 2
jsewardfca60182004-01-04 23:30:55 +0000824 94 fpu_access 10/28/108/512
njn5c004e42002-11-18 11:04:50 +0000825
826 100 fpu_access_check_SLOWLY
827 101 fpu_access_check_SLOWLY(byte loop)
njn9b007f62003-04-07 14:40:25 +0000828
829 110 new_mem_stack_4
830 111 new_mem_stack_8
831 112 new_mem_stack_12
832 113 new_mem_stack_16
833 114 new_mem_stack_32
834 115 new_mem_stack
835
836 120 die_mem_stack_4
837 121 die_mem_stack_8
838 122 die_mem_stack_12
839 123 die_mem_stack_16
840 124 die_mem_stack_32
841 125 die_mem_stack
njn5c004e42002-11-18 11:04:50 +0000842*/
843
njn43c799e2003-04-08 00:08:52 +0000844#ifdef MAC_PROFILE_MEMORY
njn5c004e42002-11-18 11:04:50 +0000845
sewardjc1a2cda2005-04-21 17:34:00 +0000846UInt MAC_(event_ctr)[N_PROF_EVENTS];
847HChar* MAC_(event_ctr_name)[N_PROF_EVENTS];
njn5c004e42002-11-18 11:04:50 +0000848
njnb4aee052003-04-15 14:09:58 +0000849static void init_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000850{
851 Int i;
sewardjc1a2cda2005-04-21 17:34:00 +0000852 for (i = 0; i < N_PROF_EVENTS; i++) {
njn43c799e2003-04-08 00:08:52 +0000853 MAC_(event_ctr)[i] = 0;
sewardjc1a2cda2005-04-21 17:34:00 +0000854 MAC_(event_ctr_name)[i] = NULL;
855 }
njn5c004e42002-11-18 11:04:50 +0000856}
857
njnb4aee052003-04-15 14:09:58 +0000858static void done_prof_mem ( void )
njn5c004e42002-11-18 11:04:50 +0000859{
sewardjc1a2cda2005-04-21 17:34:00 +0000860 Int i;
861 Bool spaced = False;
njn5c004e42002-11-18 11:04:50 +0000862 for (i = 0; i < N_PROF_EVENTS; i++) {
sewardjc1a2cda2005-04-21 17:34:00 +0000863 if (!spaced && (i % 10) == 0) {
njn5c004e42002-11-18 11:04:50 +0000864 VG_(printf)("\n");
sewardjc1a2cda2005-04-21 17:34:00 +0000865 spaced = True;
866 }
867 if (MAC_(event_ctr)[i] > 0) {
868 spaced = False;
869 VG_(printf)( "prof mem event %3d: %9d %s\n",
870 i, MAC_(event_ctr)[i],
871 MAC_(event_ctr_name)[i]
872 ? MAC_(event_ctr_name)[i] : "unnamed");
873 }
njn5c004e42002-11-18 11:04:50 +0000874 }
njn5c004e42002-11-18 11:04:50 +0000875}
876
877#else
878
njnb4aee052003-04-15 14:09:58 +0000879static void init_prof_mem ( void ) { }
880static void done_prof_mem ( void ) { }
njn5c004e42002-11-18 11:04:50 +0000881
njn5c004e42002-11-18 11:04:50 +0000882#endif
883
884/*------------------------------------------------------------*/
njn3e884182003-04-15 13:03:23 +0000885/*--- Common initialisation + finalisation ---*/
886/*------------------------------------------------------------*/
887
888void MAC_(common_pre_clo_init)(void)
889{
890 MAC_(malloc_list) = VG_(HT_construct)();
rjwalshbc0bb832004-06-19 18:12:36 +0000891 MAC_(mempool_list) = VG_(HT_construct)();
njn3e884182003-04-15 13:03:23 +0000892 init_prof_mem();
893}
894
njnb8dca862005-03-14 02:42:44 +0000895void MAC_(common_fini)(void (*leak_check)(ThreadId tid, LeakCheckMode mode))
njn3e884182003-04-15 13:03:23 +0000896{
njn86f12dc2005-03-14 01:16:05 +0000897 MAC_(print_malloc_stats)();
njn3e884182003-04-15 13:03:23 +0000898
sewardj71bc3cb2005-05-19 00:25:45 +0000899 if (VG_(clo_verbosity) == 1 && !VG_(clo_xml)) {
sewardjb5f6f512005-03-10 23:59:00 +0000900 if (MAC_(clo_leak_check) == LC_Off)
njn3e884182003-04-15 13:03:23 +0000901 VG_(message)(Vg_UserMsg,
902 "For a detailed leak analysis, rerun with: --leak-check=yes");
903
904 VG_(message)(Vg_UserMsg,
905 "For counts of detected errors, rerun with: -v");
906 }
sewardjb5f6f512005-03-10 23:59:00 +0000907 if (MAC_(clo_leak_check) != LC_Off)
njnb8dca862005-03-14 02:42:44 +0000908 leak_check(1/*bogus ThreadId*/, MAC_(clo_leak_check));
njn3e884182003-04-15 13:03:23 +0000909
910 done_prof_mem();
911}
912
913/*------------------------------------------------------------*/
njn47363ab2003-04-21 13:24:40 +0000914/*--- Common client request handling ---*/
915/*------------------------------------------------------------*/
916
nethercoted1b64b22004-11-04 18:22:28 +0000917Bool MAC_(handle_common_client_requests)(ThreadId tid, UWord* arg, UWord* ret )
njn47363ab2003-04-21 13:24:40 +0000918{
njnd7994182003-10-02 13:44:04 +0000919 Char* err =
920 "The client requests VALGRIND_MALLOCLIKE_BLOCK and\n"
921 " VALGRIND_FREELIKE_BLOCK have moved. Please recompile your\n"
922 " program to incorporate the updates in the Valgrind header files.\n"
923 " You shouldn't need to change the text of your program at all.\n"
924 " Everything should then work as before. Sorry for the bother.\n";
njn47363ab2003-04-21 13:24:40 +0000925
926 switch (arg[0]) {
njn10785452003-05-20 16:38:24 +0000927 case VG_USERREQ__COUNT_LEAKS: { /* count leaked bytes */
nethercoted1b64b22004-11-04 18:22:28 +0000928 UWord** argp = (UWord**)arg;
njne8b5c052003-07-22 22:03:58 +0000929 // MAC_(bytes_leaked) et al were set by the last leak check (or zero
930 // if no prior leak checks performed).
sewardjb5f6f512005-03-10 23:59:00 +0000931 *argp[1] = MAC_(bytes_leaked) + MAC_(bytes_indirect);
njne8b5c052003-07-22 22:03:58 +0000932 *argp[2] = MAC_(bytes_dubious);
933 *argp[3] = MAC_(bytes_reachable);
934 *argp[4] = MAC_(bytes_suppressed);
sewardjb5f6f512005-03-10 23:59:00 +0000935 // there is no argp[5]
936 //*argp[5] = MAC_(bytes_indirect);
937 // XXX need to make *argp[1-4] readable
njn47363ab2003-04-21 13:24:40 +0000938 *ret = 0;
939 return True;
njn10785452003-05-20 16:38:24 +0000940 }
njnd7994182003-10-02 13:44:04 +0000941 case VG_USERREQ__MALLOCLIKE_BLOCK__OLD_DO_NOT_USE:
942 case VG_USERREQ__FREELIKE_BLOCK__OLD_DO_NOT_USE:
njn67993252004-11-22 18:02:32 +0000943 VG_(tool_panic)(err);
njnd7994182003-10-02 13:44:04 +0000944
njn10785452003-05-20 16:38:24 +0000945 case VG_USERREQ__MALLOCLIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000946 Addr p = (Addr)arg[1];
nethercote928a5f72004-11-03 18:10:37 +0000947 SizeT sizeB = arg[2];
njnd7994182003-10-02 13:44:04 +0000948 UInt rzB = arg[3];
949 Bool is_zeroed = (Bool)arg[4];
njn47363ab2003-04-21 13:24:40 +0000950
sewardj2a99cf62004-11-24 10:44:19 +0000951 MAC_(new_block) ( tid, p, sizeB, /*ignored*/0, rzB, is_zeroed,
nethercote57e36b32004-07-10 14:56:28 +0000952 MAC_AllocCustom, MAC_(malloc_list) );
njn10785452003-05-20 16:38:24 +0000953 return True;
954 }
955 case VG_USERREQ__FREELIKE_BLOCK: {
njnd7994182003-10-02 13:44:04 +0000956 Addr p = (Addr)arg[1];
957 UInt rzB = arg[2];
njn10785452003-05-20 16:38:24 +0000958
sewardj2a99cf62004-11-24 10:44:19 +0000959 MAC_(handle_free) ( tid, p, rzB, MAC_AllocCustom );
njn10785452003-05-20 16:38:24 +0000960 return True;
961 }
njnd7994182003-10-02 13:44:04 +0000962
njn1f8b3e72005-03-22 04:27:14 +0000963 case _VG_USERREQ__MEMCHECK_RECORD_OVERLAP_ERROR: {
964 Char* s = (Char*) arg[1];
965 OverlapExtra* extra = (OverlapExtra*)arg[2];
966 MAC_(record_overlap_error)(tid, s, extra);
nethercotee3a53722004-05-05 10:46:22 +0000967 return True;
njn1f8b3e72005-03-22 04:27:14 +0000968 }
nethercotee3a53722004-05-05 10:46:22 +0000969
rjwalshbc0bb832004-06-19 18:12:36 +0000970 case VG_USERREQ__CREATE_MEMPOOL: {
971 Addr pool = (Addr)arg[1];
972 UInt rzB = arg[2];
973 Bool is_zeroed = (Bool)arg[3];
974
975 MAC_(create_mempool) ( pool, rzB, is_zeroed );
976 return True;
977 }
978
979 case VG_USERREQ__DESTROY_MEMPOOL: {
980 Addr pool = (Addr)arg[1];
981
982 MAC_(destroy_mempool) ( pool );
983 return True;
984 }
985
986 case VG_USERREQ__MEMPOOL_ALLOC: {
987 Addr pool = (Addr)arg[1];
988 Addr addr = (Addr)arg[2];
989 UInt size = arg[3];
990
sewardj2a99cf62004-11-24 10:44:19 +0000991 MAC_(mempool_alloc) ( tid, pool, addr, size );
rjwalshbc0bb832004-06-19 18:12:36 +0000992 return True;
993 }
994
995 case VG_USERREQ__MEMPOOL_FREE: {
996 Addr pool = (Addr)arg[1];
997 Addr addr = (Addr)arg[2];
998
999 MAC_(mempool_free) ( pool, addr );
1000 return True;
1001 }
1002
njn47363ab2003-04-21 13:24:40 +00001003 default:
1004 return False;
1005 }
1006}
1007
njn5c004e42002-11-18 11:04:50 +00001008/*--------------------------------------------------------------------*/
njn00cae242005-05-09 01:13:44 +00001009/*--- end ---*/
njn5c004e42002-11-18 11:04:50 +00001010/*--------------------------------------------------------------------*/