15796c8dcSSimon Schubert /* Support for complaint handling during symbol reading in GDB. 25796c8dcSSimon Schubert 35796c8dcSSimon Schubert Copyright (C) 1990, 1991, 1992, 1993, 1995, 1998, 1999, 2000, 2002, 2004, 4*cf7f2e2dSJohn Marino 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. 55796c8dcSSimon Schubert 65796c8dcSSimon Schubert This file is part of GDB. 75796c8dcSSimon Schubert 85796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify 95796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by 105796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or 115796c8dcSSimon Schubert (at your option) any later version. 125796c8dcSSimon Schubert 135796c8dcSSimon Schubert This program is distributed in the hope that it will be useful, 145796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of 155796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 165796c8dcSSimon Schubert GNU General Public License for more details. 175796c8dcSSimon Schubert 185796c8dcSSimon Schubert You should have received a copy of the GNU General Public License 195796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */ 205796c8dcSSimon Schubert 215796c8dcSSimon Schubert #include "defs.h" 225796c8dcSSimon Schubert #include "complaints.h" 235796c8dcSSimon Schubert #include "gdb_assert.h" 245796c8dcSSimon Schubert #include "command.h" 255796c8dcSSimon Schubert #include "gdbcmd.h" 265796c8dcSSimon Schubert 275796c8dcSSimon Schubert extern void _initialize_complaints (void); 285796c8dcSSimon Schubert 295796c8dcSSimon Schubert /* Should each complaint message be self explanatory, or should we assume that 305796c8dcSSimon Schubert a series of complaints is being produced? */ 315796c8dcSSimon Schubert 325796c8dcSSimon Schubert /* case 1: First message of a series that must 335796c8dcSSimon Schubert start off with explanation. case 2: Subsequent message of a series 345796c8dcSSimon Schubert that needs no explanation (the user already knows we have a problem 355796c8dcSSimon Schubert so we can just state our piece). */ 365796c8dcSSimon Schubert enum complaint_series { 375796c8dcSSimon Schubert /* Isolated self explanatory message. */ 385796c8dcSSimon Schubert ISOLATED_MESSAGE, 395796c8dcSSimon Schubert /* First message of a series, includes an explanation. */ 405796c8dcSSimon Schubert FIRST_MESSAGE, 415796c8dcSSimon Schubert /* First message of a series, but does not need to include any sort 425796c8dcSSimon Schubert of explanation. */ 435796c8dcSSimon Schubert SHORT_FIRST_MESSAGE, 445796c8dcSSimon Schubert /* Subsequent message of a series that needs no explanation (the 455796c8dcSSimon Schubert user already knows we have a problem so we can just state our 465796c8dcSSimon Schubert piece). */ 475796c8dcSSimon Schubert SUBSEQUENT_MESSAGE 485796c8dcSSimon Schubert }; 495796c8dcSSimon Schubert 505796c8dcSSimon Schubert /* Structure to manage complaints about symbol file contents. */ 515796c8dcSSimon Schubert 525796c8dcSSimon Schubert struct complain 535796c8dcSSimon Schubert { 545796c8dcSSimon Schubert const char *file; 555796c8dcSSimon Schubert int line; 565796c8dcSSimon Schubert const char *fmt; 575796c8dcSSimon Schubert int counter; 585796c8dcSSimon Schubert struct complain *next; 595796c8dcSSimon Schubert }; 605796c8dcSSimon Schubert 615796c8dcSSimon Schubert /* The explanatory message that should accompany the complaint. The 625796c8dcSSimon Schubert message is in two parts - pre and post - that are printed around 635796c8dcSSimon Schubert the complaint text. */ 645796c8dcSSimon Schubert struct explanation 655796c8dcSSimon Schubert { 665796c8dcSSimon Schubert const char *prefix; 675796c8dcSSimon Schubert const char *postfix; 685796c8dcSSimon Schubert }; 695796c8dcSSimon Schubert 705796c8dcSSimon Schubert struct complaints 715796c8dcSSimon Schubert { 725796c8dcSSimon Schubert struct complain *root; 735796c8dcSSimon Schubert 745796c8dcSSimon Schubert /* Should each complaint be self explanatory, or should we assume 755796c8dcSSimon Schubert that a series of complaints is being produced? case 0: Isolated 765796c8dcSSimon Schubert self explanatory message. case 1: First message of a series that 775796c8dcSSimon Schubert must start off with explanation. case 2: Subsequent message of a 785796c8dcSSimon Schubert series that needs no explanation (the user already knows we have 795796c8dcSSimon Schubert a problem so we can just state our piece). */ 805796c8dcSSimon Schubert int series; 815796c8dcSSimon Schubert 825796c8dcSSimon Schubert /* The explanatory messages that should accompany the complaint. 835796c8dcSSimon Schubert NOTE: cagney/2002-08-14: In a desperate attempt at being vaguely 845796c8dcSSimon Schubert i18n friendly, this is an array of two messages. When present, 855796c8dcSSimon Schubert the PRE and POST EXPLANATION[SERIES] are used to wrap the 865796c8dcSSimon Schubert message. */ 875796c8dcSSimon Schubert const struct explanation *explanation; 885796c8dcSSimon Schubert }; 895796c8dcSSimon Schubert 905796c8dcSSimon Schubert static struct complain complaint_sentinel; 915796c8dcSSimon Schubert 925796c8dcSSimon Schubert /* The symbol table complaint table. */ 935796c8dcSSimon Schubert 945796c8dcSSimon Schubert static struct explanation symfile_explanations[] = { 955796c8dcSSimon Schubert { "During symbol reading, ", "." }, 965796c8dcSSimon Schubert { "During symbol reading...", "..."}, 975796c8dcSSimon Schubert { "", "..."}, 985796c8dcSSimon Schubert { "", "..."}, 995796c8dcSSimon Schubert { NULL, NULL } 1005796c8dcSSimon Schubert }; 1015796c8dcSSimon Schubert 1025796c8dcSSimon Schubert static struct complaints symfile_complaint_book = { 1035796c8dcSSimon Schubert &complaint_sentinel, 1045796c8dcSSimon Schubert 0, 1055796c8dcSSimon Schubert symfile_explanations 1065796c8dcSSimon Schubert }; 1075796c8dcSSimon Schubert struct complaints *symfile_complaints = &symfile_complaint_book; 1085796c8dcSSimon Schubert 1095796c8dcSSimon Schubert /* Wrapper function to, on-demand, fill in a complaints object. */ 1105796c8dcSSimon Schubert 1115796c8dcSSimon Schubert static struct complaints * 1125796c8dcSSimon Schubert get_complaints (struct complaints **c) 1135796c8dcSSimon Schubert { 1145796c8dcSSimon Schubert if ((*c) != NULL) 1155796c8dcSSimon Schubert return (*c); 1165796c8dcSSimon Schubert (*c) = XMALLOC (struct complaints); 1175796c8dcSSimon Schubert (*c)->root = &complaint_sentinel; 1185796c8dcSSimon Schubert (*c)->series = ISOLATED_MESSAGE; 1195796c8dcSSimon Schubert (*c)->explanation = NULL; 1205796c8dcSSimon Schubert return (*c); 1215796c8dcSSimon Schubert } 1225796c8dcSSimon Schubert 123*cf7f2e2dSJohn Marino static struct complain * ATTRIBUTE_PRINTF (4, 0) 1245796c8dcSSimon Schubert find_complaint (struct complaints *complaints, const char *file, 1255796c8dcSSimon Schubert int line, const char *fmt) 1265796c8dcSSimon Schubert { 1275796c8dcSSimon Schubert struct complain *complaint; 1285796c8dcSSimon Schubert 1295796c8dcSSimon Schubert /* Find the complaint in the table. A more efficient search 1305796c8dcSSimon Schubert algorithm (based on hash table or something) could be used. But 1315796c8dcSSimon Schubert that can wait until someone shows evidence that this lookup is 1325796c8dcSSimon Schubert a real bottle neck. */ 1335796c8dcSSimon Schubert for (complaint = complaints->root; 1345796c8dcSSimon Schubert complaint != NULL; 1355796c8dcSSimon Schubert complaint = complaint->next) 1365796c8dcSSimon Schubert { 1375796c8dcSSimon Schubert if (complaint->fmt == fmt 1385796c8dcSSimon Schubert && complaint->file == file 1395796c8dcSSimon Schubert && complaint->line == line) 1405796c8dcSSimon Schubert return complaint; 1415796c8dcSSimon Schubert } 1425796c8dcSSimon Schubert 1435796c8dcSSimon Schubert /* Oops not seen before, fill in a new complaint. */ 1445796c8dcSSimon Schubert complaint = XMALLOC (struct complain); 1455796c8dcSSimon Schubert complaint->fmt = fmt; 1465796c8dcSSimon Schubert complaint->file = file; 1475796c8dcSSimon Schubert complaint->line = line; 1485796c8dcSSimon Schubert complaint->counter = 0; 1495796c8dcSSimon Schubert complaint->next = NULL; 1505796c8dcSSimon Schubert 1515796c8dcSSimon Schubert /* File it, return it. */ 1525796c8dcSSimon Schubert complaint->next = complaints->root; 1535796c8dcSSimon Schubert complaints->root = complaint; 1545796c8dcSSimon Schubert return complaint; 1555796c8dcSSimon Schubert } 1565796c8dcSSimon Schubert 1575796c8dcSSimon Schubert 1585796c8dcSSimon Schubert /* How many complaints about a particular thing should be printed 1595796c8dcSSimon Schubert before we stop whining about it? Default is no whining at all, 1605796c8dcSSimon Schubert since so many systems have ill-constructed symbol files. */ 1615796c8dcSSimon Schubert 1625796c8dcSSimon Schubert static int stop_whining = 0; 1635796c8dcSSimon Schubert 1645796c8dcSSimon Schubert /* Print a complaint, and link the complaint block into a chain for 1655796c8dcSSimon Schubert later handling. */ 1665796c8dcSSimon Schubert 167*cf7f2e2dSJohn Marino static void ATTRIBUTE_PRINTF (4, 0) 1685796c8dcSSimon Schubert vcomplaint (struct complaints **c, const char *file, int line, const char *fmt, 1695796c8dcSSimon Schubert va_list args) 1705796c8dcSSimon Schubert { 1715796c8dcSSimon Schubert struct complaints *complaints = get_complaints (c); 1725796c8dcSSimon Schubert struct complain *complaint = find_complaint (complaints, file, line, fmt); 1735796c8dcSSimon Schubert enum complaint_series series; 174*cf7f2e2dSJohn Marino 1755796c8dcSSimon Schubert gdb_assert (complaints != NULL); 1765796c8dcSSimon Schubert 1775796c8dcSSimon Schubert complaint->counter++; 1785796c8dcSSimon Schubert if (complaint->counter > stop_whining) 1795796c8dcSSimon Schubert return; 1805796c8dcSSimon Schubert 1815796c8dcSSimon Schubert if (info_verbose) 1825796c8dcSSimon Schubert series = SUBSEQUENT_MESSAGE; 1835796c8dcSSimon Schubert else 1845796c8dcSSimon Schubert series = complaints->series; 1855796c8dcSSimon Schubert 1865796c8dcSSimon Schubert if (complaint->file != NULL) 1875796c8dcSSimon Schubert internal_vwarning (complaint->file, complaint->line, complaint->fmt, args); 1885796c8dcSSimon Schubert else if (deprecated_warning_hook) 1895796c8dcSSimon Schubert (*deprecated_warning_hook) (complaint->fmt, args); 1905796c8dcSSimon Schubert else 1915796c8dcSSimon Schubert { 1925796c8dcSSimon Schubert if (complaints->explanation == NULL) 1935796c8dcSSimon Schubert /* A [v]warning() call always appends a newline. */ 1945796c8dcSSimon Schubert vwarning (complaint->fmt, args); 1955796c8dcSSimon Schubert else 1965796c8dcSSimon Schubert { 1975796c8dcSSimon Schubert char *msg; 1985796c8dcSSimon Schubert struct cleanup *cleanups; 1995796c8dcSSimon Schubert msg = xstrvprintf (complaint->fmt, args); 2005796c8dcSSimon Schubert cleanups = make_cleanup (xfree, msg); 2015796c8dcSSimon Schubert wrap_here (""); 2025796c8dcSSimon Schubert if (series != SUBSEQUENT_MESSAGE) 2035796c8dcSSimon Schubert begin_line (); 2045796c8dcSSimon Schubert /* XXX: i18n */ 2055796c8dcSSimon Schubert fprintf_filtered (gdb_stderr, "%s%s%s", 2065796c8dcSSimon Schubert complaints->explanation[series].prefix, msg, 2075796c8dcSSimon Schubert complaints->explanation[series].postfix); 2085796c8dcSSimon Schubert /* Force a line-break after any isolated message. For the 2095796c8dcSSimon Schubert other cases, clear_complaints() takes care of any missing 2105796c8dcSSimon Schubert trailing newline, the wrap_here() is just a hint. */ 2115796c8dcSSimon Schubert if (series == ISOLATED_MESSAGE) 2125796c8dcSSimon Schubert /* It would be really nice to use begin_line() here. 2135796c8dcSSimon Schubert Unfortunately that function doesn't track GDB_STDERR and 2145796c8dcSSimon Schubert consequently will sometimes supress a line when it 2155796c8dcSSimon Schubert shouldn't. */ 2165796c8dcSSimon Schubert fputs_filtered ("\n", gdb_stderr); 2175796c8dcSSimon Schubert else 2185796c8dcSSimon Schubert wrap_here (""); 2195796c8dcSSimon Schubert do_cleanups (cleanups); 2205796c8dcSSimon Schubert } 2215796c8dcSSimon Schubert } 2225796c8dcSSimon Schubert 2235796c8dcSSimon Schubert switch (series) 2245796c8dcSSimon Schubert { 2255796c8dcSSimon Schubert case ISOLATED_MESSAGE: 2265796c8dcSSimon Schubert break; 2275796c8dcSSimon Schubert case FIRST_MESSAGE: 2285796c8dcSSimon Schubert complaints->series = SUBSEQUENT_MESSAGE; 2295796c8dcSSimon Schubert break; 2305796c8dcSSimon Schubert case SUBSEQUENT_MESSAGE: 2315796c8dcSSimon Schubert case SHORT_FIRST_MESSAGE: 2325796c8dcSSimon Schubert complaints->series = SUBSEQUENT_MESSAGE; 2335796c8dcSSimon Schubert break; 2345796c8dcSSimon Schubert } 2355796c8dcSSimon Schubert 2365796c8dcSSimon Schubert /* If GDB dumps core, we'd like to see the complaints first. 2375796c8dcSSimon Schubert Presumably GDB will not be sending so many complaints that this 2385796c8dcSSimon Schubert becomes a performance hog. */ 2395796c8dcSSimon Schubert 2405796c8dcSSimon Schubert gdb_flush (gdb_stderr); 2415796c8dcSSimon Schubert } 2425796c8dcSSimon Schubert 2435796c8dcSSimon Schubert void 2445796c8dcSSimon Schubert complaint (struct complaints **complaints, const char *fmt, ...) 2455796c8dcSSimon Schubert { 2465796c8dcSSimon Schubert va_list args; 247*cf7f2e2dSJohn Marino 2485796c8dcSSimon Schubert va_start (args, fmt); 2495796c8dcSSimon Schubert vcomplaint (complaints, NULL/*file*/, 0/*line*/, fmt, args); 2505796c8dcSSimon Schubert va_end (args); 2515796c8dcSSimon Schubert } 2525796c8dcSSimon Schubert 2535796c8dcSSimon Schubert void 2545796c8dcSSimon Schubert internal_complaint (struct complaints **complaints, const char *file, 2555796c8dcSSimon Schubert int line, const char *fmt, ...) 2565796c8dcSSimon Schubert { 2575796c8dcSSimon Schubert va_list args; 2585796c8dcSSimon Schubert va_start (args, fmt); 2595796c8dcSSimon Schubert vcomplaint (complaints, file, line, fmt, args); 2605796c8dcSSimon Schubert va_end (args); 2615796c8dcSSimon Schubert } 2625796c8dcSSimon Schubert 2635796c8dcSSimon Schubert /* Clear out / initialize all complaint counters that have ever been 2645796c8dcSSimon Schubert incremented. If LESS_VERBOSE is 1, be less verbose about 2655796c8dcSSimon Schubert successive complaints, since the messages are appearing all 2665796c8dcSSimon Schubert together during a command that is reporting a contiguous block of 2675796c8dcSSimon Schubert complaints (rather than being interleaved with other messages). If 2685796c8dcSSimon Schubert noisy is 1, we are in a noisy command, and our caller will print 2695796c8dcSSimon Schubert enough context for the user to figure it out. */ 2705796c8dcSSimon Schubert 2715796c8dcSSimon Schubert void 2725796c8dcSSimon Schubert clear_complaints (struct complaints **c, int less_verbose, int noisy) 2735796c8dcSSimon Schubert { 2745796c8dcSSimon Schubert struct complaints *complaints = get_complaints (c); 2755796c8dcSSimon Schubert struct complain *p; 2765796c8dcSSimon Schubert 2775796c8dcSSimon Schubert for (p = complaints->root; p != NULL; p = p->next) 2785796c8dcSSimon Schubert { 2795796c8dcSSimon Schubert p->counter = 0; 2805796c8dcSSimon Schubert } 2815796c8dcSSimon Schubert 2825796c8dcSSimon Schubert switch (complaints->series) 2835796c8dcSSimon Schubert { 2845796c8dcSSimon Schubert case FIRST_MESSAGE: 2855796c8dcSSimon Schubert /* Haven't yet printed anything. */ 2865796c8dcSSimon Schubert break; 2875796c8dcSSimon Schubert case SHORT_FIRST_MESSAGE: 2885796c8dcSSimon Schubert /* Haven't yet printed anything. */ 2895796c8dcSSimon Schubert break; 2905796c8dcSSimon Schubert case ISOLATED_MESSAGE: 2915796c8dcSSimon Schubert /* The code above, always forces a line-break. No need to do it 2925796c8dcSSimon Schubert here. */ 2935796c8dcSSimon Schubert break; 2945796c8dcSSimon Schubert case SUBSEQUENT_MESSAGE: 2955796c8dcSSimon Schubert /* It would be really nice to use begin_line() here. 2965796c8dcSSimon Schubert Unfortunately that function doesn't track GDB_STDERR and 2975796c8dcSSimon Schubert consequently will sometimes supress a line when it shouldn't. */ 2985796c8dcSSimon Schubert fputs_unfiltered ("\n", gdb_stderr); 2995796c8dcSSimon Schubert break; 3005796c8dcSSimon Schubert default: 3015796c8dcSSimon Schubert internal_error (__FILE__, __LINE__, _("bad switch")); 3025796c8dcSSimon Schubert } 3035796c8dcSSimon Schubert 3045796c8dcSSimon Schubert if (!less_verbose) 3055796c8dcSSimon Schubert complaints->series = ISOLATED_MESSAGE; 3065796c8dcSSimon Schubert else if (!noisy) 3075796c8dcSSimon Schubert complaints->series = FIRST_MESSAGE; 3085796c8dcSSimon Schubert else 3095796c8dcSSimon Schubert complaints->series = SHORT_FIRST_MESSAGE; 3105796c8dcSSimon Schubert } 3115796c8dcSSimon Schubert 3125796c8dcSSimon Schubert static void 3135796c8dcSSimon Schubert complaints_show_value (struct ui_file *file, int from_tty, 3145796c8dcSSimon Schubert struct cmd_list_element *cmd, const char *value) 3155796c8dcSSimon Schubert { 3165796c8dcSSimon Schubert fprintf_filtered (file, _("Max number of complaints about incorrect" 3175796c8dcSSimon Schubert " symbols is %s.\n"), 3185796c8dcSSimon Schubert value); 3195796c8dcSSimon Schubert } 3205796c8dcSSimon Schubert 3215796c8dcSSimon Schubert void 3225796c8dcSSimon Schubert _initialize_complaints (void) 3235796c8dcSSimon Schubert { 3245796c8dcSSimon Schubert add_setshow_zinteger_cmd ("complaints", class_support, &stop_whining, _("\ 3255796c8dcSSimon Schubert Set max number of complaints about incorrect symbols."), _("\ 3265796c8dcSSimon Schubert Show max number of complaints about incorrect symbols."), NULL, 3275796c8dcSSimon Schubert NULL, complaints_show_value, 3285796c8dcSSimon Schubert &setlist, &showlist); 3295796c8dcSSimon Schubert } 330