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 *
signal_to_name_or_int(enum gdb_signal sig)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
signal_catchpoint_dtor(struct breakpoint * b)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
signal_catchpoint_insert_location(struct bp_location * bl)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
signal_catchpoint_remove_location(struct bp_location * bl)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
signal_catchpoint_breakpoint_hit(const struct bp_location * bl,struct address_space * aspace,CORE_ADDR bp_addr,const struct target_waitstatus * ws)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
signal_catchpoint_print_it(bpstat bs)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
signal_catchpoint_print_one(struct breakpoint * b,struct bp_location ** last_loc)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
signal_catchpoint_print_mention(struct breakpoint * b)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
signal_catchpoint_print_recreate(struct breakpoint * b,struct ui_file * fp)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
signal_catchpoint_explains_signal(struct breakpoint * b,enum gdb_signal sig)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
create_signal_catchpoint(int tempflag,VEC (gdb_signal_type)* filter,int catch_all)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 
VEC(gdb_signal_type)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
catch_signal_command(char * arg,int from_tty,struct cmd_list_element * command)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
initialize_signal_catchpoint_ops(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
_initialize_break_catch_sig(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