blob: 125a5648b5ac1ad0f74f72e87f6d93ce26078b2e [file] [log] [blame]
sewardj7ce71662008-05-02 10:33:15 +00001
2/*--------------------------------------------------------------------*/
3/*--- Management, printing, etc, of errors and suppressions. ---*/
4/*--- mc_errors.c ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8 This file is part of MemCheck, a heavyweight Valgrind tool for
9 detecting memory errors.
10
sewardj0f157dd2013-10-18 14:27:36 +000011 Copyright (C) 2000-2013 Julian Seward
sewardj7ce71662008-05-02 10:33:15 +000012 jseward@acm.org
13
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file COPYING.
30*/
31
32#include "pub_tool_basics.h"
sewardj3b290482011-05-06 21:02:55 +000033#include "pub_tool_gdbserver.h"
philippe6643e962012-01-17 21:16:30 +000034#include "pub_tool_poolalloc.h" // For mc_include.h
sewardj7ce71662008-05-02 10:33:15 +000035#include "pub_tool_hashtable.h" // For mc_include.h
36#include "pub_tool_libcbase.h"
37#include "pub_tool_libcassert.h"
38#include "pub_tool_libcprint.h"
39#include "pub_tool_machine.h"
40#include "pub_tool_mallocfree.h"
41#include "pub_tool_options.h"
sewardj7ce71662008-05-02 10:33:15 +000042#include "pub_tool_replacemalloc.h"
43#include "pub_tool_tooliface.h"
44#include "pub_tool_threadstate.h"
sewardj7ce71662008-05-02 10:33:15 +000045#include "pub_tool_debuginfo.h" // VG_(get_dataname_and_offset)
sewardj6b523cd2009-07-15 14:49:40 +000046#include "pub_tool_xarray.h"
philippe07c08522014-05-14 20:39:27 +000047#include "pub_tool_addrinfo.h"
sewardj7ce71662008-05-02 10:33:15 +000048
49#include "mc_include.h"
sewardj7ce71662008-05-02 10:33:15 +000050
51
52/*------------------------------------------------------------*/
53/*--- Error types ---*/
54/*------------------------------------------------------------*/
55
56/* See comment in mc_include.h */
57Bool MC_(any_value_errors) = False;
58
59
sewardj7ce71662008-05-02 10:33:15 +000060/* ------------------ Errors ----------------------- */
61
62/* What kind of error it is. */
63typedef
64 enum {
65 Err_Value,
66 Err_Cond,
67 Err_CoreMem,
68 Err_Addr,
69 Err_Jump,
70 Err_RegParam,
71 Err_MemParam,
72 Err_User,
73 Err_Free,
74 Err_FreeMismatch,
75 Err_Overlap,
76 Err_Leak,
77 Err_IllegalMempool,
florian7b6899d2014-07-13 14:41:55 +000078 Err_FishyValue,
sewardj7ce71662008-05-02 10:33:15 +000079 }
80 MC_ErrorTag;
81
82
83typedef struct _MC_Error MC_Error;
84
85struct _MC_Error {
86 // Nb: we don't need the tag here, as it's stored in the Error type! Yuk.
87 //MC_ErrorTag tag;
88
89 union {
90 // Use of an undefined value:
91 // - as a pointer in a load or store
92 // - as a jump target
93 struct {
94 SizeT szB; // size of value in bytes
95 // Origin info
96 UInt otag; // origin tag
97 ExeContext* origin_ec; // filled in later
98 } Value;
99
100 // Use of an undefined value in a conditional branch or move.
101 struct {
102 // Origin info
103 UInt otag; // origin tag
104 ExeContext* origin_ec; // filled in later
105 } Cond;
106
107 // Addressability error in core (signal-handling) operation.
108 // It would be good to get rid of this error kind, merge it with
109 // another one somehow.
110 struct {
111 } CoreMem;
112
113 // Use of an unaddressable memory location in a load or store.
114 struct {
115 Bool isWrite; // read or write?
116 SizeT szB; // not used for exec (jump) errors
117 Bool maybe_gcc; // True if just below %esp -- could be a gcc bug
118 AddrInfo ai;
119 } Addr;
120
121 // Jump to an unaddressable memory location.
122 struct {
123 AddrInfo ai;
124 } Jump;
125
126 // System call register input contains undefined bytes.
127 struct {
128 // Origin info
129 UInt otag; // origin tag
130 ExeContext* origin_ec; // filled in later
131 } RegParam;
132
133 // System call memory input contains undefined/unaddressable bytes
134 struct {
135 Bool isAddrErr; // Addressability or definedness error?
136 AddrInfo ai;
137 // Origin info
138 UInt otag; // origin tag
139 ExeContext* origin_ec; // filled in later
140 } MemParam;
141
142 // Problem found from a client request like CHECK_MEM_IS_ADDRESSABLE.
143 struct {
144 Bool isAddrErr; // Addressability or definedness error?
145 AddrInfo ai;
146 // Origin info
147 UInt otag; // origin tag
148 ExeContext* origin_ec; // filled in later
149 } User;
150
151 // Program tried to free() something that's not a heap block (this
152 // covers double-frees). */
153 struct {
154 AddrInfo ai;
155 } Free;
156
157 // Program allocates heap block with one function
158 // (malloc/new/new[]/custom) and deallocates with not the matching one.
159 struct {
160 AddrInfo ai;
161 } FreeMismatch;
162
163 // Call to strcpy, memcpy, etc, with overlapping blocks.
164 struct {
philippedfa54a52013-03-13 21:44:07 +0000165 Addr src; // Source block
166 Addr dst; // Destination block
167 SizeT szB; // Size in bytes; 0 if unused.
sewardj7ce71662008-05-02 10:33:15 +0000168 } Overlap;
169
170 // A memory leak.
171 struct {
172 UInt n_this_record;
173 UInt n_total_records;
njnb7a4e2e2009-05-01 00:30:43 +0000174 LossRecord* lr;
sewardj7ce71662008-05-02 10:33:15 +0000175 } Leak;
176
177 // A memory pool error.
178 struct {
179 AddrInfo ai;
180 } IllegalMempool;
181
florian7b6899d2014-07-13 14:41:55 +0000182 // A fishy function argument value
183 // An argument value is considered fishy if the corresponding
184 // parameter has SizeT type and the value when interpreted as a
185 // signed number is negative.
186 struct {
187 const HChar *function_name;
188 const HChar *argument_name;
189 SizeT value;
190 } FishyValue;
sewardj7ce71662008-05-02 10:33:15 +0000191 } Err;
192};
193
194
195/*------------------------------------------------------------*/
196/*--- Printing errors ---*/
197/*------------------------------------------------------------*/
198
sewardj6b523cd2009-07-15 14:49:40 +0000199/* This is the "this error is due to be printed shortly; so have a
200 look at it any print any preamble you want" function. Which, in
201 Memcheck, we don't use. Hence a no-op.
202*/
203void MC_(before_pp_Error) ( Error* err ) {
204}
205
206/* Do a printf-style operation on either the XML or normal output
207 channel, depending on the setting of VG_(clo_xml).
208*/
floriandbb35842012-10-27 18:39:11 +0000209static void emit_WRK ( const HChar* format, va_list vargs )
sewardj6b523cd2009-07-15 14:49:40 +0000210{
211 if (VG_(clo_xml)) {
212 VG_(vprintf_xml)(format, vargs);
213 } else {
214 VG_(vmessage)(Vg_UserMsg, format, vargs);
215 }
216}
floriandbb35842012-10-27 18:39:11 +0000217static void emit ( const HChar* format, ... ) PRINTF_CHECK(1, 2);
218static void emit ( const HChar* format, ... )
sewardj6b523cd2009-07-15 14:49:40 +0000219{
220 va_list vargs;
221 va_start(vargs, format);
222 emit_WRK(format, vargs);
223 va_end(vargs);
224}
sewardj6b523cd2009-07-15 14:49:40 +0000225
226
sewardj7ce71662008-05-02 10:33:15 +0000227static const HChar* str_leak_lossmode ( Reachedness lossmode )
228{
229 const HChar *loss = "?";
230 switch (lossmode) {
231 case Unreached: loss = "definitely lost"; break;
232 case IndirectLeak: loss = "indirectly lost"; break;
njn8225cc02009-03-09 22:52:24 +0000233 case Possible: loss = "possibly lost"; break;
234 case Reachable: loss = "still reachable"; break;
sewardj7ce71662008-05-02 10:33:15 +0000235 }
236 return loss;
237}
238
239static const HChar* xml_leak_kind ( Reachedness lossmode )
240{
241 const HChar *loss = "?";
242 switch (lossmode) {
243 case Unreached: loss = "Leak_DefinitelyLost"; break;
244 case IndirectLeak: loss = "Leak_IndirectlyLost"; break;
njn8225cc02009-03-09 22:52:24 +0000245 case Possible: loss = "Leak_PossiblyLost"; break;
246 case Reachable: loss = "Leak_StillReachable"; break;
sewardj7ce71662008-05-02 10:33:15 +0000247 }
248 return loss;
249}
250
philippe2193a7c2012-12-08 17:54:16 +0000251Bool MC_(parse_leak_kinds) ( const HChar* str0, UInt* lks )
252{
philippe0c2923f2014-04-19 09:52:32 +0000253 return VG_(parse_enum_set)("reachable,possible,indirect,definite",
254 str0, lks);
philippe2193a7c2012-12-08 17:54:16 +0000255}
256
257static const HChar* pp_Reachedness_for_leak_kinds(Reachedness r)
258{
259 switch(r) {
260 case Reachable: return "reachable";
261 case Possible: return "possible";
262 case IndirectLeak: return "indirect";
263 case Unreached: return "definite";
264 default: tl_assert(0);
265 }
266}
267
sewardj7ce71662008-05-02 10:33:15 +0000268static void mc_pp_origin ( ExeContext* ec, UInt okind )
269{
floriana5f894c2012-10-21 03:43:20 +0000270 const HChar* src = NULL;
sewardj7ce71662008-05-02 10:33:15 +0000271 tl_assert(ec);
272
273 switch (okind) {
274 case MC_OKIND_STACK: src = " by a stack allocation"; break;
275 case MC_OKIND_HEAP: src = " by a heap allocation"; break;
276 case MC_OKIND_USER: src = " by a client request"; break;
277 case MC_OKIND_UNKNOWN: src = ""; break;
278 }
279 tl_assert(src); /* guards against invalid 'okind' */
280
281 if (VG_(clo_xml)) {
sewardj6b523cd2009-07-15 14:49:40 +0000282 emit( " <auxwhat>Uninitialised value was created%s</auxwhat>\n",
283 src);
284 VG_(pp_ExeContext)( ec );
285 } else {
286 emit( " Uninitialised value was created%s\n", src);
287 VG_(pp_ExeContext)( ec );
sewardj7ce71662008-05-02 10:33:15 +0000288 }
289}
290
floriandbb35842012-10-27 18:39:11 +0000291HChar * MC_(snprintf_delta) (HChar * buf, Int size,
292 SizeT current_val, SizeT old_val,
293 LeakCheckDeltaMode delta_mode)
sewardjc8bd1df2011-06-26 12:41:33 +0000294{
295 if (delta_mode == LCD_Any)
296 buf[0] = '\0';
297 else if (current_val >= old_val)
298 VG_(snprintf) (buf, size, " (+%'lu)", current_val - old_val);
299 else
300 VG_(snprintf) (buf, size, " (-%'lu)", old_val - current_val);
301
302 return buf;
303}
304
philippea22f59d2012-01-26 23:13:52 +0000305static void pp_LossRecord(UInt n_this_record, UInt n_total_records,
306 LossRecord* lr, Bool xml)
307{
308 // char arrays to produce the indication of increase/decrease in case
309 // of delta_mode != LCD_Any
floriandbb35842012-10-27 18:39:11 +0000310 HChar d_bytes[20];
311 HChar d_direct_bytes[20];
312 HChar d_indirect_bytes[20];
313 HChar d_num_blocks[20];
philippea22f59d2012-01-26 23:13:52 +0000314
315 MC_(snprintf_delta) (d_bytes, 20,
316 lr->szB + lr->indirect_szB,
317 lr->old_szB + lr->old_indirect_szB,
318 MC_(detect_memory_leaks_last_delta_mode));
319 MC_(snprintf_delta) (d_direct_bytes, 20,
320 lr->szB,
321 lr->old_szB,
322 MC_(detect_memory_leaks_last_delta_mode));
323 MC_(snprintf_delta) (d_indirect_bytes, 20,
324 lr->indirect_szB,
325 lr->old_indirect_szB,
326 MC_(detect_memory_leaks_last_delta_mode));
327 MC_(snprintf_delta) (d_num_blocks, 20,
328 (SizeT) lr->num_blocks,
329 (SizeT) lr->old_num_blocks,
330 MC_(detect_memory_leaks_last_delta_mode));
331
332 if (xml) {
333 emit(" <kind>%s</kind>\n", xml_leak_kind(lr->key.state));
334 if (lr->indirect_szB > 0) {
335 emit( " <xwhat>\n" );
336 emit( " <text>%'lu%s (%'lu%s direct, %'lu%s indirect) bytes "
337 "in %'u%s blocks"
338 " are %s in loss record %'u of %'u</text>\n",
339 lr->szB + lr->indirect_szB, d_bytes,
340 lr->szB, d_direct_bytes,
341 lr->indirect_szB, d_indirect_bytes,
342 lr->num_blocks, d_num_blocks,
343 str_leak_lossmode(lr->key.state),
344 n_this_record, n_total_records );
345 // Nb: don't put commas in these XML numbers
346 emit( " <leakedbytes>%lu</leakedbytes>\n",
347 lr->szB + lr->indirect_szB );
348 emit( " <leakedblocks>%u</leakedblocks>\n", lr->num_blocks );
349 emit( " </xwhat>\n" );
350 } else {
351 emit( " <xwhat>\n" );
352 emit( " <text>%'lu%s bytes in %'u%s blocks"
353 " are %s in loss record %'u of %'u</text>\n",
354 lr->szB, d_direct_bytes,
355 lr->num_blocks, d_num_blocks,
356 str_leak_lossmode(lr->key.state),
357 n_this_record, n_total_records );
358 emit( " <leakedbytes>%ld</leakedbytes>\n", lr->szB);
359 emit( " <leakedblocks>%d</leakedblocks>\n", lr->num_blocks);
360 emit( " </xwhat>\n" );
361 }
362 VG_(pp_ExeContext)(lr->key.allocated_at);
363 } else { /* ! if (xml) */
364 if (lr->indirect_szB > 0) {
365 emit(
366 "%'lu%s (%'lu%s direct, %'lu%s indirect) bytes in %'u%s blocks"
367 " are %s in loss record %'u of %'u\n",
368 lr->szB + lr->indirect_szB, d_bytes,
369 lr->szB, d_direct_bytes,
370 lr->indirect_szB, d_indirect_bytes,
371 lr->num_blocks, d_num_blocks,
372 str_leak_lossmode(lr->key.state),
373 n_this_record, n_total_records
374 );
375 } else {
376 emit(
377 "%'lu%s bytes in %'u%s blocks are %s in loss record %'u of %'u\n",
378 lr->szB, d_direct_bytes,
379 lr->num_blocks, d_num_blocks,
380 str_leak_lossmode(lr->key.state),
381 n_this_record, n_total_records
382 );
383 }
384 VG_(pp_ExeContext)(lr->key.allocated_at);
385 } /* if (xml) */
386}
387
388void MC_(pp_LossRecord)(UInt n_this_record, UInt n_total_records,
389 LossRecord* l)
390{
391 pp_LossRecord (n_this_record, n_total_records, l, /* xml */ False);
392}
393
sewardj7ce71662008-05-02 10:33:15 +0000394void MC_(pp_Error) ( Error* err )
395{
sewardj6b523cd2009-07-15 14:49:40 +0000396 const Bool xml = VG_(clo_xml); /* a shorthand */
sewardj7ce71662008-05-02 10:33:15 +0000397 MC_Error* extra = VG_(get_error_extra)(err);
398
399 switch (VG_(get_error_kind)(err)) {
sewardj6b523cd2009-07-15 14:49:40 +0000400 case Err_CoreMem:
sewardj7ce71662008-05-02 10:33:15 +0000401 /* What the hell *is* a CoreMemError? jrs 2005-May-18 */
402 /* As of 2006-Dec-14, it's caused by unaddressable bytes in a
403 signal handler frame. --njn */
sewardj6b523cd2009-07-15 14:49:40 +0000404 // JRS 17 May 09: None of our regtests exercise this; hence AFAIK
405 // the following code is untested. Bad.
406 if (xml) {
407 emit( " <kind>CoreMemError</kind>\n" );
philippe6d0e77b2014-05-07 22:03:59 +0000408 emit( " <what>%pS contains unaddressable byte(s)</what>\n",
sewardj6b523cd2009-07-15 14:49:40 +0000409 VG_(get_error_string)(err));
410 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
411 } else {
412 emit( "%s contains unaddressable byte(s)\n",
413 VG_(get_error_string)(err));
414 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
415 }
sewardj7ce71662008-05-02 10:33:15 +0000416 break;
sewardj7ce71662008-05-02 10:33:15 +0000417
418 case Err_Value:
419 MC_(any_value_errors) = True;
sewardj6b523cd2009-07-15 14:49:40 +0000420 if (xml) {
421 emit( " <kind>UninitValue</kind>\n" );
422 emit( " <what>Use of uninitialised value of size %ld</what>\n",
423 extra->Err.Value.szB );
424 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
425 if (extra->Err.Value.origin_ec)
426 mc_pp_origin( extra->Err.Value.origin_ec,
427 extra->Err.Value.otag & 3 );
sewardj7ce71662008-05-02 10:33:15 +0000428 } else {
sewardj6b523cd2009-07-15 14:49:40 +0000429 /* Could also show extra->Err.Cond.otag if debugging origin
430 tracking */
431 emit( "Use of uninitialised value of size %ld\n",
432 extra->Err.Value.szB );
433 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
434 if (extra->Err.Value.origin_ec)
435 mc_pp_origin( extra->Err.Value.origin_ec,
436 extra->Err.Value.otag & 3 );
sewardj7ce71662008-05-02 10:33:15 +0000437 }
sewardj7ce71662008-05-02 10:33:15 +0000438 break;
439
440 case Err_Cond:
441 MC_(any_value_errors) = True;
sewardj6b523cd2009-07-15 14:49:40 +0000442 if (xml) {
443 emit( " <kind>UninitCondition</kind>\n" );
444 emit( " <what>Conditional jump or move depends"
445 " on uninitialised value(s)</what>\n" );
446 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
447 if (extra->Err.Cond.origin_ec)
448 mc_pp_origin( extra->Err.Cond.origin_ec,
449 extra->Err.Cond.otag & 3 );
sewardj7ce71662008-05-02 10:33:15 +0000450 } else {
sewardj6b523cd2009-07-15 14:49:40 +0000451 /* Could also show extra->Err.Cond.otag if debugging origin
452 tracking */
453 emit( "Conditional jump or move depends"
454 " on uninitialised value(s)\n" );
455 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
456 if (extra->Err.Cond.origin_ec)
457 mc_pp_origin( extra->Err.Cond.origin_ec,
458 extra->Err.Cond.otag & 3 );
sewardj7ce71662008-05-02 10:33:15 +0000459 }
sewardj7ce71662008-05-02 10:33:15 +0000460 break;
461
462 case Err_RegParam:
463 MC_(any_value_errors) = True;
sewardj6b523cd2009-07-15 14:49:40 +0000464 if (xml) {
465 emit( " <kind>SyscallParam</kind>\n" );
philippe6d0e77b2014-05-07 22:03:59 +0000466 emit( " <what>Syscall param %pS contains "
sewardj6b523cd2009-07-15 14:49:40 +0000467 "uninitialised byte(s)</what>\n",
468 VG_(get_error_string)(err) );
469 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
470 if (extra->Err.RegParam.origin_ec)
471 mc_pp_origin( extra->Err.RegParam.origin_ec,
472 extra->Err.RegParam.otag & 3 );
473 } else {
474 emit( "Syscall param %s contains uninitialised byte(s)\n",
475 VG_(get_error_string)(err) );
476 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
477 if (extra->Err.RegParam.origin_ec)
478 mc_pp_origin( extra->Err.RegParam.origin_ec,
479 extra->Err.RegParam.otag & 3 );
480 }
sewardj7ce71662008-05-02 10:33:15 +0000481 break;
482
483 case Err_MemParam:
484 if (!extra->Err.MemParam.isAddrErr)
485 MC_(any_value_errors) = True;
sewardj6b523cd2009-07-15 14:49:40 +0000486 if (xml) {
487 emit( " <kind>SyscallParam</kind>\n" );
philippe6d0e77b2014-05-07 22:03:59 +0000488 emit( " <what>Syscall param %pS points to %s byte(s)</what>\n",
sewardj6b523cd2009-07-15 14:49:40 +0000489 VG_(get_error_string)(err),
490 extra->Err.MemParam.isAddrErr
491 ? "unaddressable" : "uninitialised" );
492 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe07c08522014-05-14 20:39:27 +0000493 VG_(pp_addrinfo_mc)(VG_(get_error_address)(err),
494 &extra->Err.MemParam.ai, False);
sewardj6b523cd2009-07-15 14:49:40 +0000495 if (extra->Err.MemParam.origin_ec
496 && !extra->Err.MemParam.isAddrErr)
497 mc_pp_origin( extra->Err.MemParam.origin_ec,
498 extra->Err.MemParam.otag & 3 );
499 } else {
500 emit( "Syscall param %s points to %s byte(s)\n",
501 VG_(get_error_string)(err),
502 extra->Err.MemParam.isAddrErr
503 ? "unaddressable" : "uninitialised" );
504 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe07c08522014-05-14 20:39:27 +0000505 VG_(pp_addrinfo_mc)(VG_(get_error_address)(err),
506 &extra->Err.MemParam.ai, False);
sewardj6b523cd2009-07-15 14:49:40 +0000507 if (extra->Err.MemParam.origin_ec
508 && !extra->Err.MemParam.isAddrErr)
509 mc_pp_origin( extra->Err.MemParam.origin_ec,
510 extra->Err.MemParam.otag & 3 );
511 }
sewardj7ce71662008-05-02 10:33:15 +0000512 break;
513
514 case Err_User:
515 if (!extra->Err.User.isAddrErr)
516 MC_(any_value_errors) = True;
sewardj6b523cd2009-07-15 14:49:40 +0000517 if (xml) {
518 emit( " <kind>ClientCheck</kind>\n" );
519 emit( " <what>%s byte(s) found "
520 "during client check request</what>\n",
521 extra->Err.User.isAddrErr
522 ? "Unaddressable" : "Uninitialised" );
523 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe07c08522014-05-14 20:39:27 +0000524 VG_(pp_addrinfo_mc)(VG_(get_error_address)(err), &extra->Err.User.ai,
525 False);
sewardj6b523cd2009-07-15 14:49:40 +0000526 if (extra->Err.User.origin_ec && !extra->Err.User.isAddrErr)
527 mc_pp_origin( extra->Err.User.origin_ec,
528 extra->Err.User.otag & 3 );
529 } else {
530 emit( "%s byte(s) found during client check request\n",
531 extra->Err.User.isAddrErr
532 ? "Unaddressable" : "Uninitialised" );
533 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe07c08522014-05-14 20:39:27 +0000534 VG_(pp_addrinfo_mc)(VG_(get_error_address)(err), &extra->Err.User.ai,
535 False);
sewardj6b523cd2009-07-15 14:49:40 +0000536 if (extra->Err.User.origin_ec && !extra->Err.User.isAddrErr)
537 mc_pp_origin( extra->Err.User.origin_ec,
538 extra->Err.User.otag & 3 );
539 }
sewardj7ce71662008-05-02 10:33:15 +0000540 break;
541
542 case Err_Free:
sewardj6b523cd2009-07-15 14:49:40 +0000543 if (xml) {
544 emit( " <kind>InvalidFree</kind>\n" );
bart91347382011-03-25 20:07:25 +0000545 emit( " <what>Invalid free() / delete / delete[]"
546 " / realloc()</what>\n" );
sewardj6b523cd2009-07-15 14:49:40 +0000547 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe07c08522014-05-14 20:39:27 +0000548 VG_(pp_addrinfo_mc)( VG_(get_error_address)(err),
549 &extra->Err.Free.ai, False );
sewardj6b523cd2009-07-15 14:49:40 +0000550 } else {
bart91347382011-03-25 20:07:25 +0000551 emit( "Invalid free() / delete / delete[] / realloc()\n" );
sewardj6b523cd2009-07-15 14:49:40 +0000552 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe07c08522014-05-14 20:39:27 +0000553 VG_(pp_addrinfo_mc)( VG_(get_error_address)(err),
554 &extra->Err.Free.ai, False );
sewardj6b523cd2009-07-15 14:49:40 +0000555 }
sewardj7ce71662008-05-02 10:33:15 +0000556 break;
557
558 case Err_FreeMismatch:
sewardj6b523cd2009-07-15 14:49:40 +0000559 if (xml) {
560 emit( " <kind>MismatchedFree</kind>\n" );
561 emit( " <what>Mismatched free() / delete / delete []</what>\n" );
562 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe07c08522014-05-14 20:39:27 +0000563 VG_(pp_addrinfo_mc)(VG_(get_error_address)(err),
564 &extra->Err.FreeMismatch.ai, False);
sewardj6b523cd2009-07-15 14:49:40 +0000565 } else {
566 emit( "Mismatched free() / delete / delete []\n" );
567 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe07c08522014-05-14 20:39:27 +0000568 VG_(pp_addrinfo_mc)(VG_(get_error_address)(err),
569 &extra->Err.FreeMismatch.ai, False);
sewardj6b523cd2009-07-15 14:49:40 +0000570 }
sewardj7ce71662008-05-02 10:33:15 +0000571 break;
572
573 case Err_Addr:
sewardj6b523cd2009-07-15 14:49:40 +0000574 if (xml) {
575 emit( " <kind>Invalid%s</kind>\n",
576 extra->Err.Addr.isWrite ? "Write" : "Read" );
577 emit( " <what>Invalid %s of size %ld</what>\n",
578 extra->Err.Addr.isWrite ? "write" : "read",
579 extra->Err.Addr.szB );
580 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe07c08522014-05-14 20:39:27 +0000581 VG_(pp_addrinfo_mc)( VG_(get_error_address)(err),
582 &extra->Err.Addr.ai,
583 extra->Err.Addr.maybe_gcc );
sewardj7ce71662008-05-02 10:33:15 +0000584 } else {
sewardj6b523cd2009-07-15 14:49:40 +0000585 emit( "Invalid %s of size %ld\n",
586 extra->Err.Addr.isWrite ? "write" : "read",
587 extra->Err.Addr.szB );
588 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
589
philippe07c08522014-05-14 20:39:27 +0000590 VG_(pp_addrinfo_mc)( VG_(get_error_address)(err),
591 &extra->Err.Addr.ai,
592 extra->Err.Addr.maybe_gcc );
sewardj7ce71662008-05-02 10:33:15 +0000593 }
sewardj7ce71662008-05-02 10:33:15 +0000594 break;
595
596 case Err_Jump:
sewardj6b523cd2009-07-15 14:49:40 +0000597 if (xml) {
598 emit( " <kind>InvalidJump</kind>\n" );
599 emit( " <what>Jump to the invalid address stated "
600 "on the next line</what>\n" );
601 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe07c08522014-05-14 20:39:27 +0000602 VG_(pp_addrinfo_mc)( VG_(get_error_address)(err), &extra->Err.Jump.ai,
603 False );
sewardj6b523cd2009-07-15 14:49:40 +0000604 } else {
605 emit( "Jump to the invalid address stated on the next line\n" );
606 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe07c08522014-05-14 20:39:27 +0000607 VG_(pp_addrinfo_mc)( VG_(get_error_address)(err), &extra->Err.Jump.ai,
608 False );
sewardj6b523cd2009-07-15 14:49:40 +0000609 }
sewardj7ce71662008-05-02 10:33:15 +0000610 break;
611
612 case Err_Overlap:
sewardj6b523cd2009-07-15 14:49:40 +0000613 if (xml) {
614 emit( " <kind>Overlap</kind>\n" );
615 if (extra->Err.Overlap.szB == 0) {
philippe6d0e77b2014-05-07 22:03:59 +0000616 emit( " <what>Source and destination overlap "
bartb3af9cf2011-10-06 19:08:37 +0000617 "in %pS(%#lx, %#lx)\n</what>\n",
sewardj6b523cd2009-07-15 14:49:40 +0000618 VG_(get_error_string)(err),
619 extra->Err.Overlap.dst, extra->Err.Overlap.src );
620 } else {
621 emit( " <what>Source and destination overlap "
florian6a90cfb2014-06-26 11:30:05 +0000622 "in %pS(%#lx, %#lx, %lu)</what>\n",
sewardj6b523cd2009-07-15 14:49:40 +0000623 VG_(get_error_string)(err),
624 extra->Err.Overlap.dst, extra->Err.Overlap.src,
625 extra->Err.Overlap.szB );
626 }
627 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
628 } else {
629 if (extra->Err.Overlap.szB == 0) {
florian6a90cfb2014-06-26 11:30:05 +0000630 emit( "Source and destination overlap in %s(%#lx, %#lx)\n",
sewardj6b523cd2009-07-15 14:49:40 +0000631 VG_(get_error_string)(err),
632 extra->Err.Overlap.dst, extra->Err.Overlap.src );
633 } else {
philippedfa54a52013-03-13 21:44:07 +0000634 emit( "Source and destination overlap in %s(%#lx, %#lx, %lu)\n",
sewardj6b523cd2009-07-15 14:49:40 +0000635 VG_(get_error_string)(err),
636 extra->Err.Overlap.dst, extra->Err.Overlap.src,
637 extra->Err.Overlap.szB );
638 }
639 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
640 }
sewardj7ce71662008-05-02 10:33:15 +0000641 break;
642
643 case Err_IllegalMempool:
sewardj6b523cd2009-07-15 14:49:40 +0000644 // JRS 17 May 09: None of our regtests exercise this; hence AFAIK
645 // the following code is untested. Bad.
646 if (xml) {
647 emit( " <kind>InvalidMemPool</kind>\n" );
648 emit( " <what>Illegal memory pool address</what>\n" );
649 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe07c08522014-05-14 20:39:27 +0000650 VG_(pp_addrinfo_mc)( VG_(get_error_address)(err),
651 &extra->Err.IllegalMempool.ai, False );
sewardj6b523cd2009-07-15 14:49:40 +0000652 } else {
653 emit( "Illegal memory pool address\n" );
654 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
philippe07c08522014-05-14 20:39:27 +0000655 VG_(pp_addrinfo_mc)( VG_(get_error_address)(err),
656 &extra->Err.IllegalMempool.ai, False );
sewardj6b523cd2009-07-15 14:49:40 +0000657 }
sewardj7ce71662008-05-02 10:33:15 +0000658 break;
659
660 case Err_Leak: {
sewardj7ce71662008-05-02 10:33:15 +0000661 UInt n_this_record = extra->Err.Leak.n_this_record;
662 UInt n_total_records = extra->Err.Leak.n_total_records;
njnb7a4e2e2009-05-01 00:30:43 +0000663 LossRecord* lr = extra->Err.Leak.lr;
philippea22f59d2012-01-26 23:13:52 +0000664 pp_LossRecord (n_this_record, n_total_records, lr, xml);
sewardj7ce71662008-05-02 10:33:15 +0000665 break;
666 }
667
florian7b6899d2014-07-13 14:41:55 +0000668 case Err_FishyValue:
669 if (xml) {
670 emit( " <kind>FishyValue</kind>\n" );
671 emit( " <what>");
672 emit( "Argument '%s' of function %s has a fishy "
673 "(possibly negative) value: %ld\n",
674 extra->Err.FishyValue.argument_name,
675 extra->Err.FishyValue.function_name,
676 (SSizeT)extra->Err.FishyValue.value);
677 emit( "</what>");
678 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
679 } else {
680 emit( "Argument '%s' of function %s has a fishy "
681 "(possibly negative) value: %ld\n",
682 extra->Err.FishyValue.argument_name,
683 extra->Err.FishyValue.function_name,
684 (SSizeT)extra->Err.FishyValue.value);
685 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
686 }
687 break;
688
sewardj7ce71662008-05-02 10:33:15 +0000689 default:
690 VG_(printf)("Error:\n unknown Memcheck error code %d\n",
691 VG_(get_error_kind)(err));
692 VG_(tool_panic)("unknown error code in mc_pp_Error)");
693 }
694}
695
696/*------------------------------------------------------------*/
697/*--- Recording errors ---*/
698/*------------------------------------------------------------*/
699
700/* These many bytes below %ESP are considered addressible if we're
701 doing the --workaround-gcc296-bugs hack. */
702#define VG_GCC296_BUG_STACK_SLOP 1024
703
704/* Is this address within some small distance below %ESP? Used only
705 for the --workaround-gcc296-bugs kludge. */
706static Bool is_just_below_ESP( Addr esp, Addr aa )
707{
sewardj7d751b22010-07-21 12:46:44 +0000708 esp -= VG_STACK_REDZONE_SZB;
sewardj7ce71662008-05-02 10:33:15 +0000709 if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
710 return True;
711 else
712 return False;
713}
714
715/* --- Called from generated and non-generated code --- */
716
717void MC_(record_address_error) ( ThreadId tid, Addr a, Int szB,
718 Bool isWrite )
719{
720 MC_Error extra;
721 Bool just_below_esp;
722
723 if (MC_(in_ignored_range)(a))
724 return;
725
sewardj3b290482011-05-06 21:02:55 +0000726 if (VG_(is_watched)( (isWrite ? write_watchpoint : read_watchpoint), a, szB))
727 return;
728
sewardj7ce71662008-05-02 10:33:15 +0000729 just_below_esp = is_just_below_ESP( VG_(get_SP)(tid), a );
730
731 /* If this is caused by an access immediately below %ESP, and the
732 user asks nicely, we just ignore it. */
733 if (MC_(clo_workaround_gcc296_bugs) && just_below_esp)
734 return;
735
736 extra.Err.Addr.isWrite = isWrite;
737 extra.Err.Addr.szB = szB;
738 extra.Err.Addr.maybe_gcc = just_below_esp;
739 extra.Err.Addr.ai.tag = Addr_Undescribed;
740 VG_(maybe_record_error)( tid, Err_Addr, a, /*s*/NULL, &extra );
741}
742
743void MC_(record_value_error) ( ThreadId tid, Int szB, UInt otag )
744{
745 MC_Error extra;
746 tl_assert( MC_(clo_mc_level) >= 2 );
747 if (otag > 0)
748 tl_assert( MC_(clo_mc_level) == 3 );
749 extra.Err.Value.szB = szB;
750 extra.Err.Value.otag = otag;
751 extra.Err.Value.origin_ec = NULL; /* Filled in later */
752 VG_(maybe_record_error)( tid, Err_Value, /*addr*/0, /*s*/NULL, &extra );
753}
754
755void MC_(record_cond_error) ( ThreadId tid, UInt otag )
756{
757 MC_Error extra;
758 tl_assert( MC_(clo_mc_level) >= 2 );
759 if (otag > 0)
760 tl_assert( MC_(clo_mc_level) == 3 );
761 extra.Err.Cond.otag = otag;
762 extra.Err.Cond.origin_ec = NULL; /* Filled in later */
763 VG_(maybe_record_error)( tid, Err_Cond, /*addr*/0, /*s*/NULL, &extra );
764}
765
766/* --- Called from non-generated code --- */
767
njn1dcee092009-02-24 03:07:37 +0000768/* This is for memory errors in signal-related memory. */
floriane543f302012-10-21 19:43:43 +0000769void MC_(record_core_mem_error) ( ThreadId tid, const HChar* msg )
sewardj7ce71662008-05-02 10:33:15 +0000770{
771 VG_(maybe_record_error)( tid, Err_CoreMem, /*addr*/0, msg, /*extra*/NULL );
772}
773
floriane543f302012-10-21 19:43:43 +0000774void MC_(record_regparam_error) ( ThreadId tid, const HChar* msg, UInt otag )
sewardj7ce71662008-05-02 10:33:15 +0000775{
776 MC_Error extra;
777 tl_assert(VG_INVALID_THREADID != tid);
778 if (otag > 0)
779 tl_assert( MC_(clo_mc_level) == 3 );
780 extra.Err.RegParam.otag = otag;
781 extra.Err.RegParam.origin_ec = NULL; /* Filled in later */
782 VG_(maybe_record_error)( tid, Err_RegParam, /*addr*/0, msg, &extra );
783}
784
785void MC_(record_memparam_error) ( ThreadId tid, Addr a,
floriane543f302012-10-21 19:43:43 +0000786 Bool isAddrErr, const HChar* msg, UInt otag )
sewardj7ce71662008-05-02 10:33:15 +0000787{
788 MC_Error extra;
789 tl_assert(VG_INVALID_THREADID != tid);
790 if (!isAddrErr)
791 tl_assert( MC_(clo_mc_level) >= 2 );
792 if (otag != 0) {
793 tl_assert( MC_(clo_mc_level) == 3 );
794 tl_assert( !isAddrErr );
795 }
796 extra.Err.MemParam.isAddrErr = isAddrErr;
797 extra.Err.MemParam.ai.tag = Addr_Undescribed;
798 extra.Err.MemParam.otag = otag;
799 extra.Err.MemParam.origin_ec = NULL; /* Filled in later */
800 VG_(maybe_record_error)( tid, Err_MemParam, a, msg, &extra );
801}
802
803void MC_(record_jump_error) ( ThreadId tid, Addr a )
804{
805 MC_Error extra;
806 tl_assert(VG_INVALID_THREADID != tid);
807 extra.Err.Jump.ai.tag = Addr_Undescribed;
808 VG_(maybe_record_error)( tid, Err_Jump, a, /*s*/NULL, &extra );
809}
810
811void MC_(record_free_error) ( ThreadId tid, Addr a )
812{
813 MC_Error extra;
814 tl_assert(VG_INVALID_THREADID != tid);
815 extra.Err.Free.ai.tag = Addr_Undescribed;
816 VG_(maybe_record_error)( tid, Err_Free, a, /*s*/NULL, &extra );
817}
818
819void MC_(record_freemismatch_error) ( ThreadId tid, MC_Chunk* mc )
820{
821 MC_Error extra;
822 AddrInfo* ai = &extra.Err.FreeMismatch.ai;
823 tl_assert(VG_INVALID_THREADID != tid);
824 ai->tag = Addr_Block;
825 ai->Addr.Block.block_kind = Block_Mallocd; // Nb: Not 'Block_Freed'
826 ai->Addr.Block.block_desc = "block";
827 ai->Addr.Block.block_szB = mc->szB;
828 ai->Addr.Block.rwoffset = 0;
philippe8617b5b2013-01-12 19:53:08 +0000829 ai->Addr.Block.allocated_at = MC_(allocated_at) (mc);
philippe0c9ac8d2014-07-18 00:03:58 +0000830 VG_(initThreadInfo) (&ai->Addr.Block.alloc_tinfo);
philippe8617b5b2013-01-12 19:53:08 +0000831 ai->Addr.Block.freed_at = MC_(freed_at) (mc);
sewardj7ce71662008-05-02 10:33:15 +0000832 VG_(maybe_record_error)( tid, Err_FreeMismatch, mc->data, /*s*/NULL,
833 &extra );
834}
835
836void MC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )
837{
838 MC_Error extra;
839 tl_assert(VG_INVALID_THREADID != tid);
840 extra.Err.IllegalMempool.ai.tag = Addr_Undescribed;
841 VG_(maybe_record_error)( tid, Err_IllegalMempool, a, /*s*/NULL, &extra );
842}
843
floriane543f302012-10-21 19:43:43 +0000844void MC_(record_overlap_error) ( ThreadId tid, const HChar* function,
sewardj7ce71662008-05-02 10:33:15 +0000845 Addr src, Addr dst, SizeT szB )
846{
847 MC_Error extra;
848 tl_assert(VG_INVALID_THREADID != tid);
849 extra.Err.Overlap.src = src;
850 extra.Err.Overlap.dst = dst;
851 extra.Err.Overlap.szB = szB;
852 VG_(maybe_record_error)(
853 tid, Err_Overlap, /*addr*/0, /*s*/function, &extra );
854}
855
856Bool MC_(record_leak_error) ( ThreadId tid, UInt n_this_record,
njnb7a4e2e2009-05-01 00:30:43 +0000857 UInt n_total_records, LossRecord* lr,
njn18afe5d2009-08-10 08:25:39 +0000858 Bool print_record, Bool count_error )
sewardj7ce71662008-05-02 10:33:15 +0000859{
860 MC_Error extra;
861 extra.Err.Leak.n_this_record = n_this_record;
862 extra.Err.Leak.n_total_records = n_total_records;
njnb7a4e2e2009-05-01 00:30:43 +0000863 extra.Err.Leak.lr = lr;
sewardj7ce71662008-05-02 10:33:15 +0000864 return
865 VG_(unique_error) ( tid, Err_Leak, /*Addr*/0, /*s*/NULL, &extra,
njn29a5c012009-05-06 06:15:55 +0000866 lr->key.allocated_at, print_record,
njn18afe5d2009-08-10 08:25:39 +0000867 /*allow_GDB_attach*/False, count_error );
sewardj7ce71662008-05-02 10:33:15 +0000868}
869
florian7b6899d2014-07-13 14:41:55 +0000870Bool MC_(record_fishy_value_error) ( ThreadId tid, const HChar *function_name,
871 const HChar *argument_name, SizeT value)
872{
873 MC_Error extra;
874
875 tl_assert(VG_INVALID_THREADID != tid);
876
877 if ((SSizeT)value >= 0) return False; // not a fishy value
878
879 extra.Err.FishyValue.function_name = function_name;
880 extra.Err.FishyValue.argument_name = argument_name;
881 extra.Err.FishyValue.value = value;
882
883 VG_(maybe_record_error)(
884 tid, Err_FishyValue, /*addr*/0, /*s*/NULL, &extra );
885
886 return True;
887}
888
sewardj7ce71662008-05-02 10:33:15 +0000889void MC_(record_user_error) ( ThreadId tid, Addr a,
890 Bool isAddrErr, UInt otag )
891{
892 MC_Error extra;
893 if (otag != 0) {
894 tl_assert(!isAddrErr);
895 tl_assert( MC_(clo_mc_level) == 3 );
896 }
897 if (!isAddrErr) {
898 tl_assert( MC_(clo_mc_level) >= 2 );
899 }
900 tl_assert(VG_INVALID_THREADID != tid);
901 extra.Err.User.isAddrErr = isAddrErr;
902 extra.Err.User.ai.tag = Addr_Undescribed;
903 extra.Err.User.otag = otag;
904 extra.Err.User.origin_ec = NULL; /* Filled in later */
905 VG_(maybe_record_error)( tid, Err_User, a, /*s*/NULL, &extra );
906}
907
908/*------------------------------------------------------------*/
909/*--- Other error operations ---*/
910/*------------------------------------------------------------*/
911
912/* Compare error contexts, to detect duplicates. Note that if they
913 are otherwise the same, the faulting addrs and associated rwoffsets
914 are allowed to be different. */
915Bool MC_(eq_Error) ( VgRes res, Error* e1, Error* e2 )
916{
917 MC_Error* extra1 = VG_(get_error_extra)(e1);
918 MC_Error* extra2 = VG_(get_error_extra)(e2);
919
920 /* Guaranteed by calling function */
921 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
922
923 switch (VG_(get_error_kind)(e1)) {
924 case Err_CoreMem: {
floriane543f302012-10-21 19:43:43 +0000925 const HChar *e1s, *e2s;
sewardj7ce71662008-05-02 10:33:15 +0000926 e1s = VG_(get_error_string)(e1);
927 e2s = VG_(get_error_string)(e2);
928 if (e1s == e2s) return True;
929 if (VG_STREQ(e1s, e2s)) return True;
930 return False;
931 }
932
933 case Err_RegParam:
934 return VG_STREQ(VG_(get_error_string)(e1), VG_(get_error_string)(e2));
935
936 // Perhaps we should also check the addrinfo.akinds for equality.
937 // That would result in more error reports, but only in cases where
938 // a register contains uninitialised bytes and points to memory
939 // containing uninitialised bytes. Currently, the 2nd of those to be
940 // detected won't be reported. That is (nearly?) always the memory
941 // error, which is good.
942 case Err_MemParam:
943 if (!VG_STREQ(VG_(get_error_string)(e1),
944 VG_(get_error_string)(e2))) return False;
945 // fall through
946 case Err_User:
947 return ( extra1->Err.User.isAddrErr == extra2->Err.User.isAddrErr
948 ? True : False );
949
950 case Err_Free:
951 case Err_FreeMismatch:
952 case Err_Jump:
953 case Err_IllegalMempool:
954 case Err_Overlap:
955 case Err_Cond:
956 return True;
957
florian7b6899d2014-07-13 14:41:55 +0000958 case Err_FishyValue:
959 return VG_STREQ(extra1->Err.FishyValue.function_name,
960 extra2->Err.FishyValue.function_name) &&
961 VG_STREQ(extra1->Err.FishyValue.argument_name,
962 extra2->Err.FishyValue.argument_name);
963
sewardj7ce71662008-05-02 10:33:15 +0000964 case Err_Addr:
965 return ( extra1->Err.Addr.szB == extra2->Err.Addr.szB
966 ? True : False );
967
968 case Err_Value:
969 return ( extra1->Err.Value.szB == extra2->Err.Value.szB
970 ? True : False );
971
972 case Err_Leak:
973 VG_(tool_panic)("Shouldn't get Err_Leak in mc_eq_Error,\n"
974 "since it's handled with VG_(unique_error)()!");
975
976 default:
977 VG_(printf)("Error:\n unknown error code %d\n",
978 VG_(get_error_kind)(e1));
979 VG_(tool_panic)("unknown error code in mc_eq_Error");
980 }
981}
982
sewardj62b91042011-01-23 20:45:53 +0000983/* Functions used when searching MC_Chunk lists */
984static
985Bool addr_is_in_MC_Chunk_default_REDZONE_SZB(MC_Chunk* mc, Addr a)
sewardj7ce71662008-05-02 10:33:15 +0000986{
sewardj7ce71662008-05-02 10:33:15 +0000987 return VG_(addr_is_in_block)( a, mc->data, mc->szB,
philipped99c26a2012-07-31 22:17:28 +0000988 MC_(Malloc_Redzone_SzB) );
sewardj7ce71662008-05-02 10:33:15 +0000989}
sewardj62b91042011-01-23 20:45:53 +0000990static
991Bool addr_is_in_MC_Chunk_with_REDZONE_SZB(MC_Chunk* mc, Addr a, SizeT rzB)
992{
993 return VG_(addr_is_in_block)( a, mc->data, mc->szB,
994 rzB );
995}
sewardj7ce71662008-05-02 10:33:15 +0000996
sewardj62b91042011-01-23 20:45:53 +0000997// Forward declarations
sewardj7ce71662008-05-02 10:33:15 +0000998static Bool client_block_maybe_describe( Addr a, AddrInfo* ai );
sewardj62b91042011-01-23 20:45:53 +0000999static Bool mempool_block_maybe_describe( Addr a, AddrInfo* ai );
sewardj7ce71662008-05-02 10:33:15 +00001000
1001
1002/* Describe an address as best you can, for error messages,
1003 putting the result in ai. */
1004static void describe_addr ( Addr a, /*OUT*/AddrInfo* ai )
1005{
1006 MC_Chunk* mc;
sewardj7ce71662008-05-02 10:33:15 +00001007
1008 tl_assert(Addr_Undescribed == ai->tag);
1009
sewardj62b91042011-01-23 20:45:53 +00001010 /* -- Perhaps it's a user-named block? -- */
sewardj7ce71662008-05-02 10:33:15 +00001011 if (client_block_maybe_describe( a, ai )) {
1012 return;
1013 }
sewardj62b91042011-01-23 20:45:53 +00001014 /* -- Perhaps it's in mempool block? -- */
1015 if (mempool_block_maybe_describe( a, ai )) {
1016 return;
1017 }
philippe11cc9ce2012-03-11 17:59:00 +00001018 /* Blocks allocated by memcheck malloc functions are either
1019 on the recently freed list or on the malloc-ed list.
1020 Custom blocks can be on both : a recently freed block might
1021 have been just re-allocated.
1022 So, first search the malloc-ed block, as the most recent
1023 block is the probable cause of error.
1024 We however detect and report that this is a recently re-allocated
1025 block. */
1026 /* -- Search for a currently malloc'd block which might bracket it. -- */
1027 VG_(HT_ResetIter)(MC_(malloc_list));
1028 while ( (mc = VG_(HT_Next)(MC_(malloc_list))) ) {
1029 if (addr_is_in_MC_Chunk_default_REDZONE_SZB(mc, a)) {
1030 ai->tag = Addr_Block;
1031 ai->Addr.Block.block_kind = Block_Mallocd;
1032 if (MC_(get_freed_block_bracketting)( a ))
1033 ai->Addr.Block.block_desc = "recently re-allocated block";
1034 else
1035 ai->Addr.Block.block_desc = "block";
1036 ai->Addr.Block.block_szB = mc->szB;
1037 ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
philippe8617b5b2013-01-12 19:53:08 +00001038 ai->Addr.Block.allocated_at = MC_(allocated_at)(mc);
philippe0c9ac8d2014-07-18 00:03:58 +00001039 VG_(initThreadInfo) (&ai->Addr.Block.alloc_tinfo);
philippe8617b5b2013-01-12 19:53:08 +00001040 ai->Addr.Block.freed_at = MC_(freed_at)(mc);
philippe11cc9ce2012-03-11 17:59:00 +00001041 return;
1042 }
1043 }
sewardj6b523cd2009-07-15 14:49:40 +00001044 /* -- Search for a recently freed block which might bracket it. -- */
sewardj403d8aa2011-10-22 19:48:57 +00001045 mc = MC_(get_freed_block_bracketting)( a );
1046 if (mc) {
1047 ai->tag = Addr_Block;
1048 ai->Addr.Block.block_kind = Block_Freed;
1049 ai->Addr.Block.block_desc = "block";
1050 ai->Addr.Block.block_szB = mc->szB;
1051 ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
philippe8617b5b2013-01-12 19:53:08 +00001052 ai->Addr.Block.allocated_at = MC_(allocated_at)(mc);
philippe0c9ac8d2014-07-18 00:03:58 +00001053 VG_(initThreadInfo) (&ai->Addr.Block.alloc_tinfo);
philippe8617b5b2013-01-12 19:53:08 +00001054 ai->Addr.Block.freed_at = MC_(freed_at)(mc);
sewardj403d8aa2011-10-22 19:48:57 +00001055 return;
sewardj7ce71662008-05-02 10:33:15 +00001056 }
sewardj6b523cd2009-07-15 14:49:40 +00001057
philippe07c08522014-05-14 20:39:27 +00001058 /* No block found. Search a non-heap block description. */
1059 VG_(describe_addr) (a, ai);
sewardj7ce71662008-05-02 10:33:15 +00001060}
1061
sewardj3b290482011-05-06 21:02:55 +00001062void MC_(pp_describe_addr) ( Addr a )
1063{
1064 AddrInfo ai;
1065
1066 ai.tag = Addr_Undescribed;
1067 describe_addr (a, &ai);
philippe07c08522014-05-14 20:39:27 +00001068 VG_(pp_addrinfo_mc) (a, &ai, /* maybe_gcc */ False);
sewardj3b290482011-05-06 21:02:55 +00001069}
1070
sewardj7ce71662008-05-02 10:33:15 +00001071/* Fill in *origin_ec as specified by otag, or NULL it out if otag
1072 does not refer to a known origin. */
1073static void update_origin ( /*OUT*/ExeContext** origin_ec,
1074 UInt otag )
1075{
1076 UInt ecu = otag & ~3;
1077 *origin_ec = NULL;
1078 if (VG_(is_plausible_ECU)(ecu)) {
1079 *origin_ec = VG_(get_ExeContext_from_ECU)( ecu );
1080 }
1081}
1082
1083/* Updates the copy with address info if necessary (but not for all errors). */
1084UInt MC_(update_Error_extra)( Error* err )
1085{
1086 MC_Error* extra = VG_(get_error_extra)(err);
1087
1088 switch (VG_(get_error_kind)(err)) {
1089 // These ones don't have addresses associated with them, and so don't
1090 // need any updating.
1091 case Err_CoreMem:
1092 //case Err_Value:
1093 //case Err_Cond:
1094 case Err_Overlap:
florian7b6899d2014-07-13 14:41:55 +00001095 case Err_FishyValue:
sewardj7ce71662008-05-02 10:33:15 +00001096 // For Err_Leaks the returned size does not matter -- they are always
1097 // shown with VG_(unique_error)() so they 'extra' not copied. But
1098 // we make it consistent with the others.
1099 case Err_Leak:
1100 return sizeof(MC_Error);
1101
1102 // For value errors, get the ExeContext corresponding to the
1103 // origin tag. Note that it is a kludge to assume that
1104 // a length-1 trace indicates a stack origin. FIXME.
1105 case Err_Value:
1106 update_origin( &extra->Err.Value.origin_ec,
1107 extra->Err.Value.otag );
1108 return sizeof(MC_Error);
1109 case Err_Cond:
1110 update_origin( &extra->Err.Cond.origin_ec,
1111 extra->Err.Cond.otag );
1112 return sizeof(MC_Error);
1113 case Err_RegParam:
1114 update_origin( &extra->Err.RegParam.origin_ec,
1115 extra->Err.RegParam.otag );
1116 return sizeof(MC_Error);
1117
1118 // These ones always involve a memory address.
1119 case Err_Addr:
1120 describe_addr ( VG_(get_error_address)(err),
1121 &extra->Err.Addr.ai );
1122 return sizeof(MC_Error);
1123 case Err_MemParam:
1124 describe_addr ( VG_(get_error_address)(err),
1125 &extra->Err.MemParam.ai );
1126 update_origin( &extra->Err.MemParam.origin_ec,
1127 extra->Err.MemParam.otag );
1128 return sizeof(MC_Error);
1129 case Err_Jump:
1130 describe_addr ( VG_(get_error_address)(err),
1131 &extra->Err.Jump.ai );
1132 return sizeof(MC_Error);
1133 case Err_User:
1134 describe_addr ( VG_(get_error_address)(err),
1135 &extra->Err.User.ai );
1136 update_origin( &extra->Err.User.origin_ec,
1137 extra->Err.User.otag );
1138 return sizeof(MC_Error);
1139 case Err_Free:
1140 describe_addr ( VG_(get_error_address)(err),
1141 &extra->Err.Free.ai );
1142 return sizeof(MC_Error);
1143 case Err_IllegalMempool:
1144 describe_addr ( VG_(get_error_address)(err),
1145 &extra->Err.IllegalMempool.ai );
1146 return sizeof(MC_Error);
1147
1148 // Err_FreeMismatches have already had their address described; this is
1149 // possible because we have the MC_Chunk on hand when the error is
1150 // detected. However, the address may be part of a user block, and if so
1151 // we override the pre-determined description with a user block one.
1152 case Err_FreeMismatch: {
1153 tl_assert(extra && Block_Mallocd ==
1154 extra->Err.FreeMismatch.ai.Addr.Block.block_kind);
1155 (void)client_block_maybe_describe( VG_(get_error_address)(err),
1156 &extra->Err.FreeMismatch.ai );
1157 return sizeof(MC_Error);
1158 }
1159
1160 default: VG_(tool_panic)("mc_update_extra: bad errkind");
1161 }
1162}
1163
sewardj62b91042011-01-23 20:45:53 +00001164
sewardj7ce71662008-05-02 10:33:15 +00001165static Bool client_block_maybe_describe( Addr a,
1166 /*OUT*/AddrInfo* ai )
1167{
sewardj56adc352008-05-02 11:25:17 +00001168 UWord i;
sewardj7ce71662008-05-02 10:33:15 +00001169 CGenBlock* cgbs = NULL;
1170 UWord cgb_used = 0;
sewardj56adc352008-05-02 11:25:17 +00001171
sewardj7ce71662008-05-02 10:33:15 +00001172 MC_(get_ClientBlock_array)( &cgbs, &cgb_used );
1173 if (cgbs == NULL)
1174 tl_assert(cgb_used == 0);
1175
1176 /* Perhaps it's a general block ? */
1177 for (i = 0; i < cgb_used; i++) {
1178 if (cgbs[i].start == 0 && cgbs[i].size == 0)
1179 continue;
1180 // Use zero as the redzone for client blocks.
1181 if (VG_(addr_is_in_block)(a, cgbs[i].start, cgbs[i].size, 0)) {
sewardj7ce71662008-05-02 10:33:15 +00001182 ai->tag = Addr_Block;
1183 ai->Addr.Block.block_kind = Block_UserG;
1184 ai->Addr.Block.block_desc = cgbs[i].desc;
1185 ai->Addr.Block.block_szB = cgbs[i].size;
sewardj56adc352008-05-02 11:25:17 +00001186 ai->Addr.Block.rwoffset = (Word)(a) - (Word)(cgbs[i].start);
philippe8617b5b2013-01-12 19:53:08 +00001187 ai->Addr.Block.allocated_at = cgbs[i].where;
philippe0c9ac8d2014-07-18 00:03:58 +00001188 VG_(initThreadInfo) (&ai->Addr.Block.alloc_tinfo);
philippe8617b5b2013-01-12 19:53:08 +00001189 ai->Addr.Block.freed_at = VG_(null_ExeContext)();;
sewardj7ce71662008-05-02 10:33:15 +00001190 return True;
1191 }
1192 }
1193 return False;
1194}
1195
1196
sewardj62b91042011-01-23 20:45:53 +00001197static Bool mempool_block_maybe_describe( Addr a,
1198 /*OUT*/AddrInfo* ai )
1199{
1200 MC_Mempool* mp;
1201 tl_assert( MC_(mempool_list) );
1202
1203 VG_(HT_ResetIter)( MC_(mempool_list) );
1204 while ( (mp = VG_(HT_Next)(MC_(mempool_list))) ) {
1205 if (mp->chunks != NULL) {
1206 MC_Chunk* mc;
1207 VG_(HT_ResetIter)(mp->chunks);
1208 while ( (mc = VG_(HT_Next)(mp->chunks)) ) {
1209 if (addr_is_in_MC_Chunk_with_REDZONE_SZB(mc, a, mp->rzB)) {
1210 ai->tag = Addr_Block;
1211 ai->Addr.Block.block_kind = Block_MempoolChunk;
1212 ai->Addr.Block.block_desc = "block";
1213 ai->Addr.Block.block_szB = mc->szB;
1214 ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
philippe8617b5b2013-01-12 19:53:08 +00001215 ai->Addr.Block.allocated_at = MC_(allocated_at)(mc);
philippe0c9ac8d2014-07-18 00:03:58 +00001216 VG_(initThreadInfo) (&ai->Addr.Block.alloc_tinfo);
philippe8617b5b2013-01-12 19:53:08 +00001217 ai->Addr.Block.freed_at = MC_(freed_at)(mc);
sewardj62b91042011-01-23 20:45:53 +00001218 return True;
1219 }
1220 }
1221 }
1222 }
1223 return False;
1224}
1225
1226
sewardj7ce71662008-05-02 10:33:15 +00001227/*------------------------------------------------------------*/
1228/*--- Suppressions ---*/
1229/*------------------------------------------------------------*/
1230
1231typedef
1232 enum {
1233 ParamSupp, // Bad syscall params
1234 UserSupp, // Errors arising from client-request checks
1235 CoreMemSupp, // Memory errors in core (pthread ops, signal handling)
1236
1237 // Undefined value errors of given size
1238 Value1Supp, Value2Supp, Value4Supp, Value8Supp, Value16Supp,
1239
1240 // Undefined value error in conditional.
1241 CondSupp,
1242
1243 // Unaddressable read/write attempt at given size
1244 Addr1Supp, Addr2Supp, Addr4Supp, Addr8Supp, Addr16Supp,
1245
1246 JumpSupp, // Jump to unaddressable target
1247 FreeSupp, // Invalid or mismatching free
1248 OverlapSupp, // Overlapping blocks in memcpy(), strcpy(), etc
1249 LeakSupp, // Something to be suppressed in a leak check.
1250 MempoolSupp, // Memory pool suppression.
florian7b6899d2014-07-13 14:41:55 +00001251 FishyValueSupp,// Fishy value suppression.
sewardj7ce71662008-05-02 10:33:15 +00001252 }
1253 MC_SuppKind;
1254
florian19f91bb2012-11-10 22:29:54 +00001255Bool MC_(is_recognised_suppression) ( const HChar* name, Supp* su )
sewardj7ce71662008-05-02 10:33:15 +00001256{
1257 SuppKind skind;
1258
1259 if (VG_STREQ(name, "Param")) skind = ParamSupp;
1260 else if (VG_STREQ(name, "User")) skind = UserSupp;
1261 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
1262 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
1263 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
1264 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
1265 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
1266 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
1267 else if (VG_STREQ(name, "Jump")) skind = JumpSupp;
1268 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
1269 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
1270 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
1271 else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
1272 else if (VG_STREQ(name, "Cond")) skind = CondSupp;
1273 else if (VG_STREQ(name, "Value0")) skind = CondSupp; /* backwards compat */
1274 else if (VG_STREQ(name, "Value1")) skind = Value1Supp;
1275 else if (VG_STREQ(name, "Value2")) skind = Value2Supp;
1276 else if (VG_STREQ(name, "Value4")) skind = Value4Supp;
1277 else if (VG_STREQ(name, "Value8")) skind = Value8Supp;
1278 else if (VG_STREQ(name, "Value16")) skind = Value16Supp;
florian7b6899d2014-07-13 14:41:55 +00001279 else if (VG_STREQ(name, "FishyValue")) skind = FishyValueSupp;
sewardj7ce71662008-05-02 10:33:15 +00001280 else
1281 return False;
1282
1283 VG_(set_supp_kind)(su, skind);
1284 return True;
1285}
1286
philippe2193a7c2012-12-08 17:54:16 +00001287typedef struct _MC_LeakSuppExtra MC_LeakSuppExtra;
1288
1289struct _MC_LeakSuppExtra {
1290 UInt match_leak_kinds;
philippe4e32d672013-10-17 22:10:41 +00001291
1292 /* Maintains nr of blocks and bytes suppressed with this suppression
1293 during the leak search identified by leak_search_gen.
1294 blocks_suppressed and bytes_suppressed are reset to 0 when
1295 used the first time during a leak search. */
1296 SizeT blocks_suppressed;
1297 SizeT bytes_suppressed;
1298 UInt leak_search_gen;
philippe2193a7c2012-12-08 17:54:16 +00001299};
1300
florian7b6899d2014-07-13 14:41:55 +00001301typedef struct {
1302 const HChar *function_name;
1303 const HChar *argument_name;
1304} MC_FishyValueExtra;
1305
florian19f91bb2012-11-10 22:29:54 +00001306Bool MC_(read_extra_suppression_info) ( Int fd, HChar** bufpp,
philippe362441d2013-07-22 22:00:13 +00001307 SizeT* nBufp, Int* lineno, Supp *su )
sewardj7ce71662008-05-02 10:33:15 +00001308{
1309 Bool eof;
philippe2193a7c2012-12-08 17:54:16 +00001310 Int i;
sewardj7ce71662008-05-02 10:33:15 +00001311
1312 if (VG_(get_supp_kind)(su) == ParamSupp) {
philippe362441d2013-07-22 22:00:13 +00001313 eof = VG_(get_line) ( fd, bufpp, nBufp, lineno );
sewardj7ce71662008-05-02 10:33:15 +00001314 if (eof) return False;
njn35db56c2009-07-24 07:38:29 +00001315 VG_(set_supp_string)(su, VG_(strdup)("mc.resi.1", *bufpp));
philippe2193a7c2012-12-08 17:54:16 +00001316 } else if (VG_(get_supp_kind)(su) == LeakSupp) {
1317 // We might have the optional match-leak-kinds line
1318 MC_LeakSuppExtra* lse;
1319 lse = VG_(malloc)("mc.resi.2", sizeof(MC_LeakSuppExtra));
1320 lse->match_leak_kinds = RallS;
philippe4e32d672013-10-17 22:10:41 +00001321 lse->blocks_suppressed = 0;
1322 lse->bytes_suppressed = 0;
1323 lse->leak_search_gen = 0;
philippe2193a7c2012-12-08 17:54:16 +00001324 VG_(set_supp_extra)(su, lse); // By default, all kinds will match.
philippe362441d2013-07-22 22:00:13 +00001325 eof = VG_(get_line) ( fd, bufpp, nBufp, lineno );
philippe2193a7c2012-12-08 17:54:16 +00001326 if (eof) return True; // old LeakSupp style, no match-leak-kinds line.
1327 if (0 == VG_(strncmp)(*bufpp, "match-leak-kinds:", 17)) {
1328 i = 17;
1329 while ((*bufpp)[i] && VG_(isspace((*bufpp)[i])))
1330 i++;
1331 if (!MC_(parse_leak_kinds)((*bufpp)+i, &lse->match_leak_kinds)) {
1332 return False;
1333 }
1334 } else {
1335 return False; // unknown extra line.
1336 }
florian7b6899d2014-07-13 14:41:55 +00001337 } else if (VG_(get_supp_kind)(su) == FishyValueSupp) {
1338 MC_FishyValueExtra *extra;
1339 HChar *p;
1340
1341 eof = VG_(get_line) ( fd, bufpp, nBufp, lineno );
1342 if (eof) return True;
1343
1344 extra = VG_(malloc)("mc.resi.3", sizeof *extra);
1345 extra->function_name = VG_(strdup)("mv.resi.4", *bufpp);
1346
1347 // The suppression string is: function_name(argument_name)
1348 p = VG_(strchr)(extra->function_name, '(');
1349 if (p == NULL) return False; // malformed suppression string
1350 *p++ = '\0';
1351 extra->argument_name = p;
1352 p = VG_(strchr)(p, ')');
1353 if (p == NULL) return False; // malformed suppression string
1354 *p = '\0';
1355
1356 VG_(set_supp_extra)(su, extra);
sewardj7ce71662008-05-02 10:33:15 +00001357 }
1358 return True;
1359}
1360
1361Bool MC_(error_matches_suppression) ( Error* err, Supp* su )
1362{
1363 Int su_szB;
1364 MC_Error* extra = VG_(get_error_extra)(err);
1365 ErrorKind ekind = VG_(get_error_kind )(err);
1366
1367 switch (VG_(get_supp_kind)(su)) {
1368 case ParamSupp:
1369 return ((ekind == Err_RegParam || ekind == Err_MemParam)
1370 && VG_STREQ(VG_(get_error_string)(err),
1371 VG_(get_supp_string)(su)));
1372
1373 case UserSupp:
1374 return (ekind == Err_User);
1375
1376 case CoreMemSupp:
1377 return (ekind == Err_CoreMem
1378 && VG_STREQ(VG_(get_error_string)(err),
1379 VG_(get_supp_string)(su)));
1380
1381 case Value1Supp: su_szB = 1; goto value_case;
1382 case Value2Supp: su_szB = 2; goto value_case;
1383 case Value4Supp: su_szB = 4; goto value_case;
1384 case Value8Supp: su_szB = 8; goto value_case;
1385 case Value16Supp:su_szB =16; goto value_case;
1386 value_case:
1387 return (ekind == Err_Value && extra->Err.Value.szB == su_szB);
1388
1389 case CondSupp:
1390 return (ekind == Err_Cond);
1391
1392 case Addr1Supp: su_szB = 1; goto addr_case;
1393 case Addr2Supp: su_szB = 2; goto addr_case;
1394 case Addr4Supp: su_szB = 4; goto addr_case;
1395 case Addr8Supp: su_szB = 8; goto addr_case;
1396 case Addr16Supp:su_szB =16; goto addr_case;
1397 addr_case:
1398 return (ekind == Err_Addr && extra->Err.Addr.szB == su_szB);
1399
1400 case JumpSupp:
1401 return (ekind == Err_Jump);
1402
1403 case FreeSupp:
1404 return (ekind == Err_Free || ekind == Err_FreeMismatch);
1405
1406 case OverlapSupp:
1407 return (ekind == Err_Overlap);
1408
1409 case LeakSupp:
philippe2193a7c2012-12-08 17:54:16 +00001410 if (ekind == Err_Leak) {
1411 MC_LeakSuppExtra* lse = (MC_LeakSuppExtra*) VG_(get_supp_extra)(su);
philippe4e32d672013-10-17 22:10:41 +00001412 if (lse->leak_search_gen != MC_(leak_search_gen)) {
1413 // First time we see this suppression during this leak search.
1414 // => reset the counters to 0.
1415 lse->blocks_suppressed = 0;
1416 lse->bytes_suppressed = 0;
1417 lse->leak_search_gen = MC_(leak_search_gen);
1418 }
philippe2193a7c2012-12-08 17:54:16 +00001419 return RiS(extra->Err.Leak.lr->key.state, lse->match_leak_kinds);
1420 } else
1421 return False;
sewardj7ce71662008-05-02 10:33:15 +00001422
1423 case MempoolSupp:
1424 return (ekind == Err_IllegalMempool);
1425
florian7b6899d2014-07-13 14:41:55 +00001426 case FishyValueSupp: {
1427 MC_FishyValueExtra *supp_extra = VG_(get_supp_extra)(su);
1428
1429 return (ekind == Err_FishyValue) &&
1430 VG_STREQ(extra->Err.FishyValue.function_name,
1431 supp_extra->function_name) &&
1432 VG_STREQ(extra->Err.FishyValue.argument_name,
1433 supp_extra->argument_name);
1434 }
1435
sewardj7ce71662008-05-02 10:33:15 +00001436 default:
1437 VG_(printf)("Error:\n"
1438 " unknown suppression type %d\n",
1439 VG_(get_supp_kind)(su));
1440 VG_(tool_panic)("unknown suppression type in "
1441 "MC_(error_matches_suppression)");
1442 }
1443}
1444
floriane543f302012-10-21 19:43:43 +00001445const HChar* MC_(get_error_name) ( Error* err )
sewardj7ce71662008-05-02 10:33:15 +00001446{
1447 switch (VG_(get_error_kind)(err)) {
1448 case Err_RegParam: return "Param";
1449 case Err_MemParam: return "Param";
1450 case Err_User: return "User";
1451 case Err_FreeMismatch: return "Free";
1452 case Err_IllegalMempool: return "Mempool";
1453 case Err_Free: return "Free";
1454 case Err_Jump: return "Jump";
1455 case Err_CoreMem: return "CoreMem";
1456 case Err_Overlap: return "Overlap";
1457 case Err_Leak: return "Leak";
1458 case Err_Cond: return "Cond";
florian7b6899d2014-07-13 14:41:55 +00001459 case Err_FishyValue: return "FishyValue";
sewardj7ce71662008-05-02 10:33:15 +00001460 case Err_Addr: {
1461 MC_Error* extra = VG_(get_error_extra)(err);
1462 switch ( extra->Err.Addr.szB ) {
1463 case 1: return "Addr1";
1464 case 2: return "Addr2";
1465 case 4: return "Addr4";
1466 case 8: return "Addr8";
1467 case 16: return "Addr16";
1468 default: VG_(tool_panic)("unexpected size for Addr");
1469 }
1470 }
1471 case Err_Value: {
1472 MC_Error* extra = VG_(get_error_extra)(err);
1473 switch ( extra->Err.Value.szB ) {
1474 case 1: return "Value1";
1475 case 2: return "Value2";
1476 case 4: return "Value4";
1477 case 8: return "Value8";
1478 case 16: return "Value16";
1479 default: VG_(tool_panic)("unexpected size for Value");
1480 }
1481 }
1482 default: VG_(tool_panic)("get_error_name: unexpected type");
1483 }
1484}
1485
sewardj588adef2009-08-15 22:41:51 +00001486Bool MC_(get_extra_suppression_info) ( Error* err,
floriandbb35842012-10-27 18:39:11 +00001487 /*OUT*/HChar* buf, Int nBuf )
sewardj7ce71662008-05-02 10:33:15 +00001488{
1489 ErrorKind ekind = VG_(get_error_kind )(err);
sewardj588adef2009-08-15 22:41:51 +00001490 tl_assert(buf);
1491 tl_assert(nBuf >= 16); // stay sane
sewardj7ce71662008-05-02 10:33:15 +00001492 if (Err_RegParam == ekind || Err_MemParam == ekind) {
floriane543f302012-10-21 19:43:43 +00001493 const HChar* errstr = VG_(get_error_string)(err);
sewardj588adef2009-08-15 22:41:51 +00001494 tl_assert(errstr);
1495 VG_(snprintf)(buf, nBuf-1, "%s", errstr);
1496 return True;
philippe2193a7c2012-12-08 17:54:16 +00001497 } else if (Err_Leak == ekind) {
1498 MC_Error* extra = VG_(get_error_extra)(err);
1499 VG_(snprintf)
1500 (buf, nBuf-1, "match-leak-kinds: %s",
1501 pp_Reachedness_for_leak_kinds(extra->Err.Leak.lr->key.state));
1502 return True;
florian7b6899d2014-07-13 14:41:55 +00001503 } else if (Err_FishyValue == ekind) {
1504 MC_Error* extra = VG_(get_error_extra)(err);
1505 VG_(snprintf)
1506 (buf, nBuf-1, "%s(%s)", extra->Err.FishyValue.function_name,
1507 extra->Err.FishyValue.argument_name);
1508 return True;
sewardj588adef2009-08-15 22:41:51 +00001509 } else {
1510 return False;
sewardj7ce71662008-05-02 10:33:15 +00001511 }
1512}
1513
philippe4e32d672013-10-17 22:10:41 +00001514Bool MC_(print_extra_suppression_use) ( Supp *su,
1515 /*OUT*/HChar *buf, Int nBuf )
1516{
1517 if (VG_(get_supp_kind)(su) == LeakSupp) {
1518 MC_LeakSuppExtra *lse = (MC_LeakSuppExtra*) VG_(get_supp_extra) (su);
1519
1520 if (lse->leak_search_gen == MC_(leak_search_gen)
1521 && lse->blocks_suppressed > 0) {
1522 VG_(snprintf) (buf, nBuf-1,
1523 "suppressed: %'lu bytes in %'lu blocks",
1524 lse->bytes_suppressed,
1525 lse->blocks_suppressed);
1526 return True;
1527 } else
1528 return False;
1529 } else
1530 return False;
1531}
1532
1533void MC_(update_extra_suppression_use) ( Error* err, Supp* su)
1534{
1535 if (VG_(get_supp_kind)(su) == LeakSupp) {
1536 MC_LeakSuppExtra *lse = (MC_LeakSuppExtra*) VG_(get_supp_extra) (su);
1537 MC_Error* extra = VG_(get_error_extra)(err);
1538
1539 tl_assert (lse->leak_search_gen = MC_(leak_search_gen));
1540 lse->blocks_suppressed += extra->Err.Leak.lr->num_blocks;
1541 lse->bytes_suppressed
1542 += extra->Err.Leak.lr->szB + extra->Err.Leak.lr->indirect_szB;
1543 }
1544}
sewardj7ce71662008-05-02 10:33:15 +00001545
1546/*--------------------------------------------------------------------*/
1547/*--- end mc_errors.c ---*/
1548/*--------------------------------------------------------------------*/