blob: ca5b7f7703a1daa05e450b5ed95ab379f41859b8 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
3/*--- Management of error messages. vg_errcontext.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
njnc9539842002-10-02 13:26:35 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn0e1b5142003-04-15 14:58:06 +000010 Copyright (C) 2000-2003 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 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
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
31#include "vg_include.h"
sewardjde4a1d02002-03-22 01:27:54 +000032
33/*------------------------------------------------------------*/
njn25e49d8e72002-09-23 09:36:25 +000034/*--- Globals ---*/
sewardjde4a1d02002-03-22 01:27:54 +000035/*------------------------------------------------------------*/
36
sewardjde4a1d02002-03-22 01:27:54 +000037/* The list of error contexts found, both suppressed and unsuppressed.
38 Initially empty, and grows as errors are detected. */
njn810086f2002-11-14 12:42:47 +000039static Error* vg_errors = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000040
41/* The list of suppression directives, as read from the specified
42 suppressions file. */
njn810086f2002-11-14 12:42:47 +000043static Supp* vg_suppressions = NULL;
sewardjde4a1d02002-03-22 01:27:54 +000044
45/* Running count of unsuppressed errors detected. */
njn47363ab2003-04-21 13:24:40 +000046UInt VG_(n_errs_found) = 0;
sewardjde4a1d02002-03-22 01:27:54 +000047
48/* Running count of suppressed errors detected. */
49static UInt vg_n_errs_suppressed = 0;
50
51/* forwards ... */
njn810086f2002-11-14 12:42:47 +000052static Supp* is_suppressible_error ( Error* err );
sewardjde4a1d02002-03-22 01:27:54 +000053
54
55/*------------------------------------------------------------*/
56/*--- Helper fns ---*/
57/*------------------------------------------------------------*/
58
sewardjde4a1d02002-03-22 01:27:54 +000059/* Compare error contexts, to detect duplicates. Note that if they
60 are otherwise the same, the faulting addrs and associated rwoffsets
61 are allowed to be different. */
njn810086f2002-11-14 12:42:47 +000062static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
sewardjde4a1d02002-03-22 01:27:54 +000063{
njn810086f2002-11-14 12:42:47 +000064 if (e1->ekind != e2->ekind)
sewardjde4a1d02002-03-22 01:27:54 +000065 return False;
njn25e49d8e72002-09-23 09:36:25 +000066 if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
sewardjde4a1d02002-03-22 01:27:54 +000067 return False;
68
njn810086f2002-11-14 12:42:47 +000069 switch (e1->ekind) {
sewardj4dced352002-06-04 22:54:20 +000070 case PThreadErr:
njn25e49d8e72002-09-23 09:36:25 +000071 vg_assert(VG_(needs).core_errors);
njn810086f2002-11-14 12:42:47 +000072 if (e1->string == e2->string)
sewardj4dced352002-06-04 22:54:20 +000073 return True;
njn810086f2002-11-14 12:42:47 +000074 if (0 == VG_(strcmp)(e1->string, e2->string))
sewardj4dced352002-06-04 22:54:20 +000075 return True;
76 return False;
sewardjde4a1d02002-03-22 01:27:54 +000077 default:
njn25e49d8e72002-09-23 09:36:25 +000078 if (VG_(needs).skin_errors)
njn810086f2002-11-14 12:42:47 +000079 return SK_(eq_SkinError)(res, e1, e2);
njn25e49d8e72002-09-23 09:36:25 +000080 else {
81 VG_(printf)("\nUnhandled error type: %u. VG_(needs).skin_errors\n"
82 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +000083 e1->ekind);
njne427a662002-10-02 11:08:25 +000084 VG_(skin_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +000085 }
sewardjde4a1d02002-03-22 01:27:54 +000086 }
87}
88
njn810086f2002-11-14 12:42:47 +000089static void pp_Error ( Error* err, Bool printCount )
sewardjde4a1d02002-03-22 01:27:54 +000090{
sewardjde4a1d02002-03-22 01:27:54 +000091 if (printCount)
njn25e49d8e72002-09-23 09:36:25 +000092 VG_(message)(Vg_UserMsg, "Observed %d times:", err->count );
93 if (err->tid > 1)
94 VG_(message)(Vg_UserMsg, "Thread %d:", err->tid );
95
njn810086f2002-11-14 12:42:47 +000096 switch (err->ekind) {
sewardj4dced352002-06-04 22:54:20 +000097 case PThreadErr:
njn25e49d8e72002-09-23 09:36:25 +000098 vg_assert(VG_(needs).core_errors);
njn810086f2002-11-14 12:42:47 +000099 VG_(message)(Vg_UserMsg, "%s", err->string );
njn25e49d8e72002-09-23 09:36:25 +0000100 VG_(pp_ExeContext)(err->where);
sewardj4dced352002-06-04 22:54:20 +0000101 break;
sewardjde4a1d02002-03-22 01:27:54 +0000102 default:
njn25e49d8e72002-09-23 09:36:25 +0000103 if (VG_(needs).skin_errors)
njn43c799e2003-04-08 00:08:52 +0000104 SK_(pp_SkinError)( err );
njn25e49d8e72002-09-23 09:36:25 +0000105 else {
106 VG_(printf)("\nUnhandled error type: %u. VG_(needs).skin_errors\n"
107 "probably needs to be set?\n",
njn810086f2002-11-14 12:42:47 +0000108 err->ekind);
njne427a662002-10-02 11:08:25 +0000109 VG_(skin_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +0000110 }
sewardjde4a1d02002-03-22 01:27:54 +0000111 }
112}
113
sewardjde4a1d02002-03-22 01:27:54 +0000114/* Figure out if we want to attach for GDB for this error, possibly
115 by asking the user. */
njn43c799e2003-04-08 00:08:52 +0000116Bool VG_(is_action_requested) ( Char* action, Bool* clo )
sewardjde4a1d02002-03-22 01:27:54 +0000117{
118 Char ch, ch2;
119 Int res;
120
njn43c799e2003-04-08 00:08:52 +0000121 if (*clo == False)
sewardjde4a1d02002-03-22 01:27:54 +0000122 return False;
123
124 VG_(message)(Vg_UserMsg, "");
125
126 again:
127 VG_(printf)(
128 "==%d== "
njn43c799e2003-04-08 00:08:52 +0000129 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
130 VG_(getpid)(), action
sewardjde4a1d02002-03-22 01:27:54 +0000131 );
132
sewardj6024b212003-07-13 10:54:33 +0000133 res = VG_(read)(VG_(clo_input_fd), &ch, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000134 if (res != 1) goto ioerror;
135 /* res == 1 */
136 if (ch == '\n') return False;
137 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y'
138 && ch != 'C' && ch != 'c') goto again;
139
sewardj6024b212003-07-13 10:54:33 +0000140 res = VG_(read)(VG_(clo_input_fd), &ch2, 1);
sewardjde4a1d02002-03-22 01:27:54 +0000141 if (res != 1) goto ioerror;
142 if (ch2 != '\n') goto again;
143
njn43c799e2003-04-08 00:08:52 +0000144 /* No, don't want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000145 if (ch == 'n' || ch == 'N') return False;
njn43c799e2003-04-08 00:08:52 +0000146 /* Yes, want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000147 if (ch == 'y' || ch == 'Y') return True;
njn43c799e2003-04-08 00:08:52 +0000148 /* No, don't want to do action, and don't ask again either. */
sewardjde4a1d02002-03-22 01:27:54 +0000149 vg_assert(ch == 'c' || ch == 'C');
150
151 ioerror:
njn43c799e2003-04-08 00:08:52 +0000152 *clo = False;
sewardjde4a1d02002-03-22 01:27:54 +0000153 return False;
154}
155
156
njn25e49d8e72002-09-23 09:36:25 +0000157/* I've gone all object-oriented... initialisation depends on where the
158 error comes from:
159
160 - If from generated code (tst == NULL), the %EIP/%EBP values that we
njn3e884182003-04-15 13:03:23 +0000161 need in order to attach GDB are picked up out of VG_(baseBlock) rather
162 than from the thread table (vg_threads in vg_scheduler.c).
njn25e49d8e72002-09-23 09:36:25 +0000163
164 - If not from generated code but in response to requests passed back to
165 the scheduler (tst != NULL), we pick up %EIP/%EBP values from the
166 stored thread state, not from VG_(baseBlock).
167*/
168static __inline__
njn72718642003-07-24 08:45:32 +0000169void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a,
170 Char* s, void* extra, ExeContext* where )
sewardjde4a1d02002-03-22 01:27:54 +0000171{
njn72718642003-07-24 08:45:32 +0000172 sk_assert(tid < VG_N_THREADS);
173
njn810086f2002-11-14 12:42:47 +0000174 /* Core-only parts */
njn25e49d8e72002-09-23 09:36:25 +0000175 err->next = NULL;
176 err->supp = NULL;
177 err->count = 1;
njn72718642003-07-24 08:45:32 +0000178 err->tid = tid;
njn43c799e2003-04-08 00:08:52 +0000179 if (NULL == where)
njn72718642003-07-24 08:45:32 +0000180 err->where = VG_(get_ExeContext)( tid );
njn43c799e2003-04-08 00:08:52 +0000181 else
182 err->where = where;
njn1d6c4bc2002-11-21 13:38:08 +0000183
njn810086f2002-11-14 12:42:47 +0000184 /* Skin-relevant parts */
185 err->ekind = ekind;
186 err->addr = a;
njn810086f2002-11-14 12:42:47 +0000187 err->extra = extra;
sewardj7ebf7c32003-07-24 21:29:40 +0000188 if (s) {
189 err->string = VG_(arena_strdup)( VG_AR_ERRORS, s );
190 }
191 else {
192 err->string = NULL;
193 }
njn25e49d8e72002-09-23 09:36:25 +0000194 /* sanity... */
njn72718642003-07-24 08:45:32 +0000195 vg_assert( tid < VG_N_THREADS );
njn25e49d8e72002-09-23 09:36:25 +0000196}
197
njn43c799e2003-04-08 00:08:52 +0000198void VG_(gen_suppression)(Error* err)
199{
sewardj05bcdcb2003-05-18 10:05:38 +0000200 Int i;
njn43c799e2003-04-08 00:08:52 +0000201 UChar buf[M_VG_ERRTXT];
202 ExeContext* ec = VG_(get_error_where)(err);
203 Int stop_at = VG_(clo_backtrace_size);
njn43c799e2003-04-08 00:08:52 +0000204
njn633de322003-05-12 20:40:13 +0000205 if (stop_at > 4) stop_at = 4; /* At most four names */
njn43c799e2003-04-08 00:08:52 +0000206 vg_assert(stop_at > 0);
207
208 VG_(printf)("{\n");
209 VG_(printf)(" <insert a suppression name here>\n");
njn6a230532003-07-21 10:38:23 +0000210
211 if (PThreadErr == err->ekind) {
212 VG_(printf)(" core:PThread\n");
213
214 } else {
215 Char* name = SK_(get_error_name)(err);
216 if (NULL == name) {
217 VG_(message)(Vg_UserMsg,
218 "(skin does not allow error to be suppressed)");
219 return;
220 }
221 VG_(printf)(" %s:%s\n", VG_(details).name, name);
222 SK_(print_extra_suppression_info)(err);
223 }
njn43c799e2003-04-08 00:08:52 +0000224
225 /* This loop condensed from VG_(mini_stack_dump)() */
226 i = 0;
227 do {
228 Addr eip = ec->eips[i];
229 if (i > 0)
230 eip--; /* point to calling line */
231
232 if ( VG_(get_fnname_nodemangle) (eip, buf, M_VG_ERRTXT) ) {
233 VG_(printf)(" fun:%s\n", buf);
234 } else if ( VG_(get_objname)(eip, buf, M_VG_ERRTXT) ) {
235 VG_(printf)(" obj:%s\n", buf);
236 } else {
237 VG_(printf)(" ???:??? "
238 "# unknown, suppression will not work, sorry)\n");
239 }
240 i++;
241 } while (i < stop_at && ec->eips[i] != 0);
242
243 VG_(printf)("}\n");
244}
245
njnb4aee052003-04-15 14:09:58 +0000246static
njn72718642003-07-24 08:45:32 +0000247void do_actions_on_error(Error* err, Bool allow_GDB_attach)
njn43c799e2003-04-08 00:08:52 +0000248{
249 /* Perhaps we want a GDB attach at this point? */
njn3e884182003-04-15 13:03:23 +0000250 if (allow_GDB_attach &&
251 VG_(is_action_requested)( "Attach to GDB", & VG_(clo_GDB_attach) ))
252 {
njn72718642003-07-24 08:45:32 +0000253 Addr m_eip, m_esp, m_ebp;
254
255 if (VG_(is_running_thread)( err->tid )) {
256 m_eip = VG_(baseBlock)[VGOFF_(m_eip)];
257 m_esp = VG_(baseBlock)[VGOFF_(m_esp)];
258 m_ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
259 } else {
260 ThreadState* tst = & VG_(threads)[ err->tid ];
261 m_eip = tst->m_eip;
262 m_esp = tst->m_esp;
263 m_ebp = tst->m_ebp;
264 }
njn3e884182003-04-15 13:03:23 +0000265 VG_(swizzle_esp_then_start_GDB)( m_eip, m_esp, m_ebp );
njn43c799e2003-04-08 00:08:52 +0000266 }
267 /* Or maybe we want to generate the error's suppression? */
268 if (VG_(is_action_requested)( "Print suppression",
269 & VG_(clo_gen_suppressions) )) {
270 VG_(gen_suppression)(err);
271 }
272}
273
274/* Shared between VG_(maybe_record_error)() and VG_(unique_error)(),
275 just for pretty printing purposes. */
276static Bool is_first_shown_context = True;
277
njn25e49d8e72002-09-23 09:36:25 +0000278/* Top-level entry point to the error management subsystem.
279 All detected errors are notified here; this routine decides if/when the
280 user should see the error. */
njn72718642003-07-24 08:45:32 +0000281void VG_(maybe_record_error) ( ThreadId tid,
njn25e49d8e72002-09-23 09:36:25 +0000282 ErrorKind ekind, Addr a, Char* s, void* extra )
283{
njn810086f2002-11-14 12:42:47 +0000284 Error err;
285 Error* p;
286 Error* p_prev;
njn43c799e2003-04-08 00:08:52 +0000287 UInt extra_size;
njn810086f2002-11-14 12:42:47 +0000288 VgRes exe_res = Vg_MedRes;
njn810086f2002-11-14 12:42:47 +0000289 static Bool stopping_message = False;
290 static Bool slowdown_message = False;
291 static Int vg_n_errs_shown = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000292
sewardjf2537be2002-04-24 21:03:47 +0000293 /* After M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
294 been found, or M_VG_COLLECT_NO_ERRORS_AFTER_FOUND total errors
295 have been found, just refuse to collect any more. This stops
296 the burden of the error-management system becoming excessive in
297 extremely buggy programs, although it does make it pretty
298 pointless to continue the Valgrind run after this point. */
sewardj2e432902002-06-13 20:44:00 +0000299 if (VG_(clo_error_limit)
sewardj72f98ff2002-06-13 17:23:38 +0000300 && (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN
njn47363ab2003-04-21 13:24:40 +0000301 || VG_(n_errs_found) >= M_VG_COLLECT_NO_ERRORS_AFTER_FOUND)) {
sewardjde4a1d02002-03-22 01:27:54 +0000302 if (!stopping_message) {
303 VG_(message)(Vg_UserMsg, "");
sewardjf2537be2002-04-24 21:03:47 +0000304
305 if (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN) {
306 VG_(message)(Vg_UserMsg,
307 "More than %d different errors detected. "
308 "I'm not reporting any more.",
309 M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN );
310 } else {
311 VG_(message)(Vg_UserMsg,
312 "More than %d total errors detected. "
313 "I'm not reporting any more.",
314 M_VG_COLLECT_NO_ERRORS_AFTER_FOUND );
315 }
316
sewardjde4a1d02002-03-22 01:27:54 +0000317 VG_(message)(Vg_UserMsg,
sewardjf2537be2002-04-24 21:03:47 +0000318 "Final error counts will be inaccurate. Go fix your program!");
sewardj72f98ff2002-06-13 17:23:38 +0000319 VG_(message)(Vg_UserMsg,
sewardj2e432902002-06-13 20:44:00 +0000320 "Rerun with --error-limit=no to disable this cutoff. Note");
sewardj72f98ff2002-06-13 17:23:38 +0000321 VG_(message)(Vg_UserMsg,
njn25e49d8e72002-09-23 09:36:25 +0000322 "that errors may occur in your program without prior warning from");
sewardj72f98ff2002-06-13 17:23:38 +0000323 VG_(message)(Vg_UserMsg,
324 "Valgrind, because errors are no longer being displayed.");
sewardjde4a1d02002-03-22 01:27:54 +0000325 VG_(message)(Vg_UserMsg, "");
326 stopping_message = True;
327 }
328 return;
329 }
330
331 /* After M_VG_COLLECT_ERRORS_SLOWLY_AFTER different errors have
332 been found, be much more conservative about collecting new
333 ones. */
334 if (vg_n_errs_shown >= M_VG_COLLECT_ERRORS_SLOWLY_AFTER) {
njn25e49d8e72002-09-23 09:36:25 +0000335 exe_res = Vg_LowRes;
sewardjde4a1d02002-03-22 01:27:54 +0000336 if (!slowdown_message) {
337 VG_(message)(Vg_UserMsg, "");
338 VG_(message)(Vg_UserMsg,
339 "More than %d errors detected. Subsequent errors",
340 M_VG_COLLECT_ERRORS_SLOWLY_AFTER);
341 VG_(message)(Vg_UserMsg,
342 "will still be recorded, but in less detail than before.");
343 slowdown_message = True;
344 }
345 }
346
njn25e49d8e72002-09-23 09:36:25 +0000347 /* Build ourselves the error */
sewardj7ebf7c32003-07-24 21:29:40 +0000348 err.string = NULL;
njn72718642003-07-24 08:45:32 +0000349 construct_error ( &err, tid, ekind, a, s, extra, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000350
351 /* First, see if we've got an error record matching this one. */
njn25e49d8e72002-09-23 09:36:25 +0000352 p = vg_errors;
sewardjde4a1d02002-03-22 01:27:54 +0000353 p_prev = NULL;
354 while (p != NULL) {
njn810086f2002-11-14 12:42:47 +0000355 if (eq_Error(exe_res, p, &err)) {
sewardjde4a1d02002-03-22 01:27:54 +0000356 /* Found it. */
357 p->count++;
358 if (p->supp != NULL) {
359 /* Deal correctly with suppressed errors. */
360 p->supp->count++;
361 vg_n_errs_suppressed++;
362 } else {
njn47363ab2003-04-21 13:24:40 +0000363 VG_(n_errs_found)++;
sewardjde4a1d02002-03-22 01:27:54 +0000364 }
365
366 /* Move p to the front of the list so that future searches
367 for it are faster. */
368 if (p_prev != NULL) {
369 vg_assert(p_prev->next == p);
370 p_prev->next = p->next;
njn25e49d8e72002-09-23 09:36:25 +0000371 p->next = vg_errors;
372 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000373 }
sewardj7ebf7c32003-07-24 21:29:40 +0000374
375 /* Free err.string, if we allocated it. */
376 if (err.string) {
377 VG_(arena_free)( VG_AR_ERRORS, err.string );
378 err.string = NULL; /* paranoia */
379 }
380
sewardjde4a1d02002-03-22 01:27:54 +0000381 return;
382 }
383 p_prev = p;
384 p = p->next;
385 }
386
387 /* Didn't see it. Copy and add. */
388
njn43c799e2003-04-08 00:08:52 +0000389 /* OK, we're really going to collect it. The context is on the stack and
390 will disappear shortly, so we must copy it. First do the main
391 (non-`extra') part.
njn25e49d8e72002-09-23 09:36:25 +0000392
njn43c799e2003-04-08 00:08:52 +0000393 Then SK_(update_extra) can update the `extra' part. This is for when
394 there are more details to fill in which take time to work out but
395 don't affect our earlier decision to include the error -- by
njn25e49d8e72002-09-23 09:36:25 +0000396 postponing those details until now, we avoid the extra work in the
njn810086f2002-11-14 12:42:47 +0000397 case where we ignore the error. Ugly.
njn43c799e2003-04-08 00:08:52 +0000398
399 Then, if there is an `extra' part, copy it too, using the size that
400 SK_(update_extra) returned.
401 */
402
403 /* copy main part */
njn810086f2002-11-14 12:42:47 +0000404 p = VG_(arena_malloc)(VG_AR_ERRORS, sizeof(Error));
njn25e49d8e72002-09-23 09:36:25 +0000405 *p = err;
njn43c799e2003-04-08 00:08:52 +0000406
njn6a230532003-07-21 10:38:23 +0000407 /* update `extra', for non-core errors (core ones don't use 'extra') */
408 if (VG_(needs).skin_errors) {
409 extra_size = SK_(update_extra)(p);
njn43c799e2003-04-08 00:08:52 +0000410
njn6a230532003-07-21 10:38:23 +0000411 /* copy `extra' if there is one */
412 if (NULL != p->extra) {
413 void* new_extra = VG_(malloc)(extra_size);
414 VG_(memcpy)(new_extra, p->extra, extra_size);
415 p->extra = new_extra;
416 }
njn43c799e2003-04-08 00:08:52 +0000417 }
418
njn25e49d8e72002-09-23 09:36:25 +0000419 p->next = vg_errors;
420 p->supp = is_suppressible_error(&err);
421 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000422 if (p->supp == NULL) {
njn47363ab2003-04-21 13:24:40 +0000423 VG_(n_errs_found)++;
sewardjde4a1d02002-03-22 01:27:54 +0000424 if (!is_first_shown_context)
425 VG_(message)(Vg_UserMsg, "");
njn43c799e2003-04-08 00:08:52 +0000426 pp_Error(p, False);
sewardjde4a1d02002-03-22 01:27:54 +0000427 is_first_shown_context = False;
428 vg_n_errs_shown++;
njn72718642003-07-24 08:45:32 +0000429 do_actions_on_error(p, /*allow_GDB_attach*/True);
sewardjde4a1d02002-03-22 01:27:54 +0000430 } else {
431 vg_n_errs_suppressed++;
432 p->supp->count++;
433 }
434}
435
njn43c799e2003-04-08 00:08:52 +0000436/* Second top-level entry point to the error management subsystem, for
437 errors that the skin want to report immediately, eg. because they're
438 guaranteed to only happen once. This avoids all the recording and
439 comparing stuff. But they can be suppressed; returns True if it is
njn47363ab2003-04-21 13:24:40 +0000440 suppressed. Bool `print_error' dictates whether to print the error.
441 Bool `count_error' dictates whether to count the error in VG_(n_errs_found)
442*/
njn72718642003-07-24 08:45:32 +0000443Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, Char* s,
njn3e884182003-04-15 13:03:23 +0000444 void* extra, ExeContext* where, Bool print_error,
njn47363ab2003-04-21 13:24:40 +0000445 Bool allow_GDB_attach, Bool count_error )
njn43c799e2003-04-08 00:08:52 +0000446{
447 Error err;
448
449 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000450 construct_error ( &err, tid, ekind, a, s, extra, where );
njn43c799e2003-04-08 00:08:52 +0000451
452 /* Unless it's suppressed, we're going to show it. Don't need to make
453 a copy, because it's only temporary anyway.
454
455 Then update the `extra' part with SK_(update_extra), because that can
456 have an affect on whether it's suppressed. Ignore the size return
457 value of SK_(update_extra), because we're not copying `extra'. */
458 (void)SK_(update_extra)(&err);
459
460 if (NULL == is_suppressible_error(&err)) {
njn47363ab2003-04-21 13:24:40 +0000461 if (count_error)
462 VG_(n_errs_found)++;
njn43c799e2003-04-08 00:08:52 +0000463
464 if (print_error) {
465 if (!is_first_shown_context)
466 VG_(message)(Vg_UserMsg, "");
467 pp_Error(&err, False);
468 is_first_shown_context = False;
469 }
njn72718642003-07-24 08:45:32 +0000470 do_actions_on_error(&err, allow_GDB_attach);
njn43c799e2003-04-08 00:08:52 +0000471
472 return False;
473
474 } else {
475 vg_n_errs_suppressed++;
476 return True;
477 }
478}
479
sewardjde4a1d02002-03-22 01:27:54 +0000480
sewardjde4a1d02002-03-22 01:27:54 +0000481/*------------------------------------------------------------*/
482/*--- Exported fns ---*/
483/*------------------------------------------------------------*/
484
njn25e49d8e72002-09-23 09:36:25 +0000485/* These are called not from generated code but from the scheduler */
sewardj8c824512002-04-14 04:16:48 +0000486
njn25e49d8e72002-09-23 09:36:25 +0000487void VG_(record_pthread_error) ( ThreadId tid, Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +0000488{
njn25e49d8e72002-09-23 09:36:25 +0000489 if (! VG_(needs).core_errors) return;
njn72718642003-07-24 08:45:32 +0000490 VG_(maybe_record_error)( tid, PThreadErr, /*addr*/0, msg, /*extra*/NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000491}
492
sewardj8c824512002-04-14 04:16:48 +0000493/*------------------------------*/
494
sewardjde4a1d02002-03-22 01:27:54 +0000495void VG_(show_all_errors) ( void )
496{
njn810086f2002-11-14 12:42:47 +0000497 Int i, n_min;
498 Int n_err_contexts, n_supp_contexts;
499 Error *p, *p_min;
500 Supp *su;
501 Bool any_supp;
sewardjde4a1d02002-03-22 01:27:54 +0000502
503 if (VG_(clo_verbosity) == 0)
504 return;
505
506 n_err_contexts = 0;
njn25e49d8e72002-09-23 09:36:25 +0000507 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000508 if (p->supp == NULL)
509 n_err_contexts++;
510 }
511
512 n_supp_contexts = 0;
513 for (su = vg_suppressions; su != NULL; su = su->next) {
514 if (su->count > 0)
515 n_supp_contexts++;
516 }
sewardjde4a1d02002-03-22 01:27:54 +0000517 VG_(message)(Vg_UserMsg,
518 "ERROR SUMMARY: "
519 "%d errors from %d contexts (suppressed: %d from %d)",
njn47363ab2003-04-21 13:24:40 +0000520 VG_(n_errs_found), n_err_contexts,
sewardjde4a1d02002-03-22 01:27:54 +0000521 vg_n_errs_suppressed, n_supp_contexts );
522
523 if (VG_(clo_verbosity) <= 1)
524 return;
525
526 /* Print the contexts in order of increasing error count. */
527 for (i = 0; i < n_err_contexts; i++) {
528 n_min = (1 << 30) - 1;
529 p_min = NULL;
njn25e49d8e72002-09-23 09:36:25 +0000530 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000531 if (p->supp != NULL) continue;
532 if (p->count < n_min) {
533 n_min = p->count;
534 p_min = p;
535 }
536 }
njne427a662002-10-02 11:08:25 +0000537 if (p_min == NULL) VG_(skin_panic)("show_all_errors()");
sewardjde4a1d02002-03-22 01:27:54 +0000538
539 VG_(message)(Vg_UserMsg, "");
540 VG_(message)(Vg_UserMsg, "%d errors in context %d of %d:",
541 p_min->count,
542 i+1, n_err_contexts);
njn810086f2002-11-14 12:42:47 +0000543 pp_Error( p_min, False );
sewardjde4a1d02002-03-22 01:27:54 +0000544
545 if ((i+1 == VG_(clo_dump_error))) {
sewardj1e8cdc92002-04-18 11:37:52 +0000546 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to below NULLs */,
sewardj22854b92002-11-30 14:00:47 +0000547 p_min->where->eips[0], NULL, NULL, NULL, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000548 }
549
550 p_min->count = 1 << 30;
551 }
552
553 if (n_supp_contexts > 0)
554 VG_(message)(Vg_DebugMsg, "");
555 any_supp = False;
556 for (su = vg_suppressions; su != NULL; su = su->next) {
557 if (su->count > 0) {
558 any_supp = True;
njn25e49d8e72002-09-23 09:36:25 +0000559 VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count, su->sname);
sewardjde4a1d02002-03-22 01:27:54 +0000560 }
561 }
562
563 if (n_err_contexts > 0) {
564 if (any_supp)
565 VG_(message)(Vg_UserMsg, "");
566 VG_(message)(Vg_UserMsg,
567 "IN SUMMARY: "
568 "%d errors from %d contexts (suppressed: %d from %d)",
njn47363ab2003-04-21 13:24:40 +0000569 VG_(n_errs_found), n_err_contexts,
sewardjde4a1d02002-03-22 01:27:54 +0000570 vg_n_errs_suppressed,
571 n_supp_contexts );
572 VG_(message)(Vg_UserMsg, "");
573 }
574}
575
576/*------------------------------------------------------------*/
577/*--- Standard suppressions ---*/
578/*------------------------------------------------------------*/
579
580/* Get a non-blank, non-comment line of at most nBuf chars from fd.
581 Skips leading spaces on the line. Return True if EOF was hit instead.
582*/
583
584#define VG_ISSPACE(ch) (((ch)==' ') || ((ch)=='\n') || ((ch)=='\t'))
585
njn4ba5a792002-09-30 10:23:54 +0000586Bool VG_(get_line) ( Int fd, Char* buf, Int nBuf )
sewardjde4a1d02002-03-22 01:27:54 +0000587{
588 Char ch;
589 Int n, i;
590 while (True) {
591 /* First, read until a non-blank char appears. */
592 while (True) {
593 n = VG_(read)(fd, &ch, 1);
594 if (n == 1 && !VG_ISSPACE(ch)) break;
595 if (n == 0) return True;
596 }
597
598 /* Now, read the line into buf. */
599 i = 0;
600 buf[i++] = ch; buf[i] = 0;
601 while (True) {
602 n = VG_(read)(fd, &ch, 1);
603 if (n == 0) return False; /* the next call will return True */
604 if (ch == '\n') break;
605 if (i > 0 && i == nBuf-1) i--;
606 buf[i++] = ch; buf[i] = 0;
607 }
608 while (i > 1 && VG_ISSPACE(buf[i-1])) {
609 i--; buf[i] = 0;
610 };
611
612 /* VG_(printf)("The line is `%s'\n", buf); */
613 /* Ok, we have a line. If a non-comment line, return.
614 If a comment line, start all over again. */
615 if (buf[0] != '#') return False;
616 }
617}
618
619
620/* *p_caller contains the raw name of a caller, supposedly either
621 fun:some_function_name or
622 obj:some_object_name.
623 Set *p_ty accordingly and advance *p_caller over the descriptor
624 (fun: or obj:) part.
625 Returns False if failed.
626*/
njn25e49d8e72002-09-23 09:36:25 +0000627static Bool setLocationTy ( Char** p_caller, SuppLocTy* p_ty )
sewardjde4a1d02002-03-22 01:27:54 +0000628{
629 if (VG_(strncmp)(*p_caller, "fun:", 4) == 0) {
630 (*p_caller) += 4;
631 *p_ty = FunName;
632 return True;
633 }
634 if (VG_(strncmp)(*p_caller, "obj:", 4) == 0) {
635 (*p_caller) += 4;
636 *p_ty = ObjName;
637 return True;
638 }
639 VG_(printf)("location should start with fun: or obj:\n");
640 return False;
641}
642
643
njn11cc9252002-10-07 14:42:59 +0000644/* Look for "skin" in a string like "skin1,skin2,skin3" */
645static __inline__
646Bool skin_name_present(Char *name, Char *names)
647{
648 Bool found;
649 Char *s = NULL; /* Shut gcc up */
650 Int len = VG_(strlen)(name);
651
652 found = (NULL != (s = VG_(strstr)(names, name)) &&
653 (s == names || *(s-1) == ',') &&
654 (*(s+len) == ',' || *(s+len) == '\0')
655 );
656
657 return found;
658}
659
sewardjde4a1d02002-03-22 01:27:54 +0000660/* Read suppressions from the file specified in vg_clo_suppressions
661 and place them in the suppressions list. If there's any difficulty
662 doing this, just give up -- there's no point in trying to recover.
663*/
sewardjde4a1d02002-03-22 01:27:54 +0000664static void load_one_suppressions_file ( Char* filename )
665{
666# define N_BUF 200
njnc40c3a82002-10-02 11:02:27 +0000667 Int fd, i;
668 Bool eof;
669 Char buf[N_BUF+1];
njn11cc9252002-10-07 14:42:59 +0000670 Char* skin_names;
njnc40c3a82002-10-02 11:02:27 +0000671 Char* supp_name;
672
njn25e49d8e72002-09-23 09:36:25 +0000673 fd = VG_(open)( filename, VKI_O_RDONLY, 0 );
sewardjde4a1d02002-03-22 01:27:54 +0000674 if (fd == -1) {
njn25e49d8e72002-09-23 09:36:25 +0000675 VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file `%s'",
sewardjde4a1d02002-03-22 01:27:54 +0000676 filename );
677 VG_(exit)(1);
678 }
679
680 while (True) {
njn25e49d8e72002-09-23 09:36:25 +0000681 /* Assign and initialise the two suppression halves (core and skin) */
njn810086f2002-11-14 12:42:47 +0000682 Supp* supp;
683 supp = VG_(arena_malloc)(VG_AR_CORE, sizeof(Supp));
sewardjde4a1d02002-03-22 01:27:54 +0000684 supp->count = 0;
njn25e49d8e72002-09-23 09:36:25 +0000685 for (i = 0; i < VG_N_SUPP_CALLERS; i++) supp->caller[i] = NULL;
njn810086f2002-11-14 12:42:47 +0000686 supp->string = supp->extra = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000687
njn4ba5a792002-09-30 10:23:54 +0000688 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000689 if (eof) break;
690
njn43c799e2003-04-08 00:08:52 +0000691 if (!VG_STREQ(buf, "{")) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000692
njn4ba5a792002-09-30 10:23:54 +0000693 eof = VG_(get_line) ( fd, buf, N_BUF );
njn43c799e2003-04-08 00:08:52 +0000694 if (eof || VG_STREQ(buf, "}")) goto syntax_error;
njn25e49d8e72002-09-23 09:36:25 +0000695 supp->sname = VG_(arena_strdup)(VG_AR_CORE, buf);
sewardjde4a1d02002-03-22 01:27:54 +0000696
njn4ba5a792002-09-30 10:23:54 +0000697 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000698
sewardjde4a1d02002-03-22 01:27:54 +0000699 if (eof) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000700
njn11cc9252002-10-07 14:42:59 +0000701 /* Check it has the "skin1,skin2,...:supp" form (look for ':') */
njnc40c3a82002-10-02 11:02:27 +0000702 i = 0;
703 while (True) {
704 if (buf[i] == ':') break;
705 if (buf[i] == '\0') goto syntax_error;
706 i++;
njn25e49d8e72002-09-23 09:36:25 +0000707 }
njnc40c3a82002-10-02 11:02:27 +0000708 buf[i] = '\0'; /* Replace ':', splitting into two strings */
709
njn11cc9252002-10-07 14:42:59 +0000710 skin_names = & buf[0];
711 supp_name = & buf[i+1];
njnc40c3a82002-10-02 11:02:27 +0000712
njn11cc9252002-10-07 14:42:59 +0000713 /* Is it a core suppression? */
714 if (VG_(needs).core_errors && skin_name_present("core", skin_names))
njnc40c3a82002-10-02 11:02:27 +0000715 {
njn43c799e2003-04-08 00:08:52 +0000716 if (VG_STREQ(supp_name, "PThread"))
njn810086f2002-11-14 12:42:47 +0000717 supp->skind = PThreadSupp;
njnc40c3a82002-10-02 11:02:27 +0000718 else
719 goto syntax_error;
720 }
721
njn11cc9252002-10-07 14:42:59 +0000722 /* Is it a skin suppression? */
723 else if (VG_(needs).skin_errors &&
724 skin_name_present(VG_(details).name, skin_names))
njnc40c3a82002-10-02 11:02:27 +0000725 {
njn810086f2002-11-14 12:42:47 +0000726 if (SK_(recognised_suppression)(supp_name, supp))
njnc40c3a82002-10-02 11:02:27 +0000727 {
njn810086f2002-11-14 12:42:47 +0000728 /* Do nothing, function fills in supp->skind */
njnc40c3a82002-10-02 11:02:27 +0000729 } else
730 goto syntax_error;
731 }
732
njn25e49d8e72002-09-23 09:36:25 +0000733 else {
njnc40c3a82002-10-02 11:02:27 +0000734 /* Ignore rest of suppression */
njn25e49d8e72002-09-23 09:36:25 +0000735 while (True) {
njn4ba5a792002-09-30 10:23:54 +0000736 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000737 if (eof) goto syntax_error;
njn43c799e2003-04-08 00:08:52 +0000738 if (VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000739 break;
740 }
741 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000742 }
743
njn25e49d8e72002-09-23 09:36:25 +0000744 if (VG_(needs).skin_errors &&
njn810086f2002-11-14 12:42:47 +0000745 !SK_(read_extra_suppression_info)(fd, buf, N_BUF, supp))
sewardjde4a1d02002-03-22 01:27:54 +0000746 goto syntax_error;
747
njn25e49d8e72002-09-23 09:36:25 +0000748 /* "i > 0" ensures at least one caller read. */
njn633de322003-05-12 20:40:13 +0000749 for (i = 0; i <= VG_N_SUPP_CALLERS; i++) {
njn4ba5a792002-09-30 10:23:54 +0000750 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000751 if (eof) goto syntax_error;
njn43c799e2003-04-08 00:08:52 +0000752 if (i > 0 && VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000753 break;
njn633de322003-05-12 20:40:13 +0000754 if (i == VG_N_SUPP_CALLERS)
755 break;
njn25e49d8e72002-09-23 09:36:25 +0000756 supp->caller[i] = VG_(arena_strdup)(VG_AR_CORE, buf);
757 if (!setLocationTy(&(supp->caller[i]), &(supp->caller_ty[i])))
758 goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000759 }
760
sewardj57a8f5f2003-07-06 01:40:11 +0000761 /* make sure to grab the '}' if the num callers is >=
762 VG_N_SUPP_CALLERS */
763 if (!VG_STREQ(buf, "}")) {
764 do {
765 eof = VG_(get_line) ( fd, buf, N_BUF );
766 } while (!eof && !VG_STREQ(buf, "}"));
767 }
768
sewardjde4a1d02002-03-22 01:27:54 +0000769 supp->next = vg_suppressions;
770 vg_suppressions = supp;
771 }
sewardjde4a1d02002-03-22 01:27:54 +0000772 VG_(close)(fd);
773 return;
774
775 syntax_error:
776 if (eof) {
777 VG_(message)(Vg_UserMsg,
778 "FATAL: in suppressions file `%s': unexpected EOF",
779 filename );
780 } else {
781 VG_(message)(Vg_UserMsg,
njn11cc9252002-10-07 14:42:59 +0000782 "FATAL: in suppressions file: `%s': syntax error on: %s",
sewardjde4a1d02002-03-22 01:27:54 +0000783 filename, buf );
784 }
785 VG_(close)(fd);
786 VG_(message)(Vg_UserMsg, "exiting now.");
787 VG_(exit)(1);
788
789# undef N_BUF
790}
791
792
793void VG_(load_suppressions) ( void )
794{
795 Int i;
796 vg_suppressions = NULL;
797 for (i = 0; i < VG_(clo_n_suppressions); i++) {
798 if (VG_(clo_verbosity) > 1) {
799 VG_(message)(Vg_UserMsg, "Reading suppressions file: %s",
800 VG_(clo_suppressions)[i] );
801 }
802 load_one_suppressions_file( VG_(clo_suppressions)[i] );
803 }
804}
805
njn25e49d8e72002-09-23 09:36:25 +0000806/* Return the name of an erring fn in a way which is useful
807 for comparing against the contents of a suppressions file.
808 Doesn't demangle the fn name, because we want to refer to
809 mangled names in the suppressions file.
sewardj99aac972002-12-26 01:53:45 +0000810*/
njn43c799e2003-04-08 00:08:52 +0000811static void get_objname_fnname ( Addr a, Char* obj_buf, Int n_obj_buf,
812 Char* fun_buf, Int n_fun_buf )
njn25e49d8e72002-09-23 09:36:25 +0000813{
814 (void)VG_(get_objname) ( a, obj_buf, n_obj_buf );
815 (void)VG_(get_fnname_nodemangle)( a, fun_buf, n_fun_buf );
816}
817
818static __inline__
njn810086f2002-11-14 12:42:47 +0000819Bool supp_matches_error(Supp* su, Error* err)
njn25e49d8e72002-09-23 09:36:25 +0000820{
njn810086f2002-11-14 12:42:47 +0000821 switch (su->skind) {
njn25e49d8e72002-09-23 09:36:25 +0000822 case PThreadSupp:
njn810086f2002-11-14 12:42:47 +0000823 return (err->ekind == PThreadErr);
njn25e49d8e72002-09-23 09:36:25 +0000824 default:
825 if (VG_(needs).skin_errors) {
njn810086f2002-11-14 12:42:47 +0000826 return SK_(error_matches_suppression)(err, su);
njn25e49d8e72002-09-23 09:36:25 +0000827 } else {
828 VG_(printf)(
829 "\nUnhandled suppression type: %u. VG_(needs).skin_errors\n"
830 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000831 err->ekind);
njne427a662002-10-02 11:08:25 +0000832 VG_(skin_panic)("unhandled suppression type");
njn25e49d8e72002-09-23 09:36:25 +0000833 }
834 }
835}
836
837static __inline__
njn810086f2002-11-14 12:42:47 +0000838Bool supp_matches_callers(Supp* su, Char caller_obj[][M_VG_ERRTXT],
839 Char caller_fun[][M_VG_ERRTXT])
njn25e49d8e72002-09-23 09:36:25 +0000840{
841 Int i;
842
njn633de322003-05-12 20:40:13 +0000843 for (i = 0; i < VG_N_SUPP_CALLERS && su->caller[i] != NULL; i++) {
njn25e49d8e72002-09-23 09:36:25 +0000844 switch (su->caller_ty[i]) {
njn4ba5a792002-09-30 10:23:54 +0000845 case ObjName: if (VG_(string_match)(su->caller[i],
846 caller_obj[i])) break;
njn25e49d8e72002-09-23 09:36:25 +0000847 return False;
njn4ba5a792002-09-30 10:23:54 +0000848 case FunName: if (VG_(string_match)(su->caller[i],
849 caller_fun[i])) break;
njn25e49d8e72002-09-23 09:36:25 +0000850 return False;
njn43c799e2003-04-08 00:08:52 +0000851 default: VG_(skin_panic)("supp_matches_callers");
njn25e49d8e72002-09-23 09:36:25 +0000852 }
853 }
854
855 /* If we reach here, it's a match */
856 return True;
857}
sewardjde4a1d02002-03-22 01:27:54 +0000858
njn810086f2002-11-14 12:42:47 +0000859/* Does an error context match a suppression? ie is this a suppressible
860 error? If so, return a pointer to the Supp record, otherwise NULL.
njn25e49d8e72002-09-23 09:36:25 +0000861 Tries to minimise the number of symbol searches since they are expensive.
sewardjde4a1d02002-03-22 01:27:54 +0000862*/
njn810086f2002-11-14 12:42:47 +0000863static Supp* is_suppressible_error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +0000864{
njn25e49d8e72002-09-23 09:36:25 +0000865 Int i;
sewardjde4a1d02002-03-22 01:27:54 +0000866
njn25e49d8e72002-09-23 09:36:25 +0000867 Char caller_obj[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
868 Char caller_fun[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
sewardjde4a1d02002-03-22 01:27:54 +0000869
njn810086f2002-11-14 12:42:47 +0000870 Supp* su;
sewardjde4a1d02002-03-22 01:27:54 +0000871
njn25e49d8e72002-09-23 09:36:25 +0000872 /* get_objname_fnname() writes the function name and object name if
njn43c799e2003-04-08 00:08:52 +0000873 it finds them in the debug info. So the strings in the suppression
njn25e49d8e72002-09-23 09:36:25 +0000874 file should match these.
sewardjde4a1d02002-03-22 01:27:54 +0000875 */
876
877 /* Initialise these strs so they are always safe to compare, even
njn25e49d8e72002-09-23 09:36:25 +0000878 if get_objname_fnname doesn't write anything to them. */
879 for (i = 0; i < VG_N_SUPP_CALLERS; i++)
880 caller_obj[i][0] = caller_fun[i][0] = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000881
njn25e49d8e72002-09-23 09:36:25 +0000882 for (i = 0; i < VG_N_SUPP_CALLERS && i < VG_(clo_backtrace_size); i++) {
njn43c799e2003-04-08 00:08:52 +0000883 get_objname_fnname ( err->where->eips[i], caller_obj[i], M_VG_ERRTXT,
884 caller_fun[i], M_VG_ERRTXT );
sewardjde4a1d02002-03-22 01:27:54 +0000885 }
886
887 /* See if the error context matches any suppression. */
888 for (su = vg_suppressions; su != NULL; su = su->next) {
njn25e49d8e72002-09-23 09:36:25 +0000889 if (supp_matches_error(su, err) &&
890 supp_matches_callers(su, caller_obj, caller_fun)) {
891 return su;
sewardjde4a1d02002-03-22 01:27:54 +0000892 }
sewardjde4a1d02002-03-22 01:27:54 +0000893 }
njn25e49d8e72002-09-23 09:36:25 +0000894 return NULL; /* no matches */
sewardjde4a1d02002-03-22 01:27:54 +0000895}
896
sewardjde4a1d02002-03-22 01:27:54 +0000897/*--------------------------------------------------------------------*/
898/*--- end vg_errcontext.c ---*/
899/*--------------------------------------------------------------------*/