2013-05-21 Hui Zhu <hui@codesourcery.com>
[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 "gdb_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 default:
132 if (isprint (argv[0][i]))
133 obstack_grow (&obstack, argv[0] + i, 1);
134 else
135 {
136 char tmp[5];
137
138 sprintf (tmp, "\\%o", (unsigned char) argv[0][i]);
139 obstack_grow (&obstack, tmp, strlen (tmp));
140 }
141 break;
142 }
143 }
144 obstack_1grow (&obstack, '\"');
145
146 /* Apply other argv to FORMAT. */
147 for (i = 1; i < argc; i++)
148 {
149 obstack_1grow (&obstack, ',');
150 obstack_grow (&obstack, argv[i], strlen (argv[i]));
151 }
152 obstack_1grow (&obstack, '\0');
153
154 ret = xstrdup (obstack_finish (&obstack));
155 obstack_free (&obstack, NULL);
156
157 return ret;
158 }
159
160 /* Insert breakpoint.
161 If dprintf is true, it will insert dprintf.
162 If not, it will insert other type breakpoint. */
163
164 static void
165 mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
166 {
167 char *address = NULL;
168 int hardware = 0;
169 int temp_p = 0;
170 int thread = -1;
171 int ignore_count = 0;
172 char *condition = NULL;
173 int pending = 0;
174 int enabled = 1;
175 int tracepoint = 0;
176 struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
177 enum bptype type_wanted;
178 struct breakpoint_ops *ops;
179 char *extra_string = NULL;
180
181 enum opt
182 {
183 HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
184 IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
185 TRACEPOINT_OPT,
186 };
187 static const struct mi_opt opts[] =
188 {
189 {"h", HARDWARE_OPT, 0},
190 {"t", TEMP_OPT, 0},
191 {"c", CONDITION_OPT, 1},
192 {"i", IGNORE_COUNT_OPT, 1},
193 {"p", THREAD_OPT, 1},
194 {"f", PENDING_OPT, 0},
195 {"d", DISABLE_OPT, 0},
196 {"a", TRACEPOINT_OPT, 0},
197 { 0, 0, 0 }
198 };
199
200 /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
201 to denote the end of the option list. */
202 int oind = 0;
203 char *oarg;
204
205 while (1)
206 {
207 int opt = mi_getopt ("-break-insert", argc, argv,
208 opts, &oind, &oarg);
209 if (opt < 0)
210 break;
211 switch ((enum opt) opt)
212 {
213 case TEMP_OPT:
214 temp_p = 1;
215 break;
216 case HARDWARE_OPT:
217 hardware = 1;
218 break;
219 case CONDITION_OPT:
220 condition = oarg;
221 break;
222 case IGNORE_COUNT_OPT:
223 ignore_count = atol (oarg);
224 break;
225 case THREAD_OPT:
226 thread = atol (oarg);
227 break;
228 case PENDING_OPT:
229 pending = 1;
230 break;
231 case DISABLE_OPT:
232 enabled = 0;
233 break;
234 case TRACEPOINT_OPT:
235 tracepoint = 1;
236 break;
237 }
238 }
239
240 if (oind >= argc)
241 error (_("-%s-insert: Missing <location>"),
242 dprintf ? "dprintf" : "break");
243 address = argv[oind];
244 if (dprintf)
245 {
246 int format_num = oind + 1;
247
248 if (hardware || tracepoint)
249 error (_("-dprintf-insert: does not support -h or -a"));
250 if (format_num >= argc)
251 error (_("-dprintf-insert: Missing <format>"));
252
253 extra_string = mi_argv_to_format (argv + format_num, argc - format_num);
254 make_cleanup (xfree, extra_string);
255 }
256 else
257 {
258 if (oind < argc - 1)
259 error (_("-break-insert: Garbage following <location>"));
260 }
261
262 /* Now we have what we need, let's insert the breakpoint! */
263 setup_breakpoint_reporting ();
264
265 if (tracepoint)
266 {
267 /* Note that to request a fast tracepoint, the client uses the
268 "hardware" flag, although there's nothing of hardware related to
269 fast tracepoints -- one can implement slow tracepoints with
270 hardware breakpoints, but fast tracepoints are always software.
271 "fast" is a misnomer, actually, "jump" would be more appropriate.
272 A simulator or an emulator could conceivably implement fast
273 regular non-jump based tracepoints. */
274 type_wanted = hardware ? bp_fast_tracepoint : bp_tracepoint;
275 ops = &tracepoint_breakpoint_ops;
276 }
277 else if (dprintf)
278 {
279 type_wanted = bp_dprintf;
280 ops = &dprintf_breakpoint_ops;
281 }
282 else
283 {
284 type_wanted = hardware ? bp_hardware_breakpoint : bp_breakpoint;
285 ops = &bkpt_breakpoint_ops;
286 }
287
288 create_breakpoint (get_current_arch (), address, condition, thread,
289 extra_string,
290 0 /* condition and thread are valid. */,
291 temp_p, type_wanted,
292 ignore_count,
293 pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
294 ops, 0, enabled, 0, 0);
295 do_cleanups (back_to);
296 }
297
298 /* Implements the -break-insert command.
299 See the MI manual for the list of possible options. */
300
301 void
302 mi_cmd_break_insert (char *command, char **argv, int argc)
303 {
304 mi_cmd_break_insert_1 (0, command, argv, argc);
305 }
306
307 /* Implements the -dprintf-insert command.
308 See the MI manual for the list of possible options. */
309
310 void
311 mi_cmd_dprintf_insert (char *command, char **argv, int argc)
312 {
313 mi_cmd_break_insert_1 (1, command, argv, argc);
314 }
315
316 enum wp_type
317 {
318 REG_WP,
319 READ_WP,
320 ACCESS_WP
321 };
322
323 void
324 mi_cmd_break_passcount (char *command, char **argv, int argc)
325 {
326 int n;
327 int p;
328 struct tracepoint *t;
329
330 if (argc != 2)
331 error (_("Usage: tracepoint-number passcount"));
332
333 n = atoi (argv[0]);
334 p = atoi (argv[1]);
335 t = get_tracepoint (n);
336
337 if (t)
338 {
339 t->pass_count = p;
340 observer_notify_breakpoint_modified (&t->base);
341 }
342 else
343 {
344 error (_("Could not find tracepoint %d"), n);
345 }
346 }
347
348 /* Insert a watchpoint. The type of watchpoint is specified by the
349 first argument:
350 -break-watch <expr> --> insert a regular wp.
351 -break-watch -r <expr> --> insert a read watchpoint.
352 -break-watch -a <expr> --> insert an access wp. */
353
354 void
355 mi_cmd_break_watch (char *command, char **argv, int argc)
356 {
357 char *expr = NULL;
358 enum wp_type type = REG_WP;
359 enum opt
360 {
361 READ_OPT, ACCESS_OPT
362 };
363 static const struct mi_opt opts[] =
364 {
365 {"r", READ_OPT, 0},
366 {"a", ACCESS_OPT, 0},
367 { 0, 0, 0 }
368 };
369
370 /* Parse arguments. */
371 int oind = 0;
372 char *oarg;
373
374 while (1)
375 {
376 int opt = mi_getopt ("-break-watch", argc, argv,
377 opts, &oind, &oarg);
378
379 if (opt < 0)
380 break;
381 switch ((enum opt) opt)
382 {
383 case READ_OPT:
384 type = READ_WP;
385 break;
386 case ACCESS_OPT:
387 type = ACCESS_WP;
388 break;
389 }
390 }
391 if (oind >= argc)
392 error (_("-break-watch: Missing <expression>"));
393 if (oind < argc - 1)
394 error (_("-break-watch: Garbage following <expression>"));
395 expr = argv[oind];
396
397 /* Now we have what we need, let's insert the watchpoint! */
398 switch (type)
399 {
400 case REG_WP:
401 watch_command_wrapper (expr, FROM_TTY, 0);
402 break;
403 case READ_WP:
404 rwatch_command_wrapper (expr, FROM_TTY, 0);
405 break;
406 case ACCESS_WP:
407 awatch_command_wrapper (expr, FROM_TTY, 0);
408 break;
409 default:
410 error (_("-break-watch: Unknown watchpoint type."));
411 }
412 }
413
414 /* The mi_read_next_line consults these variable to return successive
415 command lines. While it would be clearer to use a closure pointer,
416 it is not expected that any future code will use read_command_lines_1,
417 therefore no point of overengineering. */
418
419 static char **mi_command_line_array;
420 static int mi_command_line_array_cnt;
421 static int mi_command_line_array_ptr;
422
423 static char *
424 mi_read_next_line (void)
425 {
426 if (mi_command_line_array_ptr == mi_command_line_array_cnt)
427 return NULL;
428 else
429 return mi_command_line_array[mi_command_line_array_ptr++];
430 }
431
432 void
433 mi_cmd_break_commands (char *command, char **argv, int argc)
434 {
435 struct command_line *break_command;
436 char *endptr;
437 int bnum;
438 struct breakpoint *b;
439
440 if (argc < 1)
441 error (_("USAGE: %s <BKPT> [<COMMAND> [<COMMAND>...]]"), command);
442
443 bnum = strtol (argv[0], &endptr, 0);
444 if (endptr == argv[0])
445 error (_("breakpoint number argument \"%s\" is not a number."),
446 argv[0]);
447 else if (*endptr != '\0')
448 error (_("junk at the end of breakpoint number argument \"%s\"."),
449 argv[0]);
450
451 b = get_breakpoint (bnum);
452 if (b == NULL)
453 error (_("breakpoint %d not found."), bnum);
454
455 mi_command_line_array = argv;
456 mi_command_line_array_ptr = 1;
457 mi_command_line_array_cnt = argc;
458
459 if (is_tracepoint (b))
460 break_command = read_command_lines_1 (mi_read_next_line, 1,
461 check_tracepoint_command, b);
462 else
463 break_command = read_command_lines_1 (mi_read_next_line, 1, 0, 0);
464
465 breakpoint_set_commands (b, break_command);
466 }
467
This page took 0.04057 seconds and 5 git commands to generate.