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