3d4062925b32d53f4e2e18bfc8b179407119186f
[external/binutils.git] / gdb / mi / mi-cmd-break.c
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