2 /*--------------------------------------------------------------------*/
3 /*--- Management, printing, etc, of errors and suppressions. ---*/
4 /*--- mc_errors.c ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of MemCheck, a heavyweight Valgrind tool for
9 detecting memory errors.
11 Copyright (C) 2000-2017 Julian Seward
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.
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.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, see <http://www.gnu.org/licenses/>.
27 The GNU General Public License is contained in the file COPYING.
30 #include "pub_tool_basics.h"
31 #include "pub_tool_gdbserver.h"
32 #include "pub_tool_poolalloc.h" // For mc_include.h
33 #include "pub_tool_hashtable.h" // For mc_include.h
34 #include "pub_tool_libcbase.h"
35 #include "pub_tool_libcassert.h"
36 #include "pub_tool_libcprint.h"
37 #include "pub_tool_machine.h"
38 #include "pub_tool_mallocfree.h"
39 #include "pub_tool_options.h"
40 #include "pub_tool_replacemalloc.h"
41 #include "pub_tool_tooliface.h"
42 #include "pub_tool_threadstate.h"
43 #include "pub_tool_debuginfo.h" // VG_(get_dataname_and_offset)
44 #include "pub_tool_xarray.h"
45 #include "pub_tool_aspacemgr.h"
46 #include "pub_tool_addrinfo.h"
48 #include "mc_include.h"
51 /*------------------------------------------------------------*/
52 /*--- Error types ---*/
53 /*------------------------------------------------------------*/
55 /* See comment in mc_include.h */
56 Bool
MC_(any_value_errors
) = False
;
59 /* ------------------ Errors ----------------------- */
61 /* What kind of error it is. */
87 typedef struct _MC_Error MC_Error
;
90 // Nb: we don't need the tag here, as it's stored in the Error type! Yuk.
94 // Use of an undefined value:
95 // - as a pointer in a load or store
98 SizeT szB
; // size of value in bytes
100 UInt otag
; // origin tag
101 ExeContext
* origin_ec
; // filled in later
104 // Use of an undefined value in a conditional branch or move.
107 UInt otag
; // origin tag
108 ExeContext
* origin_ec
; // filled in later
111 // Addressability error in core (signal-handling) operation.
112 // It would be good to get rid of this error kind, merge it with
113 // another one somehow.
117 // Use of an unaddressable memory location in a load or store.
119 Bool isWrite
; // read or write?
120 SizeT szB
; // not used for exec (jump) errors
121 Bool maybe_gcc
; // True if just below %esp -- could be a gcc bug
125 // Jump to an unaddressable memory location.
130 // System call register input contains undefined bytes.
133 UInt otag
; // origin tag
134 ExeContext
* origin_ec
; // filled in later
137 // System call memory input contains undefined/unaddressable bytes
139 Bool isAddrErr
; // Addressability or definedness error?
142 UInt otag
; // origin tag
143 ExeContext
* origin_ec
; // filled in later
146 // Problem found from a client request like CHECK_MEM_IS_ADDRESSABLE.
148 Bool isAddrErr
; // Addressability or definedness error?
151 UInt otag
; // origin tag
152 ExeContext
* origin_ec
; // filled in later
155 // Program tried to free() something that's not a heap block (this
156 // covers double-frees). */
161 // Program allocates heap block with one function
162 // (malloc/new/new[]/custom) and deallocates with not the matching one.
184 // Call to strcpy, memcpy, etc, with overlapping blocks.
186 Addr src
; // Source block
187 Addr dst
; // Destination block
188 SizeT szB
; // Size in bytes; 0 if unused.
194 UInt n_total_records
;
198 // A memory pool error.
203 // A fishy function argument value
204 // An argument value is considered fishy if the corresponding
205 // parameter has SizeT type and the value when interpreted as a
206 // signed number is negative.
208 const HChar
*function_name
;
209 const HChar
*argument_name
;
213 // Program allocates heap block with new but
214 // deallocates with a matching delete
215 // but with a different size
218 const HChar
*function_names
;
222 // Program allocates heap block with one function
223 // (malloc/new/new[]/custom) and deallocates with
224 // a matching one but different alignment
227 const HChar
*function_names
;
236 /*------------------------------------------------------------*/
237 /*--- Printing errors ---*/
238 /*------------------------------------------------------------*/
240 /* This is the "this error is due to be printed shortly; so have a
241 look at it any print any preamble you want" function. Which, in
242 Memcheck, we don't use. Hence a no-op.
244 void MC_(before_pp_Error
) ( const Error
* err
) {
247 /* Do a printf-style operation on either the XML or normal output
248 channel, depending on the setting of VG_(clo_xml).
250 static void emit_WRK ( const HChar
* format
, va_list vargs
)
253 VG_(vprintf_xml
)(format
, vargs
);
255 VG_(vmessage
)(Vg_UserMsg
, format
, vargs
);
258 static void emit ( const HChar
* format
, ... ) PRINTF_CHECK(1, 2);
259 static void emit ( const HChar
* format
, ... )
262 va_start(vargs
, format
);
263 emit_WRK(format
, vargs
);
268 static const HChar
* str_leak_lossmode ( Reachedness lossmode
)
270 const HChar
*loss
= "?";
272 case Unreached
: loss
= "definitely lost"; break;
273 case IndirectLeak
: loss
= "indirectly lost"; break;
274 case Possible
: loss
= "possibly lost"; break;
275 case Reachable
: loss
= "still reachable"; break;
280 static const HChar
* xml_leak_kind ( Reachedness lossmode
)
282 const HChar
*loss
= "?";
284 case Unreached
: loss
= "Leak_DefinitelyLost"; break;
285 case IndirectLeak
: loss
= "Leak_IndirectlyLost"; break;
286 case Possible
: loss
= "Leak_PossiblyLost"; break;
287 case Reachable
: loss
= "Leak_StillReachable"; break;
292 const HChar
* MC_(parse_leak_kinds_tokens
) =
293 "reachable,possible,indirect,definite";
295 UInt
MC_(all_Reachedness
)(void)
300 // Compute a set with all values by doing a parsing of the "all" keyword.
301 Bool parseok
= VG_(parse_enum_set
)(MC_(parse_leak_kinds_tokens
),
305 tl_assert (parseok
&& all
);
311 static const HChar
* pp_Reachedness_for_leak_kinds(Reachedness r
)
314 case Reachable
: return "reachable";
315 case Possible
: return "possible";
316 case IndirectLeak
: return "indirect";
317 case Unreached
: return "definite";
318 default: tl_assert(0);
322 static void mc_pp_origin ( ExeContext
* ec
, UInt okind
)
324 const HChar
* src
= NULL
;
328 case MC_OKIND_STACK
: src
= " by a stack allocation"; break;
329 case MC_OKIND_HEAP
: src
= " by a heap allocation"; break;
330 case MC_OKIND_USER
: src
= " by a client request"; break;
331 case MC_OKIND_UNKNOWN
: src
= ""; break;
333 tl_assert(src
); /* guards against invalid 'okind' */
336 emit( " <auxwhat>Uninitialised value was created%s</auxwhat>\n",
338 VG_(pp_ExeContext
)( ec
);
340 emit( " Uninitialised value was created%s\n", src
);
341 VG_(pp_ExeContext
)( ec
);
345 HChar
* MC_(snprintf_delta
) (HChar
* buf
, Int size
,
346 SizeT current_val
, SizeT old_val
,
347 LeakCheckDeltaMode delta_mode
)
349 // Make sure the buffer size is large enough. With old_val == 0 and
350 // current_val == ULLONG_MAX the delta including inserted commas is:
351 // 18,446,744,073,709,551,615
352 // whose length is 26. Therefore:
353 tl_assert(size
>= 26 + 4 + 1);
355 if (delta_mode
== LCD_Any
)
357 else if (current_val
>= old_val
)
358 VG_(snprintf
) (buf
, size
, " (+%'lu)", current_val
- old_val
);
360 VG_(snprintf
) (buf
, size
, " (-%'lu)", old_val
- current_val
);
365 static void pp_LossRecord(UInt n_this_record
, UInt n_total_records
,
366 LossRecord
* lr
, Bool xml
)
368 // char arrays to produce the indication of increase/decrease in case
369 // of delta_mode != LCD_Any
371 HChar d_direct_bytes
[31];
372 HChar d_indirect_bytes
[31];
373 HChar d_num_blocks
[31];
374 /* A loss record that had an old number of blocks 0 is a new loss record.
375 We mark it as new only when doing any kind of delta leak search. */
376 const HChar
*new_loss_record_marker
377 = MC_(detect_memory_leaks_last_delta_mode
) != LCD_Any
378 && lr
->old_num_blocks
== 0
381 MC_(snprintf_delta
) (d_bytes
, sizeof(d_bytes
),
382 lr
->szB
+ lr
->indirect_szB
,
383 lr
->old_szB
+ lr
->old_indirect_szB
,
384 MC_(detect_memory_leaks_last_delta_mode
));
385 MC_(snprintf_delta
) (d_direct_bytes
, sizeof(d_direct_bytes
),
388 MC_(detect_memory_leaks_last_delta_mode
));
389 MC_(snprintf_delta
) (d_indirect_bytes
, sizeof(d_indirect_bytes
),
391 lr
->old_indirect_szB
,
392 MC_(detect_memory_leaks_last_delta_mode
));
393 MC_(snprintf_delta
) (d_num_blocks
, sizeof(d_num_blocks
),
394 (SizeT
) lr
->num_blocks
,
395 (SizeT
) lr
->old_num_blocks
,
396 MC_(detect_memory_leaks_last_delta_mode
));
399 emit(" <kind>%s</kind>\n", xml_leak_kind(lr
->key
.state
));
400 if (lr
->indirect_szB
> 0) {
401 emit( " <xwhat>\n" );
402 emit( " <text>%'lu%s (%'lu%s direct, %'lu%s indirect) bytes "
404 " are %s in %sloss record %'u of %'u</text>\n",
405 lr
->szB
+ lr
->indirect_szB
, d_bytes
,
406 lr
->szB
, d_direct_bytes
,
407 lr
->indirect_szB
, d_indirect_bytes
,
408 lr
->num_blocks
, d_num_blocks
,
409 str_leak_lossmode(lr
->key
.state
),
410 new_loss_record_marker
,
411 n_this_record
, n_total_records
);
412 // Nb: don't put commas in these XML numbers
413 emit( " <leakedbytes>%lu</leakedbytes>\n",
414 lr
->szB
+ lr
->indirect_szB
);
415 emit( " <leakedblocks>%u</leakedblocks>\n", lr
->num_blocks
);
416 emit( " </xwhat>\n" );
418 emit( " <xwhat>\n" );
419 emit( " <text>%'lu%s bytes in %'u%s blocks"
420 " are %s in %sloss record %'u of %'u</text>\n",
421 lr
->szB
, d_direct_bytes
,
422 lr
->num_blocks
, d_num_blocks
,
423 str_leak_lossmode(lr
->key
.state
),
424 new_loss_record_marker
,
425 n_this_record
, n_total_records
);
426 emit( " <leakedbytes>%lu</leakedbytes>\n", lr
->szB
);
427 emit( " <leakedblocks>%u</leakedblocks>\n", lr
->num_blocks
);
428 emit( " </xwhat>\n" );
430 VG_(pp_ExeContext
)(lr
->key
.allocated_at
);
431 } else { /* ! if (xml) */
432 if (lr
->indirect_szB
> 0) {
434 "%'lu%s (%'lu%s direct, %'lu%s indirect) bytes in %'u%s blocks"
435 " are %s in %sloss record %'u of %'u\n",
436 lr
->szB
+ lr
->indirect_szB
, d_bytes
,
437 lr
->szB
, d_direct_bytes
,
438 lr
->indirect_szB
, d_indirect_bytes
,
439 lr
->num_blocks
, d_num_blocks
,
440 str_leak_lossmode(lr
->key
.state
),
441 new_loss_record_marker
,
442 n_this_record
, n_total_records
446 "%'lu%s bytes in %'u%s blocks are %s in %sloss record %'u of %'u\n",
447 lr
->szB
, d_direct_bytes
,
448 lr
->num_blocks
, d_num_blocks
,
449 str_leak_lossmode(lr
->key
.state
),
450 new_loss_record_marker
,
451 n_this_record
, n_total_records
454 VG_(pp_ExeContext
)(lr
->key
.allocated_at
);
458 void MC_(pp_LossRecord
)(UInt n_this_record
, UInt n_total_records
,
461 pp_LossRecord (n_this_record
, n_total_records
, l
, /* xml */ False
);
464 void MC_(pp_Error
) ( const Error
* err
)
466 const Bool xml
= VG_(clo_xml
); /* a shorthand */
467 MC_Error
* extra
= VG_(get_error_extra
)(err
);
469 switch (VG_(get_error_kind
)(err
)) {
471 /* What the hell *is* a CoreMemError? jrs 2005-May-18 */
472 /* As of 2006-Dec-14, it's caused by unaddressable bytes in a
473 signal handler frame. --njn */
474 // JRS 17 May 09: None of our regtests exercise this; hence AFAIK
475 // the following code is untested. Bad.
477 emit( " <kind>CoreMemError</kind>\n" );
478 emit( " <what>%pS contains unaddressable byte(s)</what>\n",
479 VG_(get_error_string
)(err
));
480 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
482 emit( "%s contains unaddressable byte(s)\n",
483 VG_(get_error_string
)(err
));
484 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
489 MC_(any_value_errors
) = True
;
491 emit( " <kind>UninitValue</kind>\n" );
492 emit( " <what>Use of uninitialised value of size %lu</what>\n",
493 extra
->Err
.Value
.szB
);
494 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
495 if (extra
->Err
.Value
.origin_ec
)
496 mc_pp_origin( extra
->Err
.Value
.origin_ec
,
497 extra
->Err
.Value
.otag
& 3 );
499 /* Could also show extra->Err.Cond.otag if debugging origin
501 emit( "Use of uninitialised value of size %lu\n",
502 extra
->Err
.Value
.szB
);
503 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
504 if (extra
->Err
.Value
.origin_ec
)
505 mc_pp_origin( extra
->Err
.Value
.origin_ec
,
506 extra
->Err
.Value
.otag
& 3 );
511 MC_(any_value_errors
) = True
;
513 emit( " <kind>UninitCondition</kind>\n" );
514 emit( " <what>Conditional jump or move depends"
515 " on uninitialised value(s)</what>\n" );
516 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
517 if (extra
->Err
.Cond
.origin_ec
)
518 mc_pp_origin( extra
->Err
.Cond
.origin_ec
,
519 extra
->Err
.Cond
.otag
& 3 );
521 /* Could also show extra->Err.Cond.otag if debugging origin
523 emit( "Conditional jump or move depends"
524 " on uninitialised value(s)\n" );
525 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
526 if (extra
->Err
.Cond
.origin_ec
)
527 mc_pp_origin( extra
->Err
.Cond
.origin_ec
,
528 extra
->Err
.Cond
.otag
& 3 );
533 MC_(any_value_errors
) = True
;
535 emit( " <kind>SyscallParam</kind>\n" );
536 emit( " <what>Syscall param %pS contains "
537 "uninitialised byte(s)</what>\n",
538 VG_(get_error_string
)(err
) );
539 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
540 if (extra
->Err
.RegParam
.origin_ec
)
541 mc_pp_origin( extra
->Err
.RegParam
.origin_ec
,
542 extra
->Err
.RegParam
.otag
& 3 );
544 emit( "Syscall param %s contains uninitialised byte(s)\n",
545 VG_(get_error_string
)(err
) );
546 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
547 if (extra
->Err
.RegParam
.origin_ec
)
548 mc_pp_origin( extra
->Err
.RegParam
.origin_ec
,
549 extra
->Err
.RegParam
.otag
& 3 );
554 if (!extra
->Err
.MemParam
.isAddrErr
)
555 MC_(any_value_errors
) = True
;
557 emit( " <kind>SyscallParam</kind>\n" );
558 emit( " <what>Syscall param %pS points to %s byte(s)</what>\n",
559 VG_(get_error_string
)(err
),
560 extra
->Err
.MemParam
.isAddrErr
561 ? "unaddressable" : "uninitialised" );
562 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
563 VG_(pp_addrinfo_mc
)(VG_(get_error_address
)(err
),
564 &extra
->Err
.MemParam
.ai
, False
);
565 if (extra
->Err
.MemParam
.origin_ec
566 && !extra
->Err
.MemParam
.isAddrErr
)
567 mc_pp_origin( extra
->Err
.MemParam
.origin_ec
,
568 extra
->Err
.MemParam
.otag
& 3 );
570 emit( "Syscall param %s points to %s byte(s)\n",
571 VG_(get_error_string
)(err
),
572 extra
->Err
.MemParam
.isAddrErr
573 ? "unaddressable" : "uninitialised" );
574 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
575 VG_(pp_addrinfo_mc
)(VG_(get_error_address
)(err
),
576 &extra
->Err
.MemParam
.ai
, False
);
577 if (extra
->Err
.MemParam
.origin_ec
578 && !extra
->Err
.MemParam
.isAddrErr
)
579 mc_pp_origin( extra
->Err
.MemParam
.origin_ec
,
580 extra
->Err
.MemParam
.otag
& 3 );
585 if (!extra
->Err
.User
.isAddrErr
)
586 MC_(any_value_errors
) = True
;
588 emit( " <kind>ClientCheck</kind>\n" );
589 emit( " <what>%s byte(s) found "
590 "during client check request</what>\n",
591 extra
->Err
.User
.isAddrErr
592 ? "Unaddressable" : "Uninitialised" );
593 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
594 VG_(pp_addrinfo_mc
)(VG_(get_error_address
)(err
), &extra
->Err
.User
.ai
,
596 if (extra
->Err
.User
.origin_ec
&& !extra
->Err
.User
.isAddrErr
)
597 mc_pp_origin( extra
->Err
.User
.origin_ec
,
598 extra
->Err
.User
.otag
& 3 );
600 emit( "%s byte(s) found during client check request\n",
601 extra
->Err
.User
.isAddrErr
602 ? "Unaddressable" : "Uninitialised" );
603 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
604 VG_(pp_addrinfo_mc
)(VG_(get_error_address
)(err
), &extra
->Err
.User
.ai
,
606 if (extra
->Err
.User
.origin_ec
&& !extra
->Err
.User
.isAddrErr
)
607 mc_pp_origin( extra
->Err
.User
.origin_ec
,
608 extra
->Err
.User
.otag
& 3 );
614 emit( " <kind>InvalidFree</kind>\n" );
615 emit( " <what>Invalid free() / delete / delete[]"
616 " / realloc()</what>\n" );
617 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
618 VG_(pp_addrinfo_mc
)( VG_(get_error_address
)(err
),
619 &extra
->Err
.Free
.ai
, False
);
621 emit( "Invalid free() / delete / delete[] / realloc()\n" );
622 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
623 VG_(pp_addrinfo_mc
)( VG_(get_error_address
)(err
),
624 &extra
->Err
.Free
.ai
, False
);
628 case Err_FreeMismatch
:
630 emit( " <kind>MismatchedFree</kind>\n" );
631 emit( " <what>Mismatched free() / delete / delete []</what>\n" );
632 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
633 VG_(pp_addrinfo_mc
)(VG_(get_error_address
)(err
),
634 &extra
->Err
.FreeMismatch
.ai
, False
);
636 emit( "Mismatched free() / delete / delete []\n" );
637 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
638 VG_(pp_addrinfo_mc
)(VG_(get_error_address
)(err
),
639 &extra
->Err
.FreeMismatch
.ai
, False
);
645 emit( " <kind>Invalid%s</kind>\n",
646 extra
->Err
.Addr
.isWrite
? "Write" : "Read" );
647 emit( " <what>Invalid %s of size %lu</what>\n",
648 extra
->Err
.Addr
.isWrite
? "write" : "read",
649 extra
->Err
.Addr
.szB
);
650 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
651 VG_(pp_addrinfo_mc
)( VG_(get_error_address
)(err
),
653 extra
->Err
.Addr
.maybe_gcc
);
655 emit( "Invalid %s of size %lu\n",
656 extra
->Err
.Addr
.isWrite
? "write" : "read",
657 extra
->Err
.Addr
.szB
);
658 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
660 VG_(pp_addrinfo_mc
)( VG_(get_error_address
)(err
),
662 extra
->Err
.Addr
.maybe_gcc
);
668 emit( " <kind>InvalidJump</kind>\n" );
669 emit( " <what>Jump to the invalid address stated "
670 "on the next line</what>\n" );
671 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
672 VG_(pp_addrinfo_mc
)( VG_(get_error_address
)(err
), &extra
->Err
.Jump
.ai
,
675 emit( "Jump to the invalid address stated on the next line\n" );
676 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
677 VG_(pp_addrinfo_mc
)( VG_(get_error_address
)(err
), &extra
->Err
.Jump
.ai
,
684 emit( " <kind>Overlap</kind>\n" );
685 if (extra
->Err
.Overlap
.szB
== 0) {
686 emit( " <what>Source and destination overlap "
687 "in %pS(%#lx, %#lx)\n</what>\n",
688 VG_(get_error_string
)(err
),
689 extra
->Err
.Overlap
.dst
, extra
->Err
.Overlap
.src
);
691 emit( " <what>Source and destination overlap "
692 "in %pS(%#lx, %#lx, %lu)</what>\n",
693 VG_(get_error_string
)(err
),
694 extra
->Err
.Overlap
.dst
, extra
->Err
.Overlap
.src
,
695 extra
->Err
.Overlap
.szB
);
697 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
699 if (extra
->Err
.Overlap
.szB
== 0) {
700 emit( "Source and destination overlap in %s(%#lx, %#lx)\n",
701 VG_(get_error_string
)(err
),
702 extra
->Err
.Overlap
.dst
, extra
->Err
.Overlap
.src
);
704 emit( "Source and destination overlap in %s(%#lx, %#lx, %lu)\n",
705 VG_(get_error_string
)(err
),
706 extra
->Err
.Overlap
.dst
, extra
->Err
.Overlap
.src
,
707 extra
->Err
.Overlap
.szB
);
709 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
713 case Err_IllegalMempool
:
714 // JRS 17 May 09: None of our regtests exercise this; hence AFAIK
715 // the following code is untested. Bad.
717 emit( " <kind>InvalidMemPool</kind>\n" );
718 emit( " <what>Illegal memory pool address</what>\n" );
719 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
720 VG_(pp_addrinfo_mc
)( VG_(get_error_address
)(err
),
721 &extra
->Err
.IllegalMempool
.ai
, False
);
723 emit( "Illegal memory pool address\n" );
724 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
725 VG_(pp_addrinfo_mc
)( VG_(get_error_address
)(err
),
726 &extra
->Err
.IllegalMempool
.ai
, False
);
731 UInt n_this_record
= extra
->Err
.Leak
.n_this_record
;
732 UInt n_total_records
= extra
->Err
.Leak
.n_total_records
;
733 LossRecord
* lr
= extra
->Err
.Leak
.lr
;
734 pp_LossRecord (n_this_record
, n_total_records
, lr
, xml
);
740 emit( " <kind>FishyValue</kind>\n" );
742 emit( "Argument '%s' of function %s has a fishy "
743 "(possibly negative) value: %ld\n",
744 extra
->Err
.FishyValue
.argument_name
,
745 extra
->Err
.FishyValue
.function_name
,
746 (SSizeT
)extra
->Err
.FishyValue
.value
);
748 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
750 emit( "Argument '%s' of function %s has a fishy "
751 "(possibly negative) value: %ld\n",
752 extra
->Err
.FishyValue
.argument_name
,
753 extra
->Err
.FishyValue
.function_name
,
754 (SSizeT
)extra
->Err
.FishyValue
.value
);
755 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
759 case Err_ReallocSizeZero
:
761 emit( " <kind>ReallocSizeZero</kind>\n" );
762 emit( " <what>realloc() with size 0</what>\n" );
763 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
764 VG_(pp_addrinfo_mc
)(VG_(get_error_address
)(err
),
765 &extra
->Err
.ReallocSizeZero
.ai
, False
);
767 emit( "realloc() with size 0\n" );
768 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
769 VG_(pp_addrinfo_mc
)(VG_(get_error_address
)(err
),
770 &extra
->Err
.ReallocSizeZero
.ai
, False
);
775 if (extra
->Err
.BadAlign
.size
) {
777 emit( " <kind>InvalidSizeAndAlignment</kind>\n" );
778 emit( " <what>Invalid size value: %lu alignment value: %lu%s</what>\n",
779 extra
->Err
.BadAlign
.size
,
780 extra
->Err
.BadAlign
.dealloc_align
, extra
->Err
.BadAlign
.msg
);
781 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
783 emit( "Invalid size value: %lu alignment value: %lu%s\n",
784 extra
->Err
.BadAlign
.size
,
785 extra
->Err
.BadAlign
.dealloc_align
, extra
->Err
.BadAlign
.msg
);
786 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
790 emit( " <kind>InvalidAlignment</kind>\n" );
791 emit( " <what>Invalid alignment value: %lu%s</what>\n",
792 extra
->Err
.BadAlign
.dealloc_align
, extra
->Err
.BadAlign
.msg
);
793 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
795 emit( "Invalid alignment value: %lu%s\n",
796 extra
->Err
.BadAlign
.dealloc_align
, extra
->Err
.BadAlign
.msg
);
797 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
804 emit( " <kind>InvalidSize</kind>\n" );
805 emit( " <what>%s invalid size value: %lu</what>\n",
806 extra
->Err
.BadSize
.func
, extra
->Err
.BadSize
.size
);
807 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
809 emit( "%s invalid size value: %lu\n",
810 extra
->Err
.BadSize
.func
, extra
->Err
.BadSize
.size
);
811 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
815 case Err_SizeMismatch
:
817 emit( " <kind>MismatchedAllocateDeallocateSize</kind>\n" );
818 emit( " <what>Mismatched %s size value: %lu</what>\n",
819 extra
->Err
.SizeMismatch
.function_names
, extra
->Err
.SizeMismatch
.size
);
820 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
821 VG_(pp_addrinfo_mc
)(VG_(get_error_address
)(err
),
822 &extra
->Err
.SizeMismatch
.ai
, False
);
824 emit( "Mismatched %s size value: %lu\n",
825 extra
->Err
.SizeMismatch
.function_names
, extra
->Err
.SizeMismatch
.size
);
826 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
827 VG_(pp_addrinfo_mc
)(VG_(get_error_address
)(err
),
828 &extra
->Err
.SizeMismatch
.ai
, False
);
832 case Err_AlignMismatch
:
834 emit( " <kind>MismatchedAllocateDeallocateAlignment</kind>\n" );
835 if (extra
->Err
.AlignMismatch
.default_delete
) {
836 emit( " <what>Mismatched %s size alloc value: %lu dealloc value: default-aligned</what>\n",
837 extra
->Err
.SizeMismatch
.function_names
, extra
->Err
.AlignMismatch
.alloc_align
);
839 emit( " <what>Mismatched %s size alloc value: %lu dealloc value: %lu</what>\n",
840 extra
->Err
.SizeMismatch
.function_names
, extra
->Err
.AlignMismatch
.alloc_align
, extra
->Err
.AlignMismatch
.dealloc_align
);
842 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
843 VG_(pp_addrinfo_mc
)(VG_(get_error_address
)(err
),
844 &extra
->Err
.AlignMismatch
.ai
, False
);
846 if (extra
->Err
.AlignMismatch
.default_delete
) {
847 emit( "Mismatched %s alignment alloc value: %lu dealloc value: default-aligned\n",
848 extra
->Err
.AlignMismatch
.function_names
, extra
->Err
.AlignMismatch
.alloc_align
);
850 emit( "Mismatched %s alignment alloc value: %lu dealloc value: %lu\n",
851 extra
->Err
.AlignMismatch
.function_names
, extra
->Err
.AlignMismatch
.alloc_align
, extra
->Err
.AlignMismatch
.dealloc_align
);
853 VG_(pp_ExeContext
)( VG_(get_error_where
)(err
) );
854 VG_(pp_addrinfo_mc
)(VG_(get_error_address
)(err
),
855 &extra
->Err
.AlignMismatch
.ai
, False
);
860 VG_(printf
)("Error:\n unknown Memcheck error code %d\n",
861 VG_(get_error_kind
)(err
));
862 VG_(tool_panic
)("unknown error code in mc_pp_Error)");
866 /*------------------------------------------------------------*/
867 /*--- Recording errors ---*/
868 /*------------------------------------------------------------*/
870 /* These many bytes below %ESP are considered addressible if we're
871 doing the --workaround-gcc296-bugs hack. */
872 #define VG_GCC296_BUG_STACK_SLOP 1024
874 /* Is this address within some small distance below %ESP? Used only
875 for the --workaround-gcc296-bugs kludge. */
876 static Bool
is_just_below_ESP( Addr esp
, Addr aa
)
878 esp
-= VG_STACK_REDZONE_SZB
;
879 if (esp
> aa
&& (esp
- aa
) <= VG_GCC296_BUG_STACK_SLOP
)
885 /* --- Called from generated and non-generated code --- */
887 void MC_(record_address_error
) ( ThreadId tid
, Addr a
, Int szB
,
893 if (MC_(in_ignored_range
)(a
))
896 if (VG_(is_watched
)( (isWrite
? write_watchpoint
: read_watchpoint
), a
, szB
))
899 Addr current_sp
= VG_(get_SP
)(tid
);
900 just_below_esp
= is_just_below_ESP( current_sp
, a
);
902 /* If this is caused by an access immediately below %ESP, and the
903 user asks nicely, we just ignore it. */
904 if (MC_(clo_workaround_gcc296_bugs
) && just_below_esp
)
907 /* Also, if this is caused by an access in the range of offsets
908 below the stack pointer as described by
909 --ignore-range-below-sp, ignore it. */
910 if (MC_(in_ignored_range_below_sp
)( current_sp
, a
, szB
))
913 extra
.Err
.Addr
.isWrite
= isWrite
;
914 extra
.Err
.Addr
.szB
= szB
;
915 extra
.Err
.Addr
.maybe_gcc
= just_below_esp
;
916 extra
.Err
.Addr
.ai
.tag
= Addr_Undescribed
;
917 VG_(maybe_record_error
)( tid
, Err_Addr
, a
, /*s*/NULL
, &extra
);
920 void MC_(record_value_error
) ( ThreadId tid
, Int szB
, UInt otag
)
923 tl_assert( MC_(clo_mc_level
) >= 2 );
925 tl_assert( MC_(clo_mc_level
) == 3 );
926 extra
.Err
.Value
.szB
= szB
;
927 extra
.Err
.Value
.otag
= otag
;
928 extra
.Err
.Value
.origin_ec
= NULL
; /* Filled in later */
929 VG_(maybe_record_error
)( tid
, Err_Value
, /*addr*/0, /*s*/NULL
, &extra
);
932 void MC_(record_cond_error
) ( ThreadId tid
, UInt otag
)
935 tl_assert( MC_(clo_mc_level
) >= 2 );
937 tl_assert( MC_(clo_mc_level
) == 3 );
938 extra
.Err
.Cond
.otag
= otag
;
939 extra
.Err
.Cond
.origin_ec
= NULL
; /* Filled in later */
940 VG_(maybe_record_error
)( tid
, Err_Cond
, /*addr*/0, /*s*/NULL
, &extra
);
943 /* --- Called from non-generated code --- */
945 /* This is for memory errors in signal-related memory. */
946 void MC_(record_core_mem_error
) ( ThreadId tid
, const HChar
* msg
)
948 VG_(maybe_record_error
)( tid
, Err_CoreMem
, /*addr*/0, msg
, /*extra*/NULL
);
951 void MC_(record_regparam_error
) ( ThreadId tid
, const HChar
* msg
, UInt otag
)
954 tl_assert(VG_INVALID_THREADID
!= tid
);
956 tl_assert( MC_(clo_mc_level
) == 3 );
957 extra
.Err
.RegParam
.otag
= otag
;
958 extra
.Err
.RegParam
.origin_ec
= NULL
; /* Filled in later */
959 VG_(maybe_record_error
)( tid
, Err_RegParam
, /*addr*/0, msg
, &extra
);
962 void MC_(record_memparam_error
) ( ThreadId tid
, Addr a
,
963 Bool isAddrErr
, const HChar
* msg
, UInt otag
)
966 tl_assert(VG_INVALID_THREADID
!= tid
);
968 tl_assert( MC_(clo_mc_level
) >= 2 );
970 tl_assert( MC_(clo_mc_level
) == 3 );
971 tl_assert( !isAddrErr
);
973 extra
.Err
.MemParam
.isAddrErr
= isAddrErr
;
974 extra
.Err
.MemParam
.ai
.tag
= Addr_Undescribed
;
975 extra
.Err
.MemParam
.otag
= otag
;
976 extra
.Err
.MemParam
.origin_ec
= NULL
; /* Filled in later */
977 VG_(maybe_record_error
)( tid
, Err_MemParam
, a
, msg
, &extra
);
980 void MC_(record_jump_error
) ( ThreadId tid
, Addr a
)
983 tl_assert(VG_INVALID_THREADID
!= tid
);
984 extra
.Err
.Jump
.ai
.tag
= Addr_Undescribed
;
985 VG_(maybe_record_error
)( tid
, Err_Jump
, a
, /*s*/NULL
, &extra
);
988 void MC_(record_free_error
) ( ThreadId tid
, Addr a
)
991 tl_assert(VG_INVALID_THREADID
!= tid
);
992 extra
.Err
.Free
.ai
.tag
= Addr_Undescribed
;
993 VG_(maybe_record_error
)( tid
, Err_Free
, a
, /*s*/NULL
, &extra
);
996 void MC_(record_freemismatch_error
) ( ThreadId tid
, MC_Chunk
* mc
)
999 AddrInfo
* ai
= &extra
.Err
.FreeMismatch
.ai
;
1000 tl_assert(VG_INVALID_THREADID
!= tid
);
1001 ai
->tag
= Addr_Block
;
1002 ai
->Addr
.Block
.block_kind
= Block_Mallocd
; // Nb: Not 'Block_Freed'
1003 ai
->Addr
.Block
.block_desc
= "block";
1004 ai
->Addr
.Block
.block_szB
= mc
->szB
;
1005 ai
->Addr
.Block
.rwoffset
= 0;
1006 ai
->Addr
.Block
.allocated_at
= MC_(allocated_at
) (mc
);
1007 VG_(initThreadInfo
) (&ai
->Addr
.Block
.alloc_tinfo
);
1008 ai
->Addr
.Block
.freed_at
= MC_(freed_at
) (mc
);
1009 VG_(maybe_record_error
)( tid
, Err_FreeMismatch
, mc
->data
, /*s*/NULL
,
1013 void MC_(record_realloc_size_zero
) ( ThreadId tid
, Addr a
)
1016 tl_assert(VG_INVALID_THREADID
!= tid
);
1017 extra
.Err
.ReallocSizeZero
.ai
.tag
= Addr_Undescribed
;
1018 VG_(maybe_record_error
)( tid
, Err_ReallocSizeZero
, a
, /*s*/NULL
, &extra
);
1021 void MC_(record_bad_alignment
) ( ThreadId tid
, SizeT align
, SizeT size
, const HChar
*msg
)
1024 tl_assert(VG_INVALID_THREADID
!= tid
);
1025 extra
.Err
.BadAlign
.dealloc_align
= align
;
1026 extra
.Err
.BadAlign
.size
= size
;
1027 extra
.Err
.BadAlign
.msg
= msg
;
1028 VG_(maybe_record_error
)( tid
, Err_BadAlign
, /*addr*/0, /*s*/NULL
, &extra
);
1031 void MC_(record_bad_size
) ( ThreadId tid
, SizeT size
, const HChar
*function
)
1034 tl_assert(VG_INVALID_THREADID
!= tid
);
1035 extra
.Err
.BadSize
.size
= size
;
1036 extra
.Err
.BadSize
.func
= function
;
1037 VG_(maybe_record_error
)( tid
, Err_BadSize
, /*addr*/0, /*s*/NULL
, &extra
);
1040 void MC_(record_illegal_mempool_error
) ( ThreadId tid
, Addr a
)
1043 tl_assert(VG_INVALID_THREADID
!= tid
);
1044 extra
.Err
.IllegalMempool
.ai
.tag
= Addr_Undescribed
;
1045 VG_(maybe_record_error
)( tid
, Err_IllegalMempool
, a
, /*s*/NULL
, &extra
);
1048 void MC_(record_overlap_error
) ( ThreadId tid
, const HChar
* function
,
1049 Addr src
, Addr dst
, SizeT szB
)
1052 tl_assert(VG_INVALID_THREADID
!= tid
);
1053 extra
.Err
.Overlap
.src
= src
;
1054 extra
.Err
.Overlap
.dst
= dst
;
1055 extra
.Err
.Overlap
.szB
= szB
;
1056 VG_(maybe_record_error
)(
1057 tid
, Err_Overlap
, /*addr*/0, /*s*/function
, &extra
);
1060 Bool
MC_(record_leak_error
) ( ThreadId tid
, UInt n_this_record
,
1061 UInt n_total_records
, LossRecord
* lr
,
1062 Bool print_record
, Bool count_error
)
1065 extra
.Err
.Leak
.n_this_record
= n_this_record
;
1066 extra
.Err
.Leak
.n_total_records
= n_total_records
;
1067 extra
.Err
.Leak
.lr
= lr
;
1069 VG_(unique_error
) ( tid
, Err_Leak
, /*Addr*/0, /*s*/NULL
, &extra
,
1070 lr
->key
.allocated_at
, print_record
,
1071 /*allow_GDB_attach*/False
, count_error
);
1074 Bool
MC_(record_fishy_value_error
) ( ThreadId tid
, const HChar
*function_name
,
1075 const HChar
*argument_name
, SizeT value
)
1079 tl_assert(VG_INVALID_THREADID
!= tid
);
1081 if ((SSizeT
)value
>= 0) return False
; // not a fishy value
1083 extra
.Err
.FishyValue
.function_name
= function_name
;
1084 extra
.Err
.FishyValue
.argument_name
= argument_name
;
1085 extra
.Err
.FishyValue
.value
= value
;
1087 VG_(maybe_record_error
)(
1088 tid
, Err_FishyValue
, /*addr*/0, /*s*/NULL
, &extra
);
1093 void MC_(record_size_mismatch_error
) ( ThreadId tid
, MC_Chunk
* mc
, SizeT size
, const HChar
*function_names
)
1096 AddrInfo
* ai
= &extra
.Err
.SizeMismatch
.ai
;
1097 tl_assert(VG_INVALID_THREADID
!= tid
);
1098 ai
->tag
= Addr_Block
;
1099 ai
->Addr
.Block
.block_kind
= Block_Mallocd
; // Nb: Not 'Block_Freed'
1100 ai
->Addr
.Block
.block_desc
= "block";
1101 ai
->Addr
.Block
.block_szB
= mc
->szB
;
1102 ai
->Addr
.Block
.rwoffset
= 0;
1103 ai
->Addr
.Block
.allocated_at
= MC_(allocated_at
) (mc
);
1104 VG_(initThreadInfo
) (&ai
->Addr
.Block
.alloc_tinfo
);
1105 ai
->Addr
.Block
.freed_at
= MC_(freed_at
) (mc
);
1106 extra
.Err
.SizeMismatch
.size
= size
;
1107 extra
.Err
.SizeMismatch
.function_names
= function_names
;
1108 VG_(maybe_record_error
)( tid
, Err_SizeMismatch
, mc
->data
, /*s*/NULL
,
1112 void MC_(record_align_mismatch_error
) ( ThreadId tid
, MC_Chunk
* mc
, SizeT align
, Bool default_delete
, const HChar
*function_names
)
1115 AddrInfo
* ai
= &extra
.Err
.AlignMismatch
.ai
;
1116 tl_assert(VG_INVALID_THREADID
!= tid
);
1117 ai
->tag
= Addr_Block
;
1118 ai
->Addr
.Block
.block_kind
= Block_Mallocd
; // Nb: Not 'Block_Freed'
1119 ai
->Addr
.Block
.block_desc
= "block";
1120 ai
->Addr
.Block
.block_szB
= mc
->szB
;
1121 ai
->Addr
.Block
.rwoffset
= 0;
1122 ai
->Addr
.Block
.allocated_at
= MC_(allocated_at
) (mc
);
1123 VG_(initThreadInfo
) (&ai
->Addr
.Block
.alloc_tinfo
);
1124 ai
->Addr
.Block
.freed_at
= MC_(freed_at
) (mc
);
1125 extra
.Err
.AlignMismatch
.alloc_align
= mc
->alignB
;
1126 extra
.Err
.AlignMismatch
.dealloc_align
= align
;
1127 extra
.Err
.AlignMismatch
.default_delete
= default_delete
;
1128 extra
.Err
.AlignMismatch
.function_names
= function_names
;
1129 VG_(maybe_record_error
)( tid
, Err_AlignMismatch
, mc
->data
, /*s*/NULL
,
1133 void MC_(record_user_error
) ( ThreadId tid
, Addr a
,
1134 Bool isAddrErr
, UInt otag
)
1138 tl_assert(!isAddrErr
);
1139 tl_assert( MC_(clo_mc_level
) == 3 );
1142 tl_assert( MC_(clo_mc_level
) >= 2 );
1144 tl_assert(VG_INVALID_THREADID
!= tid
);
1145 extra
.Err
.User
.isAddrErr
= isAddrErr
;
1146 extra
.Err
.User
.ai
.tag
= Addr_Undescribed
;
1147 extra
.Err
.User
.otag
= otag
;
1148 extra
.Err
.User
.origin_ec
= NULL
; /* Filled in later */
1149 VG_(maybe_record_error
)( tid
, Err_User
, a
, /*s*/NULL
, &extra
);
1152 Bool
MC_(is_mempool_block
)(MC_Chunk
* mc_search
)
1156 if (!MC_(mempool_list
))
1159 // A chunk can only come from a mempool if a custom allocator
1160 // is used. No search required for other kinds.
1161 if (mc_search
->allockind
== MC_AllocCustom
) {
1162 VG_(HT_ResetIter
)( MC_(mempool_list
) );
1163 while ( (mp
= VG_(HT_Next
)(MC_(mempool_list
))) ) {
1165 VG_(HT_ResetIter
)(mp
->chunks
);
1166 while ( (mc
= VG_(HT_Next
)(mp
->chunks
)) ) {
1167 if (mc
== mc_search
)
1176 /*------------------------------------------------------------*/
1177 /*--- Other error operations ---*/
1178 /*------------------------------------------------------------*/
1180 /* Compare error contexts, to detect duplicates. Note that if they
1181 are otherwise the same, the faulting addrs and associated rwoffsets
1182 are allowed to be different. */
1183 Bool
MC_(eq_Error
) ( VgRes res
, const Error
* e1
, const Error
* e2
)
1185 MC_Error
* extra1
= VG_(get_error_extra
)(e1
);
1186 MC_Error
* extra2
= VG_(get_error_extra
)(e2
);
1188 /* Guaranteed by calling function */
1189 tl_assert(VG_(get_error_kind
)(e1
) == VG_(get_error_kind
)(e2
));
1191 switch (VG_(get_error_kind
)(e1
)) {
1193 const HChar
*e1s
, *e2s
;
1194 e1s
= VG_(get_error_string
)(e1
);
1195 e2s
= VG_(get_error_string
)(e2
);
1196 if (e1s
== e2s
) return True
;
1197 if (VG_STREQ(e1s
, e2s
)) return True
;
1202 return VG_STREQ(VG_(get_error_string
)(e1
), VG_(get_error_string
)(e2
));
1204 // Perhaps we should also check the addrinfo.akinds for equality.
1205 // That would result in more error reports, but only in cases where
1206 // a register contains uninitialised bytes and points to memory
1207 // containing uninitialised bytes. Currently, the 2nd of those to be
1208 // detected won't be reported. That is (nearly?) always the memory
1209 // error, which is good.
1211 if (!VG_STREQ(VG_(get_error_string
)(e1
),
1212 VG_(get_error_string
)(e2
))) return False
;
1215 return ( extra1
->Err
.User
.isAddrErr
== extra2
->Err
.User
.isAddrErr
1219 case Err_FreeMismatch
:
1221 case Err_IllegalMempool
:
1224 case Err_ReallocSizeZero
:
1227 case Err_FishyValue
:
1228 return VG_STREQ(extra1
->Err
.FishyValue
.function_name
,
1229 extra2
->Err
.FishyValue
.function_name
) &&
1230 VG_STREQ(extra1
->Err
.FishyValue
.argument_name
,
1231 extra2
->Err
.FishyValue
.argument_name
);
1234 return ( extra1
->Err
.Addr
.szB
== extra2
->Err
.Addr
.szB
1238 return ( extra1
->Err
.Value
.szB
== extra2
->Err
.Value
.szB
1242 if (extra1
->Err
.BadAlign
.size
&&
1243 extra2
->Err
.BadAlign
.size
) {
1244 // cases where size should be non-zero or a multiple of alignment
1245 return extra1
->Err
.BadAlign
.size
==
1246 extra2
->Err
.BadAlign
.size
1248 extra1
->Err
.BadAlign
.dealloc_align
==
1249 extra2
->Err
.BadAlign
.dealloc_align
;
1251 // non multiple of 2 alignment
1252 return extra1
->Err
.BadAlign
.dealloc_align
==
1253 extra2
->Err
.BadAlign
.dealloc_align
;
1257 // sized delete mismatch
1258 return extra1
->Err
.BadSize
.size
==
1259 extra2
->Err
.BadSize
.size
;
1261 case Err_SizeMismatch
:
1262 return extra1
->Err
.SizeMismatch
.size
==
1263 extra2
->Err
.SizeMismatch
.size
;
1265 case Err_AlignMismatch
:
1266 // alignments both powers of 2 but different
1267 return extra1
->Err
.AlignMismatch
.alloc_align
==
1268 extra2
->Err
.AlignMismatch
.alloc_align
1270 extra1
->Err
.AlignMismatch
.dealloc_align
==
1271 extra2
->Err
.AlignMismatch
.dealloc_align
1273 extra1
->Err
.AlignMismatch
.default_delete
==
1274 extra2
->Err
.AlignMismatch
.default_delete
;
1277 VG_(tool_panic
)("Shouldn't get Err_Leak in mc_eq_Error,\n"
1278 "since it's handled with VG_(unique_error)()!");
1281 VG_(printf
)("Error:\n unknown error code %d\n",
1282 VG_(get_error_kind
)(e1
));
1283 VG_(tool_panic
)("unknown error code in mc_eq_Error");
1287 /* Functions used when searching MC_Chunk lists */
1289 Bool
addr_is_in_MC_Chunk_default_REDZONE_SZB(MC_Chunk
* mc
, Addr a
)
1291 return VG_(addr_is_in_block
)( a
, mc
->data
, mc
->szB
,
1292 MC_(Malloc_Redzone_SzB
) );
1295 Bool
addr_is_in_MC_Chunk_with_REDZONE_SZB(MC_Chunk
* mc
, Addr a
, SizeT rzB
)
1297 return VG_(addr_is_in_block
)( a
, mc
->data
, mc
->szB
,
1301 // Forward declarations
1302 static Bool
client_block_maybe_describe( Addr a
, AddrInfo
* ai
);
1303 static Bool
mempool_block_maybe_describe( Addr a
, Bool is_metapool
,
1307 /* Describe an address as best you can, for error messages,
1308 putting the result in ai. */
1309 static void describe_addr ( DiEpoch ep
, Addr a
, /*OUT*/AddrInfo
* ai
)
1313 tl_assert(Addr_Undescribed
== ai
->tag
);
1315 /* -- Perhaps it's a user-named block? -- */
1316 if (client_block_maybe_describe( a
, ai
)) {
1320 /* -- Perhaps it's in mempool block (non-meta)? -- */
1321 if (mempool_block_maybe_describe( a
, /*is_metapool*/ False
, ai
)) {
1325 /* Blocks allocated by memcheck malloc functions are either
1326 on the recently freed list or on the malloc-ed list.
1327 Custom blocks can be on both : a recently freed block might
1328 have been just re-allocated.
1329 So, first search the malloc-ed block, as the most recent
1330 block is the probable cause of error.
1331 We however detect and report that this is a recently re-allocated
1333 /* -- Search for a currently malloc'd block which might bracket it. -- */
1334 VG_(HT_ResetIter
)(MC_(malloc_list
));
1335 while ( (mc
= VG_(HT_Next
)(MC_(malloc_list
))) ) {
1336 if (!MC_(is_mempool_block
)(mc
) &&
1337 addr_is_in_MC_Chunk_default_REDZONE_SZB(mc
, a
)) {
1338 ai
->tag
= Addr_Block
;
1339 ai
->Addr
.Block
.block_kind
= Block_Mallocd
;
1340 if (MC_(get_freed_block_bracketting
)( a
))
1341 ai
->Addr
.Block
.block_desc
= "recently re-allocated block";
1343 ai
->Addr
.Block
.block_desc
= "block";
1344 ai
->Addr
.Block
.block_szB
= mc
->szB
;
1345 ai
->Addr
.Block
.rwoffset
= (Word
)a
- (Word
)mc
->data
;
1346 ai
->Addr
.Block
.allocated_at
= MC_(allocated_at
)(mc
);
1347 VG_(initThreadInfo
) (&ai
->Addr
.Block
.alloc_tinfo
);
1348 ai
->Addr
.Block
.freed_at
= MC_(freed_at
)(mc
);
1352 /* -- Search for a recently freed block which might bracket it. -- */
1353 mc
= MC_(get_freed_block_bracketting
)( a
);
1355 ai
->tag
= Addr_Block
;
1356 ai
->Addr
.Block
.block_kind
= Block_Freed
;
1357 ai
->Addr
.Block
.block_desc
= "block";
1358 ai
->Addr
.Block
.block_szB
= mc
->szB
;
1359 ai
->Addr
.Block
.rwoffset
= (Word
)a
- (Word
)mc
->data
;
1360 ai
->Addr
.Block
.allocated_at
= MC_(allocated_at
)(mc
);
1361 VG_(initThreadInfo
) (&ai
->Addr
.Block
.alloc_tinfo
);
1362 ai
->Addr
.Block
.freed_at
= MC_(freed_at
)(mc
);
1366 /* -- Perhaps it's in a meta mempool block? -- */
1367 /* This test is done last, because metapool blocks overlap with blocks
1368 handed out to the application. That makes every heap address part of
1369 a metapool block, so the interesting cases are handled first.
1370 This final search is a last-ditch attempt. When found, it is probably
1371 an error in the custom allocator itself. */
1372 if (mempool_block_maybe_describe( a
, /*is_metapool*/ True
, ai
)) {
1376 /* No block found. Search a non-heap block description. */
1377 VG_(describe_addr
) (ep
, a
, ai
);
1380 void MC_(pp_describe_addr
) ( DiEpoch ep
, Addr a
)
1384 ai
.tag
= Addr_Undescribed
;
1385 describe_addr (ep
, a
, &ai
);
1386 VG_(pp_addrinfo_mc
) (a
, &ai
, /* maybe_gcc */ False
);
1387 VG_(clear_addrinfo
) (&ai
);
1390 /* Fill in *origin_ec as specified by otag, or NULL it out if otag
1391 does not refer to a known origin. */
1392 static void update_origin ( /*OUT*/ExeContext
** origin_ec
,
1395 UInt ecu
= otag
& ~3;
1397 if (VG_(is_plausible_ECU
)(ecu
)) {
1398 *origin_ec
= VG_(get_ExeContext_from_ECU
)( ecu
);
1402 /* Updates the copy with address info if necessary (but not for all errors). */
1403 UInt
MC_(update_Error_extra
)( const Error
* err
)
1405 MC_Error
* extra
= VG_(get_error_extra
)(err
);
1406 DiEpoch ep
= VG_(get_ExeContext_epoch
)(VG_(get_error_where
)(err
));
1408 switch (VG_(get_error_kind
)(err
)) {
1409 // These ones don't have addresses associated with them, and so don't
1410 // need any updating.
1415 case Err_FishyValue
:
1416 // For Err_Leaks the returned size does not matter -- they are always
1417 // shown with VG_(unique_error)() so they 'extra' not copied. But
1418 // we make it consistent with the others.
1422 case Err_SizeMismatch
:
1423 case Err_AlignMismatch
:
1424 return sizeof(MC_Error
);
1426 // For value errors, get the ExeContext corresponding to the
1427 // origin tag. Note that it is a kludge to assume that
1428 // a length-1 trace indicates a stack origin. FIXME.
1430 update_origin( &extra
->Err
.Value
.origin_ec
,
1431 extra
->Err
.Value
.otag
);
1432 return sizeof(MC_Error
);
1434 update_origin( &extra
->Err
.Cond
.origin_ec
,
1435 extra
->Err
.Cond
.otag
);
1436 return sizeof(MC_Error
);
1438 update_origin( &extra
->Err
.RegParam
.origin_ec
,
1439 extra
->Err
.RegParam
.otag
);
1440 return sizeof(MC_Error
);
1442 // These ones always involve a memory address.
1444 describe_addr ( ep
, VG_(get_error_address
)(err
),
1445 &extra
->Err
.Addr
.ai
);
1446 return sizeof(MC_Error
);
1448 describe_addr ( ep
, VG_(get_error_address
)(err
),
1449 &extra
->Err
.MemParam
.ai
);
1450 update_origin( &extra
->Err
.MemParam
.origin_ec
,
1451 extra
->Err
.MemParam
.otag
);
1452 return sizeof(MC_Error
);
1454 describe_addr ( ep
, VG_(get_error_address
)(err
),
1455 &extra
->Err
.Jump
.ai
);
1456 return sizeof(MC_Error
);
1458 describe_addr ( ep
, VG_(get_error_address
)(err
),
1459 &extra
->Err
.User
.ai
);
1460 update_origin( &extra
->Err
.User
.origin_ec
,
1461 extra
->Err
.User
.otag
);
1462 return sizeof(MC_Error
);
1464 describe_addr ( ep
, VG_(get_error_address
)(err
),
1465 &extra
->Err
.Free
.ai
);
1466 return sizeof(MC_Error
);
1467 case Err_IllegalMempool
:
1468 describe_addr ( ep
, VG_(get_error_address
)(err
),
1469 &extra
->Err
.IllegalMempool
.ai
);
1470 return sizeof(MC_Error
);
1472 // Err_FreeMismatches have already had their address described; this is
1473 // possible because we have the MC_Chunk on hand when the error is
1474 // detected. However, the address may be part of a user block, and if so
1475 // we override the pre-determined description with a user block one.
1476 case Err_FreeMismatch
: {
1477 tl_assert(extra
&& Block_Mallocd
==
1478 extra
->Err
.FreeMismatch
.ai
.Addr
.Block
.block_kind
);
1479 (void)client_block_maybe_describe( VG_(get_error_address
)(err
),
1480 &extra
->Err
.FreeMismatch
.ai
);
1481 return sizeof(MC_Error
);
1483 case Err_ReallocSizeZero
:
1484 describe_addr ( ep
, VG_(get_error_address
)(err
),
1485 &extra
->Err
.ReallocSizeZero
.ai
);
1486 return sizeof(MC_Error
);
1488 default: VG_(tool_panic
)("mc_update_extra: bad errkind");
1493 static Bool
client_block_maybe_describe( Addr a
,
1494 /*OUT*/AddrInfo
* ai
)
1497 CGenBlock
* cgbs
= NULL
;
1500 MC_(get_ClientBlock_array
)( &cgbs
, &cgb_used
);
1502 tl_assert(cgb_used
== 0);
1504 /* Perhaps it's a general block ? */
1505 for (i
= 0; i
< cgb_used
; i
++) {
1506 if (cgbs
[i
].start
== 0 && cgbs
[i
].size
== 0)
1508 // Use zero as the redzone for client blocks.
1509 if (VG_(addr_is_in_block
)(a
, cgbs
[i
].start
, cgbs
[i
].size
, 0)) {
1510 ai
->tag
= Addr_Block
;
1511 ai
->Addr
.Block
.block_kind
= Block_UserG
;
1512 ai
->Addr
.Block
.block_desc
= cgbs
[i
].desc
;
1513 ai
->Addr
.Block
.block_szB
= cgbs
[i
].size
;
1514 ai
->Addr
.Block
.rwoffset
= (Word
)(a
) - (Word
)(cgbs
[i
].start
);
1515 ai
->Addr
.Block
.allocated_at
= cgbs
[i
].where
;
1516 VG_(initThreadInfo
) (&ai
->Addr
.Block
.alloc_tinfo
);
1517 ai
->Addr
.Block
.freed_at
= VG_(null_ExeContext
)();;
1525 static Bool
mempool_block_maybe_describe( Addr a
, Bool is_metapool
,
1526 /*OUT*/AddrInfo
* ai
)
1529 tl_assert( MC_(mempool_list
) );
1531 VG_(HT_ResetIter
)( MC_(mempool_list
) );
1532 while ( (mp
= VG_(HT_Next
)(MC_(mempool_list
))) ) {
1533 if (mp
->chunks
!= NULL
&& mp
->metapool
== is_metapool
) {
1535 VG_(HT_ResetIter
)(mp
->chunks
);
1536 while ( (mc
= VG_(HT_Next
)(mp
->chunks
)) ) {
1537 if (addr_is_in_MC_Chunk_with_REDZONE_SZB(mc
, a
, mp
->rzB
)) {
1538 ai
->tag
= Addr_Block
;
1539 ai
->Addr
.Block
.block_kind
= Block_MempoolChunk
;
1540 ai
->Addr
.Block
.block_desc
= "block";
1541 ai
->Addr
.Block
.block_szB
= mc
->szB
;
1542 ai
->Addr
.Block
.rwoffset
= (Word
)a
- (Word
)mc
->data
;
1543 ai
->Addr
.Block
.allocated_at
= MC_(allocated_at
)(mc
);
1544 VG_(initThreadInfo
) (&ai
->Addr
.Block
.alloc_tinfo
);
1545 ai
->Addr
.Block
.freed_at
= MC_(freed_at
)(mc
);
1555 /*------------------------------------------------------------*/
1556 /*--- Suppressions ---*/
1557 /*------------------------------------------------------------*/
1561 ParamSupp
, // Bad syscall params
1562 UserSupp
, // Errors arising from client-request checks
1563 CoreMemSupp
, // Memory errors in core (pthread ops, signal handling)
1565 // Undefined value errors of given size
1566 Value1Supp
, Value2Supp
, Value4Supp
, Value8Supp
, Value16Supp
, Value32Supp
,
1568 // Undefined value error in conditional.
1571 // Unaddressable read/write attempt at given size
1572 Addr1Supp
, Addr2Supp
, Addr4Supp
, Addr8Supp
, Addr16Supp
, Addr32Supp
,
1574 JumpSupp
, // Jump to unaddressable target
1575 FreeSupp
, // Invalid or mismatching free
1576 OverlapSupp
, // Overlapping blocks in memcpy(), strcpy(), etc
1577 LeakSupp
, // Something to be suppressed in a leak check.
1578 MempoolSupp
, // Memory pool suppression.
1579 FishyValueSupp
, // Fishy value suppression.
1580 ReallocSizeZeroSupp
, // realloc size 0 suppression
1581 BadAlignSupp
, // Alignment not 2
1582 BadSizeSupp
, // aligned alloc with size 0
1583 SizeMismatch
, // Sized deallocation did not match allocation size
1584 AlignMismatch
, // Aligned deallocation did not match aligned allocation
1588 Bool
MC_(is_recognised_suppression
) ( const HChar
* name
, Supp
* su
)
1592 if (VG_STREQ(name
, "Param")) skind
= ParamSupp
;
1593 else if (VG_STREQ(name
, "User")) skind
= UserSupp
;
1594 else if (VG_STREQ(name
, "CoreMem")) skind
= CoreMemSupp
;
1595 else if (VG_STREQ(name
, "Addr1")) skind
= Addr1Supp
;
1596 else if (VG_STREQ(name
, "Addr2")) skind
= Addr2Supp
;
1597 else if (VG_STREQ(name
, "Addr4")) skind
= Addr4Supp
;
1598 else if (VG_STREQ(name
, "Addr8")) skind
= Addr8Supp
;
1599 else if (VG_STREQ(name
, "Addr16")) skind
= Addr16Supp
;
1600 else if (VG_STREQ(name
, "Addr32")) skind
= Addr32Supp
;
1601 else if (VG_STREQ(name
, "Jump")) skind
= JumpSupp
;
1602 else if (VG_STREQ(name
, "Free")) skind
= FreeSupp
;
1603 else if (VG_STREQ(name
, "Leak")) skind
= LeakSupp
;
1604 else if (VG_STREQ(name
, "Overlap")) skind
= OverlapSupp
;
1605 else if (VG_STREQ(name
, "Mempool")) skind
= MempoolSupp
;
1606 else if (VG_STREQ(name
, "Cond")) skind
= CondSupp
;
1607 else if (VG_STREQ(name
, "Value0")) skind
= CondSupp
; /* backwards compat */
1608 else if (VG_STREQ(name
, "Value1")) skind
= Value1Supp
;
1609 else if (VG_STREQ(name
, "Value2")) skind
= Value2Supp
;
1610 else if (VG_STREQ(name
, "Value4")) skind
= Value4Supp
;
1611 else if (VG_STREQ(name
, "Value8")) skind
= Value8Supp
;
1612 else if (VG_STREQ(name
, "Value16")) skind
= Value16Supp
;
1613 else if (VG_STREQ(name
, "Value32")) skind
= Value32Supp
;
1614 else if (VG_STREQ(name
, "FishyValue")) skind
= FishyValueSupp
;
1615 else if (VG_STREQ(name
, "ReallocZero")) skind
= ReallocSizeZeroSupp
;
1616 else if (VG_STREQ(name
, "BadAlign")) skind
= BadAlignSupp
;
1617 else if (VG_STREQ(name
, "BadSize")) skind
= BadSizeSupp
;
1618 else if (VG_STREQ(name
, "SizeMismatch")) skind
= SizeMismatch
;
1619 else if (VG_STREQ(name
, "AlignMismatch")) skind
= AlignMismatch
;
1623 VG_(set_supp_kind
)(su
, skind
);
1627 typedef struct _MC_LeakSuppExtra MC_LeakSuppExtra
;
1629 struct _MC_LeakSuppExtra
{
1630 UInt match_leak_kinds
;
1631 UInt leak_search_gen
;
1633 /* Maintains nr of blocks and bytes suppressed with this suppression
1634 during the leak search identified by leak_search_gen.
1635 blocks_suppressed and bytes_suppressed are reset to 0 when
1636 used the first time during a leak search. */
1637 SizeT blocks_suppressed
;
1638 SizeT bytes_suppressed
;
1642 const HChar
*function_name
;
1643 const HChar
*argument_name
;
1644 } MC_FishyValueExtra
;
1646 Bool
MC_(read_extra_suppression_info
) ( Int fd
, HChar
** bufpp
,
1647 SizeT
* nBufp
, Int
* lineno
, Supp
*su
)
1652 if (VG_(get_supp_kind
)(su
) == ParamSupp
) {
1653 eof
= VG_(get_line
) ( fd
, bufpp
, nBufp
, lineno
);
1654 if (eof
) return False
;
1655 VG_(set_supp_string
)(su
, VG_(strdup
)("mc.resi.1", *bufpp
));
1656 if (VG_(strcmp
) (*bufpp
, "preadv(vector[...])") == 0
1657 || VG_(strcmp
) (*bufpp
, "pwritev(vector[...])") == 0) {
1658 /* Report the incompatible change introduced in 3.15
1659 when reading a unsupported 3.14 or before entry.
1661 VG_(umsg
)("WARNING: %s is an obsolete suppression line "
1662 "not supported in valgrind 3.15 or later.\n"
1663 "You should replace [...] by a specific index"
1664 " such as [0] or [1] or [2] or similar\n\n", *bufpp
);
1666 } else if (VG_(get_supp_kind
)(su
) == LeakSupp
) {
1667 // We might have the optional match-leak-kinds line
1668 MC_LeakSuppExtra
* lse
;
1669 lse
= VG_(malloc
)("mc.resi.2", sizeof(MC_LeakSuppExtra
));
1670 lse
->match_leak_kinds
= MC_(all_Reachedness
)();
1671 lse
->blocks_suppressed
= 0;
1672 lse
->bytes_suppressed
= 0;
1673 lse
->leak_search_gen
= 0;
1674 VG_(set_supp_extra
)(su
, lse
); // By default, all kinds will match.
1675 eof
= VG_(get_line
) ( fd
, bufpp
, nBufp
, lineno
);
1676 if (eof
) return True
; // old LeakSupp style, no match-leak-kinds line.
1677 if (0 == VG_(strncmp
)(*bufpp
, "match-leak-kinds:", 17)) {
1679 while ((*bufpp
)[i
] && VG_(isspace
)((*bufpp
)[i
]))
1681 if (!VG_(parse_enum_set
)(MC_(parse_leak_kinds_tokens
),
1683 (*bufpp
)+i
, &lse
->match_leak_kinds
)) {
1687 return False
; // unknown extra line.
1689 } else if (VG_(get_supp_kind
)(su
) == FishyValueSupp
) {
1690 MC_FishyValueExtra
*extra
;
1691 HChar
*p
, *function_name
, *argument_name
= NULL
;
1693 eof
= VG_(get_line
) ( fd
, bufpp
, nBufp
, lineno
);
1694 if (eof
) return True
;
1696 // The suppression string is: function_name(argument_name)
1697 function_name
= VG_(strdup
)("mv.resi.4", *bufpp
);
1698 p
= VG_(strchr
)(function_name
, '(');
1702 p
= VG_(strchr
)(p
, ')');
1706 if (p
== NULL
) { // malformed suppression string
1707 VG_(free
)(function_name
);
1711 extra
= VG_(malloc
)("mc.resi.3", sizeof *extra
);
1712 extra
->function_name
= function_name
;
1713 extra
->argument_name
= argument_name
;
1715 VG_(set_supp_extra
)(su
, extra
);
1720 Bool
MC_(error_matches_suppression
) ( const Error
* err
, const Supp
* su
)
1723 MC_Error
* extra
= VG_(get_error_extra
)(err
);
1724 ErrorKind ekind
= VG_(get_error_kind
)(err
);
1726 switch (VG_(get_supp_kind
)(su
)) {
1728 return ((ekind
== Err_RegParam
|| ekind
== Err_MemParam
)
1729 && VG_STREQ(VG_(get_error_string
)(err
),
1730 VG_(get_supp_string
)(su
)));
1733 return (ekind
== Err_User
);
1736 return (ekind
== Err_CoreMem
1737 && VG_STREQ(VG_(get_error_string
)(err
),
1738 VG_(get_supp_string
)(su
)));
1740 case Value1Supp
: su_szB
= 1; goto value_case
;
1741 case Value2Supp
: su_szB
= 2; goto value_case
;
1742 case Value4Supp
: su_szB
= 4; goto value_case
;
1743 case Value8Supp
: su_szB
= 8; goto value_case
;
1744 case Value16Supp
:su_szB
=16; goto value_case
;
1745 case Value32Supp
:su_szB
=32; goto value_case
;
1747 return (ekind
== Err_Value
&& extra
->Err
.Value
.szB
== su_szB
);
1750 return (ekind
== Err_Cond
);
1752 case Addr1Supp
: su_szB
= 1; goto addr_case
;
1753 case Addr2Supp
: su_szB
= 2; goto addr_case
;
1754 case Addr4Supp
: su_szB
= 4; goto addr_case
;
1755 case Addr8Supp
: su_szB
= 8; goto addr_case
;
1756 case Addr16Supp
:su_szB
=16; goto addr_case
;
1757 case Addr32Supp
:su_szB
=32; goto addr_case
;
1759 return (ekind
== Err_Addr
&& extra
->Err
.Addr
.szB
== su_szB
);
1762 return (ekind
== Err_Jump
);
1765 return (ekind
== Err_Free
|| ekind
== Err_FreeMismatch
);
1768 return (ekind
== Err_Overlap
);
1771 if (ekind
== Err_Leak
) {
1772 MC_LeakSuppExtra
* lse
= (MC_LeakSuppExtra
*) VG_(get_supp_extra
)(su
);
1773 if (lse
->leak_search_gen
!= MC_(leak_search_gen
)) {
1774 // First time we see this suppression during this leak search.
1775 // => reset the counters to 0.
1776 lse
->blocks_suppressed
= 0;
1777 lse
->bytes_suppressed
= 0;
1778 lse
->leak_search_gen
= MC_(leak_search_gen
);
1780 return RiS(extra
->Err
.Leak
.lr
->key
.state
, lse
->match_leak_kinds
);
1785 return (ekind
== Err_IllegalMempool
);
1787 case FishyValueSupp
: {
1788 MC_FishyValueExtra
*supp_extra
= VG_(get_supp_extra
)(su
);
1790 return (ekind
== Err_FishyValue
) &&
1791 VG_STREQ(extra
->Err
.FishyValue
.function_name
,
1792 supp_extra
->function_name
) &&
1793 VG_STREQ(extra
->Err
.FishyValue
.argument_name
,
1794 supp_extra
->argument_name
);
1797 case ReallocSizeZeroSupp
:
1798 return (ekind
== Err_ReallocSizeZero
);
1801 return (ekind
== Err_BadAlign
);
1804 return (ekind
== Err_BadSize
);
1807 return (ekind
== Err_SizeMismatch
);
1810 return (ekind
== Err_AlignMismatch
);
1813 VG_(printf
)("Error:\n"
1814 " unknown suppression type %d\n",
1815 VG_(get_supp_kind
)(su
));
1816 VG_(tool_panic
)("unknown suppression type in "
1817 "MC_(error_matches_suppression)");
1821 const HChar
* MC_(get_error_name
) ( const Error
* err
)
1823 switch (VG_(get_error_kind
)(err
)) {
1824 case Err_RegParam
: return "Param";
1825 case Err_MemParam
: return "Param";
1826 case Err_User
: return "User";
1827 case Err_FreeMismatch
: return "Free";
1828 case Err_IllegalMempool
: return "Mempool";
1829 case Err_Free
: return "Free";
1830 case Err_Jump
: return "Jump";
1831 case Err_CoreMem
: return "CoreMem";
1832 case Err_Overlap
: return "Overlap";
1833 case Err_Leak
: return "Leak";
1834 case Err_Cond
: return "Cond";
1835 case Err_FishyValue
: return "FishyValue";
1836 case Err_ReallocSizeZero
: return "ReallocZero";
1837 case Err_BadAlign
: return "BadAlign";
1838 case Err_BadSize
: return "BadSize";
1839 case Err_SizeMismatch
: return "SizeMismatch";
1840 case Err_AlignMismatch
: return "AlignMismatch";
1842 MC_Error
* extra
= VG_(get_error_extra
)(err
);
1843 switch ( extra
->Err
.Addr
.szB
) {
1844 case 1: return "Addr1";
1845 case 2: return "Addr2";
1846 case 4: return "Addr4";
1847 case 8: return "Addr8";
1848 case 16: return "Addr16";
1849 case 32: return "Addr32";
1850 default: VG_(tool_panic
)("unexpected size for Addr");
1854 MC_Error
* extra
= VG_(get_error_extra
)(err
);
1855 switch ( extra
->Err
.Value
.szB
) {
1856 case 1: return "Value1";
1857 case 2: return "Value2";
1858 case 4: return "Value4";
1859 case 8: return "Value8";
1860 case 16: return "Value16";
1861 case 32: return "Value32";
1862 default: VG_(tool_panic
)("unexpected size for Value");
1865 default: VG_(tool_panic
)("get_error_name: unexpected type");
1869 SizeT
MC_(get_extra_suppression_info
) ( const Error
* err
,
1870 /*OUT*/HChar
* buf
, Int nBuf
)
1872 ErrorKind ekind
= VG_(get_error_kind
)(err
);
1874 tl_assert(nBuf
>= 1);
1876 if (Err_RegParam
== ekind
|| Err_MemParam
== ekind
) {
1877 const HChar
* errstr
= VG_(get_error_string
)(err
);
1879 return VG_(snprintf
)(buf
, nBuf
, "%s", errstr
);
1880 } else if (Err_Leak
== ekind
) {
1881 MC_Error
* extra
= VG_(get_error_extra
)(err
);
1882 return VG_(snprintf
) (buf
, nBuf
, "match-leak-kinds: %s",
1883 pp_Reachedness_for_leak_kinds(extra
->Err
.Leak
.lr
->key
.state
));
1884 } else if (Err_FishyValue
== ekind
) {
1885 MC_Error
* extra
= VG_(get_error_extra
)(err
);
1886 return VG_(snprintf
) (buf
, nBuf
, "%s(%s)",
1887 extra
->Err
.FishyValue
.function_name
,
1888 extra
->Err
.FishyValue
.argument_name
);
1895 SizeT
MC_(print_extra_suppression_use
) ( const Supp
*su
,
1896 /*OUT*/HChar
*buf
, Int nBuf
)
1898 tl_assert(nBuf
>= 1);
1900 if (VG_(get_supp_kind
)(su
) == LeakSupp
) {
1901 MC_LeakSuppExtra
*lse
= (MC_LeakSuppExtra
*) VG_(get_supp_extra
) (su
);
1903 if (lse
->leak_search_gen
== MC_(leak_search_gen
)
1904 && lse
->blocks_suppressed
> 0) {
1905 return VG_(snprintf
) (buf
, nBuf
,
1906 "suppressed: %'lu bytes in %'lu blocks",
1907 lse
->bytes_suppressed
,
1908 lse
->blocks_suppressed
);
1916 void MC_(update_extra_suppression_use
) ( const Error
* err
, const Supp
* su
)
1918 if (VG_(get_supp_kind
)(su
) == LeakSupp
) {
1919 MC_LeakSuppExtra
*lse
= (MC_LeakSuppExtra
*) VG_(get_supp_extra
) (su
);
1920 MC_Error
* extra
= VG_(get_error_extra
)(err
);
1922 tl_assert (lse
->leak_search_gen
== MC_(leak_search_gen
));
1923 lse
->blocks_suppressed
+= extra
->Err
.Leak
.lr
->num_blocks
;
1924 lse
->bytes_suppressed
1925 += extra
->Err
.Leak
.lr
->szB
+ extra
->Err
.Leak
.lr
->indirect_szB
;
1929 /*--------------------------------------------------------------------*/
1930 /*--- end mc_errors.c ---*/
1931 /*--------------------------------------------------------------------*/