blob: b9aa00a39edb11210c7f3d61a0491d9b3d692c4d [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
sewardj03f8d3f2012-08-05 15:46:46 +000011 Copyright (C) 2000-2012 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"
sewardj7ce71662008-05-02 10:33:15 +000047
48#include "mc_include.h"
sewardj7ce71662008-05-02 10:33:15 +000049
50
51/*------------------------------------------------------------*/
52/*--- Error types ---*/
53/*------------------------------------------------------------*/
54
55/* See comment in mc_include.h */
56Bool MC_(any_value_errors) = False;
57
58
59// Different kinds of blocks.
60typedef enum {
61 Block_Mallocd = 111,
62 Block_Freed,
sewardj7ce71662008-05-02 10:33:15 +000063 Block_MempoolChunk,
64 Block_UserG
65} BlockKind;
66
67/* ------------------ Addresses -------------------- */
68
69/* The classification of a faulting address. */
70typedef
71 enum {
72 Addr_Undescribed, // as-yet unclassified
73 Addr_Unknown, // classification yielded nothing useful
74 Addr_Block, // in malloc'd/free'd block
75 Addr_Stack, // on a thread's stack
76 Addr_DataSym, // in a global data sym
77 Addr_Variable, // variable described by the debug info
78 Addr_SectKind // last-ditch classification attempt
79 }
80 AddrTag;
81
82typedef
83 struct _AddrInfo
84 AddrInfo;
85
86struct _AddrInfo {
87 AddrTag tag;
88 union {
89 // As-yet unclassified.
90 struct { } Undescribed;
91
92 // On a stack.
93 struct {
94 ThreadId tid; // Which thread's stack?
95 } Stack;
96
97 // This covers heap blocks (normal and from mempools) and user-defined
98 // blocks.
99 struct {
100 BlockKind block_kind;
floriana5f894c2012-10-21 03:43:20 +0000101 const HChar* block_desc; // "block", "mempool" or user-defined
sewardj7ce71662008-05-02 10:33:15 +0000102 SizeT block_szB;
njnc4431bf2009-01-15 21:29:24 +0000103 PtrdiffT rwoffset;
philippe8617b5b2013-01-12 19:53:08 +0000104 ExeContext* allocated_at; // might be null_ExeContext.
105 ExeContext* freed_at; // might be null_ExeContext.
sewardj7ce71662008-05-02 10:33:15 +0000106 } Block;
107
njnc4431bf2009-01-15 21:29:24 +0000108 // In a global .data symbol. This holds the first 127 chars of
109 // the variable's name (zero terminated), plus a (memory) offset.
sewardj7ce71662008-05-02 10:33:15 +0000110 struct {
florian19f91bb2012-11-10 22:29:54 +0000111 HChar name[128];
njnc4431bf2009-01-15 21:29:24 +0000112 PtrdiffT offset;
sewardj7ce71662008-05-02 10:33:15 +0000113 } DataSym;
114
sewardj6b523cd2009-07-15 14:49:40 +0000115 // Is described by Dwarf debug info. XArray*s of HChar.
sewardj7ce71662008-05-02 10:33:15 +0000116 struct {
sewardj6b523cd2009-07-15 14:49:40 +0000117 XArray* /* of HChar */ descr1;
118 XArray* /* of HChar */ descr2;
sewardj7ce71662008-05-02 10:33:15 +0000119 } Variable;
120
121 // Could only narrow it down to be the PLT/GOT/etc of a given
122 // object. Better than nothing, perhaps.
123 struct {
florian19f91bb2012-11-10 22:29:54 +0000124 HChar objname[128];
sewardj7ce71662008-05-02 10:33:15 +0000125 VgSectKind kind;
126 } SectKind;
127
128 // Classification yielded nothing useful.
129 struct { } Unknown;
130
131 } Addr;
132};
133
134/* ------------------ Errors ----------------------- */
135
136/* What kind of error it is. */
137typedef
138 enum {
139 Err_Value,
140 Err_Cond,
141 Err_CoreMem,
142 Err_Addr,
143 Err_Jump,
144 Err_RegParam,
145 Err_MemParam,
146 Err_User,
147 Err_Free,
148 Err_FreeMismatch,
149 Err_Overlap,
150 Err_Leak,
151 Err_IllegalMempool,
152 }
153 MC_ErrorTag;
154
155
156typedef struct _MC_Error MC_Error;
157
158struct _MC_Error {
159 // Nb: we don't need the tag here, as it's stored in the Error type! Yuk.
160 //MC_ErrorTag tag;
161
162 union {
163 // Use of an undefined value:
164 // - as a pointer in a load or store
165 // - as a jump target
166 struct {
167 SizeT szB; // size of value in bytes
168 // Origin info
169 UInt otag; // origin tag
170 ExeContext* origin_ec; // filled in later
171 } Value;
172
173 // Use of an undefined value in a conditional branch or move.
174 struct {
175 // Origin info
176 UInt otag; // origin tag
177 ExeContext* origin_ec; // filled in later
178 } Cond;
179
180 // Addressability error in core (signal-handling) operation.
181 // It would be good to get rid of this error kind, merge it with
182 // another one somehow.
183 struct {
184 } CoreMem;
185
186 // Use of an unaddressable memory location in a load or store.
187 struct {
188 Bool isWrite; // read or write?
189 SizeT szB; // not used for exec (jump) errors
190 Bool maybe_gcc; // True if just below %esp -- could be a gcc bug
191 AddrInfo ai;
192 } Addr;
193
194 // Jump to an unaddressable memory location.
195 struct {
196 AddrInfo ai;
197 } Jump;
198
199 // System call register input contains undefined bytes.
200 struct {
201 // Origin info
202 UInt otag; // origin tag
203 ExeContext* origin_ec; // filled in later
204 } RegParam;
205
206 // System call memory input contains undefined/unaddressable bytes
207 struct {
208 Bool isAddrErr; // Addressability or definedness error?
209 AddrInfo ai;
210 // Origin info
211 UInt otag; // origin tag
212 ExeContext* origin_ec; // filled in later
213 } MemParam;
214
215 // Problem found from a client request like CHECK_MEM_IS_ADDRESSABLE.
216 struct {
217 Bool isAddrErr; // Addressability or definedness error?
218 AddrInfo ai;
219 // Origin info
220 UInt otag; // origin tag
221 ExeContext* origin_ec; // filled in later
222 } User;
223
224 // Program tried to free() something that's not a heap block (this
225 // covers double-frees). */
226 struct {
227 AddrInfo ai;
228 } Free;
229
230 // Program allocates heap block with one function
231 // (malloc/new/new[]/custom) and deallocates with not the matching one.
232 struct {
233 AddrInfo ai;
234 } FreeMismatch;
235
236 // Call to strcpy, memcpy, etc, with overlapping blocks.
237 struct {
philippedfa54a52013-03-13 21:44:07 +0000238 Addr src; // Source block
239 Addr dst; // Destination block
240 SizeT szB; // Size in bytes; 0 if unused.
sewardj7ce71662008-05-02 10:33:15 +0000241 } Overlap;
242
243 // A memory leak.
244 struct {
245 UInt n_this_record;
246 UInt n_total_records;
njnb7a4e2e2009-05-01 00:30:43 +0000247 LossRecord* lr;
sewardj7ce71662008-05-02 10:33:15 +0000248 } Leak;
249
250 // A memory pool error.
251 struct {
252 AddrInfo ai;
253 } IllegalMempool;
254
255 } Err;
256};
257
258
259/*------------------------------------------------------------*/
260/*--- Printing errors ---*/
261/*------------------------------------------------------------*/
262
sewardj6b523cd2009-07-15 14:49:40 +0000263/* This is the "this error is due to be printed shortly; so have a
264 look at it any print any preamble you want" function. Which, in
265 Memcheck, we don't use. Hence a no-op.
266*/
267void MC_(before_pp_Error) ( Error* err ) {
268}
269
270/* Do a printf-style operation on either the XML or normal output
271 channel, depending on the setting of VG_(clo_xml).
272*/
floriandbb35842012-10-27 18:39:11 +0000273static void emit_WRK ( const HChar* format, va_list vargs )
sewardj6b523cd2009-07-15 14:49:40 +0000274{
275 if (VG_(clo_xml)) {
276 VG_(vprintf_xml)(format, vargs);
277 } else {
278 VG_(vmessage)(Vg_UserMsg, format, vargs);
279 }
280}
floriandbb35842012-10-27 18:39:11 +0000281static void emit ( const HChar* format, ... ) PRINTF_CHECK(1, 2);
282static void emit ( const HChar* format, ... )
sewardj6b523cd2009-07-15 14:49:40 +0000283{
284 va_list vargs;
285 va_start(vargs, format);
286 emit_WRK(format, vargs);
287 va_end(vargs);
288}
floriandbb35842012-10-27 18:39:11 +0000289static void emiN ( const HChar* format, ... ) /* NO FORMAT CHECK */
sewardj6b523cd2009-07-15 14:49:40 +0000290{
291 va_list vargs;
292 va_start(vargs, format);
293 emit_WRK(format, vargs);
294 va_end(vargs);
295}
296
297
sewardj7ce71662008-05-02 10:33:15 +0000298static void mc_pp_AddrInfo ( Addr a, AddrInfo* ai, Bool maybe_gcc )
299{
florian6bd9dc12012-11-23 16:17:43 +0000300 const HChar* xpre = VG_(clo_xml) ? " <auxwhat>" : " ";
301 const HChar* xpost = VG_(clo_xml) ? "</auxwhat>" : "";
sewardj7ce71662008-05-02 10:33:15 +0000302
303 switch (ai->tag) {
304 case Addr_Unknown:
305 if (maybe_gcc) {
sewardj6b523cd2009-07-15 14:49:40 +0000306 emit( "%sAddress 0x%llx is just below the stack ptr. "
307 "To suppress, use: --workaround-gcc296-bugs=yes%s\n",
308 xpre, (ULong)a, xpost );
sewardj7ce71662008-05-02 10:33:15 +0000309 } else {
sewardj6b523cd2009-07-15 14:49:40 +0000310 emit( "%sAddress 0x%llx "
311 "is not stack'd, malloc'd or (recently) free'd%s\n",
312 xpre, (ULong)a, xpost );
sewardj7ce71662008-05-02 10:33:15 +0000313 }
314 break;
315
316 case Addr_Stack:
sewardj6b523cd2009-07-15 14:49:40 +0000317 emit( "%sAddress 0x%llx is on thread %d's stack%s\n",
318 xpre, (ULong)a, ai->Addr.Stack.tid, xpost );
sewardj7ce71662008-05-02 10:33:15 +0000319 break;
320
321 case Addr_Block: {
njnc4431bf2009-01-15 21:29:24 +0000322 SizeT block_szB = ai->Addr.Block.block_szB;
323 PtrdiffT rwoffset = ai->Addr.Block.rwoffset;
324 SizeT delta;
floriana5f894c2012-10-21 03:43:20 +0000325 const HChar* relative;
sewardj7ce71662008-05-02 10:33:15 +0000326
327 if (rwoffset < 0) {
328 delta = (SizeT)(-rwoffset);
329 relative = "before";
330 } else if (rwoffset >= block_szB) {
331 delta = rwoffset - block_szB;
332 relative = "after";
333 } else {
334 delta = rwoffset;
335 relative = "inside";
336 }
sewardj6b523cd2009-07-15 14:49:40 +0000337 emit(
338 "%sAddress 0x%lx is %'lu bytes %s a %s of size %'lu %s%s\n",
sewardj7ce71662008-05-02 10:33:15 +0000339 xpre,
340 a, delta, relative, ai->Addr.Block.block_desc,
341 block_szB,
342 ai->Addr.Block.block_kind==Block_Mallocd ? "alloc'd"
343 : ai->Addr.Block.block_kind==Block_Freed ? "free'd"
344 : "client-defined",
sewardj6b523cd2009-07-15 14:49:40 +0000345 xpost
346 );
philippe8617b5b2013-01-12 19:53:08 +0000347 if (ai->Addr.Block.block_kind==Block_Mallocd) {
348 VG_(pp_ExeContext)(ai->Addr.Block.allocated_at);
349 tl_assert (ai->Addr.Block.freed_at == VG_(null_ExeContext)());
350 }
351 else if (ai->Addr.Block.block_kind==Block_Freed) {
352 VG_(pp_ExeContext)(ai->Addr.Block.freed_at);
353 if (ai->Addr.Block.allocated_at != VG_(null_ExeContext)()) {
354 emit(
355 "%s block was alloc'd at%s\n",
356 xpre,
357 xpost
358 );
359 VG_(pp_ExeContext)(ai->Addr.Block.allocated_at);
360 }
361 }
362 else {
363 // client-defined
364 VG_(pp_ExeContext)(ai->Addr.Block.allocated_at);
365 tl_assert (ai->Addr.Block.freed_at == VG_(null_ExeContext)());
366 /* Nb: cannot have a freed_at, as a freed client-defined block
367 has a Block_Freed block_kind. */
368 }
369
sewardj7ce71662008-05-02 10:33:15 +0000370 break;
371 }
372
373 case Addr_DataSym:
sewardj6b523cd2009-07-15 14:49:40 +0000374 emiN( "%sAddress 0x%llx is %llu bytes "
bartb3af9cf2011-10-06 19:08:37 +0000375 "inside data symbol \"%pS\"%s\n",
sewardj6b523cd2009-07-15 14:49:40 +0000376 xpre,
377 (ULong)a,
378 (ULong)ai->Addr.DataSym.offset,
379 ai->Addr.DataSym.name,
380 xpost );
sewardj7ce71662008-05-02 10:33:15 +0000381 break;
382
383 case Addr_Variable:
sewardj6b523cd2009-07-15 14:49:40 +0000384 /* Note, no need for XML tags here, because descr1/2 will
385 already have <auxwhat> or <xauxwhat>s on them, in XML
386 mode. */
387 if (ai->Addr.Variable.descr1)
388 emit( "%s%s\n",
389 VG_(clo_xml) ? " " : " ",
390 (HChar*)VG_(indexXA)(ai->Addr.Variable.descr1, 0) );
391 if (ai->Addr.Variable.descr2)
392 emit( "%s%s\n",
393 VG_(clo_xml) ? " " : " ",
394 (HChar*)VG_(indexXA)(ai->Addr.Variable.descr2, 0) );
sewardj7ce71662008-05-02 10:33:15 +0000395 break;
396
397 case Addr_SectKind:
bartb3af9cf2011-10-06 19:08:37 +0000398 emiN( "%sAddress 0x%llx is in the %pS segment of %pS%s\n",
sewardj6b523cd2009-07-15 14:49:40 +0000399 xpre,
400 (ULong)a,
401 VG_(pp_SectKind)(ai->Addr.SectKind.kind),
402 ai->Addr.SectKind.objname,
403 xpost );
sewardj7ce71662008-05-02 10:33:15 +0000404 break;
405
406 default:
407 VG_(tool_panic)("mc_pp_AddrInfo");
408 }
409}
410
411static const HChar* str_leak_lossmode ( Reachedness lossmode )
412{
413 const HChar *loss = "?";
414 switch (lossmode) {
415 case Unreached: loss = "definitely lost"; break;
416 case IndirectLeak: loss = "indirectly lost"; break;
njn8225cc02009-03-09 22:52:24 +0000417 case Possible: loss = "possibly lost"; break;
418 case Reachable: loss = "still reachable"; break;
sewardj7ce71662008-05-02 10:33:15 +0000419 }
420 return loss;
421}
422
423static const HChar* xml_leak_kind ( Reachedness lossmode )
424{
425 const HChar *loss = "?";
426 switch (lossmode) {
427 case Unreached: loss = "Leak_DefinitelyLost"; break;
428 case IndirectLeak: loss = "Leak_IndirectlyLost"; break;
njn8225cc02009-03-09 22:52:24 +0000429 case Possible: loss = "Leak_PossiblyLost"; break;
430 case Reachable: loss = "Leak_StillReachable"; break;
sewardj7ce71662008-05-02 10:33:15 +0000431 }
432 return loss;
433}
434
philippe2193a7c2012-12-08 17:54:16 +0000435Bool MC_(parse_leak_kinds) ( const HChar* str0, UInt* lks )
436{
437 HChar tok_str0[VG_(strlen)(str0)+1];
438 HChar* saveptr;
439 HChar* token;
440
441 Bool seen_all_kw = False;
442 Bool seen_none_kw = False;
443
444 VG_(strcpy) (tok_str0, str0);
445 *lks = 0;
446
447 for (token = VG_(strtok_r)(tok_str0, ",", &saveptr);
448 token;
449 token = VG_(strtok_r)(NULL, ",", &saveptr)) {
450 if (0 == VG_(strcmp)(token, "reachable"))
451 *lks |= R2S(Reachable);
452 else if (0 == VG_(strcmp)(token, "possible"))
453 *lks |= R2S(Possible);
454 else if (0 == VG_(strcmp)(token, "indirect"))
455 *lks |= R2S(IndirectLeak);
456 else if (0 == VG_(strcmp)(token, "definite"))
457 *lks |= R2S(Unreached);
458 else if (0 == VG_(strcmp)(token, "all"))
459 seen_all_kw = True;
460 else if (0 == VG_(strcmp)(token, "none"))
461 seen_none_kw = True;
462 else
463 return False;
464 }
465
466 if (seen_all_kw) {
467 if (seen_none_kw || *lks)
468 return False; // mixing all with either none or a specific value.
469 *lks = RallS;
470 } else if (seen_none_kw) {
471 if (seen_all_kw || *lks)
472 return False; // mixing none with either all or a specific value.
473 *lks = 0;
474 } else {
475 // seen neither all or none, we must see at least one value
476 if (*lks == 0)
477 return False;
478 }
479
480 return True;
481}
482
483static const HChar* pp_Reachedness_for_leak_kinds(Reachedness r)
484{
485 switch(r) {
486 case Reachable: return "reachable";
487 case Possible: return "possible";
488 case IndirectLeak: return "indirect";
489 case Unreached: return "definite";
490 default: tl_assert(0);
491 }
492}
493
sewardj7ce71662008-05-02 10:33:15 +0000494static void mc_pp_origin ( ExeContext* ec, UInt okind )
495{
floriana5f894c2012-10-21 03:43:20 +0000496 const HChar* src = NULL;
sewardj7ce71662008-05-02 10:33:15 +0000497 tl_assert(ec);
498
499 switch (okind) {
500 case MC_OKIND_STACK: src = " by a stack allocation"; break;
501 case MC_OKIND_HEAP: src = " by a heap allocation"; break;
502 case MC_OKIND_USER: src = " by a client request"; break;
503 case MC_OKIND_UNKNOWN: src = ""; break;
504 }
505 tl_assert(src); /* guards against invalid 'okind' */
506
507 if (VG_(clo_xml)) {
sewardj6b523cd2009-07-15 14:49:40 +0000508 emit( " <auxwhat>Uninitialised value was created%s</auxwhat>\n",
509 src);
510 VG_(pp_ExeContext)( ec );
511 } else {
512 emit( " Uninitialised value was created%s\n", src);
513 VG_(pp_ExeContext)( ec );
sewardj7ce71662008-05-02 10:33:15 +0000514 }
515}
516
floriandbb35842012-10-27 18:39:11 +0000517HChar * MC_(snprintf_delta) (HChar * buf, Int size,
518 SizeT current_val, SizeT old_val,
519 LeakCheckDeltaMode delta_mode)
sewardjc8bd1df2011-06-26 12:41:33 +0000520{
521 if (delta_mode == LCD_Any)
522 buf[0] = '\0';
523 else if (current_val >= old_val)
524 VG_(snprintf) (buf, size, " (+%'lu)", current_val - old_val);
525 else
526 VG_(snprintf) (buf, size, " (-%'lu)", old_val - current_val);
527
528 return buf;
529}
530
philippea22f59d2012-01-26 23:13:52 +0000531static void pp_LossRecord(UInt n_this_record, UInt n_total_records,
532 LossRecord* lr, Bool xml)
533{
534 // char arrays to produce the indication of increase/decrease in case
535 // of delta_mode != LCD_Any
floriandbb35842012-10-27 18:39:11 +0000536 HChar d_bytes[20];
537 HChar d_direct_bytes[20];
538 HChar d_indirect_bytes[20];
539 HChar d_num_blocks[20];
philippea22f59d2012-01-26 23:13:52 +0000540
541 MC_(snprintf_delta) (d_bytes, 20,
542 lr->szB + lr->indirect_szB,
543 lr->old_szB + lr->old_indirect_szB,
544 MC_(detect_memory_leaks_last_delta_mode));
545 MC_(snprintf_delta) (d_direct_bytes, 20,
546 lr->szB,
547 lr->old_szB,
548 MC_(detect_memory_leaks_last_delta_mode));
549 MC_(snprintf_delta) (d_indirect_bytes, 20,
550 lr->indirect_szB,
551 lr->old_indirect_szB,
552 MC_(detect_memory_leaks_last_delta_mode));
553 MC_(snprintf_delta) (d_num_blocks, 20,
554 (SizeT) lr->num_blocks,
555 (SizeT) lr->old_num_blocks,
556 MC_(detect_memory_leaks_last_delta_mode));
557
558 if (xml) {
559 emit(" <kind>%s</kind>\n", xml_leak_kind(lr->key.state));
560 if (lr->indirect_szB > 0) {
561 emit( " <xwhat>\n" );
562 emit( " <text>%'lu%s (%'lu%s direct, %'lu%s indirect) bytes "
563 "in %'u%s blocks"
564 " are %s in loss record %'u of %'u</text>\n",
565 lr->szB + lr->indirect_szB, d_bytes,
566 lr->szB, d_direct_bytes,
567 lr->indirect_szB, d_indirect_bytes,
568 lr->num_blocks, d_num_blocks,
569 str_leak_lossmode(lr->key.state),
570 n_this_record, n_total_records );
571 // Nb: don't put commas in these XML numbers
572 emit( " <leakedbytes>%lu</leakedbytes>\n",
573 lr->szB + lr->indirect_szB );
574 emit( " <leakedblocks>%u</leakedblocks>\n", lr->num_blocks );
575 emit( " </xwhat>\n" );
576 } else {
577 emit( " <xwhat>\n" );
578 emit( " <text>%'lu%s bytes in %'u%s blocks"
579 " are %s in loss record %'u of %'u</text>\n",
580 lr->szB, d_direct_bytes,
581 lr->num_blocks, d_num_blocks,
582 str_leak_lossmode(lr->key.state),
583 n_this_record, n_total_records );
584 emit( " <leakedbytes>%ld</leakedbytes>\n", lr->szB);
585 emit( " <leakedblocks>%d</leakedblocks>\n", lr->num_blocks);
586 emit( " </xwhat>\n" );
587 }
588 VG_(pp_ExeContext)(lr->key.allocated_at);
589 } else { /* ! if (xml) */
590 if (lr->indirect_szB > 0) {
591 emit(
592 "%'lu%s (%'lu%s direct, %'lu%s indirect) bytes in %'u%s blocks"
593 " are %s in loss record %'u of %'u\n",
594 lr->szB + lr->indirect_szB, d_bytes,
595 lr->szB, d_direct_bytes,
596 lr->indirect_szB, d_indirect_bytes,
597 lr->num_blocks, d_num_blocks,
598 str_leak_lossmode(lr->key.state),
599 n_this_record, n_total_records
600 );
601 } else {
602 emit(
603 "%'lu%s bytes in %'u%s blocks are %s in loss record %'u of %'u\n",
604 lr->szB, d_direct_bytes,
605 lr->num_blocks, d_num_blocks,
606 str_leak_lossmode(lr->key.state),
607 n_this_record, n_total_records
608 );
609 }
610 VG_(pp_ExeContext)(lr->key.allocated_at);
611 } /* if (xml) */
612}
613
614void MC_(pp_LossRecord)(UInt n_this_record, UInt n_total_records,
615 LossRecord* l)
616{
617 pp_LossRecord (n_this_record, n_total_records, l, /* xml */ False);
618}
619
sewardj7ce71662008-05-02 10:33:15 +0000620void MC_(pp_Error) ( Error* err )
621{
sewardj6b523cd2009-07-15 14:49:40 +0000622 const Bool xml = VG_(clo_xml); /* a shorthand */
sewardj7ce71662008-05-02 10:33:15 +0000623 MC_Error* extra = VG_(get_error_extra)(err);
624
625 switch (VG_(get_error_kind)(err)) {
sewardj6b523cd2009-07-15 14:49:40 +0000626 case Err_CoreMem:
sewardj7ce71662008-05-02 10:33:15 +0000627 /* What the hell *is* a CoreMemError? jrs 2005-May-18 */
628 /* As of 2006-Dec-14, it's caused by unaddressable bytes in a
629 signal handler frame. --njn */
sewardj6b523cd2009-07-15 14:49:40 +0000630 // JRS 17 May 09: None of our regtests exercise this; hence AFAIK
631 // the following code is untested. Bad.
632 if (xml) {
633 emit( " <kind>CoreMemError</kind>\n" );
bartb3af9cf2011-10-06 19:08:37 +0000634 emiN( " <what>%pS contains unaddressable byte(s)</what>\n",
sewardj6b523cd2009-07-15 14:49:40 +0000635 VG_(get_error_string)(err));
636 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
637 } else {
638 emit( "%s contains unaddressable byte(s)\n",
639 VG_(get_error_string)(err));
640 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
641 }
sewardj7ce71662008-05-02 10:33:15 +0000642 break;
sewardj7ce71662008-05-02 10:33:15 +0000643
644 case Err_Value:
645 MC_(any_value_errors) = True;
sewardj6b523cd2009-07-15 14:49:40 +0000646 if (xml) {
647 emit( " <kind>UninitValue</kind>\n" );
648 emit( " <what>Use of uninitialised value of size %ld</what>\n",
649 extra->Err.Value.szB );
650 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
651 if (extra->Err.Value.origin_ec)
652 mc_pp_origin( extra->Err.Value.origin_ec,
653 extra->Err.Value.otag & 3 );
sewardj7ce71662008-05-02 10:33:15 +0000654 } else {
sewardj6b523cd2009-07-15 14:49:40 +0000655 /* Could also show extra->Err.Cond.otag if debugging origin
656 tracking */
657 emit( "Use of uninitialised value of size %ld\n",
658 extra->Err.Value.szB );
659 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
660 if (extra->Err.Value.origin_ec)
661 mc_pp_origin( extra->Err.Value.origin_ec,
662 extra->Err.Value.otag & 3 );
sewardj7ce71662008-05-02 10:33:15 +0000663 }
sewardj7ce71662008-05-02 10:33:15 +0000664 break;
665
666 case Err_Cond:
667 MC_(any_value_errors) = True;
sewardj6b523cd2009-07-15 14:49:40 +0000668 if (xml) {
669 emit( " <kind>UninitCondition</kind>\n" );
670 emit( " <what>Conditional jump or move depends"
671 " on uninitialised value(s)</what>\n" );
672 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
673 if (extra->Err.Cond.origin_ec)
674 mc_pp_origin( extra->Err.Cond.origin_ec,
675 extra->Err.Cond.otag & 3 );
sewardj7ce71662008-05-02 10:33:15 +0000676 } else {
sewardj6b523cd2009-07-15 14:49:40 +0000677 /* Could also show extra->Err.Cond.otag if debugging origin
678 tracking */
679 emit( "Conditional jump or move depends"
680 " on uninitialised value(s)\n" );
681 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
682 if (extra->Err.Cond.origin_ec)
683 mc_pp_origin( extra->Err.Cond.origin_ec,
684 extra->Err.Cond.otag & 3 );
sewardj7ce71662008-05-02 10:33:15 +0000685 }
sewardj7ce71662008-05-02 10:33:15 +0000686 break;
687
688 case Err_RegParam:
689 MC_(any_value_errors) = True;
sewardj6b523cd2009-07-15 14:49:40 +0000690 if (xml) {
691 emit( " <kind>SyscallParam</kind>\n" );
bartb3af9cf2011-10-06 19:08:37 +0000692 emiN( " <what>Syscall param %pS contains "
sewardj6b523cd2009-07-15 14:49:40 +0000693 "uninitialised byte(s)</what>\n",
694 VG_(get_error_string)(err) );
695 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
696 if (extra->Err.RegParam.origin_ec)
697 mc_pp_origin( extra->Err.RegParam.origin_ec,
698 extra->Err.RegParam.otag & 3 );
699 } else {
700 emit( "Syscall param %s contains uninitialised byte(s)\n",
701 VG_(get_error_string)(err) );
702 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
703 if (extra->Err.RegParam.origin_ec)
704 mc_pp_origin( extra->Err.RegParam.origin_ec,
705 extra->Err.RegParam.otag & 3 );
706 }
sewardj7ce71662008-05-02 10:33:15 +0000707 break;
708
709 case Err_MemParam:
710 if (!extra->Err.MemParam.isAddrErr)
711 MC_(any_value_errors) = True;
sewardj6b523cd2009-07-15 14:49:40 +0000712 if (xml) {
713 emit( " <kind>SyscallParam</kind>\n" );
bartb3af9cf2011-10-06 19:08:37 +0000714 emiN( " <what>Syscall param %pS points to %s byte(s)</what>\n",
sewardj6b523cd2009-07-15 14:49:40 +0000715 VG_(get_error_string)(err),
716 extra->Err.MemParam.isAddrErr
717 ? "unaddressable" : "uninitialised" );
718 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
719 mc_pp_AddrInfo(VG_(get_error_address)(err),
720 &extra->Err.MemParam.ai, False);
721 if (extra->Err.MemParam.origin_ec
722 && !extra->Err.MemParam.isAddrErr)
723 mc_pp_origin( extra->Err.MemParam.origin_ec,
724 extra->Err.MemParam.otag & 3 );
725 } else {
726 emit( "Syscall param %s points to %s byte(s)\n",
727 VG_(get_error_string)(err),
728 extra->Err.MemParam.isAddrErr
729 ? "unaddressable" : "uninitialised" );
730 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
731 mc_pp_AddrInfo(VG_(get_error_address)(err),
732 &extra->Err.MemParam.ai, False);
733 if (extra->Err.MemParam.origin_ec
734 && !extra->Err.MemParam.isAddrErr)
735 mc_pp_origin( extra->Err.MemParam.origin_ec,
736 extra->Err.MemParam.otag & 3 );
737 }
sewardj7ce71662008-05-02 10:33:15 +0000738 break;
739
740 case Err_User:
741 if (!extra->Err.User.isAddrErr)
742 MC_(any_value_errors) = True;
sewardj6b523cd2009-07-15 14:49:40 +0000743 if (xml) {
744 emit( " <kind>ClientCheck</kind>\n" );
745 emit( " <what>%s byte(s) found "
746 "during client check request</what>\n",
747 extra->Err.User.isAddrErr
748 ? "Unaddressable" : "Uninitialised" );
749 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
750 mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.User.ai,
751 False);
752 if (extra->Err.User.origin_ec && !extra->Err.User.isAddrErr)
753 mc_pp_origin( extra->Err.User.origin_ec,
754 extra->Err.User.otag & 3 );
755 } else {
756 emit( "%s byte(s) found during client check request\n",
757 extra->Err.User.isAddrErr
758 ? "Unaddressable" : "Uninitialised" );
759 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
760 mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.User.ai,
761 False);
762 if (extra->Err.User.origin_ec && !extra->Err.User.isAddrErr)
763 mc_pp_origin( extra->Err.User.origin_ec,
764 extra->Err.User.otag & 3 );
765 }
sewardj7ce71662008-05-02 10:33:15 +0000766 break;
767
768 case Err_Free:
sewardj6b523cd2009-07-15 14:49:40 +0000769 if (xml) {
770 emit( " <kind>InvalidFree</kind>\n" );
bart91347382011-03-25 20:07:25 +0000771 emit( " <what>Invalid free() / delete / delete[]"
772 " / realloc()</what>\n" );
sewardj6b523cd2009-07-15 14:49:40 +0000773 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
774 mc_pp_AddrInfo( VG_(get_error_address)(err),
775 &extra->Err.Free.ai, False );
776 } else {
bart91347382011-03-25 20:07:25 +0000777 emit( "Invalid free() / delete / delete[] / realloc()\n" );
sewardj6b523cd2009-07-15 14:49:40 +0000778 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
779 mc_pp_AddrInfo( VG_(get_error_address)(err),
780 &extra->Err.Free.ai, False );
781 }
sewardj7ce71662008-05-02 10:33:15 +0000782 break;
783
784 case Err_FreeMismatch:
sewardj6b523cd2009-07-15 14:49:40 +0000785 if (xml) {
786 emit( " <kind>MismatchedFree</kind>\n" );
787 emit( " <what>Mismatched free() / delete / delete []</what>\n" );
788 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
789 mc_pp_AddrInfo(VG_(get_error_address)(err),
790 &extra->Err.FreeMismatch.ai, False);
791 } else {
792 emit( "Mismatched free() / delete / delete []\n" );
793 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
794 mc_pp_AddrInfo(VG_(get_error_address)(err),
795 &extra->Err.FreeMismatch.ai, False);
796 }
sewardj7ce71662008-05-02 10:33:15 +0000797 break;
798
799 case Err_Addr:
sewardj6b523cd2009-07-15 14:49:40 +0000800 if (xml) {
801 emit( " <kind>Invalid%s</kind>\n",
802 extra->Err.Addr.isWrite ? "Write" : "Read" );
803 emit( " <what>Invalid %s of size %ld</what>\n",
804 extra->Err.Addr.isWrite ? "write" : "read",
805 extra->Err.Addr.szB );
806 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
807 mc_pp_AddrInfo( VG_(get_error_address)(err),
808 &extra->Err.Addr.ai,
809 extra->Err.Addr.maybe_gcc );
sewardj7ce71662008-05-02 10:33:15 +0000810 } else {
sewardj6b523cd2009-07-15 14:49:40 +0000811 emit( "Invalid %s of size %ld\n",
812 extra->Err.Addr.isWrite ? "write" : "read",
813 extra->Err.Addr.szB );
814 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
815
816 mc_pp_AddrInfo( VG_(get_error_address)(err),
817 &extra->Err.Addr.ai,
818 extra->Err.Addr.maybe_gcc );
sewardj7ce71662008-05-02 10:33:15 +0000819 }
sewardj7ce71662008-05-02 10:33:15 +0000820 break;
821
822 case Err_Jump:
sewardj6b523cd2009-07-15 14:49:40 +0000823 if (xml) {
824 emit( " <kind>InvalidJump</kind>\n" );
825 emit( " <what>Jump to the invalid address stated "
826 "on the next line</what>\n" );
827 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
828 mc_pp_AddrInfo( VG_(get_error_address)(err), &extra->Err.Jump.ai,
829 False );
830 } else {
831 emit( "Jump to the invalid address stated on the next line\n" );
832 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
833 mc_pp_AddrInfo( VG_(get_error_address)(err), &extra->Err.Jump.ai,
834 False );
835 }
sewardj7ce71662008-05-02 10:33:15 +0000836 break;
837
838 case Err_Overlap:
sewardj6b523cd2009-07-15 14:49:40 +0000839 if (xml) {
840 emit( " <kind>Overlap</kind>\n" );
841 if (extra->Err.Overlap.szB == 0) {
842 emiN( " <what>Source and destination overlap "
bartb3af9cf2011-10-06 19:08:37 +0000843 "in %pS(%#lx, %#lx)\n</what>\n",
sewardj6b523cd2009-07-15 14:49:40 +0000844 VG_(get_error_string)(err),
845 extra->Err.Overlap.dst, extra->Err.Overlap.src );
846 } else {
847 emit( " <what>Source and destination overlap "
philippedfa54a52013-03-13 21:44:07 +0000848 "in %s(%#lx, %#lx, %lu)</what>\n",
sewardj6b523cd2009-07-15 14:49:40 +0000849 VG_(get_error_string)(err),
850 extra->Err.Overlap.dst, extra->Err.Overlap.src,
851 extra->Err.Overlap.szB );
852 }
853 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
854 } else {
855 if (extra->Err.Overlap.szB == 0) {
bartb3af9cf2011-10-06 19:08:37 +0000856 emiN( "Source and destination overlap in %pS(%#lx, %#lx)\n",
sewardj6b523cd2009-07-15 14:49:40 +0000857 VG_(get_error_string)(err),
858 extra->Err.Overlap.dst, extra->Err.Overlap.src );
859 } else {
philippedfa54a52013-03-13 21:44:07 +0000860 emit( "Source and destination overlap in %s(%#lx, %#lx, %lu)\n",
sewardj6b523cd2009-07-15 14:49:40 +0000861 VG_(get_error_string)(err),
862 extra->Err.Overlap.dst, extra->Err.Overlap.src,
863 extra->Err.Overlap.szB );
864 }
865 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
866 }
sewardj7ce71662008-05-02 10:33:15 +0000867 break;
868
869 case Err_IllegalMempool:
sewardj6b523cd2009-07-15 14:49:40 +0000870 // JRS 17 May 09: None of our regtests exercise this; hence AFAIK
871 // the following code is untested. Bad.
872 if (xml) {
873 emit( " <kind>InvalidMemPool</kind>\n" );
874 emit( " <what>Illegal memory pool address</what>\n" );
875 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
876 mc_pp_AddrInfo( VG_(get_error_address)(err),
877 &extra->Err.IllegalMempool.ai, False );
878 } else {
879 emit( "Illegal memory pool address\n" );
880 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
881 mc_pp_AddrInfo( VG_(get_error_address)(err),
882 &extra->Err.IllegalMempool.ai, False );
883 }
sewardj7ce71662008-05-02 10:33:15 +0000884 break;
885
886 case Err_Leak: {
sewardj7ce71662008-05-02 10:33:15 +0000887 UInt n_this_record = extra->Err.Leak.n_this_record;
888 UInt n_total_records = extra->Err.Leak.n_total_records;
njnb7a4e2e2009-05-01 00:30:43 +0000889 LossRecord* lr = extra->Err.Leak.lr;
philippea22f59d2012-01-26 23:13:52 +0000890 pp_LossRecord (n_this_record, n_total_records, lr, xml);
sewardj7ce71662008-05-02 10:33:15 +0000891 break;
892 }
893
894 default:
895 VG_(printf)("Error:\n unknown Memcheck error code %d\n",
896 VG_(get_error_kind)(err));
897 VG_(tool_panic)("unknown error code in mc_pp_Error)");
898 }
899}
900
901/*------------------------------------------------------------*/
902/*--- Recording errors ---*/
903/*------------------------------------------------------------*/
904
905/* These many bytes below %ESP are considered addressible if we're
906 doing the --workaround-gcc296-bugs hack. */
907#define VG_GCC296_BUG_STACK_SLOP 1024
908
909/* Is this address within some small distance below %ESP? Used only
910 for the --workaround-gcc296-bugs kludge. */
911static Bool is_just_below_ESP( Addr esp, Addr aa )
912{
sewardj7d751b22010-07-21 12:46:44 +0000913 esp -= VG_STACK_REDZONE_SZB;
sewardj7ce71662008-05-02 10:33:15 +0000914 if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
915 return True;
916 else
917 return False;
918}
919
920/* --- Called from generated and non-generated code --- */
921
922void MC_(record_address_error) ( ThreadId tid, Addr a, Int szB,
923 Bool isWrite )
924{
925 MC_Error extra;
926 Bool just_below_esp;
927
928 if (MC_(in_ignored_range)(a))
929 return;
930
sewardj3b290482011-05-06 21:02:55 +0000931 if (VG_(is_watched)( (isWrite ? write_watchpoint : read_watchpoint), a, szB))
932 return;
933
sewardj7ce71662008-05-02 10:33:15 +0000934 just_below_esp = is_just_below_ESP( VG_(get_SP)(tid), a );
935
936 /* If this is caused by an access immediately below %ESP, and the
937 user asks nicely, we just ignore it. */
938 if (MC_(clo_workaround_gcc296_bugs) && just_below_esp)
939 return;
940
941 extra.Err.Addr.isWrite = isWrite;
942 extra.Err.Addr.szB = szB;
943 extra.Err.Addr.maybe_gcc = just_below_esp;
944 extra.Err.Addr.ai.tag = Addr_Undescribed;
945 VG_(maybe_record_error)( tid, Err_Addr, a, /*s*/NULL, &extra );
946}
947
948void MC_(record_value_error) ( ThreadId tid, Int szB, UInt otag )
949{
950 MC_Error extra;
951 tl_assert( MC_(clo_mc_level) >= 2 );
952 if (otag > 0)
953 tl_assert( MC_(clo_mc_level) == 3 );
954 extra.Err.Value.szB = szB;
955 extra.Err.Value.otag = otag;
956 extra.Err.Value.origin_ec = NULL; /* Filled in later */
957 VG_(maybe_record_error)( tid, Err_Value, /*addr*/0, /*s*/NULL, &extra );
958}
959
960void MC_(record_cond_error) ( ThreadId tid, UInt otag )
961{
962 MC_Error extra;
963 tl_assert( MC_(clo_mc_level) >= 2 );
964 if (otag > 0)
965 tl_assert( MC_(clo_mc_level) == 3 );
966 extra.Err.Cond.otag = otag;
967 extra.Err.Cond.origin_ec = NULL; /* Filled in later */
968 VG_(maybe_record_error)( tid, Err_Cond, /*addr*/0, /*s*/NULL, &extra );
969}
970
971/* --- Called from non-generated code --- */
972
njn1dcee092009-02-24 03:07:37 +0000973/* This is for memory errors in signal-related memory. */
floriane543f302012-10-21 19:43:43 +0000974void MC_(record_core_mem_error) ( ThreadId tid, const HChar* msg )
sewardj7ce71662008-05-02 10:33:15 +0000975{
976 VG_(maybe_record_error)( tid, Err_CoreMem, /*addr*/0, msg, /*extra*/NULL );
977}
978
floriane543f302012-10-21 19:43:43 +0000979void MC_(record_regparam_error) ( ThreadId tid, const HChar* msg, UInt otag )
sewardj7ce71662008-05-02 10:33:15 +0000980{
981 MC_Error extra;
982 tl_assert(VG_INVALID_THREADID != tid);
983 if (otag > 0)
984 tl_assert( MC_(clo_mc_level) == 3 );
985 extra.Err.RegParam.otag = otag;
986 extra.Err.RegParam.origin_ec = NULL; /* Filled in later */
987 VG_(maybe_record_error)( tid, Err_RegParam, /*addr*/0, msg, &extra );
988}
989
990void MC_(record_memparam_error) ( ThreadId tid, Addr a,
floriane543f302012-10-21 19:43:43 +0000991 Bool isAddrErr, const HChar* msg, UInt otag )
sewardj7ce71662008-05-02 10:33:15 +0000992{
993 MC_Error extra;
994 tl_assert(VG_INVALID_THREADID != tid);
995 if (!isAddrErr)
996 tl_assert( MC_(clo_mc_level) >= 2 );
997 if (otag != 0) {
998 tl_assert( MC_(clo_mc_level) == 3 );
999 tl_assert( !isAddrErr );
1000 }
1001 extra.Err.MemParam.isAddrErr = isAddrErr;
1002 extra.Err.MemParam.ai.tag = Addr_Undescribed;
1003 extra.Err.MemParam.otag = otag;
1004 extra.Err.MemParam.origin_ec = NULL; /* Filled in later */
1005 VG_(maybe_record_error)( tid, Err_MemParam, a, msg, &extra );
1006}
1007
1008void MC_(record_jump_error) ( ThreadId tid, Addr a )
1009{
1010 MC_Error extra;
1011 tl_assert(VG_INVALID_THREADID != tid);
1012 extra.Err.Jump.ai.tag = Addr_Undescribed;
1013 VG_(maybe_record_error)( tid, Err_Jump, a, /*s*/NULL, &extra );
1014}
1015
1016void MC_(record_free_error) ( ThreadId tid, Addr a )
1017{
1018 MC_Error extra;
1019 tl_assert(VG_INVALID_THREADID != tid);
1020 extra.Err.Free.ai.tag = Addr_Undescribed;
1021 VG_(maybe_record_error)( tid, Err_Free, a, /*s*/NULL, &extra );
1022}
1023
1024void MC_(record_freemismatch_error) ( ThreadId tid, MC_Chunk* mc )
1025{
1026 MC_Error extra;
1027 AddrInfo* ai = &extra.Err.FreeMismatch.ai;
1028 tl_assert(VG_INVALID_THREADID != tid);
1029 ai->tag = Addr_Block;
1030 ai->Addr.Block.block_kind = Block_Mallocd; // Nb: Not 'Block_Freed'
1031 ai->Addr.Block.block_desc = "block";
1032 ai->Addr.Block.block_szB = mc->szB;
1033 ai->Addr.Block.rwoffset = 0;
philippe8617b5b2013-01-12 19:53:08 +00001034 ai->Addr.Block.allocated_at = MC_(allocated_at) (mc);
1035 ai->Addr.Block.freed_at = MC_(freed_at) (mc);
sewardj7ce71662008-05-02 10:33:15 +00001036 VG_(maybe_record_error)( tid, Err_FreeMismatch, mc->data, /*s*/NULL,
1037 &extra );
1038}
1039
1040void MC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )
1041{
1042 MC_Error extra;
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 );
1046}
1047
floriane543f302012-10-21 19:43:43 +00001048void MC_(record_overlap_error) ( ThreadId tid, const HChar* function,
sewardj7ce71662008-05-02 10:33:15 +00001049 Addr src, Addr dst, SizeT szB )
1050{
1051 MC_Error extra;
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 );
1058}
1059
1060Bool MC_(record_leak_error) ( ThreadId tid, UInt n_this_record,
njnb7a4e2e2009-05-01 00:30:43 +00001061 UInt n_total_records, LossRecord* lr,
njn18afe5d2009-08-10 08:25:39 +00001062 Bool print_record, Bool count_error )
sewardj7ce71662008-05-02 10:33:15 +00001063{
1064 MC_Error extra;
1065 extra.Err.Leak.n_this_record = n_this_record;
1066 extra.Err.Leak.n_total_records = n_total_records;
njnb7a4e2e2009-05-01 00:30:43 +00001067 extra.Err.Leak.lr = lr;
sewardj7ce71662008-05-02 10:33:15 +00001068 return
1069 VG_(unique_error) ( tid, Err_Leak, /*Addr*/0, /*s*/NULL, &extra,
njn29a5c012009-05-06 06:15:55 +00001070 lr->key.allocated_at, print_record,
njn18afe5d2009-08-10 08:25:39 +00001071 /*allow_GDB_attach*/False, count_error );
sewardj7ce71662008-05-02 10:33:15 +00001072}
1073
1074void MC_(record_user_error) ( ThreadId tid, Addr a,
1075 Bool isAddrErr, UInt otag )
1076{
1077 MC_Error extra;
1078 if (otag != 0) {
1079 tl_assert(!isAddrErr);
1080 tl_assert( MC_(clo_mc_level) == 3 );
1081 }
1082 if (!isAddrErr) {
1083 tl_assert( MC_(clo_mc_level) >= 2 );
1084 }
1085 tl_assert(VG_INVALID_THREADID != tid);
1086 extra.Err.User.isAddrErr = isAddrErr;
1087 extra.Err.User.ai.tag = Addr_Undescribed;
1088 extra.Err.User.otag = otag;
1089 extra.Err.User.origin_ec = NULL; /* Filled in later */
1090 VG_(maybe_record_error)( tid, Err_User, a, /*s*/NULL, &extra );
1091}
1092
1093/*------------------------------------------------------------*/
1094/*--- Other error operations ---*/
1095/*------------------------------------------------------------*/
1096
1097/* Compare error contexts, to detect duplicates. Note that if they
1098 are otherwise the same, the faulting addrs and associated rwoffsets
1099 are allowed to be different. */
1100Bool MC_(eq_Error) ( VgRes res, Error* e1, Error* e2 )
1101{
1102 MC_Error* extra1 = VG_(get_error_extra)(e1);
1103 MC_Error* extra2 = VG_(get_error_extra)(e2);
1104
1105 /* Guaranteed by calling function */
1106 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
1107
1108 switch (VG_(get_error_kind)(e1)) {
1109 case Err_CoreMem: {
floriane543f302012-10-21 19:43:43 +00001110 const HChar *e1s, *e2s;
sewardj7ce71662008-05-02 10:33:15 +00001111 e1s = VG_(get_error_string)(e1);
1112 e2s = VG_(get_error_string)(e2);
1113 if (e1s == e2s) return True;
1114 if (VG_STREQ(e1s, e2s)) return True;
1115 return False;
1116 }
1117
1118 case Err_RegParam:
1119 return VG_STREQ(VG_(get_error_string)(e1), VG_(get_error_string)(e2));
1120
1121 // Perhaps we should also check the addrinfo.akinds for equality.
1122 // That would result in more error reports, but only in cases where
1123 // a register contains uninitialised bytes and points to memory
1124 // containing uninitialised bytes. Currently, the 2nd of those to be
1125 // detected won't be reported. That is (nearly?) always the memory
1126 // error, which is good.
1127 case Err_MemParam:
1128 if (!VG_STREQ(VG_(get_error_string)(e1),
1129 VG_(get_error_string)(e2))) return False;
1130 // fall through
1131 case Err_User:
1132 return ( extra1->Err.User.isAddrErr == extra2->Err.User.isAddrErr
1133 ? True : False );
1134
1135 case Err_Free:
1136 case Err_FreeMismatch:
1137 case Err_Jump:
1138 case Err_IllegalMempool:
1139 case Err_Overlap:
1140 case Err_Cond:
1141 return True;
1142
1143 case Err_Addr:
1144 return ( extra1->Err.Addr.szB == extra2->Err.Addr.szB
1145 ? True : False );
1146
1147 case Err_Value:
1148 return ( extra1->Err.Value.szB == extra2->Err.Value.szB
1149 ? True : False );
1150
1151 case Err_Leak:
1152 VG_(tool_panic)("Shouldn't get Err_Leak in mc_eq_Error,\n"
1153 "since it's handled with VG_(unique_error)()!");
1154
1155 default:
1156 VG_(printf)("Error:\n unknown error code %d\n",
1157 VG_(get_error_kind)(e1));
1158 VG_(tool_panic)("unknown error code in mc_eq_Error");
1159 }
1160}
1161
sewardj62b91042011-01-23 20:45:53 +00001162/* Functions used when searching MC_Chunk lists */
1163static
1164Bool addr_is_in_MC_Chunk_default_REDZONE_SZB(MC_Chunk* mc, Addr a)
sewardj7ce71662008-05-02 10:33:15 +00001165{
sewardj7ce71662008-05-02 10:33:15 +00001166 return VG_(addr_is_in_block)( a, mc->data, mc->szB,
philipped99c26a2012-07-31 22:17:28 +00001167 MC_(Malloc_Redzone_SzB) );
sewardj7ce71662008-05-02 10:33:15 +00001168}
sewardj62b91042011-01-23 20:45:53 +00001169static
1170Bool addr_is_in_MC_Chunk_with_REDZONE_SZB(MC_Chunk* mc, Addr a, SizeT rzB)
1171{
1172 return VG_(addr_is_in_block)( a, mc->data, mc->szB,
1173 rzB );
1174}
sewardj7ce71662008-05-02 10:33:15 +00001175
sewardj62b91042011-01-23 20:45:53 +00001176// Forward declarations
sewardj7ce71662008-05-02 10:33:15 +00001177static Bool client_block_maybe_describe( Addr a, AddrInfo* ai );
sewardj62b91042011-01-23 20:45:53 +00001178static Bool mempool_block_maybe_describe( Addr a, AddrInfo* ai );
sewardj7ce71662008-05-02 10:33:15 +00001179
1180
1181/* Describe an address as best you can, for error messages,
1182 putting the result in ai. */
1183static void describe_addr ( Addr a, /*OUT*/AddrInfo* ai )
1184{
1185 MC_Chunk* mc;
1186 ThreadId tid;
1187 Addr stack_min, stack_max;
1188 VgSectKind sect;
1189
1190 tl_assert(Addr_Undescribed == ai->tag);
1191
sewardj62b91042011-01-23 20:45:53 +00001192 /* -- Perhaps it's a user-named block? -- */
sewardj7ce71662008-05-02 10:33:15 +00001193 if (client_block_maybe_describe( a, ai )) {
1194 return;
1195 }
sewardj62b91042011-01-23 20:45:53 +00001196 /* -- Perhaps it's in mempool block? -- */
1197 if (mempool_block_maybe_describe( a, ai )) {
1198 return;
1199 }
philippe11cc9ce2012-03-11 17:59:00 +00001200 /* Blocks allocated by memcheck malloc functions are either
1201 on the recently freed list or on the malloc-ed list.
1202 Custom blocks can be on both : a recently freed block might
1203 have been just re-allocated.
1204 So, first search the malloc-ed block, as the most recent
1205 block is the probable cause of error.
1206 We however detect and report that this is a recently re-allocated
1207 block. */
1208 /* -- Search for a currently malloc'd block which might bracket it. -- */
1209 VG_(HT_ResetIter)(MC_(malloc_list));
1210 while ( (mc = VG_(HT_Next)(MC_(malloc_list))) ) {
1211 if (addr_is_in_MC_Chunk_default_REDZONE_SZB(mc, a)) {
1212 ai->tag = Addr_Block;
1213 ai->Addr.Block.block_kind = Block_Mallocd;
1214 if (MC_(get_freed_block_bracketting)( a ))
1215 ai->Addr.Block.block_desc = "recently re-allocated block";
1216 else
1217 ai->Addr.Block.block_desc = "block";
1218 ai->Addr.Block.block_szB = mc->szB;
1219 ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
philippe8617b5b2013-01-12 19:53:08 +00001220 ai->Addr.Block.allocated_at = MC_(allocated_at)(mc);
1221 ai->Addr.Block.freed_at = MC_(freed_at)(mc);
philippe11cc9ce2012-03-11 17:59:00 +00001222 return;
1223 }
1224 }
sewardj6b523cd2009-07-15 14:49:40 +00001225 /* -- Search for a recently freed block which might bracket it. -- */
sewardj403d8aa2011-10-22 19:48:57 +00001226 mc = MC_(get_freed_block_bracketting)( a );
1227 if (mc) {
1228 ai->tag = Addr_Block;
1229 ai->Addr.Block.block_kind = Block_Freed;
1230 ai->Addr.Block.block_desc = "block";
1231 ai->Addr.Block.block_szB = mc->szB;
1232 ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
philippe8617b5b2013-01-12 19:53:08 +00001233 ai->Addr.Block.allocated_at = MC_(allocated_at)(mc);
1234 ai->Addr.Block.freed_at = MC_(freed_at)(mc);
sewardj403d8aa2011-10-22 19:48:57 +00001235 return;
sewardj7ce71662008-05-02 10:33:15 +00001236 }
sewardj6b523cd2009-07-15 14:49:40 +00001237 /* -- Perhaps the variable type/location data describes it? -- */
1238 ai->Addr.Variable.descr1
1239 = VG_(newXA)( VG_(malloc), "mc.da.descr1",
1240 VG_(free), sizeof(HChar) );
1241 ai->Addr.Variable.descr2
1242 = VG_(newXA)( VG_(malloc), "mc.da.descr2",
1243 VG_(free), sizeof(HChar) );
1244
1245 (void) VG_(get_data_description)( ai->Addr.Variable.descr1,
1246 ai->Addr.Variable.descr2, a );
1247 /* If there's nothing in descr1/2, free them. Why is it safe to to
1248 VG_(indexXA) at zero here? Because VG_(get_data_description)
1249 guarantees to zero terminate descr1/2 regardless of the outcome
1250 of the call. So there's always at least one element in each XA
1251 after the call.
1252 */
1253 if (0 == VG_(strlen)( VG_(indexXA)( ai->Addr.Variable.descr1, 0 ))) {
1254 VG_(deleteXA)( ai->Addr.Variable.descr1 );
1255 ai->Addr.Variable.descr1 = NULL;
1256 }
1257 if (0 == VG_(strlen)( VG_(indexXA)( ai->Addr.Variable.descr2, 0 ))) {
1258 VG_(deleteXA)( ai->Addr.Variable.descr2 );
1259 ai->Addr.Variable.descr2 = NULL;
1260 }
1261 /* Assume (assert) that VG_(get_data_description) fills in descr1
1262 before it fills in descr2 */
1263 if (ai->Addr.Variable.descr1 == NULL)
1264 tl_assert(ai->Addr.Variable.descr2 == NULL);
1265 /* So did we get lucky? */
1266 if (ai->Addr.Variable.descr1 != NULL) {
sewardj7ce71662008-05-02 10:33:15 +00001267 ai->tag = Addr_Variable;
sewardj7ce71662008-05-02 10:33:15 +00001268 return;
1269 }
sewardj6b523cd2009-07-15 14:49:40 +00001270 /* -- Have a look at the low level data symbols - perhaps it's in
1271 there. -- */
sewardj7ce71662008-05-02 10:33:15 +00001272 VG_(memset)( &ai->Addr.DataSym.name,
1273 0, sizeof(ai->Addr.DataSym.name));
1274 if (VG_(get_datasym_and_offset)(
1275 a, &ai->Addr.DataSym.name[0],
1276 sizeof(ai->Addr.DataSym.name)-1,
1277 &ai->Addr.DataSym.offset )) {
1278 ai->tag = Addr_DataSym;
1279 tl_assert( ai->Addr.DataSym.name
1280 [ sizeof(ai->Addr.DataSym.name)-1 ] == 0);
1281 return;
1282 }
sewardj6b523cd2009-07-15 14:49:40 +00001283 /* -- Perhaps it's on a thread's stack? -- */
sewardj7ce71662008-05-02 10:33:15 +00001284 VG_(thread_stack_reset_iter)(&tid);
1285 while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
1286 if (stack_min - VG_STACK_REDZONE_SZB <= a && a <= stack_max) {
1287 ai->tag = Addr_Stack;
1288 ai->Addr.Stack.tid = tid;
1289 return;
1290 }
1291 }
sewardj6b523cd2009-07-15 14:49:40 +00001292 /* -- last ditch attempt at classification -- */
sewardj7ce71662008-05-02 10:33:15 +00001293 tl_assert( sizeof(ai->Addr.SectKind.objname) > 4 );
1294 VG_(memset)( &ai->Addr.SectKind.objname,
1295 0, sizeof(ai->Addr.SectKind.objname));
1296 VG_(strcpy)( ai->Addr.SectKind.objname, "???" );
sewardje3f1e592009-07-31 09:41:29 +00001297 sect = VG_(DebugInfo_sect_kind)( &ai->Addr.SectKind.objname[0],
1298 sizeof(ai->Addr.SectKind.objname)-1, a);
sewardj7ce71662008-05-02 10:33:15 +00001299 if (sect != Vg_SectUnknown) {
1300 ai->tag = Addr_SectKind;
1301 ai->Addr.SectKind.kind = sect;
1302 tl_assert( ai->Addr.SectKind.objname
1303 [ sizeof(ai->Addr.SectKind.objname)-1 ] == 0);
1304 return;
1305 }
sewardj6b523cd2009-07-15 14:49:40 +00001306 /* -- Clueless ... -- */
sewardj7ce71662008-05-02 10:33:15 +00001307 ai->tag = Addr_Unknown;
1308 return;
1309}
1310
sewardj3b290482011-05-06 21:02:55 +00001311void MC_(pp_describe_addr) ( Addr a )
1312{
1313 AddrInfo ai;
1314
1315 ai.tag = Addr_Undescribed;
1316 describe_addr (a, &ai);
1317 mc_pp_AddrInfo (a, &ai, /* maybe_gcc */ False);
1318}
1319
sewardj7ce71662008-05-02 10:33:15 +00001320/* Fill in *origin_ec as specified by otag, or NULL it out if otag
1321 does not refer to a known origin. */
1322static void update_origin ( /*OUT*/ExeContext** origin_ec,
1323 UInt otag )
1324{
1325 UInt ecu = otag & ~3;
1326 *origin_ec = NULL;
1327 if (VG_(is_plausible_ECU)(ecu)) {
1328 *origin_ec = VG_(get_ExeContext_from_ECU)( ecu );
1329 }
1330}
1331
1332/* Updates the copy with address info if necessary (but not for all errors). */
1333UInt MC_(update_Error_extra)( Error* err )
1334{
1335 MC_Error* extra = VG_(get_error_extra)(err);
1336
1337 switch (VG_(get_error_kind)(err)) {
1338 // These ones don't have addresses associated with them, and so don't
1339 // need any updating.
1340 case Err_CoreMem:
1341 //case Err_Value:
1342 //case Err_Cond:
1343 case Err_Overlap:
1344 // For Err_Leaks the returned size does not matter -- they are always
1345 // shown with VG_(unique_error)() so they 'extra' not copied. But
1346 // we make it consistent with the others.
1347 case Err_Leak:
1348 return sizeof(MC_Error);
1349
1350 // For value errors, get the ExeContext corresponding to the
1351 // origin tag. Note that it is a kludge to assume that
1352 // a length-1 trace indicates a stack origin. FIXME.
1353 case Err_Value:
1354 update_origin( &extra->Err.Value.origin_ec,
1355 extra->Err.Value.otag );
1356 return sizeof(MC_Error);
1357 case Err_Cond:
1358 update_origin( &extra->Err.Cond.origin_ec,
1359 extra->Err.Cond.otag );
1360 return sizeof(MC_Error);
1361 case Err_RegParam:
1362 update_origin( &extra->Err.RegParam.origin_ec,
1363 extra->Err.RegParam.otag );
1364 return sizeof(MC_Error);
1365
1366 // These ones always involve a memory address.
1367 case Err_Addr:
1368 describe_addr ( VG_(get_error_address)(err),
1369 &extra->Err.Addr.ai );
1370 return sizeof(MC_Error);
1371 case Err_MemParam:
1372 describe_addr ( VG_(get_error_address)(err),
1373 &extra->Err.MemParam.ai );
1374 update_origin( &extra->Err.MemParam.origin_ec,
1375 extra->Err.MemParam.otag );
1376 return sizeof(MC_Error);
1377 case Err_Jump:
1378 describe_addr ( VG_(get_error_address)(err),
1379 &extra->Err.Jump.ai );
1380 return sizeof(MC_Error);
1381 case Err_User:
1382 describe_addr ( VG_(get_error_address)(err),
1383 &extra->Err.User.ai );
1384 update_origin( &extra->Err.User.origin_ec,
1385 extra->Err.User.otag );
1386 return sizeof(MC_Error);
1387 case Err_Free:
1388 describe_addr ( VG_(get_error_address)(err),
1389 &extra->Err.Free.ai );
1390 return sizeof(MC_Error);
1391 case Err_IllegalMempool:
1392 describe_addr ( VG_(get_error_address)(err),
1393 &extra->Err.IllegalMempool.ai );
1394 return sizeof(MC_Error);
1395
1396 // Err_FreeMismatches have already had their address described; this is
1397 // possible because we have the MC_Chunk on hand when the error is
1398 // detected. However, the address may be part of a user block, and if so
1399 // we override the pre-determined description with a user block one.
1400 case Err_FreeMismatch: {
1401 tl_assert(extra && Block_Mallocd ==
1402 extra->Err.FreeMismatch.ai.Addr.Block.block_kind);
1403 (void)client_block_maybe_describe( VG_(get_error_address)(err),
1404 &extra->Err.FreeMismatch.ai );
1405 return sizeof(MC_Error);
1406 }
1407
1408 default: VG_(tool_panic)("mc_update_extra: bad errkind");
1409 }
1410}
1411
sewardj62b91042011-01-23 20:45:53 +00001412
sewardj7ce71662008-05-02 10:33:15 +00001413static Bool client_block_maybe_describe( Addr a,
1414 /*OUT*/AddrInfo* ai )
1415{
sewardj56adc352008-05-02 11:25:17 +00001416 UWord i;
sewardj7ce71662008-05-02 10:33:15 +00001417 CGenBlock* cgbs = NULL;
1418 UWord cgb_used = 0;
sewardj56adc352008-05-02 11:25:17 +00001419
sewardj7ce71662008-05-02 10:33:15 +00001420 MC_(get_ClientBlock_array)( &cgbs, &cgb_used );
1421 if (cgbs == NULL)
1422 tl_assert(cgb_used == 0);
1423
1424 /* Perhaps it's a general block ? */
1425 for (i = 0; i < cgb_used; i++) {
1426 if (cgbs[i].start == 0 && cgbs[i].size == 0)
1427 continue;
1428 // Use zero as the redzone for client blocks.
1429 if (VG_(addr_is_in_block)(a, cgbs[i].start, cgbs[i].size, 0)) {
sewardj7ce71662008-05-02 10:33:15 +00001430 ai->tag = Addr_Block;
1431 ai->Addr.Block.block_kind = Block_UserG;
1432 ai->Addr.Block.block_desc = cgbs[i].desc;
1433 ai->Addr.Block.block_szB = cgbs[i].size;
sewardj56adc352008-05-02 11:25:17 +00001434 ai->Addr.Block.rwoffset = (Word)(a) - (Word)(cgbs[i].start);
philippe8617b5b2013-01-12 19:53:08 +00001435 ai->Addr.Block.allocated_at = cgbs[i].where;
1436 ai->Addr.Block.freed_at = VG_(null_ExeContext)();;
sewardj7ce71662008-05-02 10:33:15 +00001437 return True;
1438 }
1439 }
1440 return False;
1441}
1442
1443
sewardj62b91042011-01-23 20:45:53 +00001444static Bool mempool_block_maybe_describe( Addr a,
1445 /*OUT*/AddrInfo* ai )
1446{
1447 MC_Mempool* mp;
1448 tl_assert( MC_(mempool_list) );
1449
1450 VG_(HT_ResetIter)( MC_(mempool_list) );
1451 while ( (mp = VG_(HT_Next)(MC_(mempool_list))) ) {
1452 if (mp->chunks != NULL) {
1453 MC_Chunk* mc;
1454 VG_(HT_ResetIter)(mp->chunks);
1455 while ( (mc = VG_(HT_Next)(mp->chunks)) ) {
1456 if (addr_is_in_MC_Chunk_with_REDZONE_SZB(mc, a, mp->rzB)) {
1457 ai->tag = Addr_Block;
1458 ai->Addr.Block.block_kind = Block_MempoolChunk;
1459 ai->Addr.Block.block_desc = "block";
1460 ai->Addr.Block.block_szB = mc->szB;
1461 ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
philippe8617b5b2013-01-12 19:53:08 +00001462 ai->Addr.Block.allocated_at = MC_(allocated_at)(mc);
1463 ai->Addr.Block.freed_at = MC_(freed_at)(mc);
sewardj62b91042011-01-23 20:45:53 +00001464 return True;
1465 }
1466 }
1467 }
1468 }
1469 return False;
1470}
1471
1472
sewardj7ce71662008-05-02 10:33:15 +00001473/*------------------------------------------------------------*/
1474/*--- Suppressions ---*/
1475/*------------------------------------------------------------*/
1476
1477typedef
1478 enum {
1479 ParamSupp, // Bad syscall params
1480 UserSupp, // Errors arising from client-request checks
1481 CoreMemSupp, // Memory errors in core (pthread ops, signal handling)
1482
1483 // Undefined value errors of given size
1484 Value1Supp, Value2Supp, Value4Supp, Value8Supp, Value16Supp,
1485
1486 // Undefined value error in conditional.
1487 CondSupp,
1488
1489 // Unaddressable read/write attempt at given size
1490 Addr1Supp, Addr2Supp, Addr4Supp, Addr8Supp, Addr16Supp,
1491
1492 JumpSupp, // Jump to unaddressable target
1493 FreeSupp, // Invalid or mismatching free
1494 OverlapSupp, // Overlapping blocks in memcpy(), strcpy(), etc
1495 LeakSupp, // Something to be suppressed in a leak check.
1496 MempoolSupp, // Memory pool suppression.
1497 }
1498 MC_SuppKind;
1499
florian19f91bb2012-11-10 22:29:54 +00001500Bool MC_(is_recognised_suppression) ( const HChar* name, Supp* su )
sewardj7ce71662008-05-02 10:33:15 +00001501{
1502 SuppKind skind;
1503
1504 if (VG_STREQ(name, "Param")) skind = ParamSupp;
1505 else if (VG_STREQ(name, "User")) skind = UserSupp;
1506 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
1507 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
1508 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
1509 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
1510 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
1511 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
1512 else if (VG_STREQ(name, "Jump")) skind = JumpSupp;
1513 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
1514 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
1515 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
1516 else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
1517 else if (VG_STREQ(name, "Cond")) skind = CondSupp;
1518 else if (VG_STREQ(name, "Value0")) skind = CondSupp; /* backwards compat */
1519 else if (VG_STREQ(name, "Value1")) skind = Value1Supp;
1520 else if (VG_STREQ(name, "Value2")) skind = Value2Supp;
1521 else if (VG_STREQ(name, "Value4")) skind = Value4Supp;
1522 else if (VG_STREQ(name, "Value8")) skind = Value8Supp;
1523 else if (VG_STREQ(name, "Value16")) skind = Value16Supp;
1524 else
1525 return False;
1526
1527 VG_(set_supp_kind)(su, skind);
1528 return True;
1529}
1530
philippe2193a7c2012-12-08 17:54:16 +00001531typedef struct _MC_LeakSuppExtra MC_LeakSuppExtra;
1532
1533struct _MC_LeakSuppExtra {
1534 UInt match_leak_kinds;
1535};
1536
florian19f91bb2012-11-10 22:29:54 +00001537Bool MC_(read_extra_suppression_info) ( Int fd, HChar** bufpp,
philippe362441d2013-07-22 22:00:13 +00001538 SizeT* nBufp, Int* lineno, Supp *su )
sewardj7ce71662008-05-02 10:33:15 +00001539{
1540 Bool eof;
philippe2193a7c2012-12-08 17:54:16 +00001541 Int i;
sewardj7ce71662008-05-02 10:33:15 +00001542
1543 if (VG_(get_supp_kind)(su) == ParamSupp) {
philippe362441d2013-07-22 22:00:13 +00001544 eof = VG_(get_line) ( fd, bufpp, nBufp, lineno );
sewardj7ce71662008-05-02 10:33:15 +00001545 if (eof) return False;
njn35db56c2009-07-24 07:38:29 +00001546 VG_(set_supp_string)(su, VG_(strdup)("mc.resi.1", *bufpp));
philippe2193a7c2012-12-08 17:54:16 +00001547 } else if (VG_(get_supp_kind)(su) == LeakSupp) {
1548 // We might have the optional match-leak-kinds line
1549 MC_LeakSuppExtra* lse;
1550 lse = VG_(malloc)("mc.resi.2", sizeof(MC_LeakSuppExtra));
1551 lse->match_leak_kinds = RallS;
1552 VG_(set_supp_extra)(su, lse); // By default, all kinds will match.
philippe362441d2013-07-22 22:00:13 +00001553 eof = VG_(get_line) ( fd, bufpp, nBufp, lineno );
philippe2193a7c2012-12-08 17:54:16 +00001554 if (eof) return True; // old LeakSupp style, no match-leak-kinds line.
1555 if (0 == VG_(strncmp)(*bufpp, "match-leak-kinds:", 17)) {
1556 i = 17;
1557 while ((*bufpp)[i] && VG_(isspace((*bufpp)[i])))
1558 i++;
1559 if (!MC_(parse_leak_kinds)((*bufpp)+i, &lse->match_leak_kinds)) {
1560 return False;
1561 }
1562 } else {
1563 return False; // unknown extra line.
1564 }
sewardj7ce71662008-05-02 10:33:15 +00001565 }
1566 return True;
1567}
1568
1569Bool MC_(error_matches_suppression) ( Error* err, Supp* su )
1570{
1571 Int su_szB;
1572 MC_Error* extra = VG_(get_error_extra)(err);
1573 ErrorKind ekind = VG_(get_error_kind )(err);
1574
1575 switch (VG_(get_supp_kind)(su)) {
1576 case ParamSupp:
1577 return ((ekind == Err_RegParam || ekind == Err_MemParam)
1578 && VG_STREQ(VG_(get_error_string)(err),
1579 VG_(get_supp_string)(su)));
1580
1581 case UserSupp:
1582 return (ekind == Err_User);
1583
1584 case CoreMemSupp:
1585 return (ekind == Err_CoreMem
1586 && VG_STREQ(VG_(get_error_string)(err),
1587 VG_(get_supp_string)(su)));
1588
1589 case Value1Supp: su_szB = 1; goto value_case;
1590 case Value2Supp: su_szB = 2; goto value_case;
1591 case Value4Supp: su_szB = 4; goto value_case;
1592 case Value8Supp: su_szB = 8; goto value_case;
1593 case Value16Supp:su_szB =16; goto value_case;
1594 value_case:
1595 return (ekind == Err_Value && extra->Err.Value.szB == su_szB);
1596
1597 case CondSupp:
1598 return (ekind == Err_Cond);
1599
1600 case Addr1Supp: su_szB = 1; goto addr_case;
1601 case Addr2Supp: su_szB = 2; goto addr_case;
1602 case Addr4Supp: su_szB = 4; goto addr_case;
1603 case Addr8Supp: su_szB = 8; goto addr_case;
1604 case Addr16Supp:su_szB =16; goto addr_case;
1605 addr_case:
1606 return (ekind == Err_Addr && extra->Err.Addr.szB == su_szB);
1607
1608 case JumpSupp:
1609 return (ekind == Err_Jump);
1610
1611 case FreeSupp:
1612 return (ekind == Err_Free || ekind == Err_FreeMismatch);
1613
1614 case OverlapSupp:
1615 return (ekind == Err_Overlap);
1616
1617 case LeakSupp:
philippe2193a7c2012-12-08 17:54:16 +00001618 if (ekind == Err_Leak) {
1619 MC_LeakSuppExtra* lse = (MC_LeakSuppExtra*) VG_(get_supp_extra)(su);
1620 return RiS(extra->Err.Leak.lr->key.state, lse->match_leak_kinds);
1621 } else
1622 return False;
sewardj7ce71662008-05-02 10:33:15 +00001623
1624 case MempoolSupp:
1625 return (ekind == Err_IllegalMempool);
1626
1627 default:
1628 VG_(printf)("Error:\n"
1629 " unknown suppression type %d\n",
1630 VG_(get_supp_kind)(su));
1631 VG_(tool_panic)("unknown suppression type in "
1632 "MC_(error_matches_suppression)");
1633 }
1634}
1635
floriane543f302012-10-21 19:43:43 +00001636const HChar* MC_(get_error_name) ( Error* err )
sewardj7ce71662008-05-02 10:33:15 +00001637{
1638 switch (VG_(get_error_kind)(err)) {
1639 case Err_RegParam: return "Param";
1640 case Err_MemParam: return "Param";
1641 case Err_User: return "User";
1642 case Err_FreeMismatch: return "Free";
1643 case Err_IllegalMempool: return "Mempool";
1644 case Err_Free: return "Free";
1645 case Err_Jump: return "Jump";
1646 case Err_CoreMem: return "CoreMem";
1647 case Err_Overlap: return "Overlap";
1648 case Err_Leak: return "Leak";
1649 case Err_Cond: return "Cond";
1650 case Err_Addr: {
1651 MC_Error* extra = VG_(get_error_extra)(err);
1652 switch ( extra->Err.Addr.szB ) {
1653 case 1: return "Addr1";
1654 case 2: return "Addr2";
1655 case 4: return "Addr4";
1656 case 8: return "Addr8";
1657 case 16: return "Addr16";
1658 default: VG_(tool_panic)("unexpected size for Addr");
1659 }
1660 }
1661 case Err_Value: {
1662 MC_Error* extra = VG_(get_error_extra)(err);
1663 switch ( extra->Err.Value.szB ) {
1664 case 1: return "Value1";
1665 case 2: return "Value2";
1666 case 4: return "Value4";
1667 case 8: return "Value8";
1668 case 16: return "Value16";
1669 default: VG_(tool_panic)("unexpected size for Value");
1670 }
1671 }
1672 default: VG_(tool_panic)("get_error_name: unexpected type");
1673 }
1674}
1675
sewardj588adef2009-08-15 22:41:51 +00001676Bool MC_(get_extra_suppression_info) ( Error* err,
floriandbb35842012-10-27 18:39:11 +00001677 /*OUT*/HChar* buf, Int nBuf )
sewardj7ce71662008-05-02 10:33:15 +00001678{
1679 ErrorKind ekind = VG_(get_error_kind )(err);
sewardj588adef2009-08-15 22:41:51 +00001680 tl_assert(buf);
1681 tl_assert(nBuf >= 16); // stay sane
sewardj7ce71662008-05-02 10:33:15 +00001682 if (Err_RegParam == ekind || Err_MemParam == ekind) {
floriane543f302012-10-21 19:43:43 +00001683 const HChar* errstr = VG_(get_error_string)(err);
sewardj588adef2009-08-15 22:41:51 +00001684 tl_assert(errstr);
1685 VG_(snprintf)(buf, nBuf-1, "%s", errstr);
1686 return True;
philippe2193a7c2012-12-08 17:54:16 +00001687 } else if (Err_Leak == ekind) {
1688 MC_Error* extra = VG_(get_error_extra)(err);
1689 VG_(snprintf)
1690 (buf, nBuf-1, "match-leak-kinds: %s",
1691 pp_Reachedness_for_leak_kinds(extra->Err.Leak.lr->key.state));
1692 return True;
sewardj588adef2009-08-15 22:41:51 +00001693 } else {
1694 return False;
sewardj7ce71662008-05-02 10:33:15 +00001695 }
1696}
1697
1698
1699/*--------------------------------------------------------------------*/
1700/*--- end mc_errors.c ---*/
1701/*--------------------------------------------------------------------*/