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