xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/mi/mi-cmd-break.c (revision 796c32c94f6e154afc9de0f63da35c91bb739b45)
1 /* MI Command Set - breakpoint and watchpoint commands.
2    Copyright (C) 2000-2016 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 "mi-getopt.h"
27 #include "gdb.h"
28 #include "observer.h"
29 #include "mi-main.h"
30 #include "mi-cmd-break.h"
31 #include "language.h"
32 #include "location.h"
33 #include "linespec.h"
34 #include "gdb_obstack.h"
35 #include <ctype.h>
36 
37 enum
38   {
39     FROM_TTY = 0
40   };
41 
42 /* True if MI breakpoint observers have been registered.  */
43 
44 static int mi_breakpoint_observers_installed;
45 
46 /* Control whether breakpoint_notify may act.  */
47 
48 static int mi_can_breakpoint_notify;
49 
50 /* Output a single breakpoint, when allowed.  */
51 
52 static void
53 breakpoint_notify (struct breakpoint *b)
54 {
55   if (mi_can_breakpoint_notify)
56     gdb_breakpoint_query (current_uiout, b->number, NULL);
57 }
58 
59 enum bp_type
60   {
61     REG_BP,
62     HW_BP,
63     REGEXP_BP
64   };
65 
66 /* Arrange for all new breakpoints and catchpoints to be reported to
67    CURRENT_UIOUT until the cleanup returned by this function is run.
68 
69    Note that MI output will be probably invalid if more than one
70    breakpoint is created inside one MI command.  */
71 
72 struct cleanup *
73 setup_breakpoint_reporting (void)
74 {
75   struct cleanup *rev_flag;
76 
77   if (! mi_breakpoint_observers_installed)
78     {
79       observer_attach_breakpoint_created (breakpoint_notify);
80       mi_breakpoint_observers_installed = 1;
81     }
82 
83   rev_flag = make_cleanup_restore_integer (&mi_can_breakpoint_notify);
84   mi_can_breakpoint_notify = 1;
85 
86   return rev_flag;
87 }
88 
89 
90 /* Convert arguments in ARGV to the string in "format",argv,argv...
91    and return it.  */
92 
93 static char *
94 mi_argv_to_format (char **argv, int argc)
95 {
96   int i;
97   struct obstack obstack;
98   char *ret;
99 
100   obstack_init (&obstack);
101 
102   /* Convert ARGV[OIND + 1] to format string and save to FORMAT.  */
103   obstack_1grow (&obstack, '\"');
104   for (i = 0; i < strlen (argv[0]); i++)
105     {
106       switch (argv[0][i])
107 	{
108 	case '\\':
109 	  obstack_grow (&obstack, "\\\\", 2);
110 	  break;
111 	case '\a':
112 	  obstack_grow (&obstack, "\\a", 2);
113 	  break;
114 	case '\b':
115 	  obstack_grow (&obstack, "\\b", 2);
116 	  break;
117 	case '\f':
118 	  obstack_grow (&obstack, "\\f", 2);
119 	  break;
120 	case '\n':
121 	  obstack_grow (&obstack, "\\n", 2);
122 	  break;
123 	case '\r':
124 	  obstack_grow (&obstack, "\\r", 2);
125 	  break;
126 	case '\t':
127 	  obstack_grow (&obstack, "\\t", 2);
128 	  break;
129 	case '\v':
130 	  obstack_grow (&obstack, "\\v", 2);
131 	  break;
132 	case '"':
133 	  obstack_grow (&obstack, "\\\"", 2);
134 	  break;
135 	default:
136 	  if (isprint (argv[0][i]))
137 	    obstack_grow (&obstack, argv[0] + i, 1);
138 	  else
139 	    {
140 	      char tmp[5];
141 
142 	      xsnprintf (tmp, sizeof (tmp), "\\%o",
143 			 (unsigned char) argv[0][i]);
144 	      obstack_grow (&obstack, tmp, strlen (tmp));
145 	    }
146 	  break;
147 	}
148     }
149   obstack_1grow (&obstack, '\"');
150 
151   /* Apply other argv to FORMAT.  */
152   for (i = 1; i < argc; i++)
153     {
154       obstack_1grow (&obstack, ',');
155       obstack_grow (&obstack, argv[i], strlen (argv[i]));
156     }
157   obstack_1grow (&obstack, '\0');
158 
159   ret = xstrdup ((const char *) obstack_finish (&obstack));
160   obstack_free (&obstack, NULL);
161 
162   return ret;
163 }
164 
165 /* Insert breakpoint.
166    If dprintf is true, it will insert dprintf.
167    If not, it will insert other type breakpoint.  */
168 
169 static void
170 mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
171 {
172   char *address = NULL;
173   int hardware = 0;
174   int temp_p = 0;
175   int thread = -1;
176   int ignore_count = 0;
177   char *condition = NULL;
178   int pending = 0;
179   int enabled = 1;
180   int tracepoint = 0;
181   struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
182   enum bptype type_wanted;
183   struct event_location *location;
184   struct breakpoint_ops *ops;
185   int is_explicit = 0;
186   struct explicit_location explicit_loc;
187   char *extra_string = NULL;
188 
189   enum opt
190     {
191       HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
192       IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
193       TRACEPOINT_OPT,
194       EXPLICIT_SOURCE_OPT, EXPLICIT_FUNC_OPT,
195       EXPLICIT_LABEL_OPT, EXPLICIT_LINE_OPT
196     };
197   static const struct mi_opt opts[] =
198   {
199     {"h", HARDWARE_OPT, 0},
200     {"t", TEMP_OPT, 0},
201     {"c", CONDITION_OPT, 1},
202     {"i", IGNORE_COUNT_OPT, 1},
203     {"p", THREAD_OPT, 1},
204     {"f", PENDING_OPT, 0},
205     {"d", DISABLE_OPT, 0},
206     {"a", TRACEPOINT_OPT, 0},
207     {"-source" , EXPLICIT_SOURCE_OPT, 1},
208     {"-function", EXPLICIT_FUNC_OPT, 1},
209     {"-label", EXPLICIT_LABEL_OPT, 1},
210     {"-line", EXPLICIT_LINE_OPT, 1},
211     { 0, 0, 0 }
212   };
213 
214   /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
215      to denote the end of the option list. */
216   int oind = 0;
217   char *oarg;
218 
219   initialize_explicit_location (&explicit_loc);
220 
221   while (1)
222     {
223       int opt = mi_getopt ("-break-insert", argc, argv,
224 			   opts, &oind, &oarg);
225       if (opt < 0)
226 	break;
227       switch ((enum opt) opt)
228 	{
229 	case TEMP_OPT:
230 	  temp_p = 1;
231 	  break;
232 	case HARDWARE_OPT:
233 	  hardware = 1;
234 	  break;
235 	case CONDITION_OPT:
236 	  condition = oarg;
237 	  break;
238 	case IGNORE_COUNT_OPT:
239 	  ignore_count = atol (oarg);
240 	  break;
241 	case THREAD_OPT:
242 	  thread = atol (oarg);
243 	  break;
244 	case PENDING_OPT:
245 	  pending = 1;
246 	  break;
247 	case DISABLE_OPT:
248 	  enabled = 0;
249 	  break;
250 	case TRACEPOINT_OPT:
251 	  tracepoint = 1;
252 	  break;
253 	case EXPLICIT_SOURCE_OPT:
254 	  is_explicit = 1;
255 	  explicit_loc.source_filename = oarg;
256 	  break;
257 	case EXPLICIT_FUNC_OPT:
258 	  is_explicit = 1;
259 	  explicit_loc.function_name = oarg;
260 	  break;
261 	case EXPLICIT_LABEL_OPT:
262 	  is_explicit = 1;
263 	  explicit_loc.label_name = oarg;
264 	  break;
265 	case EXPLICIT_LINE_OPT:
266 	  is_explicit = 1;
267 	  explicit_loc.line_offset = linespec_parse_line_offset (oarg);
268 	  break;
269 	}
270     }
271 
272   if (oind >= argc && !is_explicit)
273     error (_("-%s-insert: Missing <location>"),
274 	   dprintf ? "dprintf" : "break");
275   if (dprintf)
276     {
277       int format_num = is_explicit ? oind : oind + 1;
278 
279       if (hardware || tracepoint)
280 	error (_("-dprintf-insert: does not support -h or -a"));
281       if (format_num >= argc)
282 	error (_("-dprintf-insert: Missing <format>"));
283 
284       extra_string = mi_argv_to_format (argv + format_num, argc - format_num);
285       make_cleanup (xfree, extra_string);
286       address = argv[oind];
287     }
288   else
289     {
290       if (is_explicit)
291 	{
292 	  if (oind < argc)
293 	    error (_("-break-insert: Garbage following explicit location"));
294 	}
295       else
296 	{
297 	  if (oind < argc - 1)
298 	    error (_("-break-insert: Garbage following <location>"));
299 	  address = argv[oind];
300 	}
301     }
302 
303   /* Now we have what we need, let's insert the breakpoint!  */
304   setup_breakpoint_reporting ();
305 
306   if (tracepoint)
307     {
308       /* Note that to request a fast tracepoint, the client uses the
309 	 "hardware" flag, although there's nothing of hardware related to
310 	 fast tracepoints -- one can implement slow tracepoints with
311 	 hardware breakpoints, but fast tracepoints are always software.
312 	 "fast" is a misnomer, actually, "jump" would be more appropriate.
313 	 A simulator or an emulator could conceivably implement fast
314 	 regular non-jump based tracepoints.  */
315       type_wanted = hardware ? bp_fast_tracepoint : bp_tracepoint;
316       ops = &tracepoint_breakpoint_ops;
317     }
318   else if (dprintf)
319     {
320       type_wanted = bp_dprintf;
321       ops = &dprintf_breakpoint_ops;
322     }
323   else
324     {
325       type_wanted = hardware ? bp_hardware_breakpoint : bp_breakpoint;
326       ops = &bkpt_breakpoint_ops;
327     }
328 
329   if (is_explicit)
330     {
331       /* Error check -- we must have one of the other
332 	 parameters specified.  */
333       if (explicit_loc.source_filename != NULL
334 	  && explicit_loc.function_name == NULL
335 	  && explicit_loc.label_name == NULL
336 	  && explicit_loc.line_offset.sign == LINE_OFFSET_UNKNOWN)
337 	error (_("-%s-insert: --source option requires --function, --label,"
338 		 " or --line"), dprintf ? "dprintf" : "break");
339 
340       location = new_explicit_location (&explicit_loc);
341     }
342   else
343     {
344       location = string_to_event_location_basic (&address, current_language);
345       if (*address)
346 	{
347 	  delete_event_location (location);
348 	  error (_("Garbage '%s' at end of location"), address);
349 	}
350     }
351 
352   make_cleanup_delete_event_location (location);
353 
354   create_breakpoint (get_current_arch (), location, condition, thread,
355 		     extra_string,
356 		     0 /* condition and thread are valid.  */,
357 		     temp_p, type_wanted,
358 		     ignore_count,
359 		     pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
360 		     ops, 0, enabled, 0, 0);
361   do_cleanups (back_to);
362 }
363 
364 /* Implements the -break-insert command.
365    See the MI manual for the list of possible options.  */
366 
367 void
368 mi_cmd_break_insert (char *command, char **argv, int argc)
369 {
370   mi_cmd_break_insert_1 (0, command, argv, argc);
371 }
372 
373 /* Implements the -dprintf-insert command.
374    See the MI manual for the list of possible options.  */
375 
376 void
377 mi_cmd_dprintf_insert (char *command, char **argv, int argc)
378 {
379   mi_cmd_break_insert_1 (1, command, argv, argc);
380 }
381 
382 enum wp_type
383 {
384   REG_WP,
385   READ_WP,
386   ACCESS_WP
387 };
388 
389 void
390 mi_cmd_break_passcount (char *command, char **argv, int argc)
391 {
392   int n;
393   int p;
394   struct tracepoint *t;
395 
396   if (argc != 2)
397     error (_("Usage: tracepoint-number passcount"));
398 
399   n = atoi (argv[0]);
400   p = atoi (argv[1]);
401   t = get_tracepoint (n);
402 
403   if (t)
404     {
405       t->pass_count = p;
406       observer_notify_breakpoint_modified (&t->base);
407     }
408   else
409     {
410       error (_("Could not find tracepoint %d"), n);
411     }
412 }
413 
414 /* Insert a watchpoint. The type of watchpoint is specified by the
415    first argument:
416    -break-watch <expr> --> insert a regular wp.
417    -break-watch -r <expr> --> insert a read watchpoint.
418    -break-watch -a <expr> --> insert an access wp.  */
419 
420 void
421 mi_cmd_break_watch (char *command, char **argv, int argc)
422 {
423   char *expr = NULL;
424   enum wp_type type = REG_WP;
425   enum opt
426     {
427       READ_OPT, ACCESS_OPT
428     };
429   static const struct mi_opt opts[] =
430   {
431     {"r", READ_OPT, 0},
432     {"a", ACCESS_OPT, 0},
433     { 0, 0, 0 }
434   };
435 
436   /* Parse arguments. */
437   int oind = 0;
438   char *oarg;
439 
440   while (1)
441     {
442       int opt = mi_getopt ("-break-watch", argc, argv,
443 			   opts, &oind, &oarg);
444 
445       if (opt < 0)
446 	break;
447       switch ((enum opt) opt)
448 	{
449 	case READ_OPT:
450 	  type = READ_WP;
451 	  break;
452 	case ACCESS_OPT:
453 	  type = ACCESS_WP;
454 	  break;
455 	}
456     }
457   if (oind >= argc)
458     error (_("-break-watch: Missing <expression>"));
459   if (oind < argc - 1)
460     error (_("-break-watch: Garbage following <expression>"));
461   expr = argv[oind];
462 
463   /* Now we have what we need, let's insert the watchpoint!  */
464   switch (type)
465     {
466     case REG_WP:
467       watch_command_wrapper (expr, FROM_TTY, 0);
468       break;
469     case READ_WP:
470       rwatch_command_wrapper (expr, FROM_TTY, 0);
471       break;
472     case ACCESS_WP:
473       awatch_command_wrapper (expr, FROM_TTY, 0);
474       break;
475     default:
476       error (_("-break-watch: Unknown watchpoint type."));
477     }
478 }
479 
480 /* The mi_read_next_line consults these variable to return successive
481    command lines.  While it would be clearer to use a closure pointer,
482    it is not expected that any future code will use read_command_lines_1,
483    therefore no point of overengineering.  */
484 
485 static char **mi_command_line_array;
486 static int mi_command_line_array_cnt;
487 static int mi_command_line_array_ptr;
488 
489 static char *
490 mi_read_next_line (void)
491 {
492   if (mi_command_line_array_ptr == mi_command_line_array_cnt)
493     return NULL;
494   else
495     return mi_command_line_array[mi_command_line_array_ptr++];
496 }
497 
498 void
499 mi_cmd_break_commands (char *command, char **argv, int argc)
500 {
501   struct command_line *break_command;
502   char *endptr;
503   int bnum;
504   struct breakpoint *b;
505 
506   if (argc < 1)
507     error (_("USAGE: %s <BKPT> [<COMMAND> [<COMMAND>...]]"), command);
508 
509   bnum = strtol (argv[0], &endptr, 0);
510   if (endptr == argv[0])
511     error (_("breakpoint number argument \"%s\" is not a number."),
512 	   argv[0]);
513   else if (*endptr != '\0')
514     error (_("junk at the end of breakpoint number argument \"%s\"."),
515 	   argv[0]);
516 
517   b = get_breakpoint (bnum);
518   if (b == NULL)
519     error (_("breakpoint %d not found."), bnum);
520 
521   mi_command_line_array = argv;
522   mi_command_line_array_ptr = 1;
523   mi_command_line_array_cnt = argc;
524 
525   if (is_tracepoint (b))
526     break_command = read_command_lines_1 (mi_read_next_line, 1,
527 					  check_tracepoint_command, b);
528   else
529     break_command = read_command_lines_1 (mi_read_next_line, 1, 0, 0);
530 
531   breakpoint_set_commands (b, break_command);
532 }
533 
534