14f901f07c257c9982f1e3d654e57dd5abacae07
[deliverable/binutils-gdb.git] / gdb / break-catch-sig.c
1 /* Everything about signal catchpoints, for GDB.
2
3 Copyright (C) 2011-2019 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
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
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
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.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include "defs.h"
21
22 /* Standard C includes. */
23 #include <ctype.h>
24
25 /* Standard C++ includes. */
26 #include <string>
27
28 /* Local non-gdb includes. */
29 #include "annotate.h"
30 #include "arch-utils.h"
31 #include "breakpoint.h"
32 #include "cli/cli-utils.h"
33 #include "completer.h"
34 #include "gdbcmd.h"
35 #include "inferior.h"
36 #include "infrun.h"
37 #include "valprint.h"
38
39 #define INTERNAL_SIGNAL(x) ((x) == GDB_SIGNAL_TRAP || (x) == GDB_SIGNAL_INT)
40
41 /* An instance of this type is used to represent a signal catchpoint.
42 A breakpoint is really of this type iff its ops pointer points to
43 SIGNAL_CATCHPOINT_OPS. */
44
45 struct signal_catchpoint : public breakpoint
46 {
47 /* Signal numbers used for the 'catch signal' feature. If no signal
48 has been specified for filtering, it is empty. Otherwise,
49 it holds a list of all signals to be caught. */
50
51 std::vector<gdb_signal> signals_to_be_caught;
52
53 /* If SIGNALS_TO_BE_CAUGHT is empty, then all "ordinary" signals are
54 caught. If CATCH_ALL is true, then internal signals are caught
55 as well. If SIGNALS_TO_BE_CAUGHT is not empty, then this field
56 is ignored. */
57
58 bool catch_all;
59 };
60
61 /* The breakpoint_ops structure to be used in signal catchpoints. */
62
63 static struct breakpoint_ops signal_catchpoint_ops;
64
65 /* Count of each signal. */
66
67 static unsigned int *signal_catch_counts;
68
69 \f
70
71 /* A convenience wrapper for gdb_signal_to_name that returns the
72 integer value if the name is not known. */
73
74 static const char *
75 signal_to_name_or_int (enum gdb_signal sig)
76 {
77 const char *result = gdb_signal_to_name (sig);
78
79 if (strcmp (result, "?") == 0)
80 result = plongest (sig);
81
82 return result;
83 }
84
85 \f
86
87 /* Implement the "insert_location" breakpoint_ops method for signal
88 catchpoints. */
89
90 static int
91 signal_catchpoint_insert_location (struct bp_location *bl)
92 {
93 struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
94
95 if (!c->signals_to_be_caught.empty ())
96 {
97 for (gdb_signal iter : c->signals_to_be_caught)
98 ++signal_catch_counts[iter];
99 }
100 else
101 {
102 for (int i = 0; i < GDB_SIGNAL_LAST; ++i)
103 {
104 if (c->catch_all || !INTERNAL_SIGNAL (i))
105 ++signal_catch_counts[i];
106 }
107 }
108
109 signal_catch_update (signal_catch_counts);
110
111 return 0;
112 }
113
114 /* Implement the "remove_location" breakpoint_ops method for signal
115 catchpoints. */
116
117 static int
118 signal_catchpoint_remove_location (struct bp_location *bl,
119 enum remove_bp_reason reason)
120 {
121 struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
122
123 if (!c->signals_to_be_caught.empty ())
124 {
125 for (gdb_signal iter : c->signals_to_be_caught)
126 {
127 gdb_assert (signal_catch_counts[iter] > 0);
128 --signal_catch_counts[iter];
129 }
130 }
131 else
132 {
133 for (int i = 0; i < GDB_SIGNAL_LAST; ++i)
134 {
135 if (c->catch_all || !INTERNAL_SIGNAL (i))
136 {
137 gdb_assert (signal_catch_counts[i] > 0);
138 --signal_catch_counts[i];
139 }
140 }
141 }
142
143 signal_catch_update (signal_catch_counts);
144
145 return 0;
146 }
147
148 /* Implement the "breakpoint_hit" breakpoint_ops method for signal
149 catchpoints. */
150
151 static int
152 signal_catchpoint_breakpoint_hit (const struct bp_location *bl,
153 const address_space *aspace,
154 CORE_ADDR bp_addr,
155 const struct target_waitstatus *ws)
156 {
157 const struct signal_catchpoint *c
158 = (const struct signal_catchpoint *) bl->owner;
159 gdb_signal signal_number;
160
161 if (ws->kind != TARGET_WAITKIND_STOPPED)
162 return 0;
163
164 signal_number = ws->value.sig;
165
166 /* If we are catching specific signals in this breakpoint, then we
167 must guarantee that the called signal is the same signal we are
168 catching. */
169 if (!c->signals_to_be_caught.empty ())
170 {
171 for (gdb_signal iter : c->signals_to_be_caught)
172 if (signal_number == iter)
173 return 1;
174 /* Not the same. */
175 return 0;
176 }
177 else
178 return c->catch_all || !INTERNAL_SIGNAL (signal_number);
179 }
180
181 /* Implement the "print_it" breakpoint_ops method for signal
182 catchpoints. */
183
184 static enum print_stop_action
185 signal_catchpoint_print_it (bpstat bs)
186 {
187 struct breakpoint *b = bs->breakpoint_at;
188 ptid_t ptid;
189 struct target_waitstatus last;
190 const char *signal_name;
191 struct ui_out *uiout = current_uiout;
192
193 get_last_target_status (&ptid, &last);
194
195 signal_name = signal_to_name_or_int (last.value.sig);
196
197 annotate_catchpoint (b->number);
198 maybe_print_thread_hit_breakpoint (uiout);
199
200 printf_filtered (_("Catchpoint %d (signal %s), "), b->number, signal_name);
201
202 return PRINT_SRC_AND_LOC;
203 }
204
205 /* Implement the "print_one" breakpoint_ops method for signal
206 catchpoints. */
207
208 static void
209 signal_catchpoint_print_one (struct breakpoint *b,
210 struct bp_location **last_loc)
211 {
212 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
213 struct value_print_options opts;
214 struct ui_out *uiout = current_uiout;
215
216 get_user_print_options (&opts);
217
218 /* Field 4, the address, is omitted (which makes the columns
219 not line up too nicely with the headers, but the effect
220 is relatively readable). */
221 if (opts.addressprint)
222 uiout->field_skip ("addr");
223 annotate_field (5);
224
225 if (c->signals_to_be_caught.size () > 1)
226 uiout->text ("signals \"");
227 else
228 uiout->text ("signal \"");
229
230 if (!c->signals_to_be_caught.empty ())
231 {
232 std::string text;
233
234 bool first = true;
235 for (gdb_signal iter : c->signals_to_be_caught)
236 {
237 const char *name = signal_to_name_or_int (iter);
238
239 if (!first)
240 text += " ";
241 first = false;
242
243 text += name;
244 }
245 uiout->field_string ("what", text.c_str ());
246 }
247 else
248 uiout->field_string ("what",
249 c->catch_all ? "<any signal>" : "<standard signals>");
250 uiout->text ("\" ");
251
252 if (uiout->is_mi_like_p ())
253 uiout->field_string ("catch-type", "signal");
254 }
255
256 /* Implement the "print_mention" breakpoint_ops method for signal
257 catchpoints. */
258
259 static void
260 signal_catchpoint_print_mention (struct breakpoint *b)
261 {
262 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
263
264 if (!c->signals_to_be_caught.empty ())
265 {
266 if (c->signals_to_be_caught.size () > 1)
267 printf_filtered (_("Catchpoint %d (signals"), b->number);
268 else
269 printf_filtered (_("Catchpoint %d (signal"), b->number);
270
271 for (gdb_signal iter : c->signals_to_be_caught)
272 {
273 const char *name = signal_to_name_or_int (iter);
274
275 printf_filtered (" %s", name);
276 }
277 printf_filtered (")");
278 }
279 else if (c->catch_all)
280 printf_filtered (_("Catchpoint %d (any signal)"), b->number);
281 else
282 printf_filtered (_("Catchpoint %d (standard signals)"), b->number);
283 }
284
285 /* Implement the "print_recreate" breakpoint_ops method for signal
286 catchpoints. */
287
288 static void
289 signal_catchpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
290 {
291 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
292
293 fprintf_unfiltered (fp, "catch signal");
294
295 if (!c->signals_to_be_caught.empty ())
296 {
297 for (gdb_signal iter : c->signals_to_be_caught)
298 fprintf_unfiltered (fp, " %s", signal_to_name_or_int (iter));
299 }
300 else if (c->catch_all)
301 fprintf_unfiltered (fp, " all");
302 fputc_unfiltered ('\n', fp);
303 }
304
305 /* Implement the "explains_signal" breakpoint_ops method for signal
306 catchpoints. */
307
308 static int
309 signal_catchpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
310 {
311 return 1;
312 }
313
314 /* Create a new signal catchpoint. TEMPFLAG is true if this should be
315 a temporary catchpoint. FILTER is the list of signals to catch; it
316 can be empty, meaning all signals. CATCH_ALL is a flag indicating
317 whether signals used internally by gdb should be caught; it is only
318 valid if FILTER is NULL. If FILTER is empty and CATCH_ALL is zero,
319 then internal signals like SIGTRAP are not caught. */
320
321 static void
322 create_signal_catchpoint (int tempflag, std::vector<gdb_signal> &&filter,
323 bool catch_all)
324 {
325 struct gdbarch *gdbarch = get_current_arch ();
326
327 std::unique_ptr<signal_catchpoint> c (new signal_catchpoint ());
328 init_catchpoint (c.get (), gdbarch, tempflag, NULL, &signal_catchpoint_ops);
329 c->signals_to_be_caught = std::move (filter);
330 c->catch_all = catch_all;
331
332 install_breakpoint (0, std::move (c), 1);
333 }
334
335
336 /* Splits the argument using space as delimiter. Returns a filter
337 list, which is empty if no filtering is required. */
338
339 static std::vector<gdb_signal>
340 catch_signal_split_args (const char *arg, bool *catch_all)
341 {
342 std::vector<gdb_signal> result;
343 bool first = true;
344
345 while (*arg != '\0')
346 {
347 int num;
348 gdb_signal signal_number;
349 char *endptr;
350
351 std::string one_arg = extract_arg (&arg);
352 if (one_arg.empty ())
353 break;
354
355 /* Check for the special flag "all". */
356 if (one_arg == "all")
357 {
358 arg = skip_spaces (arg);
359 if (*arg != '\0' || !first)
360 error (_("'all' cannot be caught with other signals"));
361 *catch_all = true;
362 gdb_assert (result.empty ());
363 return result;
364 }
365
366 first = false;
367
368 /* Check if the user provided a signal name or a number. */
369 num = (int) strtol (one_arg.c_str (), &endptr, 0);
370 if (*endptr == '\0')
371 signal_number = gdb_signal_from_command (num);
372 else
373 {
374 signal_number = gdb_signal_from_name (one_arg.c_str ());
375 if (signal_number == GDB_SIGNAL_UNKNOWN)
376 error (_("Unknown signal name '%s'."), one_arg.c_str ());
377 }
378
379 result.push_back (signal_number);
380 }
381
382 result.shrink_to_fit ();
383 return result;
384 }
385
386 /* Implement the "catch signal" command. */
387
388 static void
389 catch_signal_command (const char *arg, int from_tty,
390 struct cmd_list_element *command)
391 {
392 int tempflag;
393 bool catch_all = false;
394 std::vector<gdb_signal> filter;
395
396 tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
397
398 arg = skip_spaces (arg);
399
400 /* The allowed syntax is:
401 catch signal
402 catch signal <name | number> [<name | number> ... <name | number>]
403
404 Let's check if there's a signal name. */
405
406 if (arg != NULL)
407 filter = catch_signal_split_args (arg, &catch_all);
408
409 create_signal_catchpoint (tempflag, std::move (filter), catch_all);
410 }
411
412 static void
413 initialize_signal_catchpoint_ops (void)
414 {
415 struct breakpoint_ops *ops;
416
417 initialize_breakpoint_ops ();
418
419 ops = &signal_catchpoint_ops;
420 *ops = base_breakpoint_ops;
421 ops->insert_location = signal_catchpoint_insert_location;
422 ops->remove_location = signal_catchpoint_remove_location;
423 ops->breakpoint_hit = signal_catchpoint_breakpoint_hit;
424 ops->print_it = signal_catchpoint_print_it;
425 ops->print_one = signal_catchpoint_print_one;
426 ops->print_mention = signal_catchpoint_print_mention;
427 ops->print_recreate = signal_catchpoint_print_recreate;
428 ops->explains_signal = signal_catchpoint_explains_signal;
429 }
430
431 void
432 _initialize_break_catch_sig (void)
433 {
434 initialize_signal_catchpoint_ops ();
435
436 signal_catch_counts = XCNEWVEC (unsigned int, GDB_SIGNAL_LAST);
437
438 add_catch_command ("signal", _("\
439 Catch signals by their names and/or numbers.\n\
440 Usage: catch signal [[NAME|NUMBER] [NAME|NUMBER]...|all]\n\
441 Arguments say which signals to catch. If no arguments\n\
442 are given, every \"normal\" signal will be caught.\n\
443 The argument \"all\" means to also catch signals used by GDB.\n\
444 Arguments, if given, should be one or more signal names\n\
445 (if your system supports that), or signal numbers."),
446 catch_signal_command,
447 signal_completer,
448 CATCH_PERMANENT,
449 CATCH_TEMPORARY);
450 }
This page took 0.039488 seconds and 4 git commands to generate.