GDB (API)
/home/stan/gdb/src/gdb/mi/mi-cmd-break.c
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines