Sort includes for files gdb/[a-f]*.[chyl].
[deliverable/binutils-gdb.git] / gdb / break-catch-sig.c
CommitLineData
ab04a2af
TT
1/* Everything about signal catchpoints, for GDB.
2
42a4f53d 3 Copyright (C) 2011-2019 Free Software Foundation, Inc.
ab04a2af
TT
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"
d55e5aa6
TT
21
22/* Standard C includes. */
ab04a2af 23#include <ctype.h>
d55e5aa6
TT
24
25/* Standard C++ includes. */
26#include <string>
27
28/* Local non-gdb includes. */
29#include "annotate.h"
30#include "arch-utils.h"
ab04a2af 31#include "breakpoint.h"
d55e5aa6
TT
32#include "cli/cli-utils.h"
33#include "completer.h"
ab04a2af
TT
34#include "gdbcmd.h"
35#include "inferior.h"
45741a9c 36#include "infrun.h"
ab04a2af 37#include "valprint.h"
ab04a2af
TT
38
39#define INTERNAL_SIGNAL(x) ((x) == GDB_SIGNAL_TRAP || (x) == GDB_SIGNAL_INT)
40
ab04a2af 41/* An instance of this type is used to represent a signal catchpoint.
c1fc2657 42 A breakpoint is really of this type iff its ops pointer points to
ab04a2af
TT
43 SIGNAL_CATCHPOINT_OPS. */
44
c1fc2657 45struct signal_catchpoint : public breakpoint
ab04a2af 46{
ab04a2af 47 /* Signal numbers used for the 'catch signal' feature. If no signal
f746a154 48 has been specified for filtering, it is empty. Otherwise,
ab04a2af
TT
49 it holds a list of all signals to be caught. */
50
f746a154 51 std::vector<gdb_signal> signals_to_be_caught;
ab04a2af 52
f746a154
TT
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. */
ab04a2af 57
f746a154 58 bool catch_all;
ab04a2af
TT
59};
60
61/* The breakpoint_ops structure to be used in signal catchpoints. */
62
63static struct breakpoint_ops signal_catchpoint_ops;
64
65/* Count of each signal. */
66
67static 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
74static const char *
75signal_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
ab04a2af
TT
87/* Implement the "insert_location" breakpoint_ops method for signal
88 catchpoints. */
89
90static int
91signal_catchpoint_insert_location (struct bp_location *bl)
92{
9a3c8263 93 struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
ab04a2af 94
f746a154 95 if (!c->signals_to_be_caught.empty ())
ab04a2af 96 {
f746a154 97 for (gdb_signal iter : c->signals_to_be_caught)
ab04a2af
TT
98 ++signal_catch_counts[iter];
99 }
100 else
101 {
f746a154 102 for (int i = 0; i < GDB_SIGNAL_LAST; ++i)
ab04a2af
TT
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
117static int
73971819
PA
118signal_catchpoint_remove_location (struct bp_location *bl,
119 enum remove_bp_reason reason)
ab04a2af 120{
9a3c8263 121 struct signal_catchpoint *c = (struct signal_catchpoint *) bl->owner;
ab04a2af 122
f746a154 123 if (!c->signals_to_be_caught.empty ())
ab04a2af 124 {
f746a154 125 for (gdb_signal iter : c->signals_to_be_caught)
ab04a2af
TT
126 {
127 gdb_assert (signal_catch_counts[iter] > 0);
128 --signal_catch_counts[iter];
129 }
130 }
131 else
132 {
f746a154 133 for (int i = 0; i < GDB_SIGNAL_LAST; ++i)
ab04a2af
TT
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
151static int
152signal_catchpoint_breakpoint_hit (const struct bp_location *bl,
bd522513 153 const address_space *aspace,
ab04a2af
TT
154 CORE_ADDR bp_addr,
155 const struct target_waitstatus *ws)
156{
9a3c8263
SM
157 const struct signal_catchpoint *c
158 = (const struct signal_catchpoint *) bl->owner;
f746a154 159 gdb_signal signal_number;
ab04a2af
TT
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. */
f746a154 169 if (!c->signals_to_be_caught.empty ())
ab04a2af 170 {
f746a154 171 for (gdb_signal iter : c->signals_to_be_caught)
ab04a2af 172 if (signal_number == iter)
96f7d3f1 173 return 1;
ab04a2af 174 /* Not the same. */
96f7d3f1 175 return 0;
ab04a2af 176 }
96f7d3f1
PW
177 else
178 return c->catch_all || !INTERNAL_SIGNAL (signal_number);
ab04a2af
TT
179}
180
181/* Implement the "print_it" breakpoint_ops method for signal
182 catchpoints. */
183
184static enum print_stop_action
185signal_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;
f303dbd6 191 struct ui_out *uiout = current_uiout;
ab04a2af
TT
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);
f303dbd6 198 maybe_print_thread_hit_breakpoint (uiout);
ab04a2af 199
f303dbd6 200 printf_filtered (_("Catchpoint %d (signal %s), "), b->number, signal_name);
ab04a2af
TT
201
202 return PRINT_SRC_AND_LOC;
203}
204
205/* Implement the "print_one" breakpoint_ops method for signal
206 catchpoints. */
207
208static void
209signal_catchpoint_print_one (struct breakpoint *b,
210 struct bp_location **last_loc)
211{
9a3c8263 212 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
ab04a2af
TT
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)
112e8700 222 uiout->field_skip ("addr");
ab04a2af
TT
223 annotate_field (5);
224
f746a154 225 if (c->signals_to_be_caught.size () > 1)
112e8700 226 uiout->text ("signals \"");
ab04a2af 227 else
112e8700 228 uiout->text ("signal \"");
ab04a2af 229
f746a154 230 if (!c->signals_to_be_caught.empty ())
ab04a2af 231 {
5809899d 232 std::string text;
ab04a2af 233
f746a154
TT
234 bool first = true;
235 for (gdb_signal iter : c->signals_to_be_caught)
ab04a2af
TT
236 {
237 const char *name = signal_to_name_or_int (iter);
238
f746a154 239 if (!first)
5809899d 240 text += " ";
f746a154
TT
241 first = false;
242
5809899d 243 text += name;
ab04a2af 244 }
112e8700 245 uiout->field_string ("what", text.c_str ());
ab04a2af
TT
246 }
247 else
112e8700 248 uiout->field_string ("what",
ab04a2af 249 c->catch_all ? "<any signal>" : "<standard signals>");
112e8700 250 uiout->text ("\" ");
ab04a2af 251
112e8700
SM
252 if (uiout->is_mi_like_p ())
253 uiout->field_string ("catch-type", "signal");
ab04a2af
TT
254}
255
256/* Implement the "print_mention" breakpoint_ops method for signal
257 catchpoints. */
258
259static void
260signal_catchpoint_print_mention (struct breakpoint *b)
261{
9a3c8263 262 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
ab04a2af 263
f746a154 264 if (!c->signals_to_be_caught.empty ())
ab04a2af 265 {
f746a154 266 if (c->signals_to_be_caught.size () > 1)
ab04a2af
TT
267 printf_filtered (_("Catchpoint %d (signals"), b->number);
268 else
269 printf_filtered (_("Catchpoint %d (signal"), b->number);
270
f746a154 271 for (gdb_signal iter : c->signals_to_be_caught)
ab04a2af
TT
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
288static void
289signal_catchpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
290{
9a3c8263 291 struct signal_catchpoint *c = (struct signal_catchpoint *) b;
ab04a2af
TT
292
293 fprintf_unfiltered (fp, "catch signal");
294
f746a154 295 if (!c->signals_to_be_caught.empty ())
ab04a2af 296 {
f746a154 297 for (gdb_signal iter : c->signals_to_be_caught)
ab04a2af
TT
298 fprintf_unfiltered (fp, " %s", signal_to_name_or_int (iter));
299 }
300 else if (c->catch_all)
301 fprintf_unfiltered (fp, " all");
c780cc2f 302 fputc_unfiltered ('\n', fp);
ab04a2af
TT
303}
304
305/* Implement the "explains_signal" breakpoint_ops method for signal
306 catchpoints. */
307
47591c29 308static int
427cd150 309signal_catchpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
ab04a2af 310{
47591c29 311 return 1;
ab04a2af
TT
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
f746a154 316 can be empty, meaning all signals. CATCH_ALL is a flag indicating
ab04a2af 317 whether signals used internally by gdb should be caught; it is only
f746a154 318 valid if FILTER is NULL. If FILTER is empty and CATCH_ALL is zero,
ab04a2af
TT
319 then internal signals like SIGTRAP are not caught. */
320
321static void
f746a154
TT
322create_signal_catchpoint (int tempflag, std::vector<gdb_signal> &&filter,
323 bool catch_all)
ab04a2af 324{
ab04a2af
TT
325 struct gdbarch *gdbarch = get_current_arch ();
326
b270e6f9
TT
327 std::unique_ptr<signal_catchpoint> c (new signal_catchpoint ());
328 init_catchpoint (c.get (), gdbarch, tempflag, NULL, &signal_catchpoint_ops);
2f5404b3 329 c->signals_to_be_caught = std::move (filter);
ab04a2af
TT
330 c->catch_all = catch_all;
331
b270e6f9 332 install_breakpoint (0, std::move (c), 1);
ab04a2af
TT
333}
334
335
f746a154
TT
336/* Splits the argument using space as delimiter. Returns a filter
337 list, which is empty if no filtering is required. */
ab04a2af 338
f746a154 339static std::vector<gdb_signal>
eb4c3f4a 340catch_signal_split_args (const char *arg, bool *catch_all)
ab04a2af 341{
f746a154
TT
342 std::vector<gdb_signal> result;
343 bool first = true;
ab04a2af
TT
344
345 while (*arg != '\0')
346 {
347 int num;
f746a154
TT
348 gdb_signal signal_number;
349 char *endptr;
ab04a2af 350
cb791d59
TT
351 std::string one_arg = extract_arg (&arg);
352 if (one_arg.empty ())
ab04a2af 353 break;
ab04a2af
TT
354
355 /* Check for the special flag "all". */
cb791d59 356 if (one_arg == "all")
ab04a2af
TT
357 {
358 arg = skip_spaces (arg);
359 if (*arg != '\0' || !first)
360 error (_("'all' cannot be caught with other signals"));
f746a154
TT
361 *catch_all = true;
362 gdb_assert (result.empty ());
363 return result;
ab04a2af
TT
364 }
365
f746a154 366 first = false;
ab04a2af
TT
367
368 /* Check if the user provided a signal name or a number. */
cb791d59 369 num = (int) strtol (one_arg.c_str (), &endptr, 0);
ab04a2af
TT
370 if (*endptr == '\0')
371 signal_number = gdb_signal_from_command (num);
372 else
373 {
cb791d59 374 signal_number = gdb_signal_from_name (one_arg.c_str ());
ab04a2af 375 if (signal_number == GDB_SIGNAL_UNKNOWN)
cb791d59 376 error (_("Unknown signal name '%s'."), one_arg.c_str ());
ab04a2af
TT
377 }
378
f746a154 379 result.push_back (signal_number);
ab04a2af
TT
380 }
381
f746a154 382 result.shrink_to_fit ();
ab04a2af
TT
383 return result;
384}
385
386/* Implement the "catch signal" command. */
387
388static void
eb4c3f4a 389catch_signal_command (const char *arg, int from_tty,
ab04a2af
TT
390 struct cmd_list_element *command)
391{
f746a154
TT
392 int tempflag;
393 bool catch_all = false;
394 std::vector<gdb_signal> filter;
ab04a2af
TT
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);
ab04a2af 408
f746a154 409 create_signal_catchpoint (tempflag, std::move (filter), catch_all);
ab04a2af
TT
410}
411
412static void
413initialize_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;
ab04a2af
TT
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
ab04a2af
TT
431void
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", _("\
439Catch signals by their names and/or numbers.\n\
440Usage: catch signal [[NAME|NUMBER] [NAME|NUMBER]...|all]\n\
441Arguments say which signals to catch. If no arguments\n\
442are given, every \"normal\" signal will be caught.\n\
443The argument \"all\" means to also catch signals used by GDB.\n\
444Arguments, 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.424568 seconds and 4 git commands to generate.