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