]> Git Repo - binutils.git/blame - gdb/mi/mi-cmd-break.c
Automatic date update in version.in
[binutils.git] / gdb / mi / mi-cmd-break.c
CommitLineData
fb40c209 1/* MI Command Set - breakpoint and watchpoint commands.
4a94e368 2 Copyright (C) 2000-2022 Free Software Foundation, Inc.
ab91fdd5 3 Contributed by Cygnus Solutions (a Red Hat company).
fb40c209
AC
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
fb40c209
AC
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
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
fb40c209
AC
19
20#include "defs.h"
a6d9a66e 21#include "arch-utils.h"
fb40c209
AC
22#include "mi-cmds.h"
23#include "ui-out.h"
24#include "mi-out.h"
25#include "breakpoint.h"
fb40c209 26#include "mi-getopt.h"
76727919 27#include "observable.h"
8d3788bd 28#include "mi-main.h"
91985142 29#include "mi-cmd-break.h"
f00aae0f
KS
30#include "language.h"
31#include "location.h"
32#include "linespec.h"
bf31fd38 33#include "gdbsupport/gdb_obstack.h"
c5867ab6 34#include <ctype.h>
60b3cef2 35#include "tracepoint.h"
fb40c209 36
fb40c209
AC
37enum
38 {
39 FROM_TTY = 0
40 };
41
383f836e
TT
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
2b03b41d 50/* Output a single breakpoint, when allowed. */
fb40c209
AC
51
52static void
8d3788bd 53breakpoint_notify (struct breakpoint *b)
fb40c209 54{
383f836e 55 if (mi_can_breakpoint_notify)
65630365 56 {
a70b8144 57 try
65630365
PA
58 {
59 print_breakpoint (b);
60 }
230d2906 61 catch (const gdb_exception &ex)
65630365
PA
62 {
63 exception_print (gdb_stderr, ex);
64 }
65630365 65 }
fb40c209
AC
66}
67
fb40c209
AC
68enum bp_type
69 {
70 REG_BP,
71 HW_BP,
72 REGEXP_BP
73 };
74
91985142 75/* Arrange for all new breakpoints and catchpoints to be reported to
00f675ff
TT
76 CURRENT_UIOUT until the destructor of the returned scoped_restore
77 is run.
91985142
MG
78
79 Note that MI output will be probably invalid if more than one
80 breakpoint is created inside one MI command. */
81
00f675ff 82scoped_restore_tmpl<int>
91985142
MG
83setup_breakpoint_reporting (void)
84{
91985142
MG
85 if (! mi_breakpoint_observers_installed)
86 {
c90e7d63
SM
87 gdb::observers::breakpoint_created.attach (breakpoint_notify,
88 "mi-cmd-break");
91985142
MG
89 mi_breakpoint_observers_installed = 1;
90 }
91
00f675ff 92 return make_scoped_restore (&mi_can_breakpoint_notify, 1);
91985142
MG
93}
94
95
c5867ab6
HZ
96/* Convert arguments in ARGV to the string in "format",argv,argv...
97 and return it. */
fb40c209 98
784c453a 99static std::string
c5867ab6
HZ
100mi_argv_to_format (char **argv, int argc)
101{
102 int i;
784c453a 103 std::string result;
c5867ab6
HZ
104
105 /* Convert ARGV[OIND + 1] to format string and save to FORMAT. */
784c453a 106 result += '\"';
c5867ab6
HZ
107 for (i = 0; i < strlen (argv[0]); i++)
108 {
109 switch (argv[0][i])
110 {
111 case '\\':
784c453a 112 result += "\\\\";
c5867ab6
HZ
113 break;
114 case '\a':
784c453a 115 result += "\\a";
c5867ab6
HZ
116 break;
117 case '\b':
784c453a 118 result += "\\b";
c5867ab6
HZ
119 break;
120 case '\f':
784c453a 121 result += "\\f";
c5867ab6
HZ
122 break;
123 case '\n':
784c453a 124 result += "\\n";
c5867ab6
HZ
125 break;
126 case '\r':
784c453a 127 result += "\\r";
c5867ab6
HZ
128 break;
129 case '\t':
784c453a 130 result += "\\t";
c5867ab6
HZ
131 break;
132 case '\v':
784c453a 133 result += "\\v";
c5867ab6 134 break;
fa876972 135 case '"':
784c453a 136 result += "\\\"";
fa876972 137 break;
c5867ab6
HZ
138 default:
139 if (isprint (argv[0][i]))
784c453a 140 result += argv[0][i];
c5867ab6
HZ
141 else
142 {
143 char tmp[5];
144
ce70887a
JB
145 xsnprintf (tmp, sizeof (tmp), "\\%o",
146 (unsigned char) argv[0][i]);
784c453a 147 result += tmp;
c5867ab6
HZ
148 }
149 break;
150 }
151 }
784c453a 152 result += '\"';
c5867ab6
HZ
153
154 /* Apply other argv to FORMAT. */
155 for (i = 1; i < argc; i++)
156 {
784c453a
TT
157 result += ',';
158 result += argv[i];
c5867ab6 159 }
c5867ab6 160
784c453a 161 return result;
c5867ab6
HZ
162}
163
164/* Insert breakpoint.
165 If dprintf is true, it will insert dprintf.
166 If not, it will insert other type breakpoint. */
167
168static void
9f33b8b7 169mi_cmd_break_insert_1 (int dprintf, const char *command, char **argv, int argc)
fb40c209 170{
f2fc3015 171 const char *address = NULL;
8cdf0e15 172 int hardware = 0;
fb40c209
AC
173 int temp_p = 0;
174 int thread = -1;
175 int ignore_count = 0;
176 char *condition = NULL;
afe8ab22 177 int pending = 0;
41447f92 178 int enabled = 1;
6534d786 179 int tracepoint = 0;
6791b117 180 symbol_name_match_type match_type = symbol_name_match_type::WILD;
0fb4aa4b 181 enum bptype type_wanted;
264f9890 182 location_spec_up locspec;
779dcceb 183 const struct breakpoint_ops *ops;
eb8c4e2e 184 int is_explicit = 0;
40d97ee2
PA
185 std::unique_ptr<explicit_location_spec> explicit_loc
186 (new explicit_location_spec ());
784c453a 187 std::string extra_string;
10e578d7 188 bool force_condition = false;
41447f92 189
fb40c209
AC
190 enum opt
191 {
8cdf0e15 192 HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
6534d786
VP
193 IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
194 TRACEPOINT_OPT,
10e578d7 195 FORCE_CONDITION_OPT,
6791b117 196 QUALIFIED_OPT,
eb8c4e2e
KS
197 EXPLICIT_SOURCE_OPT, EXPLICIT_FUNC_OPT,
198 EXPLICIT_LABEL_OPT, EXPLICIT_LINE_OPT
fb40c209 199 };
91174723 200 static const struct mi_opt opts[] =
fb40c209
AC
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},
afe8ab22 207 {"f", PENDING_OPT, 0},
41447f92 208 {"d", DISABLE_OPT, 0},
6534d786 209 {"a", TRACEPOINT_OPT, 0},
10e578d7 210 {"-force-condition", FORCE_CONDITION_OPT, 0},
6791b117 211 {"-qualified", QUALIFIED_OPT, 0},
eb8c4e2e
KS
212 {"-source" , EXPLICIT_SOURCE_OPT, 1},
213 {"-function", EXPLICIT_FUNC_OPT, 1},
214 {"-label", EXPLICIT_LABEL_OPT, 1},
215 {"-line", EXPLICIT_LINE_OPT, 1},
d5d6fca5 216 { 0, 0, 0 }
fb40c209
AC
217 };
218
219 /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
220 to denote the end of the option list. */
f8c000a2
AS
221 int oind = 0;
222 char *oarg;
102040f0 223
fb40c209
AC
224 while (1)
225 {
1b05df00 226 int opt = mi_getopt ("-break-insert", argc, argv,
f8c000a2 227 opts, &oind, &oarg);
fb40c209
AC
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:
8cdf0e15 236 hardware = 1;
fb40c209 237 break;
fb40c209 238 case CONDITION_OPT:
f8c000a2 239 condition = oarg;
fb40c209
AC
240 break;
241 case IGNORE_COUNT_OPT:
f8c000a2 242 ignore_count = atol (oarg);
fb40c209
AC
243 break;
244 case THREAD_OPT:
f8c000a2 245 thread = atol (oarg);
fb40c209 246 break;
afe8ab22
VP
247 case PENDING_OPT:
248 pending = 1;
249 break;
41447f92
VP
250 case DISABLE_OPT:
251 enabled = 0;
6534d786
VP
252 break;
253 case TRACEPOINT_OPT:
254 tracepoint = 1;
255 break;
6791b117
PA
256 case QUALIFIED_OPT:
257 match_type = symbol_name_match_type::FULL;
258 break;
eb8c4e2e
KS
259 case EXPLICIT_SOURCE_OPT:
260 is_explicit = 1;
40d97ee2 261 explicit_loc->source_filename = xstrdup (oarg);
eb8c4e2e
KS
262 break;
263 case EXPLICIT_FUNC_OPT:
264 is_explicit = 1;
40d97ee2 265 explicit_loc->function_name = xstrdup (oarg);
eb8c4e2e
KS
266 break;
267 case EXPLICIT_LABEL_OPT:
268 is_explicit = 1;
40d97ee2 269 explicit_loc->label_name = xstrdup (oarg);
eb8c4e2e
KS
270 break;
271 case EXPLICIT_LINE_OPT:
272 is_explicit = 1;
40d97ee2 273 explicit_loc->line_offset = linespec_parse_line_offset (oarg);
eb8c4e2e 274 break;
10e578d7
TBA
275 case FORCE_CONDITION_OPT:
276 force_condition = true;
277 break;
fb40c209
AC
278 }
279 }
280
eb8c4e2e 281 if (oind >= argc && !is_explicit)
c5867ab6
HZ
282 error (_("-%s-insert: Missing <location>"),
283 dprintf ? "dprintf" : "break");
c5867ab6
HZ
284 if (dprintf)
285 {
eb8c4e2e 286 int format_num = is_explicit ? oind : oind + 1;
c5867ab6
HZ
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);
eb8c4e2e 294 address = argv[oind];
c5867ab6
HZ
295 }
296 else
297 {
eb8c4e2e
KS
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 }
c5867ab6 309 }
fb40c209 310
2b03b41d 311 /* Now we have what we need, let's insert the breakpoint! */
00f675ff 312 scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
c5867ab6
HZ
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;
264f9890 324 ops = breakpoint_ops_for_location_spec (nullptr, true);
c5867ab6
HZ
325 }
326 else if (dprintf)
327 {
328 type_wanted = bp_dprintf;
74421c0b 329 ops = &code_breakpoint_ops;
c5867ab6
HZ
330 }
331 else
332 {
333 type_wanted = hardware ? bp_hardware_breakpoint : bp_breakpoint;
74421c0b 334 ops = &code_breakpoint_ops;
c5867ab6 335 }
0fb4aa4b 336
eb8c4e2e
KS
337 if (is_explicit)
338 {
339 /* Error check -- we must have one of the other
340 parameters specified. */
40d97ee2
PA
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)
eb8c4e2e
KS
345 error (_("-%s-insert: --source option requires --function, --label,"
346 " or --line"), dprintf ? "dprintf" : "break");
347
40d97ee2 348 explicit_loc->func_name_match_type = match_type;
6791b117 349
40d97ee2 350 locspec = std::move (explicit_loc);
eb8c4e2e
KS
351 }
352 else
353 {
264f9890
PA
354 locspec = string_to_location_spec_basic (&address, current_language,
355 match_type);
eb8c4e2e 356 if (*address)
ffc2605c 357 error (_("Garbage '%s' at end of location"), address);
eb8c4e2e 358 }
f00aae0f 359
264f9890 360 create_breakpoint (get_current_arch (), locspec.get (), condition, thread,
784c453a 361 extra_string.c_str (),
10e578d7 362 force_condition,
8cdf0e15 363 0 /* condition and thread are valid. */,
0fb4aa4b 364 temp_p, type_wanted,
8cdf0e15
VP
365 ignore_count,
366 pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
19ca11c5 367 ops, 0, enabled, 0, 0);
c5867ab6
HZ
368}
369
370/* Implements the -break-insert command.
371 See the MI manual for the list of possible options. */
8cdf0e15 372
c5867ab6 373void
9f33b8b7 374mi_cmd_break_insert (const char *command, char **argv, int argc)
c5867ab6
HZ
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
382void
9f33b8b7 383mi_cmd_dprintf_insert (const char *command, char **argv, int argc)
c5867ab6
HZ
384{
385 mi_cmd_break_insert_1 (1, command, argv, argc);
fb40c209
AC
386}
387
79aabb73
TBA
388/* Implements the -break-condition command.
389 See the MI manual for the list of options. */
390
391void
392mi_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
b6c42051
TBA
425 /* There must be at least one more arg: a bpnum. */
426 if (oind >= argc)
427 error (_("-break-condition: Missing the <number> argument"));
79aabb73
TBA
428
429 int bpnum = atoi (argv[oind]);
430
431 /* The rest form the condition expr. */
b6c42051
TBA
432 std::string expr = "";
433 for (int i = oind + 1; i < argc; ++i)
79aabb73 434 {
79aabb73 435 expr += argv[i];
b6c42051
TBA
436 if (i + 1 < argc)
437 expr += " ";
79aabb73
TBA
438 }
439
440 set_breakpoint_condition (bpnum, expr.c_str (), 0 /* from_tty */,
441 force_condition);
442}
443
fb40c209
AC
444enum wp_type
445{
446 REG_WP,
447 READ_WP,
448 ACCESS_WP
449};
450
9b4c786c 451void
9f33b8b7 452mi_cmd_break_passcount (const char *command, char **argv, int argc)
9b4c786c
VP
453{
454 int n;
455 int p;
d9b3f62e 456 struct tracepoint *t;
9b4c786c
VP
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;
76727919 468 gdb::observers::breakpoint_modified.notify (t);
9b4c786c
VP
469 }
470 else
471 {
401a70b8 472 error (_("Could not find tracepoint %d"), n);
9b4c786c
VP
473 }
474}
475
fb40c209
AC
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.
2b03b41d 480 -break-watch -a <expr> --> insert an access wp. */
fb40c209 481
ce8f13f8 482void
9f33b8b7 483mi_cmd_break_watch (const char *command, char **argv, int argc)
fb40c209
AC
484{
485 char *expr = NULL;
486 enum wp_type type = REG_WP;
487 enum opt
488 {
489 READ_OPT, ACCESS_OPT
490 };
91174723 491 static const struct mi_opt opts[] =
fb40c209
AC
492 {
493 {"r", READ_OPT, 0},
494 {"a", ACCESS_OPT, 0},
d5d6fca5 495 { 0, 0, 0 }
fb40c209
AC
496 };
497
498 /* Parse arguments. */
f8c000a2
AS
499 int oind = 0;
500 char *oarg;
102040f0 501
fb40c209
AC
502 while (1)
503 {
1b05df00 504 int opt = mi_getopt ("-break-watch", argc, argv,
f8c000a2 505 opts, &oind, &oarg);
102040f0 506
fb40c209
AC
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 }
f8c000a2 519 if (oind >= argc)
1b05df00 520 error (_("-break-watch: Missing <expression>"));
f8c000a2 521 if (oind < argc - 1)
1b05df00 522 error (_("-break-watch: Garbage following <expression>"));
f8c000a2 523 expr = argv[oind];
fb40c209 524
2b03b41d 525 /* Now we have what we need, let's insert the watchpoint! */
fb40c209
AC
526 switch (type)
527 {
528 case REG_WP:
2e362716 529 watch_command_wrapper (expr, FROM_TTY, false);
fb40c209
AC
530 break;
531 case READ_WP:
2e362716 532 rwatch_command_wrapper (expr, FROM_TTY, false);
fb40c209
AC
533 break;
534 case ACCESS_WP:
2e362716 535 awatch_command_wrapper (expr, FROM_TTY, false);
fb40c209
AC
536 break;
537 default:
1b05df00 538 error (_("-break-watch: Unknown watchpoint type."));
fb40c209 539 }
fb40c209 540}
48cb2d85 541
48cb2d85 542void
9f33b8b7 543mi_cmd_break_commands (const char *command, char **argv, int argc)
48cb2d85 544{
12973681 545 counted_command_line break_command;
48cb2d85
VP
546 char *endptr;
547 int bnum;
548 struct breakpoint *b;
549
550 if (argc < 1)
9b20d036 551 error (_("USAGE: %s <BKPT> [<COMMAND> [<COMMAND>...]]"), command);
48cb2d85
VP
552
553 bnum = strtol (argv[0], &endptr, 0);
554 if (endptr == argv[0])
9b20d036 555 error (_("breakpoint number argument \"%s\" is not a number."),
48cb2d85
VP
556 argv[0]);
557 else if (*endptr != '\0')
9b20d036 558 error (_("junk at the end of breakpoint number argument \"%s\"."),
48cb2d85
VP
559 argv[0]);
560
561 b = get_breakpoint (bnum);
562 if (b == NULL)
9b20d036 563 error (_("breakpoint %d not found."), bnum);
48cb2d85 564
60b3cef2
TT
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 };
48cb2d85 574
d77f58be 575 if (is_tracepoint (b))
60b3cef2
TT
576 break_command = read_command_lines_1 (reader, 1,
577 [=] (const char *line)
578 {
579 validate_actionline (line, b);
580 });
a7bdde9e 581 else
60b3cef2 582 break_command = read_command_lines_1 (reader, 1, 0);
a7bdde9e 583
93921405 584 breakpoint_set_commands (b, std::move (break_command));
48cb2d85
VP
585}
586
This page took 4.419115 seconds and 5 git commands to generate.