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