blob: 76b9439594b3c316b1f53b5872dae989368dc83e [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
10 Copyright (C) 2000-2002 Julian Seward
11 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. */
49static UInt vg_n_errs_found = 0;
50
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
njn3e884182003-04-15 13:03:23 +0000250void do_actions_on_error(Error* err, Bool allow_GDB_attach,
251 Addr m_eip, Addr m_esp, Addr m_ebp )
njn43c799e2003-04-08 00:08:52 +0000252{
253 /* Perhaps we want a GDB attach at this point? */
njn3e884182003-04-15 13:03:23 +0000254 if (allow_GDB_attach &&
255 VG_(is_action_requested)( "Attach to GDB", & VG_(clo_GDB_attach) ))
256 {
257 VG_(swizzle_esp_then_start_GDB)( m_eip, m_esp, m_ebp );
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) )) {
262 VG_(gen_suppression)(err);
263 }
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. */
273void VG_(maybe_record_error) ( ThreadState* tst,
274 ErrorKind ekind, Addr a, Char* s, void* extra )
275{
njn3e884182003-04-15 13:03:23 +0000276 Addr m_eip, m_esp, m_ebp;
njn810086f2002-11-14 12:42:47 +0000277 Error err;
278 Error* p;
279 Error* p_prev;
njn43c799e2003-04-08 00:08:52 +0000280 UInt extra_size;
njn810086f2002-11-14 12:42:47 +0000281 VgRes exe_res = Vg_MedRes;
njn810086f2002-11-14 12:42:47 +0000282 static Bool stopping_message = False;
283 static Bool slowdown_message = False;
284 static Int vg_n_errs_shown = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000285
sewardjf2537be2002-04-24 21:03:47 +0000286 /* After M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have
287 been found, or M_VG_COLLECT_NO_ERRORS_AFTER_FOUND total errors
288 have been found, just refuse to collect any more. This stops
289 the burden of the error-management system becoming excessive in
290 extremely buggy programs, although it does make it pretty
291 pointless to continue the Valgrind run after this point. */
sewardj2e432902002-06-13 20:44:00 +0000292 if (VG_(clo_error_limit)
sewardj72f98ff2002-06-13 17:23:38 +0000293 && (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN
294 || vg_n_errs_found >= M_VG_COLLECT_NO_ERRORS_AFTER_FOUND)) {
sewardjde4a1d02002-03-22 01:27:54 +0000295 if (!stopping_message) {
296 VG_(message)(Vg_UserMsg, "");
sewardjf2537be2002-04-24 21:03:47 +0000297
298 if (vg_n_errs_shown >= M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN) {
299 VG_(message)(Vg_UserMsg,
300 "More than %d different errors detected. "
301 "I'm not reporting any more.",
302 M_VG_COLLECT_NO_ERRORS_AFTER_SHOWN );
303 } else {
304 VG_(message)(Vg_UserMsg,
305 "More than %d total errors detected. "
306 "I'm not reporting any more.",
307 M_VG_COLLECT_NO_ERRORS_AFTER_FOUND );
308 }
309
sewardjde4a1d02002-03-22 01:27:54 +0000310 VG_(message)(Vg_UserMsg,
sewardjf2537be2002-04-24 21:03:47 +0000311 "Final error counts will be inaccurate. Go fix your program!");
sewardj72f98ff2002-06-13 17:23:38 +0000312 VG_(message)(Vg_UserMsg,
sewardj2e432902002-06-13 20:44:00 +0000313 "Rerun with --error-limit=no to disable this cutoff. Note");
sewardj72f98ff2002-06-13 17:23:38 +0000314 VG_(message)(Vg_UserMsg,
njn25e49d8e72002-09-23 09:36:25 +0000315 "that errors may occur in your program without prior warning from");
sewardj72f98ff2002-06-13 17:23:38 +0000316 VG_(message)(Vg_UserMsg,
317 "Valgrind, because errors are no longer being displayed.");
sewardjde4a1d02002-03-22 01:27:54 +0000318 VG_(message)(Vg_UserMsg, "");
319 stopping_message = True;
320 }
321 return;
322 }
323
324 /* After M_VG_COLLECT_ERRORS_SLOWLY_AFTER different errors have
325 been found, be much more conservative about collecting new
326 ones. */
327 if (vg_n_errs_shown >= M_VG_COLLECT_ERRORS_SLOWLY_AFTER) {
njn25e49d8e72002-09-23 09:36:25 +0000328 exe_res = Vg_LowRes;
sewardjde4a1d02002-03-22 01:27:54 +0000329 if (!slowdown_message) {
330 VG_(message)(Vg_UserMsg, "");
331 VG_(message)(Vg_UserMsg,
332 "More than %d errors detected. Subsequent errors",
333 M_VG_COLLECT_ERRORS_SLOWLY_AFTER);
334 VG_(message)(Vg_UserMsg,
335 "will still be recorded, but in less detail than before.");
336 slowdown_message = True;
337 }
338 }
339
njn25e49d8e72002-09-23 09:36:25 +0000340 /* Build ourselves the error */
njn3e884182003-04-15 13:03:23 +0000341 construct_error ( &err, tst, ekind, a, s, extra, NULL,
342 &m_eip, &m_esp, &m_ebp );
sewardjde4a1d02002-03-22 01:27:54 +0000343
344 /* First, see if we've got an error record matching this one. */
njn25e49d8e72002-09-23 09:36:25 +0000345 p = vg_errors;
sewardjde4a1d02002-03-22 01:27:54 +0000346 p_prev = NULL;
347 while (p != NULL) {
njn810086f2002-11-14 12:42:47 +0000348 if (eq_Error(exe_res, p, &err)) {
sewardjde4a1d02002-03-22 01:27:54 +0000349 /* Found it. */
350 p->count++;
351 if (p->supp != NULL) {
352 /* Deal correctly with suppressed errors. */
353 p->supp->count++;
354 vg_n_errs_suppressed++;
355 } else {
356 vg_n_errs_found++;
357 }
358
359 /* Move p to the front of the list so that future searches
360 for it are faster. */
361 if (p_prev != NULL) {
362 vg_assert(p_prev->next == p);
363 p_prev->next = p->next;
njn25e49d8e72002-09-23 09:36:25 +0000364 p->next = vg_errors;
365 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000366 }
367 return;
368 }
369 p_prev = p;
370 p = p->next;
371 }
372
373 /* Didn't see it. Copy and add. */
374
njn43c799e2003-04-08 00:08:52 +0000375 /* OK, we're really going to collect it. The context is on the stack and
376 will disappear shortly, so we must copy it. First do the main
377 (non-`extra') part.
njn25e49d8e72002-09-23 09:36:25 +0000378
njn43c799e2003-04-08 00:08:52 +0000379 Then SK_(update_extra) can update the `extra' part. This is for when
380 there are more details to fill in which take time to work out but
381 don't affect our earlier decision to include the error -- by
njn25e49d8e72002-09-23 09:36:25 +0000382 postponing those details until now, we avoid the extra work in the
njn810086f2002-11-14 12:42:47 +0000383 case where we ignore the error. Ugly.
njn43c799e2003-04-08 00:08:52 +0000384
385 Then, if there is an `extra' part, copy it too, using the size that
386 SK_(update_extra) returned.
387 */
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
393 /* update `extra' */
394 extra_size = SK_(update_extra)(p);
395
396 /* copy `extra' if there is one */
397 if (NULL != p->extra) {
398 void* new_extra = VG_(malloc)(extra_size);
399 VG_(memcpy)(new_extra, p->extra, extra_size);
400 p->extra = new_extra;
401 }
402
njn25e49d8e72002-09-23 09:36:25 +0000403 p->next = vg_errors;
404 p->supp = is_suppressible_error(&err);
405 vg_errors = p;
sewardjde4a1d02002-03-22 01:27:54 +0000406 if (p->supp == NULL) {
407 vg_n_errs_found++;
408 if (!is_first_shown_context)
409 VG_(message)(Vg_UserMsg, "");
njn43c799e2003-04-08 00:08:52 +0000410 pp_Error(p, False);
sewardjde4a1d02002-03-22 01:27:54 +0000411 is_first_shown_context = False;
412 vg_n_errs_shown++;
njn3e884182003-04-15 13:03:23 +0000413 do_actions_on_error(p, /*allow_GDB_attach*/True, m_eip, m_esp, m_ebp );
sewardjde4a1d02002-03-22 01:27:54 +0000414 } else {
415 vg_n_errs_suppressed++;
416 p->supp->count++;
417 }
418}
419
njn43c799e2003-04-08 00:08:52 +0000420/* Second top-level entry point to the error management subsystem, for
421 errors that the skin want to report immediately, eg. because they're
422 guaranteed to only happen once. This avoids all the recording and
423 comparing stuff. But they can be suppressed; returns True if it is
424 suppressed. Bool `print_error' dictates whether to print the error. */
425Bool VG_(unique_error) ( ThreadState* tst, ErrorKind ekind, Addr a, Char* s,
njn3e884182003-04-15 13:03:23 +0000426 void* extra, ExeContext* where, Bool print_error,
427 Bool allow_GDB_attach )
njn43c799e2003-04-08 00:08:52 +0000428{
429 Error err;
njn3e884182003-04-15 13:03:23 +0000430 Addr m_eip, m_esp, m_ebp;
njn43c799e2003-04-08 00:08:52 +0000431
432 /* Build ourselves the error */
njn3e884182003-04-15 13:03:23 +0000433 construct_error ( &err, tst, ekind, a, s, extra, where,
434 &m_eip, &m_esp, &m_ebp );
njn43c799e2003-04-08 00:08:52 +0000435
436 /* Unless it's suppressed, we're going to show it. Don't need to make
437 a copy, because it's only temporary anyway.
438
439 Then update the `extra' part with SK_(update_extra), because that can
440 have an affect on whether it's suppressed. Ignore the size return
441 value of SK_(update_extra), because we're not copying `extra'. */
442 (void)SK_(update_extra)(&err);
443
444 if (NULL == is_suppressible_error(&err)) {
445 vg_n_errs_found++;
446
447 if (print_error) {
448 if (!is_first_shown_context)
449 VG_(message)(Vg_UserMsg, "");
450 pp_Error(&err, False);
451 is_first_shown_context = False;
452 }
njn3e884182003-04-15 13:03:23 +0000453 do_actions_on_error(&err, allow_GDB_attach, m_eip, m_esp, m_ebp);
njn43c799e2003-04-08 00:08:52 +0000454
455 return False;
456
457 } else {
458 vg_n_errs_suppressed++;
459 return True;
460 }
461}
462
sewardjde4a1d02002-03-22 01:27:54 +0000463
sewardjde4a1d02002-03-22 01:27:54 +0000464/*------------------------------------------------------------*/
465/*--- Exported fns ---*/
466/*------------------------------------------------------------*/
467
njn25e49d8e72002-09-23 09:36:25 +0000468/* These are called not from generated code but from the scheduler */
sewardj8c824512002-04-14 04:16:48 +0000469
njn25e49d8e72002-09-23 09:36:25 +0000470void VG_(record_pthread_error) ( ThreadId tid, Char* msg )
sewardjde4a1d02002-03-22 01:27:54 +0000471{
njn25e49d8e72002-09-23 09:36:25 +0000472 if (! VG_(needs).core_errors) return;
473 VG_(maybe_record_error)( &VG_(threads)[tid], PThreadErr, /*addr*/0, msg,
474 /*extra*/NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000475}
476
sewardj8c824512002-04-14 04:16:48 +0000477/*------------------------------*/
478
sewardjde4a1d02002-03-22 01:27:54 +0000479void VG_(show_all_errors) ( void )
480{
njn810086f2002-11-14 12:42:47 +0000481 Int i, n_min;
482 Int n_err_contexts, n_supp_contexts;
483 Error *p, *p_min;
484 Supp *su;
485 Bool any_supp;
sewardjde4a1d02002-03-22 01:27:54 +0000486
487 if (VG_(clo_verbosity) == 0)
488 return;
489
490 n_err_contexts = 0;
njn25e49d8e72002-09-23 09:36:25 +0000491 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000492 if (p->supp == NULL)
493 n_err_contexts++;
494 }
495
496 n_supp_contexts = 0;
497 for (su = vg_suppressions; su != NULL; su = su->next) {
498 if (su->count > 0)
499 n_supp_contexts++;
500 }
sewardjde4a1d02002-03-22 01:27:54 +0000501 VG_(message)(Vg_UserMsg,
502 "ERROR SUMMARY: "
503 "%d errors from %d contexts (suppressed: %d from %d)",
504 vg_n_errs_found, n_err_contexts,
505 vg_n_errs_suppressed, n_supp_contexts );
506
507 if (VG_(clo_verbosity) <= 1)
508 return;
509
510 /* Print the contexts in order of increasing error count. */
511 for (i = 0; i < n_err_contexts; i++) {
512 n_min = (1 << 30) - 1;
513 p_min = NULL;
njn25e49d8e72002-09-23 09:36:25 +0000514 for (p = vg_errors; p != NULL; p = p->next) {
sewardjde4a1d02002-03-22 01:27:54 +0000515 if (p->supp != NULL) continue;
516 if (p->count < n_min) {
517 n_min = p->count;
518 p_min = p;
519 }
520 }
njne427a662002-10-02 11:08:25 +0000521 if (p_min == NULL) VG_(skin_panic)("show_all_errors()");
sewardjde4a1d02002-03-22 01:27:54 +0000522
523 VG_(message)(Vg_UserMsg, "");
524 VG_(message)(Vg_UserMsg, "%d errors in context %d of %d:",
525 p_min->count,
526 i+1, n_err_contexts);
njn810086f2002-11-14 12:42:47 +0000527 pp_Error( p_min, False );
sewardjde4a1d02002-03-22 01:27:54 +0000528
529 if ((i+1 == VG_(clo_dump_error))) {
sewardj1e8cdc92002-04-18 11:37:52 +0000530 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to below NULLs */,
sewardj22854b92002-11-30 14:00:47 +0000531 p_min->where->eips[0], NULL, NULL, NULL, NULL );
sewardjde4a1d02002-03-22 01:27:54 +0000532 }
533
534 p_min->count = 1 << 30;
535 }
536
537 if (n_supp_contexts > 0)
538 VG_(message)(Vg_DebugMsg, "");
539 any_supp = False;
540 for (su = vg_suppressions; su != NULL; su = su->next) {
541 if (su->count > 0) {
542 any_supp = True;
njn25e49d8e72002-09-23 09:36:25 +0000543 VG_(message)(Vg_DebugMsg, "supp: %4d %s", su->count, su->sname);
sewardjde4a1d02002-03-22 01:27:54 +0000544 }
545 }
546
547 if (n_err_contexts > 0) {
548 if (any_supp)
549 VG_(message)(Vg_UserMsg, "");
550 VG_(message)(Vg_UserMsg,
551 "IN SUMMARY: "
552 "%d errors from %d contexts (suppressed: %d from %d)",
553 vg_n_errs_found, n_err_contexts,
554 vg_n_errs_suppressed,
555 n_supp_contexts );
556 VG_(message)(Vg_UserMsg, "");
557 }
558}
559
560/*------------------------------------------------------------*/
561/*--- Standard suppressions ---*/
562/*------------------------------------------------------------*/
563
564/* Get a non-blank, non-comment line of at most nBuf chars from fd.
565 Skips leading spaces on the line. Return True if EOF was hit instead.
566*/
567
568#define VG_ISSPACE(ch) (((ch)==' ') || ((ch)=='\n') || ((ch)=='\t'))
569
njn4ba5a792002-09-30 10:23:54 +0000570Bool VG_(get_line) ( Int fd, Char* buf, Int nBuf )
sewardjde4a1d02002-03-22 01:27:54 +0000571{
572 Char ch;
573 Int n, i;
574 while (True) {
575 /* First, read until a non-blank char appears. */
576 while (True) {
577 n = VG_(read)(fd, &ch, 1);
578 if (n == 1 && !VG_ISSPACE(ch)) break;
579 if (n == 0) return True;
580 }
581
582 /* Now, read the line into buf. */
583 i = 0;
584 buf[i++] = ch; buf[i] = 0;
585 while (True) {
586 n = VG_(read)(fd, &ch, 1);
587 if (n == 0) return False; /* the next call will return True */
588 if (ch == '\n') break;
589 if (i > 0 && i == nBuf-1) i--;
590 buf[i++] = ch; buf[i] = 0;
591 }
592 while (i > 1 && VG_ISSPACE(buf[i-1])) {
593 i--; buf[i] = 0;
594 };
595
596 /* VG_(printf)("The line is `%s'\n", buf); */
597 /* Ok, we have a line. If a non-comment line, return.
598 If a comment line, start all over again. */
599 if (buf[0] != '#') return False;
600 }
601}
602
603
604/* *p_caller contains the raw name of a caller, supposedly either
605 fun:some_function_name or
606 obj:some_object_name.
607 Set *p_ty accordingly and advance *p_caller over the descriptor
608 (fun: or obj:) part.
609 Returns False if failed.
610*/
njn25e49d8e72002-09-23 09:36:25 +0000611static Bool setLocationTy ( Char** p_caller, SuppLocTy* p_ty )
sewardjde4a1d02002-03-22 01:27:54 +0000612{
613 if (VG_(strncmp)(*p_caller, "fun:", 4) == 0) {
614 (*p_caller) += 4;
615 *p_ty = FunName;
616 return True;
617 }
618 if (VG_(strncmp)(*p_caller, "obj:", 4) == 0) {
619 (*p_caller) += 4;
620 *p_ty = ObjName;
621 return True;
622 }
623 VG_(printf)("location should start with fun: or obj:\n");
624 return False;
625}
626
627
njn11cc9252002-10-07 14:42:59 +0000628/* Look for "skin" in a string like "skin1,skin2,skin3" */
629static __inline__
630Bool skin_name_present(Char *name, Char *names)
631{
632 Bool found;
633 Char *s = NULL; /* Shut gcc up */
634 Int len = VG_(strlen)(name);
635
636 found = (NULL != (s = VG_(strstr)(names, name)) &&
637 (s == names || *(s-1) == ',') &&
638 (*(s+len) == ',' || *(s+len) == '\0')
639 );
640
641 return found;
642}
643
sewardjde4a1d02002-03-22 01:27:54 +0000644/* Read suppressions from the file specified in vg_clo_suppressions
645 and place them in the suppressions list. If there's any difficulty
646 doing this, just give up -- there's no point in trying to recover.
647*/
sewardjde4a1d02002-03-22 01:27:54 +0000648static void load_one_suppressions_file ( Char* filename )
649{
650# define N_BUF 200
njnc40c3a82002-10-02 11:02:27 +0000651 Int fd, i;
652 Bool eof;
653 Char buf[N_BUF+1];
njn11cc9252002-10-07 14:42:59 +0000654 Char* skin_names;
njnc40c3a82002-10-02 11:02:27 +0000655 Char* supp_name;
656
njn25e49d8e72002-09-23 09:36:25 +0000657 fd = VG_(open)( filename, VKI_O_RDONLY, 0 );
sewardjde4a1d02002-03-22 01:27:54 +0000658 if (fd == -1) {
njn25e49d8e72002-09-23 09:36:25 +0000659 VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file `%s'",
sewardjde4a1d02002-03-22 01:27:54 +0000660 filename );
661 VG_(exit)(1);
662 }
663
664 while (True) {
njn25e49d8e72002-09-23 09:36:25 +0000665 /* Assign and initialise the two suppression halves (core and skin) */
njn810086f2002-11-14 12:42:47 +0000666 Supp* supp;
667 supp = VG_(arena_malloc)(VG_AR_CORE, sizeof(Supp));
sewardjde4a1d02002-03-22 01:27:54 +0000668 supp->count = 0;
njn25e49d8e72002-09-23 09:36:25 +0000669 for (i = 0; i < VG_N_SUPP_CALLERS; i++) supp->caller[i] = NULL;
njn810086f2002-11-14 12:42:47 +0000670 supp->string = supp->extra = NULL;
sewardjde4a1d02002-03-22 01:27:54 +0000671
njn4ba5a792002-09-30 10:23:54 +0000672 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000673 if (eof) break;
674
njn43c799e2003-04-08 00:08:52 +0000675 if (!VG_STREQ(buf, "{")) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000676
njn4ba5a792002-09-30 10:23:54 +0000677 eof = VG_(get_line) ( fd, buf, N_BUF );
njn43c799e2003-04-08 00:08:52 +0000678 if (eof || VG_STREQ(buf, "}")) goto syntax_error;
njn25e49d8e72002-09-23 09:36:25 +0000679 supp->sname = VG_(arena_strdup)(VG_AR_CORE, buf);
sewardjde4a1d02002-03-22 01:27:54 +0000680
njn4ba5a792002-09-30 10:23:54 +0000681 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000682
sewardjde4a1d02002-03-22 01:27:54 +0000683 if (eof) goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000684
njn11cc9252002-10-07 14:42:59 +0000685 /* Check it has the "skin1,skin2,...:supp" form (look for ':') */
njnc40c3a82002-10-02 11:02:27 +0000686 i = 0;
687 while (True) {
688 if (buf[i] == ':') break;
689 if (buf[i] == '\0') goto syntax_error;
690 i++;
njn25e49d8e72002-09-23 09:36:25 +0000691 }
njnc40c3a82002-10-02 11:02:27 +0000692 buf[i] = '\0'; /* Replace ':', splitting into two strings */
693
njn11cc9252002-10-07 14:42:59 +0000694 skin_names = & buf[0];
695 supp_name = & buf[i+1];
njnc40c3a82002-10-02 11:02:27 +0000696
njn11cc9252002-10-07 14:42:59 +0000697 /* Is it a core suppression? */
698 if (VG_(needs).core_errors && skin_name_present("core", skin_names))
njnc40c3a82002-10-02 11:02:27 +0000699 {
njn43c799e2003-04-08 00:08:52 +0000700 if (VG_STREQ(supp_name, "PThread"))
njn810086f2002-11-14 12:42:47 +0000701 supp->skind = PThreadSupp;
njnc40c3a82002-10-02 11:02:27 +0000702 else
703 goto syntax_error;
704 }
705
njn11cc9252002-10-07 14:42:59 +0000706 /* Is it a skin suppression? */
707 else if (VG_(needs).skin_errors &&
708 skin_name_present(VG_(details).name, skin_names))
njnc40c3a82002-10-02 11:02:27 +0000709 {
njn810086f2002-11-14 12:42:47 +0000710 if (SK_(recognised_suppression)(supp_name, supp))
njnc40c3a82002-10-02 11:02:27 +0000711 {
njn810086f2002-11-14 12:42:47 +0000712 /* Do nothing, function fills in supp->skind */
njnc40c3a82002-10-02 11:02:27 +0000713 } else
714 goto syntax_error;
715 }
716
njn25e49d8e72002-09-23 09:36:25 +0000717 else {
njnc40c3a82002-10-02 11:02:27 +0000718 /* Ignore rest of suppression */
njn25e49d8e72002-09-23 09:36:25 +0000719 while (True) {
njn4ba5a792002-09-30 10:23:54 +0000720 eof = VG_(get_line) ( fd, buf, N_BUF );
njn25e49d8e72002-09-23 09:36:25 +0000721 if (eof) goto syntax_error;
njn43c799e2003-04-08 00:08:52 +0000722 if (VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000723 break;
724 }
725 continue;
sewardjde4a1d02002-03-22 01:27:54 +0000726 }
727
njn25e49d8e72002-09-23 09:36:25 +0000728 if (VG_(needs).skin_errors &&
njn810086f2002-11-14 12:42:47 +0000729 !SK_(read_extra_suppression_info)(fd, buf, N_BUF, supp))
sewardjde4a1d02002-03-22 01:27:54 +0000730 goto syntax_error;
731
njn25e49d8e72002-09-23 09:36:25 +0000732 /* "i > 0" ensures at least one caller read. */
733 for (i = 0; i < VG_N_SUPP_CALLERS; i++) {
njn4ba5a792002-09-30 10:23:54 +0000734 eof = VG_(get_line) ( fd, buf, N_BUF );
sewardjde4a1d02002-03-22 01:27:54 +0000735 if (eof) goto syntax_error;
njn43c799e2003-04-08 00:08:52 +0000736 if (i > 0 && VG_STREQ(buf, "}"))
njn25e49d8e72002-09-23 09:36:25 +0000737 break;
738 supp->caller[i] = VG_(arena_strdup)(VG_AR_CORE, buf);
739 if (!setLocationTy(&(supp->caller[i]), &(supp->caller_ty[i])))
740 goto syntax_error;
sewardjde4a1d02002-03-22 01:27:54 +0000741 }
742
743 supp->next = vg_suppressions;
744 vg_suppressions = supp;
745 }
sewardjde4a1d02002-03-22 01:27:54 +0000746 VG_(close)(fd);
747 return;
748
749 syntax_error:
750 if (eof) {
751 VG_(message)(Vg_UserMsg,
752 "FATAL: in suppressions file `%s': unexpected EOF",
753 filename );
754 } else {
755 VG_(message)(Vg_UserMsg,
njn11cc9252002-10-07 14:42:59 +0000756 "FATAL: in suppressions file: `%s': syntax error on: %s",
sewardjde4a1d02002-03-22 01:27:54 +0000757 filename, buf );
758 }
759 VG_(close)(fd);
760 VG_(message)(Vg_UserMsg, "exiting now.");
761 VG_(exit)(1);
762
763# undef N_BUF
764}
765
766
767void VG_(load_suppressions) ( void )
768{
769 Int i;
770 vg_suppressions = NULL;
771 for (i = 0; i < VG_(clo_n_suppressions); i++) {
772 if (VG_(clo_verbosity) > 1) {
773 VG_(message)(Vg_UserMsg, "Reading suppressions file: %s",
774 VG_(clo_suppressions)[i] );
775 }
776 load_one_suppressions_file( VG_(clo_suppressions)[i] );
777 }
778}
779
njn25e49d8e72002-09-23 09:36:25 +0000780/* Return the name of an erring fn in a way which is useful
781 for comparing against the contents of a suppressions file.
782 Doesn't demangle the fn name, because we want to refer to
783 mangled names in the suppressions file.
sewardj99aac972002-12-26 01:53:45 +0000784*/
njn43c799e2003-04-08 00:08:52 +0000785static void get_objname_fnname ( Addr a, Char* obj_buf, Int n_obj_buf,
786 Char* fun_buf, Int n_fun_buf )
njn25e49d8e72002-09-23 09:36:25 +0000787{
788 (void)VG_(get_objname) ( a, obj_buf, n_obj_buf );
789 (void)VG_(get_fnname_nodemangle)( a, fun_buf, n_fun_buf );
790}
791
792static __inline__
njn810086f2002-11-14 12:42:47 +0000793Bool supp_matches_error(Supp* su, Error* err)
njn25e49d8e72002-09-23 09:36:25 +0000794{
njn810086f2002-11-14 12:42:47 +0000795 switch (su->skind) {
njn25e49d8e72002-09-23 09:36:25 +0000796 case PThreadSupp:
njn810086f2002-11-14 12:42:47 +0000797 return (err->ekind == PThreadErr);
njn25e49d8e72002-09-23 09:36:25 +0000798 default:
799 if (VG_(needs).skin_errors) {
njn810086f2002-11-14 12:42:47 +0000800 return SK_(error_matches_suppression)(err, su);
njn25e49d8e72002-09-23 09:36:25 +0000801 } else {
802 VG_(printf)(
803 "\nUnhandled suppression type: %u. VG_(needs).skin_errors\n"
804 "probably needs to be set.\n",
njn810086f2002-11-14 12:42:47 +0000805 err->ekind);
njne427a662002-10-02 11:08:25 +0000806 VG_(skin_panic)("unhandled suppression type");
njn25e49d8e72002-09-23 09:36:25 +0000807 }
808 }
809}
810
811static __inline__
njn810086f2002-11-14 12:42:47 +0000812Bool supp_matches_callers(Supp* su, Char caller_obj[][M_VG_ERRTXT],
813 Char caller_fun[][M_VG_ERRTXT])
njn25e49d8e72002-09-23 09:36:25 +0000814{
815 Int i;
816
817 for (i = 0; su->caller[i] != NULL; i++) {
818 switch (su->caller_ty[i]) {
njn4ba5a792002-09-30 10:23:54 +0000819 case ObjName: if (VG_(string_match)(su->caller[i],
820 caller_obj[i])) break;
njn25e49d8e72002-09-23 09:36:25 +0000821 return False;
njn4ba5a792002-09-30 10:23:54 +0000822 case FunName: if (VG_(string_match)(su->caller[i],
823 caller_fun[i])) break;
njn25e49d8e72002-09-23 09:36:25 +0000824 return False;
njn43c799e2003-04-08 00:08:52 +0000825 default: VG_(skin_panic)("supp_matches_callers");
njn25e49d8e72002-09-23 09:36:25 +0000826 }
827 }
828
829 /* If we reach here, it's a match */
830 return True;
831}
sewardjde4a1d02002-03-22 01:27:54 +0000832
njn810086f2002-11-14 12:42:47 +0000833/* Does an error context match a suppression? ie is this a suppressible
834 error? If so, return a pointer to the Supp record, otherwise NULL.
njn25e49d8e72002-09-23 09:36:25 +0000835 Tries to minimise the number of symbol searches since they are expensive.
sewardjde4a1d02002-03-22 01:27:54 +0000836*/
njn810086f2002-11-14 12:42:47 +0000837static Supp* is_suppressible_error ( Error* err )
sewardjde4a1d02002-03-22 01:27:54 +0000838{
njn25e49d8e72002-09-23 09:36:25 +0000839 Int i;
sewardjde4a1d02002-03-22 01:27:54 +0000840
njn25e49d8e72002-09-23 09:36:25 +0000841 Char caller_obj[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
842 Char caller_fun[VG_N_SUPP_CALLERS][M_VG_ERRTXT];
sewardjde4a1d02002-03-22 01:27:54 +0000843
njn810086f2002-11-14 12:42:47 +0000844 Supp* su;
sewardjde4a1d02002-03-22 01:27:54 +0000845
njn25e49d8e72002-09-23 09:36:25 +0000846 /* get_objname_fnname() writes the function name and object name if
njn43c799e2003-04-08 00:08:52 +0000847 it finds them in the debug info. So the strings in the suppression
njn25e49d8e72002-09-23 09:36:25 +0000848 file should match these.
sewardjde4a1d02002-03-22 01:27:54 +0000849 */
850
851 /* Initialise these strs so they are always safe to compare, even
njn25e49d8e72002-09-23 09:36:25 +0000852 if get_objname_fnname doesn't write anything to them. */
853 for (i = 0; i < VG_N_SUPP_CALLERS; i++)
854 caller_obj[i][0] = caller_fun[i][0] = 0;
sewardjde4a1d02002-03-22 01:27:54 +0000855
njn25e49d8e72002-09-23 09:36:25 +0000856 for (i = 0; i < VG_N_SUPP_CALLERS && i < VG_(clo_backtrace_size); i++) {
njn43c799e2003-04-08 00:08:52 +0000857 get_objname_fnname ( err->where->eips[i], caller_obj[i], M_VG_ERRTXT,
858 caller_fun[i], M_VG_ERRTXT );
sewardjde4a1d02002-03-22 01:27:54 +0000859 }
860
861 /* See if the error context matches any suppression. */
862 for (su = vg_suppressions; su != NULL; su = su->next) {
njn25e49d8e72002-09-23 09:36:25 +0000863 if (supp_matches_error(su, err) &&
864 supp_matches_callers(su, caller_obj, caller_fun)) {
865 return su;
sewardjde4a1d02002-03-22 01:27:54 +0000866 }
sewardjde4a1d02002-03-22 01:27:54 +0000867 }
njn25e49d8e72002-09-23 09:36:25 +0000868 return NULL; /* no matches */
sewardjde4a1d02002-03-22 01:27:54 +0000869}
870
sewardjde4a1d02002-03-22 01:27:54 +0000871/*--------------------------------------------------------------------*/
872/*--- end vg_errcontext.c ---*/
873/*--------------------------------------------------------------------*/