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