xref: /dragonfly/contrib/gdb-7/gdb/mi/mi-cmd-break.c (revision 9348a738)
1 /* MI Command Set - breakpoint and watchpoint commands.
2    Copyright (C) 2000-2013 Free Software Foundation, Inc.
3    Contributed by Cygnus Solutions (a Red Hat company).
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"
21 #include "arch-utils.h"
22 #include "mi-cmds.h"
23 #include "ui-out.h"
24 #include "mi-out.h"
25 #include "breakpoint.h"
26 #include "gdb_string.h"
27 #include "mi-getopt.h"
28 #include "gdb.h"
29 #include "exceptions.h"
30 #include "observer.h"
31 #include "mi-main.h"
32 #include "mi-cmd-break.h"
33 
34 enum
35   {
36     FROM_TTY = 0
37   };
38 
39 /* True if MI breakpoint observers have been registered.  */
40 
41 static int mi_breakpoint_observers_installed;
42 
43 /* Control whether breakpoint_notify may act.  */
44 
45 static int mi_can_breakpoint_notify;
46 
47 /* Output a single breakpoint, when allowed.  */
48 
49 static void
50 breakpoint_notify (struct breakpoint *b)
51 {
52   if (mi_can_breakpoint_notify)
53     gdb_breakpoint_query (current_uiout, b->number, NULL);
54 }
55 
56 enum bp_type
57   {
58     REG_BP,
59     HW_BP,
60     REGEXP_BP
61   };
62 
63 /* Arrange for all new breakpoints and catchpoints to be reported to
64    CURRENT_UIOUT until the cleanup returned by this function is run.
65 
66    Note that MI output will be probably invalid if more than one
67    breakpoint is created inside one MI command.  */
68 
69 struct cleanup *
70 setup_breakpoint_reporting (void)
71 {
72   struct cleanup *rev_flag;
73 
74   if (! mi_breakpoint_observers_installed)
75     {
76       observer_attach_breakpoint_created (breakpoint_notify);
77       mi_breakpoint_observers_installed = 1;
78     }
79 
80   rev_flag = make_cleanup_restore_integer (&mi_can_breakpoint_notify);
81   mi_can_breakpoint_notify = 1;
82 
83   return rev_flag;
84 }
85 
86 
87 /* Implements the -break-insert command.
88    See the MI manual for the list of possible options.  */
89 
90 void
91 mi_cmd_break_insert (char *command, char **argv, int argc)
92 {
93   char *address = NULL;
94   int hardware = 0;
95   int temp_p = 0;
96   int thread = -1;
97   int ignore_count = 0;
98   char *condition = NULL;
99   int pending = 0;
100   int enabled = 1;
101   int tracepoint = 0;
102   struct cleanup *back_to;
103   enum bptype type_wanted;
104   struct breakpoint_ops *ops;
105 
106   enum opt
107     {
108       HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
109       IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
110       TRACEPOINT_OPT,
111     };
112   static const struct mi_opt opts[] =
113   {
114     {"h", HARDWARE_OPT, 0},
115     {"t", TEMP_OPT, 0},
116     {"c", CONDITION_OPT, 1},
117     {"i", IGNORE_COUNT_OPT, 1},
118     {"p", THREAD_OPT, 1},
119     {"f", PENDING_OPT, 0},
120     {"d", DISABLE_OPT, 0},
121     {"a", TRACEPOINT_OPT, 0},
122     { 0, 0, 0 }
123   };
124 
125   /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
126      to denote the end of the option list. */
127   int oind = 0;
128   char *oarg;
129 
130   while (1)
131     {
132       int opt = mi_getopt ("-break-insert", argc, argv,
133 			   opts, &oind, &oarg);
134       if (opt < 0)
135 	break;
136       switch ((enum opt) opt)
137 	{
138 	case TEMP_OPT:
139 	  temp_p = 1;
140 	  break;
141 	case HARDWARE_OPT:
142 	  hardware = 1;
143 	  break;
144 	case CONDITION_OPT:
145 	  condition = oarg;
146 	  break;
147 	case IGNORE_COUNT_OPT:
148 	  ignore_count = atol (oarg);
149 	  break;
150 	case THREAD_OPT:
151 	  thread = atol (oarg);
152 	  break;
153 	case PENDING_OPT:
154 	  pending = 1;
155 	  break;
156 	case DISABLE_OPT:
157 	  enabled = 0;
158 	  break;
159 	case TRACEPOINT_OPT:
160 	  tracepoint = 1;
161 	  break;
162 	}
163     }
164 
165   if (oind >= argc)
166     error (_("-break-insert: Missing <location>"));
167   if (oind < argc - 1)
168     error (_("-break-insert: Garbage following <location>"));
169   address = argv[oind];
170 
171   /* Now we have what we need, let's insert the breakpoint!  */
172   back_to = setup_breakpoint_reporting ();
173 
174   /* Note that to request a fast tracepoint, the client uses the
175      "hardware" flag, although there's nothing of hardware related to
176      fast tracepoints -- one can implement slow tracepoints with
177      hardware breakpoints, but fast tracepoints are always software.
178      "fast" is a misnomer, actually, "jump" would be more appropriate.
179      A simulator or an emulator could conceivably implement fast
180      regular non-jump based tracepoints.  */
181   type_wanted = (tracepoint
182 		 ? (hardware ? bp_fast_tracepoint : bp_tracepoint)
183 		 : (hardware ? bp_hardware_breakpoint : bp_breakpoint));
184   ops = tracepoint ? &tracepoint_breakpoint_ops : &bkpt_breakpoint_ops;
185 
186   create_breakpoint (get_current_arch (), address, condition, thread,
187 		     NULL,
188 		     0 /* condition and thread are valid.  */,
189 		     temp_p, type_wanted,
190 		     ignore_count,
191 		     pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
192 		     ops, 0, enabled, 0, 0);
193   do_cleanups (back_to);
194 
195 }
196 
197 enum wp_type
198 {
199   REG_WP,
200   READ_WP,
201   ACCESS_WP
202 };
203 
204 void
205 mi_cmd_break_passcount (char *command, char **argv, int argc)
206 {
207   int n;
208   int p;
209   struct tracepoint *t;
210 
211   if (argc != 2)
212     error (_("Usage: tracepoint-number passcount"));
213 
214   n = atoi (argv[0]);
215   p = atoi (argv[1]);
216   t = get_tracepoint (n);
217 
218   if (t)
219     {
220       t->pass_count = p;
221       observer_notify_breakpoint_modified (&t->base);
222     }
223   else
224     {
225       error (_("Could not find tracepoint %d"), n);
226     }
227 }
228 
229 /* Insert a watchpoint. The type of watchpoint is specified by the
230    first argument:
231    -break-watch <expr> --> insert a regular wp.
232    -break-watch -r <expr> --> insert a read watchpoint.
233    -break-watch -a <expr> --> insert an access wp.  */
234 
235 void
236 mi_cmd_break_watch (char *command, char **argv, int argc)
237 {
238   char *expr = NULL;
239   enum wp_type type = REG_WP;
240   enum opt
241     {
242       READ_OPT, ACCESS_OPT
243     };
244   static const struct mi_opt opts[] =
245   {
246     {"r", READ_OPT, 0},
247     {"a", ACCESS_OPT, 0},
248     { 0, 0, 0 }
249   };
250 
251   /* Parse arguments. */
252   int oind = 0;
253   char *oarg;
254 
255   while (1)
256     {
257       int opt = mi_getopt ("-break-watch", argc, argv,
258 			   opts, &oind, &oarg);
259 
260       if (opt < 0)
261 	break;
262       switch ((enum opt) opt)
263 	{
264 	case READ_OPT:
265 	  type = READ_WP;
266 	  break;
267 	case ACCESS_OPT:
268 	  type = ACCESS_WP;
269 	  break;
270 	}
271     }
272   if (oind >= argc)
273     error (_("-break-watch: Missing <expression>"));
274   if (oind < argc - 1)
275     error (_("-break-watch: Garbage following <expression>"));
276   expr = argv[oind];
277 
278   /* Now we have what we need, let's insert the watchpoint!  */
279   switch (type)
280     {
281     case REG_WP:
282       watch_command_wrapper (expr, FROM_TTY, 0);
283       break;
284     case READ_WP:
285       rwatch_command_wrapper (expr, FROM_TTY, 0);
286       break;
287     case ACCESS_WP:
288       awatch_command_wrapper (expr, FROM_TTY, 0);
289       break;
290     default:
291       error (_("-break-watch: Unknown watchpoint type."));
292     }
293 }
294 
295 /* The mi_read_next_line consults these variable to return successive
296    command lines.  While it would be clearer to use a closure pointer,
297    it is not expected that any future code will use read_command_lines_1,
298    therefore no point of overengineering.  */
299 
300 static char **mi_command_line_array;
301 static int mi_command_line_array_cnt;
302 static int mi_command_line_array_ptr;
303 
304 static char *
305 mi_read_next_line (void)
306 {
307   if (mi_command_line_array_ptr == mi_command_line_array_cnt)
308     return NULL;
309   else
310     return mi_command_line_array[mi_command_line_array_ptr++];
311 }
312 
313 void
314 mi_cmd_break_commands (char *command, char **argv, int argc)
315 {
316   struct command_line *break_command;
317   char *endptr;
318   int bnum;
319   struct breakpoint *b;
320 
321   if (argc < 1)
322     error (_("USAGE: %s <BKPT> [<COMMAND> [<COMMAND>...]]"), command);
323 
324   bnum = strtol (argv[0], &endptr, 0);
325   if (endptr == argv[0])
326     error (_("breakpoint number argument \"%s\" is not a number."),
327 	   argv[0]);
328   else if (*endptr != '\0')
329     error (_("junk at the end of breakpoint number argument \"%s\"."),
330 	   argv[0]);
331 
332   b = get_breakpoint (bnum);
333   if (b == NULL)
334     error (_("breakpoint %d not found."), bnum);
335 
336   mi_command_line_array = argv;
337   mi_command_line_array_ptr = 1;
338   mi_command_line_array_cnt = argc;
339 
340   if (is_tracepoint (b))
341     break_command = read_command_lines_1 (mi_read_next_line, 1,
342 					  check_tracepoint_command, b);
343   else
344     break_command = read_command_lines_1 (mi_read_next_line, 1, 0, 0);
345 
346   breakpoint_set_commands (b, break_command);
347 }
348 
349