/* Read suppressions from the file specified in vg_clo_suppressions and place them in the suppressions list. If there's any difficulty doing this, just give up -- there's no point in trying to recover. */ static void load_one_suppressions_file ( Char* filename ) { # define N_BUF 200 Int fd, i; Bool eof, too_many_contexts = False; Char buf[N_BUF+1]; Char* tool_names; Char* supp_name; fd = VG_(open)( filename, VKI_O_RDONLY, 0 ); if (fd < 0) { VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file `%s'", filename ); VG_(exit)(1); } while (True) { /* Assign and initialise the two suppression halves (core and tool) */ Supp* supp; supp = VG_(arena_malloc)(VG_AR_CORE, sizeof(Supp)); supp->count = 0; for (i = 0; i < VG_N_SUPP_CALLERS; i++) supp->caller[i] = NULL; supp->string = supp->extra = NULL; eof = VG_(get_line) ( fd, buf, N_BUF ); if (eof) break; if (!VG_STREQ(buf, "{")) goto syntax_error; eof = VG_(get_line) ( fd, buf, N_BUF ); if (eof || VG_STREQ(buf, "}")) goto syntax_error; supp->sname = VG_(arena_strdup)(VG_AR_CORE, buf); eof = VG_(get_line) ( fd, buf, N_BUF ); if (eof) goto syntax_error; /* Check it has the "skin1,skin2,...:supp" form (look for ':') */ i = 0; while (True) { if (buf[i] == ':') break; if (buf[i] == '\0') goto syntax_error; i++; } buf[i] = '\0'; /* Replace ':', splitting into two strings */ tool_names = & buf[0]; supp_name = & buf[i+1]; /* Is it a core suppression? */ if (VG_(needs).core_errors && tool_name_present("core", tool_names)) { if (VG_STREQ(supp_name, "PThread")) supp->skind = PThreadSupp; else goto syntax_error; } /* Is it a tool suppression? */ else if (VG_(needs).skin_errors && tool_name_present(VG_(details).name, tool_names)) { if (SK_(recognised_suppression)(supp_name, supp)) { /* Do nothing, function fills in supp->skind */ } else goto syntax_error; } else { /* Ignore rest of suppression */ while (True) { eof = VG_(get_line) ( fd, buf, N_BUF ); if (eof) goto syntax_error; if (VG_STREQ(buf, "}")) break; } continue; } if (VG_(needs).skin_errors && !SK_(read_extra_suppression_info)(fd, buf, N_BUF, supp)) goto syntax_error; /* "i > 0" ensures at least one caller read. */ for (i = 0; i <= VG_N_SUPP_CALLERS; i++) { eof = VG_(get_line) ( fd, buf, N_BUF ); if (eof) goto syntax_error; if (i > 0 && VG_STREQ(buf, "}")) break; if (i == VG_N_SUPP_CALLERS) break; supp->caller[i] = VG_(arena_strdup)(VG_AR_CORE, buf); if (!setLocationTy(&(supp->caller[i]), &(supp->caller_ty[i]))) goto syntax_error; } /* make sure to grab the '}' if the num callers is >= VG_N_SUPP_CALLERS */ if (!VG_STREQ(buf, "}")) { // Don't just ignore extra lines -- abort. (Someone complained // about silent ignoring of lines in bug #77922.) //do { // eof = VG_(get_line) ( fd, buf, N_BUF ); //} while (!eof && !VG_STREQ(buf, "}")); too_many_contexts = True; goto syntax_error; } supp->next = vg_suppressions; vg_suppressions = supp; } VG_(close)(fd); return; syntax_error: if (eof) { VG_(message)(Vg_UserMsg, "FATAL: in suppressions file `%s': unexpected EOF", filename ); } else if (too_many_contexts) { VG_(message)(Vg_UserMsg, "FATAL: in suppressions file: `%s': at %s:", filename, buf ); VG_(message)(Vg_UserMsg, "too many lines (limit of %d contexts in suppressions)", VG_N_SUPP_CALLERS); } else { VG_(message)(Vg_UserMsg, "FATAL: in suppressions file: `%s': syntax error on: %s", filename, buf ); } VG_(close)(fd); VG_(message)(Vg_UserMsg, "exiting now."); VG_(exit)(1); # undef N_BUF }
/* Read suppressions from the file specified in VG_(clo_suppressions) and place them in the suppressions list. If there's any difficulty doing this, just give up -- there's no point in trying to recover. */ static void load_one_suppressions_file ( Char* filename ) { # define N_BUF 200 SysRes sres; Int fd, i; Bool eof; Char buf[N_BUF+1]; Char* tool_names; Char* supp_name; Char* err_str = NULL; SuppLoc tmp_callers[VG_MAX_SUPP_CALLERS]; fd = -1; sres = VG_(open)( filename, VKI_O_RDONLY, 0 ); if (sres.isError) { if (VG_(clo_xml)) VG_(message)(Vg_UserMsg, "</valgrindoutput>\n"); VG_(message)(Vg_UserMsg, "FATAL: can't open suppressions file '%s'", filename ); VG_(exit)(1); } fd = sres.res; # define BOMB(S) { err_str = S; goto syntax_error; } while (True) { /* Assign and initialise the two suppression halves (core and tool) */ Supp* supp; supp = VG_(arena_malloc)(VG_AR_CORE, sizeof(Supp)); supp->count = 0; // Initialise temporary reading-in buffer. for (i = 0; i < VG_MAX_SUPP_CALLERS; i++) { tmp_callers[i].ty = NoName; tmp_callers[i].name = NULL; } supp->string = supp->extra = NULL; eof = VG_(get_line) ( fd, buf, N_BUF ); if (eof) break; if (!VG_STREQ(buf, "{")) BOMB("expected '{' or end-of-file"); eof = VG_(get_line) ( fd, buf, N_BUF ); if (eof || VG_STREQ(buf, "}")) BOMB("unexpected '}'"); supp->sname = VG_(arena_strdup)(VG_AR_CORE, buf); eof = VG_(get_line) ( fd, buf, N_BUF ); if (eof) BOMB("unexpected end-of-file"); /* Check it has the "tool1,tool2,...:supp" form (look for ':') */ i = 0; while (True) { if (buf[i] == ':') break; if (buf[i] == '\0') BOMB("malformed 'tool1,tool2,...:supp' line"); i++; } buf[i] = '\0'; /* Replace ':', splitting into two strings */ tool_names = & buf[0]; supp_name = & buf[i+1]; if (VG_(needs).core_errors && tool_name_present("core", tool_names)) { // A core suppression //(example code, see comment on CoreSuppKind above) //if (VG_STREQ(supp_name, "Thread")) // supp->skind = ThreadSupp; //else BOMB("unknown core suppression type"); } else if (VG_(needs).tool_errors && tool_name_present(VG_(details).name, tool_names)) { // A tool suppression if (VG_TDICT_CALL(tool_recognised_suppression, supp_name, supp)) { /* Do nothing, function fills in supp->skind */ } else { BOMB("unknown tool suppression type"); } } else { // Ignore rest of suppression while (True) { eof = VG_(get_line) ( fd, buf, N_BUF ); if (eof) BOMB("unexpected end-of-file"); if (VG_STREQ(buf, "}")) break; } continue; } if (VG_(needs).tool_errors && !VG_TDICT_CALL(tool_read_extra_suppression_info, fd, buf, N_BUF, supp)) { BOMB("bad or missing extra suppression info"); } i = 0; while (True) { eof = VG_(get_line) ( fd, buf, N_BUF ); if (eof) BOMB("unexpected end-of-file"); if (VG_STREQ(buf, "}")) { if (i > 0) { break; } else { BOMB("missing stack trace"); } } if (i == VG_MAX_SUPP_CALLERS) BOMB("too many callers in stack trace"); if (i > 0 && i >= VG_(clo_backtrace_size)) break; tmp_callers[i].name = VG_(arena_strdup)(VG_AR_CORE, buf); if (!setLocationTy(&(tmp_callers[i]))) BOMB("location should start with 'fun:' or 'obj:'"); i++; } // If the num callers is >= VG_(clo_backtrace_size), ignore any extra // lines and grab the '}'. if (!VG_STREQ(buf, "}")) { do { eof = VG_(get_line) ( fd, buf, N_BUF ); } while (!eof && !VG_STREQ(buf, "}")); } // Copy tmp_callers[] into supp->callers[] supp->n_callers = i; supp->callers = VG_(arena_malloc)(VG_AR_CORE, i*sizeof(SuppLoc)); for (i = 0; i < supp->n_callers; i++) { supp->callers[i] = tmp_callers[i]; } supp->next = suppressions; suppressions = supp; } VG_(close)(fd); return; syntax_error: if (VG_(clo_xml)) VG_(message)(Vg_UserMsg, "</valgrindoutput>\n"); VG_(message)(Vg_UserMsg, "FATAL: in suppressions file '%s': %s", filename, err_str ); VG_(close)(fd); VG_(message)(Vg_UserMsg, "exiting now."); VG_(exit)(1); # undef BOMB # undef N_BUF }