07902bbecb16a908035e844aa9fb3b56f83b69fd
[deliverable/binutils-gdb.git] / gdb / mi / mi-cmd-break.c
1 /* MI Command Set - breakpoint and watchpoint commands.
2 Copyright (C) 2000-2013 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 <string.h>
27 #include "mi-getopt.h"
28 #include "gdb.h"
29 #include "exceptions.h"
30 #include "observer.h"
31 #include "mi-main.h"
32 #include "mi-cmd-break.h"
33 #include "gdb_obstack.h"
34 #include <ctype.h>
35
36 enum
37 {
38 FROM_TTY = 0
39 };
40
41 /* True if MI breakpoint observers have been registered. */
42
43 static int mi_breakpoint_observers_installed;
44
45 /* Control whether breakpoint_notify may act. */
46
47 static int mi_can_breakpoint_notify;
48
49 /* Output a single breakpoint, when allowed. */
50
51 static void
52 breakpoint_notify (struct breakpoint *b)
53 {
54 if (mi_can_breakpoint_notify)
55 gdb_breakpoint_query (current_uiout, b->number, NULL);
56 }
57
58 enum bp_type
59 {
60 REG_BP,
61 HW_BP,
62 REGEXP_BP
63 };
64
65 /* Arrange for all new breakpoints and catchpoints to be reported to
66 CURRENT_UIOUT until the cleanup returned by this function is run.
67
68 Note that MI output will be probably invalid if more than one
69 breakpoint is created inside one MI command. */
70
71 struct cleanup *
72 setup_breakpoint_reporting (void)
73 {
74 struct cleanup *rev_flag;
75
76 if (! mi_breakpoint_observers_installed)
77 {
78 observer_attach_breakpoint_created (breakpoint_notify);
79 mi_breakpoint_observers_installed = 1;
80 }
81
82 rev_flag = make_cleanup_restore_integer (&mi_can_breakpoint_notify);
83 mi_can_breakpoint_notify = 1;
84
85 return rev_flag;
86 }
87
88
89 /* Convert arguments in ARGV to the string in "format",argv,argv...
90 and return it. */
91
92 static char *
93 mi_argv_to_format (char **argv, int argc)
94 {
95 int i;
96 struct obstack obstack;
97 char *ret;
98
99 obstack_init (&obstack);
100
101 /* Convert ARGV[OIND + 1] to format string and save to FORMAT. */
102 obstack_1grow (&obstack, '\"');
103 for (i = 0; i < strlen (argv[0]); i++)
104 {
105 switch (argv[0][i])
106 {
107 case '\\':
108 obstack_grow (&obstack, "\\\\", 2);
109 break;
110 case '\a':
111 obstack_grow (&obstack, "\\a", 2);
112 break;
113 case '\b':
114 obstack_grow (&obstack, "\\b", 2);
115 break;
116 case '\f':
117 obstack_grow (&obstack, "\\f", 2);
118 break;
119 case '\n':
120 obstack_grow (&obstack, "\\n", 2);
121 break;
122 case '\r':
123 obstack_grow (&obstack, "\\r", 2);
124 break;
125 case '\t':
126 obstack_grow (&obstack, "\\t", 2);
127 break;
128 case '\v':
129 obstack_grow (&obstack, "\\v", 2);
130 break;
131 case '"':
132 obstack_grow (&obstack, "\\\"", 2);
133 break;
134 default:
135 if (isprint (argv[0][i]))
136 obstack_grow (&obstack, argv[0] + i, 1);
137 else
138 {
139 char tmp[5];
140
141 xsnprintf (tmp, sizeof (tmp), "\\%o",
142 (unsigned char) argv[0][i]);
143 obstack_grow (&obstack, tmp, strlen (tmp));
144 }
145 break;
146 }
147 }
148 obstack_1grow (&obstack, '\"');
149
150 /* Apply other argv to FORMAT. */
151 for (i = 1; i < argc; i++)
152 {
153 obstack_1grow (&obstack, ',');
154 obstack_grow (&obstack, argv[i], strlen (argv[i]));
155 }
156 obstack_1grow (&obstack, '\0');
157
158 ret = xstrdup (obstack_finish (&obstack));
159 obstack_free (&obstack, NULL);
160
161 return ret;
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, char *command, char **argv, int argc)
170 {
171 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 struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
181 enum bptype type_wanted;
182 struct breakpoint_ops *ops;
183 char *extra_string = NULL;
184
185 enum opt
186 {
187 HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
188 IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
189 TRACEPOINT_OPT,
190 };
191 static const struct mi_opt opts[] =
192 {
193 {"h", HARDWARE_OPT, 0},
194 {"t", TEMP_OPT, 0},
195 {"c", CONDITION_OPT, 1},
196 {"i", IGNORE_COUNT_OPT, 1},
197 {"p", THREAD_OPT, 1},
198 {"f", PENDING_OPT, 0},
199 {"d", DISABLE_OPT, 0},
200 {"a", TRACEPOINT_OPT, 0},
201 { 0, 0, 0 }
202 };
203
204 /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
205 to denote the end of the option list. */
206 int oind = 0;
207 char *oarg;
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 }
242 }
243
244 if (oind >= argc)
245 error (_("-%s-insert: Missing <location>"),
246 dprintf ? "dprintf" : "break");
247 address = argv[oind];
248 if (dprintf)
249 {
250 int format_num = oind + 1;
251
252 if (hardware || tracepoint)
253 error (_("-dprintf-insert: does not support -h or -a"));
254 if (format_num >= argc)
255 error (_("-dprintf-insert: Missing <format>"));
256
257 extra_string = mi_argv_to_format (argv + format_num, argc - format_num);
258 make_cleanup (xfree, extra_string);
259 }
260 else
261 {
262 if (oind < argc - 1)
263 error (_("-break-insert: Garbage following <location>"));
264 }
265
266 /* Now we have what we need, let's insert the breakpoint! */
267 setup_breakpoint_reporting ();
268
269 if (tracepoint)
270 {
271 /* Note that to request a fast tracepoint, the client uses the
272 "hardware" flag, although there's nothing of hardware related to
273 fast tracepoints -- one can implement slow tracepoints with
274 hardware breakpoints, but fast tracepoints are always software.
275 "fast" is a misnomer, actually, "jump" would be more appropriate.
276 A simulator or an emulator could conceivably implement fast
277 regular non-jump based tracepoints. */
278 type_wanted = hardware ? bp_fast_tracepoint : bp_tracepoint;
279 ops = &tracepoint_breakpoint_ops;
280 }
281 else if (dprintf)
282 {
283 type_wanted = bp_dprintf;
284 ops = &dprintf_breakpoint_ops;
285 }
286 else
287 {
288 type_wanted = hardware ? bp_hardware_breakpoint : bp_breakpoint;
289 ops = &bkpt_breakpoint_ops;
290 }
291
292 create_breakpoint (get_current_arch (), address, condition, thread,
293 extra_string,
294 0 /* condition and thread are valid. */,
295 temp_p, type_wanted,
296 ignore_count,
297 pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
298 ops, 0, enabled, 0, 0);
299 do_cleanups (back_to);
300 }
301
302 /* Implements the -break-insert command.
303 See the MI manual for the list of possible options. */
304
305 void
306 mi_cmd_break_insert (char *command, char **argv, int argc)
307 {
308 mi_cmd_break_insert_1 (0, command, argv, argc);
309 }
310
311 /* Implements the -dprintf-insert command.
312 See the MI manual for the list of possible options. */
313
314 void
315 mi_cmd_dprintf_insert (char *command, char **argv, int argc)
316 {
317 mi_cmd_break_insert_1 (1, command, argv, argc);
318 }
319
320 enum wp_type
321 {
322 REG_WP,
323 READ_WP,
324 ACCESS_WP
325 };
326
327 void
328 mi_cmd_break_passcount (char *command, char **argv, int argc)
329 {
330 int n;
331 int p;
332 struct tracepoint *t;
333
334 if (argc != 2)
335 error (_("Usage: tracepoint-number passcount"));
336
337 n = atoi (argv[0]);
338 p = atoi (argv[1]);
339 t = get_tracepoint (n);
340
341 if (t)
342 {
343 t->pass_count = p;
344 observer_notify_breakpoint_modified (&t->base);
345 }
346 else
347 {
348 error (_("Could not find tracepoint %d"), n);
349 }
350 }
351
352 /* Insert a watchpoint. The type of watchpoint is specified by the
353 first argument:
354 -break-watch <expr> --> insert a regular wp.
355 -break-watch -r <expr> --> insert a read watchpoint.
356 -break-watch -a <expr> --> insert an access wp. */
357
358 void
359 mi_cmd_break_watch (char *command, char **argv, int argc)
360 {
361 char *expr = NULL;
362 enum wp_type type = REG_WP;
363 enum opt
364 {
365 READ_OPT, ACCESS_OPT
366 };
367 static const struct mi_opt opts[] =
368 {
369 {"r", READ_OPT, 0},
370 {"a", ACCESS_OPT, 0},
371 { 0, 0, 0 }
372 };
373
374 /* Parse arguments. */
375 int oind = 0;
376 char *oarg;
377
378 while (1)
379 {
380 int opt = mi_getopt ("-break-watch", argc, argv,
381 opts, &oind, &oarg);
382
383 if (opt < 0)
384 break;
385 switch ((enum opt) opt)
386 {
387 case READ_OPT:
388 type = READ_WP;
389 break;
390 case ACCESS_OPT:
391 type = ACCESS_WP;
392 break;
393 }
394 }
395 if (oind >= argc)
396 error (_("-break-watch: Missing <expression>"));
397 if (oind < argc - 1)
398 error (_("-break-watch: Garbage following <expression>"));
399 expr = argv[oind];
400
401 /* Now we have what we need, let's insert the watchpoint! */
402 switch (type)
403 {
404 case REG_WP:
405 watch_command_wrapper (expr, FROM_TTY, 0);
406 break;
407 case READ_WP:
408 rwatch_command_wrapper (expr, FROM_TTY, 0);
409 break;
410 case ACCESS_WP:
411 awatch_command_wrapper (expr, FROM_TTY, 0);
412 break;
413 default:
414 error (_("-break-watch: Unknown watchpoint type."));
415 }
416 }
417
418 /* The mi_read_next_line consults these variable to return successive
419 command lines. While it would be clearer to use a closure pointer,
420 it is not expected that any future code will use read_command_lines_1,
421 therefore no point of overengineering. */
422
423 static char **mi_command_line_array;
424 static int mi_command_line_array_cnt;
425 static int mi_command_line_array_ptr;
426
427 static char *
428 mi_read_next_line (void)
429 {
430 if (mi_command_line_array_ptr == mi_command_line_array_cnt)
431 return NULL;
432 else
433 return mi_command_line_array[mi_command_line_array_ptr++];
434 }
435
436 void
437 mi_cmd_break_commands (char *command, char **argv, int argc)
438 {
439 struct command_line *break_command;
440 char *endptr;
441 int bnum;
442 struct breakpoint *b;
443
444 if (argc < 1)
445 error (_("USAGE: %s <BKPT> [<COMMAND> [<COMMAND>...]]"), command);
446
447 bnum = strtol (argv[0], &endptr, 0);
448 if (endptr == argv[0])
449 error (_("breakpoint number argument \"%s\" is not a number."),
450 argv[0]);
451 else if (*endptr != '\0')
452 error (_("junk at the end of breakpoint number argument \"%s\"."),
453 argv[0]);
454
455 b = get_breakpoint (bnum);
456 if (b == NULL)
457 error (_("breakpoint %d not found."), bnum);
458
459 mi_command_line_array = argv;
460 mi_command_line_array_ptr = 1;
461 mi_command_line_array_cnt = argc;
462
463 if (is_tracepoint (b))
464 break_command = read_command_lines_1 (mi_read_next_line, 1,
465 check_tracepoint_command, b);
466 else
467 break_command = read_command_lines_1 (mi_read_next_line, 1, 0, 0);
468
469 breakpoint_set_commands (b, break_command);
470 }
471
This page took 0.038713 seconds and 4 git commands to generate.