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