gdb/break-catch-sig.c - gdb
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #include "defs.h"
- #include "arch-utils.h"
- #include <ctype.h>
- #include "breakpoint.h"
- #include "gdbcmd.h"
- #include "inferior.h"
- #include "infrun.h"
- #include "annotate.h"
- #include "valprint.h"
- #include "cli/cli-utils.h"
- #include "completer.h"
- #include "gdb_obstack.h"
- #define INTERNAL_SIGNAL(x) ((x) == GDB_SIGNAL_TRAP || (x) == GDB_SIGNAL_INT)
- typedef enum gdb_signal gdb_signal_type;
- DEF_VEC_I (gdb_signal_type);
- struct signal_catchpoint
- {
-
- struct breakpoint base;
-
- VEC (gdb_signal_type) *signals_to_be_caught;
-
- int catch_all;
- };
- static struct breakpoint_ops signal_catchpoint_ops;
- static unsigned int *signal_catch_counts;
- static const char *
- signal_to_name_or_int (enum gdb_signal sig)
- {
- const char *result = gdb_signal_to_name (sig);
- if (strcmp (result, "?") == 0)
- result = plongest (sig);
- return result;
- }
- static void
- signal_catchpoint_dtor (struct breakpoint *b)
- {
- struct signal_catchpoint *c = (struct signal_catchpoint *) b;
- VEC_free (gdb_signal_type, c->signals_to_be_caught);
- base_breakpoint_ops.dtor (b);
- }
- static int
- signal_catchpoint_insert_location (struct bp_location *bl)
- {
- struct signal_catchpoint *c = (void *) bl->owner;
- int i;
- if (c->signals_to_be_caught != NULL)
- {
- gdb_signal_type iter;
- for (i = 0;
- VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
- i++)
- ++signal_catch_counts[iter];
- }
- else
- {
- for (i = 0; i < GDB_SIGNAL_LAST; ++i)
- {
- if (c->catch_all || !INTERNAL_SIGNAL (i))
- ++signal_catch_counts[i];
- }
- }
- signal_catch_update (signal_catch_counts);
- return 0;
- }
- static int
- signal_catchpoint_remove_location (struct bp_location *bl)
- {
- struct signal_catchpoint *c = (void *) bl->owner;
- int i;
- if (c->signals_to_be_caught != NULL)
- {
- gdb_signal_type iter;
- for (i = 0;
- VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
- i++)
- {
- gdb_assert (signal_catch_counts[iter] > 0);
- --signal_catch_counts[iter];
- }
- }
- else
- {
- for (i = 0; i < GDB_SIGNAL_LAST; ++i)
- {
- if (c->catch_all || !INTERNAL_SIGNAL (i))
- {
- gdb_assert (signal_catch_counts[i] > 0);
- --signal_catch_counts[i];
- }
- }
- }
- signal_catch_update (signal_catch_counts);
- return 0;
- }
- static int
- signal_catchpoint_breakpoint_hit (const struct bp_location *bl,
- struct address_space *aspace,
- CORE_ADDR bp_addr,
- const struct target_waitstatus *ws)
- {
- const struct signal_catchpoint *c = (void *) bl->owner;
- gdb_signal_type signal_number;
- if (ws->kind != TARGET_WAITKIND_STOPPED)
- return 0;
- signal_number = ws->value.sig;
-
- if (c->signals_to_be_caught)
- {
- int i;
- gdb_signal_type iter;
- for (i = 0;
- VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
- i++)
- if (signal_number == iter)
- return 1;
-
- gdb_assert (!iter);
- return 0;
- }
- else
- return c->catch_all || !INTERNAL_SIGNAL (signal_number);
- }
- static enum print_stop_action
- signal_catchpoint_print_it (bpstat bs)
- {
- struct breakpoint *b = bs->breakpoint_at;
- ptid_t ptid;
- struct target_waitstatus last;
- const char *signal_name;
- get_last_target_status (&ptid, &last);
- signal_name = signal_to_name_or_int (last.value.sig);
- annotate_catchpoint (b->number);
- printf_filtered (_("\nCatchpoint %d (signal %s), "), b->number, signal_name);
- return PRINT_SRC_AND_LOC;
- }
- static void
- signal_catchpoint_print_one (struct breakpoint *b,
- struct bp_location **last_loc)
- {
- struct signal_catchpoint *c = (void *) b;
- struct value_print_options opts;
- struct ui_out *uiout = current_uiout;
- get_user_print_options (&opts);
-
- if (opts.addressprint)
- ui_out_field_skip (uiout, "addr");
- annotate_field (5);
- if (c->signals_to_be_caught
- && VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
- ui_out_text (uiout, "signals \"");
- else
- ui_out_text (uiout, "signal \"");
- if (c->signals_to_be_caught)
- {
- int i;
- gdb_signal_type iter;
- struct obstack text;
- struct cleanup *cleanup;
- obstack_init (&text);
- cleanup = make_cleanup_obstack_free (&text);
- for (i = 0;
- VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
- i++)
- {
- const char *name = signal_to_name_or_int (iter);
- if (i > 0)
- obstack_grow (&text, " ", 1);
- obstack_grow (&text, name, strlen (name));
- }
- obstack_grow (&text, "", 1);
- ui_out_field_string (uiout, "what", obstack_base (&text));
- do_cleanups (cleanup);
- }
- else
- ui_out_field_string (uiout, "what",
- c->catch_all ? "<any signal>" : "<standard signals>");
- ui_out_text (uiout, "\" ");
- if (ui_out_is_mi_like_p (uiout))
- ui_out_field_string (uiout, "catch-type", "signal");
- }
- static void
- signal_catchpoint_print_mention (struct breakpoint *b)
- {
- struct signal_catchpoint *c = (void *) b;
- if (c->signals_to_be_caught)
- {
- int i;
- gdb_signal_type iter;
- if (VEC_length (gdb_signal_type, c->signals_to_be_caught) > 1)
- printf_filtered (_("Catchpoint %d (signals"), b->number);
- else
- printf_filtered (_("Catchpoint %d (signal"), b->number);
- for (i = 0;
- VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
- i++)
- {
- const char *name = signal_to_name_or_int (iter);
- printf_filtered (" %s", name);
- }
- printf_filtered (")");
- }
- else if (c->catch_all)
- printf_filtered (_("Catchpoint %d (any signal)"), b->number);
- else
- printf_filtered (_("Catchpoint %d (standard signals)"), b->number);
- }
- static void
- signal_catchpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
- {
- struct signal_catchpoint *c = (void *) b;
- fprintf_unfiltered (fp, "catch signal");
- if (c->signals_to_be_caught)
- {
- int i;
- gdb_signal_type iter;
- for (i = 0;
- VEC_iterate (gdb_signal_type, c->signals_to_be_caught, i, iter);
- i++)
- fprintf_unfiltered (fp, " %s", signal_to_name_or_int (iter));
- }
- else if (c->catch_all)
- fprintf_unfiltered (fp, " all");
- fputc_unfiltered ('\n', fp);
- }
- static int
- signal_catchpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
- {
- return 1;
- }
- static void
- create_signal_catchpoint (int tempflag, VEC (gdb_signal_type) *filter,
- int catch_all)
- {
- struct signal_catchpoint *c;
- struct gdbarch *gdbarch = get_current_arch ();
- c = XNEW (struct signal_catchpoint);
- init_catchpoint (&c->base, gdbarch, tempflag, NULL, &signal_catchpoint_ops);
- c->signals_to_be_caught = filter;
- c->catch_all = catch_all;
- install_breakpoint (0, &c->base, 1);
- }
- static VEC (gdb_signal_type) *
- catch_signal_split_args (char *arg, int *catch_all)
- {
- VEC (gdb_signal_type) *result = NULL;
- struct cleanup *cleanup = make_cleanup (VEC_cleanup (gdb_signal_type),
- &result);
- int first = 1;
- while (*arg != '\0')
- {
- int num;
- gdb_signal_type signal_number;
- char *one_arg, *endptr;
- struct cleanup *inner_cleanup;
- one_arg = extract_arg (&arg);
- if (one_arg == NULL)
- break;
- inner_cleanup = make_cleanup (xfree, one_arg);
-
- if (strcmp (one_arg, "all") == 0)
- {
- arg = skip_spaces (arg);
- if (*arg != '\0' || !first)
- error (_("'all' cannot be caught with other signals"));
- *catch_all = 1;
- gdb_assert (result == NULL);
- do_cleanups (inner_cleanup);
- discard_cleanups (cleanup);
- return NULL;
- }
- first = 0;
-
- num = (int) strtol (one_arg, &endptr, 0);
- if (*endptr == '\0')
- signal_number = gdb_signal_from_command (num);
- else
- {
- signal_number = gdb_signal_from_name (one_arg);
- if (signal_number == GDB_SIGNAL_UNKNOWN)
- error (_("Unknown signal name '%s'."), one_arg);
- }
- VEC_safe_push (gdb_signal_type, result, signal_number);
- do_cleanups (inner_cleanup);
- }
- discard_cleanups (cleanup);
- return result;
- }
- static void
- catch_signal_command (char *arg, int from_tty,
- struct cmd_list_element *command)
- {
- int tempflag, catch_all = 0;
- VEC (gdb_signal_type) *filter;
- tempflag = get_cmd_context (command) == CATCH_TEMPORARY;
- arg = skip_spaces (arg);
-
- if (arg != NULL)
- filter = catch_signal_split_args (arg, &catch_all);
- else
- filter = NULL;
- create_signal_catchpoint (tempflag, filter, catch_all);
- }
- static void
- initialize_signal_catchpoint_ops (void)
- {
- struct breakpoint_ops *ops;
- initialize_breakpoint_ops ();
- ops = &signal_catchpoint_ops;
- *ops = base_breakpoint_ops;
- ops->dtor = signal_catchpoint_dtor;
- ops->insert_location = signal_catchpoint_insert_location;
- ops->remove_location = signal_catchpoint_remove_location;
- ops->breakpoint_hit = signal_catchpoint_breakpoint_hit;
- ops->print_it = signal_catchpoint_print_it;
- ops->print_one = signal_catchpoint_print_one;
- ops->print_mention = signal_catchpoint_print_mention;
- ops->print_recreate = signal_catchpoint_print_recreate;
- ops->explains_signal = signal_catchpoint_explains_signal;
- }
- initialize_file_ftype _initialize_break_catch_sig;
- void
- _initialize_break_catch_sig (void)
- {
- initialize_signal_catchpoint_ops ();
- signal_catch_counts = XCNEWVEC (unsigned int, GDB_SIGNAL_LAST);
- add_catch_command ("signal", _("\
- Catch signals by their names and/or numbers.\n\
- Usage: catch signal [[NAME|NUMBER] [NAME|NUMBER]...|all]\n\
- Arguments say which signals to catch. If no arguments\n\
- are given, every \"normal\" signal will be caught.\n\
- The argument \"all\" means to also catch signals used by GDB.\n\
- Arguments, if given, should be one or more signal names\n\
- (if your system supports that), or signal numbers."),
- catch_signal_command,
- signal_completer,
- CATCH_PERMANENT,
- CATCH_TEMPORARY);
- }