blob: 33dcc266f3dbb9e2cf986b5f60c87ecd3cd98cb2 [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
11 Copyright (C) 2000-2008 Julian Seward
12 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"
sewardj7ce71662008-05-02 10:33:15 +000033#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"
sewardj7ce71662008-05-02 10:33:15 +000040#include "pub_tool_replacemalloc.h"
41#include "pub_tool_tooliface.h"
42#include "pub_tool_threadstate.h"
sewardj7ce71662008-05-02 10:33:15 +000043#include "pub_tool_debuginfo.h" // VG_(get_dataname_and_offset)
44
45#include "mc_include.h"
sewardj7ce71662008-05-02 10:33:15 +000046
47
48/*------------------------------------------------------------*/
49/*--- Error types ---*/
50/*------------------------------------------------------------*/
51
52/* See comment in mc_include.h */
53Bool MC_(any_value_errors) = False;
54
55
56// Different kinds of blocks.
57typedef enum {
58 Block_Mallocd = 111,
59 Block_Freed,
60 Block_Mempool,
61 Block_MempoolChunk,
62 Block_UserG
63} BlockKind;
64
65/* ------------------ Addresses -------------------- */
66
67/* The classification of a faulting address. */
68typedef
69 enum {
70 Addr_Undescribed, // as-yet unclassified
71 Addr_Unknown, // classification yielded nothing useful
72 Addr_Block, // in malloc'd/free'd block
73 Addr_Stack, // on a thread's stack
74 Addr_DataSym, // in a global data sym
75 Addr_Variable, // variable described by the debug info
76 Addr_SectKind // last-ditch classification attempt
77 }
78 AddrTag;
79
80typedef
81 struct _AddrInfo
82 AddrInfo;
83
84struct _AddrInfo {
85 AddrTag tag;
86 union {
87 // As-yet unclassified.
88 struct { } Undescribed;
89
90 // On a stack.
91 struct {
92 ThreadId tid; // Which thread's stack?
93 } Stack;
94
95 // This covers heap blocks (normal and from mempools) and user-defined
96 // blocks.
97 struct {
98 BlockKind block_kind;
99 Char* block_desc; // "block", "mempool" or user-defined
100 SizeT block_szB;
njnc4431bf2009-01-15 21:29:24 +0000101 PtrdiffT rwoffset;
sewardj7ce71662008-05-02 10:33:15 +0000102 ExeContext* lastchange;
103 } Block;
104
njnc4431bf2009-01-15 21:29:24 +0000105 // In a global .data symbol. This holds the first 127 chars of
106 // the variable's name (zero terminated), plus a (memory) offset.
sewardj7ce71662008-05-02 10:33:15 +0000107 struct {
njnc4431bf2009-01-15 21:29:24 +0000108 Char name[128];
109 PtrdiffT offset;
sewardj7ce71662008-05-02 10:33:15 +0000110 } DataSym;
111
112 // Is described by Dwarf debug info. Arbitrary strings. Must
113 // be the same length.
114 struct {
115 Char descr1[96];
116 Char descr2[96];
117 } Variable;
118
119 // Could only narrow it down to be the PLT/GOT/etc of a given
120 // object. Better than nothing, perhaps.
121 struct {
122 Char objname[128];
123 VgSectKind kind;
124 } SectKind;
125
126 // Classification yielded nothing useful.
127 struct { } Unknown;
128
129 } Addr;
130};
131
132/* ------------------ Errors ----------------------- */
133
134/* What kind of error it is. */
135typedef
136 enum {
137 Err_Value,
138 Err_Cond,
139 Err_CoreMem,
140 Err_Addr,
141 Err_Jump,
142 Err_RegParam,
143 Err_MemParam,
144 Err_User,
145 Err_Free,
146 Err_FreeMismatch,
147 Err_Overlap,
148 Err_Leak,
149 Err_IllegalMempool,
150 }
151 MC_ErrorTag;
152
153
154typedef struct _MC_Error MC_Error;
155
156struct _MC_Error {
157 // Nb: we don't need the tag here, as it's stored in the Error type! Yuk.
158 //MC_ErrorTag tag;
159
160 union {
161 // Use of an undefined value:
162 // - as a pointer in a load or store
163 // - as a jump target
164 struct {
165 SizeT szB; // size of value in bytes
166 // Origin info
167 UInt otag; // origin tag
168 ExeContext* origin_ec; // filled in later
169 } Value;
170
171 // Use of an undefined value in a conditional branch or move.
172 struct {
173 // Origin info
174 UInt otag; // origin tag
175 ExeContext* origin_ec; // filled in later
176 } Cond;
177
178 // Addressability error in core (signal-handling) operation.
179 // It would be good to get rid of this error kind, merge it with
180 // another one somehow.
181 struct {
182 } CoreMem;
183
184 // Use of an unaddressable memory location in a load or store.
185 struct {
186 Bool isWrite; // read or write?
187 SizeT szB; // not used for exec (jump) errors
188 Bool maybe_gcc; // True if just below %esp -- could be a gcc bug
189 AddrInfo ai;
190 } Addr;
191
192 // Jump to an unaddressable memory location.
193 struct {
194 AddrInfo ai;
195 } Jump;
196
197 // System call register input contains undefined bytes.
198 struct {
199 // Origin info
200 UInt otag; // origin tag
201 ExeContext* origin_ec; // filled in later
202 } RegParam;
203
204 // System call memory input contains undefined/unaddressable bytes
205 struct {
206 Bool isAddrErr; // Addressability or definedness error?
207 AddrInfo ai;
208 // Origin info
209 UInt otag; // origin tag
210 ExeContext* origin_ec; // filled in later
211 } MemParam;
212
213 // Problem found from a client request like CHECK_MEM_IS_ADDRESSABLE.
214 struct {
215 Bool isAddrErr; // Addressability or definedness error?
216 AddrInfo ai;
217 // Origin info
218 UInt otag; // origin tag
219 ExeContext* origin_ec; // filled in later
220 } User;
221
222 // Program tried to free() something that's not a heap block (this
223 // covers double-frees). */
224 struct {
225 AddrInfo ai;
226 } Free;
227
228 // Program allocates heap block with one function
229 // (malloc/new/new[]/custom) and deallocates with not the matching one.
230 struct {
231 AddrInfo ai;
232 } FreeMismatch;
233
234 // Call to strcpy, memcpy, etc, with overlapping blocks.
235 struct {
236 Addr src; // Source block
237 Addr dst; // Destination block
238 Int szB; // Size in bytes; 0 if unused.
239 } Overlap;
240
241 // A memory leak.
242 struct {
243 UInt n_this_record;
244 UInt n_total_records;
245 LossRecord* lossRecord;
246 } Leak;
247
248 // A memory pool error.
249 struct {
250 AddrInfo ai;
251 } IllegalMempool;
252
253 } Err;
254};
255
256
257/*------------------------------------------------------------*/
258/*--- Printing errors ---*/
259/*------------------------------------------------------------*/
260
261static void mc_pp_AddrInfo ( Addr a, AddrInfo* ai, Bool maybe_gcc )
262{
263 HChar* xpre = VG_(clo_xml) ? " <auxwhat>" : " ";
264 HChar* xpost = VG_(clo_xml) ? "</auxwhat>" : "";
265
266 switch (ai->tag) {
267 case Addr_Unknown:
268 if (maybe_gcc) {
269 VG_(message)(Vg_UserMsg,
270 "%sAddress 0x%llx is just below the stack ptr. "
271 "To suppress, use: --workaround-gcc296-bugs=yes%s",
272 xpre, (ULong)a, xpost
273 );
274 } else {
275 VG_(message)(Vg_UserMsg,
276 "%sAddress 0x%llx "
277 "is not stack'd, malloc'd or (recently) free'd%s",
278 xpre, (ULong)a, xpost);
279 }
280 break;
281
282 case Addr_Stack:
283 VG_(message)(Vg_UserMsg,
284 "%sAddress 0x%llx is on thread %d's stack%s",
285 xpre, (ULong)a, ai->Addr.Stack.tid, xpost);
286 break;
287
288 case Addr_Block: {
njnc4431bf2009-01-15 21:29:24 +0000289 SizeT block_szB = ai->Addr.Block.block_szB;
290 PtrdiffT rwoffset = ai->Addr.Block.rwoffset;
291 SizeT delta;
292 const Char* relative;
sewardj7ce71662008-05-02 10:33:15 +0000293
294 if (rwoffset < 0) {
295 delta = (SizeT)(-rwoffset);
296 relative = "before";
297 } else if (rwoffset >= block_szB) {
298 delta = rwoffset - block_szB;
299 relative = "after";
300 } else {
301 delta = rwoffset;
302 relative = "inside";
303 }
304 VG_(message)(Vg_UserMsg,
barta0b6b2c2008-07-07 06:49:24 +0000305 "%sAddress 0x%lx is %'lu bytes %s a %s of size %'lu %s%s",
sewardj7ce71662008-05-02 10:33:15 +0000306 xpre,
307 a, delta, relative, ai->Addr.Block.block_desc,
308 block_szB,
309 ai->Addr.Block.block_kind==Block_Mallocd ? "alloc'd"
310 : ai->Addr.Block.block_kind==Block_Freed ? "free'd"
311 : "client-defined",
312 xpost);
313 VG_(pp_ExeContext)(ai->Addr.Block.lastchange);
314 break;
315 }
316
317 case Addr_DataSym:
barta0b6b2c2008-07-07 06:49:24 +0000318 VG_(message_no_f_c)(Vg_UserMsg,
319 "%sAddress 0x%llx is %llu bytes "
320 "inside data symbol \"%t\"%s",
321 xpre,
322 (ULong)a,
323 (ULong)ai->Addr.DataSym.offset,
324 ai->Addr.DataSym.name,
325 xpost);
sewardj7ce71662008-05-02 10:33:15 +0000326 break;
327
328 case Addr_Variable:
329 if (ai->Addr.Variable.descr1[0] != '\0')
330 VG_(message)(Vg_UserMsg, "%s%s%s",
331 xpre, ai->Addr.Variable.descr1, xpost);
332 if (ai->Addr.Variable.descr2[0] != '\0')
333 VG_(message)(Vg_UserMsg, "%s%s%s",
334 xpre, ai->Addr.Variable.descr2, xpost);
335 break;
336
337 case Addr_SectKind:
barta0b6b2c2008-07-07 06:49:24 +0000338 VG_(message_no_f_c)(Vg_UserMsg,
339 "%sAddress 0x%llx is in the %t segment of %t%s",
340 xpre,
341 (ULong)a,
342 VG_(pp_SectKind)(ai->Addr.SectKind.kind),
343 ai->Addr.SectKind.objname,
344 xpost);
sewardj7ce71662008-05-02 10:33:15 +0000345 break;
346
347 default:
348 VG_(tool_panic)("mc_pp_AddrInfo");
349 }
350}
351
352static const HChar* str_leak_lossmode ( Reachedness lossmode )
353{
354 const HChar *loss = "?";
355 switch (lossmode) {
356 case Unreached: loss = "definitely lost"; break;
357 case IndirectLeak: loss = "indirectly lost"; break;
358 case Interior: loss = "possibly lost"; break;
359 case Proper: loss = "still reachable"; break;
360 }
361 return loss;
362}
363
364static const HChar* xml_leak_kind ( Reachedness lossmode )
365{
366 const HChar *loss = "?";
367 switch (lossmode) {
368 case Unreached: loss = "Leak_DefinitelyLost"; break;
369 case IndirectLeak: loss = "Leak_IndirectlyLost"; break;
370 case Interior: loss = "Leak_PossiblyLost"; break;
371 case Proper: loss = "Leak_StillReachable"; break;
372 }
373 return loss;
374}
375
376static void mc_pp_msg( Char* xml_name, Error* err, const HChar* format, ... )
377{
378 HChar* xpre = VG_(clo_xml) ? " <what>" : "";
379 HChar* xpost = VG_(clo_xml) ? "</what>" : "";
380 Char buf[256];
381 va_list vargs;
382
383 if (VG_(clo_xml))
384 VG_(message)(Vg_UserMsg, " <kind>%s</kind>", xml_name);
385 // Stick xpre and xpost on the front and back of the format string.
386 VG_(snprintf)(buf, 256, "%s%s%s", xpre, format, xpost);
387 va_start(vargs, format);
388 VG_(vmessage) ( Vg_UserMsg, buf, vargs );
389 va_end(vargs);
390 VG_(pp_ExeContext)( VG_(get_error_where)(err) );
391}
392
393static void mc_pp_origin ( ExeContext* ec, UInt okind )
394{
395 HChar* src = NULL;
396 HChar* xpre = VG_(clo_xml) ? " <what>" : " ";
397 HChar* xpost = VG_(clo_xml) ? "</what>" : "";
398 tl_assert(ec);
399
400 switch (okind) {
401 case MC_OKIND_STACK: src = " by a stack allocation"; break;
402 case MC_OKIND_HEAP: src = " by a heap allocation"; break;
403 case MC_OKIND_USER: src = " by a client request"; break;
404 case MC_OKIND_UNKNOWN: src = ""; break;
405 }
406 tl_assert(src); /* guards against invalid 'okind' */
407
408 if (VG_(clo_xml)) {
409 VG_(message)(Vg_UserMsg, " <origin>");
410 }
411
412 VG_(message)(Vg_UserMsg, "%sUninitialised value was created%s%s",
413 xpre, src, xpost);
414 VG_(pp_ExeContext)( ec );
415 if (VG_(clo_xml)) {
416 VG_(message)(Vg_UserMsg, " </origin>");
417 }
418}
419
420void MC_(pp_Error) ( Error* err )
421{
422 MC_Error* extra = VG_(get_error_extra)(err);
423
424 switch (VG_(get_error_kind)(err)) {
425 case Err_CoreMem: {
426 /* What the hell *is* a CoreMemError? jrs 2005-May-18 */
427 /* As of 2006-Dec-14, it's caused by unaddressable bytes in a
428 signal handler frame. --njn */
429 mc_pp_msg("CoreMemError", err,
430 "%s contains unaddressable byte(s)",
431 VG_(get_error_string)(err));
432 break;
433 }
434
435 case Err_Value:
436 MC_(any_value_errors) = True;
437 if (1 || extra->Err.Value.otag == 0) {
438 mc_pp_msg("UninitValue", err,
439 "Use of uninitialised value of size %d",
440 extra->Err.Value.szB);
441 } else {
442 mc_pp_msg("UninitValue", err,
443 "Use of uninitialised value of size %d (otag %u)",
444 extra->Err.Value.szB, extra->Err.Value.otag);
445 }
446 if (extra->Err.Value.origin_ec)
447 mc_pp_origin( extra->Err.Value.origin_ec,
448 extra->Err.Value.otag & 3 );
449 break;
450
451 case Err_Cond:
452 MC_(any_value_errors) = True;
453 if (1 || extra->Err.Cond.otag == 0) {
454 mc_pp_msg("UninitCondition", err,
455 "Conditional jump or move depends"
456 " on uninitialised value(s)");
457 } else {
458 mc_pp_msg("UninitCondition", err,
459 "Conditional jump or move depends"
460 " on uninitialised value(s) (otag %u)",
461 extra->Err.Cond.otag);
462 }
463 if (extra->Err.Cond.origin_ec)
464 mc_pp_origin( extra->Err.Cond.origin_ec,
465 extra->Err.Cond.otag & 3 );
466 break;
467
468 case Err_RegParam:
469 MC_(any_value_errors) = True;
470 mc_pp_msg("SyscallParam", err,
471 "Syscall param %s contains uninitialised byte(s)",
472 VG_(get_error_string)(err));
473 if (extra->Err.RegParam.origin_ec)
474 mc_pp_origin( extra->Err.RegParam.origin_ec,
475 extra->Err.RegParam.otag & 3 );
476 break;
477
478 case Err_MemParam:
479 if (!extra->Err.MemParam.isAddrErr)
480 MC_(any_value_errors) = True;
481 mc_pp_msg("SyscallParam", err,
482 "Syscall param %s points to %s byte(s)",
483 VG_(get_error_string)(err),
484 ( extra->Err.MemParam.isAddrErr
485 ? "unaddressable" : "uninitialised" ));
486 mc_pp_AddrInfo(VG_(get_error_address)(err),
487 &extra->Err.MemParam.ai, False);
488 if (extra->Err.MemParam.origin_ec && !extra->Err.MemParam.isAddrErr)
489 mc_pp_origin( extra->Err.MemParam.origin_ec,
490 extra->Err.MemParam.otag & 3 );
491 break;
492
493 case Err_User:
494 if (!extra->Err.User.isAddrErr)
495 MC_(any_value_errors) = True;
496 mc_pp_msg("ClientCheck", err,
497 "%s byte(s) found during client check request",
498 ( extra->Err.User.isAddrErr
499 ? "Unaddressable" : "Uninitialised" ));
500 mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.User.ai,
501 False);
502 if (extra->Err.User.origin_ec && !extra->Err.User.isAddrErr)
503 mc_pp_origin( extra->Err.User.origin_ec,
504 extra->Err.User.otag & 3 );
505 break;
506
507 case Err_Free:
508 mc_pp_msg("InvalidFree", err,
509 "Invalid free() / delete / delete[]");
510 mc_pp_AddrInfo(VG_(get_error_address)(err),
511 &extra->Err.Free.ai, False);
512 break;
513
514 case Err_FreeMismatch:
515 mc_pp_msg("MismatchedFree", err,
516 "Mismatched free() / delete / delete []");
517 mc_pp_AddrInfo(VG_(get_error_address)(err),
518 &extra->Err.FreeMismatch.ai, False);
519 break;
520
521 case Err_Addr:
522 if (extra->Err.Addr.isWrite) {
523 mc_pp_msg("InvalidWrite", err,
524 "Invalid write of size %d",
525 extra->Err.Addr.szB);
526 } else {
527 mc_pp_msg("InvalidRead", err,
528 "Invalid read of size %d",
529 extra->Err.Addr.szB);
530 }
531 mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.Addr.ai,
532 extra->Err.Addr.maybe_gcc);
533 break;
534
535 case Err_Jump:
536 mc_pp_msg("InvalidJump", err,
537 "Jump to the invalid address stated on the next line");
538 mc_pp_AddrInfo(VG_(get_error_address)(err), &extra->Err.Jump.ai,
539 False);
540 break;
541
542 case Err_Overlap:
543 if (extra->Err.Overlap.szB == 0)
544 mc_pp_msg("Overlap", err,
545 "Source and destination overlap in %s(%p, %p)",
546 VG_(get_error_string)(err),
547 extra->Err.Overlap.dst, extra->Err.Overlap.src);
548 else
549 mc_pp_msg("Overlap", err,
550 "Source and destination overlap in %s(%p, %p, %d)",
551 VG_(get_error_string)(err),
552 extra->Err.Overlap.dst, extra->Err.Overlap.src,
553 extra->Err.Overlap.szB);
554 break;
555
556 case Err_IllegalMempool:
557 mc_pp_msg("InvalidMemPool", err,
558 "Illegal memory pool address");
559 mc_pp_AddrInfo(VG_(get_error_address)(err),
560 &extra->Err.IllegalMempool.ai, False);
561 break;
562
563 case Err_Leak: {
564 HChar* xpre = VG_(clo_xml) ? " <what>" : "";
565 HChar* xpost = VG_(clo_xml) ? "</what>" : "";
566 UInt n_this_record = extra->Err.Leak.n_this_record;
567 UInt n_total_records = extra->Err.Leak.n_total_records;
568 LossRecord* l = extra->Err.Leak.lossRecord;
569
570 if (VG_(clo_xml)) {
barta0b6b2c2008-07-07 06:49:24 +0000571 VG_(message_no_f_c)(Vg_UserMsg, " <kind>%t</kind>",
572 xml_leak_kind(l->loss_mode));
sewardj7ce71662008-05-02 10:33:15 +0000573 } else {
574 VG_(message)(Vg_UserMsg, "");
575 }
576
577 if (l->indirect_bytes) {
578 VG_(message)(Vg_UserMsg,
barta0b6b2c2008-07-07 06:49:24 +0000579 "%s%'lu (%'lu direct, %'lu indirect) bytes in %'u blocks"
580 " are %s in loss record %'u of %'u%s",
sewardj7ce71662008-05-02 10:33:15 +0000581 xpre,
582 l->total_bytes + l->indirect_bytes,
583 l->total_bytes, l->indirect_bytes, l->num_blocks,
584 str_leak_lossmode(l->loss_mode), n_this_record, n_total_records,
585 xpost
586 );
587 if (VG_(clo_xml)) {
588 // Nb: don't put commas in these XML numbers
589 VG_(message)(Vg_UserMsg, " <leakedbytes>%lu</leakedbytes>",
590 l->total_bytes + l->indirect_bytes);
591 VG_(message)(Vg_UserMsg, " <leakedblocks>%u</leakedblocks>",
592 l->num_blocks);
593 }
594 } else {
595 VG_(message)(
596 Vg_UserMsg,
barta0b6b2c2008-07-07 06:49:24 +0000597 "%s%'lu bytes in %'u blocks are %s in loss record %'u of %'u%s",
sewardj7ce71662008-05-02 10:33:15 +0000598 xpre,
599 l->total_bytes, l->num_blocks,
600 str_leak_lossmode(l->loss_mode), n_this_record, n_total_records,
601 xpost
602 );
603 if (VG_(clo_xml)) {
barta0b6b2c2008-07-07 06:49:24 +0000604 VG_(message)(Vg_UserMsg, " <leakedbytes>%ld</leakedbytes>",
sewardj7ce71662008-05-02 10:33:15 +0000605 l->total_bytes);
606 VG_(message)(Vg_UserMsg, " <leakedblocks>%d</leakedblocks>",
607 l->num_blocks);
608 }
609 }
610 VG_(pp_ExeContext)(l->allocated_at);
611 break;
612 }
613
614 default:
615 VG_(printf)("Error:\n unknown Memcheck error code %d\n",
616 VG_(get_error_kind)(err));
617 VG_(tool_panic)("unknown error code in mc_pp_Error)");
618 }
619}
620
621/*------------------------------------------------------------*/
622/*--- Recording errors ---*/
623/*------------------------------------------------------------*/
624
625/* These many bytes below %ESP are considered addressible if we're
626 doing the --workaround-gcc296-bugs hack. */
627#define VG_GCC296_BUG_STACK_SLOP 1024
628
629/* Is this address within some small distance below %ESP? Used only
630 for the --workaround-gcc296-bugs kludge. */
631static Bool is_just_below_ESP( Addr esp, Addr aa )
632{
633 if (esp > aa && (esp - aa) <= VG_GCC296_BUG_STACK_SLOP)
634 return True;
635 else
636 return False;
637}
638
639/* --- Called from generated and non-generated code --- */
640
641void MC_(record_address_error) ( ThreadId tid, Addr a, Int szB,
642 Bool isWrite )
643{
644 MC_Error extra;
645 Bool just_below_esp;
646
647 if (MC_(in_ignored_range)(a))
648 return;
649
650# if defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
651 /* AIX zero-page handling. On AIX, reads from page zero are,
652 bizarrely enough, legitimate. Writes to page zero aren't,
653 though. Since memcheck can't distinguish reads from writes, the
654 best we can do is to 'act normal' and mark the A bits in the
655 normal way as noaccess, but then hide any reads from that page
656 that get reported here. */
657 if ((!isWrite) && a >= 0 && a < 4096 && a+szB <= 4096)
658 return;
659
660 /* Appalling AIX hack. It suppresses reads done by glink
661 fragments. Getting rid of this would require figuring out
662 somehow where the referenced data areas are (and their
663 sizes). */
664 if ((!isWrite) && szB == sizeof(Word)) {
665 UInt i1, i2;
666 UInt* pc = (UInt*)VG_(get_IP)(tid);
667 if (sizeof(Word) == 4) {
668 i1 = 0x800c0000; /* lwz r0,0(r12) */
669 i2 = 0x804c0004; /* lwz r2,4(r12) */
670 } else {
671 i1 = 0xe80c0000; /* ld r0,0(r12) */
672 i2 = 0xe84c0008; /* ld r2,8(r12) */
673 }
674 if (pc[0] == i1 && pc[1] == i2) return;
675 if (pc[0] == i2 && pc[-1] == i1) return;
676 }
677# endif
678
679 just_below_esp = is_just_below_ESP( VG_(get_SP)(tid), a );
680
681 /* If this is caused by an access immediately below %ESP, and the
682 user asks nicely, we just ignore it. */
683 if (MC_(clo_workaround_gcc296_bugs) && just_below_esp)
684 return;
685
686 extra.Err.Addr.isWrite = isWrite;
687 extra.Err.Addr.szB = szB;
688 extra.Err.Addr.maybe_gcc = just_below_esp;
689 extra.Err.Addr.ai.tag = Addr_Undescribed;
690 VG_(maybe_record_error)( tid, Err_Addr, a, /*s*/NULL, &extra );
691}
692
693void MC_(record_value_error) ( ThreadId tid, Int szB, UInt otag )
694{
695 MC_Error extra;
696 tl_assert( MC_(clo_mc_level) >= 2 );
697 if (otag > 0)
698 tl_assert( MC_(clo_mc_level) == 3 );
699 extra.Err.Value.szB = szB;
700 extra.Err.Value.otag = otag;
701 extra.Err.Value.origin_ec = NULL; /* Filled in later */
702 VG_(maybe_record_error)( tid, Err_Value, /*addr*/0, /*s*/NULL, &extra );
703}
704
705void MC_(record_cond_error) ( ThreadId tid, UInt otag )
706{
707 MC_Error extra;
708 tl_assert( MC_(clo_mc_level) >= 2 );
709 if (otag > 0)
710 tl_assert( MC_(clo_mc_level) == 3 );
711 extra.Err.Cond.otag = otag;
712 extra.Err.Cond.origin_ec = NULL; /* Filled in later */
713 VG_(maybe_record_error)( tid, Err_Cond, /*addr*/0, /*s*/NULL, &extra );
714}
715
716/* --- Called from non-generated code --- */
717
718/* This is for memory errors in pthread functions, as opposed to pthread API
719 errors which are found by the core. */
720void MC_(record_core_mem_error) ( ThreadId tid, Bool isAddrErr, Char* msg )
721{
722 VG_(maybe_record_error)( tid, Err_CoreMem, /*addr*/0, msg, /*extra*/NULL );
723}
724
725void MC_(record_regparam_error) ( ThreadId tid, Char* msg, UInt otag )
726{
727 MC_Error extra;
728 tl_assert(VG_INVALID_THREADID != tid);
729 if (otag > 0)
730 tl_assert( MC_(clo_mc_level) == 3 );
731 extra.Err.RegParam.otag = otag;
732 extra.Err.RegParam.origin_ec = NULL; /* Filled in later */
733 VG_(maybe_record_error)( tid, Err_RegParam, /*addr*/0, msg, &extra );
734}
735
736void MC_(record_memparam_error) ( ThreadId tid, Addr a,
737 Bool isAddrErr, Char* msg, UInt otag )
738{
739 MC_Error extra;
740 tl_assert(VG_INVALID_THREADID != tid);
741 if (!isAddrErr)
742 tl_assert( MC_(clo_mc_level) >= 2 );
743 if (otag != 0) {
744 tl_assert( MC_(clo_mc_level) == 3 );
745 tl_assert( !isAddrErr );
746 }
747 extra.Err.MemParam.isAddrErr = isAddrErr;
748 extra.Err.MemParam.ai.tag = Addr_Undescribed;
749 extra.Err.MemParam.otag = otag;
750 extra.Err.MemParam.origin_ec = NULL; /* Filled in later */
751 VG_(maybe_record_error)( tid, Err_MemParam, a, msg, &extra );
752}
753
754void MC_(record_jump_error) ( ThreadId tid, Addr a )
755{
756 MC_Error extra;
757 tl_assert(VG_INVALID_THREADID != tid);
758 extra.Err.Jump.ai.tag = Addr_Undescribed;
759 VG_(maybe_record_error)( tid, Err_Jump, a, /*s*/NULL, &extra );
760}
761
762void MC_(record_free_error) ( ThreadId tid, Addr a )
763{
764 MC_Error extra;
765 tl_assert(VG_INVALID_THREADID != tid);
766 extra.Err.Free.ai.tag = Addr_Undescribed;
767 VG_(maybe_record_error)( tid, Err_Free, a, /*s*/NULL, &extra );
768}
769
770void MC_(record_freemismatch_error) ( ThreadId tid, MC_Chunk* mc )
771{
772 MC_Error extra;
773 AddrInfo* ai = &extra.Err.FreeMismatch.ai;
774 tl_assert(VG_INVALID_THREADID != tid);
775 ai->tag = Addr_Block;
776 ai->Addr.Block.block_kind = Block_Mallocd; // Nb: Not 'Block_Freed'
777 ai->Addr.Block.block_desc = "block";
778 ai->Addr.Block.block_szB = mc->szB;
779 ai->Addr.Block.rwoffset = 0;
780 ai->Addr.Block.lastchange = mc->where;
781 VG_(maybe_record_error)( tid, Err_FreeMismatch, mc->data, /*s*/NULL,
782 &extra );
783}
784
785void MC_(record_illegal_mempool_error) ( ThreadId tid, Addr a )
786{
787 MC_Error extra;
788 tl_assert(VG_INVALID_THREADID != tid);
789 extra.Err.IllegalMempool.ai.tag = Addr_Undescribed;
790 VG_(maybe_record_error)( tid, Err_IllegalMempool, a, /*s*/NULL, &extra );
791}
792
793void MC_(record_overlap_error) ( ThreadId tid, Char* function,
794 Addr src, Addr dst, SizeT szB )
795{
796 MC_Error extra;
797 tl_assert(VG_INVALID_THREADID != tid);
798 extra.Err.Overlap.src = src;
799 extra.Err.Overlap.dst = dst;
800 extra.Err.Overlap.szB = szB;
801 VG_(maybe_record_error)(
802 tid, Err_Overlap, /*addr*/0, /*s*/function, &extra );
803}
804
805Bool MC_(record_leak_error) ( ThreadId tid, UInt n_this_record,
806 UInt n_total_records, LossRecord* lossRecord,
807 Bool print_record )
808{
809 MC_Error extra;
810 extra.Err.Leak.n_this_record = n_this_record;
811 extra.Err.Leak.n_total_records = n_total_records;
812 extra.Err.Leak.lossRecord = lossRecord;
813 return
814 VG_(unique_error) ( tid, Err_Leak, /*Addr*/0, /*s*/NULL, &extra,
815 lossRecord->allocated_at, print_record,
816 /*allow_GDB_attach*/False, /*count_error*/False );
817}
818
819void MC_(record_user_error) ( ThreadId tid, Addr a,
820 Bool isAddrErr, UInt otag )
821{
822 MC_Error extra;
823 if (otag != 0) {
824 tl_assert(!isAddrErr);
825 tl_assert( MC_(clo_mc_level) == 3 );
826 }
827 if (!isAddrErr) {
828 tl_assert( MC_(clo_mc_level) >= 2 );
829 }
830 tl_assert(VG_INVALID_THREADID != tid);
831 extra.Err.User.isAddrErr = isAddrErr;
832 extra.Err.User.ai.tag = Addr_Undescribed;
833 extra.Err.User.otag = otag;
834 extra.Err.User.origin_ec = NULL; /* Filled in later */
835 VG_(maybe_record_error)( tid, Err_User, a, /*s*/NULL, &extra );
836}
837
838/*------------------------------------------------------------*/
839/*--- Other error operations ---*/
840/*------------------------------------------------------------*/
841
842/* Compare error contexts, to detect duplicates. Note that if they
843 are otherwise the same, the faulting addrs and associated rwoffsets
844 are allowed to be different. */
845Bool MC_(eq_Error) ( VgRes res, Error* e1, Error* e2 )
846{
847 MC_Error* extra1 = VG_(get_error_extra)(e1);
848 MC_Error* extra2 = VG_(get_error_extra)(e2);
849
850 /* Guaranteed by calling function */
851 tl_assert(VG_(get_error_kind)(e1) == VG_(get_error_kind)(e2));
852
853 switch (VG_(get_error_kind)(e1)) {
854 case Err_CoreMem: {
855 Char *e1s, *e2s;
856 e1s = VG_(get_error_string)(e1);
857 e2s = VG_(get_error_string)(e2);
858 if (e1s == e2s) return True;
859 if (VG_STREQ(e1s, e2s)) return True;
860 return False;
861 }
862
863 case Err_RegParam:
864 return VG_STREQ(VG_(get_error_string)(e1), VG_(get_error_string)(e2));
865
866 // Perhaps we should also check the addrinfo.akinds for equality.
867 // That would result in more error reports, but only in cases where
868 // a register contains uninitialised bytes and points to memory
869 // containing uninitialised bytes. Currently, the 2nd of those to be
870 // detected won't be reported. That is (nearly?) always the memory
871 // error, which is good.
872 case Err_MemParam:
873 if (!VG_STREQ(VG_(get_error_string)(e1),
874 VG_(get_error_string)(e2))) return False;
875 // fall through
876 case Err_User:
877 return ( extra1->Err.User.isAddrErr == extra2->Err.User.isAddrErr
878 ? True : False );
879
880 case Err_Free:
881 case Err_FreeMismatch:
882 case Err_Jump:
883 case Err_IllegalMempool:
884 case Err_Overlap:
885 case Err_Cond:
886 return True;
887
888 case Err_Addr:
889 return ( extra1->Err.Addr.szB == extra2->Err.Addr.szB
890 ? True : False );
891
892 case Err_Value:
893 return ( extra1->Err.Value.szB == extra2->Err.Value.szB
894 ? True : False );
895
896 case Err_Leak:
897 VG_(tool_panic)("Shouldn't get Err_Leak in mc_eq_Error,\n"
898 "since it's handled with VG_(unique_error)()!");
899
900 default:
901 VG_(printf)("Error:\n unknown error code %d\n",
902 VG_(get_error_kind)(e1));
903 VG_(tool_panic)("unknown error code in mc_eq_Error");
904 }
905}
906
907/* Function used when searching MC_Chunk lists */
908static Bool addr_is_in_MC_Chunk(MC_Chunk* mc, Addr a)
909{
910 // Nb: this is not quite right! It assumes that the heap block has
911 // a redzone of size MC_MALLOC_REDZONE_SZB. That's true for malloc'd
912 // blocks, but not necessarily true for custom-alloc'd blocks. So
913 // in some cases this could result in an incorrect description (eg.
914 // saying "12 bytes after block A" when really it's within block B.
915 // Fixing would require adding redzone size to MC_Chunks, though.
916 return VG_(addr_is_in_block)( a, mc->data, mc->szB,
917 MC_MALLOC_REDZONE_SZB );
918}
919
920// Forward declaration
921static Bool client_block_maybe_describe( Addr a, AddrInfo* ai );
922
923
924/* Describe an address as best you can, for error messages,
925 putting the result in ai. */
926static void describe_addr ( Addr a, /*OUT*/AddrInfo* ai )
927{
928 MC_Chunk* mc;
929 ThreadId tid;
930 Addr stack_min, stack_max;
931 VgSectKind sect;
932
933 tl_assert(Addr_Undescribed == ai->tag);
934
935 /* Perhaps it's a user-def'd block? */
936 if (client_block_maybe_describe( a, ai )) {
937 return;
938 }
939 /* Search for a recently freed block which might bracket it. */
940 mc = MC_(get_freed_list_head)();
941 while (mc) {
942 if (addr_is_in_MC_Chunk(mc, a)) {
943 ai->tag = Addr_Block;
944 ai->Addr.Block.block_kind = Block_Freed;
945 ai->Addr.Block.block_desc = "block";
946 ai->Addr.Block.block_szB = mc->szB;
sewardj56adc352008-05-02 11:25:17 +0000947 ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
sewardj7ce71662008-05-02 10:33:15 +0000948 ai->Addr.Block.lastchange = mc->where;
949 return;
950 }
951 mc = mc->next;
952 }
953 /* Search for a currently malloc'd block which might bracket it. */
954 VG_(HT_ResetIter)(MC_(malloc_list));
955 while ( (mc = VG_(HT_Next)(MC_(malloc_list))) ) {
956 if (addr_is_in_MC_Chunk(mc, a)) {
957 ai->tag = Addr_Block;
958 ai->Addr.Block.block_kind = Block_Mallocd;
959 ai->Addr.Block.block_desc = "block";
960 ai->Addr.Block.block_szB = mc->szB;
sewardj56adc352008-05-02 11:25:17 +0000961 ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
sewardj7ce71662008-05-02 10:33:15 +0000962 ai->Addr.Block.lastchange = mc->where;
963 return;
964 }
965 }
966 /* Perhaps the variable type/location data describes it? */
967 tl_assert(sizeof(ai->Addr.Variable.descr1)
968 == sizeof(ai->Addr.Variable.descr2));
969 VG_(memset)( &ai->Addr.Variable.descr1,
970 0, sizeof(ai->Addr.Variable.descr1));
971 VG_(memset)( &ai->Addr.Variable.descr2,
972 0, sizeof(ai->Addr.Variable.descr2));
973 if (VG_(get_data_description)(
974 &ai->Addr.Variable.descr1[0],
975 &ai->Addr.Variable.descr2[0],
976 sizeof(ai->Addr.Variable.descr1)-1,
977 a )) {
978 ai->tag = Addr_Variable;
979 tl_assert( ai->Addr.Variable.descr1
980 [ sizeof(ai->Addr.Variable.descr1)-1 ] == 0);
981 tl_assert( ai->Addr.Variable.descr2
982 [ sizeof(ai->Addr.Variable.descr2)-1 ] == 0);
983 return;
984 }
985 /* Have a look at the low level data symbols - perhaps it's in
986 there. */
987 VG_(memset)( &ai->Addr.DataSym.name,
988 0, sizeof(ai->Addr.DataSym.name));
989 if (VG_(get_datasym_and_offset)(
990 a, &ai->Addr.DataSym.name[0],
991 sizeof(ai->Addr.DataSym.name)-1,
992 &ai->Addr.DataSym.offset )) {
993 ai->tag = Addr_DataSym;
994 tl_assert( ai->Addr.DataSym.name
995 [ sizeof(ai->Addr.DataSym.name)-1 ] == 0);
996 return;
997 }
998 /* Perhaps it's on a thread's stack? */
999 VG_(thread_stack_reset_iter)(&tid);
1000 while ( VG_(thread_stack_next)(&tid, &stack_min, &stack_max) ) {
1001 if (stack_min - VG_STACK_REDZONE_SZB <= a && a <= stack_max) {
1002 ai->tag = Addr_Stack;
1003 ai->Addr.Stack.tid = tid;
1004 return;
1005 }
1006 }
1007 /* last ditch attempt at classification */
1008 tl_assert( sizeof(ai->Addr.SectKind.objname) > 4 );
1009 VG_(memset)( &ai->Addr.SectKind.objname,
1010 0, sizeof(ai->Addr.SectKind.objname));
1011 VG_(strcpy)( ai->Addr.SectKind.objname, "???" );
1012 sect = VG_(seginfo_sect_kind)( &ai->Addr.SectKind.objname[0],
1013 sizeof(ai->Addr.SectKind.objname)-1, a);
1014 if (sect != Vg_SectUnknown) {
1015 ai->tag = Addr_SectKind;
1016 ai->Addr.SectKind.kind = sect;
1017 tl_assert( ai->Addr.SectKind.objname
1018 [ sizeof(ai->Addr.SectKind.objname)-1 ] == 0);
1019 return;
1020 }
1021 /* Clueless ... */
1022 ai->tag = Addr_Unknown;
1023 return;
1024}
1025
1026/* Fill in *origin_ec as specified by otag, or NULL it out if otag
1027 does not refer to a known origin. */
1028static void update_origin ( /*OUT*/ExeContext** origin_ec,
1029 UInt otag )
1030{
1031 UInt ecu = otag & ~3;
1032 *origin_ec = NULL;
1033 if (VG_(is_plausible_ECU)(ecu)) {
1034 *origin_ec = VG_(get_ExeContext_from_ECU)( ecu );
1035 }
1036}
1037
1038/* Updates the copy with address info if necessary (but not for all errors). */
1039UInt MC_(update_Error_extra)( Error* err )
1040{
1041 MC_Error* extra = VG_(get_error_extra)(err);
1042
1043 switch (VG_(get_error_kind)(err)) {
1044 // These ones don't have addresses associated with them, and so don't
1045 // need any updating.
1046 case Err_CoreMem:
1047 //case Err_Value:
1048 //case Err_Cond:
1049 case Err_Overlap:
1050 // For Err_Leaks the returned size does not matter -- they are always
1051 // shown with VG_(unique_error)() so they 'extra' not copied. But
1052 // we make it consistent with the others.
1053 case Err_Leak:
1054 return sizeof(MC_Error);
1055
1056 // For value errors, get the ExeContext corresponding to the
1057 // origin tag. Note that it is a kludge to assume that
1058 // a length-1 trace indicates a stack origin. FIXME.
1059 case Err_Value:
1060 update_origin( &extra->Err.Value.origin_ec,
1061 extra->Err.Value.otag );
1062 return sizeof(MC_Error);
1063 case Err_Cond:
1064 update_origin( &extra->Err.Cond.origin_ec,
1065 extra->Err.Cond.otag );
1066 return sizeof(MC_Error);
1067 case Err_RegParam:
1068 update_origin( &extra->Err.RegParam.origin_ec,
1069 extra->Err.RegParam.otag );
1070 return sizeof(MC_Error);
1071
1072 // These ones always involve a memory address.
1073 case Err_Addr:
1074 describe_addr ( VG_(get_error_address)(err),
1075 &extra->Err.Addr.ai );
1076 return sizeof(MC_Error);
1077 case Err_MemParam:
1078 describe_addr ( VG_(get_error_address)(err),
1079 &extra->Err.MemParam.ai );
1080 update_origin( &extra->Err.MemParam.origin_ec,
1081 extra->Err.MemParam.otag );
1082 return sizeof(MC_Error);
1083 case Err_Jump:
1084 describe_addr ( VG_(get_error_address)(err),
1085 &extra->Err.Jump.ai );
1086 return sizeof(MC_Error);
1087 case Err_User:
1088 describe_addr ( VG_(get_error_address)(err),
1089 &extra->Err.User.ai );
1090 update_origin( &extra->Err.User.origin_ec,
1091 extra->Err.User.otag );
1092 return sizeof(MC_Error);
1093 case Err_Free:
1094 describe_addr ( VG_(get_error_address)(err),
1095 &extra->Err.Free.ai );
1096 return sizeof(MC_Error);
1097 case Err_IllegalMempool:
1098 describe_addr ( VG_(get_error_address)(err),
1099 &extra->Err.IllegalMempool.ai );
1100 return sizeof(MC_Error);
1101
1102 // Err_FreeMismatches have already had their address described; this is
1103 // possible because we have the MC_Chunk on hand when the error is
1104 // detected. However, the address may be part of a user block, and if so
1105 // we override the pre-determined description with a user block one.
1106 case Err_FreeMismatch: {
1107 tl_assert(extra && Block_Mallocd ==
1108 extra->Err.FreeMismatch.ai.Addr.Block.block_kind);
1109 (void)client_block_maybe_describe( VG_(get_error_address)(err),
1110 &extra->Err.FreeMismatch.ai );
1111 return sizeof(MC_Error);
1112 }
1113
1114 default: VG_(tool_panic)("mc_update_extra: bad errkind");
1115 }
1116}
1117
1118// FIXME: does this perhaps want to live somewhere else
1119// in this file?
1120static Bool client_block_maybe_describe( Addr a,
1121 /*OUT*/AddrInfo* ai )
1122{
sewardj56adc352008-05-02 11:25:17 +00001123 UWord i;
sewardj7ce71662008-05-02 10:33:15 +00001124 CGenBlock* cgbs = NULL;
1125 UWord cgb_used = 0;
sewardj56adc352008-05-02 11:25:17 +00001126
sewardj7ce71662008-05-02 10:33:15 +00001127 MC_(get_ClientBlock_array)( &cgbs, &cgb_used );
1128 if (cgbs == NULL)
1129 tl_assert(cgb_used == 0);
1130
1131 /* Perhaps it's a general block ? */
1132 for (i = 0; i < cgb_used; i++) {
1133 if (cgbs[i].start == 0 && cgbs[i].size == 0)
1134 continue;
1135 // Use zero as the redzone for client blocks.
1136 if (VG_(addr_is_in_block)(a, cgbs[i].start, cgbs[i].size, 0)) {
1137 /* OK - maybe it's a mempool, too? */
1138 MC_Mempool* mp = VG_(HT_lookup)(MC_(mempool_list),
1139 (UWord)cgbs[i].start);
1140 if (mp != NULL) {
1141 if (mp->chunks != NULL) {
1142 MC_Chunk* mc;
1143 VG_(HT_ResetIter)(mp->chunks);
1144 while ( (mc = VG_(HT_Next)(mp->chunks)) ) {
1145 if (addr_is_in_MC_Chunk(mc, a)) {
1146 ai->tag = Addr_Block;
1147 ai->Addr.Block.block_kind = Block_MempoolChunk;
1148 ai->Addr.Block.block_desc = "block";
1149 ai->Addr.Block.block_szB = mc->szB;
sewardj56adc352008-05-02 11:25:17 +00001150 ai->Addr.Block.rwoffset = (Word)a - (Word)mc->data;
sewardj7ce71662008-05-02 10:33:15 +00001151 ai->Addr.Block.lastchange = mc->where;
1152 return True;
1153 }
1154 }
1155 }
1156 ai->tag = Addr_Block;
1157 ai->Addr.Block.block_kind = Block_Mempool;
1158 ai->Addr.Block.block_desc = "mempool";
1159 ai->Addr.Block.block_szB = cgbs[i].size;
sewardj56adc352008-05-02 11:25:17 +00001160 ai->Addr.Block.rwoffset = (Word)(a) - (Word)(cgbs[i].start);
sewardj7ce71662008-05-02 10:33:15 +00001161 ai->Addr.Block.lastchange = cgbs[i].where;
1162 return True;
1163 }
1164 ai->tag = Addr_Block;
1165 ai->Addr.Block.block_kind = Block_UserG;
1166 ai->Addr.Block.block_desc = cgbs[i].desc;
1167 ai->Addr.Block.block_szB = cgbs[i].size;
sewardj56adc352008-05-02 11:25:17 +00001168 ai->Addr.Block.rwoffset = (Word)(a) - (Word)(cgbs[i].start);
sewardj7ce71662008-05-02 10:33:15 +00001169 ai->Addr.Block.lastchange = cgbs[i].where;
1170 return True;
1171 }
1172 }
1173 return False;
1174}
1175
1176
1177/*------------------------------------------------------------*/
1178/*--- Suppressions ---*/
1179/*------------------------------------------------------------*/
1180
1181typedef
1182 enum {
1183 ParamSupp, // Bad syscall params
1184 UserSupp, // Errors arising from client-request checks
1185 CoreMemSupp, // Memory errors in core (pthread ops, signal handling)
1186
1187 // Undefined value errors of given size
1188 Value1Supp, Value2Supp, Value4Supp, Value8Supp, Value16Supp,
1189
1190 // Undefined value error in conditional.
1191 CondSupp,
1192
1193 // Unaddressable read/write attempt at given size
1194 Addr1Supp, Addr2Supp, Addr4Supp, Addr8Supp, Addr16Supp,
1195
1196 JumpSupp, // Jump to unaddressable target
1197 FreeSupp, // Invalid or mismatching free
1198 OverlapSupp, // Overlapping blocks in memcpy(), strcpy(), etc
1199 LeakSupp, // Something to be suppressed in a leak check.
1200 MempoolSupp, // Memory pool suppression.
1201 }
1202 MC_SuppKind;
1203
1204Bool MC_(is_recognised_suppression) ( Char* name, Supp* su )
1205{
1206 SuppKind skind;
1207
1208 if (VG_STREQ(name, "Param")) skind = ParamSupp;
1209 else if (VG_STREQ(name, "User")) skind = UserSupp;
1210 else if (VG_STREQ(name, "CoreMem")) skind = CoreMemSupp;
1211 else if (VG_STREQ(name, "Addr1")) skind = Addr1Supp;
1212 else if (VG_STREQ(name, "Addr2")) skind = Addr2Supp;
1213 else if (VG_STREQ(name, "Addr4")) skind = Addr4Supp;
1214 else if (VG_STREQ(name, "Addr8")) skind = Addr8Supp;
1215 else if (VG_STREQ(name, "Addr16")) skind = Addr16Supp;
1216 else if (VG_STREQ(name, "Jump")) skind = JumpSupp;
1217 else if (VG_STREQ(name, "Free")) skind = FreeSupp;
1218 else if (VG_STREQ(name, "Leak")) skind = LeakSupp;
1219 else if (VG_STREQ(name, "Overlap")) skind = OverlapSupp;
1220 else if (VG_STREQ(name, "Mempool")) skind = MempoolSupp;
1221 else if (VG_STREQ(name, "Cond")) skind = CondSupp;
1222 else if (VG_STREQ(name, "Value0")) skind = CondSupp; /* backwards compat */
1223 else if (VG_STREQ(name, "Value1")) skind = Value1Supp;
1224 else if (VG_STREQ(name, "Value2")) skind = Value2Supp;
1225 else if (VG_STREQ(name, "Value4")) skind = Value4Supp;
1226 else if (VG_STREQ(name, "Value8")) skind = Value8Supp;
1227 else if (VG_STREQ(name, "Value16")) skind = Value16Supp;
1228 else
1229 return False;
1230
1231 VG_(set_supp_kind)(su, skind);
1232 return True;
1233}
1234
1235Bool MC_(read_extra_suppression_info) ( Int fd, Char* buf,
1236 Int nBuf, Supp *su )
1237{
1238 Bool eof;
1239
1240 if (VG_(get_supp_kind)(su) == ParamSupp) {
1241 eof = VG_(get_line) ( fd, buf, nBuf );
1242 if (eof) return False;
sewardj9c606bd2008-09-18 18:12:50 +00001243 VG_(set_supp_string)(su, VG_(strdup)("mc.resi.1", buf));
sewardj7ce71662008-05-02 10:33:15 +00001244 }
1245 return True;
1246}
1247
1248Bool MC_(error_matches_suppression) ( Error* err, Supp* su )
1249{
1250 Int su_szB;
1251 MC_Error* extra = VG_(get_error_extra)(err);
1252 ErrorKind ekind = VG_(get_error_kind )(err);
1253
1254 switch (VG_(get_supp_kind)(su)) {
1255 case ParamSupp:
1256 return ((ekind == Err_RegParam || ekind == Err_MemParam)
1257 && VG_STREQ(VG_(get_error_string)(err),
1258 VG_(get_supp_string)(su)));
1259
1260 case UserSupp:
1261 return (ekind == Err_User);
1262
1263 case CoreMemSupp:
1264 return (ekind == Err_CoreMem
1265 && VG_STREQ(VG_(get_error_string)(err),
1266 VG_(get_supp_string)(su)));
1267
1268 case Value1Supp: su_szB = 1; goto value_case;
1269 case Value2Supp: su_szB = 2; goto value_case;
1270 case Value4Supp: su_szB = 4; goto value_case;
1271 case Value8Supp: su_szB = 8; goto value_case;
1272 case Value16Supp:su_szB =16; goto value_case;
1273 value_case:
1274 return (ekind == Err_Value && extra->Err.Value.szB == su_szB);
1275
1276 case CondSupp:
1277 return (ekind == Err_Cond);
1278
1279 case Addr1Supp: su_szB = 1; goto addr_case;
1280 case Addr2Supp: su_szB = 2; goto addr_case;
1281 case Addr4Supp: su_szB = 4; goto addr_case;
1282 case Addr8Supp: su_szB = 8; goto addr_case;
1283 case Addr16Supp:su_szB =16; goto addr_case;
1284 addr_case:
1285 return (ekind == Err_Addr && extra->Err.Addr.szB == su_szB);
1286
1287 case JumpSupp:
1288 return (ekind == Err_Jump);
1289
1290 case FreeSupp:
1291 return (ekind == Err_Free || ekind == Err_FreeMismatch);
1292
1293 case OverlapSupp:
1294 return (ekind == Err_Overlap);
1295
1296 case LeakSupp:
1297 return (ekind == Err_Leak);
1298
1299 case MempoolSupp:
1300 return (ekind == Err_IllegalMempool);
1301
1302 default:
1303 VG_(printf)("Error:\n"
1304 " unknown suppression type %d\n",
1305 VG_(get_supp_kind)(su));
1306 VG_(tool_panic)("unknown suppression type in "
1307 "MC_(error_matches_suppression)");
1308 }
1309}
1310
1311Char* MC_(get_error_name) ( Error* err )
1312{
1313 switch (VG_(get_error_kind)(err)) {
1314 case Err_RegParam: return "Param";
1315 case Err_MemParam: return "Param";
1316 case Err_User: return "User";
1317 case Err_FreeMismatch: return "Free";
1318 case Err_IllegalMempool: return "Mempool";
1319 case Err_Free: return "Free";
1320 case Err_Jump: return "Jump";
1321 case Err_CoreMem: return "CoreMem";
1322 case Err_Overlap: return "Overlap";
1323 case Err_Leak: return "Leak";
1324 case Err_Cond: return "Cond";
1325 case Err_Addr: {
1326 MC_Error* extra = VG_(get_error_extra)(err);
1327 switch ( extra->Err.Addr.szB ) {
1328 case 1: return "Addr1";
1329 case 2: return "Addr2";
1330 case 4: return "Addr4";
1331 case 8: return "Addr8";
1332 case 16: return "Addr16";
1333 default: VG_(tool_panic)("unexpected size for Addr");
1334 }
1335 }
1336 case Err_Value: {
1337 MC_Error* extra = VG_(get_error_extra)(err);
1338 switch ( extra->Err.Value.szB ) {
1339 case 1: return "Value1";
1340 case 2: return "Value2";
1341 case 4: return "Value4";
1342 case 8: return "Value8";
1343 case 16: return "Value16";
1344 default: VG_(tool_panic)("unexpected size for Value");
1345 }
1346 }
1347 default: VG_(tool_panic)("get_error_name: unexpected type");
1348 }
1349}
1350
1351void MC_(print_extra_suppression_info) ( Error* err )
1352{
1353 ErrorKind ekind = VG_(get_error_kind )(err);
1354 if (Err_RegParam == ekind || Err_MemParam == ekind) {
1355 VG_(printf)(" %s\n", VG_(get_error_string)(err));
1356 }
1357}
1358
1359
1360/*--------------------------------------------------------------------*/
1361/*--- end mc_errors.c ---*/
1362/*--------------------------------------------------------------------*/