blob: f36426e71d151bb167d6a4bc7766763937cab3c2 [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
sewardj99aac972002-12-26 01:53:45 +000045/* And a helper function so the leak detector can get hold of it. */
46Supp* VG_(get_suppressions) ( void ) { return vg_suppressions; }
47
sewardjde4a1d02002-03-22 01:27:54 +000048/* Running count of unsuppressed errors detected. */
njn47363ab2003-04-21 13:24:40 +000049UInt VG_(n_errs_found) = 0;
sewardjde4a1d02002-03-22 01:27:54 +000050
51/* Running count of suppressed errors detected. */
52static UInt vg_n_errs_suppressed = 0;
53
54/* forwards ... */
njn810086f2002-11-14 12:42:47 +000055static Supp* is_suppressible_error ( Error* err );
sewardjde4a1d02002-03-22 01:27:54 +000056
57
58/*------------------------------------------------------------*/
59/*--- Helper fns ---*/
60/*------------------------------------------------------------*/
61
sewardjde4a1d02002-03-22 01:27:54 +000062/* Compare error contexts, to detect duplicates. Note that if they
63 are otherwise the same, the faulting addrs and associated rwoffsets
64 are allowed to be different. */
njn810086f2002-11-14 12:42:47 +000065static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
sewardjde4a1d02002-03-22 01:27:54 +000066{
njn810086f2002-11-14 12:42:47 +000067 if (e1->ekind != e2->ekind)
sewardjde4a1d02002-03-22 01:27:54 +000068 return False;
njn25e49d8e72002-09-23 09:36:25 +000069 if (!VG_(eq_ExeContext)(res, e1->where, e2->where))
sewardjde4a1d02002-03-22 01:27:54 +000070 return False;
71
njn810086f2002-11-14 12:42:47 +000072 switch (e1->ekind) {
sewardj4dced352002-06-04 22:54:20 +000073 case PThreadErr:
njn25e49d8e72002-09-23 09:36:25 +000074 vg_assert(VG_(needs).core_errors);
njn810086f2002-11-14 12:42:47 +000075 if (e1->string == e2->string)
sewardj4dced352002-06-04 22:54:20 +000076 return True;
njn810086f2002-11-14 12:42:47 +000077 if (0 == VG_(strcmp)(e1->string, e2->string))
sewardj4dced352002-06-04 22:54:20 +000078 return True;
79 return False;
sewardjde4a1d02002-03-22 01:27:54 +000080 default:
njn25e49d8e72002-09-23 09:36:25 +000081 if (VG_(needs).skin_errors)
njn810086f2002-11-14 12:42:47 +000082 return SK_(eq_SkinError)(res, e1, e2);
njn25e49d8e72002-09-23 09:36:25 +000083 else {
84 VG_(printf)("\nUnhandled error type: %u. VG_(needs).skin_errors\n"
85 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +000086 e1->ekind);
njne427a662002-10-02 11:08:25 +000087 VG_(skin_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +000088 }
sewardjde4a1d02002-03-22 01:27:54 +000089 }
90}
91
njn810086f2002-11-14 12:42:47 +000092static void pp_Error ( Error* err, Bool printCount )
sewardjde4a1d02002-03-22 01:27:54 +000093{
sewardjde4a1d02002-03-22 01:27:54 +000094 if (printCount)
njn25e49d8e72002-09-23 09:36:25 +000095 VG_(message)(Vg_UserMsg, "Observed %d times:", err->count );
96 if (err->tid > 1)
97 VG_(message)(Vg_UserMsg, "Thread %d:", err->tid );
98
njn810086f2002-11-14 12:42:47 +000099 switch (err->ekind) {
sewardj4dced352002-06-04 22:54:20 +0000100 case PThreadErr:
njn25e49d8e72002-09-23 09:36:25 +0000101 vg_assert(VG_(needs).core_errors);
njn810086f2002-11-14 12:42:47 +0000102 VG_(message)(Vg_UserMsg, "%s", err->string );
njn25e49d8e72002-09-23 09:36:25 +0000103 VG_(pp_ExeContext)(err->where);
sewardj4dced352002-06-04 22:54:20 +0000104 break;
sewardjde4a1d02002-03-22 01:27:54 +0000105 default:
njn25e49d8e72002-09-23 09:36:25 +0000106 if (VG_(needs).skin_errors)
njn43c799e2003-04-08 00:08:52 +0000107 SK_(pp_SkinError)( err );
njn25e49d8e72002-09-23 09:36:25 +0000108 else {
109 VG_(printf)("\nUnhandled error type: %u. VG_(needs).skin_errors\n"
110 "probably needs to be set?\n",
njn810086f2002-11-14 12:42:47 +0000111 err->ekind);
njne427a662002-10-02 11:08:25 +0000112 VG_(skin_panic)("unhandled error type");
njn25e49d8e72002-09-23 09:36:25 +0000113 }
sewardjde4a1d02002-03-22 01:27:54 +0000114 }
115}
116
sewardjde4a1d02002-03-22 01:27:54 +0000117/* Figure out if we want to attach for GDB for this error, possibly
118 by asking the user. */
njn43c799e2003-04-08 00:08:52 +0000119Bool VG_(is_action_requested) ( Char* action, Bool* clo )
sewardjde4a1d02002-03-22 01:27:54 +0000120{
121 Char ch, ch2;
122 Int res;
123
njn43c799e2003-04-08 00:08:52 +0000124 if (*clo == False)
sewardjde4a1d02002-03-22 01:27:54 +0000125 return False;
126
127 VG_(message)(Vg_UserMsg, "");
128
129 again:
130 VG_(printf)(
131 "==%d== "
njn43c799e2003-04-08 00:08:52 +0000132 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ",
133 VG_(getpid)(), action
sewardjde4a1d02002-03-22 01:27:54 +0000134 );
135
136 res = VG_(read)(0 /*stdin*/, &ch, 1);
137 if (res != 1) goto ioerror;
138 /* res == 1 */
139 if (ch == '\n') return False;
140 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y'
141 && ch != 'C' && ch != 'c') goto again;
142
143 res = VG_(read)(0 /*stdin*/, &ch2, 1);
144 if (res != 1) goto ioerror;
145 if (ch2 != '\n') goto again;
146
njn43c799e2003-04-08 00:08:52 +0000147 /* No, don't want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000148 if (ch == 'n' || ch == 'N') return False;
njn43c799e2003-04-08 00:08:52 +0000149 /* Yes, want to do action. */
sewardjde4a1d02002-03-22 01:27:54 +0000150 if (ch == 'y' || ch == 'Y') return True;
njn43c799e2003-04-08 00:08:52 +0000151 /* No, don't want to do action, and don't ask again either. */
sewardjde4a1d02002-03-22 01:27:54 +0000152 vg_assert(ch == 'c' || ch == 'C');
153
154 ioerror:
njn43c799e2003-04-08 00:08:52 +0000155 *clo = False;
sewardjde4a1d02002-03-22 01:27:54 +0000156 return False;
157}
158
159
njn25e49d8e72002-09-23 09:36:25 +0000160/* I've gone all object-oriented... initialisation depends on where the
161 error comes from:
162
163 - If from generated code (tst == NULL), the %EIP/%EBP values that we
njn3e884182003-04-15 13:03:23 +0000164 need in order to attach GDB are picked up out of VG_(baseBlock) rather
165 than from the thread table (vg_threads in vg_scheduler.c).
njn25e49d8e72002-09-23 09:36:25 +0000166
167 - If not from generated code but in response to requests passed back to
168 the scheduler (tst != NULL), we pick up %EIP/%EBP values from the
169 stored thread state, not from VG_(baseBlock).
170*/
171static __inline__
njn43c799e2003-04-08 00:08:52 +0000172void construct_error ( Error* err, ThreadState* tst, ErrorKind ekind, Addr a,
njn3e884182003-04-15 13:03:23 +0000173 Char* s, void* extra, ExeContext* where,
174 /*out*/Addr* m_eip, /*out*/Addr* m_esp,
175 /*out*/Addr* m_ebp )
sewardjde4a1d02002-03-22 01:27:54 +0000176{
njn810086f2002-11-14 12:42:47 +0000177 /* Core-only parts */
njn25e49d8e72002-09-23 09:36:25 +0000178 err->next = NULL;
179 err->supp = NULL;
180 err->count = 1;
njn43c799e2003-04-08 00:08:52 +0000181 if (NULL == where)
182 err->where = VG_(get_ExeContext)( tst );
183 else
184 err->where = where;
njn1d6c4bc2002-11-21 13:38:08 +0000185
njn25e49d8e72002-09-23 09:36:25 +0000186 if (NULL == tst) {
187 err->tid = VG_(get_current_tid)();
njn3e884182003-04-15 13:03:23 +0000188 *m_eip = VG_(baseBlock)[VGOFF_(m_eip)];
189 *m_esp = VG_(baseBlock)[VGOFF_(m_esp)];
190 *m_ebp = VG_(baseBlock)[VGOFF_(m_ebp)];
njn25e49d8e72002-09-23 09:36:25 +0000191 } else {
njn25e49d8e72002-09-23 09:36:25 +0000192 err->tid = tst->tid;
njn3e884182003-04-15 13:03:23 +0000193 *m_eip = tst->m_eip;
194 *m_esp = tst->m_esp;
195 *m_ebp = tst->m_ebp;
njn25e49d8e72002-09-23 09:36:25 +0000196 }
197
njn810086f2002-11-14 12:42:47 +0000198 /* Skin-relevant parts */
199 err->ekind = ekind;
200 err->addr = a;
201 err->string = s;
202 err->extra = extra;
njn25e49d8e72002-09-23 09:36:25 +0000203
204 /* sanity... */
205 vg_assert(err->tid >= 0 && err->tid < VG_N_THREADS);
206}
207
njn43c799e2003-04-08 00:08:52 +0000208void VG_(gen_suppression)(Error* err)
209{
210 UInt i;
211 UChar buf[M_VG_ERRTXT];
212 ExeContext* ec = VG_(get_error_where)(err);
213 Int stop_at = VG_(clo_backtrace_size);
214 Char* name = SK_(get_error_name)(err);
215
216 if (NULL == name) {
217 VG_(message)(Vg_UserMsg, "(skin does not allow error to be suppressed)");
218 return;
219 }
220
221 if (stop_at > 3) stop_at = 3; /* At most three names */
222 vg_assert(stop_at > 0);
223
224 VG_(printf)("{\n");
225 VG_(printf)(" <insert a suppression name here>\n");
226 VG_(printf)(" %s:%s\n", VG_(details).name, name);
227 SK_(print_extra_suppression_info)(err);
228
229 /* This loop condensed from VG_(mini_stack_dump)() */
230 i = 0;
231 do {
232 Addr eip = ec->eips[i];
233 if (i > 0)
234 eip--; /* point to calling line */
235
236 if ( VG_(get_fnname_nodemangle) (eip, buf, M_VG_ERRTXT) ) {
237 VG_(printf)(" fun:%s\n", buf);
238 } else if ( VG_(get_objname)(eip, buf, M_VG_ERRTXT) ) {
239 VG_(printf)(" obj:%s\n", buf);
240 } else {
241 VG_(printf)(" ???:??? "
242 "# unknown, suppression will not work, sorry)\n");
243 }
244 i++;
245 } while (i < stop_at && ec->eips[i] != 0);
246
247 VG_(printf)("}\n");
248}
249
njnb4aee052003-04-15 14:09:58 +0000250static
njn3e884182003-04-15 13:03:23 +0000251void do_actions_on_error(Error* err, Bool allow_GDB_attach,
252 Addr m_eip, Addr m_esp, Addr m_ebp )
njn43c799e2003-04-08 00:08:52 +0000253{
254 /* Perhaps we want a GDB attach at this point? */
njn3e884182003-04-15 13:03:23 +0000255 if (allow_GDB_attach &&
256 VG_(is_action_requested)( "Attach to GDB", & VG_(clo_GDB_attach) ))
257 {
258 VG_(swizzle_esp_then_start_GDB)( m_eip, m_esp, m_ebp );
njn43c799e2003-04-08 00:08:52 +0000259 }
260 /* Or maybe we want to generate the error's suppression? */
261 if (VG_(is_action_requested)( "Print suppression",
262 & VG_(clo_gen_suppressions) )) {
263 VG_(gen_suppression)(err);
264 }
265}
266
267/* Shared between VG_(maybe_record_error)() and VG_(unique_error)(),
268 just for pretty printing purposes. */
269static Bool is_first_shown_context = True;
270
njn25e49d8e72002-09-23 09:36:25 +0000271/* Top-level entry point to the error management subsystem.
272 All detected errors are notified here; this routine decides if/when the
273 user should see the error. */
274void VG_(maybe_record_error) ( ThreadState* tst,
275 ErrorKind ekind, Addr a, Char* s, void* extra )
276{
njn3e884182003-04-15 13:03:23 +0000277 Addr m_eip, m_esp, m_ebp;
njn810086f2002-11-14 12:42:47 +0000278 Error err;
279 Error* p;
280 Error* p_prev;
njn43c799e2003-04-08 00:08:52 +0000281 UInt extra_size;
njn810086f2002-11-14 12:42:47 +0000282 VgRes exe_res = Vg_MedRes;
njn810086f2002-11-14 12:42:47 +0000283 static Bool stopping_message = False;
284 static Bool slowdown_message = False;
285 static Int vg_n_errs_shown = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000286
sewardjf2537be2002-04-24 21:03:47 +0000287 /* After M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
288 been found, or M_VG_COLLECT_NO_ERRORS_AFTER_FOUND total errors
289 have been found, just refuse to collect any more. This stops
290 the burden of the error-management system becoming excessive in
291 extremely buggy programs, although it does make it pretty
292 pointless to continue the Valgrind run after this point. */
sewardj2e432902002-06-13 20:44:00 +0000293 if (VG_(clo_error_limit)
sewardj72f98ff2002-06-13 17:23:38 +0000294 && (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN
njn47363ab2003-04-21 13:24:40 +0000295 || VG_(n_errs_found) >= M_VG_COLLECT_NO_ERRORS_AFTER_FOUND)) {
sewardjde4a1d02002-03-22 01:27:54 +0000296 if (!stopping_message) {
297 VG_(message)(Vg_UserMsg, "");
sewardjf2537be2002-04-24 21:03:47 +0000298
299 if (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN) {
300 VG_(message)(Vg_UserMsg,
301 "More than %d different errors detected. "
302 "I'm not reporting any more.",
303 M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN );
304 } else {
305 VG_(message)(Vg_UserMsg,
306 "More than %d total errors detected. "
307 "I'm not reporting any more.",
308 M_VG_COLLECT_NO_ERRORS_AFTER_FOUND );
309 }
310
sewardjde4a1d02002-03-22 01:27:54 +0000311 VG_(message)(Vg_UserMsg,
sewardjf2537be2002-04-24 21:03:47 +0000312 "Final error counts will be inaccurate. Go fix your program!");
sewardj72f98ff2002-06-13 17:23:38 +0000313 VG_(message)(Vg_UserMsg,
sewardj2e432902002-06-13 20:44:00 +0000314 "Rerun with --error-limit=no to disable this cutoff. Note");
sewardj72f98ff2002-06-13 17:23:38 +0000315 VG_(message)(Vg_UserMsg,
njn25e49d8e72002-09-23 09:36:25 +0000316 "that errors may occur in your program without prior warning from");
sewardj72f98ff2002-06-13 17:23:38 +0000317 VG_(message)(Vg_UserMsg,
318 "Valgrind, because errors are no longer being displayed.");
sewardjde4a1d02002-03-22 01:27:54 +0000319 VG_(message)(Vg_UserMsg, "");
320 stopping_message = True;
321 }
322 return;
323 }
324
325 /* After M_VG_COLLECT_ERRORS_SLOWLY_AFTER different errors have
326 been found, be much more conservative about collecting new
327 ones. */
328 if (vg_n_errs_shown >= M_VG_COLLECT_ERRORS_SLOWLY_AFTER) {
njn25e49d8e72002-09-23 09:36:25 +0000329 exe_res = Vg_LowRes;
sewardjde4a1d02002-03-22 01:27:54 +0000330 if (!slowdown_message) {
331 VG_(message)(Vg_UserMsg, "");
332 VG_(message)(Vg_UserMsg,
333 "More than %d errors detected. Subsequent errors",
334 M_VG_COLLECT_ERRORS_SLOWLY_AFTER);
335 VG_(message)(Vg_UserMsg,
336 "will still be recorded, but in less detail than before.");
337 slowdown_message = True;
338 }
339 }
340
njn25e49d8e72002-09-23 09:36:25 +0000341 /* Build ourselves the error */
njn3e884182003-04-15 13:03:23 +0000342 construct_error ( &err, tst, ekind, a, s, extra, NULL,
343 &m_eip, &m_esp, &m_ebp );
sewardjde4a1d02002-03-22 01:27:54 +0000344
345 /* First, see if we've got an error record matching this one. */
njn25e49d8e72002-09-23 09:36:25 +0000346 p = vg_errors;
sewardjde4a1d02002-03-22 01:27:54 +0000347 p_prev = NULL;
348 while (p != NULL) {
njn810086f2002-11-14 12:42:47 +0000349 if (eq_Error(exe_res, p, &err)) {
sewardjde4a1d02002-03-22 01:27:54 +0000350 /* Found it. */
351 p->count++;
352 if (p->supp != NULL) {
353 /* Deal correctly with suppressed errors. */
354 p->supp->count++;
355 vg_n_errs_suppressed++;
356 } else {
njn47363ab2003-04-21 13:24:40 +0000357 VG_(n_errs_found)++;
sewardjde4a1d02002-03-22 01:27:54 +0000358 }
359
360 /* Move p to the front of the list so that future searches
361 for it are faster. */
362 if (p_prev != NULL) {
363 vg_assert(p_prev->next == p);
364 p_prev->next = p->next;
njn25e49d8e72002-09-23 09:36:25 +0000365 p->next = vg_errors;
366 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000367 }
368 return;
369 }
370 p_prev = p;
371 p = p->next;
372 }
373
374 /* Didn't see it. Copy and add. */
375
njn43c799e2003-04-08 00:08:52 +0000376 /* OK, we're really going to collect it. The context is on the stack and
377 will disappear shortly, so we must copy it. First do the main
378 (non-`extra') part.
njn25e49d8e72002-09-23 09:36:25 +0000379
njn43c799e2003-04-08 00:08:52 +0000380 Then SK_(update_extra) can update the `extra' part. This is for when
381 there are more details to fill in which take time to work out but
382 don't affect our earlier decision to include the error -- by
njn25e49d8e72002-09-23 09:36:25 +0000383 postponing those details until now, we avoid the extra work in the
njn810086f2002-11-14 12:42:47 +0000384 case where we ignore the error. Ugly.
njn43c799e2003-04-08 00:08:52 +0000385
386 Then, if there is an `extra' part, copy it too, using the size that
387 SK_(update_extra) returned.
388 */
389
390 /* copy main part */
njn810086f2002-11-14 12:42:47 +0000391 p = VG_(arena_malloc)(VG_AR_ERRORS, sizeof(Error));
njn25e49d8e72002-09-23 09:36:25 +0000392 *p = err;
njn43c799e2003-04-08 00:08:52 +0000393
394 /* update `extra' */
395 extra_size = SK_(update_extra)(p);
396
397 /* copy `extra' if there is one */
398 if (NULL != p->extra) {
399 void* new_extra = VG_(malloc)(extra_size);
400 VG_(memcpy)(new_extra, p->extra, extra_size);
401 p->extra = new_extra;
402 }
403
njn25e49d8e72002-09-23 09:36:25 +0000404 p->next = vg_errors;
405 p->supp = is_suppressible_error(&err);
406 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000407 if (p->supp == NULL) {
njn47363ab2003-04-21 13:24:40 +0000408 VG_(n_errs_found)++;
sewardjde4a1d02002-03-22 01:27:54 +0000409 if (!is_first_shown_context)
410 VG_(message)(Vg_UserMsg, "");
njn43c799e2003-04-08 00:08:52 +0000411 pp_Error(p, False);
sewardjde4a1d02002-03-22 01:27:54 +0000412 is_first_shown_context = False;
413 vg_n_errs_shown++;
njn3e884182003-04-15 13:03:23 +0000414 do_actions_on_error(p, /*allow_GDB_attach*/True, m_eip, m_esp, m_ebp );
sewardjde4a1d02002-03-22 01:27:54 +0000415 } else {
416 vg_n_errs_suppressed++;
417 p->supp->count++;
418 }
419}
420
njn43c799e2003-04-08 00:08:52 +0000421/* Second top-level entry point to the error management subsystem, for
422 errors that the skin want to report immediately, eg. because they're
423 guaranteed to only happen once. This avoids all the recording and
424 comparing stuff. But they can be suppressed; returns True if it is
njn47363ab2003-04-21 13:24:40 +0000425 suppressed. Bool `print_error' dictates whether to print the error.
426 Bool `count_error' dictates whether to count the error in VG_(n_errs_found)
427*/
njn43c799e2003-04-08 00:08:52 +0000428Bool VG_(unique_error) ( ThreadState* tst, ErrorKind ekind, Addr a, Char* s,
njn3e884182003-04-15 13:03:23 +0000429 void* extra, ExeContext* where, Bool print_error,
njn47363ab2003-04-21 13:24:40 +0000430 Bool allow_GDB_attach, Bool count_error )
njn43c799e2003-04-08 00:08:52 +0000431{
432 Error err;
njn3e884182003-04-15 13:03:23 +0000433 Addr m_eip, m_esp, m_ebp;
njn43c799e2003-04-08 00:08:52 +0000434
435 /* Build ourselves the error */
njn3e884182003-04-15 13:03:23 +0000436 construct_error ( &err, tst, ekind, a, s, extra, where,
437 &m_eip, &m_esp, &m_ebp );
njn43c799e2003-04-08 00:08:52 +0000438
439 /* Unless it's suppressed, we're going to show it. Don't need to make
440 a copy, because it's only temporary anyway.
441
442 Then update the `extra' part with SK_(update_extra), because that can
443 have an affect on whether it's suppressed. Ignore the size return
444 value of SK_(update_extra), because we're not copying `extra'. */
445 (void)SK_(update_extra)(&err);
446
447 if (NULL == is_suppressible_error(&err)) {
njn47363ab2003-04-21 13:24:40 +0000448 if (count_error)
449 VG_(n_errs_found)++;
njn43c799e2003-04-08 00:08:52 +0000450
451 if (print_error) {
452 if (!is_first_shown_context)
453 VG_(message)(Vg_UserMsg, "");
454 pp_Error(&err, False);
455 is_first_shown_context = False;
456 }
njn3e884182003-04-15 13:03:23 +0000457 do_actions_on_error(&err, allow_GDB_attach, m_eip, m_esp, m_ebp);
njn43c799e2003-04-08 00:08:52 +0000458
459 return False;
460
461 } else {
462 vg_n_errs_suppressed++;
463 return True;
464 }
465}
466
sewardjde4a1d02002-03-22 01:27:54 +0000467
sewardjde4a1d02002-03-22 01:27:54 +0000468/*------------------------------------------------------------*/
469/*--- Exported fns ---*/
470/*------------------------------------------------------------*/
471
njn25e49d8e72002-09-23 09:36:25 +0000472/* These are called not from generated code but from the scheduler */
sewardj8c824512002-04-14 04:16:48 +0000473
njn25e49d8e72002-09-23 09:36:25 +0000474void VG_(record_pthread_error) ( ThreadId tid, Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +0000475{
njn25e49d8e72002-09-23 09:36:25 +0000476 if (! VG_(needs).core_errors) return;
477 VG_(maybe_record_error)( &VG_(threads)[tid], PThreadErr, /*addr*/0, msg,
478 /*extra*/NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000479}
480
sewardj8c824512002-04-14 04:16:48 +0000481/*------------------------------*/
482
sewardjde4a1d02002-03-22 01:27:54 +0000483void VG_(show_all_errors) ( void )
484{
njn810086f2002-11-14 12:42:47 +0000485 Int i, n_min;
486 Int n_err_contexts, n_supp_contexts;
487 Error *p, *p_min;
488 Supp *su;
489 Bool any_supp;
sewardjde4a1d02002-03-22 01:27:54 +0000490
491 if (VG_(clo_verbosity) == 0)
492 return;
493
494 n_err_contexts = 0;
njn25e49d8e72002-09-23 09:36:25 +0000495 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000496 if (p->supp == NULL)
497 n_err_contexts++;
498 }
499
500 n_supp_contexts = 0;
501 for (su = vg_suppressions; su != NULL; su = su->next) {
502 if (su->count > 0)
503 n_supp_contexts++;
504 }
sewardjde4a1d02002-03-22 01:27:54 +0000505 VG_(message)(Vg_UserMsg,
506 "ERROR SUMMARY: "
507 "%d errors from %d contexts (suppressed: %d from %d)",
njn47363ab2003-04-21 13:24:40 +0000508 VG_(n_errs_found), n_err_contexts,
sewardjde4a1d02002-03-22 01:27:54 +0000509 vg_n_errs_suppressed, n_supp_contexts );
510
511 if (VG_(clo_verbosity) <= 1)
512 return;
513
514 /* Print the contexts in order of increasing error count. */
515 for (i = 0; i < n_err_contexts; i++) {
516 n_min = (1 << 30) - 1;
517 p_min = NULL;
njn25e49d8e72002-09-23 09:36:25 +0000518 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000519 if (p->supp != NULL) continue;
520 if (p->count < n_min) {
521 n_min = p->count;
522 p_min = p;
523 }
524 }
njne427a662002-10-02 11:08:25 +0000525 if (p_min == NULL) VG_(skin_panic)("show_all_errors()");
sewardjde4a1d02002-03-22 01:27:54 +0000526
527 VG_(message)(Vg_UserMsg, "");
528 VG_(message)(Vg_UserMsg, "%d errors in context %d of %d:",
529 p_min->count,
530 i+1, n_err_contexts);
njn810086f2002-11-14 12:42:47 +0000531 pp_Error( p_min, False );
sewardjde4a1d02002-03-22 01:27:54 +0000532
533 if ((i+1 == VG_(clo_dump_error))) {
sewardj1e8cdc92002-04-18 11:37:52 +0000534 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to below NULLs */,
sewardj22854b92002-11-30 14:00:47 +0000535 p_min->where->eips[0], NULL, NULL, NULL, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000536 }
537
538 p_min->count = 1 << 30;
539 }
540
541 if (n_supp_contexts > 0)
542 VG_(message)(Vg_DebugMsg, "");
543 any_supp = False;
544 for (su = vg_suppressions; su != NULL; su = su->next) {
545 if (su->count > 0) {
546 any_supp = True;
njn25e49d8e72002-09-23 09:36:25 +0000547 VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count, su->sname);
sewardjde4a1d02002-03-22 01:27:54 +0000548 }
549 }
550
551 if (n_err_contexts > 0) {
552 if (any_supp)
553 VG_(message)(Vg_UserMsg, "");
554 VG_(message)(Vg_UserMsg,
555 "IN SUMMARY: "
556 "%d errors from %d contexts (suppressed: %d from %d)",
njn47363ab2003-04-21 13:24:40 +0000557 VG_(n_errs_found), n_err_contexts,
sewardjde4a1d02002-03-22 01:27:54 +0000558 vg_n_errs_suppressed,
559 n_supp_contexts );
560 VG_(message)(Vg_UserMsg, "");
561 }
562}
563
564/*------------------------------------------------------------*/
565/*--- Standard suppressions ---*/
566/*------------------------------------------------------------*/
567
568/* Get a non-blank, non-comment line of at most nBuf chars from fd.
569 Skips leading spaces on the line. Return True if EOF was hit instead.
570*/
571
572#define VG_ISSPACE(ch) (((ch)==' ') || ((ch)=='\n') || ((ch)=='\t'))
573
njn4ba5a792002-09-30 10:23:54 +0000574Bool VG_(get_line) ( Int fd, Char* buf, Int nBuf )
sewardjde4a1d02002-03-22 01:27:54 +0000575{
576 Char ch;
577 Int n, i;
578 while (True) {
579 /* First, read until a non-blank char appears. */
580 while (True) {
581 n = VG_(read)(fd, &ch, 1);
582 if (n == 1 && !VG_ISSPACE(ch)) break;
583 if (n == 0) return True;
584 }
585
586 /* Now, read the line into buf. */
587 i = 0;
588 buf[i++] = ch; buf[i] = 0;
589 while (True) {
590 n = VG_(read)(fd, &ch, 1);
591 if (n == 0) return False; /* the next call will return True */
592 if (ch == '\n') break;
593 if (i > 0 && i == nBuf-1) i--;
594 buf[i++] = ch; buf[i] = 0;
595 }
596 while (i > 1 && VG_ISSPACE(buf[i-1])) {
597 i--; buf[i] = 0;
598 };
599
600 /* VG_(printf)("The line is `%s'\n", buf); */
601 /* Ok, we have a line. If a non-comment line, return.
602 If a comment line, start all over again. */
603 if (buf[0] != '#') return False;
604 }
605}
606
607
608/* *p_caller contains the raw name of a caller, supposedly either
609 fun:some_function_name or
610 obj:some_object_name.
611 Set *p_ty accordingly and advance *p_caller over the descriptor
612 (fun: or obj:) part.
613 Returns False if failed.
614*/
njn25e49d8e72002-09-23 09:36:25 +0000615static Bool setLocationTy ( Char** p_caller, SuppLocTy* p_ty )
sewardjde4a1d02002-03-22 01:27:54 +0000616{
617 if (VG_(strncmp)(*p_caller, "fun:", 4) == 0) {
618 (*p_caller) += 4;
619 *p_ty = FunName;
620 return True;
621 }
622 if (VG_(strncmp)(*p_caller, "obj:", 4) == 0) {
623 (*p_caller) += 4;
624 *p_ty = ObjName;
625 return True;
626 }
627 VG_(printf)("location should start with fun: or obj:\n");
628 return False;
629}
630
631
njn11cc9252002-10-07 14:42:59 +0000632/* Look for "skin" in a string like "skin1,skin2,skin3" */
633static __inline__
634Bool skin_name_present(Char *name, Char *names)
635{
636 Bool found;
637 Char *s = NULL; /* Shut gcc up */
638 Int len = VG_(strlen)(name);
639
640 found = (NULL != (s = VG_(strstr)(names, name)) &&
641 (s == names || *(s-1) == ',') &&
642 (*(s+len) == ',' || *(s+len) == '\0')
643 );
644
645 return found;
646}
647
sewardjde4a1d02002-03-22 01:27:54 +0000648/* Read suppressions from the file specified in vg_clo_suppressions
649 and place them in the suppressions list. If there's any difficulty
650 doing this, just give up -- there's no point in trying to recover.
651*/
sewardjde4a1d02002-03-22 01:27:54 +0000652static void load_one_suppressions_file ( Char* filename )
653{
654# define N_BUF 200
njnc40c3a82002-10-02 11:02:27 +0000655 Int fd, i;
656 Bool eof;
657 Char buf[N_BUF+1];
njn11cc9252002-10-07 14:42:59 +0000658 Char* skin_names;
njnc40c3a82002-10-02 11:02:27 +0000659 Char* supp_name;
660
njn25e49d8e72002-09-23 09:36:25 +0000661 fd = VG_(open)( filename, VKI_O_RDONLY, 0 );
sewardjde4a1d02002-03-22 01:27:54 +0000662 if (fd == -1) {
njn25e49d8e72002-09-23 09:36:25 +0000663 VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file `%s'",
sewardjde4a1d02002-03-22 01:27:54 +0000664 filename );
665 VG_(exit)(1);
666 }
667
668 while (True) {
njn25e49d8e72002-09-23 09:36:25 +0000669 /* Assign and initialise the two suppression halves (core and skin) */
njn810086f2002-11-14 12:42:47 +0000670 Supp* supp;
671 supp = VG_(arena_malloc)(VG_AR_CORE, sizeof(Supp));
sewardjde4a1d02002-03-22 01:27:54 +0000672 supp->count = 0;
njn25e49d8e72002-09-23 09:36:25 +0000673 for (i = 0; i < VG_N_SUPP_CALLERS; i++) supp->caller[i] = NULL;
njn810086f2002-11-14 12:42:47 +0000674 supp->string = supp->extra = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000675
njn4ba5a792002-09-30 10:23:54 +0000676 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000677 if (eof) break;
678
njn43c799e2003-04-08 00:08:52 +0000679 if (!VG_STREQ(buf, "{")) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000680
njn4ba5a792002-09-30 10:23:54 +0000681 eof = VG_(get_line) ( fd, buf, N_BUF );
njn43c799e2003-04-08 00:08:52 +0000682 if (eof || VG_STREQ(buf, "}")) goto syntax_error;
njn25e49d8e72002-09-23 09:36:25 +0000683 supp->sname = VG_(arena_strdup)(VG_AR_CORE, buf);
sewardjde4a1d02002-03-22 01:27:54 +0000684
njn4ba5a792002-09-30 10:23:54 +0000685 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000686
sewardjde4a1d02002-03-22 01:27:54 +0000687 if (eof) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000688
njn11cc9252002-10-07 14:42:59 +0000689 /* Check it has the "skin1,skin2,...:supp" form (look for ':') */
njnc40c3a82002-10-02 11:02:27 +0000690 i = 0;
691 while (True) {
692 if (buf[i] == ':') break;
693 if (buf[i] == '\0') goto syntax_error;
694 i++;
njn25e49d8e72002-09-23 09:36:25 +0000695 }
njnc40c3a82002-10-02 11:02:27 +0000696 buf[i] = '\0'; /* Replace ':', splitting into two strings */
697
njn11cc9252002-10-07 14:42:59 +0000698 skin_names = & buf[0];
699 supp_name = & buf[i+1];
njnc40c3a82002-10-02 11:02:27 +0000700
njn11cc9252002-10-07 14:42:59 +0000701 /* Is it a core suppression? */
702 if (VG_(needs).core_errors && skin_name_present("core", skin_names))
njnc40c3a82002-10-02 11:02:27 +0000703 {
njn43c799e2003-04-08 00:08:52 +0000704 if (VG_STREQ(supp_name, "PThread"))
njn810086f2002-11-14 12:42:47 +0000705 supp->skind = PThreadSupp;
njnc40c3a82002-10-02 11:02:27 +0000706 else
707 goto syntax_error;
708 }
709
njn11cc9252002-10-07 14:42:59 +0000710 /* Is it a skin suppression? */
711 else if (VG_(needs).skin_errors &&
712 skin_name_present(VG_(details).name, skin_names))
njnc40c3a82002-10-02 11:02:27 +0000713 {
njn810086f2002-11-14 12:42:47 +0000714 if (SK_(recognised_suppression)(supp_name, supp))
njnc40c3a82002-10-02 11:02:27 +0000715 {
njn810086f2002-11-14 12:42:47 +0000716 /* Do nothing, function fills in supp->skind */
njnc40c3a82002-10-02 11:02:27 +0000717 } else
718 goto syntax_error;
719 }
720
njn25e49d8e72002-09-23 09:36:25 +0000721 else {
njnc40c3a82002-10-02 11:02:27 +0000722 /* Ignore rest of suppression */
njn25e49d8e72002-09-23 09:36:25 +0000723 while (True) {
njn4ba5a792002-09-30 10:23:54 +0000724 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000725 if (eof) goto syntax_error;
njn43c799e2003-04-08 00:08:52 +0000726 if (VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000727 break;
728 }
729 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000730 }
731
njn25e49d8e72002-09-23 09:36:25 +0000732 if (VG_(needs).skin_errors &&
njn810086f2002-11-14 12:42:47 +0000733 !SK_(read_extra_suppression_info)(fd, buf, N_BUF, supp))
sewardjde4a1d02002-03-22 01:27:54 +0000734 goto syntax_error;
735
njn25e49d8e72002-09-23 09:36:25 +0000736 /* "i > 0" ensures at least one caller read. */
737 for (i = 0; i < VG_N_SUPP_CALLERS; i++) {
njn4ba5a792002-09-30 10:23:54 +0000738 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000739 if (eof) goto syntax_error;
njn43c799e2003-04-08 00:08:52 +0000740 if (i > 0 && VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000741 break;
742 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
747 supp->next = vg_suppressions;
748 vg_suppressions = supp;
749 }
sewardjde4a1d02002-03-22 01:27:54 +0000750 VG_(close)(fd);
751 return;
752
753 syntax_error:
754 if (eof) {
755 VG_(message)(Vg_UserMsg,
756 "FATAL: in suppressions file `%s': unexpected EOF",
757 filename );
758 } else {
759 VG_(message)(Vg_UserMsg,
njn11cc9252002-10-07 14:42:59 +0000760 "FATAL: in suppressions file: `%s': syntax error on: %s",
sewardjde4a1d02002-03-22 01:27:54 +0000761 filename, buf );
762 }
763 VG_(close)(fd);
764 VG_(message)(Vg_UserMsg, "exiting now.");
765 VG_(exit)(1);
766
767# undef N_BUF
768}
769
770
771void VG_(load_suppressions) ( void )
772{
773 Int i;
774 vg_suppressions = NULL;
775 for (i = 0; i < VG_(clo_n_suppressions); i++) {
776 if (VG_(clo_verbosity) > 1) {
777 VG_(message)(Vg_UserMsg, "Reading suppressions file: %s",
778 VG_(clo_suppressions)[i] );
779 }
780 load_one_suppressions_file( VG_(clo_suppressions)[i] );
781 }
782}
783
njn25e49d8e72002-09-23 09:36:25 +0000784/* Return the name of an erring fn in a way which is useful
785 for comparing against the contents of a suppressions file.
786 Doesn't demangle the fn name, because we want to refer to
787 mangled names in the suppressions file.
sewardj99aac972002-12-26 01:53:45 +0000788*/
njn43c799e2003-04-08 00:08:52 +0000789static void get_objname_fnname ( Addr a, Char* obj_buf, Int n_obj_buf,
790 Char* fun_buf, Int n_fun_buf )
njn25e49d8e72002-09-23 09:36:25 +0000791{
792 (void)VG_(get_objname) ( a, obj_buf, n_obj_buf );
793 (void)VG_(get_fnname_nodemangle)( a, fun_buf, n_fun_buf );
794}
795
796static __inline__
njn810086f2002-11-14 12:42:47 +0000797Bool supp_matches_error(Supp* su, Error* err)
njn25e49d8e72002-09-23 09:36:25 +0000798{
njn810086f2002-11-14 12:42:47 +0000799 switch (su->skind) {
njn25e49d8e72002-09-23 09:36:25 +0000800 case PThreadSupp:
njn810086f2002-11-14 12:42:47 +0000801 return (err->ekind == PThreadErr);
njn25e49d8e72002-09-23 09:36:25 +0000802 default:
803 if (VG_(needs).skin_errors) {
njn810086f2002-11-14 12:42:47 +0000804 return SK_(error_matches_suppression)(err, su);
njn25e49d8e72002-09-23 09:36:25 +0000805 } else {
806 VG_(printf)(
807 "\nUnhandled suppression type: %u. VG_(needs).skin_errors\n"
808 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000809 err->ekind);
njne427a662002-10-02 11:08:25 +0000810 VG_(skin_panic)("unhandled suppression type");
njn25e49d8e72002-09-23 09:36:25 +0000811 }
812 }
813}
814
815static __inline__
njn810086f2002-11-14 12:42:47 +0000816Bool supp_matches_callers(Supp* su, Char caller_obj[][M_VG_ERRTXT],
817 Char caller_fun[][M_VG_ERRTXT])
njn25e49d8e72002-09-23 09:36:25 +0000818{
819 Int i;
820
821 for (i = 0; su->caller[i] != NULL; i++) {
822 switch (su->caller_ty[i]) {
njn4ba5a792002-09-30 10:23:54 +0000823 case ObjName: if (VG_(string_match)(su->caller[i],
824 caller_obj[i])) break;
njn25e49d8e72002-09-23 09:36:25 +0000825 return False;
njn4ba5a792002-09-30 10:23:54 +0000826 case FunName: if (VG_(string_match)(su->caller[i],
827 caller_fun[i])) break;
njn25e49d8e72002-09-23 09:36:25 +0000828 return False;
njn43c799e2003-04-08 00:08:52 +0000829 default: VG_(skin_panic)("supp_matches_callers");
njn25e49d8e72002-09-23 09:36:25 +0000830 }
831 }
832
833 /* If we reach here, it's a match */
834 return True;
835}
sewardjde4a1d02002-03-22 01:27:54 +0000836
njn810086f2002-11-14 12:42:47 +0000837/* Does an error context match a suppression? ie is this a suppressible
838 error? If so, return a pointer to the Supp record, otherwise NULL.
njn25e49d8e72002-09-23 09:36:25 +0000839 Tries to minimise the number of symbol searches since they are expensive.
sewardjde4a1d02002-03-22 01:27:54 +0000840*/
njn810086f2002-11-14 12:42:47 +0000841static Supp* is_suppressible_error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +0000842{
njn25e49d8e72002-09-23 09:36:25 +0000843 Int i;
sewardjde4a1d02002-03-22 01:27:54 +0000844
njn25e49d8e72002-09-23 09:36:25 +0000845 Char caller_obj[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
846 Char caller_fun[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
sewardjde4a1d02002-03-22 01:27:54 +0000847
njn810086f2002-11-14 12:42:47 +0000848 Supp* su;
sewardjde4a1d02002-03-22 01:27:54 +0000849
njn25e49d8e72002-09-23 09:36:25 +0000850 /* get_objname_fnname() writes the function name and object name if
njn43c799e2003-04-08 00:08:52 +0000851 it finds them in the debug info. So the strings in the suppression
njn25e49d8e72002-09-23 09:36:25 +0000852 file should match these.
sewardjde4a1d02002-03-22 01:27:54 +0000853 */
854
855 /* Initialise these strs so they are always safe to compare, even
njn25e49d8e72002-09-23 09:36:25 +0000856 if get_objname_fnname doesn't write anything to them. */
857 for (i = 0; i < VG_N_SUPP_CALLERS; i++)
858 caller_obj[i][0] = caller_fun[i][0] = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000859
njn25e49d8e72002-09-23 09:36:25 +0000860 for (i = 0; i < VG_N_SUPP_CALLERS && i < VG_(clo_backtrace_size); i++) {
njn43c799e2003-04-08 00:08:52 +0000861 get_objname_fnname ( err->where->eips[i], caller_obj[i], M_VG_ERRTXT,
862 caller_fun[i], M_VG_ERRTXT );
sewardjde4a1d02002-03-22 01:27:54 +0000863 }
864
865 /* See if the error context matches any suppression. */
866 for (su = vg_suppressions; su != NULL; su = su->next) {
njn25e49d8e72002-09-23 09:36:25 +0000867 if (supp_matches_error(su, err) &&
868 supp_matches_callers(su, caller_obj, caller_fun)) {
869 return su;
sewardjde4a1d02002-03-22 01:27:54 +0000870 }
sewardjde4a1d02002-03-22 01:27:54 +0000871 }
njn25e49d8e72002-09-23 09:36:25 +0000872 return NULL; /* no matches */
sewardjde4a1d02002-03-22 01:27:54 +0000873}
874
sewardjde4a1d02002-03-22 01:27:54 +0000875/*--------------------------------------------------------------------*/
876/*--- end vg_errcontext.c ---*/
877/*--------------------------------------------------------------------*/