GDB (API)
|
00001 /* MI Command Set - breakpoint and watchpoint commands. 00002 Copyright (C) 2000-2013 Free Software Foundation, Inc. 00003 Contributed by Cygnus Solutions (a Red Hat company). 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #include "defs.h" 00021 #include "arch-utils.h" 00022 #include "mi-cmds.h" 00023 #include "ui-out.h" 00024 #include "mi-out.h" 00025 #include "breakpoint.h" 00026 #include "gdb_string.h" 00027 #include "mi-getopt.h" 00028 #include "gdb.h" 00029 #include "exceptions.h" 00030 #include "observer.h" 00031 #include "mi-main.h" 00032 #include "mi-cmd-break.h" 00033 #include "gdb_obstack.h" 00034 #include <ctype.h> 00035 00036 enum 00037 { 00038 FROM_TTY = 0 00039 }; 00040 00041 /* True if MI breakpoint observers have been registered. */ 00042 00043 static int mi_breakpoint_observers_installed; 00044 00045 /* Control whether breakpoint_notify may act. */ 00046 00047 static int mi_can_breakpoint_notify; 00048 00049 /* Output a single breakpoint, when allowed. */ 00050 00051 static void 00052 breakpoint_notify (struct breakpoint *b) 00053 { 00054 if (mi_can_breakpoint_notify) 00055 gdb_breakpoint_query (current_uiout, b->number, NULL); 00056 } 00057 00058 enum bp_type 00059 { 00060 REG_BP, 00061 HW_BP, 00062 REGEXP_BP 00063 }; 00064 00065 /* Arrange for all new breakpoints and catchpoints to be reported to 00066 CURRENT_UIOUT until the cleanup returned by this function is run. 00067 00068 Note that MI output will be probably invalid if more than one 00069 breakpoint is created inside one MI command. */ 00070 00071 struct cleanup * 00072 setup_breakpoint_reporting (void) 00073 { 00074 struct cleanup *rev_flag; 00075 00076 if (! mi_breakpoint_observers_installed) 00077 { 00078 observer_attach_breakpoint_created (breakpoint_notify); 00079 mi_breakpoint_observers_installed = 1; 00080 } 00081 00082 rev_flag = make_cleanup_restore_integer (&mi_can_breakpoint_notify); 00083 mi_can_breakpoint_notify = 1; 00084 00085 return rev_flag; 00086 } 00087 00088 00089 /* Convert arguments in ARGV to the string in "format",argv,argv... 00090 and return it. */ 00091 00092 static char * 00093 mi_argv_to_format (char **argv, int argc) 00094 { 00095 int i; 00096 struct obstack obstack; 00097 char *ret; 00098 00099 obstack_init (&obstack); 00100 00101 /* Convert ARGV[OIND + 1] to format string and save to FORMAT. */ 00102 obstack_1grow (&obstack, '\"'); 00103 for (i = 0; i < strlen (argv[0]); i++) 00104 { 00105 switch (argv[0][i]) 00106 { 00107 case '\\': 00108 obstack_grow (&obstack, "\\\\", 2); 00109 break; 00110 case '\a': 00111 obstack_grow (&obstack, "\\a", 2); 00112 break; 00113 case '\b': 00114 obstack_grow (&obstack, "\\b", 2); 00115 break; 00116 case '\f': 00117 obstack_grow (&obstack, "\\f", 2); 00118 break; 00119 case '\n': 00120 obstack_grow (&obstack, "\\n", 2); 00121 break; 00122 case '\r': 00123 obstack_grow (&obstack, "\\r", 2); 00124 break; 00125 case '\t': 00126 obstack_grow (&obstack, "\\t", 2); 00127 break; 00128 case '\v': 00129 obstack_grow (&obstack, "\\v", 2); 00130 break; 00131 case '"': 00132 obstack_grow (&obstack, "\\\"", 2); 00133 break; 00134 default: 00135 if (isprint (argv[0][i])) 00136 obstack_grow (&obstack, argv[0] + i, 1); 00137 else 00138 { 00139 char tmp[5]; 00140 00141 xsnprintf (tmp, sizeof (tmp), "\\%o", 00142 (unsigned char) argv[0][i]); 00143 obstack_grow (&obstack, tmp, strlen (tmp)); 00144 } 00145 break; 00146 } 00147 } 00148 obstack_1grow (&obstack, '\"'); 00149 00150 /* Apply other argv to FORMAT. */ 00151 for (i = 1; i < argc; i++) 00152 { 00153 obstack_1grow (&obstack, ','); 00154 obstack_grow (&obstack, argv[i], strlen (argv[i])); 00155 } 00156 obstack_1grow (&obstack, '\0'); 00157 00158 ret = xstrdup (obstack_finish (&obstack)); 00159 obstack_free (&obstack, NULL); 00160 00161 return ret; 00162 } 00163 00164 /* Insert breakpoint. 00165 If dprintf is true, it will insert dprintf. 00166 If not, it will insert other type breakpoint. */ 00167 00168 static void 00169 mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc) 00170 { 00171 char *address = NULL; 00172 int hardware = 0; 00173 int temp_p = 0; 00174 int thread = -1; 00175 int ignore_count = 0; 00176 char *condition = NULL; 00177 int pending = 0; 00178 int enabled = 1; 00179 int tracepoint = 0; 00180 struct cleanup *back_to = make_cleanup (null_cleanup, NULL); 00181 enum bptype type_wanted; 00182 struct breakpoint_ops *ops; 00183 char *extra_string = NULL; 00184 00185 enum opt 00186 { 00187 HARDWARE_OPT, TEMP_OPT, CONDITION_OPT, 00188 IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT, 00189 TRACEPOINT_OPT, 00190 }; 00191 static const struct mi_opt opts[] = 00192 { 00193 {"h", HARDWARE_OPT, 0}, 00194 {"t", TEMP_OPT, 0}, 00195 {"c", CONDITION_OPT, 1}, 00196 {"i", IGNORE_COUNT_OPT, 1}, 00197 {"p", THREAD_OPT, 1}, 00198 {"f", PENDING_OPT, 0}, 00199 {"d", DISABLE_OPT, 0}, 00200 {"a", TRACEPOINT_OPT, 0}, 00201 { 0, 0, 0 } 00202 }; 00203 00204 /* Parse arguments. It could be -r or -h or -t, <location> or ``--'' 00205 to denote the end of the option list. */ 00206 int oind = 0; 00207 char *oarg; 00208 00209 while (1) 00210 { 00211 int opt = mi_getopt ("-break-insert", argc, argv, 00212 opts, &oind, &oarg); 00213 if (opt < 0) 00214 break; 00215 switch ((enum opt) opt) 00216 { 00217 case TEMP_OPT: 00218 temp_p = 1; 00219 break; 00220 case HARDWARE_OPT: 00221 hardware = 1; 00222 break; 00223 case CONDITION_OPT: 00224 condition = oarg; 00225 break; 00226 case IGNORE_COUNT_OPT: 00227 ignore_count = atol (oarg); 00228 break; 00229 case THREAD_OPT: 00230 thread = atol (oarg); 00231 break; 00232 case PENDING_OPT: 00233 pending = 1; 00234 break; 00235 case DISABLE_OPT: 00236 enabled = 0; 00237 break; 00238 case TRACEPOINT_OPT: 00239 tracepoint = 1; 00240 break; 00241 } 00242 } 00243 00244 if (oind >= argc) 00245 error (_("-%s-insert: Missing <location>"), 00246 dprintf ? "dprintf" : "break"); 00247 address = argv[oind]; 00248 if (dprintf) 00249 { 00250 int format_num = oind + 1; 00251 00252 if (hardware || tracepoint) 00253 error (_("-dprintf-insert: does not support -h or -a")); 00254 if (format_num >= argc) 00255 error (_("-dprintf-insert: Missing <format>")); 00256 00257 extra_string = mi_argv_to_format (argv + format_num, argc - format_num); 00258 make_cleanup (xfree, extra_string); 00259 } 00260 else 00261 { 00262 if (oind < argc - 1) 00263 error (_("-break-insert: Garbage following <location>")); 00264 } 00265 00266 /* Now we have what we need, let's insert the breakpoint! */ 00267 setup_breakpoint_reporting (); 00268 00269 if (tracepoint) 00270 { 00271 /* Note that to request a fast tracepoint, the client uses the 00272 "hardware" flag, although there's nothing of hardware related to 00273 fast tracepoints -- one can implement slow tracepoints with 00274 hardware breakpoints, but fast tracepoints are always software. 00275 "fast" is a misnomer, actually, "jump" would be more appropriate. 00276 A simulator or an emulator could conceivably implement fast 00277 regular non-jump based tracepoints. */ 00278 type_wanted = hardware ? bp_fast_tracepoint : bp_tracepoint; 00279 ops = &tracepoint_breakpoint_ops; 00280 } 00281 else if (dprintf) 00282 { 00283 type_wanted = bp_dprintf; 00284 ops = &dprintf_breakpoint_ops; 00285 } 00286 else 00287 { 00288 type_wanted = hardware ? bp_hardware_breakpoint : bp_breakpoint; 00289 ops = &bkpt_breakpoint_ops; 00290 } 00291 00292 create_breakpoint (get_current_arch (), address, condition, thread, 00293 extra_string, 00294 0 /* condition and thread are valid. */, 00295 temp_p, type_wanted, 00296 ignore_count, 00297 pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE, 00298 ops, 0, enabled, 0, 0); 00299 do_cleanups (back_to); 00300 } 00301 00302 /* Implements the -break-insert command. 00303 See the MI manual for the list of possible options. */ 00304 00305 void 00306 mi_cmd_break_insert (char *command, char **argv, int argc) 00307 { 00308 mi_cmd_break_insert_1 (0, command, argv, argc); 00309 } 00310 00311 /* Implements the -dprintf-insert command. 00312 See the MI manual for the list of possible options. */ 00313 00314 void 00315 mi_cmd_dprintf_insert (char *command, char **argv, int argc) 00316 { 00317 mi_cmd_break_insert_1 (1, command, argv, argc); 00318 } 00319 00320 enum wp_type 00321 { 00322 REG_WP, 00323 READ_WP, 00324 ACCESS_WP 00325 }; 00326 00327 void 00328 mi_cmd_break_passcount (char *command, char **argv, int argc) 00329 { 00330 int n; 00331 int p; 00332 struct tracepoint *t; 00333 00334 if (argc != 2) 00335 error (_("Usage: tracepoint-number passcount")); 00336 00337 n = atoi (argv[0]); 00338 p = atoi (argv[1]); 00339 t = get_tracepoint (n); 00340 00341 if (t) 00342 { 00343 t->pass_count = p; 00344 observer_notify_breakpoint_modified (&t->base); 00345 } 00346 else 00347 { 00348 error (_("Could not find tracepoint %d"), n); 00349 } 00350 } 00351 00352 /* Insert a watchpoint. The type of watchpoint is specified by the 00353 first argument: 00354 -break-watch <expr> --> insert a regular wp. 00355 -break-watch -r <expr> --> insert a read watchpoint. 00356 -break-watch -a <expr> --> insert an access wp. */ 00357 00358 void 00359 mi_cmd_break_watch (char *command, char **argv, int argc) 00360 { 00361 char *expr = NULL; 00362 enum wp_type type = REG_WP; 00363 enum opt 00364 { 00365 READ_OPT, ACCESS_OPT 00366 }; 00367 static const struct mi_opt opts[] = 00368 { 00369 {"r", READ_OPT, 0}, 00370 {"a", ACCESS_OPT, 0}, 00371 { 0, 0, 0 } 00372 }; 00373 00374 /* Parse arguments. */ 00375 int oind = 0; 00376 char *oarg; 00377 00378 while (1) 00379 { 00380 int opt = mi_getopt ("-break-watch", argc, argv, 00381 opts, &oind, &oarg); 00382 00383 if (opt < 0) 00384 break; 00385 switch ((enum opt) opt) 00386 { 00387 case READ_OPT: 00388 type = READ_WP; 00389 break; 00390 case ACCESS_OPT: 00391 type = ACCESS_WP; 00392 break; 00393 } 00394 } 00395 if (oind >= argc) 00396 error (_("-break-watch: Missing <expression>")); 00397 if (oind < argc - 1) 00398 error (_("-break-watch: Garbage following <expression>")); 00399 expr = argv[oind]; 00400 00401 /* Now we have what we need, let's insert the watchpoint! */ 00402 switch (type) 00403 { 00404 case REG_WP: 00405 watch_command_wrapper (expr, FROM_TTY, 0); 00406 break; 00407 case READ_WP: 00408 rwatch_command_wrapper (expr, FROM_TTY, 0); 00409 break; 00410 case ACCESS_WP: 00411 awatch_command_wrapper (expr, FROM_TTY, 0); 00412 break; 00413 default: 00414 error (_("-break-watch: Unknown watchpoint type.")); 00415 } 00416 } 00417 00418 /* The mi_read_next_line consults these variable to return successive 00419 command lines. While it would be clearer to use a closure pointer, 00420 it is not expected that any future code will use read_command_lines_1, 00421 therefore no point of overengineering. */ 00422 00423 static char **mi_command_line_array; 00424 static int mi_command_line_array_cnt; 00425 static int mi_command_line_array_ptr; 00426 00427 static char * 00428 mi_read_next_line (void) 00429 { 00430 if (mi_command_line_array_ptr == mi_command_line_array_cnt) 00431 return NULL; 00432 else 00433 return mi_command_line_array[mi_command_line_array_ptr++]; 00434 } 00435 00436 void 00437 mi_cmd_break_commands (char *command, char **argv, int argc) 00438 { 00439 struct command_line *break_command; 00440 char *endptr; 00441 int bnum; 00442 struct breakpoint *b; 00443 00444 if (argc < 1) 00445 error (_("USAGE: %s <BKPT> [<COMMAND> [<COMMAND>...]]"), command); 00446 00447 bnum = strtol (argv[0], &endptr, 0); 00448 if (endptr == argv[0]) 00449 error (_("breakpoint number argument \"%s\" is not a number."), 00450 argv[0]); 00451 else if (*endptr != '\0') 00452 error (_("junk at the end of breakpoint number argument \"%s\"."), 00453 argv[0]); 00454 00455 b = get_breakpoint (bnum); 00456 if (b == NULL) 00457 error (_("breakpoint %d not found."), bnum); 00458 00459 mi_command_line_array = argv; 00460 mi_command_line_array_ptr = 1; 00461 mi_command_line_array_cnt = argc; 00462 00463 if (is_tracepoint (b)) 00464 break_command = read_command_lines_1 (mi_read_next_line, 1, 00465 check_tracepoint_command, b); 00466 else 00467 break_command = read_command_lines_1 (mi_read_next_line, 1, 0, 0); 00468 00469 breakpoint_set_commands (b, break_command); 00470 } 00471