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