blob: 9de782e5f26142cd5131fe7f5affca6088bd3e15 [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 }
fitzhardingea49f9b52003-12-16 22:26:45 +0000268 VG_(printf)("starting gdb with eip=%p esp=%p ebp=%p\n",
269 m_eip, m_esp, m_ebp);
njn3e884182003-04-15 13:03:23 +0000270 VG_(swizzle_esp_then_start_GDB)( m_eip, m_esp, m_ebp );
njn43c799e2003-04-08 00:08:52 +0000271 }
272 /* Or maybe we want to generate the error's suppression? */
273 if (VG_(is_action_requested)( "Print suppression",
274 & VG_(clo_gen_suppressions) )) {
275 VG_(gen_suppression)(err);
276 }
277}
278
279/* Shared between VG_(maybe_record_error)() and VG_(unique_error)(),
280 just for pretty printing purposes. */
281static Bool is_first_shown_context = True;
282
njn25e49d8e72002-09-23 09:36:25 +0000283/* Top-level entry point to the error management subsystem.
284 All detected errors are notified here; this routine decides if/when the
285 user should see the error. */
njn72718642003-07-24 08:45:32 +0000286void VG_(maybe_record_error) ( ThreadId tid,
njn25e49d8e72002-09-23 09:36:25 +0000287 ErrorKind ekind, Addr a, Char* s, void* extra )
288{
njn810086f2002-11-14 12:42:47 +0000289 Error err;
290 Error* p;
291 Error* p_prev;
njn43c799e2003-04-08 00:08:52 +0000292 UInt extra_size;
njn810086f2002-11-14 12:42:47 +0000293 VgRes exe_res = Vg_MedRes;
njn810086f2002-11-14 12:42:47 +0000294 static Bool stopping_message = False;
295 static Bool slowdown_message = False;
296 static Int vg_n_errs_shown = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000297
sewardjf2537be2002-04-24 21:03:47 +0000298 /* After M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
299 been found, or M_VG_COLLECT_NO_ERRORS_AFTER_FOUND total errors
300 have been found, just refuse to collect any more. This stops
301 the burden of the error-management system becoming excessive in
302 extremely buggy programs, although it does make it pretty
303 pointless to continue the Valgrind run after this point. */
sewardj2e432902002-06-13 20:44:00 +0000304 if (VG_(clo_error_limit)
sewardj72f98ff2002-06-13 17:23:38 +0000305 && (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN
njn47363ab2003-04-21 13:24:40 +0000306 || VG_(n_errs_found) >= M_VG_COLLECT_NO_ERRORS_AFTER_FOUND)) {
sewardjde4a1d02002-03-22 01:27:54 +0000307 if (!stopping_message) {
308 VG_(message)(Vg_UserMsg, "");
sewardjf2537be2002-04-24 21:03:47 +0000309
310 if (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN) {
311 VG_(message)(Vg_UserMsg,
312 "More than %d different errors detected. "
313 "I'm not reporting any more.",
314 M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN );
315 } else {
316 VG_(message)(Vg_UserMsg,
317 "More than %d total errors detected. "
318 "I'm not reporting any more.",
319 M_VG_COLLECT_NO_ERRORS_AFTER_FOUND );
320 }
321
sewardjde4a1d02002-03-22 01:27:54 +0000322 VG_(message)(Vg_UserMsg,
sewardjf2537be2002-04-24 21:03:47 +0000323 "Final error counts will be inaccurate. Go fix your program!");
sewardj72f98ff2002-06-13 17:23:38 +0000324 VG_(message)(Vg_UserMsg,
sewardj2e432902002-06-13 20:44:00 +0000325 "Rerun with --error-limit=no to disable this cutoff. Note");
sewardj72f98ff2002-06-13 17:23:38 +0000326 VG_(message)(Vg_UserMsg,
njn25e49d8e72002-09-23 09:36:25 +0000327 "that errors may occur in your program without prior warning from");
sewardj72f98ff2002-06-13 17:23:38 +0000328 VG_(message)(Vg_UserMsg,
329 "Valgrind, because errors are no longer being displayed.");
sewardjde4a1d02002-03-22 01:27:54 +0000330 VG_(message)(Vg_UserMsg, "");
331 stopping_message = True;
332 }
333 return;
334 }
335
336 /* After M_VG_COLLECT_ERRORS_SLOWLY_AFTER different errors have
337 been found, be much more conservative about collecting new
338 ones. */
339 if (vg_n_errs_shown >= M_VG_COLLECT_ERRORS_SLOWLY_AFTER) {
njn25e49d8e72002-09-23 09:36:25 +0000340 exe_res = Vg_LowRes;
sewardjde4a1d02002-03-22 01:27:54 +0000341 if (!slowdown_message) {
342 VG_(message)(Vg_UserMsg, "");
343 VG_(message)(Vg_UserMsg,
344 "More than %d errors detected. Subsequent errors",
345 M_VG_COLLECT_ERRORS_SLOWLY_AFTER);
346 VG_(message)(Vg_UserMsg,
347 "will still be recorded, but in less detail than before.");
348 slowdown_message = True;
349 }
350 }
351
njn25e49d8e72002-09-23 09:36:25 +0000352 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000353 construct_error ( &err, tid, ekind, a, s, extra, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000354
355 /* First, see if we've got an error record matching this one. */
njn25e49d8e72002-09-23 09:36:25 +0000356 p = vg_errors;
sewardjde4a1d02002-03-22 01:27:54 +0000357 p_prev = NULL;
358 while (p != NULL) {
njn810086f2002-11-14 12:42:47 +0000359 if (eq_Error(exe_res, p, &err)) {
sewardjde4a1d02002-03-22 01:27:54 +0000360 /* Found it. */
361 p->count++;
362 if (p->supp != NULL) {
363 /* Deal correctly with suppressed errors. */
364 p->supp->count++;
365 vg_n_errs_suppressed++;
366 } else {
njn47363ab2003-04-21 13:24:40 +0000367 VG_(n_errs_found)++;
sewardjde4a1d02002-03-22 01:27:54 +0000368 }
369
370 /* Move p to the front of the list so that future searches
371 for it are faster. */
372 if (p_prev != NULL) {
373 vg_assert(p_prev->next == p);
374 p_prev->next = p->next;
njn25e49d8e72002-09-23 09:36:25 +0000375 p->next = vg_errors;
376 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000377 }
sewardj7ebf7c32003-07-24 21:29:40 +0000378
sewardjde4a1d02002-03-22 01:27:54 +0000379 return;
380 }
381 p_prev = p;
382 p = p->next;
383 }
384
385 /* Didn't see it. Copy and add. */
386
njn43c799e2003-04-08 00:08:52 +0000387 /* OK, we're really going to collect it. The context is on the stack and
388 will disappear shortly, so we must copy it. First do the main
389 (non-`extra') part.
njn25e49d8e72002-09-23 09:36:25 +0000390
njn43c799e2003-04-08 00:08:52 +0000391 Then SK_(update_extra) can update the `extra' part. This is for when
392 there are more details to fill in which take time to work out but
393 don't affect our earlier decision to include the error -- by
njn25e49d8e72002-09-23 09:36:25 +0000394 postponing those details until now, we avoid the extra work in the
njn810086f2002-11-14 12:42:47 +0000395 case where we ignore the error. Ugly.
njn43c799e2003-04-08 00:08:52 +0000396
397 Then, if there is an `extra' part, copy it too, using the size that
njna70114c2003-08-19 16:14:42 +0000398 SK_(update_extra) returned. Also allow for people using the void*
399 extra field for a scalar value like an integer.
njn43c799e2003-04-08 00:08:52 +0000400 */
401
402 /* copy main part */
njn810086f2002-11-14 12:42:47 +0000403 p = VG_(arena_malloc)(VG_AR_ERRORS, sizeof(Error));
njn25e49d8e72002-09-23 09:36:25 +0000404 *p = err;
njn43c799e2003-04-08 00:08:52 +0000405
njn6a230532003-07-21 10:38:23 +0000406 /* update `extra', for non-core errors (core ones don't use 'extra') */
njna70114c2003-08-19 16:14:42 +0000407 if (VG_(needs).skin_errors && PThreadErr != ekind) {
njn6a230532003-07-21 10:38:23 +0000408 extra_size = SK_(update_extra)(p);
njn43c799e2003-04-08 00:08:52 +0000409
njna70114c2003-08-19 16:14:42 +0000410 /* copy block pointed to by `extra', if there is one */
411 if (NULL != p->extra && 0 != extra_size) {
njn6a230532003-07-21 10:38:23 +0000412 void* new_extra = VG_(malloc)(extra_size);
413 VG_(memcpy)(new_extra, p->extra, extra_size);
414 p->extra = new_extra;
415 }
njn43c799e2003-04-08 00:08:52 +0000416 }
417
njn25e49d8e72002-09-23 09:36:25 +0000418 p->next = vg_errors;
419 p->supp = is_suppressible_error(&err);
420 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000421 if (p->supp == NULL) {
njn47363ab2003-04-21 13:24:40 +0000422 VG_(n_errs_found)++;
sewardjde4a1d02002-03-22 01:27:54 +0000423 if (!is_first_shown_context)
424 VG_(message)(Vg_UserMsg, "");
njn43c799e2003-04-08 00:08:52 +0000425 pp_Error(p, False);
sewardjde4a1d02002-03-22 01:27:54 +0000426 is_first_shown_context = False;
427 vg_n_errs_shown++;
njn72718642003-07-24 08:45:32 +0000428 do_actions_on_error(p, /*allow_GDB_attach*/True);
sewardjde4a1d02002-03-22 01:27:54 +0000429 } else {
430 vg_n_errs_suppressed++;
431 p->supp->count++;
432 }
433}
434
njn43c799e2003-04-08 00:08:52 +0000435/* Second top-level entry point to the error management subsystem, for
436 errors that the skin want to report immediately, eg. because they're
437 guaranteed to only happen once. This avoids all the recording and
438 comparing stuff. But they can be suppressed; returns True if it is
njn47363ab2003-04-21 13:24:40 +0000439 suppressed. Bool `print_error' dictates whether to print the error.
440 Bool `count_error' dictates whether to count the error in VG_(n_errs_found)
441*/
njn72718642003-07-24 08:45:32 +0000442Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, Char* s,
njn3e884182003-04-15 13:03:23 +0000443 void* extra, ExeContext* where, Bool print_error,
njn47363ab2003-04-21 13:24:40 +0000444 Bool allow_GDB_attach, Bool count_error )
njn43c799e2003-04-08 00:08:52 +0000445{
446 Error err;
447
448 /* Build ourselves the error */
njn72718642003-07-24 08:45:32 +0000449 construct_error ( &err, tid, ekind, a, s, extra, where );
njn43c799e2003-04-08 00:08:52 +0000450
451 /* Unless it's suppressed, we're going to show it. Don't need to make
452 a copy, because it's only temporary anyway.
453
454 Then update the `extra' part with SK_(update_extra), because that can
455 have an affect on whether it's suppressed. Ignore the size return
456 value of SK_(update_extra), because we're not copying `extra'. */
457 (void)SK_(update_extra)(&err);
458
459 if (NULL == is_suppressible_error(&err)) {
njn47363ab2003-04-21 13:24:40 +0000460 if (count_error)
461 VG_(n_errs_found)++;
njn43c799e2003-04-08 00:08:52 +0000462
463 if (print_error) {
464 if (!is_first_shown_context)
465 VG_(message)(Vg_UserMsg, "");
466 pp_Error(&err, False);
467 is_first_shown_context = False;
468 }
njn72718642003-07-24 08:45:32 +0000469 do_actions_on_error(&err, allow_GDB_attach);
njn43c799e2003-04-08 00:08:52 +0000470
471 return False;
472
473 } else {
474 vg_n_errs_suppressed++;
475 return True;
476 }
477}
478
sewardjde4a1d02002-03-22 01:27:54 +0000479
sewardjde4a1d02002-03-22 01:27:54 +0000480/*------------------------------------------------------------*/
481/*--- Exported fns ---*/
482/*------------------------------------------------------------*/
483
njn25e49d8e72002-09-23 09:36:25 +0000484/* These are called not from generated code but from the scheduler */
sewardj8c824512002-04-14 04:16:48 +0000485
njn25e49d8e72002-09-23 09:36:25 +0000486void VG_(record_pthread_error) ( ThreadId tid, Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +0000487{
njn25e49d8e72002-09-23 09:36:25 +0000488 if (! VG_(needs).core_errors) return;
njn72718642003-07-24 08:45:32 +0000489 VG_(maybe_record_error)( tid, PThreadErr, /*addr*/0, msg, /*extra*/NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000490}
491
sewardj8c824512002-04-14 04:16:48 +0000492/*------------------------------*/
493
sewardjde4a1d02002-03-22 01:27:54 +0000494void VG_(show_all_errors) ( void )
495{
njn810086f2002-11-14 12:42:47 +0000496 Int i, n_min;
497 Int n_err_contexts, n_supp_contexts;
498 Error *p, *p_min;
499 Supp *su;
500 Bool any_supp;
sewardjde4a1d02002-03-22 01:27:54 +0000501
502 if (VG_(clo_verbosity) == 0)
503 return;
504
505 n_err_contexts = 0;
njn25e49d8e72002-09-23 09:36:25 +0000506 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000507 if (p->supp == NULL)
508 n_err_contexts++;
509 }
510
511 n_supp_contexts = 0;
512 for (su = vg_suppressions; su != NULL; su = su->next) {
513 if (su->count > 0)
514 n_supp_contexts++;
515 }
sewardjde4a1d02002-03-22 01:27:54 +0000516 VG_(message)(Vg_UserMsg,
517 "ERROR SUMMARY: "
518 "%d errors from %d contexts (suppressed: %d from %d)",
njn47363ab2003-04-21 13:24:40 +0000519 VG_(n_errs_found), n_err_contexts,
sewardjde4a1d02002-03-22 01:27:54 +0000520 vg_n_errs_suppressed, n_supp_contexts );
521
522 if (VG_(clo_verbosity) <= 1)
523 return;
524
525 /* Print the contexts in order of increasing error count. */
526 for (i = 0; i < n_err_contexts; i++) {
527 n_min = (1 << 30) - 1;
528 p_min = NULL;
njn25e49d8e72002-09-23 09:36:25 +0000529 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000530 if (p->supp != NULL) continue;
531 if (p->count < n_min) {
532 n_min = p->count;
533 p_min = p;
534 }
535 }
njne427a662002-10-02 11:08:25 +0000536 if (p_min == NULL) VG_(skin_panic)("show_all_errors()");
sewardjde4a1d02002-03-22 01:27:54 +0000537
538 VG_(message)(Vg_UserMsg, "");
539 VG_(message)(Vg_UserMsg, "%d errors in context %d of %d:",
540 p_min->count,
541 i+1, n_err_contexts);
njn810086f2002-11-14 12:42:47 +0000542 pp_Error( p_min, False );
sewardjde4a1d02002-03-22 01:27:54 +0000543
544 if ((i+1 == VG_(clo_dump_error))) {
sewardj1e8cdc92002-04-18 11:37:52 +0000545 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to below NULLs */,
sewardj22854b92002-11-30 14:00:47 +0000546 p_min->where->eips[0], NULL, NULL, NULL, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000547 }
548
549 p_min->count = 1 << 30;
550 }
551
552 if (n_supp_contexts > 0)
553 VG_(message)(Vg_DebugMsg, "");
554 any_supp = False;
555 for (su = vg_suppressions; su != NULL; su = su->next) {
556 if (su->count > 0) {
557 any_supp = True;
njn25e49d8e72002-09-23 09:36:25 +0000558 VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count, su->sname);
sewardjde4a1d02002-03-22 01:27:54 +0000559 }
560 }
561
562 if (n_err_contexts > 0) {
563 if (any_supp)
564 VG_(message)(Vg_UserMsg, "");
565 VG_(message)(Vg_UserMsg,
566 "IN SUMMARY: "
567 "%d errors from %d contexts (suppressed: %d from %d)",
njn47363ab2003-04-21 13:24:40 +0000568 VG_(n_errs_found), n_err_contexts,
sewardjde4a1d02002-03-22 01:27:54 +0000569 vg_n_errs_suppressed,
570 n_supp_contexts );
571 VG_(message)(Vg_UserMsg, "");
572 }
573}
574
575/*------------------------------------------------------------*/
576/*--- Standard suppressions ---*/
577/*------------------------------------------------------------*/
578
579/* Get a non-blank, non-comment line of at most nBuf chars from fd.
580 Skips leading spaces on the line. Return True if EOF was hit instead.
581*/
582
583#define VG_ISSPACE(ch) (((ch)==' ') || ((ch)=='\n') || ((ch)=='\t'))
584
njn4ba5a792002-09-30 10:23:54 +0000585Bool VG_(get_line) ( Int fd, Char* buf, Int nBuf )
sewardjde4a1d02002-03-22 01:27:54 +0000586{
587 Char ch;
588 Int n, i;
589 while (True) {
590 /* First, read until a non-blank char appears. */
591 while (True) {
592 n = VG_(read)(fd, &ch, 1);
593 if (n == 1 && !VG_ISSPACE(ch)) break;
594 if (n == 0) return True;
595 }
596
597 /* Now, read the line into buf. */
598 i = 0;
599 buf[i++] = ch; buf[i] = 0;
600 while (True) {
601 n = VG_(read)(fd, &ch, 1);
602 if (n == 0) return False; /* the next call will return True */
603 if (ch == '\n') break;
604 if (i > 0 && i == nBuf-1) i--;
605 buf[i++] = ch; buf[i] = 0;
606 }
607 while (i > 1 && VG_ISSPACE(buf[i-1])) {
608 i--; buf[i] = 0;
609 };
610
611 /* VG_(printf)("The line is `%s'\n", buf); */
612 /* Ok, we have a line. If a non-comment line, return.
613 If a comment line, start all over again. */
614 if (buf[0] != '#') return False;
615 }
616}
617
618
619/* *p_caller contains the raw name of a caller, supposedly either
620 fun:some_function_name or
621 obj:some_object_name.
622 Set *p_ty accordingly and advance *p_caller over the descriptor
623 (fun: or obj:) part.
624 Returns False if failed.
625*/
njn25e49d8e72002-09-23 09:36:25 +0000626static Bool setLocationTy ( Char** p_caller, SuppLocTy* p_ty )
sewardjde4a1d02002-03-22 01:27:54 +0000627{
628 if (VG_(strncmp)(*p_caller, "fun:", 4) == 0) {
629 (*p_caller) += 4;
630 *p_ty = FunName;
631 return True;
632 }
633 if (VG_(strncmp)(*p_caller, "obj:", 4) == 0) {
634 (*p_caller) += 4;
635 *p_ty = ObjName;
636 return True;
637 }
638 VG_(printf)("location should start with fun: or obj:\n");
639 return False;
640}
641
642
njn11cc9252002-10-07 14:42:59 +0000643/* Look for "skin" in a string like "skin1,skin2,skin3" */
644static __inline__
645Bool skin_name_present(Char *name, Char *names)
646{
647 Bool found;
648 Char *s = NULL; /* Shut gcc up */
649 Int len = VG_(strlen)(name);
650
651 found = (NULL != (s = VG_(strstr)(names, name)) &&
652 (s == names || *(s-1) == ',') &&
653 (*(s+len) == ',' || *(s+len) == '\0')
654 );
655
656 return found;
657}
658
sewardjde4a1d02002-03-22 01:27:54 +0000659/* Read suppressions from the file specified in vg_clo_suppressions
660 and place them in the suppressions list. If there's any difficulty
661 doing this, just give up -- there's no point in trying to recover.
662*/
sewardjde4a1d02002-03-22 01:27:54 +0000663static void load_one_suppressions_file ( Char* filename )
664{
665# define N_BUF 200
njnc40c3a82002-10-02 11:02:27 +0000666 Int fd, i;
667 Bool eof;
668 Char buf[N_BUF+1];
njn11cc9252002-10-07 14:42:59 +0000669 Char* skin_names;
njnc40c3a82002-10-02 11:02:27 +0000670 Char* supp_name;
671
njn25e49d8e72002-09-23 09:36:25 +0000672 fd = VG_(open)( filename, VKI_O_RDONLY, 0 );
jsgff3c3f1a2003-10-14 22:13:28 +0000673 if (fd < 0) {
njn25e49d8e72002-09-23 09:36:25 +0000674 VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file `%s'",
sewardjde4a1d02002-03-22 01:27:54 +0000675 filename );
676 VG_(exit)(1);
677 }
678
679 while (True) {
njn25e49d8e72002-09-23 09:36:25 +0000680 /* Assign and initialise the two suppression halves (core and skin) */
njn810086f2002-11-14 12:42:47 +0000681 Supp* supp;
682 supp = VG_(arena_malloc)(VG_AR_CORE, sizeof(Supp));
sewardjde4a1d02002-03-22 01:27:54 +0000683 supp->count = 0;
njn25e49d8e72002-09-23 09:36:25 +0000684 for (i = 0; i < VG_N_SUPP_CALLERS; i++) supp->caller[i] = NULL;
njn810086f2002-11-14 12:42:47 +0000685 supp->string = supp->extra = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000686
njn4ba5a792002-09-30 10:23:54 +0000687 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000688 if (eof) break;
689
njn43c799e2003-04-08 00:08:52 +0000690 if (!VG_STREQ(buf, "{")) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000691
njn4ba5a792002-09-30 10:23:54 +0000692 eof = VG_(get_line) ( fd, buf, N_BUF );
njn43c799e2003-04-08 00:08:52 +0000693 if (eof || VG_STREQ(buf, "}")) goto syntax_error;
njn25e49d8e72002-09-23 09:36:25 +0000694 supp->sname = VG_(arena_strdup)(VG_AR_CORE, buf);
sewardjde4a1d02002-03-22 01:27:54 +0000695
njn4ba5a792002-09-30 10:23:54 +0000696 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000697
sewardjde4a1d02002-03-22 01:27:54 +0000698 if (eof) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000699
njn11cc9252002-10-07 14:42:59 +0000700 /* Check it has the "skin1,skin2,...:supp" form (look for ':') */
njnc40c3a82002-10-02 11:02:27 +0000701 i = 0;
702 while (True) {
703 if (buf[i] == ':') break;
704 if (buf[i] == '\0') goto syntax_error;
705 i++;
njn25e49d8e72002-09-23 09:36:25 +0000706 }
njnc40c3a82002-10-02 11:02:27 +0000707 buf[i] = '\0'; /* Replace ':', splitting into two strings */
708
njn11cc9252002-10-07 14:42:59 +0000709 skin_names = & buf[0];
710 supp_name = & buf[i+1];
njnc40c3a82002-10-02 11:02:27 +0000711
njn11cc9252002-10-07 14:42:59 +0000712 /* Is it a core suppression? */
713 if (VG_(needs).core_errors && skin_name_present("core", skin_names))
njnc40c3a82002-10-02 11:02:27 +0000714 {
njn43c799e2003-04-08 00:08:52 +0000715 if (VG_STREQ(supp_name, "PThread"))
njn810086f2002-11-14 12:42:47 +0000716 supp->skind = PThreadSupp;
njnc40c3a82002-10-02 11:02:27 +0000717 else
718 goto syntax_error;
719 }
720
njn11cc9252002-10-07 14:42:59 +0000721 /* Is it a skin suppression? */
722 else if (VG_(needs).skin_errors &&
723 skin_name_present(VG_(details).name, skin_names))
njnc40c3a82002-10-02 11:02:27 +0000724 {
njn810086f2002-11-14 12:42:47 +0000725 if (SK_(recognised_suppression)(supp_name, supp))
njnc40c3a82002-10-02 11:02:27 +0000726 {
njn810086f2002-11-14 12:42:47 +0000727 /* Do nothing, function fills in supp->skind */
njnc40c3a82002-10-02 11:02:27 +0000728 } else
729 goto syntax_error;
730 }
731
njn25e49d8e72002-09-23 09:36:25 +0000732 else {
njnc40c3a82002-10-02 11:02:27 +0000733 /* Ignore rest of suppression */
njn25e49d8e72002-09-23 09:36:25 +0000734 while (True) {
njn4ba5a792002-09-30 10:23:54 +0000735 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000736 if (eof) goto syntax_error;
njn43c799e2003-04-08 00:08:52 +0000737 if (VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000738 break;
739 }
740 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000741 }
742
njn25e49d8e72002-09-23 09:36:25 +0000743 if (VG_(needs).skin_errors &&
njn810086f2002-11-14 12:42:47 +0000744 !SK_(read_extra_suppression_info)(fd, buf, N_BUF, supp))
sewardjde4a1d02002-03-22 01:27:54 +0000745 goto syntax_error;
746
njn25e49d8e72002-09-23 09:36:25 +0000747 /* "i > 0" ensures at least one caller read. */
njn633de322003-05-12 20:40:13 +0000748 for (i = 0; i <= VG_N_SUPP_CALLERS; i++) {
njn4ba5a792002-09-30 10:23:54 +0000749 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000750 if (eof) goto syntax_error;
njn43c799e2003-04-08 00:08:52 +0000751 if (i > 0 && VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000752 break;
njn633de322003-05-12 20:40:13 +0000753 if (i == VG_N_SUPP_CALLERS)
754 break;
njn25e49d8e72002-09-23 09:36:25 +0000755 supp->caller[i] = VG_(arena_strdup)(VG_AR_CORE, buf);
756 if (!setLocationTy(&(supp->caller[i]), &(supp->caller_ty[i])))
757 goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000758 }
759
sewardj57a8f5f2003-07-06 01:40:11 +0000760 /* make sure to grab the '}' if the num callers is >=
761 VG_N_SUPP_CALLERS */
762 if (!VG_STREQ(buf, "}")) {
763 do {
764 eof = VG_(get_line) ( fd, buf, N_BUF );
765 } while (!eof && !VG_STREQ(buf, "}"));
766 }
767
sewardjde4a1d02002-03-22 01:27:54 +0000768 supp->next = vg_suppressions;
769 vg_suppressions = supp;
770 }
sewardjde4a1d02002-03-22 01:27:54 +0000771 VG_(close)(fd);
772 return;
773
774 syntax_error:
775 if (eof) {
776 VG_(message)(Vg_UserMsg,
777 "FATAL: in suppressions file `%s': unexpected EOF",
778 filename );
779 } else {
780 VG_(message)(Vg_UserMsg,
njn11cc9252002-10-07 14:42:59 +0000781 "FATAL: in suppressions file: `%s': syntax error on: %s",
sewardjde4a1d02002-03-22 01:27:54 +0000782 filename, buf );
783 }
784 VG_(close)(fd);
785 VG_(message)(Vg_UserMsg, "exiting now.");
786 VG_(exit)(1);
787
788# undef N_BUF
789}
790
791
792void VG_(load_suppressions) ( void )
793{
794 Int i;
795 vg_suppressions = NULL;
796 for (i = 0; i < VG_(clo_n_suppressions); i++) {
797 if (VG_(clo_verbosity) > 1) {
798 VG_(message)(Vg_UserMsg, "Reading suppressions file: %s",
799 VG_(clo_suppressions)[i] );
800 }
801 load_one_suppressions_file( VG_(clo_suppressions)[i] );
802 }
803}
804
njn25e49d8e72002-09-23 09:36:25 +0000805/* Return the name of an erring fn in a way which is useful
806 for comparing against the contents of a suppressions file.
807 Doesn't demangle the fn name, because we want to refer to
808 mangled names in the suppressions file.
sewardj99aac972002-12-26 01:53:45 +0000809*/
njn43c799e2003-04-08 00:08:52 +0000810static void get_objname_fnname ( Addr a, Char* obj_buf, Int n_obj_buf,
811 Char* fun_buf, Int n_fun_buf )
njn25e49d8e72002-09-23 09:36:25 +0000812{
813 (void)VG_(get_objname) ( a, obj_buf, n_obj_buf );
814 (void)VG_(get_fnname_nodemangle)( a, fun_buf, n_fun_buf );
815}
816
817static __inline__
njn810086f2002-11-14 12:42:47 +0000818Bool supp_matches_error(Supp* su, Error* err)
njn25e49d8e72002-09-23 09:36:25 +0000819{
njn810086f2002-11-14 12:42:47 +0000820 switch (su->skind) {
njn25e49d8e72002-09-23 09:36:25 +0000821 case PThreadSupp:
njn810086f2002-11-14 12:42:47 +0000822 return (err->ekind == PThreadErr);
njn25e49d8e72002-09-23 09:36:25 +0000823 default:
824 if (VG_(needs).skin_errors) {
njn810086f2002-11-14 12:42:47 +0000825 return SK_(error_matches_suppression)(err, su);
njn25e49d8e72002-09-23 09:36:25 +0000826 } else {
827 VG_(printf)(
828 "\nUnhandled suppression type: %u. VG_(needs).skin_errors\n"
829 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000830 err->ekind);
njne427a662002-10-02 11:08:25 +0000831 VG_(skin_panic)("unhandled suppression type");
njn25e49d8e72002-09-23 09:36:25 +0000832 }
833 }
834}
835
836static __inline__
njn810086f2002-11-14 12:42:47 +0000837Bool supp_matches_callers(Supp* su, Char caller_obj[][M_VG_ERRTXT],
838 Char caller_fun[][M_VG_ERRTXT])
njn25e49d8e72002-09-23 09:36:25 +0000839{
840 Int i;
841
njn633de322003-05-12 20:40:13 +0000842 for (i = 0; i < VG_N_SUPP_CALLERS && su->caller[i] != NULL; i++) {
njn25e49d8e72002-09-23 09:36:25 +0000843 switch (su->caller_ty[i]) {
njn4ba5a792002-09-30 10:23:54 +0000844 case ObjName: if (VG_(string_match)(su->caller[i],
845 caller_obj[i])) break;
njn25e49d8e72002-09-23 09:36:25 +0000846 return False;
njn4ba5a792002-09-30 10:23:54 +0000847 case FunName: if (VG_(string_match)(su->caller[i],
848 caller_fun[i])) break;
njn25e49d8e72002-09-23 09:36:25 +0000849 return False;
njn43c799e2003-04-08 00:08:52 +0000850 default: VG_(skin_panic)("supp_matches_callers");
njn25e49d8e72002-09-23 09:36:25 +0000851 }
852 }
853
854 /* If we reach here, it's a match */
855 return True;
856}
sewardjde4a1d02002-03-22 01:27:54 +0000857
njn810086f2002-11-14 12:42:47 +0000858/* Does an error context match a suppression? ie is this a suppressible
859 error? If so, return a pointer to the Supp record, otherwise NULL.
njn25e49d8e72002-09-23 09:36:25 +0000860 Tries to minimise the number of symbol searches since they are expensive.
sewardjde4a1d02002-03-22 01:27:54 +0000861*/
njn810086f2002-11-14 12:42:47 +0000862static Supp* is_suppressible_error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +0000863{
njn25e49d8e72002-09-23 09:36:25 +0000864 Int i;
sewardjde4a1d02002-03-22 01:27:54 +0000865
njn25e49d8e72002-09-23 09:36:25 +0000866 Char caller_obj[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
867 Char caller_fun[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
sewardjde4a1d02002-03-22 01:27:54 +0000868
njn810086f2002-11-14 12:42:47 +0000869 Supp* su;
sewardjde4a1d02002-03-22 01:27:54 +0000870
njn25e49d8e72002-09-23 09:36:25 +0000871 /* get_objname_fnname() writes the function name and object name if
njn43c799e2003-04-08 00:08:52 +0000872 it finds them in the debug info. So the strings in the suppression
njn25e49d8e72002-09-23 09:36:25 +0000873 file should match these.
sewardjde4a1d02002-03-22 01:27:54 +0000874 */
875
876 /* Initialise these strs so they are always safe to compare, even
njn25e49d8e72002-09-23 09:36:25 +0000877 if get_objname_fnname doesn't write anything to them. */
878 for (i = 0; i < VG_N_SUPP_CALLERS; i++)
879 caller_obj[i][0] = caller_fun[i][0] = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000880
njn25e49d8e72002-09-23 09:36:25 +0000881 for (i = 0; i < VG_N_SUPP_CALLERS && i < VG_(clo_backtrace_size); i++) {
njn43c799e2003-04-08 00:08:52 +0000882 get_objname_fnname ( err->where->eips[i], caller_obj[i], M_VG_ERRTXT,
883 caller_fun[i], M_VG_ERRTXT );
sewardjde4a1d02002-03-22 01:27:54 +0000884 }
885
886 /* See if the error context matches any suppression. */
887 for (su = vg_suppressions; su != NULL; su = su->next) {
njn25e49d8e72002-09-23 09:36:25 +0000888 if (supp_matches_error(su, err) &&
889 supp_matches_callers(su, caller_obj, caller_fun)) {
890 return su;
sewardjde4a1d02002-03-22 01:27:54 +0000891 }
sewardjde4a1d02002-03-22 01:27:54 +0000892 }
njn25e49d8e72002-09-23 09:36:25 +0000893 return NULL; /* no matches */
sewardjde4a1d02002-03-22 01:27:54 +0000894}
895
sewardjde4a1d02002-03-22 01:27:54 +0000896/*--------------------------------------------------------------------*/
897/*--- end vg_errcontext.c ---*/
898/*--------------------------------------------------------------------*/