blob: 60eaba05e2dbb01024c64bb7078fc5060e7ab073 [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. */
sewardj72f98ff2002-06-13 17:23:38 +0000500 if (VG_(clo_event_horizon)
501 && (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN
502 || vg_n_errs_found >= M_VG_COLLECT_NO_ERRORS_AFTER_FOUND)) {
sewardjde4a1d02002-03-22 01:27:54 +0000503 if (!stopping_message) {
504 VG_(message)(Vg_UserMsg, "");
sewardjf2537be2002-04-24 21:03:47 +0000505
506 if (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN) {
507 VG_(message)(Vg_UserMsg,
508 "More than %d different errors detected. "
509 "I'm not reporting any more.",
510 M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN );
511 } else {
512 VG_(message)(Vg_UserMsg,
513 "More than %d total errors detected. "
514 "I'm not reporting any more.",
515 M_VG_COLLECT_NO_ERRORS_AFTER_FOUND );
516 }
517
sewardjde4a1d02002-03-22 01:27:54 +0000518 VG_(message)(Vg_UserMsg,
sewardjf2537be2002-04-24 21:03:47 +0000519 "Final error counts will be inaccurate. Go fix your program!");
sewardj72f98ff2002-06-13 17:23:38 +0000520 VG_(message)(Vg_UserMsg,
521 "Rerun with --event-horizon=no to disable this cutoff. Note");
522 VG_(message)(Vg_UserMsg,
523 "that your program may now segfault without prior warning from");
524 VG_(message)(Vg_UserMsg,
525 "Valgrind, because errors are no longer being displayed.");
sewardjde4a1d02002-03-22 01:27:54 +0000526 VG_(message)(Vg_UserMsg, "");
527 stopping_message = True;
sewardjc96f9312002-04-24 20:20:22 +0000528 vg_ignore_errors = True;
sewardjde4a1d02002-03-22 01:27:54 +0000529 }
530 return;
531 }
532
533 /* After M_VG_COLLECT_ERRORS_SLOWLY_AFTER different errors have
534 been found, be much more conservative about collecting new
535 ones. */
536 if (vg_n_errs_shown >= M_VG_COLLECT_ERRORS_SLOWLY_AFTER) {
537 cheap_addr_cmp = True;
538 if (!slowdown_message) {
539 VG_(message)(Vg_UserMsg, "");
540 VG_(message)(Vg_UserMsg,
541 "More than %d errors detected. Subsequent errors",
542 M_VG_COLLECT_ERRORS_SLOWLY_AFTER);
543 VG_(message)(Vg_UserMsg,
544 "will still be recorded, but in less detail than before.");
545 slowdown_message = True;
546 }
547 }
548
549
550 /* First, see if we've got an error record matching this one. */
551 p = vg_err_contexts;
552 p_prev = NULL;
553 while (p != NULL) {
554 if (eq_ErrContext(cheap_addr_cmp, p, ec)) {
555 /* Found it. */
556 p->count++;
557 if (p->supp != NULL) {
558 /* Deal correctly with suppressed errors. */
559 p->supp->count++;
560 vg_n_errs_suppressed++;
561 } else {
562 vg_n_errs_found++;
563 }
564
565 /* Move p to the front of the list so that future searches
566 for it are faster. */
567 if (p_prev != NULL) {
568 vg_assert(p_prev->next == p);
569 p_prev->next = p->next;
570 p->next = vg_err_contexts;
571 vg_err_contexts = p;
572 }
573 return;
574 }
575 p_prev = p;
576 p = p->next;
577 }
578
579 /* Didn't see it. Copy and add. */
580
sewardjb581a132002-05-08 00:32:50 +0000581 /* OK, we're really going to collect it. First, describe any addr
582 info in the error. */
583 if (ec->addrinfo.akind == Undescribed)
584 VG_(describe_addr) ( ec->addr, &ec->addrinfo );
sewardjde4a1d02002-03-22 01:27:54 +0000585
586 p = VG_(malloc)(VG_AR_ERRCTXT, sizeof(ErrContext));
587 *p = *ec;
588 p->next = vg_err_contexts;
589 p->supp = is_suppressible_error(ec);
590 vg_err_contexts = p;
591 if (p->supp == NULL) {
592 vg_n_errs_found++;
593 if (!is_first_shown_context)
594 VG_(message)(Vg_UserMsg, "");
595 pp_ErrContext(p, False);
596 is_first_shown_context = False;
597 vg_n_errs_shown++;
598 /* Perhaps we want a GDB attach at this point? */
599 if (vg_is_GDB_attach_requested()) {
sewardj35805422002-04-21 13:05:34 +0000600 VG_(swizzle_esp_then_start_GDB)(
601 ec->m_eip, ec->m_esp, ec->m_ebp);
sewardjde4a1d02002-03-22 01:27:54 +0000602 }
603 } else {
604 vg_n_errs_suppressed++;
605 p->supp->count++;
606 }
607}
608
609
610
611
612/*------------------------------------------------------------*/
613/*--- Exported fns ---*/
614/*------------------------------------------------------------*/
615
sewardjaabd5ad2002-04-19 15:43:37 +0000616/* These two are called from generated code, so that the %EIP/%EBP
sewardj8c824512002-04-14 04:16:48 +0000617 values that we need in order to create proper error messages are
618 picked up out of VG_(baseBlock) rather than from the thread table
619 (vg_threads in vg_scheduler.c). */
620
sewardjde4a1d02002-03-22 01:27:54 +0000621void VG_(record_value_error) ( Int size )
622{
623 ErrContext ec;
sewardjc96f9312002-04-24 20:20:22 +0000624 if (vg_ignore_errors) return;
sewardjde4a1d02002-03-22 01:27:54 +0000625 clear_ErrContext( &ec );
626 ec.count = 1;
627 ec.next = NULL;
sewardj8c824512002-04-14 04:16:48 +0000628 ec.where = VG_(get_ExeContext)( False, VG_(baseBlock)[VGOFF_(m_eip)],
629 VG_(baseBlock)[VGOFF_(m_ebp)] );
sewardjde4a1d02002-03-22 01:27:54 +0000630 ec.ekind = ValueErr;
631 ec.size = size;
sewardj1e8cdc92002-04-18 11:37:52 +0000632 ec.tid = VG_(get_current_tid)();
sewardj35805422002-04-21 13:05:34 +0000633 ec.m_eip = VG_(baseBlock)[VGOFF_(m_eip)];
634 ec.m_esp = VG_(baseBlock)[VGOFF_(m_esp)];
635 ec.m_ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
sewardjde4a1d02002-03-22 01:27:54 +0000636 VG_(maybe_add_context) ( &ec );
637}
638
639void VG_(record_address_error) ( Addr a, Int size, Bool isWrite )
640{
641 ErrContext ec;
sewardjb581a132002-05-08 00:32:50 +0000642 Bool just_below_esp;
sewardjc96f9312002-04-24 20:20:22 +0000643 if (vg_ignore_errors) return;
sewardjde4a1d02002-03-22 01:27:54 +0000644
sewardjb581a132002-05-08 00:32:50 +0000645 just_below_esp
646 = VG_(is_just_below_ESP)( VG_(baseBlock)[VGOFF_(m_esp)], a );
647
sewardjde4a1d02002-03-22 01:27:54 +0000648 /* If this is caused by an access immediately below %ESP, and the
649 user asks nicely, we just ignore it. */
sewardjb581a132002-05-08 00:32:50 +0000650 if (VG_(clo_workaround_gcc296_bugs) && just_below_esp)
sewardjde4a1d02002-03-22 01:27:54 +0000651 return;
652
653 clear_ErrContext( &ec );
654 ec.count = 1;
655 ec.next = NULL;
sewardj8c824512002-04-14 04:16:48 +0000656 ec.where = VG_(get_ExeContext)( False, VG_(baseBlock)[VGOFF_(m_eip)],
657 VG_(baseBlock)[VGOFF_(m_ebp)] );
sewardjde4a1d02002-03-22 01:27:54 +0000658 ec.ekind = AddrErr;
659 ec.axskind = isWrite ? WriteAxs : ReadAxs;
660 ec.size = size;
661 ec.addr = a;
sewardj1e8cdc92002-04-18 11:37:52 +0000662 ec.tid = VG_(get_current_tid)();
sewardj35805422002-04-21 13:05:34 +0000663 ec.m_eip = VG_(baseBlock)[VGOFF_(m_eip)];
664 ec.m_esp = VG_(baseBlock)[VGOFF_(m_esp)];
665 ec.m_ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
sewardjb581a132002-05-08 00:32:50 +0000666 ec.addrinfo.akind = Undescribed;
667 ec.addrinfo.maybe_gcc = just_below_esp;
sewardjde4a1d02002-03-22 01:27:54 +0000668 VG_(maybe_add_context) ( &ec );
669}
670
sewardjde4a1d02002-03-22 01:27:54 +0000671
sewardjaabd5ad2002-04-19 15:43:37 +0000672/* These five are called not from generated code but in response to
sewardj8c824512002-04-14 04:16:48 +0000673 requests passed back to the scheduler. So we pick up %EIP/%EBP
674 values from the stored thread state, not from VG_(baseBlock). */
675
sewardjaabd5ad2002-04-19 15:43:37 +0000676void VG_(record_free_error) ( ThreadState* tst, Addr a )
677{
678 ErrContext ec;
sewardjc96f9312002-04-24 20:20:22 +0000679 if (vg_ignore_errors) return;
sewardjaabd5ad2002-04-19 15:43:37 +0000680 clear_ErrContext( &ec );
681 ec.count = 1;
682 ec.next = NULL;
sewardj7c062c92002-05-01 21:46:38 +0000683 ec.where = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
sewardjaabd5ad2002-04-19 15:43:37 +0000684 ec.ekind = FreeErr;
685 ec.addr = a;
686 ec.tid = tst->tid;
sewardj35805422002-04-21 13:05:34 +0000687 ec.m_eip = tst->m_eip;
688 ec.m_esp = tst->m_esp;
689 ec.m_ebp = tst->m_ebp;
sewardjb581a132002-05-08 00:32:50 +0000690 ec.addrinfo.akind = Undescribed;
sewardjaabd5ad2002-04-19 15:43:37 +0000691 VG_(maybe_add_context) ( &ec );
692}
693
694void VG_(record_freemismatch_error) ( ThreadState* tst, Addr a )
695{
696 ErrContext ec;
sewardjc96f9312002-04-24 20:20:22 +0000697 if (vg_ignore_errors) return;
sewardjaabd5ad2002-04-19 15:43:37 +0000698 clear_ErrContext( &ec );
699 ec.count = 1;
700 ec.next = NULL;
sewardj7c062c92002-05-01 21:46:38 +0000701 ec.where = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
sewardjaabd5ad2002-04-19 15:43:37 +0000702 ec.ekind = FreeMismatchErr;
703 ec.addr = a;
704 ec.tid = tst->tid;
sewardj35805422002-04-21 13:05:34 +0000705 ec.m_eip = tst->m_eip;
706 ec.m_esp = tst->m_esp;
707 ec.m_ebp = tst->m_ebp;
sewardjb581a132002-05-08 00:32:50 +0000708 ec.addrinfo.akind = Undescribed;
sewardjaabd5ad2002-04-19 15:43:37 +0000709 VG_(maybe_add_context) ( &ec );
710}
711
sewardj1e8cdc92002-04-18 11:37:52 +0000712void VG_(record_jump_error) ( ThreadState* tst, Addr a )
713{
714 ErrContext ec;
sewardjc96f9312002-04-24 20:20:22 +0000715 if (vg_ignore_errors) return;
sewardj1e8cdc92002-04-18 11:37:52 +0000716 clear_ErrContext( &ec );
717 ec.count = 1;
718 ec.next = NULL;
719 ec.where = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
720 ec.ekind = AddrErr;
721 ec.axskind = ExecAxs;
722 ec.addr = a;
723 ec.tid = tst->tid;
sewardj35805422002-04-21 13:05:34 +0000724 ec.m_eip = tst->m_eip;
725 ec.m_esp = tst->m_esp;
726 ec.m_ebp = tst->m_ebp;
sewardjb581a132002-05-08 00:32:50 +0000727 ec.addrinfo.akind = Undescribed;
sewardj1e8cdc92002-04-18 11:37:52 +0000728 VG_(maybe_add_context) ( &ec );
729}
730
sewardj8c824512002-04-14 04:16:48 +0000731void VG_(record_param_err) ( ThreadState* tst, Addr a, Bool isWriteLack,
732 Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +0000733{
734 ErrContext ec;
sewardjc96f9312002-04-24 20:20:22 +0000735 if (vg_ignore_errors) return;
sewardjde4a1d02002-03-22 01:27:54 +0000736 clear_ErrContext( &ec );
737 ec.count = 1;
738 ec.next = NULL;
sewardj8c824512002-04-14 04:16:48 +0000739 ec.where = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
sewardjde4a1d02002-03-22 01:27:54 +0000740 ec.ekind = ParamErr;
741 ec.addr = a;
sewardj1e8cdc92002-04-18 11:37:52 +0000742 ec.tid = tst->tid;
sewardj35805422002-04-21 13:05:34 +0000743 ec.m_eip = tst->m_eip;
744 ec.m_esp = tst->m_esp;
745 ec.m_ebp = tst->m_ebp;
sewardjb581a132002-05-08 00:32:50 +0000746 ec.addrinfo.akind = Undescribed;
sewardjde4a1d02002-03-22 01:27:54 +0000747 ec.syscall_param = msg;
748 ec.isWriteableLack = isWriteLack;
749 VG_(maybe_add_context) ( &ec );
750}
751
sewardj8c824512002-04-14 04:16:48 +0000752void VG_(record_user_err) ( ThreadState* tst, Addr a, Bool isWriteLack )
sewardjde4a1d02002-03-22 01:27:54 +0000753{
754 ErrContext ec;
sewardjc96f9312002-04-24 20:20:22 +0000755 if (vg_ignore_errors) return;
sewardjde4a1d02002-03-22 01:27:54 +0000756 clear_ErrContext( &ec );
757 ec.count = 1;
758 ec.next = NULL;
sewardj8c824512002-04-14 04:16:48 +0000759 ec.where = VG_(get_ExeContext)( False, tst->m_eip, tst->m_ebp );
sewardjde4a1d02002-03-22 01:27:54 +0000760 ec.ekind = UserErr;
761 ec.addr = a;
sewardj1e8cdc92002-04-18 11:37:52 +0000762 ec.tid = tst->tid;
sewardj35805422002-04-21 13:05:34 +0000763 ec.m_eip = tst->m_eip;
764 ec.m_esp = tst->m_esp;
765 ec.m_ebp = tst->m_ebp;
sewardjb581a132002-05-08 00:32:50 +0000766 ec.addrinfo.akind = Undescribed;
sewardjde4a1d02002-03-22 01:27:54 +0000767 ec.isWriteableLack = isWriteLack;
768 VG_(maybe_add_context) ( &ec );
769}
770
sewardj4dced352002-06-04 22:54:20 +0000771void VG_(record_pthread_err) ( ThreadId tid, Char* msg )
772{
773 ErrContext ec;
774 if (vg_ignore_errors) return;
775 if (!VG_(clo_instrument)) return;
776 clear_ErrContext( &ec );
777 ec.count = 1;
778 ec.next = NULL;
779 ec.where = VG_(get_ExeContext)( False, VG_(threads)[tid].m_eip,
780 VG_(threads)[tid].m_ebp );
781 ec.ekind = PThreadErr;
782 ec.tid = tid;
783 ec.syscall_param = msg;
784 ec.m_eip = VG_(threads)[tid].m_eip;
785 ec.m_esp = VG_(threads)[tid].m_esp;
786 ec.m_ebp = VG_(threads)[tid].m_ebp;
787 VG_(maybe_add_context) ( &ec );
788}
789
sewardjde4a1d02002-03-22 01:27:54 +0000790
sewardj8c824512002-04-14 04:16:48 +0000791/*------------------------------*/
792
sewardjde4a1d02002-03-22 01:27:54 +0000793void VG_(show_all_errors) ( void )
794{
795 Int i, n_min;
796 Int n_err_contexts, n_supp_contexts;
797 ErrContext *p, *p_min;
798 Suppression *su;
799 Bool any_supp;
800
801 if (VG_(clo_verbosity) == 0)
802 return;
803
804 n_err_contexts = 0;
805 for (p = vg_err_contexts; p != NULL; p = p->next) {
806 if (p->supp == NULL)
807 n_err_contexts++;
808 }
809
810 n_supp_contexts = 0;
811 for (su = vg_suppressions; su != NULL; su = su->next) {
812 if (su->count > 0)
813 n_supp_contexts++;
814 }
815
816 VG_(message)(Vg_UserMsg,
817 "ERROR SUMMARY: "
818 "%d errors from %d contexts (suppressed: %d from %d)",
819 vg_n_errs_found, n_err_contexts,
820 vg_n_errs_suppressed, n_supp_contexts );
821
822 if (VG_(clo_verbosity) <= 1)
823 return;
824
825 /* Print the contexts in order of increasing error count. */
826 for (i = 0; i < n_err_contexts; i++) {
827 n_min = (1 << 30) - 1;
828 p_min = NULL;
829 for (p = vg_err_contexts; p != NULL; p = p->next) {
830 if (p->supp != NULL) continue;
831 if (p->count < n_min) {
832 n_min = p->count;
833 p_min = p;
834 }
835 }
836 if (p_min == NULL) VG_(panic)("pp_AllErrContexts");
837
838 VG_(message)(Vg_UserMsg, "");
839 VG_(message)(Vg_UserMsg, "%d errors in context %d of %d:",
840 p_min->count,
841 i+1, n_err_contexts);
842 pp_ErrContext( p_min, False );
843
844 if ((i+1 == VG_(clo_dump_error))) {
sewardj1e8cdc92002-04-18 11:37:52 +0000845 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to below NULLs */,
846 p_min->where->eips[0], NULL, NULL, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000847 }
848
849 p_min->count = 1 << 30;
850 }
851
852 if (n_supp_contexts > 0)
853 VG_(message)(Vg_DebugMsg, "");
854 any_supp = False;
855 for (su = vg_suppressions; su != NULL; su = su->next) {
856 if (su->count > 0) {
857 any_supp = True;
858 VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count,
859 su->sname);
860 }
861 }
862
863 if (n_err_contexts > 0) {
864 if (any_supp)
865 VG_(message)(Vg_UserMsg, "");
866 VG_(message)(Vg_UserMsg,
867 "IN SUMMARY: "
868 "%d errors from %d contexts (suppressed: %d from %d)",
869 vg_n_errs_found, n_err_contexts,
870 vg_n_errs_suppressed,
871 n_supp_contexts );
872 VG_(message)(Vg_UserMsg, "");
873 }
874}
875
876/*------------------------------------------------------------*/
877/*--- Standard suppressions ---*/
878/*------------------------------------------------------------*/
879
880/* Get a non-blank, non-comment line of at most nBuf chars from fd.
881 Skips leading spaces on the line. Return True if EOF was hit instead.
882*/
883
884#define VG_ISSPACE(ch) (((ch)==' ') || ((ch)=='\n') || ((ch)=='\t'))
885
886static Bool getLine ( Int fd, Char* buf, Int nBuf )
887{
888 Char ch;
889 Int n, i;
890 while (True) {
891 /* First, read until a non-blank char appears. */
892 while (True) {
893 n = VG_(read)(fd, &ch, 1);
894 if (n == 1 && !VG_ISSPACE(ch)) break;
895 if (n == 0) return True;
896 }
897
898 /* Now, read the line into buf. */
899 i = 0;
900 buf[i++] = ch; buf[i] = 0;
901 while (True) {
902 n = VG_(read)(fd, &ch, 1);
903 if (n == 0) return False; /* the next call will return True */
904 if (ch == '\n') break;
905 if (i > 0 && i == nBuf-1) i--;
906 buf[i++] = ch; buf[i] = 0;
907 }
908 while (i > 1 && VG_ISSPACE(buf[i-1])) {
909 i--; buf[i] = 0;
910 };
911
912 /* VG_(printf)("The line is `%s'\n", buf); */
913 /* Ok, we have a line. If a non-comment line, return.
914 If a comment line, start all over again. */
915 if (buf[0] != '#') return False;
916 }
917}
918
919
920/* *p_caller contains the raw name of a caller, supposedly either
921 fun:some_function_name or
922 obj:some_object_name.
923 Set *p_ty accordingly and advance *p_caller over the descriptor
924 (fun: or obj:) part.
925 Returns False if failed.
926*/
927static Bool setLocationTy ( Char** p_caller, SuppressionLocTy* p_ty )
928{
929 if (VG_(strncmp)(*p_caller, "fun:", 4) == 0) {
930 (*p_caller) += 4;
931 *p_ty = FunName;
932 return True;
933 }
934 if (VG_(strncmp)(*p_caller, "obj:", 4) == 0) {
935 (*p_caller) += 4;
936 *p_ty = ObjName;
937 return True;
938 }
939 VG_(printf)("location should start with fun: or obj:\n");
940 return False;
941}
942
943
944/* Read suppressions from the file specified in vg_clo_suppressions
945 and place them in the suppressions list. If there's any difficulty
946 doing this, just give up -- there's no point in trying to recover.
947*/
948#define STREQ(s1,s2) (s1 != NULL && s2 != NULL \
949 && VG_(strcmp)((s1),(s2))==0)
950
951static Char* copyStr ( Char* str )
952{
953 Int n, i;
954 Char* str2;
955 n = VG_(strlen)(str);
956 str2 = VG_(malloc)(VG_AR_PRIVATE, n+1);
957 vg_assert(n > 0);
958 for (i = 0; i < n+1; i++) str2[i] = str[i];
959 return str2;
960}
961
962static void load_one_suppressions_file ( Char* filename )
963{
964# define N_BUF 200
965 Int fd;
966 Bool eof;
967 Char buf[N_BUF+1];
968 fd = VG_(open_read)( filename );
969 if (fd == -1) {
970 VG_(message)(Vg_UserMsg,
971 "FATAL: can't open suppressions file `%s'",
972 filename );
973 VG_(exit)(1);
974 }
975
976 while (True) {
977 Suppression* supp;
978 supp = VG_(malloc)(VG_AR_PRIVATE, sizeof(Suppression));
979 supp->count = 0;
980 supp->param = supp->caller0 = supp->caller1
981 = supp->caller2 = supp->caller3 = NULL;
982
983 eof = getLine ( fd, buf, N_BUF );
984 if (eof) break;
985
986 if (!STREQ(buf, "{")) goto syntax_error;
987
988 eof = getLine ( fd, buf, N_BUF );
989 if (eof || STREQ(buf, "}")) goto syntax_error;
990 supp->sname = copyStr(buf);
991
992 eof = getLine ( fd, buf, N_BUF );
993 if (eof) goto syntax_error;
994 else if (STREQ(buf, "Param")) supp->skind = Param;
sewardja7dc7952002-03-24 11:29:13 +0000995 else if (STREQ(buf, "Value0")) supp->skind = Value0; /* backwards compat */
996 else if (STREQ(buf, "Cond")) supp->skind = Value0;
sewardjde4a1d02002-03-22 01:27:54 +0000997 else if (STREQ(buf, "Value1")) supp->skind = Value1;
998 else if (STREQ(buf, "Value2")) supp->skind = Value2;
999 else if (STREQ(buf, "Value4")) supp->skind = Value4;
1000 else if (STREQ(buf, "Value8")) supp->skind = Value8;
1001 else if (STREQ(buf, "Addr1")) supp->skind = Addr1;
1002 else if (STREQ(buf, "Addr2")) supp->skind = Addr2;
1003 else if (STREQ(buf, "Addr4")) supp->skind = Addr4;
1004 else if (STREQ(buf, "Addr8")) supp->skind = Addr8;
1005 else if (STREQ(buf, "Free")) supp->skind = FreeS;
sewardj4dced352002-06-04 22:54:20 +00001006 else if (STREQ(buf, "PThread")) supp->skind = PThread;
sewardjde4a1d02002-03-22 01:27:54 +00001007 else goto syntax_error;
1008
1009 if (supp->skind == Param) {
1010 eof = getLine ( fd, buf, N_BUF );
1011 if (eof) goto syntax_error;
1012 supp->param = copyStr(buf);
1013 }
1014
1015 eof = getLine ( fd, buf, N_BUF );
1016 if (eof) goto syntax_error;
1017 supp->caller0 = copyStr(buf);
1018 if (!setLocationTy(&(supp->caller0), &(supp->caller0_ty)))
1019 goto syntax_error;
1020
1021 eof = getLine ( fd, buf, N_BUF );
1022 if (eof) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +00001023 if (!STREQ(buf, "}")) {
sewardj0873c942002-03-24 09:45:26 +00001024 supp->caller1 = copyStr(buf);
1025 if (!setLocationTy(&(supp->caller1), &(supp->caller1_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 );
1029 if (eof) goto syntax_error;
1030 if (!STREQ(buf, "}")) {
sewardj0873c942002-03-24 09:45:26 +00001031 supp->caller2 = copyStr(buf);
1032 if (!setLocationTy(&(supp->caller2), &(supp->caller2_ty)))
sewardjde4a1d02002-03-22 01:27:54 +00001033 goto syntax_error;
sewardj0873c942002-03-24 09:45:26 +00001034
sewardjde4a1d02002-03-22 01:27:54 +00001035 eof = getLine ( fd, buf, N_BUF );
sewardj0873c942002-03-24 09:45:26 +00001036 if (eof) goto syntax_error;
1037 if (!STREQ(buf, "}")) {
1038 supp->caller3 = copyStr(buf);
1039 if (!setLocationTy(&(supp->caller3), &(supp->caller3_ty)))
1040 goto syntax_error;
1041
1042 eof = getLine ( fd, buf, N_BUF );
1043 if (eof || !STREQ(buf, "}")) goto syntax_error;
1044 }
sewardjde4a1d02002-03-22 01:27:54 +00001045 }
1046 }
1047
1048 supp->next = vg_suppressions;
1049 vg_suppressions = supp;
1050 }
1051
1052 VG_(close)(fd);
1053 return;
1054
1055 syntax_error:
1056 if (eof) {
1057 VG_(message)(Vg_UserMsg,
1058 "FATAL: in suppressions file `%s': unexpected EOF",
1059 filename );
1060 } else {
1061 VG_(message)(Vg_UserMsg,
1062 "FATAL: in suppressions file `%s': syntax error on: %s",
1063 filename, buf );
1064 }
1065 VG_(close)(fd);
1066 VG_(message)(Vg_UserMsg, "exiting now.");
1067 VG_(exit)(1);
1068
1069# undef N_BUF
1070}
1071
1072
1073void VG_(load_suppressions) ( void )
1074{
1075 Int i;
1076 vg_suppressions = NULL;
1077 for (i = 0; i < VG_(clo_n_suppressions); i++) {
1078 if (VG_(clo_verbosity) > 1) {
1079 VG_(message)(Vg_UserMsg, "Reading suppressions file: %s",
1080 VG_(clo_suppressions)[i] );
1081 }
1082 load_one_suppressions_file( VG_(clo_suppressions)[i] );
1083 }
1084}
1085
1086
1087/* Does an error context match a suppression? ie is this a
1088 suppressible error? If so, return a pointer to the Suppression
1089 record, otherwise NULL.
1090 Tries to minimise the number of calls to what_fn_is_this since they
1091 are expensive.
1092*/
1093static Suppression* is_suppressible_error ( ErrContext* ec )
1094{
1095# define STREQ(s1,s2) (s1 != NULL && s2 != NULL \
1096 && VG_(strcmp)((s1),(s2))==0)
1097
1098 Char caller0_obj[M_VG_ERRTXT];
1099 Char caller0_fun[M_VG_ERRTXT];
1100 Char caller1_obj[M_VG_ERRTXT];
1101 Char caller1_fun[M_VG_ERRTXT];
1102 Char caller2_obj[M_VG_ERRTXT];
1103 Char caller2_fun[M_VG_ERRTXT];
1104 Char caller3_obj[M_VG_ERRTXT];
1105 Char caller3_fun[M_VG_ERRTXT];
1106
1107 Suppression* su;
1108 Int su_size;
1109
1110 /* vg_what_fn_or_object_is_this returns:
1111 <function_name> or
1112 <object_name> or
1113 ???
1114 so the strings in the suppression file should match these.
1115 */
1116
1117 /* Initialise these strs so they are always safe to compare, even
1118 if what_fn_or_object_is_this doesn't write anything to them. */
1119 caller0_obj[0] = caller1_obj[0] = caller2_obj[0] = caller3_obj[0] = 0;
1120 caller0_fun[0] = caller1_fun[0] = caller2_obj[0] = caller3_obj[0] = 0;
1121
1122 VG_(what_obj_and_fun_is_this)
1123 ( ec->where->eips[0], caller0_obj, M_VG_ERRTXT,
1124 caller0_fun, M_VG_ERRTXT );
1125 VG_(what_obj_and_fun_is_this)
1126 ( ec->where->eips[1], caller1_obj, M_VG_ERRTXT,
1127 caller1_fun, M_VG_ERRTXT );
1128
1129 if (VG_(clo_backtrace_size) > 2) {
1130 VG_(what_obj_and_fun_is_this)
1131 ( ec->where->eips[2], caller2_obj, M_VG_ERRTXT,
1132 caller2_fun, M_VG_ERRTXT );
1133
1134 if (VG_(clo_backtrace_size) > 3) {
1135 VG_(what_obj_and_fun_is_this)
1136 ( ec->where->eips[3], caller3_obj, M_VG_ERRTXT,
1137 caller3_fun, M_VG_ERRTXT );
1138 }
1139 }
1140
1141 /* See if the error context matches any suppression. */
1142 for (su = vg_suppressions; su != NULL; su = su->next) {
1143 switch (su->skind) {
sewardj4dced352002-06-04 22:54:20 +00001144 case FreeS: case PThread:
sewardjde4a1d02002-03-22 01:27:54 +00001145 case Param: case Value0: su_size = 0; break;
1146 case Value1: case Addr1: su_size = 1; break;
1147 case Value2: case Addr2: su_size = 2; break;
1148 case Value4: case Addr4: su_size = 4; break;
1149 case Value8: case Addr8: su_size = 8; break;
1150 default: VG_(panic)("errcontext_matches_suppression");
1151 }
1152 switch (su->skind) {
1153 case Param:
1154 if (ec->ekind != ParamErr) continue;
1155 if (!STREQ(su->param, ec->syscall_param)) continue;
1156 break;
1157 case Value0: case Value1: case Value2: case Value4: case Value8:
1158 if (ec->ekind != ValueErr) continue;
1159 if (ec->size != su_size) continue;
1160 break;
1161 case Addr1: case Addr2: case Addr4: case Addr8:
1162 if (ec->ekind != AddrErr) continue;
1163 if (ec->size != su_size) continue;
1164 break;
1165 case FreeS:
sewardj4dced352002-06-04 22:54:20 +00001166 if (ec->ekind != FreeErr
1167 && ec->ekind != FreeMismatchErr) continue;
1168 break;
1169 case PThread:
1170 if (ec->ekind != PThreadErr) continue;
sewardjde4a1d02002-03-22 01:27:54 +00001171 break;
1172 }
1173
1174 switch (su->caller0_ty) {
1175 case ObjName: if (!VG_(stringMatch)(su->caller0,
1176 caller0_obj)) continue;
1177 break;
1178 case FunName: if (!VG_(stringMatch)(su->caller0,
1179 caller0_fun)) continue;
1180 break;
1181 default: goto baaaad;
1182 }
1183
sewardj0873c942002-03-24 09:45:26 +00001184 if (su->caller1 != NULL) {
1185 vg_assert(VG_(clo_backtrace_size) >= 2);
1186 switch (su->caller1_ty) {
1187 case ObjName: if (!VG_(stringMatch)(su->caller1,
1188 caller1_obj)) continue;
1189 break;
1190 case FunName: if (!VG_(stringMatch)(su->caller1,
1191 caller1_fun)) continue;
1192 break;
1193 default: goto baaaad;
1194 }
sewardjde4a1d02002-03-22 01:27:54 +00001195 }
1196
1197 if (VG_(clo_backtrace_size) > 2 && su->caller2 != NULL) {
1198 switch (su->caller2_ty) {
1199 case ObjName: if (!VG_(stringMatch)(su->caller2,
1200 caller2_obj)) continue;
1201 break;
1202 case FunName: if (!VG_(stringMatch)(su->caller2,
1203 caller2_fun)) continue;
1204 break;
1205 default: goto baaaad;
1206 }
1207 }
1208
1209 if (VG_(clo_backtrace_size) > 3 && su->caller3 != NULL) {
1210 switch (su->caller3_ty) {
1211 case ObjName: if (!VG_(stringMatch)(su->caller3,
1212 caller3_obj)) continue;
1213 break;
1214 case FunName: if (!VG_(stringMatch)(su->caller3,
1215 caller3_fun)) continue;
1216 break;
1217 default: goto baaaad;
1218 }
1219 }
1220
1221 return su;
1222 }
1223
1224 return NULL;
1225
1226 baaaad:
1227 VG_(panic)("is_suppressible_error");
1228
1229# undef STREQ
1230}
1231
1232/*--------------------------------------------------------------------*/
1233/*--- end vg_errcontext.c ---*/
1234/*--------------------------------------------------------------------*/