blob: d5e0abb43dfd12bebbf5a043e8f4190ec7523105 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- Management of error messages. vg_errcontext.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, an x86 protected-mode emulator
8 designed for debugging and profiling binaries on x86-Unixes.
9
10 Copyright (C) 2000-2002 Julian Seward
11 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file LICENSE.
29*/
30
31#include "vg_include.h"
32#include "vg_constants.h"
33
34
35/*------------------------------------------------------------*/
36/*--- Defns ---*/
37/*------------------------------------------------------------*/
38
39/* Suppression is a type describing an error which we want to
40 suppress, ie, not show the user, usually because it is caused by a
41 problem in a library which we can't fix, replace or work around.
42 Suppressions are read from a file at startup time, specified by
43 vg_clo_suppressions, and placed in the vg_suppressions list. This
44 gives flexibility so that new suppressions can be added to the file
45 as and when needed.
46*/
47typedef
48 enum {
49 /* Bad syscall params */
50 Param,
51 /* Use of invalid values of given size */
52 Value0, Value1, Value2, Value4, Value8,
53 /* Invalid read/write attempt at given size */
54 Addr1, Addr2, Addr4, Addr8,
55 /* Invalid or mismatching free */
sewardj4dced352002-06-04 22:54:20 +000056 FreeS,
57 /* Pthreading error */
58 PThread
sewardjde4a1d02002-03-22 01:27:54 +000059 }
60 SuppressionKind;
61
62
63/* For each caller specified for a suppression, record the nature of
64 the caller name. */
65typedef
66 enum {
67 /* Name is of an shared object file. */
68 ObjName,
69 /* Name is of a function. */
70 FunName
71 }
72 SuppressionLocTy;
73
74
75/* A complete suppression record. */
76typedef
77 struct _Suppression {
78 struct _Suppression* next;
79 /* The number of times this error has been suppressed. */
80 Int count;
81 /* The name by which the suppression is referred to. */
82 Char* sname;
83 /* What kind of suppression. */
84 SuppressionKind skind;
85 /* Name of syscall param if skind==Param */
86 Char* param;
87 /* Name of fn where err occurs, and immediate caller (mandatory). */
88 SuppressionLocTy caller0_ty;
89 Char* caller0;
90 SuppressionLocTy caller1_ty;
91 Char* caller1;
92 /* Optional extra callers. */
93 SuppressionLocTy caller2_ty;
94 Char* caller2;
95 SuppressionLocTy caller3_ty;
96 Char* caller3;
97 }
98 Suppression;
99
100
101/* ErrContext is a type for recording just enough info to generate an
102 error report for an illegal memory access. The idea is that
103 (typically) the same few points in the program generate thousands
104 of illegal accesses, and we don't want to spew out a fresh error
105 message for each one. Instead, we use these structures to common
106 up duplicates.
107*/
108
109/* What kind of error it is. */
110typedef
111 enum { ValueErr, AddrErr,
112 ParamErr, UserErr, /* behaves like an anonymous ParamErr */
sewardj4dced352002-06-04 22:54:20 +0000113 FreeErr, FreeMismatchErr,
114 PThreadErr /* pthread API error */
115 }
sewardjde4a1d02002-03-22 01:27:54 +0000116 ErrKind;
117
118/* What kind of memory access is involved in the error? */
119typedef
120 enum { ReadAxs, WriteAxs, ExecAxs }
121 AxsKind;
122
123/* Top-level struct for recording errors. */
124typedef
125 struct _ErrContext {
126 /* ALL */
127 struct _ErrContext* next;
128 /* ALL */
129 /* NULL if unsuppressed; or ptr to suppression record. */
130 Suppression* supp;
131 /* ALL */
132 Int count;
133 /* ALL */
134 ErrKind ekind;
135 /* ALL */
136 ExeContext* where;
137 /* Addr */
138 AxsKind axskind;
139 /* Addr, Value */
140 Int size;
141 /* Addr, Free, Param, User */
142 Addr addr;
143 /* Addr, Free, Param, User */
144 AddrInfo addrinfo;
sewardj4dced352002-06-04 22:54:20 +0000145 /* Param; hijacked for PThread as a description */
sewardjde4a1d02002-03-22 01:27:54 +0000146 Char* syscall_param;
147 /* Param, User */
148 Bool isWriteableLack;
sewardj1e8cdc92002-04-18 11:37:52 +0000149 /* ALL */
150 ThreadId tid;
sewardj35805422002-04-21 13:05:34 +0000151 /* ALL */
152 /* These record %EIP, %ESP and %EBP at the error point. They
153 are only used to make GDB-attaching convenient; there is no
154 other purpose; specifically they are not used to do
155 comparisons between errors. */
156 UInt m_eip;
157 UInt m_esp;
158 UInt m_ebp;
sewardjde4a1d02002-03-22 01:27:54 +0000159 }
160 ErrContext;
161
162/* The list of error contexts found, both suppressed and unsuppressed.
163 Initially empty, and grows as errors are detected. */
164static ErrContext* vg_err_contexts = NULL;
165
166/* The list of suppression directives, as read from the specified
167 suppressions file. */
168static Suppression* vg_suppressions = NULL;
169
170/* Running count of unsuppressed errors detected. */
171static UInt vg_n_errs_found = 0;
172
173/* Running count of suppressed errors detected. */
174static UInt vg_n_errs_suppressed = 0;
175
sewardjc96f9312002-04-24 20:20:22 +0000176/* Used to disable further error reporting once some huge number of
177 errors have already been logged. */
178static Bool vg_ignore_errors = False;
179
sewardjde4a1d02002-03-22 01:27:54 +0000180/* forwards ... */
181static Suppression* is_suppressible_error ( ErrContext* ec );
182
183
184/*------------------------------------------------------------*/
185/*--- Helper fns ---*/
186/*------------------------------------------------------------*/
187
188
189static void clear_AddrInfo ( AddrInfo* ai )
190{
191 ai->akind = Unknown;
192 ai->blksize = 0;
193 ai->rwoffset = 0;
194 ai->lastchange = NULL;
sewardj1e8cdc92002-04-18 11:37:52 +0000195 ai->stack_tid = VG_INVALID_THREADID;
sewardjb581a132002-05-08 00:32:50 +0000196 ai->maybe_gcc = False;
sewardjde4a1d02002-03-22 01:27:54 +0000197}
198
199static void clear_ErrContext ( ErrContext* ec )
200{
201 ec->next = NULL;
202 ec->supp = NULL;
203 ec->count = 0;
204 ec->ekind = ValueErr;
205 ec->where = NULL;
206 ec->axskind = ReadAxs;
207 ec->size = 0;
208 ec->addr = 0;
209 clear_AddrInfo ( &ec->addrinfo );
210 ec->syscall_param = NULL;
211 ec->isWriteableLack = False;
sewardj35805422002-04-21 13:05:34 +0000212 ec->m_eip = 0xDEADB00F;
213 ec->m_esp = 0xDEADBE0F;
214 ec->m_ebp = 0xDEADB0EF;
sewardj1e8cdc92002-04-18 11:37:52 +0000215 ec->tid = VG_INVALID_THREADID;
sewardjde4a1d02002-03-22 01:27:54 +0000216}
217
218
219static __inline__
220Bool vg_eq_ExeContext ( Bool top_2_only,
221 ExeContext* e1, ExeContext* e2 )
222{
223 /* Note that frames after the 4th are always ignored. */
224 if (top_2_only) {
225 return VG_(eq_ExeContext_top2(e1, e2));
226 } else {
227 return VG_(eq_ExeContext_top4(e1, e2));
228 }
229}
230
231
232static Bool eq_AddrInfo ( Bool cheap_addr_cmp,
233 AddrInfo* ai1, AddrInfo* ai2 )
234{
sewardjb581a132002-05-08 00:32:50 +0000235 if (ai1->akind != Undescribed
236 && ai2->akind != Undescribed
237 && ai1->akind != ai2->akind)
sewardjde4a1d02002-03-22 01:27:54 +0000238 return False;
239 if (ai1->akind == Freed || ai1->akind == Mallocd) {
240 if (ai1->blksize != ai2->blksize)
241 return False;
242 if (!vg_eq_ExeContext(cheap_addr_cmp,
243 ai1->lastchange, ai2->lastchange))
244 return False;
245 }
246 return True;
247}
248
249/* Compare error contexts, to detect duplicates. Note that if they
250 are otherwise the same, the faulting addrs and associated rwoffsets
251 are allowed to be different. */
252
253static Bool eq_ErrContext ( Bool cheap_addr_cmp,
254 ErrContext* e1, ErrContext* e2 )
255{
256 if (e1->ekind != e2->ekind)
257 return False;
258 if (!vg_eq_ExeContext(cheap_addr_cmp, e1->where, e2->where))
259 return False;
260
261 switch (e1->ekind) {
sewardj4dced352002-06-04 22:54:20 +0000262 case PThreadErr:
263 if (e1->syscall_param == e2->syscall_param)
264 return True;
265 if (0 == VG_(strcmp)(e1->syscall_param, e2->syscall_param))
266 return True;
267 return False;
sewardjde4a1d02002-03-22 01:27:54 +0000268 case UserErr:
269 case ParamErr:
270 if (e1->isWriteableLack != e2->isWriteableLack) return False;
271 if (e1->ekind == ParamErr
272 && 0 != VG_(strcmp)(e1->syscall_param, e2->syscall_param))
273 return False;
274 return True;
275 case FreeErr:
276 case FreeMismatchErr:
277 if (e1->addr != e2->addr) return False;
278 if (!eq_AddrInfo(cheap_addr_cmp, &e1->addrinfo, &e2->addrinfo))
279 return False;
280 return True;
281 case AddrErr:
282 if (e1->axskind != e2->axskind) return False;
283 if (e1->size != e2->size) return False;
284 if (!eq_AddrInfo(cheap_addr_cmp, &e1->addrinfo, &e2->addrinfo))
285 return False;
286 return True;
287 case ValueErr:
288 if (e1->size != e2->size) return False;
289 return True;
290 default:
291 VG_(panic)("eq_ErrContext");
292 }
293}
294
295static void pp_AddrInfo ( Addr a, AddrInfo* ai )
296{
297 switch (ai->akind) {
298 case Stack:
sewardj1e8cdc92002-04-18 11:37:52 +0000299 VG_(message)(Vg_UserMsg,
300 " Address 0x%x is on thread %d's stack",
sewardjb48e5002002-05-13 00:16:03 +0000301 a, ai->stack_tid);
sewardjde4a1d02002-03-22 01:27:54 +0000302 break;
303 case Unknown:
sewardjb581a132002-05-08 00:32:50 +0000304 if (ai->maybe_gcc) {
305 VG_(message)(Vg_UserMsg,
306 " Address 0x%x is just below %%esp. Possibly a bug in GCC/G++",
307 a);
308 VG_(message)(Vg_UserMsg,
309 " v 2.96 or 3.0.X. To suppress, use: --workaround-gcc296-bugs=yes");
310 } else {
311 VG_(message)(Vg_UserMsg,
312 " Address 0x%x is not stack'd, malloc'd or free'd", a);
313 }
sewardjde4a1d02002-03-22 01:27:54 +0000314 break;
315 case Freed: case Mallocd: case UserG: case UserS: {
316 UInt delta;
317 UChar* relative;
318 if (ai->rwoffset < 0) {
319 delta = (UInt)(- ai->rwoffset);
320 relative = "before";
321 } else if (ai->rwoffset >= ai->blksize) {
322 delta = ai->rwoffset - ai->blksize;
323 relative = "after";
324 } else {
325 delta = ai->rwoffset;
326 relative = "inside";
327 }
328 if (ai->akind == UserS) {
329 VG_(message)(Vg_UserMsg,
330 " Address 0x%x is %d bytes %s a %d-byte stack red-zone created",
331 a, delta, relative,
332 ai->blksize );
333 } else {
334 VG_(message)(Vg_UserMsg,
335 " Address 0x%x is %d bytes %s a block of size %d %s",
336 a, delta, relative,
337 ai->blksize,
338 ai->akind==Mallocd ? "alloc'd"
339 : ai->akind==Freed ? "free'd"
340 : "client-defined");
341 }
342 VG_(pp_ExeContext)(ai->lastchange);
343 break;
344 }
345 default:
346 VG_(panic)("pp_AddrInfo");
347 }
348}
349
350static void pp_ErrContext ( ErrContext* ec, Bool printCount )
351{
352 if (printCount)
353 VG_(message)(Vg_UserMsg, "Observed %d times:", ec->count );
sewardj6072c362002-04-19 14:40:57 +0000354 if (ec->tid > 1)
sewardj1e8cdc92002-04-18 11:37:52 +0000355 VG_(message)(Vg_UserMsg, "Thread %d:", ec->tid );
sewardjde4a1d02002-03-22 01:27:54 +0000356 switch (ec->ekind) {
357 case ValueErr:
358 if (ec->size == 0) {
sewardja7dc7952002-03-24 11:29:13 +0000359 VG_(message)(
360 Vg_UserMsg,
361 "Conditional jump or move depends on uninitialised value(s)");
sewardjde4a1d02002-03-22 01:27:54 +0000362 } else {
363 VG_(message)(Vg_UserMsg,
364 "Use of uninitialised value of size %d",
365 ec->size);
366 }
367 VG_(pp_ExeContext)(ec->where);
368 break;
369 case AddrErr:
370 switch (ec->axskind) {
371 case ReadAxs:
372 VG_(message)(Vg_UserMsg, "Invalid read of size %d",
373 ec->size );
374 break;
375 case WriteAxs:
376 VG_(message)(Vg_UserMsg, "Invalid write of size %d",
377 ec->size );
378 break;
379 case ExecAxs:
380 VG_(message)(Vg_UserMsg, "Jump to the invalid address "
381 "stated on the next line");
382 break;
383 default:
384 VG_(panic)("pp_ErrContext(axskind)");
385 }
386 VG_(pp_ExeContext)(ec->where);
387 pp_AddrInfo(ec->addr, &ec->addrinfo);
388 break;
389 case FreeErr:
390 VG_(message)(Vg_UserMsg,"Invalid free() / delete / delete[]");
391 /* fall through */
392 case FreeMismatchErr:
393 if (ec->ekind == FreeMismatchErr)
394 VG_(message)(Vg_UserMsg,
395 "Mismatched free() / delete / delete []");
396 VG_(pp_ExeContext)(ec->where);
397 pp_AddrInfo(ec->addr, &ec->addrinfo);
398 break;
399 case ParamErr:
400 if (ec->isWriteableLack) {
401 VG_(message)(Vg_UserMsg,
402 "Syscall param %s contains unaddressable byte(s)",
403 ec->syscall_param );
404 } else {
405 VG_(message)(Vg_UserMsg,
406 "Syscall param %s contains uninitialised or "
407 "unaddressable byte(s)",
408 ec->syscall_param);
409 }
410 VG_(pp_ExeContext)(ec->where);
411 pp_AddrInfo(ec->addr, &ec->addrinfo);
412 break;
413 case UserErr:
414 if (ec->isWriteableLack) {
415 VG_(message)(Vg_UserMsg,
416 "Unaddressable byte(s) found during client check request");
417 } else {
418 VG_(message)(Vg_UserMsg,
419 "Uninitialised or "
420 "unaddressable byte(s) found during client check request");
421 }
422 VG_(pp_ExeContext)(ec->where);
423 pp_AddrInfo(ec->addr, &ec->addrinfo);
424 break;
sewardj4dced352002-06-04 22:54:20 +0000425 case PThreadErr:
426 VG_(message)(Vg_UserMsg, "%s", ec->syscall_param );
427 VG_(pp_ExeContext)(ec->where);
428 break;
sewardjde4a1d02002-03-22 01:27:54 +0000429 default:
430 VG_(panic)("pp_ErrContext");
431 }
432}
433
434
435/* Figure out if we want to attach for GDB for this error, possibly
436 by asking the user. */
437static
438Bool vg_is_GDB_attach_requested ( void )
439{
440 Char ch, ch2;
441 Int res;
442
443 if (VG_(clo_GDB_attach) == False)
444 return False;
445
446 VG_(message)(Vg_UserMsg, "");
447
448 again:
449 VG_(printf)(
450 "==%d== "
451 "---- Attach to GDB ? --- [Return/N/n/Y/y/C/c] ---- ",
452 VG_(getpid)()
453 );
454
455 res = VG_(read)(0 /*stdin*/, &ch, 1);
456 if (res != 1) goto ioerror;
457 /* res == 1 */
458 if (ch == '\n') return False;
459 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y'
460 && ch != 'C' && ch != 'c') goto again;
461
462 res = VG_(read)(0 /*stdin*/, &ch2, 1);
463 if (res != 1) goto ioerror;
464 if (ch2 != '\n') goto again;
465
466 /* No, don't want to attach. */
467 if (ch == 'n' || ch == 'N') return False;
468 /* Yes, want to attach. */
469 if (ch == 'y' || ch == 'Y') return True;
470 /* No, don't want to attach, and don't ask again either. */
471 vg_assert(ch == 'c' || ch == 'C');
472
473 ioerror:
474 VG_(clo_GDB_attach) = False;
475 return False;
476}
477
478
479/* Top-level entry point to the error management subsystem. All
480 detected errors are notified here; this routine decides if/when the
481 user should see the error. */
482static void VG_(maybe_add_context) ( ErrContext* ec )
483{
484 ErrContext* p;
485 ErrContext* p_prev;
486 Bool cheap_addr_cmp = False;
487 static Bool is_first_shown_context = True;
488 static Bool stopping_message = False;
489 static Bool slowdown_message = False;
490 static Int vg_n_errs_shown = 0;
491
sewardj1e8cdc92002-04-18 11:37:52 +0000492 vg_assert(ec->tid >= 0 && ec->tid < VG_N_THREADS);
493
sewardjf2537be2002-04-24 21:03:47 +0000494 /* After M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
495 been found, or M_VG_COLLECT_NO_ERRORS_AFTER_FOUND total errors
496 have been found, just refuse to collect any more. This stops
497 the burden of the error-management system becoming excessive in
498 extremely buggy programs, although it does make it pretty
499 pointless to continue the Valgrind run after this point. */
500 if (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN
501 || vg_n_errs_found >= M_VG_COLLECT_NO_ERRORS_AFTER_FOUND) {
sewardjde4a1d02002-03-22 01:27:54 +0000502 if (!stopping_message) {
503 VG_(message)(Vg_UserMsg, "");
sewardjf2537be2002-04-24 21:03:47 +0000504
505 if (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN) {
506 VG_(message)(Vg_UserMsg,
507 "More than %d different errors detected. "
508 "I'm not reporting any more.",
509 M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN );
510 } else {
511 VG_(message)(Vg_UserMsg,
512 "More than %d total errors detected. "
513 "I'm not reporting any more.",
514 M_VG_COLLECT_NO_ERRORS_AFTER_FOUND );
515 }
516
sewardjde4a1d02002-03-22 01:27:54 +0000517 VG_(message)(Vg_UserMsg,
sewardjf2537be2002-04-24 21:03:47 +0000518 "Final error counts will be inaccurate. Go fix your program!");
sewardjde4a1d02002-03-22 01:27:54 +0000519 VG_(message)(Vg_UserMsg, "");
520 stopping_message = True;
sewardjc96f9312002-04-24 20:20:22 +0000521 vg_ignore_errors = True;
sewardjde4a1d02002-03-22 01:27:54 +0000522 }
523 return;
524 }
525
526 /* After M_VG_COLLECT_ERRORS_SLOWLY_AFTER different errors have
527 been found, be much more conservative about collecting new
528 ones. */
529 if (vg_n_errs_shown >= M_VG_COLLECT_ERRORS_SLOWLY_AFTER) {
530 cheap_addr_cmp = True;
531 if (!slowdown_message) {
532 VG_(message)(Vg_UserMsg, "");
533 VG_(message)(Vg_UserMsg,
534 "More than %d errors detected. Subsequent errors",
535 M_VG_COLLECT_ERRORS_SLOWLY_AFTER);
536 VG_(message)(Vg_UserMsg,
537 "will still be recorded, but in less detail than before.");
538 slowdown_message = True;
539 }
540 }
541
542
543 /* First, see if we've got an error record matching this one. */
544 p = vg_err_contexts;
545 p_prev = NULL;
546 while (p != NULL) {
547 if (eq_ErrContext(cheap_addr_cmp, p, ec)) {
548 /* Found it. */
549 p->count++;
550 if (p->supp != NULL) {
551 /* Deal correctly with suppressed errors. */
552 p->supp->count++;
553 vg_n_errs_suppressed++;
554 } else {
555 vg_n_errs_found++;
556 }
557
558 /* Move p to the front of the list so that future searches
559 for it are faster. */
560 if (p_prev != NULL) {
561 vg_assert(p_prev->next == p);
562 p_prev->next = p->next;
563 p->next = vg_err_contexts;
564 vg_err_contexts = p;
565 }
566 return;
567 }
568 p_prev = p;
569 p = p->next;
570 }
571
572 /* Didn't see it. Copy and add. */
573
sewardjb581a132002-05-08 00:32:50 +0000574 /* OK, we're really going to collect it. First, describe any addr
575 info in the error. */
576 if (ec->addrinfo.akind == Undescribed)
577 VG_(describe_addr) ( ec->addr, &ec->addrinfo );
sewardjde4a1d02002-03-22 01:27:54 +0000578
579 p = VG_(malloc)(VG_AR_ERRCTXT, sizeof(ErrContext));
580 *p = *ec;
581 p->next = vg_err_contexts;
582 p->supp = is_suppressible_error(ec);
583 vg_err_contexts = p;
584 if (p->supp == NULL) {
585 vg_n_errs_found++;
586 if (!is_first_shown_context)
587 VG_(message)(Vg_UserMsg, "");
588 pp_ErrContext(p, False);
589 is_first_shown_context = False;
590 vg_n_errs_shown++;
591 /* Perhaps we want a GDB attach at this point? */
592 if (vg_is_GDB_attach_requested()) {
sewardj35805422002-04-21 13:05:34 +0000593 VG_(swizzle_esp_then_start_GDB)(
594 ec->m_eip, ec->m_esp, ec->m_ebp);
sewardjde4a1d02002-03-22 01:27:54 +0000595 }
596 } else {
597 vg_n_errs_suppressed++;
598 p->supp->count++;
599 }
600}
601
602
603
604
605/*------------------------------------------------------------*/
606/*--- Exported fns ---*/
607/*------------------------------------------------------------*/
608
sewardjaabd5ad2002-04-19 15:43:37 +0000609/* These two are called from generated code, so that the %EIP/%EBP
sewardj8c824512002-04-14 04:16:48 +0000610 values that we need in order to create proper error messages are
611 picked up out of VG_(baseBlock) rather than from the thread table
612 (vg_threads in vg_scheduler.c). */
613
sewardjde4a1d02002-03-22 01:27:54 +0000614void VG_(record_value_error) ( Int size )
615{
616 ErrContext ec;
sewardjc96f9312002-04-24 20:20:22 +0000617 if (vg_ignore_errors) return;
sewardjde4a1d02002-03-22 01:27:54 +0000618 clear_ErrContext( &ec );
619 ec.count = 1;
620 ec.next = NULL;
sewardj8c824512002-04-14 04:16:48 +0000621 ec.where = VG_(get_ExeContext)( False, VG_(baseBlock)[VGOFF_(m_eip)],
622 VG_(baseBlock)[VGOFF_(m_ebp)] );
sewardjde4a1d02002-03-22 01:27:54 +0000623 ec.ekind = ValueErr;
624 ec.size = size;
sewardj1e8cdc92002-04-18 11:37:52 +0000625 ec.tid = VG_(get_current_tid)();
sewardj35805422002-04-21 13:05:34 +0000626 ec.m_eip = VG_(baseBlock)[VGOFF_(m_eip)];
627 ec.m_esp = VG_(baseBlock)[VGOFF_(m_esp)];
628 ec.m_ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
sewardjde4a1d02002-03-22 01:27:54 +0000629 VG_(maybe_add_context) ( &ec );
630}
631
632void VG_(record_address_error) ( Addr a, Int size, Bool isWrite )
633{
634 ErrContext ec;
sewardjb581a132002-05-08 00:32:50 +0000635 Bool just_below_esp;
sewardjc96f9312002-04-24 20:20:22 +0000636 if (vg_ignore_errors) return;
sewardjde4a1d02002-03-22 01:27:54 +0000637
sewardjb581a132002-05-08 00:32:50 +0000638 just_below_esp
639 = VG_(is_just_below_ESP)( VG_(baseBlock)[VGOFF_(m_esp)], a );
640
sewardjde4a1d02002-03-22 01:27:54 +0000641 /* If this is caused by an access immediately below %ESP, and the
642 user asks nicely, we just ignore it. */
sewardjb581a132002-05-08 00:32:50 +0000643 if (VG_(clo_workaround_gcc296_bugs) && just_below_esp)
sewardjde4a1d02002-03-22 01:27:54 +0000644 return;
645
646 clear_ErrContext( &ec );
647 ec.count = 1;
648 ec.next = NULL;
sewardj8c824512002-04-14 04:16:48 +0000649 ec.where = VG_(get_ExeContext)( False, VG_(baseBlock)[VGOFF_(m_eip)],
650 VG_(baseBlock)[VGOFF_(m_ebp)] );
sewardjde4a1d02002-03-22 01:27:54 +0000651 ec.ekind = AddrErr;
652 ec.axskind = isWrite ? WriteAxs : ReadAxs;
653 ec.size = size;
654 ec.addr = a;
sewardj1e8cdc92002-04-18 11:37:52 +0000655 ec.tid = VG_(get_current_tid)();
sewardj35805422002-04-21 13:05:34 +0000656 ec.m_eip = VG_(baseBlock)[VGOFF_(m_eip)];
657 ec.m_esp = VG_(baseBlock)[VGOFF_(m_esp)];
658 ec.m_ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
sewardjb581a132002-05-08 00:32:50 +0000659 ec.addrinfo.akind = Undescribed;
660 ec.addrinfo.maybe_gcc = just_below_esp;
sewardjde4a1d02002-03-22 01:27:54 +0000661 VG_(maybe_add_context) ( &ec );
662}
663
sewardjde4a1d02002-03-22 01:27:54 +0000664
sewardjaabd5ad2002-04-19 15:43:37 +0000665/* These five are called not from generated code but in response to
sewardj8c824512002-04-14 04:16:48 +0000666 requests passed back to the scheduler. So we pick up %EIP/%EBP
667 values from the stored thread state, not from VG_(baseBlock). */
668
sewardjaabd5ad2002-04-19 15:43:37 +0000669void VG_(record_free_error) ( ThreadState* tst, Addr a )
670{
671 ErrContext ec;
sewardjc96f9312002-04-24 20:20:22 +0000672 if (vg_ignore_errors) return;
sewardjaabd5ad2002-04-19 15:43:37 +0000673 clear_ErrContext( &ec );
674 ec.count = 1;
675 ec.next = NULL;
sewardj7c062c92002-05-01 21:46:38 +0000676 ec.where = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
sewardjaabd5ad2002-04-19 15:43:37 +0000677 ec.ekind = FreeErr;
678 ec.addr = a;
679 ec.tid = tst->tid;
sewardj35805422002-04-21 13:05:34 +0000680 ec.m_eip = tst->m_eip;
681 ec.m_esp = tst->m_esp;
682 ec.m_ebp = tst->m_ebp;
sewardjb581a132002-05-08 00:32:50 +0000683 ec.addrinfo.akind = Undescribed;
sewardjaabd5ad2002-04-19 15:43:37 +0000684 VG_(maybe_add_context) ( &ec );
685}
686
687void VG_(record_freemismatch_error) ( ThreadState* tst, Addr a )
688{
689 ErrContext ec;
sewardjc96f9312002-04-24 20:20:22 +0000690 if (vg_ignore_errors) return;
sewardjaabd5ad2002-04-19 15:43:37 +0000691 clear_ErrContext( &ec );
692 ec.count = 1;
693 ec.next = NULL;
sewardj7c062c92002-05-01 21:46:38 +0000694 ec.where = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
sewardjaabd5ad2002-04-19 15:43:37 +0000695 ec.ekind = FreeMismatchErr;
696 ec.addr = a;
697 ec.tid = tst->tid;
sewardj35805422002-04-21 13:05:34 +0000698 ec.m_eip = tst->m_eip;
699 ec.m_esp = tst->m_esp;
700 ec.m_ebp = tst->m_ebp;
sewardjb581a132002-05-08 00:32:50 +0000701 ec.addrinfo.akind = Undescribed;
sewardjaabd5ad2002-04-19 15:43:37 +0000702 VG_(maybe_add_context) ( &ec );
703}
704
sewardj1e8cdc92002-04-18 11:37:52 +0000705void VG_(record_jump_error) ( ThreadState* tst, Addr a )
706{
707 ErrContext ec;
sewardjc96f9312002-04-24 20:20:22 +0000708 if (vg_ignore_errors) return;
sewardj1e8cdc92002-04-18 11:37:52 +0000709 clear_ErrContext( &ec );
710 ec.count = 1;
711 ec.next = NULL;
712 ec.where = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
713 ec.ekind = AddrErr;
714 ec.axskind = ExecAxs;
715 ec.addr = a;
716 ec.tid = tst->tid;
sewardj35805422002-04-21 13:05:34 +0000717 ec.m_eip = tst->m_eip;
718 ec.m_esp = tst->m_esp;
719 ec.m_ebp = tst->m_ebp;
sewardjb581a132002-05-08 00:32:50 +0000720 ec.addrinfo.akind = Undescribed;
sewardj1e8cdc92002-04-18 11:37:52 +0000721 VG_(maybe_add_context) ( &ec );
722}
723
sewardj8c824512002-04-14 04:16:48 +0000724void VG_(record_param_err) ( ThreadState* tst, Addr a, Bool isWriteLack,
725 Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +0000726{
727 ErrContext ec;
sewardjc96f9312002-04-24 20:20:22 +0000728 if (vg_ignore_errors) return;
sewardjde4a1d02002-03-22 01:27:54 +0000729 clear_ErrContext( &ec );
730 ec.count = 1;
731 ec.next = NULL;
sewardj8c824512002-04-14 04:16:48 +0000732 ec.where = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
sewardjde4a1d02002-03-22 01:27:54 +0000733 ec.ekind = ParamErr;
734 ec.addr = a;
sewardj1e8cdc92002-04-18 11:37:52 +0000735 ec.tid = tst->tid;
sewardj35805422002-04-21 13:05:34 +0000736 ec.m_eip = tst->m_eip;
737 ec.m_esp = tst->m_esp;
738 ec.m_ebp = tst->m_ebp;
sewardjb581a132002-05-08 00:32:50 +0000739 ec.addrinfo.akind = Undescribed;
sewardjde4a1d02002-03-22 01:27:54 +0000740 ec.syscall_param = msg;
741 ec.isWriteableLack = isWriteLack;
742 VG_(maybe_add_context) ( &ec );
743}
744
sewardj8c824512002-04-14 04:16:48 +0000745void VG_(record_user_err) ( ThreadState* tst, Addr a, Bool isWriteLack )
sewardjde4a1d02002-03-22 01:27:54 +0000746{
747 ErrContext ec;
sewardjc96f9312002-04-24 20:20:22 +0000748 if (vg_ignore_errors) return;
sewardjde4a1d02002-03-22 01:27:54 +0000749 clear_ErrContext( &ec );
750 ec.count = 1;
751 ec.next = NULL;
sewardj8c824512002-04-14 04:16:48 +0000752 ec.where = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
sewardjde4a1d02002-03-22 01:27:54 +0000753 ec.ekind = UserErr;
754 ec.addr = a;
sewardj1e8cdc92002-04-18 11:37:52 +0000755 ec.tid = tst->tid;
sewardj35805422002-04-21 13:05:34 +0000756 ec.m_eip = tst->m_eip;
757 ec.m_esp = tst->m_esp;
758 ec.m_ebp = tst->m_ebp;
sewardjb581a132002-05-08 00:32:50 +0000759 ec.addrinfo.akind = Undescribed;
sewardjde4a1d02002-03-22 01:27:54 +0000760 ec.isWriteableLack = isWriteLack;
761 VG_(maybe_add_context) ( &ec );
762}
763
sewardj4dced352002-06-04 22:54:20 +0000764void VG_(record_pthread_err) ( ThreadId tid, Char* msg )
765{
766 ErrContext ec;
767 if (vg_ignore_errors) return;
768 if (!VG_(clo_instrument)) return;
769 clear_ErrContext( &ec );
770 ec.count = 1;
771 ec.next = NULL;
772 ec.where = VG_(get_ExeContext)( False, VG_(threads)[tid].m_eip,
773 VG_(threads)[tid].m_ebp );
774 ec.ekind = PThreadErr;
775 ec.tid = tid;
776 ec.syscall_param = msg;
777 ec.m_eip = VG_(threads)[tid].m_eip;
778 ec.m_esp = VG_(threads)[tid].m_esp;
779 ec.m_ebp = VG_(threads)[tid].m_ebp;
780 VG_(maybe_add_context) ( &ec );
781}
782
sewardjde4a1d02002-03-22 01:27:54 +0000783
sewardj8c824512002-04-14 04:16:48 +0000784/*------------------------------*/
785
sewardjde4a1d02002-03-22 01:27:54 +0000786void VG_(show_all_errors) ( void )
787{
788 Int i, n_min;
789 Int n_err_contexts, n_supp_contexts;
790 ErrContext *p, *p_min;
791 Suppression *su;
792 Bool any_supp;
793
794 if (VG_(clo_verbosity) == 0)
795 return;
796
797 n_err_contexts = 0;
798 for (p = vg_err_contexts; p != NULL; p = p->next) {
799 if (p->supp == NULL)
800 n_err_contexts++;
801 }
802
803 n_supp_contexts = 0;
804 for (su = vg_suppressions; su != NULL; su = su->next) {
805 if (su->count > 0)
806 n_supp_contexts++;
807 }
808
809 VG_(message)(Vg_UserMsg,
810 "ERROR SUMMARY: "
811 "%d errors from %d contexts (suppressed: %d from %d)",
812 vg_n_errs_found, n_err_contexts,
813 vg_n_errs_suppressed, n_supp_contexts );
814
815 if (VG_(clo_verbosity) <= 1)
816 return;
817
818 /* Print the contexts in order of increasing error count. */
819 for (i = 0; i < n_err_contexts; i++) {
820 n_min = (1 << 30) - 1;
821 p_min = NULL;
822 for (p = vg_err_contexts; p != NULL; p = p->next) {
823 if (p->supp != NULL) continue;
824 if (p->count < n_min) {
825 n_min = p->count;
826 p_min = p;
827 }
828 }
829 if (p_min == NULL) VG_(panic)("pp_AllErrContexts");
830
831 VG_(message)(Vg_UserMsg, "");
832 VG_(message)(Vg_UserMsg, "%d errors in context %d of %d:",
833 p_min->count,
834 i+1, n_err_contexts);
835 pp_ErrContext( p_min, False );
836
837 if ((i+1 == VG_(clo_dump_error))) {
sewardj1e8cdc92002-04-18 11:37:52 +0000838 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to below NULLs */,
839 p_min->where->eips[0], NULL, NULL, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000840 }
841
842 p_min->count = 1 << 30;
843 }
844
845 if (n_supp_contexts > 0)
846 VG_(message)(Vg_DebugMsg, "");
847 any_supp = False;
848 for (su = vg_suppressions; su != NULL; su = su->next) {
849 if (su->count > 0) {
850 any_supp = True;
851 VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count,
852 su->sname);
853 }
854 }
855
856 if (n_err_contexts > 0) {
857 if (any_supp)
858 VG_(message)(Vg_UserMsg, "");
859 VG_(message)(Vg_UserMsg,
860 "IN SUMMARY: "
861 "%d errors from %d contexts (suppressed: %d from %d)",
862 vg_n_errs_found, n_err_contexts,
863 vg_n_errs_suppressed,
864 n_supp_contexts );
865 VG_(message)(Vg_UserMsg, "");
866 }
867}
868
869/*------------------------------------------------------------*/
870/*--- Standard suppressions ---*/
871/*------------------------------------------------------------*/
872
873/* Get a non-blank, non-comment line of at most nBuf chars from fd.
874 Skips leading spaces on the line. Return True if EOF was hit instead.
875*/
876
877#define VG_ISSPACE(ch) (((ch)==' ') || ((ch)=='\n') || ((ch)=='\t'))
878
879static Bool getLine ( Int fd, Char* buf, Int nBuf )
880{
881 Char ch;
882 Int n, i;
883 while (True) {
884 /* First, read until a non-blank char appears. */
885 while (True) {
886 n = VG_(read)(fd, &ch, 1);
887 if (n == 1 && !VG_ISSPACE(ch)) break;
888 if (n == 0) return True;
889 }
890
891 /* Now, read the line into buf. */
892 i = 0;
893 buf[i++] = ch; buf[i] = 0;
894 while (True) {
895 n = VG_(read)(fd, &ch, 1);
896 if (n == 0) return False; /* the next call will return True */
897 if (ch == '\n') break;
898 if (i > 0 && i == nBuf-1) i--;
899 buf[i++] = ch; buf[i] = 0;
900 }
901 while (i > 1 && VG_ISSPACE(buf[i-1])) {
902 i--; buf[i] = 0;
903 };
904
905 /* VG_(printf)("The line is `%s'\n", buf); */
906 /* Ok, we have a line. If a non-comment line, return.
907 If a comment line, start all over again. */
908 if (buf[0] != '#') return False;
909 }
910}
911
912
913/* *p_caller contains the raw name of a caller, supposedly either
914 fun:some_function_name or
915 obj:some_object_name.
916 Set *p_ty accordingly and advance *p_caller over the descriptor
917 (fun: or obj:) part.
918 Returns False if failed.
919*/
920static Bool setLocationTy ( Char** p_caller, SuppressionLocTy* p_ty )
921{
922 if (VG_(strncmp)(*p_caller, "fun:", 4) == 0) {
923 (*p_caller) += 4;
924 *p_ty = FunName;
925 return True;
926 }
927 if (VG_(strncmp)(*p_caller, "obj:", 4) == 0) {
928 (*p_caller) += 4;
929 *p_ty = ObjName;
930 return True;
931 }
932 VG_(printf)("location should start with fun: or obj:\n");
933 return False;
934}
935
936
937/* Read suppressions from the file specified in vg_clo_suppressions
938 and place them in the suppressions list. If there's any difficulty
939 doing this, just give up -- there's no point in trying to recover.
940*/
941#define STREQ(s1,s2) (s1 != NULL && s2 != NULL \
942 && VG_(strcmp)((s1),(s2))==0)
943
944static Char* copyStr ( Char* str )
945{
946 Int n, i;
947 Char* str2;
948 n = VG_(strlen)(str);
949 str2 = VG_(malloc)(VG_AR_PRIVATE, n+1);
950 vg_assert(n > 0);
951 for (i = 0; i < n+1; i++) str2[i] = str[i];
952 return str2;
953}
954
955static void load_one_suppressions_file ( Char* filename )
956{
957# define N_BUF 200
958 Int fd;
959 Bool eof;
960 Char buf[N_BUF+1];
961 fd = VG_(open_read)( filename );
962 if (fd == -1) {
963 VG_(message)(Vg_UserMsg,
964 "FATAL: can't open suppressions file `%s'",
965 filename );
966 VG_(exit)(1);
967 }
968
969 while (True) {
970 Suppression* supp;
971 supp = VG_(malloc)(VG_AR_PRIVATE, sizeof(Suppression));
972 supp->count = 0;
973 supp->param = supp->caller0 = supp->caller1
974 = supp->caller2 = supp->caller3 = NULL;
975
976 eof = getLine ( fd, buf, N_BUF );
977 if (eof) break;
978
979 if (!STREQ(buf, "{")) goto syntax_error;
980
981 eof = getLine ( fd, buf, N_BUF );
982 if (eof || STREQ(buf, "}")) goto syntax_error;
983 supp->sname = copyStr(buf);
984
985 eof = getLine ( fd, buf, N_BUF );
986 if (eof) goto syntax_error;
987 else if (STREQ(buf, "Param")) supp->skind = Param;
sewardja7dc7952002-03-24 11:29:13 +0000988 else if (STREQ(buf, "Value0")) supp->skind = Value0; /* backwards compat */
989 else if (STREQ(buf, "Cond")) supp->skind = Value0;
sewardjde4a1d02002-03-22 01:27:54 +0000990 else if (STREQ(buf, "Value1")) supp->skind = Value1;
991 else if (STREQ(buf, "Value2")) supp->skind = Value2;
992 else if (STREQ(buf, "Value4")) supp->skind = Value4;
993 else if (STREQ(buf, "Value8")) supp->skind = Value8;
994 else if (STREQ(buf, "Addr1")) supp->skind = Addr1;
995 else if (STREQ(buf, "Addr2")) supp->skind = Addr2;
996 else if (STREQ(buf, "Addr4")) supp->skind = Addr4;
997 else if (STREQ(buf, "Addr8")) supp->skind = Addr8;
998 else if (STREQ(buf, "Free")) supp->skind = FreeS;
sewardj4dced352002-06-04 22:54:20 +0000999 else if (STREQ(buf, "PThread")) supp->skind = PThread;
sewardjde4a1d02002-03-22 01:27:54 +00001000 else goto syntax_error;
1001
1002 if (supp->skind == Param) {
1003 eof = getLine ( fd, buf, N_BUF );
1004 if (eof) goto syntax_error;
1005 supp->param = copyStr(buf);
1006 }
1007
1008 eof = getLine ( fd, buf, N_BUF );
1009 if (eof) goto syntax_error;
1010 supp->caller0 = copyStr(buf);
1011 if (!setLocationTy(&(supp->caller0), &(supp->caller0_ty)))
1012 goto syntax_error;
1013
1014 eof = getLine ( fd, buf, N_BUF );
1015 if (eof) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +00001016 if (!STREQ(buf, "}")) {
sewardj0873c942002-03-24 09:45:26 +00001017 supp->caller1 = copyStr(buf);
1018 if (!setLocationTy(&(supp->caller1), &(supp->caller1_ty)))
sewardjde4a1d02002-03-22 01:27:54 +00001019 goto syntax_error;
sewardj0873c942002-03-24 09:45:26 +00001020
sewardjde4a1d02002-03-22 01:27:54 +00001021 eof = getLine ( fd, buf, N_BUF );
1022 if (eof) goto syntax_error;
1023 if (!STREQ(buf, "}")) {
sewardj0873c942002-03-24 09:45:26 +00001024 supp->caller2 = copyStr(buf);
1025 if (!setLocationTy(&(supp->caller2), &(supp->caller2_ty)))
sewardjde4a1d02002-03-22 01:27:54 +00001026 goto syntax_error;
sewardj0873c942002-03-24 09:45:26 +00001027
sewardjde4a1d02002-03-22 01:27:54 +00001028 eof = getLine ( fd, buf, N_BUF );
sewardj0873c942002-03-24 09:45:26 +00001029 if (eof) goto syntax_error;
1030 if (!STREQ(buf, "}")) {
1031 supp->caller3 = copyStr(buf);
1032 if (!setLocationTy(&(supp->caller3), &(supp->caller3_ty)))
1033 goto syntax_error;
1034
1035 eof = getLine ( fd, buf, N_BUF );
1036 if (eof || !STREQ(buf, "}")) goto syntax_error;
1037 }
sewardjde4a1d02002-03-22 01:27:54 +00001038 }
1039 }
1040
1041 supp->next = vg_suppressions;
1042 vg_suppressions = supp;
1043 }
1044
1045 VG_(close)(fd);
1046 return;
1047
1048 syntax_error:
1049 if (eof) {
1050 VG_(message)(Vg_UserMsg,
1051 "FATAL: in suppressions file `%s': unexpected EOF",
1052 filename );
1053 } else {
1054 VG_(message)(Vg_UserMsg,
1055 "FATAL: in suppressions file `%s': syntax error on: %s",
1056 filename, buf );
1057 }
1058 VG_(close)(fd);
1059 VG_(message)(Vg_UserMsg, "exiting now.");
1060 VG_(exit)(1);
1061
1062# undef N_BUF
1063}
1064
1065
1066void VG_(load_suppressions) ( void )
1067{
1068 Int i;
1069 vg_suppressions = NULL;
1070 for (i = 0; i < VG_(clo_n_suppressions); i++) {
1071 if (VG_(clo_verbosity) > 1) {
1072 VG_(message)(Vg_UserMsg, "Reading suppressions file: %s",
1073 VG_(clo_suppressions)[i] );
1074 }
1075 load_one_suppressions_file( VG_(clo_suppressions)[i] );
1076 }
1077}
1078
1079
1080/* Does an error context match a suppression? ie is this a
1081 suppressible error? If so, return a pointer to the Suppression
1082 record, otherwise NULL.
1083 Tries to minimise the number of calls to what_fn_is_this since they
1084 are expensive.
1085*/
1086static Suppression* is_suppressible_error ( ErrContext* ec )
1087{
1088# define STREQ(s1,s2) (s1 != NULL && s2 != NULL \
1089 && VG_(strcmp)((s1),(s2))==0)
1090
1091 Char caller0_obj[M_VG_ERRTXT];
1092 Char caller0_fun[M_VG_ERRTXT];
1093 Char caller1_obj[M_VG_ERRTXT];
1094 Char caller1_fun[M_VG_ERRTXT];
1095 Char caller2_obj[M_VG_ERRTXT];
1096 Char caller2_fun[M_VG_ERRTXT];
1097 Char caller3_obj[M_VG_ERRTXT];
1098 Char caller3_fun[M_VG_ERRTXT];
1099
1100 Suppression* su;
1101 Int su_size;
1102
1103 /* vg_what_fn_or_object_is_this returns:
1104 <function_name> or
1105 <object_name> or
1106 ???
1107 so the strings in the suppression file should match these.
1108 */
1109
1110 /* Initialise these strs so they are always safe to compare, even
1111 if what_fn_or_object_is_this doesn't write anything to them. */
1112 caller0_obj[0] = caller1_obj[0] = caller2_obj[0] = caller3_obj[0] = 0;
1113 caller0_fun[0] = caller1_fun[0] = caller2_obj[0] = caller3_obj[0] = 0;
1114
1115 VG_(what_obj_and_fun_is_this)
1116 ( ec->where->eips[0], caller0_obj, M_VG_ERRTXT,
1117 caller0_fun, M_VG_ERRTXT );
1118 VG_(what_obj_and_fun_is_this)
1119 ( ec->where->eips[1], caller1_obj, M_VG_ERRTXT,
1120 caller1_fun, M_VG_ERRTXT );
1121
1122 if (VG_(clo_backtrace_size) > 2) {
1123 VG_(what_obj_and_fun_is_this)
1124 ( ec->where->eips[2], caller2_obj, M_VG_ERRTXT,
1125 caller2_fun, M_VG_ERRTXT );
1126
1127 if (VG_(clo_backtrace_size) > 3) {
1128 VG_(what_obj_and_fun_is_this)
1129 ( ec->where->eips[3], caller3_obj, M_VG_ERRTXT,
1130 caller3_fun, M_VG_ERRTXT );
1131 }
1132 }
1133
1134 /* See if the error context matches any suppression. */
1135 for (su = vg_suppressions; su != NULL; su = su->next) {
1136 switch (su->skind) {
sewardj4dced352002-06-04 22:54:20 +00001137 case FreeS: case PThread:
sewardjde4a1d02002-03-22 01:27:54 +00001138 case Param: case Value0: su_size = 0; break;
1139 case Value1: case Addr1: su_size = 1; break;
1140 case Value2: case Addr2: su_size = 2; break;
1141 case Value4: case Addr4: su_size = 4; break;
1142 case Value8: case Addr8: su_size = 8; break;
1143 default: VG_(panic)("errcontext_matches_suppression");
1144 }
1145 switch (su->skind) {
1146 case Param:
1147 if (ec->ekind != ParamErr) continue;
1148 if (!STREQ(su->param, ec->syscall_param)) continue;
1149 break;
1150 case Value0: case Value1: case Value2: case Value4: case Value8:
1151 if (ec->ekind != ValueErr) continue;
1152 if (ec->size != su_size) continue;
1153 break;
1154 case Addr1: case Addr2: case Addr4: case Addr8:
1155 if (ec->ekind != AddrErr) continue;
1156 if (ec->size != su_size) continue;
1157 break;
1158 case FreeS:
sewardj4dced352002-06-04 22:54:20 +00001159 if (ec->ekind != FreeErr
1160 && ec->ekind != FreeMismatchErr) continue;
1161 break;
1162 case PThread:
1163 if (ec->ekind != PThreadErr) continue;
sewardjde4a1d02002-03-22 01:27:54 +00001164 break;
1165 }
1166
1167 switch (su->caller0_ty) {
1168 case ObjName: if (!VG_(stringMatch)(su->caller0,
1169 caller0_obj)) continue;
1170 break;
1171 case FunName: if (!VG_(stringMatch)(su->caller0,
1172 caller0_fun)) continue;
1173 break;
1174 default: goto baaaad;
1175 }
1176
sewardj0873c942002-03-24 09:45:26 +00001177 if (su->caller1 != NULL) {
1178 vg_assert(VG_(clo_backtrace_size) >= 2);
1179 switch (su->caller1_ty) {
1180 case ObjName: if (!VG_(stringMatch)(su->caller1,
1181 caller1_obj)) continue;
1182 break;
1183 case FunName: if (!VG_(stringMatch)(su->caller1,
1184 caller1_fun)) continue;
1185 break;
1186 default: goto baaaad;
1187 }
sewardjde4a1d02002-03-22 01:27:54 +00001188 }
1189
1190 if (VG_(clo_backtrace_size) > 2 && su->caller2 != NULL) {
1191 switch (su->caller2_ty) {
1192 case ObjName: if (!VG_(stringMatch)(su->caller2,
1193 caller2_obj)) continue;
1194 break;
1195 case FunName: if (!VG_(stringMatch)(su->caller2,
1196 caller2_fun)) continue;
1197 break;
1198 default: goto baaaad;
1199 }
1200 }
1201
1202 if (VG_(clo_backtrace_size) > 3 && su->caller3 != NULL) {
1203 switch (su->caller3_ty) {
1204 case ObjName: if (!VG_(stringMatch)(su->caller3,
1205 caller3_obj)) continue;
1206 break;
1207 case FunName: if (!VG_(stringMatch)(su->caller3,
1208 caller3_fun)) continue;
1209 break;
1210 default: goto baaaad;
1211 }
1212 }
1213
1214 return su;
1215 }
1216
1217 return NULL;
1218
1219 baaaad:
1220 VG_(panic)("is_suppressible_error");
1221
1222# undef STREQ
1223}
1224
1225/*--------------------------------------------------------------------*/
1226/*--- end vg_errcontext.c ---*/
1227/*--------------------------------------------------------------------*/