xref: /dragonfly/contrib/gdb-7/gdb/mi/mi-cmd-break.c (revision 10cbe914)
1 /* MI Command Set - breakpoint and watchpoint commands.
2    Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009
3    Free Software Foundation, Inc.
4    Contributed by Cygnus Solutions (a Red Hat company).
5 
6    This file is part of GDB.
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20 
21 #include "defs.h"
22 #include "arch-utils.h"
23 #include "mi-cmds.h"
24 #include "ui-out.h"
25 #include "mi-out.h"
26 #include "breakpoint.h"
27 #include "gdb_string.h"
28 #include "mi-getopt.h"
29 #include "gdb.h"
30 #include "exceptions.h"
31 #include "observer.h"
32 
33 enum
34   {
35     FROM_TTY = 0
36   };
37 
38 /* True if MI breakpoint observers have been registered.  */
39 
40 static int mi_breakpoint_observers_installed;
41 
42 /* Control whether breakpoint_notify may act.  */
43 
44 static int mi_can_breakpoint_notify;
45 
46 /* Output a single breakpoint, when allowed. */
47 
48 static void
49 breakpoint_notify (int b)
50 {
51   if (mi_can_breakpoint_notify)
52     gdb_breakpoint_query (uiout, b, NULL);
53 }
54 
55 enum bp_type
56   {
57     REG_BP,
58     HW_BP,
59     REGEXP_BP
60   };
61 
62 /* Implements the -break-insert command.
63    See the MI manual for the list of possible options.  */
64 
65 void
66 mi_cmd_break_insert (char *command, char **argv, int argc)
67 {
68   char *address = NULL;
69   enum bp_type type = REG_BP;
70   int temp_p = 0;
71   int thread = -1;
72   int ignore_count = 0;
73   char *condition = NULL;
74   int pending = 0;
75   int enabled = 1;
76 
77   struct gdb_exception e;
78   struct gdb_events *old_hooks;
79   enum opt
80     {
81       HARDWARE_OPT, TEMP_OPT /*, REGEXP_OPT */ , CONDITION_OPT,
82       IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT
83     };
84   static struct mi_opt opts[] =
85   {
86     {"h", HARDWARE_OPT, 0},
87     {"t", TEMP_OPT, 0},
88     {"c", CONDITION_OPT, 1},
89     {"i", IGNORE_COUNT_OPT, 1},
90     {"p", THREAD_OPT, 1},
91     {"f", PENDING_OPT, 0},
92     {"d", DISABLE_OPT, 0},
93     { 0, 0, 0 }
94   };
95 
96   /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
97      to denote the end of the option list. */
98   int optind = 0;
99   char *optarg;
100   while (1)
101     {
102       int opt = mi_getopt ("mi_cmd_break_insert", argc, argv, opts, &optind, &optarg);
103       if (opt < 0)
104 	break;
105       switch ((enum opt) opt)
106 	{
107 	case TEMP_OPT:
108 	  temp_p = 1;
109 	  break;
110 	case HARDWARE_OPT:
111 	  type = HW_BP;
112 	  break;
113 #if 0
114 	case REGEXP_OPT:
115 	  type = REGEXP_BP;
116 	  break;
117 #endif
118 	case CONDITION_OPT:
119 	  condition = optarg;
120 	  break;
121 	case IGNORE_COUNT_OPT:
122 	  ignore_count = atol (optarg);
123 	  break;
124 	case THREAD_OPT:
125 	  thread = atol (optarg);
126 	  break;
127 	case PENDING_OPT:
128 	  pending = 1;
129 	  break;
130 	case DISABLE_OPT:
131 	  enabled = 0;
132 	}
133     }
134 
135   if (optind >= argc)
136     error (_("mi_cmd_break_insert: Missing <location>"));
137   if (optind < argc - 1)
138     error (_("mi_cmd_break_insert: Garbage following <location>"));
139   address = argv[optind];
140 
141   /* Now we have what we need, let's insert the breakpoint! */
142   if (! mi_breakpoint_observers_installed)
143     {
144       observer_attach_breakpoint_created (breakpoint_notify);
145       observer_attach_breakpoint_modified (breakpoint_notify);
146       observer_attach_breakpoint_deleted (breakpoint_notify);
147       mi_breakpoint_observers_installed = 1;
148     }
149 
150   mi_can_breakpoint_notify = 1;
151   /* Make sure we restore hooks even if exception is thrown.  */
152   TRY_CATCH (e, RETURN_MASK_ALL)
153     {
154       switch (type)
155 	{
156 	case REG_BP:
157 	  set_breakpoint (get_current_arch (), address, condition,
158 			  0 /*hardwareflag */ , temp_p,
159 			  thread, ignore_count,
160 			  pending, enabled);
161 	  break;
162 	case HW_BP:
163 	  set_breakpoint (get_current_arch (), address, condition,
164 			  1 /*hardwareflag */ , temp_p,
165 			  thread, ignore_count,
166 			  pending, enabled);
167 	  break;
168 #if 0
169 	case REGEXP_BP:
170 	  if (temp_p)
171 	    error (_("mi_cmd_break_insert: Unsupported tempoary regexp breakpoint"));
172 	  else
173 	    rbreak_command_wrapper (address, FROM_TTY);
174 	  break;
175 #endif
176 	default:
177 	  internal_error (__FILE__, __LINE__,
178 			  _("mi_cmd_break_insert: Bad switch."));
179 	}
180     }
181   mi_can_breakpoint_notify = 0;
182   if (e.reason < 0)
183     throw_exception (e);
184 }
185 
186 enum wp_type
187 {
188   REG_WP,
189   READ_WP,
190   ACCESS_WP
191 };
192 
193 /* Insert a watchpoint. The type of watchpoint is specified by the
194    first argument:
195    -break-watch <expr> --> insert a regular wp.
196    -break-watch -r <expr> --> insert a read watchpoint.
197    -break-watch -a <expr> --> insert an access wp. */
198 
199 void
200 mi_cmd_break_watch (char *command, char **argv, int argc)
201 {
202   char *expr = NULL;
203   enum wp_type type = REG_WP;
204   enum opt
205     {
206       READ_OPT, ACCESS_OPT
207     };
208   static struct mi_opt opts[] =
209   {
210     {"r", READ_OPT, 0},
211     {"a", ACCESS_OPT, 0},
212     { 0, 0, 0 }
213   };
214 
215   /* Parse arguments. */
216   int optind = 0;
217   char *optarg;
218   while (1)
219     {
220       int opt = mi_getopt ("mi_cmd_break_watch", argc, argv, opts, &optind, &optarg);
221       if (opt < 0)
222 	break;
223       switch ((enum opt) opt)
224 	{
225 	case READ_OPT:
226 	  type = READ_WP;
227 	  break;
228 	case ACCESS_OPT:
229 	  type = ACCESS_WP;
230 	  break;
231 	}
232     }
233   if (optind >= argc)
234     error (_("mi_cmd_break_watch: Missing <expression>"));
235   if (optind < argc - 1)
236     error (_("mi_cmd_break_watch: Garbage following <expression>"));
237   expr = argv[optind];
238 
239   /* Now we have what we need, let's insert the watchpoint! */
240   switch (type)
241     {
242     case REG_WP:
243       watch_command_wrapper (expr, FROM_TTY);
244       break;
245     case READ_WP:
246       rwatch_command_wrapper (expr, FROM_TTY);
247       break;
248     case ACCESS_WP:
249       awatch_command_wrapper (expr, FROM_TTY);
250       break;
251     default:
252       error (_("mi_cmd_break_watch: Unknown watchpoint type."));
253     }
254 }
255 
256 /* The mi_read_next_line consults these variable to return successive
257    command lines.  While it would be clearer to use a closure pointer,
258    it is not expected that any future code will use read_command_lines_1,
259    therefore no point of overengineering.  */
260 
261 static char **mi_command_line_array;
262 static int mi_command_line_array_cnt;
263 static int mi_command_line_array_ptr;
264 
265 static char *
266 mi_read_next_line ()
267 {
268   if (mi_command_line_array_ptr == mi_command_line_array_cnt)
269     return NULL;
270   else
271     return mi_command_line_array[mi_command_line_array_ptr++];
272 }
273 
274 void
275 mi_cmd_break_commands (char *command, char **argv, int argc)
276 {
277   struct command_line *break_command;
278   char *endptr;
279   int bnum;
280   struct breakpoint *b;
281 
282   if (argc < 1)
283     error ("USAGE: %s <BKPT> [<COMMAND> [<COMMAND>...]]", command);
284 
285   bnum = strtol (argv[0], &endptr, 0);
286   if (endptr == argv[0])
287     error ("breakpoint number argument \"%s\" is not a number.",
288 	   argv[0]);
289   else if (*endptr != '\0')
290     error ("junk at the end of breakpoint number argument \"%s\".",
291 	   argv[0]);
292 
293   b = get_breakpoint (bnum);
294   if (b == NULL)
295     error ("breakpoint %d not found.", bnum);
296 
297   mi_command_line_array = argv;
298   mi_command_line_array_ptr = 1;
299   mi_command_line_array_cnt = argc;
300 
301   break_command = read_command_lines_1 (mi_read_next_line, 0);
302   breakpoint_set_commands (b, break_command);
303 }
304 
305