]>
Commit | Line | Data |
---|---|---|
c906108c | 1 | /* Support for complaint handling during symbol reading in GDB. |
b9caf505 | 2 | |
1d506c26 | 3 | Copyright (C) 1990-2024 Free Software Foundation, Inc. |
c906108c | 4 | |
c5aa993b | 5 | This file is part of GDB. |
c906108c | 6 | |
c5aa993b JM |
7 | This program is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by | |
a9762ec7 | 9 | the Free Software Foundation; either version 3 of the License, or |
c5aa993b | 10 | (at your option) any later version. |
c906108c | 11 | |
c5aa993b JM |
12 | This program is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
c906108c | 16 | |
c5aa993b | 17 | You should have received a copy of the GNU General Public License |
a9762ec7 | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
c906108c SS |
19 | |
20 | #include "defs.h" | |
d55e5aa6 | 21 | #include "complaints.h" |
4de283e4 | 22 | #include "command.h" |
c906108c | 23 | #include "gdbcmd.h" |
54b815dd | 24 | #include "run-on-main-thread.h" |
86fe51fc | 25 | #include "gdbsupport/selftest.h" |
4de283e4 | 26 | #include <unordered_map> |
da632297 | 27 | #include <mutex> |
c906108c | 28 | |
ff1cf532 | 29 | /* Map format strings to counters. */ |
c906108c | 30 | |
ff1cf532 | 31 | static std::unordered_map<const char *, int> counters; |
c906108c | 32 | |
b9caf505 AC |
33 | /* How many complaints about a particular thing should be printed |
34 | before we stop whining about it? Default is no whining at all, | |
35 | since so many systems have ill-constructed symbol files. */ | |
36 | ||
62d7ae92 | 37 | int stop_whining = 0; |
b9caf505 | 38 | |
da632297 TT |
39 | #if CXX_STD_THREAD |
40 | static std::mutex complaint_mutex; | |
41 | #endif /* CXX_STD_THREAD */ | |
42 | ||
de54e1a5 | 43 | /* See complaints.h. */ |
b9caf505 | 44 | |
de54e1a5 TT |
45 | void |
46 | complaint_internal (const char *fmt, ...) | |
b9caf505 | 47 | { |
de54e1a5 | 48 | va_list args; |
c5504eaf | 49 | |
da632297 TT |
50 | { |
51 | #if CXX_STD_THREAD | |
52 | std::lock_guard<std::mutex> guard (complaint_mutex); | |
53 | #endif | |
54 | if (++counters[fmt] > stop_whining) | |
55 | return; | |
56 | } | |
b9caf505 | 57 | |
de54e1a5 | 58 | va_start (args, fmt); |
b9caf505 | 59 | |
49346fa7 AVK |
60 | warning_hook_handler handler = get_warning_hook_handler (); |
61 | if (handler != nullptr) | |
62 | handler (fmt, args); | |
b9caf505 | 63 | else |
c906108c | 64 | { |
0426ad51 | 65 | gdb_puts (_("During symbol reading: "), gdb_stderr); |
19a7b8ab | 66 | gdb_vprintf (gdb_stderr, fmt, args); |
0426ad51 | 67 | gdb_puts ("\n", gdb_stderr); |
c906108c | 68 | } |
c906108c | 69 | |
b9caf505 AC |
70 | va_end (args); |
71 | } | |
72 | ||
5ca8c39f | 73 | /* See complaints.h. */ |
c906108c SS |
74 | |
75 | void | |
5ca8c39f | 76 | clear_complaints () |
c906108c | 77 | { |
ff1cf532 | 78 | counters.clear (); |
c906108c SS |
79 | } |
80 | ||
da632297 TT |
81 | /* See complaints.h. */ |
82 | ||
54b815dd | 83 | thread_local complaint_interceptor *complaint_interceptor::g_complaint_interceptor; |
da632297 TT |
84 | |
85 | /* See complaints.h. */ | |
86 | ||
87 | complaint_interceptor::complaint_interceptor () | |
49346fa7 AVK |
88 | : m_saved_complaint_interceptor (&g_complaint_interceptor, this), |
89 | m_saved_warning_hook (issue_complaint) | |
da632297 | 90 | { |
da632297 TT |
91 | } |
92 | ||
93 | /* A helper that wraps a warning hook. */ | |
94 | ||
95 | static void | |
49346fa7 | 96 | wrap_warning_hook (warning_hook_handler hook, ...) |
da632297 TT |
97 | { |
98 | va_list args; | |
99 | va_start (args, hook); | |
100 | hook ("%s", args); | |
101 | va_end (args); | |
102 | } | |
103 | ||
104 | /* See complaints.h. */ | |
105 | ||
54b815dd TT |
106 | void |
107 | re_emit_complaints (const complaint_collection &complaints) | |
da632297 | 108 | { |
54b815dd TT |
109 | gdb_assert (is_main_thread ()); |
110 | ||
111 | for (const std::string &str : complaints) | |
da632297 | 112 | { |
49346fa7 AVK |
113 | warning_hook_handler handler = get_warning_hook_handler (); |
114 | if (handler != nullptr) | |
115 | wrap_warning_hook (handler, str.c_str ()); | |
da632297 TT |
116 | else |
117 | gdb_printf (gdb_stderr, _("During symbol reading: %s\n"), | |
118 | str.c_str ()); | |
119 | } | |
da632297 TT |
120 | } |
121 | ||
122 | /* See complaints.h. */ | |
123 | ||
124 | void | |
125 | complaint_interceptor::issue_complaint (const char *fmt, va_list args) | |
126 | { | |
127 | #if CXX_STD_THREAD | |
128 | std::lock_guard<std::mutex> guard (complaint_mutex); | |
129 | #endif | |
130 | g_complaint_interceptor->m_complaints.insert (string_vprintf (fmt, args)); | |
131 | } | |
132 | ||
335cca0d | 133 | static void |
08546159 AC |
134 | complaints_show_value (struct ui_file *file, int from_tty, |
135 | struct cmd_list_element *cmd, const char *value) | |
335cca0d | 136 | { |
6cb06a8c TT |
137 | gdb_printf (file, _("Max number of complaints about incorrect" |
138 | " symbols is %s.\n"), | |
139 | value); | |
335cca0d AC |
140 | } |
141 | ||
86fe51fc TV |
142 | #if GDB_SELF_TEST |
143 | namespace selftests { | |
144 | ||
145 | /* Entry point for complaints unit tests. */ | |
146 | ||
147 | static void | |
148 | test_complaints () | |
149 | { | |
150 | std::unordered_map<const char *, int> tmp; | |
151 | scoped_restore reset_counters = make_scoped_restore (&counters, tmp); | |
152 | scoped_restore reset_stop_whining = make_scoped_restore (&stop_whining, 2); | |
153 | ||
154 | #define CHECK_COMPLAINT(STR, CNT) \ | |
155 | do \ | |
156 | { \ | |
157 | std::string output; \ | |
84a6adfd | 158 | execute_fn_to_string (output, []() { complaint (STR); }, false); \ |
86fe51fc TV |
159 | std::string expected \ |
160 | = _("During symbol reading: ") + std::string (STR "\n"); \ | |
161 | SELF_CHECK (output == expected); \ | |
162 | SELF_CHECK (counters[STR] == CNT); \ | |
163 | } while (0) | |
164 | ||
165 | #define CHECK_COMPLAINT_SILENT(STR, CNT) \ | |
166 | do \ | |
167 | { \ | |
168 | std::string output; \ | |
84a6adfd | 169 | execute_fn_to_string (output, []() { complaint (STR); }, false); \ |
86fe51fc TV |
170 | SELF_CHECK (output.empty ()); \ |
171 | SELF_CHECK (counters[STR] == CNT); \ | |
172 | } while (0) | |
173 | ||
174 | CHECK_COMPLAINT ("maintenance complaint 0", 1); | |
175 | CHECK_COMPLAINT ("maintenance complaint 0", 2); | |
176 | CHECK_COMPLAINT_SILENT ("maintenance complaint 0", 3); | |
177 | CHECK_COMPLAINT ("maintenance complaint 1", 1); | |
178 | clear_complaints (); | |
179 | CHECK_COMPLAINT ("maintenance complaint 0", 1); | |
180 | ||
181 | #undef CHECK_COMPLAINT | |
182 | #undef CHECK_COMPLAINT_SILENT | |
183 | } | |
184 | ||
185 | ||
186 | } // namespace selftests | |
187 | #endif /* GDB_SELF_TEST */ | |
188 | ||
6c265988 | 189 | void _initialize_complaints (); |
c906108c | 190 | void |
6c265988 | 191 | _initialize_complaints () |
c906108c | 192 | { |
aff410f1 MS |
193 | add_setshow_zinteger_cmd ("complaints", class_support, |
194 | &stop_whining, _("\ | |
3d263c1d | 195 | Set max number of complaints about incorrect symbols."), _("\ |
335cca0d | 196 | Show max number of complaints about incorrect symbols."), NULL, |
08546159 | 197 | NULL, complaints_show_value, |
b3f42336 | 198 | &setlist, &showlist); |
86fe51fc TV |
199 | |
200 | #if GDB_SELF_TEST | |
201 | selftests::register_test ("complaints", selftests::test_complaints); | |
202 | #endif /* GDB_SELF_TEST */ | |
c906108c | 203 | } |