1 2 /*--------------------------------------------------------------------*/ 3 /*--- Management of error messages. m_errormgr.c ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2000-2013 Julian Seward 11 jseward (at) acm.org 12 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 28 The GNU General Public License is contained in the file COPYING. 29 */ 30 31 #include "pub_core_basics.h" 32 #include "pub_core_vki.h" 33 #include "pub_core_libcsetjmp.h" 34 #include "pub_core_threadstate.h" // For VG_N_THREADS 35 #include "pub_core_debugger.h" 36 #include "pub_core_debuginfo.h" 37 #include "pub_core_errormgr.h" 38 #include "pub_core_execontext.h" 39 #include "pub_core_gdbserver.h" 40 #include "pub_core_libcbase.h" 41 #include "pub_core_libcassert.h" 42 #include "pub_core_libcfile.h" 43 #include "pub_core_libcprint.h" 44 #include "pub_core_libcproc.h" // For VG_(getpid)() 45 #include "pub_core_seqmatch.h" 46 #include "pub_core_mallocfree.h" 47 #include "pub_core_options.h" 48 #include "pub_core_stacktrace.h" 49 #include "pub_core_tooliface.h" 50 #include "pub_core_translate.h" // for VG_(translate)() 51 #include "pub_core_xarray.h" // VG_(xaprintf) et al 52 53 /*------------------------------------------------------------*/ 54 /*--- Globals ---*/ 55 /*------------------------------------------------------------*/ 56 57 /* After this many different unsuppressed errors have been observed, 58 be more conservative about collecting new ones. */ 59 #define M_COLLECT_ERRORS_SLOWLY_AFTER 100 60 61 /* After this many different unsuppressed errors have been observed, 62 stop collecting errors at all, and tell the user their program is 63 evidently a steaming pile of camel dung. */ 64 #define M_COLLECT_NO_ERRORS_AFTER_SHOWN 1000 65 66 /* After this many total errors have been observed, stop collecting 67 errors at all. Counterpart to M_COLLECT_NO_ERRORS_AFTER_SHOWN. */ 68 #define M_COLLECT_NO_ERRORS_AFTER_FOUND 10000000 69 70 /* The list of error contexts found, both suppressed and unsuppressed. 71 Initially empty, and grows as errors are detected. */ 72 static Error* errors = NULL; 73 74 /* The list of suppression directives, as read from the specified 75 suppressions file. Note that the list gets rearranged as a result 76 of the searches done by is_suppressible_error(). */ 77 static Supp* suppressions = NULL; 78 79 /* Running count of unsuppressed errors detected. */ 80 static UInt n_errs_found = 0; 81 82 /* Running count of suppressed errors detected. */ 83 static UInt n_errs_suppressed = 0; 84 85 /* Running count of errors shown. */ 86 static UInt n_errs_shown = 0; 87 88 /* Running count of unsuppressed error contexts. */ 89 static UInt n_err_contexts = 0; 90 91 /* Running count of suppressed error contexts. */ 92 static UInt n_supp_contexts = 0; 93 94 95 /* forwards ... */ 96 static Supp* is_suppressible_error ( Error* err ); 97 98 static ThreadId last_tid_printed = 1; 99 100 /* Stats: number of searches of the error list initiated. */ 101 static UWord em_errlist_searches = 0; 102 103 /* Stats: number of comparisons done during error list 104 searching. */ 105 static UWord em_errlist_cmps = 0; 106 107 /* Stats: number of searches of the suppression list initiated. */ 108 static UWord em_supplist_searches = 0; 109 110 /* Stats: number of comparisons done during suppression list 111 searching. */ 112 static UWord em_supplist_cmps = 0; 113 114 /*------------------------------------------------------------*/ 115 /*--- Error type ---*/ 116 /*------------------------------------------------------------*/ 117 118 /* Errors. Extensible (via the 'extra' field). Tools can use a normal 119 enum (with element values in the normal range (0..)) for 'ekind'. 120 Functions for getting/setting the tool-relevant fields are in 121 include/pub_tool_errormgr.h. 122 123 When errors are found and recorded with VG_(maybe_record_error)(), all 124 the tool must do is pass in the four parameters; core will 125 allocate/initialise the error record. 126 */ 127 struct _Error { 128 struct _Error* next; 129 // Unique tag. This gives the error a unique identity (handle) by 130 // which it can be referred to afterwords. Currently only used for 131 // XML printing. 132 UInt unique; 133 // NULL if unsuppressed; or ptr to suppression record. 134 Supp* supp; 135 Int count; 136 137 // The tool-specific part 138 ThreadId tid; // Initialised by core 139 ExeContext* where; // Initialised by core 140 ErrorKind ekind; // Used by ALL. Must be in the range (0..) 141 Addr addr; // Used frequently 142 const HChar* string; // Used frequently 143 void* extra; // For any tool-specific extras 144 }; 145 146 147 ExeContext* VG_(get_error_where) ( Error* err ) 148 { 149 return err->where; 150 } 151 152 ErrorKind VG_(get_error_kind) ( Error* err ) 153 { 154 return err->ekind; 155 } 156 157 Addr VG_(get_error_address) ( Error* err ) 158 { 159 return err->addr; 160 } 161 162 const HChar* VG_(get_error_string) ( Error* err ) 163 { 164 return err->string; 165 } 166 167 void* VG_(get_error_extra) ( Error* err ) 168 { 169 return err->extra; 170 } 171 172 UInt VG_(get_n_errs_found)( void ) 173 { 174 return n_errs_found; 175 } 176 177 UInt VG_(get_n_errs_shown)( void ) 178 { 179 return n_errs_shown; 180 } 181 182 /*------------------------------------------------------------*/ 183 /*--- Suppression type ---*/ 184 /*------------------------------------------------------------*/ 185 186 /* Note: it is imperative this doesn't overlap with (0..) at all, as tools 187 * effectively extend it by defining their own enums in the (0..) range. */ 188 typedef 189 enum { 190 // Nb: thread errors are a relic of the time when Valgrind's core 191 // could detect them. This example is left commented-out as an 192 // example should new core errors ever be added. 193 ThreadSupp = -1, /* Matches ThreadErr */ 194 } 195 CoreSuppKind; 196 197 /* Max number of callers for context in a suppression. */ 198 #define VG_MAX_SUPP_CALLERS 24 199 200 /* For each caller specified for a suppression, record the nature of 201 the caller name. Not of interest to tools. */ 202 typedef 203 enum { 204 NoName, /* Error case */ 205 ObjName, /* Name is of an shared object file. */ 206 FunName, /* Name is of a function. */ 207 DotDotDot /* Frame-level wildcard */ 208 } 209 SuppLocTy; 210 211 typedef 212 struct { 213 SuppLocTy ty; 214 Bool name_is_simple_str; /* True if name is a string without 215 '?' and '*' wildcard characters. */ 216 HChar* name; /* NULL for NoName and DotDotDot */ 217 } 218 SuppLoc; 219 220 /* Suppressions. Tools can get/set tool-relevant parts with functions 221 declared in include/pub_tool_errormgr.h. Extensible via the 'extra' field. 222 Tools can use a normal enum (with element values in the normal range 223 (0..)) for 'skind'. */ 224 struct _Supp { 225 struct _Supp* next; 226 Int count; // The number of times this error has been suppressed. 227 HChar* sname; // The name by which the suppression is referred to. 228 229 // Index in VG_(clo_suppressions) giving filename from which suppression 230 // was read, and the lineno in this file where sname was read. 231 Int clo_suppressions_i; 232 Int sname_lineno; 233 234 // Length of 'callers' 235 Int n_callers; 236 // Array of callers, for matching stack traces. First one (name of fn 237 // where err occurs) is mandatory; rest are optional. 238 SuppLoc* callers; 239 240 /* The tool-specific part */ 241 SuppKind skind; // What kind of suppression. Must use the range (0..). 242 HChar* string; // String -- use is optional. NULL by default. 243 void* extra; // Anything else -- use is optional. NULL by default. 244 }; 245 246 SuppKind VG_(get_supp_kind) ( Supp* su ) 247 { 248 return su->skind; 249 } 250 251 HChar* VG_(get_supp_string) ( Supp* su ) 252 { 253 return su->string; 254 } 255 256 void* VG_(get_supp_extra) ( Supp* su ) 257 { 258 return su->extra; 259 } 260 261 262 void VG_(set_supp_kind) ( Supp* su, SuppKind skind ) 263 { 264 su->skind = skind; 265 } 266 267 void VG_(set_supp_string) ( Supp* su, HChar* string ) 268 { 269 su->string = string; 270 } 271 272 void VG_(set_supp_extra) ( Supp* su, void* extra ) 273 { 274 su->extra = extra; 275 } 276 277 278 /*------------------------------------------------------------*/ 279 /*--- Helper fns ---*/ 280 /*------------------------------------------------------------*/ 281 282 // Only show core errors if the tool wants to, we're not running with -q, 283 // and were not outputting XML. 284 Bool VG_(showing_core_errors)(void) 285 { 286 return VG_(needs).core_errors && VG_(clo_verbosity) >= 1 && !VG_(clo_xml); 287 } 288 289 /* Compare errors, to detect duplicates. 290 */ 291 static Bool eq_Error ( VgRes res, Error* e1, Error* e2 ) 292 { 293 if (e1->ekind != e2->ekind) 294 return False; 295 if (!VG_(eq_ExeContext)(res, e1->where, e2->where)) 296 return False; 297 298 switch (e1->ekind) { 299 //(example code, see comment on CoreSuppKind above) 300 //case ThreadErr: 301 // vg_assert(VG_(needs).core_errors); 302 // return <something> 303 default: 304 if (VG_(needs).tool_errors) { 305 return VG_TDICT_CALL(tool_eq_Error, res, e1, e2); 306 } else { 307 VG_(printf)("\nUnhandled error type: %u. VG_(needs).tool_errors\n" 308 "probably needs to be set.\n", 309 e1->ekind); 310 VG_(tool_panic)("unhandled error type"); 311 } 312 } 313 } 314 315 316 /* Helper functions for suppression generation: print a single line of 317 a suppression pseudo-stack-trace, either in XML or text mode. It's 318 important that the behaviour of these two functions exactly 319 corresponds. 320 */ 321 #define ERRTXT_LEN 4096 322 323 static void printSuppForIp_XML(UInt n, Addr ip, void* uu_opaque) 324 { 325 static HChar buf[ERRTXT_LEN]; 326 if ( VG_(get_fnname_no_cxx_demangle) (ip, buf, ERRTXT_LEN) ) { 327 VG_(printf_xml)(" <sframe> <fun>%pS</fun> </sframe>\n", buf); 328 } else 329 if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) { 330 VG_(printf_xml)(" <sframe> <obj>%pS</obj> </sframe>\n", buf); 331 } else { 332 VG_(printf_xml)(" <sframe> <obj>*</obj> </sframe>\n"); 333 } 334 } 335 336 static void printSuppForIp_nonXML(UInt n, Addr ip, void* textV) 337 { 338 static HChar buf[ERRTXT_LEN]; 339 XArray* /* of HChar */ text = (XArray*)textV; 340 if ( VG_(get_fnname_no_cxx_demangle) (ip, buf, ERRTXT_LEN) ) { 341 VG_(xaprintf)(text, " fun:%s\n", buf); 342 } else 343 if ( VG_(get_objname)(ip, buf, ERRTXT_LEN) ) { 344 VG_(xaprintf)(text, " obj:%s\n", buf); 345 } else { 346 VG_(xaprintf)(text, " obj:*\n"); 347 } 348 } 349 350 /* Generate a suppression for an error, either in text or XML mode. 351 */ 352 static void gen_suppression(Error* err) 353 { 354 HChar xtra[256]; /* assumed big enough (is overrun-safe) */ 355 Bool anyXtra; 356 const HChar* name; 357 ExeContext* ec; 358 XArray* /* HChar */ text; 359 360 const HChar* dummy_name = "insert_a_suppression_name_here"; 361 362 vg_assert(err); 363 364 ec = VG_(get_error_where)(err); 365 vg_assert(ec); 366 367 name = VG_TDICT_CALL(tool_get_error_name, err); 368 if (NULL == name) { 369 VG_(umsg)("(%s does not allow error to be suppressed)\n", 370 VG_(details).name); 371 return; 372 } 373 374 /* In XML mode, we also need to print the plain text version of the 375 suppresion in a CDATA section. What that really means is, we 376 need to generate the plaintext version both in XML and text 377 mode. So generate it into TEXT. */ 378 text = VG_(newXA)( VG_(malloc), "errormgr.gen_suppression.1", 379 VG_(free), sizeof(HChar) ); 380 vg_assert(text); 381 382 /* Ok. Generate the plain text version into TEXT. */ 383 VG_(xaprintf)(text, "{\n"); 384 VG_(xaprintf)(text, " <%s>\n", dummy_name); 385 VG_(xaprintf)(text, " %s:%s\n", VG_(details).name, name); 386 387 VG_(memset)(xtra, 0, sizeof(xtra)); 388 anyXtra = VG_TDICT_CALL(tool_get_extra_suppression_info, 389 err, xtra, sizeof(xtra)); 390 vg_assert(xtra[sizeof(xtra)-1] == 0); 391 392 if (anyXtra) 393 VG_(xaprintf)(text, " %s\n", xtra); 394 395 // Print stack trace elements 396 UInt n_ips = VG_(get_ExeContext_n_ips)(ec); 397 tl_assert(n_ips > 0); 398 if (n_ips > VG_MAX_SUPP_CALLERS) 399 n_ips = VG_MAX_SUPP_CALLERS; 400 VG_(apply_StackTrace)(printSuppForIp_nonXML, 401 text, 402 VG_(get_ExeContext_StackTrace)(ec), 403 n_ips); 404 405 VG_(xaprintf)(text, "}\n"); 406 // zero terminate 407 VG_(xaprintf)(text, "%c", (HChar)0 ); 408 // VG_(printf) of text 409 410 /* And now display it. */ 411 if (! VG_(clo_xml) ) { 412 413 // the simple case 414 VG_(printf)("%s", (HChar*) VG_(indexXA)(text, 0) ); 415 416 } else { 417 418 /* Now we have to print the XML directly. No need to go to the 419 effort of stuffing it in an XArray, since we won't need it 420 again. */ 421 VG_(printf_xml)(" <suppression>\n"); 422 VG_(printf_xml)(" <sname>%s</sname>\n", dummy_name); 423 VG_(printf_xml)( 424 " <skind>%pS:%pS</skind>\n", VG_(details).name, name); 425 if (anyXtra) 426 VG_(printf_xml)(" <skaux>%pS</skaux>\n", xtra); 427 428 // Print stack trace elements 429 VG_(apply_StackTrace)(printSuppForIp_XML, 430 NULL, 431 VG_(get_ExeContext_StackTrace)(ec), 432 VG_(get_ExeContext_n_ips)(ec)); 433 434 // And now the cdata bit 435 // XXX FIXME! properly handle the case where the raw text 436 // itself contains "]]>", as specified in Protocol 4. 437 VG_(printf_xml)(" <rawtext>\n"); 438 VG_(printf_xml)("<![CDATA[\n"); 439 VG_(printf_xml)("%s", (HChar*) VG_(indexXA)(text, 0) ); 440 VG_(printf_xml)("]]>\n"); 441 VG_(printf_xml)(" </rawtext>\n"); 442 VG_(printf_xml)(" </suppression>\n"); 443 444 } 445 446 VG_(deleteXA)(text); 447 } 448 449 450 /* Figure out if we want to perform a given action for this error, 451 possibly by asking the user. 452 */ 453 Bool VG_(is_action_requested) ( const HChar* action, Bool* clo ) 454 { 455 HChar ch, ch2; 456 Int res; 457 458 /* First off, we shouldn't be asking the user anything if 459 we're in XML mode. */ 460 if (VG_(clo_xml)) 461 return False; /* That's a Nein, oder Nay as they say down here in B-W */ 462 463 if (*clo == False) 464 return False; 465 466 VG_(umsg)("\n"); 467 468 again: 469 VG_(printf)( 470 "==%d== " 471 "---- %s ? --- [Return/N/n/Y/y/C/c] ---- ", 472 VG_(getpid)(), action 473 ); 474 475 res = VG_(read)(VG_(clo_input_fd), &ch, 1); 476 if (res != 1) goto ioerror; 477 /* res == 1 */ 478 if (ch == '\n') return False; 479 if (ch != 'N' && ch != 'n' && ch != 'Y' && ch != 'y' 480 && ch != 'C' && ch != 'c') goto again; 481 482 res = VG_(read)(VG_(clo_input_fd), &ch2, 1); 483 if (res != 1) goto ioerror; 484 if (ch2 != '\n') goto again; 485 486 /* No, don't want to do action. */ 487 if (ch == 'n' || ch == 'N') return False; 488 /* Yes, want to do action. */ 489 if (ch == 'y' || ch == 'Y') return True; 490 /* No, don't want to do action, and don't ask again either. */ 491 vg_assert(ch == 'c' || ch == 'C'); 492 493 ioerror: 494 *clo = False; 495 return False; 496 } 497 498 499 /* Do text-mode actions on error, that is, immediately after an error 500 is printed. These are: 501 * possibly, attach to a debugger 502 * possibly, generate a suppression. 503 Note this should not be called in XML mode! 504 */ 505 static 506 void do_actions_on_error(Error* err, Bool allow_db_attach) 507 { 508 Bool still_noisy = True; 509 510 /* Should be assured by caller */ 511 vg_assert( ! VG_(clo_xml) ); 512 513 /* if user wants to debug from a certain error nr, then wait for gdb/vgdb */ 514 if (VG_(clo_vgdb) != Vg_VgdbNo 515 && allow_db_attach 516 && VG_(dyn_vgdb_error) <= n_errs_shown) { 517 VG_(umsg)("(action on error) vgdb me ... \n"); 518 VG_(gdbserver)( err->tid ); 519 VG_(umsg)("Continuing ...\n"); 520 } 521 522 /* Perhaps we want a debugger attach at this point? */ 523 /* GDBTD ??? maybe we should/could remove the below assuming the 524 gdbserver interface is better ??? */ 525 if (allow_db_attach && 526 VG_(is_action_requested)( "Attach to debugger", & VG_(clo_db_attach) )) 527 { 528 if (0) VG_(printf)("starting debugger\n"); 529 VG_(start_debugger)( err->tid ); 530 } 531 /* Or maybe we want to generate the error's suppression? */ 532 if (VG_(clo_gen_suppressions) == 2 533 || (VG_(clo_gen_suppressions) == 1 534 && VG_(is_action_requested)( "Print suppression", &still_noisy )) 535 ) { 536 gen_suppression(err); 537 } 538 if (VG_(clo_gen_suppressions) == 1 && !still_noisy) 539 VG_(clo_gen_suppressions) = 0; 540 } 541 542 543 /* Prints an error. Not entirely simple because of the differences 544 between XML and text mode output. 545 546 In XML mode: 547 548 * calls the tool's pre-show method, so the tool can create any 549 preamble ahead of the message, if it wants. 550 551 * prints the opening tag, and the <unique> and <tid> fields 552 553 * prints the tool-specific parts of the message 554 555 * if suppression generation is required, a suppression 556 557 * the closing tag 558 559 In text mode: 560 561 * calls the tool's pre-show method, so the tool can create any 562 preamble ahead of the message, if it wants. 563 564 * prints the tool-specific parts of the message 565 566 * calls do_actions_on_error. This optionally does a debugger 567 attach (and detach), and optionally prints a suppression; both 568 of these may require user input. 569 */ 570 static void pp_Error ( Error* err, Bool allow_db_attach, Bool xml ) 571 { 572 /* If this fails, you probably specified your tool's method 573 dictionary incorrectly. */ 574 vg_assert(VG_(needs).tool_errors); 575 576 if (xml) { 577 578 /* Note, allow_db_attach is ignored in here. */ 579 580 /* Ensure that suppression generation is either completely 581 enabled or completely disabled; either way, we won't require 582 any user input. m_main.process_cmd_line_options should 583 ensure the asserted condition holds. */ 584 vg_assert( VG_(clo_gen_suppressions) == 0 /* disabled */ 585 || VG_(clo_gen_suppressions) == 2 /* for all errors */ ); 586 587 /* Pre-show it to the tool */ 588 VG_TDICT_CALL( tool_before_pp_Error, err ); 589 590 /* standard preamble */ 591 VG_(printf_xml)("<error>\n"); 592 VG_(printf_xml)(" <unique>0x%x</unique>\n", err->unique); 593 VG_(printf_xml)(" <tid>%d</tid>\n", err->tid); 594 ThreadState* tst = VG_(get_ThreadState)(err->tid); 595 if (tst->thread_name) { 596 VG_(printf_xml)(" <threadname>%s</threadname>\n", tst->thread_name); 597 } 598 599 /* actually print it */ 600 VG_TDICT_CALL( tool_pp_Error, err ); 601 602 if (VG_(clo_gen_suppressions) > 0) 603 gen_suppression(err); 604 605 /* postamble */ 606 VG_(printf_xml)("</error>\n"); 607 VG_(printf_xml)("\n"); 608 609 } else { 610 611 VG_TDICT_CALL( tool_before_pp_Error, err ); 612 613 if (VG_(tdict).tool_show_ThreadIDs_for_errors 614 && err->tid > 0 && err->tid != last_tid_printed) { 615 ThreadState* tst = VG_(get_ThreadState)(err->tid); 616 if (tst->thread_name) { 617 VG_(umsg)("Thread %d %s:\n", err->tid, tst->thread_name ); 618 } else { 619 VG_(umsg)("Thread %d:\n", err->tid ); 620 } 621 last_tid_printed = err->tid; 622 } 623 624 VG_TDICT_CALL( tool_pp_Error, err ); 625 VG_(umsg)("\n"); 626 627 do_actions_on_error(err, allow_db_attach); 628 } 629 } 630 631 632 /* Construct an error */ 633 static 634 void construct_error ( Error* err, ThreadId tid, ErrorKind ekind, Addr a, 635 const HChar* s, void* extra, ExeContext* where ) 636 { 637 /* DO NOT MAKE unique_counter NON-STATIC */ 638 static UInt unique_counter = 0; 639 640 tl_assert(tid < VG_N_THREADS); 641 642 /* Core-only parts */ 643 err->unique = unique_counter++; 644 err->next = NULL; 645 err->supp = NULL; 646 err->count = 1; 647 err->tid = tid; 648 if (NULL == where) 649 err->where = VG_(record_ExeContext)( tid, 0 ); 650 else 651 err->where = where; 652 653 /* Tool-relevant parts */ 654 err->ekind = ekind; 655 err->addr = a; 656 err->extra = extra; 657 err->string = s; 658 659 /* sanity... */ 660 vg_assert( tid < VG_N_THREADS ); 661 } 662 663 664 665 /* Top-level entry point to the error management subsystem. 666 All detected errors are notified here; this routine decides if/when the 667 user should see the error. */ 668 void VG_(maybe_record_error) ( ThreadId tid, 669 ErrorKind ekind, Addr a, const HChar* s, void* extra ) 670 { 671 Error err; 672 Error* p; 673 Error* p_prev; 674 UInt extra_size; 675 VgRes exe_res = Vg_MedRes; 676 static Bool stopping_message = False; 677 static Bool slowdown_message = False; 678 679 /* After M_COLLECT_NO_ERRORS_AFTER_SHOWN different errors have 680 been found, or M_COLLECT_NO_ERRORS_AFTER_FOUND total errors 681 have been found, just refuse to collect any more. This stops 682 the burden of the error-management system becoming excessive in 683 extremely buggy programs, although it does make it pretty 684 pointless to continue the Valgrind run after this point. */ 685 if (VG_(clo_error_limit) 686 && (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN 687 || n_errs_found >= M_COLLECT_NO_ERRORS_AFTER_FOUND) 688 && !VG_(clo_xml)) { 689 if (!stopping_message) { 690 VG_(umsg)("\n"); 691 692 if (n_errs_shown >= M_COLLECT_NO_ERRORS_AFTER_SHOWN) { 693 VG_(umsg)( 694 "More than %d different errors detected. " 695 "I'm not reporting any more.\n", 696 M_COLLECT_NO_ERRORS_AFTER_SHOWN ); 697 } else { 698 VG_(umsg)( 699 "More than %d total errors detected. " 700 "I'm not reporting any more.\n", 701 M_COLLECT_NO_ERRORS_AFTER_FOUND ); 702 } 703 704 VG_(umsg)("Final error counts will be inaccurate. " 705 "Go fix your program!\n"); 706 VG_(umsg)("Rerun with --error-limit=no to disable " 707 "this cutoff. Note\n"); 708 VG_(umsg)("that errors may occur in your program without " 709 "prior warning from\n"); 710 VG_(umsg)("Valgrind, because errors are no longer " 711 "being displayed.\n"); 712 VG_(umsg)("\n"); 713 stopping_message = True; 714 } 715 return; 716 } 717 718 /* Ignore it if error acquisition is disabled for this thread. */ 719 { ThreadState* tst = VG_(get_ThreadState)(tid); 720 if (tst->err_disablement_level > 0) 721 return; 722 } 723 724 /* After M_COLLECT_ERRORS_SLOWLY_AFTER different errors have 725 been found, be much more conservative about collecting new 726 ones. */ 727 if (n_errs_shown >= M_COLLECT_ERRORS_SLOWLY_AFTER 728 && !VG_(clo_xml)) { 729 exe_res = Vg_LowRes; 730 if (!slowdown_message) { 731 VG_(umsg)("\n"); 732 VG_(umsg)("More than %d errors detected. Subsequent errors\n", 733 M_COLLECT_ERRORS_SLOWLY_AFTER); 734 VG_(umsg)("will still be recorded, but in less " 735 "detail than before.\n"); 736 slowdown_message = True; 737 } 738 } 739 740 /* Build ourselves the error */ 741 construct_error ( &err, tid, ekind, a, s, extra, NULL ); 742 743 /* First, see if we've got an error record matching this one. */ 744 em_errlist_searches++; 745 p = errors; 746 p_prev = NULL; 747 while (p != NULL) { 748 em_errlist_cmps++; 749 if (eq_Error(exe_res, p, &err)) { 750 /* Found it. */ 751 p->count++; 752 if (p->supp != NULL) { 753 /* Deal correctly with suppressed errors. */ 754 p->supp->count++; 755 n_errs_suppressed++; 756 } else { 757 n_errs_found++; 758 } 759 760 /* Move p to the front of the list so that future searches 761 for it are faster. It also allows to print the last 762 error (see VG_(show_last_error). */ 763 if (p_prev != NULL) { 764 vg_assert(p_prev->next == p); 765 p_prev->next = p->next; 766 p->next = errors; 767 errors = p; 768 } 769 770 return; 771 } 772 p_prev = p; 773 p = p->next; 774 } 775 776 /* Didn't see it. Copy and add. */ 777 778 /* OK, we're really going to collect it. The context is on the stack and 779 will disappear shortly, so we must copy it. First do the main 780 (non-'extra') part. 781 782 Then VG_(tdict).tool_update_extra can update the 'extra' part. This 783 is for when there are more details to fill in which take time to work 784 out but don't affect our earlier decision to include the error -- by 785 postponing those details until now, we avoid the extra work in the 786 case where we ignore the error. Ugly. 787 788 Then, if there is an 'extra' part, copy it too, using the size that 789 VG_(tdict).tool_update_extra returned. Also allow for people using 790 the void* extra field for a scalar value like an integer. 791 */ 792 793 /* copy main part */ 794 p = VG_(malloc)("errormgr.mre.1", sizeof(Error)); 795 *p = err; 796 797 /* update 'extra' */ 798 switch (ekind) { 799 //(example code, see comment on CoreSuppKind above) 800 //case ThreadErr: 801 // vg_assert(VG_(needs).core_errors); 802 // extra_size = <something> 803 // break; 804 default: 805 vg_assert(VG_(needs).tool_errors); 806 extra_size = VG_TDICT_CALL(tool_update_extra, p); 807 break; 808 } 809 810 /* copy block pointed to by 'extra', if there is one */ 811 if (NULL != p->extra && 0 != extra_size) { 812 void* new_extra = VG_(malloc)("errormgr.mre.2", extra_size); 813 VG_(memcpy)(new_extra, p->extra, extra_size); 814 p->extra = new_extra; 815 } 816 817 p->next = errors; 818 p->supp = is_suppressible_error(&err); 819 errors = p; 820 if (p->supp == NULL) { 821 /* update stats */ 822 n_err_contexts++; 823 n_errs_found++; 824 n_errs_shown++; 825 /* Actually show the error; more complex than you might think. */ 826 pp_Error( p, /*allow_db_attach*/True, VG_(clo_xml) ); 827 } else { 828 n_supp_contexts++; 829 n_errs_suppressed++; 830 p->supp->count++; 831 } 832 } 833 834 /* Second top-level entry point to the error management subsystem, for 835 errors that the tool wants to report immediately, eg. because they're 836 guaranteed to only happen once. This avoids all the recording and 837 comparing stuff. But they can be suppressed; returns True if it is 838 suppressed. Bool 'print_error' dictates whether to print the error. 839 Bool 'count_error' dictates whether to count the error in n_errs_found. 840 */ 841 Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind, Addr a, const HChar* s, 842 void* extra, ExeContext* where, Bool print_error, 843 Bool allow_db_attach, Bool count_error ) 844 { 845 Error err; 846 Supp *su; 847 848 /* Ignore it if error acquisition is disabled for this thread. */ 849 ThreadState* tst = VG_(get_ThreadState)(tid); 850 if (tst->err_disablement_level > 0) 851 return False; /* ignored, not suppressed */ 852 853 /* Build ourselves the error */ 854 construct_error ( &err, tid, ekind, a, s, extra, where ); 855 856 /* Unless it's suppressed, we're going to show it. Don't need to make 857 a copy, because it's only temporary anyway. 858 859 Then update the 'extra' part with VG_(tdict).tool_update_extra), 860 because that can have an affect on whether it's suppressed. Ignore 861 the size return value of VG_(tdict).tool_update_extra, because we're 862 not copying 'extra'. */ 863 (void)VG_TDICT_CALL(tool_update_extra, &err); 864 865 su = is_suppressible_error(&err); 866 if (NULL == su) { 867 if (count_error) { 868 n_errs_found++; 869 n_err_contexts++; 870 } 871 872 if (print_error) { 873 /* update stats */ 874 n_errs_shown++; 875 /* Actually show the error; more complex than you might think. */ 876 pp_Error(&err, allow_db_attach, VG_(clo_xml)); 877 } 878 return False; 879 880 } else { 881 if (count_error) { 882 n_errs_suppressed++; 883 n_supp_contexts++; 884 } 885 su->count++; 886 return True; 887 } 888 } 889 890 891 /*------------------------------------------------------------*/ 892 /*--- Exported fns ---*/ 893 /*------------------------------------------------------------*/ 894 895 /* Show the used suppressions. Returns False if no suppression 896 got used. */ 897 static Bool show_used_suppressions ( void ) 898 { 899 Supp *su; 900 Bool any_supp; 901 902 if (VG_(clo_xml)) 903 VG_(printf_xml)("<suppcounts>\n"); 904 905 any_supp = False; 906 for (su = suppressions; su != NULL; su = su->next) { 907 if (su->count <= 0) 908 continue; 909 if (VG_(clo_xml)) { 910 VG_(printf_xml)( " <pair>\n" 911 " <count>%d</count>\n" 912 " <name>%pS</name>\n" 913 " </pair>\n", 914 su->count, su->sname ); 915 } else { 916 HChar xtra[256]; /* assumed big enough (is overrun-safe) */ 917 Bool anyXtra; 918 // blank line before the first shown suppression, if any 919 if (!any_supp) 920 VG_(dmsg)("\n"); 921 VG_(memset)(xtra, 0, sizeof(xtra)); 922 anyXtra = VG_TDICT_CALL(tool_print_extra_suppression_use, 923 su, xtra, sizeof(xtra)); 924 vg_assert(xtra[sizeof(xtra)-1] == 0); 925 VG_(dmsg)("used_suppression: %6d %s %s:%d%s%s\n", su->count, su->sname, 926 VG_(clo_suppressions)[su->clo_suppressions_i], 927 su->sname_lineno, 928 anyXtra ? " " : "", xtra); 929 } 930 any_supp = True; 931 } 932 933 if (VG_(clo_xml)) 934 VG_(printf_xml)("</suppcounts>\n"); 935 936 return any_supp; 937 } 938 939 /* Show all the errors that occurred, and possibly also the 940 suppressions used. */ 941 void VG_(show_all_errors) ( Int verbosity, Bool xml ) 942 { 943 Int i, n_min; 944 Error *p, *p_min; 945 Bool any_supp; 946 947 if (verbosity == 0) 948 return; 949 950 /* If we're printing XML, just show the suppressions and stop. */ 951 if (xml) { 952 (void)show_used_suppressions(); 953 return; 954 } 955 956 /* We only get here if not printing XML. */ 957 VG_(umsg)("ERROR SUMMARY: " 958 "%d errors from %d contexts (suppressed: %d from %d)\n", 959 n_errs_found, n_err_contexts, 960 n_errs_suppressed, n_supp_contexts ); 961 962 if (verbosity <= 1) 963 return; 964 965 // We do the following only at -v or above, and only in non-XML 966 // mode 967 968 /* Print the contexts in order of increasing error count. 969 Once an error is shown, we add a huge value to its count to filter it 970 out. 971 After having shown all errors, we reset count to the original value. */ 972 for (i = 0; i < n_err_contexts; i++) { 973 n_min = (1 << 30) - 1; 974 p_min = NULL; 975 for (p = errors; p != NULL; p = p->next) { 976 if (p->supp != NULL) continue; 977 if (p->count < n_min) { 978 n_min = p->count; 979 p_min = p; 980 } 981 } 982 // XXX: this isn't right. See bug 203651. 983 if (p_min == NULL) continue; //VG_(tool_panic)("show_all_errors()"); 984 985 VG_(umsg)("\n"); 986 VG_(umsg)("%d errors in context %d of %d:\n", 987 p_min->count, i+1, n_err_contexts); 988 pp_Error( p_min, False/*allow_db_attach*/, False /* xml */ ); 989 990 // We're not printing XML -- we'd have exited above if so. 991 vg_assert(! xml); 992 993 if ((i+1 == VG_(clo_dump_error))) { 994 StackTrace ips = VG_(get_ExeContext_StackTrace)(p_min->where); 995 VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/, 996 ips[0], /*debugging*/True, 0xFE/*verbosity*/, 997 /*bbs_done*/0, 998 /*allow redir?*/True); 999 } 1000 1001 p_min->count = p_min->count + (1 << 30); 1002 } 1003 1004 /* reset the counts, otherwise a 2nd call does not show anything anymore */ 1005 for (p = errors; p != NULL; p = p->next) { 1006 if (p->count >= (1 << 30)) 1007 p->count = p->count - (1 << 30); 1008 } 1009 1010 1011 any_supp = show_used_suppressions(); 1012 1013 if (any_supp) 1014 VG_(umsg)("\n"); 1015 // reprint this, so users don't have to scroll way up to find 1016 // the first printing 1017 VG_(umsg)("ERROR SUMMARY: " 1018 "%d errors from %d contexts (suppressed: %d from %d)\n", 1019 n_errs_found, n_err_contexts, n_errs_suppressed, 1020 n_supp_contexts ); 1021 } 1022 1023 void VG_(show_last_error) ( void ) 1024 { 1025 if (n_err_contexts == 0) { 1026 VG_(umsg)("No errors yet\n"); 1027 return; 1028 } 1029 1030 pp_Error( errors, False/*allow_db_attach*/, False/*xml*/ ); 1031 } 1032 1033 1034 /* Show occurrence counts of all errors, in XML form. */ 1035 void VG_(show_error_counts_as_XML) ( void ) 1036 { 1037 Error* err; 1038 VG_(printf_xml)("<errorcounts>\n"); 1039 for (err = errors; err != NULL; err = err->next) { 1040 if (err->supp != NULL) 1041 continue; 1042 if (err->count <= 0) 1043 continue; 1044 VG_(printf_xml)(" <pair>\n"); 1045 VG_(printf_xml)(" <count>%d</count>\n", err->count); 1046 VG_(printf_xml)(" <unique>0x%x</unique>\n", err->unique); 1047 VG_(printf_xml)(" </pair>\n"); 1048 } 1049 VG_(printf_xml)("</errorcounts>\n"); 1050 VG_(printf_xml)("\n"); 1051 } 1052 1053 1054 /*------------------------------------------------------------*/ 1055 /*--- Suppression parsing ---*/ 1056 /*------------------------------------------------------------*/ 1057 1058 /* Get the next char from fd into *out_buf. Returns 1 if success, 1059 0 if eof or < 0 if error. */ 1060 1061 static Int get_char ( Int fd, HChar* out_buf ) 1062 { 1063 Int r; 1064 static HChar buf[256]; 1065 static Int buf_size = 0; 1066 static Int buf_used = 0; 1067 vg_assert(buf_size >= 0 && buf_size <= 256); 1068 vg_assert(buf_used >= 0 && buf_used <= buf_size); 1069 if (buf_used == buf_size) { 1070 r = VG_(read)(fd, buf, 256); 1071 if (r < 0) return r; /* read failed */ 1072 vg_assert(r >= 0 && r <= 256); 1073 buf_size = r; 1074 buf_used = 0; 1075 } 1076 if (buf_size == 0) 1077 return 0; /* eof */ 1078 vg_assert(buf_size >= 0 && buf_size <= 256); 1079 vg_assert(buf_used >= 0 && buf_used < buf_size); 1080 *out_buf = buf[buf_used]; 1081 buf_used++; 1082 return 1; 1083 } 1084 1085 // Get a non blank non comment line. 1086 // Returns True if eof. 1087 static Bool get_nbnc_line ( Int fd, HChar** bufpp, SizeT* nBufp, Int* lineno ) 1088 { 1089 HChar* buf = *bufpp; 1090 SizeT nBuf = *nBufp; 1091 HChar ch; 1092 Int n, i; 1093 1094 vg_assert(lineno); // lineno needed to correctly track line numbers. 1095 1096 while (True) { 1097 buf[0] = 0; 1098 /* First, read until a non-blank char appears. */ 1099 while (True) { 1100 n = get_char(fd, &ch); 1101 if (n == 1 && !VG_(isspace)(ch)) break; 1102 if (n == 1 && ch == '\n' && lineno) 1103 (*lineno)++; 1104 if (n <= 0) return True; 1105 } 1106 1107 /* Now, read the line into buf. */ 1108 i = 0; 1109 buf[i++] = ch; buf[i] = 0; 1110 while (True) { 1111 n = get_char(fd, &ch); 1112 if (n <= 0) return False; /* the next call will return True */ 1113 if (ch == '\n' && lineno) 1114 (*lineno)++; 1115 if (ch == '\n') break; 1116 if (i > 0 && i == nBuf-1) { 1117 *nBufp = nBuf = nBuf * 2; 1118 #define RIDICULOUS 100000 1119 vg_assert2(nBuf < RIDICULOUS, // Just a sanity check, really. 1120 "VG_(get_line): line longer than %d chars, aborting\n", 1121 RIDICULOUS); 1122 *bufpp = buf = VG_(realloc)("errormgr.get_line.1", buf, nBuf); 1123 } 1124 buf[i++] = ch; buf[i] = 0; 1125 } 1126 while (i > 1 && VG_(isspace)(buf[i-1])) { 1127 i--; buf[i] = 0; 1128 }; 1129 1130 // VG_(printf)("The line *%p %d is '%s'\n", lineno, *lineno, buf); 1131 /* Ok, we have a line. If a non-comment line, return. 1132 If a comment line, start all over again. */ 1133 if (buf[0] != '#') return False; 1134 } 1135 } 1136 1137 // True if buf starts with fun: or obj: or is ... 1138 static Bool is_location_line (HChar* buf) 1139 { 1140 return VG_(strncmp)(buf, "fun:", 4) == 0 1141 || VG_(strncmp)(buf, "obj:", 4) == 0 1142 || VG_(strcmp)(buf, "...") == 0; 1143 } 1144 1145 Bool VG_(get_line) ( Int fd, HChar** bufpp, SizeT* nBufp, Int* lineno ) 1146 { 1147 Bool eof = get_nbnc_line (fd, bufpp, nBufp, lineno); 1148 1149 if (eof) 1150 return True; 1151 1152 if (is_location_line(*bufpp)) 1153 return True; // Not a extra suppr line 1154 else 1155 return False; // A suppression extra line 1156 } 1157 1158 /* True if s contains no wildcard (?, *) characters. */ 1159 static Bool is_simple_str (const HChar *s) 1160 { 1161 while (*s) { 1162 if (*s == '?' || *s == '*') 1163 return False; 1164 s++; 1165 } 1166 return True; 1167 } 1168 1169 /* buf contains the raw name of a caller, supposedly either 1170 fun:some_function_name or 1171 obj:some_object_name or 1172 ... 1173 Set p->ty and p->name accordingly. 1174 p->name is allocated and set to the string 1175 after the descriptor (fun: or obj:) part. 1176 Returns False if failed. 1177 */ 1178 static Bool setLocationTy ( SuppLoc* p, HChar *buf ) 1179 { 1180 if (VG_(strncmp)(buf, "fun:", 4) == 0) { 1181 p->name = VG_(arena_strdup)(VG_AR_CORE, 1182 "errormgr.sLTy.1", buf+4); 1183 p->name_is_simple_str = is_simple_str (p->name); 1184 p->ty = FunName; 1185 return True; 1186 } 1187 if (VG_(strncmp)(buf, "obj:", 4) == 0) { 1188 p->name = VG_(arena_strdup)(VG_AR_CORE, 1189 "errormgr.sLTy.2", buf+4); 1190 p->name_is_simple_str = is_simple_str (p->name); 1191 p->ty = ObjName; 1192 return True; 1193 } 1194 if (VG_(strcmp)(buf, "...") == 0) { 1195 p->name = NULL; 1196 p->name_is_simple_str = False; 1197 p->ty = DotDotDot; 1198 return True; 1199 } 1200 VG_(printf)("location should be \"...\", or should start " 1201 "with \"fun:\" or \"obj:\"\n"); 1202 return False; 1203 } 1204 1205 1206 /* Look for "tool" in a string like "tool1,tool2,tool3" */ 1207 static Bool tool_name_present(const HChar *name, HChar *names) 1208 { 1209 Bool found; 1210 HChar *s = NULL; /* Shut gcc up */ 1211 Int len = VG_(strlen)(name); 1212 1213 found = (NULL != (s = VG_(strstr)(names, name)) && 1214 (s == names || *(s-1) == ',') && 1215 (*(s+len) == ',' || *(s+len) == '\0') 1216 ); 1217 1218 return found; 1219 } 1220 1221 /* Read suppressions from the file specified in 1222 VG_(clo_suppressions)[clo_suppressions_i] 1223 and place them in the suppressions list. If there's any difficulty 1224 doing this, just give up -- there's no point in trying to recover. 1225 */ 1226 static void load_one_suppressions_file ( Int clo_suppressions_i ) 1227 { 1228 const HChar* filename = VG_(clo_suppressions)[clo_suppressions_i]; 1229 SysRes sres; 1230 Int fd, i, j, lineno = 0; 1231 Bool got_a_location_line_read_by_tool; 1232 Bool eof; 1233 SizeT nBuf = 200; 1234 HChar* buf = VG_(malloc)("errormgr.losf.1", nBuf); 1235 HChar* tool_names; 1236 HChar* supp_name; 1237 const HChar* err_str = NULL; 1238 SuppLoc tmp_callers[VG_MAX_SUPP_CALLERS]; 1239 1240 // Check it's not a directory. 1241 if (VG_(is_dir)( filename )) { 1242 if (VG_(clo_xml)) 1243 VG_(printf_xml)("</valgrindoutput>\n"); 1244 VG_(umsg)("FATAL: suppressions file \"%s\" is a directory\n", filename ); 1245 VG_(exit)(1); 1246 } 1247 1248 // Open the suppression file. 1249 sres = VG_(open)( filename, VKI_O_RDONLY, 0 ); 1250 if (sr_isError(sres)) { 1251 if (VG_(clo_xml)) 1252 VG_(printf_xml)("</valgrindoutput>\n"); 1253 VG_(umsg)("FATAL: can't open suppressions file \"%s\"\n", filename ); 1254 VG_(exit)(1); 1255 } 1256 fd = sr_Res(sres); 1257 1258 # define BOMB(S) { err_str = S; goto syntax_error; } 1259 1260 while (True) { 1261 /* Assign and initialise the two suppression halves (core and tool) */ 1262 Supp* supp; 1263 supp = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.1", 1264 sizeof(Supp)); 1265 supp->count = 0; 1266 1267 // Initialise temporary reading-in buffer. 1268 for (i = 0; i < VG_MAX_SUPP_CALLERS; i++) { 1269 tmp_callers[i].ty = NoName; 1270 tmp_callers[i].name_is_simple_str = False; 1271 tmp_callers[i].name = NULL; 1272 } 1273 1274 supp->string = supp->extra = NULL; 1275 1276 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno ); 1277 if (eof) { 1278 VG_(arena_free)(VG_AR_CORE, supp); 1279 break; 1280 } 1281 1282 if (!VG_STREQ(buf, "{")) BOMB("expected '{' or end-of-file"); 1283 1284 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno ); 1285 1286 if (eof || VG_STREQ(buf, "}")) BOMB("unexpected '}'"); 1287 1288 supp->sname = VG_(arena_strdup)(VG_AR_CORE, "errormgr.losf.2", buf); 1289 supp->clo_suppressions_i = clo_suppressions_i; 1290 supp->sname_lineno = lineno; 1291 1292 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno ); 1293 1294 if (eof) BOMB("unexpected end-of-file (expecting tool:suppr)"); 1295 1296 /* Check it has the "tool1,tool2,...:supp" form (look for ':') */ 1297 i = 0; 1298 while (True) { 1299 if (buf[i] == ':') break; 1300 if (buf[i] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line"); 1301 i++; 1302 } 1303 buf[i] = '\0'; /* Replace ':', splitting into two strings */ 1304 1305 tool_names = & buf[0]; 1306 supp_name = & buf[i+1]; 1307 1308 if (VG_(needs).core_errors && tool_name_present("core", tool_names)) 1309 { 1310 // A core suppression 1311 //(example code, see comment on CoreSuppKind above) 1312 //if (VG_STREQ(supp_name, "Thread")) 1313 // supp->skind = ThreadSupp; 1314 //else 1315 BOMB("unknown core suppression type"); 1316 } 1317 else if (VG_(needs).tool_errors && 1318 tool_name_present(VG_(details).name, tool_names)) 1319 { 1320 // A tool suppression 1321 if (VG_TDICT_CALL(tool_recognised_suppression, supp_name, supp)) { 1322 /* Do nothing, function fills in supp->skind */ 1323 } else { 1324 BOMB("unknown tool suppression type"); 1325 } 1326 } 1327 else { 1328 // Ignore rest of suppression 1329 while (True) { 1330 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno ); 1331 if (eof) BOMB("unexpected end-of-file (when skipping suppression)"); 1332 if (VG_STREQ(buf, "}")) 1333 break; 1334 } 1335 VG_(arena_free)(VG_AR_CORE, supp->sname); 1336 VG_(arena_free)(VG_AR_CORE, supp); 1337 continue; 1338 } 1339 1340 buf[0] = 0; 1341 // tool_read_extra_suppression_info might read lines 1342 // from fd till a location line. 1343 if (VG_(needs).tool_errors && 1344 !VG_TDICT_CALL(tool_read_extra_suppression_info, 1345 fd, &buf, &nBuf, &lineno, supp)) 1346 { 1347 BOMB("bad or missing extra suppression info"); 1348 } 1349 1350 got_a_location_line_read_by_tool = buf[0] != 0 && is_location_line(buf); 1351 1352 /* the main frame-descriptor reading loop */ 1353 i = 0; 1354 while (True) { 1355 if (got_a_location_line_read_by_tool) { 1356 got_a_location_line_read_by_tool = False; 1357 eof = False; 1358 } else { 1359 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno ); 1360 } 1361 if (eof) 1362 BOMB("unexpected end-of-file (when reading stack trace)"); 1363 if (VG_STREQ(buf, "}")) { 1364 if (i > 0) { 1365 break; 1366 } else { 1367 BOMB("missing stack trace"); 1368 } 1369 } 1370 if (i == VG_MAX_SUPP_CALLERS) 1371 BOMB("too many callers in stack trace"); 1372 if (i > 0 && i >= VG_(clo_backtrace_size)) 1373 break; 1374 if (!setLocationTy(&(tmp_callers[i]), buf)) 1375 BOMB("location should be \"...\", or should start " 1376 "with \"fun:\" or \"obj:\""); 1377 i++; 1378 } 1379 1380 // If the num callers is >= VG_(clo_backtrace_size), ignore any extra 1381 // lines and grab the '}'. 1382 if (!VG_STREQ(buf, "}")) { 1383 do { 1384 eof = get_nbnc_line ( fd, &buf, &nBuf, &lineno ); 1385 } while (!eof && !VG_STREQ(buf, "}")); 1386 } 1387 1388 // Reject entries which are entirely composed of frame 1389 // level wildcards. 1390 vg_assert(i > 0); // guaranteed by frame-descriptor reading loop 1391 for (j = 0; j < i; j++) { 1392 if (tmp_callers[j].ty == FunName || tmp_callers[j].ty == ObjName) 1393 break; 1394 vg_assert(tmp_callers[j].ty == DotDotDot); 1395 } 1396 vg_assert(j >= 0 && j <= i); 1397 if (j == i) { 1398 // we didn't find any non-"..." entries 1399 BOMB("suppression must contain at least one location " 1400 "line which is not \"...\""); 1401 } 1402 1403 // Copy tmp_callers[] into supp->callers[] 1404 supp->n_callers = i; 1405 supp->callers = VG_(arena_malloc)(VG_AR_CORE, "errormgr.losf.4", 1406 i*sizeof(SuppLoc)); 1407 for (i = 0; i < supp->n_callers; i++) { 1408 supp->callers[i] = tmp_callers[i]; 1409 } 1410 1411 supp->next = suppressions; 1412 suppressions = supp; 1413 } 1414 VG_(free)(buf); 1415 VG_(close)(fd); 1416 return; 1417 1418 syntax_error: 1419 if (VG_(clo_xml)) 1420 VG_(printf_xml)("</valgrindoutput>\n"); 1421 VG_(umsg)("FATAL: in suppressions file \"%s\" near line %d:\n", 1422 filename, lineno ); 1423 VG_(umsg)(" %s\n", err_str ); 1424 1425 VG_(close)(fd); 1426 VG_(umsg)("exiting now.\n"); 1427 VG_(exit)(1); 1428 1429 # undef BOMB 1430 } 1431 1432 1433 void VG_(load_suppressions) ( void ) 1434 { 1435 Int i; 1436 suppressions = NULL; 1437 for (i = 0; i < VG_(clo_n_suppressions); i++) { 1438 if (VG_(clo_verbosity) > 1) { 1439 VG_(dmsg)("Reading suppressions file: %s\n", 1440 VG_(clo_suppressions)[i] ); 1441 } 1442 load_one_suppressions_file( i ); 1443 } 1444 } 1445 1446 1447 /*------------------------------------------------------------*/ 1448 /*--- Matching errors to suppressions ---*/ 1449 /*------------------------------------------------------------*/ 1450 1451 /* Parameterising functions for the use of VG_(generic_match) in 1452 suppression-vs-error matching. The suppression frames (SuppLoc) 1453 play the role of 'pattern'-element, and the error frames (IPs, 1454 hence simply Addrs) play the role of 'input'. In short then, we're 1455 matching a sequence of Addrs against a pattern composed of a 1456 sequence of SuppLocs. 1457 */ 1458 static Bool supploc_IsStar ( const void* supplocV ) 1459 { 1460 const SuppLoc* supploc = supplocV; 1461 return supploc->ty == DotDotDot; 1462 } 1463 1464 static Bool supploc_IsQuery ( const void* supplocV ) 1465 { 1466 return False; /* there's no '?' equivalent in the supp syntax */ 1467 } 1468 1469 /* IPtoFunOrObjCompleter is a lazy completer of the IPs 1470 needed to match an error with the suppression patterns. 1471 The matching between an IP and a suppression pattern is done either 1472 with the IP function name or with the IP object name. 1473 First time the fun or obj name is needed for an IP member 1474 of a stack trace, it will be computed and stored in names. 1475 The IPtoFunOrObjCompleter type is designed to minimise the nr of 1476 allocations and the nr of debuginfo search. */ 1477 typedef 1478 struct { 1479 StackTrace ips; // stack trace we are lazily completing. 1480 UWord n_ips; // nr of elements in ips. 1481 1482 Int* fun_offsets; 1483 // fun_offsets[i] is the offset in names where the 1484 // function name for ips[i] is located. 1485 // An offset -1 means the function name is not yet completed. 1486 Int* obj_offsets; 1487 // Similarly, obj_offsets[i] gives the offset for the 1488 // object name for ips[i] (-1 meaning object name not yet completed). 1489 1490 // All function names and object names will be concatenated 1491 // in names. names is reallocated on demand. 1492 HChar *names; 1493 Int names_szB; // size of names. 1494 Int names_free; // offset first free HChar in names. 1495 } 1496 IPtoFunOrObjCompleter; 1497 1498 // free the memory in ip2fo. 1499 static void clearIPtoFunOrObjCompleter 1500 (IPtoFunOrObjCompleter* ip2fo) 1501 { 1502 if (ip2fo->fun_offsets) VG_(free)(ip2fo->fun_offsets); 1503 if (ip2fo->obj_offsets) VG_(free)(ip2fo->obj_offsets); 1504 if (ip2fo->names) VG_(free)(ip2fo->names); 1505 } 1506 1507 /* foComplete returns the function name or object name for IP. 1508 If needFun, returns the function name for IP 1509 else returns the object name for IP. 1510 The function name or object name will be computed and added in 1511 names if not yet done. 1512 IP must be equal to focompl->ipc[ixIP]. */ 1513 static HChar* foComplete(IPtoFunOrObjCompleter* ip2fo, 1514 Addr IP, Int ixIP, Bool needFun) 1515 { 1516 vg_assert (ixIP < ip2fo->n_ips); 1517 vg_assert (IP == ip2fo->ips[ixIP]); 1518 1519 // ptr to the offset array for function offsets (if needFun) 1520 // or object offsets (if !needFun). 1521 Int** offsets; 1522 if (needFun) 1523 offsets = &ip2fo->fun_offsets; 1524 else 1525 offsets = &ip2fo->obj_offsets; 1526 1527 // Allocate offsets if not yet done. 1528 if (!*offsets) { 1529 Int i; 1530 *offsets = 1531 VG_(malloc)("foComplete", 1532 ip2fo->n_ips * sizeof(Int)); 1533 for (i = 0; i < ip2fo->n_ips; i++) 1534 (*offsets)[i] = -1; 1535 } 1536 1537 // Complete Fun name or Obj name for IP if not yet done. 1538 if ((*offsets)[ixIP] == -1) { 1539 /* Ensure we have ERRTXT_LEN characters available in names */ 1540 if (ip2fo->names_szB 1541 < ip2fo->names_free + ERRTXT_LEN) { 1542 ip2fo->names 1543 = VG_(realloc)("foc_names", 1544 ip2fo->names, 1545 ip2fo->names_szB + ERRTXT_LEN); 1546 ip2fo->names_szB += ERRTXT_LEN; 1547 } 1548 HChar* caller_name = ip2fo->names + ip2fo->names_free; 1549 (*offsets)[ixIP] = ip2fo->names_free; 1550 if (needFun) { 1551 /* Get the function name into 'caller_name', or "???" 1552 if unknown. */ 1553 // Nb: C++-mangled names are used in suppressions. Do, though, 1554 // Z-demangle them, since otherwise it's possible to wind 1555 // up comparing "malloc" in the suppression against 1556 // "_vgrZU_libcZdsoZa_malloc" in the backtrace, and the 1557 // two of them need to be made to match. 1558 if (!VG_(get_fnname_no_cxx_demangle)(IP, caller_name, ERRTXT_LEN)) 1559 VG_(strcpy)(caller_name, "???"); 1560 } else { 1561 /* Get the object name into 'caller_name', or "???" 1562 if unknown. */ 1563 if (!VG_(get_objname)(IP, caller_name, ERRTXT_LEN)) 1564 VG_(strcpy)(caller_name, "???"); 1565 } 1566 ip2fo->names_free += VG_(strlen)(caller_name) + 1; 1567 } 1568 1569 return ip2fo->names + (*offsets)[ixIP]; 1570 } 1571 1572 static Bool supp_pattEQinp ( const void* supplocV, const void* addrV, 1573 void* inputCompleter, UWord ixAddrV ) 1574 { 1575 const SuppLoc* supploc = supplocV; /* PATTERN */ 1576 Addr ip = *(const Addr*)addrV; /* INPUT */ 1577 IPtoFunOrObjCompleter* ip2fo = inputCompleter; 1578 HChar* funobj_name; // Fun or Obj name. 1579 1580 /* So, does this IP address match this suppression-line? */ 1581 switch (supploc->ty) { 1582 case DotDotDot: 1583 /* supp_pattEQinp is a callback from VG_(generic_match). As 1584 per the spec thereof (see include/pub_tool_seqmatch.h), we 1585 should never get called with a pattern value for which the 1586 _IsStar or _IsQuery function would return True. Hence 1587 this can't happen. */ 1588 vg_assert(0); 1589 case ObjName: 1590 funobj_name = foComplete(ip2fo, ip, ixAddrV, False /*needFun*/); 1591 break; 1592 case FunName: 1593 funobj_name = foComplete(ip2fo, ip, ixAddrV, True /*needFun*/); 1594 break; 1595 default: 1596 vg_assert(0); 1597 } 1598 1599 /* So now we have the function or object name in funobj_name, and 1600 the pattern (at the character level) to match against is in 1601 supploc->name. Hence (and leading to a re-entrant call of 1602 VG_(generic_match) if there is a wildcard character): */ 1603 if (supploc->name_is_simple_str) 1604 return VG_(strcmp) (supploc->name, funobj_name) == 0; 1605 else 1606 return VG_(string_match)(supploc->name, funobj_name); 1607 } 1608 1609 ///////////////////////////////////////////////////// 1610 1611 static Bool supp_matches_callers(IPtoFunOrObjCompleter* ip2fo, Supp* su) 1612 { 1613 /* Unwrap the args and set up the correct parameterisation of 1614 VG_(generic_match), using supploc_IsStar, supploc_IsQuery and 1615 supp_pattEQinp. */ 1616 /* note, StackTrace ip2fo->ips === Addr* */ 1617 SuppLoc* supps = su->callers; 1618 UWord n_supps = su->n_callers; 1619 UWord szbPatt = sizeof(SuppLoc); 1620 UWord szbInput = sizeof(Addr); 1621 Bool matchAll = False; /* we just want to match a prefix */ 1622 return 1623 VG_(generic_match)( 1624 matchAll, 1625 /*PATT*/supps, szbPatt, n_supps, 0/*initial Ix*/, 1626 /*INPUT*/ip2fo->ips, szbInput, ip2fo->n_ips, 0/*initial Ix*/, 1627 supploc_IsStar, supploc_IsQuery, supp_pattEQinp, 1628 ip2fo 1629 ); 1630 } 1631 1632 ///////////////////////////////////////////////////// 1633 1634 static 1635 Bool supp_matches_error(Supp* su, Error* err) 1636 { 1637 switch (su->skind) { 1638 //(example code, see comment on CoreSuppKind above) 1639 //case ThreadSupp: 1640 // return (err->ekind == ThreadErr); 1641 default: 1642 if (VG_(needs).tool_errors) { 1643 return VG_TDICT_CALL(tool_error_matches_suppression, err, su); 1644 } else { 1645 VG_(printf)( 1646 "\nUnhandled suppression type: %u. VG_(needs).tool_errors\n" 1647 "probably needs to be set.\n", 1648 err->ekind); 1649 VG_(tool_panic)("unhandled suppression type"); 1650 } 1651 } 1652 } 1653 1654 ///////////////////////////////////////////////////// 1655 1656 /* Does an error context match a suppression? ie is this a suppressible 1657 error? If so, return a pointer to the Supp record, otherwise NULL. 1658 Tries to minimise the number of symbol searches since they are expensive. 1659 */ 1660 static Supp* is_suppressible_error ( Error* err ) 1661 { 1662 Supp* su; 1663 Supp* su_prev; 1664 1665 IPtoFunOrObjCompleter ip2fo; 1666 /* Conceptually, ip2fo contains an array of function names and an array of 1667 object names, corresponding to the array of IP of err->where. 1668 These names are just computed 'on demand' (so once maximum), 1669 then stored (efficiently, avoiding too many allocs) in ip2fo to be 1670 re-usable for the matching of the same IP with the next suppression 1671 pattern. 1672 1673 VG_(generic_match) gets this 'IP to Fun or Obj name completer' as one 1674 of its arguments. It will then pass it to the function 1675 supp_pattEQinp which will then lazily complete the IP function name or 1676 object name inside ip2fo. Next time the fun or obj name for the same 1677 IP is needed (i.e. for the matching with the next suppr pattern), then 1678 the fun or obj name will not be searched again in the debug info. */ 1679 1680 /* stats gathering */ 1681 em_supplist_searches++; 1682 1683 /* Prepare the lazy input completer. */ 1684 ip2fo.ips = VG_(get_ExeContext_StackTrace)(err->where); 1685 ip2fo.n_ips = VG_(get_ExeContext_n_ips)(err->where); 1686 ip2fo.fun_offsets = NULL; 1687 ip2fo.obj_offsets = NULL; 1688 ip2fo.names = NULL; 1689 ip2fo.names_szB = 0; 1690 ip2fo.names_free = 0; 1691 1692 /* See if the error context matches any suppression. */ 1693 su_prev = NULL; 1694 for (su = suppressions; su != NULL; su = su->next) { 1695 em_supplist_cmps++; 1696 if (supp_matches_error(su, err) 1697 && supp_matches_callers(&ip2fo, su)) { 1698 /* got a match. */ 1699 /* Inform the tool that err is suppressed by su. */ 1700 (void)VG_TDICT_CALL(tool_update_extra_suppression_use, err, su); 1701 /* Move this entry to the head of the list 1702 in the hope of making future searches cheaper. */ 1703 if (su_prev) { 1704 vg_assert(su_prev->next == su); 1705 su_prev->next = su->next; 1706 su->next = suppressions; 1707 suppressions = su; 1708 } 1709 clearIPtoFunOrObjCompleter(&ip2fo); 1710 return su; 1711 } 1712 su_prev = su; 1713 } 1714 clearIPtoFunOrObjCompleter(&ip2fo); 1715 return NULL; /* no matches */ 1716 } 1717 1718 /* Show accumulated error-list and suppression-list search stats. 1719 */ 1720 void VG_(print_errormgr_stats) ( void ) 1721 { 1722 VG_(dmsg)( 1723 " errormgr: %'lu supplist searches, %'lu comparisons during search\n", 1724 em_supplist_searches, em_supplist_cmps 1725 ); 1726 VG_(dmsg)( 1727 " errormgr: %'lu errlist searches, %'lu comparisons during search\n", 1728 em_errlist_searches, em_errlist_cmps 1729 ); 1730 } 1731 1732 /*--------------------------------------------------------------------*/ 1733 /*--- end ---*/ 1734 /*--------------------------------------------------------------------*/ 1735