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