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