blob: 89baa24c0d0ef418ef627f8eeec2cb5b601ff1bc [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;
sewardja6022612003-07-24 23:50:17 +0000188 err->string = s;
189
njn25e49d8e72002-09-23 09:36:25 +0000190 /* sanity... */
njn72718642003-07-24 08:45:32 +0000191 vg_assert( tid < VG_N_THREADS );
njn25e49d8e72002-09-23 09:36:25 +0000192}
193
njn43c799e2003-04-08 00:08:52 +0000194void VG_(gen_suppression)(Error* err)
195{
sewardj05bcdcb2003-05-18 10:05:38 +0000196 Int i;
njn43c799e2003-04-08 00:08:52 +0000197 UChar buf[M_VG_ERRTXT];
nethercote77eba602003-11-13 17:35:04 +0000198 Bool main_done = False;
njn43c799e2003-04-08 00:08:52 +0000199 ExeContext* ec = VG_(get_error_where)(err);
200 Int stop_at = VG_(clo_backtrace_size);
njn43c799e2003-04-08 00:08:52 +0000201
njn633de322003-05-12 20:40:13 +0000202 if (stop_at > 4) stop_at = 4; /* At most four names */
njn43c799e2003-04-08 00:08:52 +0000203 vg_assert(stop_at > 0);
204
205 VG_(printf)("{\n");
206 VG_(printf)(" <insert a suppression name here>\n");
njn6a230532003-07-21 10:38:23 +0000207
208 if (PThreadErr == err->ekind) {
209 VG_(printf)(" core:PThread\n");
210
211 } else {
212 Char* name = SK_(get_error_name)(err);
213 if (NULL == name) {
214 VG_(message)(Vg_UserMsg,
nethercote137bc552003-11-14 17:47:54 +0000215 "(tool does not allow error to be suppressed)");
njn6a230532003-07-21 10:38:23 +0000216 return;
217 }
218 VG_(printf)(" %s:%s\n", VG_(details).name, name);
219 SK_(print_extra_suppression_info)(err);
220 }
njn43c799e2003-04-08 00:08:52 +0000221
222 /* This loop condensed from VG_(mini_stack_dump)() */
223 i = 0;
224 do {
225 Addr eip = ec->eips[i];
nethercote77eba602003-11-13 17:35:04 +0000226 if (i > 0) eip--; /* point to calling line */
njn43c799e2003-04-08 00:08:52 +0000227 if ( VG_(get_fnname_nodemangle) (eip, buf, M_VG_ERRTXT) ) {
nethercote77eba602003-11-13 17:35:04 +0000228 // Stop after "main"; if main() is recursive, stop after last main().
229
230 if ( ! VG_(clo_show_below_main)) {
231 if (VG_STREQ(buf, "main"))
232 main_done = True;
233 else if (main_done)
234 break;
235 }
njn43c799e2003-04-08 00:08:52 +0000236 VG_(printf)(" fun:%s\n", buf);
237 } else if ( VG_(get_objname)(eip, buf, M_VG_ERRTXT) ) {
238 VG_(printf)(" obj:%s\n", buf);
239 } else {
240 VG_(printf)(" ???:??? "
241 "# unknown, suppression will not work, sorry)\n");
242 }
243 i++;
244 } while (i < stop_at && ec->eips[i] != 0);
245
246 VG_(printf)("}\n");
247}
248
njnb4aee052003-04-15 14:09:58 +0000249static
njn72718642003-07-24 08:45:32 +0000250void do_actions_on_error(Error* err, Bool allow_GDB_attach)
njn43c799e2003-04-08 00:08:52 +0000251{
252 /* Perhaps we want a GDB attach at this point? */
njn3e884182003-04-15 13:03:23 +0000253 if (allow_GDB_attach &&
254 VG_(is_action_requested)( "Attach to GDB", & VG_(clo_GDB_attach) ))
255 {
njn72718642003-07-24 08:45:32 +0000256 Addr m_eip, m_esp, m_ebp;
257
258 if (VG_(is_running_thread)( err->tid )) {
259 m_eip = VG_(baseBlock)[VGOFF_(m_eip)];
260 m_esp = VG_(baseBlock)[VGOFF_(m_esp)];
261 m_ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
262 } else {
263 ThreadState* tst = & VG_(threads)[ err->tid ];
264 m_eip = tst->m_eip;
265 m_esp = tst->m_esp;
266 m_ebp = tst->m_ebp;
267 }
njn3e884182003-04-15 13:03:23 +0000268 VG_(swizzle_esp_then_start_GDB)( m_eip, m_esp, m_ebp );
njn43c799e2003-04-08 00:08:52 +0000269 }
270 /* Or maybe we want to generate the error's suppression? */
271 if (VG_(is_action_requested)( "Print suppression",
272 & VG_(clo_gen_suppressions) )) {
273 VG_(gen_suppression)(err);
274 }
275}
276
277/* Shared between VG_(maybe_record_error)() and VG_(unique_error)(),
278 just for pretty printing purposes. */
279static Bool is_first_shown_context = True;
280
njn25e49d8e72002-09-23 09:36:25 +0000281/* Top-level entry point to the error management subsystem.
282 All detected errors are notified here; this routine decides if/when the
283 user should see the error. */
njn72718642003-07-24 08:45:32 +0000284void VG_(maybe_record_error) ( ThreadId tid,
njn25e49d8e72002-09-23 09:36:25 +0000285 ErrorKind ekind, Addr a, Char* s, void* extra )
286{
njn810086f2002-11-14 12:42:47 +0000287 Error err;
288 Error* p;
289 Error* p_prev;
njn43c799e2003-04-08 00:08:52 +0000290 UInt extra_size;
njn810086f2002-11-14 12:42:47 +0000291 VgRes exe_res = Vg_MedRes;
njn810086f2002-11-14 12:42:47 +0000292 static Bool stopping_message = False;
293 static Bool slowdown_message = False;
294 static Int vg_n_errs_shown = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000295
sewardjf2537be2002-04-24 21:03:47 +0000296 /* After M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
297 been found, or M_VG_COLLECT_NO_ERRORS_AFTER_FOUND total errors
298 have been found, just refuse to collect any more. This stops
299 the burden of the error-management system becoming excessive in
300 extremely buggy programs, although it does make it pretty
301 pointless to continue the Valgrind run after this point. */
sewardj2e432902002-06-13 20:44:00 +0000302 if (VG_(clo_error_limit)
sewardj72f98ff2002-06-13 17:23:38 +0000303 && (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN
njn47363ab2003-04-21 13:24:40 +0000304 || VG_(n_errs_found) >= M_VG_COLLECT_NO_ERRORS_AFTER_FOUND)) {
sewardjde4a1d02002-03-22 01:27:54 +0000305 if (!stopping_message) {
306 VG_(message)(Vg_UserMsg, "");
sewardjf2537be2002-04-24 21:03:47 +0000307
308 if (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN) {
309 VG_(message)(Vg_UserMsg,
310 "More than %d different errors detected. "
311 "I'm not reporting any more.",
312 M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN );
313 } else {
314 VG_(message)(Vg_UserMsg,
315 "More than %d total errors detected. "
316 "I'm not reporting any more.",
317 M_VG_COLLECT_NO_ERRORS_AFTER_FOUND );
318 }
319
sewardjde4a1d02002-03-22 01:27:54 +0000320 VG_(message)(Vg_UserMsg,
sewardjf2537be2002-04-24 21:03:47 +0000321 "Final error counts will be inaccurate. Go fix your program!");
sewardj72f98ff2002-06-13 17:23:38 +0000322 VG_(message)(Vg_UserMsg,
sewardj2e432902002-06-13 20:44:00 +0000323 "Rerun with --error-limit=no to disable this cutoff. Note");
sewardj72f98ff2002-06-13 17:23:38 +0000324 VG_(message)(Vg_UserMsg,
njn25e49d8e72002-09-23 09:36:25 +0000325 "that errors may occur in your program without prior warning from");
sewardj72f98ff2002-06-13 17:23:38 +0000326 VG_(message)(Vg_UserMsg,
327 "Valgrind, because errors are no longer being displayed.");
sewardjde4a1d02002-03-22 01:27:54 +0000328 VG_(message)(Vg_UserMsg, "");
329 stopping_message = True;
330 }
331 return;
332 }
333
334 /* After M_VG_COLLECT_ERRORS_SLOWLY_AFTER different errors have
335 been found, be much more conservative about collecting new
336 ones. */
337 if (vg_n_errs_shown >= M_VG_COLLECT_ERRORS_SLOWLY_AFTER) {
njn25e49d8e72002-09-23 09:36:25 +0000338 exe_res = Vg_LowRes;
sewardjde4a1d02002-03-22 01:27:54 +0000339 if (!slowdown_message) {
340 VG_(message)(Vg_UserMsg, "");
341 VG_(message)(Vg_UserMsg,
342 "More than %d errors detected. Subsequent errors",
343 M_VG_COLLECT_ERRORS_SLOWLY_AFTER);
344 VG_(message)(Vg_UserMsg,
345 "will still be recorded, but in less detail than before.");
346 slowdown_message = True;
347 }
348 }
349
njn25e49d8e72002-09-23 09:36:25 +0000350 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000351 construct_error ( &err, tid, ekind, a, s, extra, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000352
353 /* First, see if we've got an error record matching this one. */
njn25e49d8e72002-09-23 09:36:25 +0000354 p = vg_errors;
sewardjde4a1d02002-03-22 01:27:54 +0000355 p_prev = NULL;
356 while (p != NULL) {
njn810086f2002-11-14 12:42:47 +0000357 if (eq_Error(exe_res, p, &err)) {
sewardjde4a1d02002-03-22 01:27:54 +0000358 /* Found it. */
359 p->count++;
360 if (p->supp != NULL) {
361 /* Deal correctly with suppressed errors. */
362 p->supp->count++;
363 vg_n_errs_suppressed++;
364 } else {
njn47363ab2003-04-21 13:24:40 +0000365 VG_(n_errs_found)++;
sewardjde4a1d02002-03-22 01:27:54 +0000366 }
367
368 /* Move p to the front of the list so that future searches
369 for it are faster. */
370 if (p_prev != NULL) {
371 vg_assert(p_prev->next == p);
372 p_prev->next = p->next;
njn25e49d8e72002-09-23 09:36:25 +0000373 p->next = vg_errors;
374 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000375 }
sewardj7ebf7c32003-07-24 21:29:40 +0000376
sewardjde4a1d02002-03-22 01:27:54 +0000377 return;
378 }
379 p_prev = p;
380 p = p->next;
381 }
382
383 /* Didn't see it. Copy and add. */
384
njn43c799e2003-04-08 00:08:52 +0000385 /* OK, we're really going to collect it. The context is on the stack and
386 will disappear shortly, so we must copy it. First do the main
387 (non-`extra') part.
njn25e49d8e72002-09-23 09:36:25 +0000388
njn43c799e2003-04-08 00:08:52 +0000389 Then SK_(update_extra) can update the `extra' part. This is for when
390 there are more details to fill in which take time to work out but
391 don't affect our earlier decision to include the error -- by
njn25e49d8e72002-09-23 09:36:25 +0000392 postponing those details until now, we avoid the extra work in the
njn810086f2002-11-14 12:42:47 +0000393 case where we ignore the error. Ugly.
njn43c799e2003-04-08 00:08:52 +0000394
395 Then, if there is an `extra' part, copy it too, using the size that
njna70114c2003-08-19 16:14:42 +0000396 SK_(update_extra) returned. Also allow for people using the void*
397 extra field for a scalar value like an integer.
njn43c799e2003-04-08 00:08:52 +0000398 */
399
400 /* copy main part */
njn810086f2002-11-14 12:42:47 +0000401 p = VG_(arena_malloc)(VG_AR_ERRORS, sizeof(Error));
njn25e49d8e72002-09-23 09:36:25 +0000402 *p = err;
njn43c799e2003-04-08 00:08:52 +0000403
njn6a230532003-07-21 10:38:23 +0000404 /* update `extra', for non-core errors (core ones don't use 'extra') */
njna70114c2003-08-19 16:14:42 +0000405 if (VG_(needs).skin_errors && PThreadErr != ekind) {
njn6a230532003-07-21 10:38:23 +0000406 extra_size = SK_(update_extra)(p);
njn43c799e2003-04-08 00:08:52 +0000407
njna70114c2003-08-19 16:14:42 +0000408 /* copy block pointed to by `extra', if there is one */
409 if (NULL != p->extra && 0 != extra_size) {
njn6a230532003-07-21 10:38:23 +0000410 void* new_extra = VG_(malloc)(extra_size);
411 VG_(memcpy)(new_extra, p->extra, extra_size);
412 p->extra = new_extra;
413 }
njn43c799e2003-04-08 00:08:52 +0000414 }
415
njn25e49d8e72002-09-23 09:36:25 +0000416 p->next = vg_errors;
417 p->supp = is_suppressible_error(&err);
418 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000419 if (p->supp == NULL) {
njn47363ab2003-04-21 13:24:40 +0000420 VG_(n_errs_found)++;
sewardjde4a1d02002-03-22 01:27:54 +0000421 if (!is_first_shown_context)
422 VG_(message)(Vg_UserMsg, "");
njn43c799e2003-04-08 00:08:52 +0000423 pp_Error(p, False);
sewardjde4a1d02002-03-22 01:27:54 +0000424 is_first_shown_context = False;
425 vg_n_errs_shown++;
njn72718642003-07-24 08:45:32 +0000426 do_actions_on_error(p, /*allow_GDB_attach*/True);
sewardjde4a1d02002-03-22 01:27:54 +0000427 } else {
428 vg_n_errs_suppressed++;
429 p->supp->count++;
430 }
431}
432
njn43c799e2003-04-08 00:08:52 +0000433/* Second top-level entry point to the error management subsystem, for
434 errors that the skin want to report immediately, eg. because they're
435 guaranteed to only happen once. This avoids all the recording and
436 comparing stuff. But they can be suppressed; returns True if it is
njn47363ab2003-04-21 13:24:40 +0000437 suppressed. Bool `print_error' dictates whether to print the error.
438 Bool `count_error' dictates whether to count the error in VG_(n_errs_found)
439*/
njn72718642003-07-24 08:45:32 +0000440Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, Char* s,
njn3e884182003-04-15 13:03:23 +0000441 void* extra, ExeContext* where, Bool print_error,
njn47363ab2003-04-21 13:24:40 +0000442 Bool allow_GDB_attach, Bool count_error )
njn43c799e2003-04-08 00:08:52 +0000443{
444 Error err;
445
446 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000447 construct_error ( &err, tid, ekind, a, s, extra, where );
njn43c799e2003-04-08 00:08:52 +0000448
449 /* Unless it's suppressed, we're going to show it. Don't need to make
450 a copy, because it's only temporary anyway.
451
452 Then update the `extra' part with SK_(update_extra), because that can
453 have an affect on whether it's suppressed. Ignore the size return
454 value of SK_(update_extra), because we're not copying `extra'. */
455 (void)SK_(update_extra)(&err);
456
457 if (NULL == is_suppressible_error(&err)) {
njn47363ab2003-04-21 13:24:40 +0000458 if (count_error)
459 VG_(n_errs_found)++;
njn43c799e2003-04-08 00:08:52 +0000460
461 if (print_error) {
462 if (!is_first_shown_context)
463 VG_(message)(Vg_UserMsg, "");
464 pp_Error(&err, False);
465 is_first_shown_context = False;
466 }
njn72718642003-07-24 08:45:32 +0000467 do_actions_on_error(&err, allow_GDB_attach);
njn43c799e2003-04-08 00:08:52 +0000468
469 return False;
470
471 } else {
472 vg_n_errs_suppressed++;
473 return True;
474 }
475}
476
sewardjde4a1d02002-03-22 01:27:54 +0000477
sewardjde4a1d02002-03-22 01:27:54 +0000478/*------------------------------------------------------------*/
479/*--- Exported fns ---*/
480/*------------------------------------------------------------*/
481
njn25e49d8e72002-09-23 09:36:25 +0000482/* These are called not from generated code but from the scheduler */
sewardj8c824512002-04-14 04:16:48 +0000483
njn25e49d8e72002-09-23 09:36:25 +0000484void VG_(record_pthread_error) ( ThreadId tid, Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +0000485{
njn25e49d8e72002-09-23 09:36:25 +0000486 if (! VG_(needs).core_errors) return;
njn72718642003-07-24 08:45:32 +0000487 VG_(maybe_record_error)( tid, PThreadErr, /*addr*/0, msg, /*extra*/NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000488}
489
sewardj8c824512002-04-14 04:16:48 +0000490/*------------------------------*/
491
sewardjde4a1d02002-03-22 01:27:54 +0000492void VG_(show_all_errors) ( void )
493{
njn810086f2002-11-14 12:42:47 +0000494 Int i, n_min;
495 Int n_err_contexts, n_supp_contexts;
496 Error *p, *p_min;
497 Supp *su;
498 Bool any_supp;
sewardjde4a1d02002-03-22 01:27:54 +0000499
500 if (VG_(clo_verbosity) == 0)
501 return;
502
503 n_err_contexts = 0;
njn25e49d8e72002-09-23 09:36:25 +0000504 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000505 if (p->supp == NULL)
506 n_err_contexts++;
507 }
508
509 n_supp_contexts = 0;
510 for (su = vg_suppressions; su != NULL; su = su->next) {
511 if (su->count > 0)
512 n_supp_contexts++;
513 }
sewardjde4a1d02002-03-22 01:27:54 +0000514 VG_(message)(Vg_UserMsg,
515 "ERROR SUMMARY: "
516 "%d errors from %d contexts (suppressed: %d from %d)",
njn47363ab2003-04-21 13:24:40 +0000517 VG_(n_errs_found), n_err_contexts,
sewardjde4a1d02002-03-22 01:27:54 +0000518 vg_n_errs_suppressed, n_supp_contexts );
519
520 if (VG_(clo_verbosity) <= 1)
521 return;
522
523 /* Print the contexts in order of increasing error count. */
524 for (i = 0; i < n_err_contexts; i++) {
525 n_min = (1 << 30) - 1;
526 p_min = NULL;
njn25e49d8e72002-09-23 09:36:25 +0000527 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000528 if (p->supp != NULL) continue;
529 if (p->count < n_min) {
530 n_min = p->count;
531 p_min = p;
532 }
533 }
njne427a662002-10-02 11:08:25 +0000534 if (p_min == NULL) VG_(skin_panic)("show_all_errors()");
sewardjde4a1d02002-03-22 01:27:54 +0000535
536 VG_(message)(Vg_UserMsg, "");
537 VG_(message)(Vg_UserMsg, "%d errors in context %d of %d:",
538 p_min->count,
539 i+1, n_err_contexts);
njn810086f2002-11-14 12:42:47 +0000540 pp_Error( p_min, False );
sewardjde4a1d02002-03-22 01:27:54 +0000541
542 if ((i+1 == VG_(clo_dump_error))) {
sewardj1e8cdc92002-04-18 11:37:52 +0000543 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to below NULLs */,
sewardj22854b92002-11-30 14:00:47 +0000544 p_min->where->eips[0], NULL, NULL, NULL, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000545 }
546
547 p_min->count = 1 << 30;
548 }
549
550 if (n_supp_contexts > 0)
551 VG_(message)(Vg_DebugMsg, "");
552 any_supp = False;
553 for (su = vg_suppressions; su != NULL; su = su->next) {
554 if (su->count > 0) {
555 any_supp = True;
njn25e49d8e72002-09-23 09:36:25 +0000556 VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count, su->sname);
sewardjde4a1d02002-03-22 01:27:54 +0000557 }
558 }
559
560 if (n_err_contexts > 0) {
561 if (any_supp)
562 VG_(message)(Vg_UserMsg, "");
563 VG_(message)(Vg_UserMsg,
564 "IN SUMMARY: "
565 "%d errors from %d contexts (suppressed: %d from %d)",
njn47363ab2003-04-21 13:24:40 +0000566 VG_(n_errs_found), n_err_contexts,
sewardjde4a1d02002-03-22 01:27:54 +0000567 vg_n_errs_suppressed,
568 n_supp_contexts );
569 VG_(message)(Vg_UserMsg, "");
570 }
571}
572
573/*------------------------------------------------------------*/
574/*--- Standard suppressions ---*/
575/*------------------------------------------------------------*/
576
577/* Get a non-blank, non-comment line of at most nBuf chars from fd.
578 Skips leading spaces on the line. Return True if EOF was hit instead.
579*/
580
581#define VG_ISSPACE(ch) (((ch)==' ') || ((ch)=='\n') || ((ch)=='\t'))
582
njn4ba5a792002-09-30 10:23:54 +0000583Bool VG_(get_line) ( Int fd, Char* buf, Int nBuf )
sewardjde4a1d02002-03-22 01:27:54 +0000584{
585 Char ch;
586 Int n, i;
587 while (True) {
588 /* First, read until a non-blank char appears. */
589 while (True) {
590 n = VG_(read)(fd, &ch, 1);
591 if (n == 1 && !VG_ISSPACE(ch)) break;
592 if (n == 0) return True;
593 }
594
595 /* Now, read the line into buf. */
596 i = 0;
597 buf[i++] = ch; buf[i] = 0;
598 while (True) {
599 n = VG_(read)(fd, &ch, 1);
600 if (n == 0) return False; /* the next call will return True */
601 if (ch == '\n') break;
602 if (i > 0 && i == nBuf-1) i--;
603 buf[i++] = ch; buf[i] = 0;
604 }
605 while (i > 1 && VG_ISSPACE(buf[i-1])) {
606 i--; buf[i] = 0;
607 };
608
609 /* VG_(printf)("The line is `%s'\n", buf); */
610 /* Ok, we have a line. If a non-comment line, return.
611 If a comment line, start all over again. */
612 if (buf[0] != '#') return False;
613 }
614}
615
616
617/* *p_caller contains the raw name of a caller, supposedly either
618 fun:some_function_name or
619 obj:some_object_name.
620 Set *p_ty accordingly and advance *p_caller over the descriptor
621 (fun: or obj:) part.
622 Returns False if failed.
623*/
njn25e49d8e72002-09-23 09:36:25 +0000624static Bool setLocationTy ( Char** p_caller, SuppLocTy* p_ty )
sewardjde4a1d02002-03-22 01:27:54 +0000625{
626 if (VG_(strncmp)(*p_caller, "fun:", 4) == 0) {
627 (*p_caller) += 4;
628 *p_ty = FunName;
629 return True;
630 }
631 if (VG_(strncmp)(*p_caller, "obj:", 4) == 0) {
632 (*p_caller) += 4;
633 *p_ty = ObjName;
634 return True;
635 }
636 VG_(printf)("location should start with fun: or obj:\n");
637 return False;
638}
639
640
njn11cc9252002-10-07 14:42:59 +0000641/* Look for "skin" in a string like "skin1,skin2,skin3" */
642static __inline__
643Bool skin_name_present(Char *name, Char *names)
644{
645 Bool found;
646 Char *s = NULL; /* Shut gcc up */
647 Int len = VG_(strlen)(name);
648
649 found = (NULL != (s = VG_(strstr)(names, name)) &&
650 (s == names || *(s-1) == ',') &&
651 (*(s+len) == ',' || *(s+len) == '\0')
652 );
653
654 return found;
655}
656
sewardjde4a1d02002-03-22 01:27:54 +0000657/* Read suppressions from the file specified in vg_clo_suppressions
658 and place them in the suppressions list. If there's any difficulty
659 doing this, just give up -- there's no point in trying to recover.
660*/
sewardjde4a1d02002-03-22 01:27:54 +0000661static void load_one_suppressions_file ( Char* filename )
662{
663# define N_BUF 200
njnc40c3a82002-10-02 11:02:27 +0000664 Int fd, i;
665 Bool eof;
666 Char buf[N_BUF+1];
njn11cc9252002-10-07 14:42:59 +0000667 Char* skin_names;
njnc40c3a82002-10-02 11:02:27 +0000668 Char* supp_name;
669
njn25e49d8e72002-09-23 09:36:25 +0000670 fd = VG_(open)( filename, VKI_O_RDONLY, 0 );
jsgff3c3f1a2003-10-14 22:13:28 +0000671 if (fd < 0) {
njn25e49d8e72002-09-23 09:36:25 +0000672 VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file `%s'",
sewardjde4a1d02002-03-22 01:27:54 +0000673 filename );
674 VG_(exit)(1);
675 }
676
677 while (True) {
njn25e49d8e72002-09-23 09:36:25 +0000678 /* Assign and initialise the two suppression halves (core and skin) */
njn810086f2002-11-14 12:42:47 +0000679 Supp* supp;
680 supp = VG_(arena_malloc)(VG_AR_CORE, sizeof(Supp));
sewardjde4a1d02002-03-22 01:27:54 +0000681 supp->count = 0;
njn25e49d8e72002-09-23 09:36:25 +0000682 for (i = 0; i < VG_N_SUPP_CALLERS; i++) supp->caller[i] = NULL;
njn810086f2002-11-14 12:42:47 +0000683 supp->string = supp->extra = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000684
njn4ba5a792002-09-30 10:23:54 +0000685 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000686 if (eof) break;
687
njn43c799e2003-04-08 00:08:52 +0000688 if (!VG_STREQ(buf, "{")) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000689
njn4ba5a792002-09-30 10:23:54 +0000690 eof = VG_(get_line) ( fd, buf, N_BUF );
njn43c799e2003-04-08 00:08:52 +0000691 if (eof || VG_STREQ(buf, "}")) goto syntax_error;
njn25e49d8e72002-09-23 09:36:25 +0000692 supp->sname = VG_(arena_strdup)(VG_AR_CORE, buf);
sewardjde4a1d02002-03-22 01:27:54 +0000693
njn4ba5a792002-09-30 10:23:54 +0000694 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000695
sewardjde4a1d02002-03-22 01:27:54 +0000696 if (eof) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000697
njn11cc9252002-10-07 14:42:59 +0000698 /* Check it has the "skin1,skin2,...:supp" form (look for ':') */
njnc40c3a82002-10-02 11:02:27 +0000699 i = 0;
700 while (True) {
701 if (buf[i] == ':') break;
702 if (buf[i] == '\0') goto syntax_error;
703 i++;
njn25e49d8e72002-09-23 09:36:25 +0000704 }
njnc40c3a82002-10-02 11:02:27 +0000705 buf[i] = '\0'; /* Replace ':', splitting into two strings */
706
njn11cc9252002-10-07 14:42:59 +0000707 skin_names = & buf[0];
708 supp_name = & buf[i+1];
njnc40c3a82002-10-02 11:02:27 +0000709
njn11cc9252002-10-07 14:42:59 +0000710 /* Is it a core suppression? */
711 if (VG_(needs).core_errors && skin_name_present("core", skin_names))
njnc40c3a82002-10-02 11:02:27 +0000712 {
njn43c799e2003-04-08 00:08:52 +0000713 if (VG_STREQ(supp_name, "PThread"))
njn810086f2002-11-14 12:42:47 +0000714 supp->skind = PThreadSupp;
njnc40c3a82002-10-02 11:02:27 +0000715 else
716 goto syntax_error;
717 }
718
njn11cc9252002-10-07 14:42:59 +0000719 /* Is it a skin suppression? */
720 else if (VG_(needs).skin_errors &&
721 skin_name_present(VG_(details).name, skin_names))
njnc40c3a82002-10-02 11:02:27 +0000722 {
njn810086f2002-11-14 12:42:47 +0000723 if (SK_(recognised_suppression)(supp_name, supp))
njnc40c3a82002-10-02 11:02:27 +0000724 {
njn810086f2002-11-14 12:42:47 +0000725 /* Do nothing, function fills in supp->skind */
njnc40c3a82002-10-02 11:02:27 +0000726 } else
727 goto syntax_error;
728 }
729
njn25e49d8e72002-09-23 09:36:25 +0000730 else {
njnc40c3a82002-10-02 11:02:27 +0000731 /* Ignore rest of suppression */
njn25e49d8e72002-09-23 09:36:25 +0000732 while (True) {
njn4ba5a792002-09-30 10:23:54 +0000733 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000734 if (eof) goto syntax_error;
njn43c799e2003-04-08 00:08:52 +0000735 if (VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000736 break;
737 }
738 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000739 }
740
njn25e49d8e72002-09-23 09:36:25 +0000741 if (VG_(needs).skin_errors &&
njn810086f2002-11-14 12:42:47 +0000742 !SK_(read_extra_suppression_info)(fd, buf, N_BUF, supp))
sewardjde4a1d02002-03-22 01:27:54 +0000743 goto syntax_error;
744
njn25e49d8e72002-09-23 09:36:25 +0000745 /* "i > 0" ensures at least one caller read. */
njn633de322003-05-12 20:40:13 +0000746 for (i = 0; i <= VG_N_SUPP_CALLERS; i++) {
njn4ba5a792002-09-30 10:23:54 +0000747 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000748 if (eof) goto syntax_error;
njn43c799e2003-04-08 00:08:52 +0000749 if (i > 0 && VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000750 break;
njn633de322003-05-12 20:40:13 +0000751 if (i == VG_N_SUPP_CALLERS)
752 break;
njn25e49d8e72002-09-23 09:36:25 +0000753 supp->caller[i] = VG_(arena_strdup)(VG_AR_CORE, buf);
754 if (!setLocationTy(&(supp->caller[i]), &(supp->caller_ty[i])))
755 goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000756 }
757
sewardj57a8f5f2003-07-06 01:40:11 +0000758 /* make sure to grab the '}' if the num callers is >=
759 VG_N_SUPP_CALLERS */
760 if (!VG_STREQ(buf, "}")) {
761 do {
762 eof = VG_(get_line) ( fd, buf, N_BUF );
763 } while (!eof && !VG_STREQ(buf, "}"));
764 }
765
sewardjde4a1d02002-03-22 01:27:54 +0000766 supp->next = vg_suppressions;
767 vg_suppressions = supp;
768 }
sewardjde4a1d02002-03-22 01:27:54 +0000769 VG_(close)(fd);
770 return;
771
772 syntax_error:
773 if (eof) {
774 VG_(message)(Vg_UserMsg,
775 "FATAL: in suppressions file `%s': unexpected EOF",
776 filename );
777 } else {
778 VG_(message)(Vg_UserMsg,
njn11cc9252002-10-07 14:42:59 +0000779 "FATAL: in suppressions file: `%s': syntax error on: %s",
sewardjde4a1d02002-03-22 01:27:54 +0000780 filename, buf );
781 }
782 VG_(close)(fd);
783 VG_(message)(Vg_UserMsg, "exiting now.");
784 VG_(exit)(1);
785
786# undef N_BUF
787}
788
789
790void VG_(load_suppressions) ( void )
791{
792 Int i;
793 vg_suppressions = NULL;
794 for (i = 0; i < VG_(clo_n_suppressions); i++) {
795 if (VG_(clo_verbosity) > 1) {
796 VG_(message)(Vg_UserMsg, "Reading suppressions file: %s",
797 VG_(clo_suppressions)[i] );
798 }
799 load_one_suppressions_file( VG_(clo_suppressions)[i] );
800 }
801}
802
njn25e49d8e72002-09-23 09:36:25 +0000803/* Return the name of an erring fn in a way which is useful
804 for comparing against the contents of a suppressions file.
805 Doesn't demangle the fn name, because we want to refer to
806 mangled names in the suppressions file.
sewardj99aac972002-12-26 01:53:45 +0000807*/
njn43c799e2003-04-08 00:08:52 +0000808static void get_objname_fnname ( Addr a, Char* obj_buf, Int n_obj_buf,
809 Char* fun_buf, Int n_fun_buf )
njn25e49d8e72002-09-23 09:36:25 +0000810{
811 (void)VG_(get_objname) ( a, obj_buf, n_obj_buf );
812 (void)VG_(get_fnname_nodemangle)( a, fun_buf, n_fun_buf );
813}
814
815static __inline__
njn810086f2002-11-14 12:42:47 +0000816Bool supp_matches_error(Supp* su, Error* err)
njn25e49d8e72002-09-23 09:36:25 +0000817{
njn810086f2002-11-14 12:42:47 +0000818 switch (su->skind) {
njn25e49d8e72002-09-23 09:36:25 +0000819 case PThreadSupp:
njn810086f2002-11-14 12:42:47 +0000820 return (err->ekind == PThreadErr);
njn25e49d8e72002-09-23 09:36:25 +0000821 default:
822 if (VG_(needs).skin_errors) {
njn810086f2002-11-14 12:42:47 +0000823 return SK_(error_matches_suppression)(err, su);
njn25e49d8e72002-09-23 09:36:25 +0000824 } else {
825 VG_(printf)(
826 "\nUnhandled suppression type: %u. VG_(needs).skin_errors\n"
827 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000828 err->ekind);
njne427a662002-10-02 11:08:25 +0000829 VG_(skin_panic)("unhandled suppression type");
njn25e49d8e72002-09-23 09:36:25 +0000830 }
831 }
832}
833
834static __inline__
njn810086f2002-11-14 12:42:47 +0000835Bool supp_matches_callers(Supp* su, Char caller_obj[][M_VG_ERRTXT],
836 Char caller_fun[][M_VG_ERRTXT])
njn25e49d8e72002-09-23 09:36:25 +0000837{
838 Int i;
839
njn633de322003-05-12 20:40:13 +0000840 for (i = 0; i < VG_N_SUPP_CALLERS && su->caller[i] != NULL; i++) {
njn25e49d8e72002-09-23 09:36:25 +0000841 switch (su->caller_ty[i]) {
njn4ba5a792002-09-30 10:23:54 +0000842 case ObjName: if (VG_(string_match)(su->caller[i],
843 caller_obj[i])) break;
njn25e49d8e72002-09-23 09:36:25 +0000844 return False;
njn4ba5a792002-09-30 10:23:54 +0000845 case FunName: if (VG_(string_match)(su->caller[i],
846 caller_fun[i])) break;
njn25e49d8e72002-09-23 09:36:25 +0000847 return False;
njn43c799e2003-04-08 00:08:52 +0000848 default: VG_(skin_panic)("supp_matches_callers");
njn25e49d8e72002-09-23 09:36:25 +0000849 }
850 }
851
852 /* If we reach here, it's a match */
853 return True;
854}
sewardjde4a1d02002-03-22 01:27:54 +0000855
njn810086f2002-11-14 12:42:47 +0000856/* Does an error context match a suppression? ie is this a suppressible
857 error? If so, return a pointer to the Supp record, otherwise NULL.
njn25e49d8e72002-09-23 09:36:25 +0000858 Tries to minimise the number of symbol searches since they are expensive.
sewardjde4a1d02002-03-22 01:27:54 +0000859*/
njn810086f2002-11-14 12:42:47 +0000860static Supp* is_suppressible_error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +0000861{
njn25e49d8e72002-09-23 09:36:25 +0000862 Int i;
sewardjde4a1d02002-03-22 01:27:54 +0000863
njn25e49d8e72002-09-23 09:36:25 +0000864 Char caller_obj[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
865 Char caller_fun[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
sewardjde4a1d02002-03-22 01:27:54 +0000866
njn810086f2002-11-14 12:42:47 +0000867 Supp* su;
sewardjde4a1d02002-03-22 01:27:54 +0000868
njn25e49d8e72002-09-23 09:36:25 +0000869 /* get_objname_fnname() writes the function name and object name if
njn43c799e2003-04-08 00:08:52 +0000870 it finds them in the debug info. So the strings in the suppression
njn25e49d8e72002-09-23 09:36:25 +0000871 file should match these.
sewardjde4a1d02002-03-22 01:27:54 +0000872 */
873
874 /* Initialise these strs so they are always safe to compare, even
njn25e49d8e72002-09-23 09:36:25 +0000875 if get_objname_fnname doesn't write anything to them. */
876 for (i = 0; i < VG_N_SUPP_CALLERS; i++)
877 caller_obj[i][0] = caller_fun[i][0] = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000878
njn25e49d8e72002-09-23 09:36:25 +0000879 for (i = 0; i < VG_N_SUPP_CALLERS && i < VG_(clo_backtrace_size); i++) {
njn43c799e2003-04-08 00:08:52 +0000880 get_objname_fnname ( err->where->eips[i], caller_obj[i], M_VG_ERRTXT,
881 caller_fun[i], M_VG_ERRTXT );
sewardjde4a1d02002-03-22 01:27:54 +0000882 }
883
884 /* See if the error context matches any suppression. */
885 for (su = vg_suppressions; su != NULL; su = su->next) {
njn25e49d8e72002-09-23 09:36:25 +0000886 if (supp_matches_error(su, err) &&
887 supp_matches_callers(su, caller_obj, caller_fun)) {
888 return su;
sewardjde4a1d02002-03-22 01:27:54 +0000889 }
sewardjde4a1d02002-03-22 01:27:54 +0000890 }
njn25e49d8e72002-09-23 09:36:25 +0000891 return NULL; /* no matches */
sewardjde4a1d02002-03-22 01:27:54 +0000892}
893
sewardjde4a1d02002-03-22 01:27:54 +0000894/*--------------------------------------------------------------------*/
895/*--- end vg_errcontext.c ---*/
896/*--------------------------------------------------------------------*/