blob: 745e34553b1fe4dacd9403c87da26e6f71e6c427 [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
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 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
nethercote04d0fbc2004-01-26 16:48:06 +0000114/* Figure out if we want to perform a given action for this error, possibly
sewardjde4a1d02002-03-22 01:27:54 +0000115 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
nethercote10d481a2004-01-25 20:33:53 +0000194static void gen_suppression(Error* err)
njn43c799e2003-04-08 00:08:52 +0000195{
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
nethercote04d0fbc2004-01-26 16:48:06 +0000250void do_actions_on_error(Error* err, Bool allow_db_attach)
njn43c799e2003-04-08 00:08:52 +0000251{
nethercote04d0fbc2004-01-26 16:48:06 +0000252 /* Perhaps we want a debugger attach at this point? */
253 if (allow_db_attach &&
254 VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) ))
njn3e884182003-04-15 13:03:23 +0000255 {
nethercote04d0fbc2004-01-26 16:48:06 +0000256 VG_(printf)("starting debugger\n");
257 VG_(start_debugger)( err->tid );
njn43c799e2003-04-08 00:08:52 +0000258 }
259 /* Or maybe we want to generate the error's suppression? */
260 if (VG_(is_action_requested)( "Print suppression",
261 & VG_(clo_gen_suppressions) )) {
nethercote42602b12004-01-25 19:30:29 +0000262 gen_suppression(err);
njn43c799e2003-04-08 00:08:52 +0000263 }
264}
265
266/* Shared between VG_(maybe_record_error)() and VG_(unique_error)(),
267 just for pretty printing purposes. */
268static Bool is_first_shown_context = True;
269
njn25e49d8e72002-09-23 09:36:25 +0000270/* Top-level entry point to the error management subsystem.
271 All detected errors are notified here; this routine decides if/when the
272 user should see the error. */
njn72718642003-07-24 08:45:32 +0000273void VG_(maybe_record_error) ( ThreadId tid,
njn25e49d8e72002-09-23 09:36:25 +0000274 ErrorKind ekind, Addr a, Char* s, void* extra )
275{
njn810086f2002-11-14 12:42:47 +0000276 Error err;
277 Error* p;
278 Error* p_prev;
njn43c799e2003-04-08 00:08:52 +0000279 UInt extra_size;
njn810086f2002-11-14 12:42:47 +0000280 VgRes exe_res = Vg_MedRes;
njn810086f2002-11-14 12:42:47 +0000281 static Bool stopping_message = False;
282 static Bool slowdown_message = False;
283 static Int vg_n_errs_shown = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000284
sewardjf2537be2002-04-24 21:03:47 +0000285 /* After M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
286 been found, or M_VG_COLLECT_NO_ERRORS_AFTER_FOUND total errors
287 have been found, just refuse to collect any more. This stops
288 the burden of the error-management system becoming excessive in
289 extremely buggy programs, although it does make it pretty
290 pointless to continue the Valgrind run after this point. */
sewardj2e432902002-06-13 20:44:00 +0000291 if (VG_(clo_error_limit)
sewardj72f98ff2002-06-13 17:23:38 +0000292 && (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN
njn47363ab2003-04-21 13:24:40 +0000293 || VG_(n_errs_found) >= M_VG_COLLECT_NO_ERRORS_AFTER_FOUND)) {
sewardjde4a1d02002-03-22 01:27:54 +0000294 if (!stopping_message) {
295 VG_(message)(Vg_UserMsg, "");
sewardjf2537be2002-04-24 21:03:47 +0000296
297 if (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN) {
298 VG_(message)(Vg_UserMsg,
299 "More than %d different errors detected. "
300 "I'm not reporting any more.",
301 M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN );
302 } else {
303 VG_(message)(Vg_UserMsg,
304 "More than %d total errors detected. "
305 "I'm not reporting any more.",
306 M_VG_COLLECT_NO_ERRORS_AFTER_FOUND );
307 }
308
sewardjde4a1d02002-03-22 01:27:54 +0000309 VG_(message)(Vg_UserMsg,
sewardjf2537be2002-04-24 21:03:47 +0000310 "Final error counts will be inaccurate. Go fix your program!");
sewardj72f98ff2002-06-13 17:23:38 +0000311 VG_(message)(Vg_UserMsg,
sewardj2e432902002-06-13 20:44:00 +0000312 "Rerun with --error-limit=no to disable this cutoff. Note");
sewardj72f98ff2002-06-13 17:23:38 +0000313 VG_(message)(Vg_UserMsg,
njn25e49d8e72002-09-23 09:36:25 +0000314 "that errors may occur in your program without prior warning from");
sewardj72f98ff2002-06-13 17:23:38 +0000315 VG_(message)(Vg_UserMsg,
316 "Valgrind, because errors are no longer being displayed.");
sewardjde4a1d02002-03-22 01:27:54 +0000317 VG_(message)(Vg_UserMsg, "");
318 stopping_message = True;
319 }
320 return;
321 }
322
323 /* After M_VG_COLLECT_ERRORS_SLOWLY_AFTER different errors have
324 been found, be much more conservative about collecting new
325 ones. */
326 if (vg_n_errs_shown >= M_VG_COLLECT_ERRORS_SLOWLY_AFTER) {
njn25e49d8e72002-09-23 09:36:25 +0000327 exe_res = Vg_LowRes;
sewardjde4a1d02002-03-22 01:27:54 +0000328 if (!slowdown_message) {
329 VG_(message)(Vg_UserMsg, "");
330 VG_(message)(Vg_UserMsg,
331 "More than %d errors detected. Subsequent errors",
332 M_VG_COLLECT_ERRORS_SLOWLY_AFTER);
333 VG_(message)(Vg_UserMsg,
334 "will still be recorded, but in less detail than before.");
335 slowdown_message = True;
336 }
337 }
338
njn25e49d8e72002-09-23 09:36:25 +0000339 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000340 construct_error ( &err, tid, ekind, a, s, extra, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000341
342 /* First, see if we've got an error record matching this one. */
njn25e49d8e72002-09-23 09:36:25 +0000343 p = vg_errors;
sewardjde4a1d02002-03-22 01:27:54 +0000344 p_prev = NULL;
345 while (p != NULL) {
njn810086f2002-11-14 12:42:47 +0000346 if (eq_Error(exe_res, p, &err)) {
sewardjde4a1d02002-03-22 01:27:54 +0000347 /* Found it. */
348 p->count++;
349 if (p->supp != NULL) {
350 /* Deal correctly with suppressed errors. */
351 p->supp->count++;
352 vg_n_errs_suppressed++;
353 } else {
njn47363ab2003-04-21 13:24:40 +0000354 VG_(n_errs_found)++;
sewardjde4a1d02002-03-22 01:27:54 +0000355 }
356
357 /* Move p to the front of the list so that future searches
358 for it are faster. */
359 if (p_prev != NULL) {
360 vg_assert(p_prev->next == p);
361 p_prev->next = p->next;
njn25e49d8e72002-09-23 09:36:25 +0000362 p->next = vg_errors;
363 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000364 }
sewardj7ebf7c32003-07-24 21:29:40 +0000365
sewardjde4a1d02002-03-22 01:27:54 +0000366 return;
367 }
368 p_prev = p;
369 p = p->next;
370 }
371
372 /* Didn't see it. Copy and add. */
373
njn43c799e2003-04-08 00:08:52 +0000374 /* OK, we're really going to collect it. The context is on the stack and
375 will disappear shortly, so we must copy it. First do the main
376 (non-`extra') part.
njn25e49d8e72002-09-23 09:36:25 +0000377
njn43c799e2003-04-08 00:08:52 +0000378 Then SK_(update_extra) can update the `extra' part. This is for when
379 there are more details to fill in which take time to work out but
380 don't affect our earlier decision to include the error -- by
njn25e49d8e72002-09-23 09:36:25 +0000381 postponing those details until now, we avoid the extra work in the
njn810086f2002-11-14 12:42:47 +0000382 case where we ignore the error. Ugly.
njn43c799e2003-04-08 00:08:52 +0000383
384 Then, if there is an `extra' part, copy it too, using the size that
njna70114c2003-08-19 16:14:42 +0000385 SK_(update_extra) returned. Also allow for people using the void*
386 extra field for a scalar value like an integer.
njn43c799e2003-04-08 00:08:52 +0000387 */
388
389 /* copy main part */
njn810086f2002-11-14 12:42:47 +0000390 p = VG_(arena_malloc)(VG_AR_ERRORS, sizeof(Error));
njn25e49d8e72002-09-23 09:36:25 +0000391 *p = err;
njn43c799e2003-04-08 00:08:52 +0000392
njn6a230532003-07-21 10:38:23 +0000393 /* update `extra', for non-core errors (core ones don't use 'extra') */
njna70114c2003-08-19 16:14:42 +0000394 if (VG_(needs).skin_errors && PThreadErr != ekind) {
njn6a230532003-07-21 10:38:23 +0000395 extra_size = SK_(update_extra)(p);
njn43c799e2003-04-08 00:08:52 +0000396
njna70114c2003-08-19 16:14:42 +0000397 /* copy block pointed to by `extra', if there is one */
398 if (NULL != p->extra && 0 != extra_size) {
njn6a230532003-07-21 10:38:23 +0000399 void* new_extra = VG_(malloc)(extra_size);
400 VG_(memcpy)(new_extra, p->extra, extra_size);
401 p->extra = new_extra;
402 }
njn43c799e2003-04-08 00:08:52 +0000403 }
404
njn25e49d8e72002-09-23 09:36:25 +0000405 p->next = vg_errors;
406 p->supp = is_suppressible_error(&err);
407 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000408 if (p->supp == NULL) {
njn47363ab2003-04-21 13:24:40 +0000409 VG_(n_errs_found)++;
sewardjde4a1d02002-03-22 01:27:54 +0000410 if (!is_first_shown_context)
411 VG_(message)(Vg_UserMsg, "");
njn43c799e2003-04-08 00:08:52 +0000412 pp_Error(p, False);
sewardjde4a1d02002-03-22 01:27:54 +0000413 is_first_shown_context = False;
414 vg_n_errs_shown++;
nethercote04d0fbc2004-01-26 16:48:06 +0000415 do_actions_on_error(p, /*allow_db_attach*/True);
sewardjde4a1d02002-03-22 01:27:54 +0000416 } else {
417 vg_n_errs_suppressed++;
418 p->supp->count++;
419 }
420}
421
njn43c799e2003-04-08 00:08:52 +0000422/* Second top-level entry point to the error management subsystem, for
nethercote7cc9c232004-01-21 15:08:04 +0000423 errors that the tool wants to report immediately, eg. because they're
njn43c799e2003-04-08 00:08:52 +0000424 guaranteed to only happen once. This avoids all the recording and
425 comparing stuff. But they can be suppressed; returns True if it is
njn47363ab2003-04-21 13:24:40 +0000426 suppressed. Bool `print_error' dictates whether to print the error.
427 Bool `count_error' dictates whether to count the error in VG_(n_errs_found)
428*/
njn72718642003-07-24 08:45:32 +0000429Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, Char* s,
njn3e884182003-04-15 13:03:23 +0000430 void* extra, ExeContext* where, Bool print_error,
nethercote04d0fbc2004-01-26 16:48:06 +0000431 Bool allow_db_attach, Bool count_error )
njn43c799e2003-04-08 00:08:52 +0000432{
433 Error err;
434
435 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000436 construct_error ( &err, tid, ekind, a, s, extra, where );
njn43c799e2003-04-08 00:08:52 +0000437
438 /* Unless it's suppressed, we're going to show it. Don't need to make
439 a copy, because it's only temporary anyway.
440
441 Then update the `extra' part with SK_(update_extra), because that can
442 have an affect on whether it's suppressed. Ignore the size return
443 value of SK_(update_extra), because we're not copying `extra'. */
444 (void)SK_(update_extra)(&err);
445
446 if (NULL == is_suppressible_error(&err)) {
njn47363ab2003-04-21 13:24:40 +0000447 if (count_error)
448 VG_(n_errs_found)++;
njn43c799e2003-04-08 00:08:52 +0000449
450 if (print_error) {
451 if (!is_first_shown_context)
452 VG_(message)(Vg_UserMsg, "");
453 pp_Error(&err, False);
454 is_first_shown_context = False;
455 }
nethercote04d0fbc2004-01-26 16:48:06 +0000456 do_actions_on_error(&err, allow_db_attach);
njn43c799e2003-04-08 00:08:52 +0000457
458 return False;
459
460 } else {
461 vg_n_errs_suppressed++;
462 return True;
463 }
464}
465
sewardjde4a1d02002-03-22 01:27:54 +0000466
sewardjde4a1d02002-03-22 01:27:54 +0000467/*------------------------------------------------------------*/
468/*--- Exported fns ---*/
469/*------------------------------------------------------------*/
470
njn25e49d8e72002-09-23 09:36:25 +0000471/* These are called not from generated code but from the scheduler */
sewardj8c824512002-04-14 04:16:48 +0000472
njn25e49d8e72002-09-23 09:36:25 +0000473void VG_(record_pthread_error) ( ThreadId tid, Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +0000474{
njn25e49d8e72002-09-23 09:36:25 +0000475 if (! VG_(needs).core_errors) return;
njn72718642003-07-24 08:45:32 +0000476 VG_(maybe_record_error)( tid, PThreadErr, /*addr*/0, msg, /*extra*/NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000477}
478
sewardj8c824512002-04-14 04:16:48 +0000479/*------------------------------*/
480
sewardjde4a1d02002-03-22 01:27:54 +0000481void VG_(show_all_errors) ( void )
482{
njn810086f2002-11-14 12:42:47 +0000483 Int i, n_min;
484 Int n_err_contexts, n_supp_contexts;
485 Error *p, *p_min;
486 Supp *su;
487 Bool any_supp;
sewardjde4a1d02002-03-22 01:27:54 +0000488
489 if (VG_(clo_verbosity) == 0)
490 return;
491
492 n_err_contexts = 0;
njn25e49d8e72002-09-23 09:36:25 +0000493 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000494 if (p->supp == NULL)
495 n_err_contexts++;
496 }
497
498 n_supp_contexts = 0;
499 for (su = vg_suppressions; su != NULL; su = su->next) {
500 if (su->count > 0)
501 n_supp_contexts++;
502 }
sewardjde4a1d02002-03-22 01:27:54 +0000503 VG_(message)(Vg_UserMsg,
504 "ERROR SUMMARY: "
505 "%d errors from %d contexts (suppressed: %d from %d)",
njn47363ab2003-04-21 13:24:40 +0000506 VG_(n_errs_found), n_err_contexts,
sewardjde4a1d02002-03-22 01:27:54 +0000507 vg_n_errs_suppressed, n_supp_contexts );
508
509 if (VG_(clo_verbosity) <= 1)
510 return;
511
512 /* Print the contexts in order of increasing error count. */
513 for (i = 0; i < n_err_contexts; i++) {
514 n_min = (1 << 30) - 1;
515 p_min = NULL;
njn25e49d8e72002-09-23 09:36:25 +0000516 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000517 if (p->supp != NULL) continue;
518 if (p->count < n_min) {
519 n_min = p->count;
520 p_min = p;
521 }
522 }
njne427a662002-10-02 11:08:25 +0000523 if (p_min == NULL) VG_(skin_panic)("show_all_errors()");
sewardjde4a1d02002-03-22 01:27:54 +0000524
525 VG_(message)(Vg_UserMsg, "");
526 VG_(message)(Vg_UserMsg, "%d errors in context %d of %d:",
527 p_min->count,
528 i+1, n_err_contexts);
njn810086f2002-11-14 12:42:47 +0000529 pp_Error( p_min, False );
sewardjde4a1d02002-03-22 01:27:54 +0000530
531 if ((i+1 == VG_(clo_dump_error))) {
sewardj1e8cdc92002-04-18 11:37:52 +0000532 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to below NULLs */,
sewardj22854b92002-11-30 14:00:47 +0000533 p_min->where->eips[0], NULL, NULL, NULL, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000534 }
535
536 p_min->count = 1 << 30;
537 }
538
539 if (n_supp_contexts > 0)
540 VG_(message)(Vg_DebugMsg, "");
541 any_supp = False;
542 for (su = vg_suppressions; su != NULL; su = su->next) {
543 if (su->count > 0) {
544 any_supp = True;
njn25e49d8e72002-09-23 09:36:25 +0000545 VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count, su->sname);
sewardjde4a1d02002-03-22 01:27:54 +0000546 }
547 }
548
549 if (n_err_contexts > 0) {
550 if (any_supp)
551 VG_(message)(Vg_UserMsg, "");
552 VG_(message)(Vg_UserMsg,
553 "IN SUMMARY: "
554 "%d errors from %d contexts (suppressed: %d from %d)",
njn47363ab2003-04-21 13:24:40 +0000555 VG_(n_errs_found), n_err_contexts,
sewardjde4a1d02002-03-22 01:27:54 +0000556 vg_n_errs_suppressed,
557 n_supp_contexts );
558 VG_(message)(Vg_UserMsg, "");
559 }
560}
561
562/*------------------------------------------------------------*/
563/*--- Standard suppressions ---*/
564/*------------------------------------------------------------*/
565
566/* Get a non-blank, non-comment line of at most nBuf chars from fd.
567 Skips leading spaces on the line. Return True if EOF was hit instead.
568*/
569
570#define VG_ISSPACE(ch) (((ch)==' ') || ((ch)=='\n') || ((ch)=='\t'))
571
njn4ba5a792002-09-30 10:23:54 +0000572Bool VG_(get_line) ( Int fd, Char* buf, Int nBuf )
sewardjde4a1d02002-03-22 01:27:54 +0000573{
574 Char ch;
575 Int n, i;
576 while (True) {
577 /* First, read until a non-blank char appears. */
578 while (True) {
579 n = VG_(read)(fd, &ch, 1);
580 if (n == 1 && !VG_ISSPACE(ch)) break;
581 if (n == 0) return True;
582 }
583
584 /* Now, read the line into buf. */
585 i = 0;
586 buf[i++] = ch; buf[i] = 0;
587 while (True) {
588 n = VG_(read)(fd, &ch, 1);
589 if (n == 0) return False; /* the next call will return True */
590 if (ch == '\n') break;
591 if (i > 0 && i == nBuf-1) i--;
592 buf[i++] = ch; buf[i] = 0;
593 }
594 while (i > 1 && VG_ISSPACE(buf[i-1])) {
595 i--; buf[i] = 0;
596 };
597
598 /* VG_(printf)("The line is `%s'\n", buf); */
599 /* Ok, we have a line. If a non-comment line, return.
600 If a comment line, start all over again. */
601 if (buf[0] != '#') return False;
602 }
603}
604
605
606/* *p_caller contains the raw name of a caller, supposedly either
607 fun:some_function_name or
608 obj:some_object_name.
609 Set *p_ty accordingly and advance *p_caller over the descriptor
610 (fun: or obj:) part.
611 Returns False if failed.
612*/
njn25e49d8e72002-09-23 09:36:25 +0000613static Bool setLocationTy ( Char** p_caller, SuppLocTy* p_ty )
sewardjde4a1d02002-03-22 01:27:54 +0000614{
615 if (VG_(strncmp)(*p_caller, "fun:", 4) == 0) {
616 (*p_caller) += 4;
617 *p_ty = FunName;
618 return True;
619 }
620 if (VG_(strncmp)(*p_caller, "obj:", 4) == 0) {
621 (*p_caller) += 4;
622 *p_ty = ObjName;
623 return True;
624 }
625 VG_(printf)("location should start with fun: or obj:\n");
626 return False;
627}
628
629
nethercote7cc9c232004-01-21 15:08:04 +0000630/* Look for "tool" in a string like "tool1,tool2,tool3" */
njn11cc9252002-10-07 14:42:59 +0000631static __inline__
nethercote7cc9c232004-01-21 15:08:04 +0000632Bool tool_name_present(Char *name, Char *names)
njn11cc9252002-10-07 14:42:59 +0000633{
634 Bool found;
635 Char *s = NULL; /* Shut gcc up */
636 Int len = VG_(strlen)(name);
637
638 found = (NULL != (s = VG_(strstr)(names, name)) &&
639 (s == names || *(s-1) == ',') &&
640 (*(s+len) == ',' || *(s+len) == '\0')
641 );
642
643 return found;
644}
645
sewardjde4a1d02002-03-22 01:27:54 +0000646/* Read suppressions from the file specified in vg_clo_suppressions
647 and place them in the suppressions list. If there's any difficulty
648 doing this, just give up -- there's no point in trying to recover.
649*/
sewardjde4a1d02002-03-22 01:27:54 +0000650static void load_one_suppressions_file ( Char* filename )
651{
652# define N_BUF 200
njnc40c3a82002-10-02 11:02:27 +0000653 Int fd, i;
654 Bool eof;
655 Char buf[N_BUF+1];
nethercote7cc9c232004-01-21 15:08:04 +0000656 Char* tool_names;
njnc40c3a82002-10-02 11:02:27 +0000657 Char* supp_name;
658
njn25e49d8e72002-09-23 09:36:25 +0000659 fd = VG_(open)( filename, VKI_O_RDONLY, 0 );
jsgff3c3f1a2003-10-14 22:13:28 +0000660 if (fd < 0) {
njn25e49d8e72002-09-23 09:36:25 +0000661 VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file `%s'",
sewardjde4a1d02002-03-22 01:27:54 +0000662 filename );
663 VG_(exit)(1);
664 }
665
666 while (True) {
nethercote7cc9c232004-01-21 15:08:04 +0000667 /* Assign and initialise the two suppression halves (core and tool) */
njn810086f2002-11-14 12:42:47 +0000668 Supp* supp;
669 supp = VG_(arena_malloc)(VG_AR_CORE, sizeof(Supp));
sewardjde4a1d02002-03-22 01:27:54 +0000670 supp->count = 0;
njn25e49d8e72002-09-23 09:36:25 +0000671 for (i = 0; i < VG_N_SUPP_CALLERS; i++) supp->caller[i] = NULL;
njn810086f2002-11-14 12:42:47 +0000672 supp->string = supp->extra = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000673
njn4ba5a792002-09-30 10:23:54 +0000674 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000675 if (eof) break;
676
njn43c799e2003-04-08 00:08:52 +0000677 if (!VG_STREQ(buf, "{")) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000678
njn4ba5a792002-09-30 10:23:54 +0000679 eof = VG_(get_line) ( fd, buf, N_BUF );
njn43c799e2003-04-08 00:08:52 +0000680 if (eof || VG_STREQ(buf, "}")) goto syntax_error;
njn25e49d8e72002-09-23 09:36:25 +0000681 supp->sname = VG_(arena_strdup)(VG_AR_CORE, buf);
sewardjde4a1d02002-03-22 01:27:54 +0000682
njn4ba5a792002-09-30 10:23:54 +0000683 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000684
sewardjde4a1d02002-03-22 01:27:54 +0000685 if (eof) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000686
njn11cc9252002-10-07 14:42:59 +0000687 /* Check it has the "skin1,skin2,...:supp" form (look for ':') */
njnc40c3a82002-10-02 11:02:27 +0000688 i = 0;
689 while (True) {
690 if (buf[i] == ':') break;
691 if (buf[i] == '\0') goto syntax_error;
692 i++;
njn25e49d8e72002-09-23 09:36:25 +0000693 }
njnc40c3a82002-10-02 11:02:27 +0000694 buf[i] = '\0'; /* Replace ':', splitting into two strings */
695
nethercote7cc9c232004-01-21 15:08:04 +0000696 tool_names = & buf[0];
njn11cc9252002-10-07 14:42:59 +0000697 supp_name = & buf[i+1];
njnc40c3a82002-10-02 11:02:27 +0000698
njn11cc9252002-10-07 14:42:59 +0000699 /* Is it a core suppression? */
nethercote7cc9c232004-01-21 15:08:04 +0000700 if (VG_(needs).core_errors && tool_name_present("core", tool_names))
njnc40c3a82002-10-02 11:02:27 +0000701 {
njn43c799e2003-04-08 00:08:52 +0000702 if (VG_STREQ(supp_name, "PThread"))
njn810086f2002-11-14 12:42:47 +0000703 supp->skind = PThreadSupp;
njnc40c3a82002-10-02 11:02:27 +0000704 else
705 goto syntax_error;
706 }
707
nethercote7cc9c232004-01-21 15:08:04 +0000708 /* Is it a tool suppression? */
njn11cc9252002-10-07 14:42:59 +0000709 else if (VG_(needs).skin_errors &&
nethercote7cc9c232004-01-21 15:08:04 +0000710 tool_name_present(VG_(details).name, tool_names))
njnc40c3a82002-10-02 11:02:27 +0000711 {
njn810086f2002-11-14 12:42:47 +0000712 if (SK_(recognised_suppression)(supp_name, supp))
njnc40c3a82002-10-02 11:02:27 +0000713 {
njn810086f2002-11-14 12:42:47 +0000714 /* Do nothing, function fills in supp->skind */
njnc40c3a82002-10-02 11:02:27 +0000715 } else
716 goto syntax_error;
717 }
718
njn25e49d8e72002-09-23 09:36:25 +0000719 else {
njnc40c3a82002-10-02 11:02:27 +0000720 /* Ignore rest of suppression */
njn25e49d8e72002-09-23 09:36:25 +0000721 while (True) {
njn4ba5a792002-09-30 10:23:54 +0000722 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000723 if (eof) goto syntax_error;
njn43c799e2003-04-08 00:08:52 +0000724 if (VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000725 break;
726 }
727 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000728 }
729
njn25e49d8e72002-09-23 09:36:25 +0000730 if (VG_(needs).skin_errors &&
njn810086f2002-11-14 12:42:47 +0000731 !SK_(read_extra_suppression_info)(fd, buf, N_BUF, supp))
sewardjde4a1d02002-03-22 01:27:54 +0000732 goto syntax_error;
733
njn25e49d8e72002-09-23 09:36:25 +0000734 /* "i > 0" ensures at least one caller read. */
njn633de322003-05-12 20:40:13 +0000735 for (i = 0; i <= VG_N_SUPP_CALLERS; i++) {
njn4ba5a792002-09-30 10:23:54 +0000736 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000737 if (eof) goto syntax_error;
njn43c799e2003-04-08 00:08:52 +0000738 if (i > 0 && VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000739 break;
njn633de322003-05-12 20:40:13 +0000740 if (i == VG_N_SUPP_CALLERS)
741 break;
njn25e49d8e72002-09-23 09:36:25 +0000742 supp->caller[i] = VG_(arena_strdup)(VG_AR_CORE, buf);
743 if (!setLocationTy(&(supp->caller[i]), &(supp->caller_ty[i])))
744 goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000745 }
746
sewardj57a8f5f2003-07-06 01:40:11 +0000747 /* make sure to grab the '}' if the num callers is >=
748 VG_N_SUPP_CALLERS */
749 if (!VG_STREQ(buf, "}")) {
750 do {
751 eof = VG_(get_line) ( fd, buf, N_BUF );
752 } while (!eof && !VG_STREQ(buf, "}"));
753 }
754
sewardjde4a1d02002-03-22 01:27:54 +0000755 supp->next = vg_suppressions;
756 vg_suppressions = supp;
757 }
sewardjde4a1d02002-03-22 01:27:54 +0000758 VG_(close)(fd);
759 return;
760
761 syntax_error:
762 if (eof) {
763 VG_(message)(Vg_UserMsg,
764 "FATAL: in suppressions file `%s': unexpected EOF",
765 filename );
766 } else {
767 VG_(message)(Vg_UserMsg,
njn11cc9252002-10-07 14:42:59 +0000768 "FATAL: in suppressions file: `%s': syntax error on: %s",
sewardjde4a1d02002-03-22 01:27:54 +0000769 filename, buf );
770 }
771 VG_(close)(fd);
772 VG_(message)(Vg_UserMsg, "exiting now.");
773 VG_(exit)(1);
774
775# undef N_BUF
776}
777
778
779void VG_(load_suppressions) ( void )
780{
781 Int i;
782 vg_suppressions = NULL;
783 for (i = 0; i < VG_(clo_n_suppressions); i++) {
784 if (VG_(clo_verbosity) > 1) {
785 VG_(message)(Vg_UserMsg, "Reading suppressions file: %s",
786 VG_(clo_suppressions)[i] );
787 }
788 load_one_suppressions_file( VG_(clo_suppressions)[i] );
789 }
790}
791
njn25e49d8e72002-09-23 09:36:25 +0000792/* Return the name of an erring fn in a way which is useful
793 for comparing against the contents of a suppressions file.
794 Doesn't demangle the fn name, because we want to refer to
795 mangled names in the suppressions file.
sewardj99aac972002-12-26 01:53:45 +0000796*/
njn43c799e2003-04-08 00:08:52 +0000797static void get_objname_fnname ( Addr a, Char* obj_buf, Int n_obj_buf,
798 Char* fun_buf, Int n_fun_buf )
njn25e49d8e72002-09-23 09:36:25 +0000799{
800 (void)VG_(get_objname) ( a, obj_buf, n_obj_buf );
801 (void)VG_(get_fnname_nodemangle)( a, fun_buf, n_fun_buf );
802}
803
804static __inline__
njn810086f2002-11-14 12:42:47 +0000805Bool supp_matches_error(Supp* su, Error* err)
njn25e49d8e72002-09-23 09:36:25 +0000806{
njn810086f2002-11-14 12:42:47 +0000807 switch (su->skind) {
njn25e49d8e72002-09-23 09:36:25 +0000808 case PThreadSupp:
njn810086f2002-11-14 12:42:47 +0000809 return (err->ekind == PThreadErr);
njn25e49d8e72002-09-23 09:36:25 +0000810 default:
811 if (VG_(needs).skin_errors) {
njn810086f2002-11-14 12:42:47 +0000812 return SK_(error_matches_suppression)(err, su);
njn25e49d8e72002-09-23 09:36:25 +0000813 } else {
814 VG_(printf)(
815 "\nUnhandled suppression type: %u. VG_(needs).skin_errors\n"
816 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000817 err->ekind);
njne427a662002-10-02 11:08:25 +0000818 VG_(skin_panic)("unhandled suppression type");
njn25e49d8e72002-09-23 09:36:25 +0000819 }
820 }
821}
822
823static __inline__
njn810086f2002-11-14 12:42:47 +0000824Bool supp_matches_callers(Supp* su, Char caller_obj[][M_VG_ERRTXT],
825 Char caller_fun[][M_VG_ERRTXT])
njn25e49d8e72002-09-23 09:36:25 +0000826{
827 Int i;
828
njn633de322003-05-12 20:40:13 +0000829 for (i = 0; i < VG_N_SUPP_CALLERS && su->caller[i] != NULL; i++) {
njn25e49d8e72002-09-23 09:36:25 +0000830 switch (su->caller_ty[i]) {
njn4ba5a792002-09-30 10:23:54 +0000831 case ObjName: if (VG_(string_match)(su->caller[i],
832 caller_obj[i])) break;
njn25e49d8e72002-09-23 09:36:25 +0000833 return False;
njn4ba5a792002-09-30 10:23:54 +0000834 case FunName: if (VG_(string_match)(su->caller[i],
835 caller_fun[i])) break;
njn25e49d8e72002-09-23 09:36:25 +0000836 return False;
njn43c799e2003-04-08 00:08:52 +0000837 default: VG_(skin_panic)("supp_matches_callers");
njn25e49d8e72002-09-23 09:36:25 +0000838 }
839 }
840
841 /* If we reach here, it's a match */
842 return True;
843}
sewardjde4a1d02002-03-22 01:27:54 +0000844
njn810086f2002-11-14 12:42:47 +0000845/* Does an error context match a suppression? ie is this a suppressible
846 error? If so, return a pointer to the Supp record, otherwise NULL.
njn25e49d8e72002-09-23 09:36:25 +0000847 Tries to minimise the number of symbol searches since they are expensive.
sewardjde4a1d02002-03-22 01:27:54 +0000848*/
njn810086f2002-11-14 12:42:47 +0000849static Supp* is_suppressible_error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +0000850{
njn25e49d8e72002-09-23 09:36:25 +0000851 Int i;
sewardjde4a1d02002-03-22 01:27:54 +0000852
njn25e49d8e72002-09-23 09:36:25 +0000853 Char caller_obj[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
854 Char caller_fun[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
sewardjde4a1d02002-03-22 01:27:54 +0000855
njn810086f2002-11-14 12:42:47 +0000856 Supp* su;
sewardjde4a1d02002-03-22 01:27:54 +0000857
njn25e49d8e72002-09-23 09:36:25 +0000858 /* get_objname_fnname() writes the function name and object name if
njn43c799e2003-04-08 00:08:52 +0000859 it finds them in the debug info. So the strings in the suppression
njn25e49d8e72002-09-23 09:36:25 +0000860 file should match these.
sewardjde4a1d02002-03-22 01:27:54 +0000861 */
862
863 /* Initialise these strs so they are always safe to compare, even
njn25e49d8e72002-09-23 09:36:25 +0000864 if get_objname_fnname doesn't write anything to them. */
865 for (i = 0; i < VG_N_SUPP_CALLERS; i++)
866 caller_obj[i][0] = caller_fun[i][0] = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000867
njn25e49d8e72002-09-23 09:36:25 +0000868 for (i = 0; i < VG_N_SUPP_CALLERS && i < VG_(clo_backtrace_size); i++) {
njn43c799e2003-04-08 00:08:52 +0000869 get_objname_fnname ( err->where->eips[i], caller_obj[i], M_VG_ERRTXT,
870 caller_fun[i], M_VG_ERRTXT );
sewardjde4a1d02002-03-22 01:27:54 +0000871 }
872
873 /* See if the error context matches any suppression. */
874 for (su = vg_suppressions; su != NULL; su = su->next) {
njn25e49d8e72002-09-23 09:36:25 +0000875 if (supp_matches_error(su, err) &&
876 supp_matches_callers(su, caller_obj, caller_fun)) {
877 return su;
sewardjde4a1d02002-03-22 01:27:54 +0000878 }
sewardjde4a1d02002-03-22 01:27:54 +0000879 }
njn25e49d8e72002-09-23 09:36:25 +0000880 return NULL; /* no matches */
sewardjde4a1d02002-03-22 01:27:54 +0000881}
882
sewardjde4a1d02002-03-22 01:27:54 +0000883/*--------------------------------------------------------------------*/
884/*--- end vg_errcontext.c ---*/
885/*--------------------------------------------------------------------*/