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