Home | History | Annotate | Line # | Download | only in mi
      1   1.1  christos /* MI Command Set - breakpoint and watchpoint commands.
      2  1.11  christos    Copyright (C) 2000-2024 Free Software Foundation, Inc.
      3   1.1  christos    Contributed by Cygnus Solutions (a Red Hat company).
      4   1.1  christos 
      5   1.1  christos    This file is part of GDB.
      6   1.1  christos 
      7   1.1  christos    This program is free software; you can redistribute it and/or modify
      8   1.1  christos    it under the terms of the GNU General Public License as published by
      9   1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10   1.1  christos    (at your option) any later version.
     11   1.1  christos 
     12   1.1  christos    This program is distributed in the hope that it will be useful,
     13   1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14   1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15   1.1  christos    GNU General Public License for more details.
     16   1.1  christos 
     17   1.1  christos    You should have received a copy of the GNU General Public License
     18   1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19   1.1  christos 
     20   1.1  christos #include "arch-utils.h"
     21   1.1  christos #include "mi-cmds.h"
     22   1.1  christos #include "ui-out.h"
     23   1.1  christos #include "mi-out.h"
     24   1.1  christos #include "breakpoint.h"
     25   1.1  christos #include "mi-getopt.h"
     26   1.8  christos #include "observable.h"
     27   1.1  christos #include "mi-main.h"
     28   1.1  christos #include "mi-cmd-break.h"
     29   1.6  christos #include "language.h"
     30   1.6  christos #include "location.h"
     31   1.6  christos #include "linespec.h"
     32  1.10  christos #include "gdbsupport/gdb_obstack.h"
     33   1.1  christos #include <ctype.h>
     34   1.8  christos #include "tracepoint.h"
     35   1.1  christos 
     36   1.1  christos enum
     37   1.1  christos   {
     38   1.1  christos     FROM_TTY = 0
     39   1.1  christos   };
     40   1.1  christos 
     41   1.1  christos /* True if MI breakpoint observers have been registered.  */
     42   1.1  christos 
     43   1.1  christos static int mi_breakpoint_observers_installed;
     44   1.1  christos 
     45   1.1  christos /* Control whether breakpoint_notify may act.  */
     46   1.1  christos 
     47   1.1  christos static int mi_can_breakpoint_notify;
     48   1.1  christos 
     49   1.1  christos /* Output a single breakpoint, when allowed.  */
     50   1.1  christos 
     51   1.1  christos static void
     52   1.1  christos breakpoint_notify (struct breakpoint *b)
     53   1.1  christos {
     54   1.1  christos   if (mi_can_breakpoint_notify)
     55   1.8  christos     {
     56   1.9  christos       try
     57   1.8  christos 	{
     58   1.8  christos 	  print_breakpoint (b);
     59   1.8  christos 	}
     60  1.11  christos       catch (const gdb_exception_error &ex)
     61   1.8  christos 	{
     62   1.8  christos 	  exception_print (gdb_stderr, ex);
     63   1.8  christos 	}
     64   1.8  christos     }
     65   1.1  christos }
     66   1.1  christos 
     67   1.1  christos enum bp_type
     68   1.1  christos   {
     69   1.1  christos     REG_BP,
     70   1.1  christos     HW_BP,
     71   1.1  christos     REGEXP_BP
     72   1.1  christos   };
     73   1.1  christos 
     74   1.1  christos /* Arrange for all new breakpoints and catchpoints to be reported to
     75   1.8  christos    CURRENT_UIOUT until the destructor of the returned scoped_restore
     76   1.8  christos    is run.
     77   1.1  christos 
     78   1.1  christos    Note that MI output will be probably invalid if more than one
     79   1.1  christos    breakpoint is created inside one MI command.  */
     80   1.1  christos 
     81   1.8  christos scoped_restore_tmpl<int>
     82   1.1  christos setup_breakpoint_reporting (void)
     83   1.1  christos {
     84   1.1  christos   if (! mi_breakpoint_observers_installed)
     85   1.1  christos     {
     86  1.10  christos       gdb::observers::breakpoint_created.attach (breakpoint_notify,
     87  1.10  christos 						 "mi-cmd-break");
     88   1.1  christos       mi_breakpoint_observers_installed = 1;
     89   1.1  christos     }
     90   1.1  christos 
     91   1.8  christos   return make_scoped_restore (&mi_can_breakpoint_notify, 1);
     92   1.1  christos }
     93   1.1  christos 
     94   1.1  christos 
     95  1.11  christos /* Convert arguments in ARGV to a string suitable for parsing by
     96  1.11  christos    dprintf like "FORMAT",ARG,ARG... and return it.  */
     97   1.1  christos 
     98   1.8  christos static std::string
     99  1.11  christos mi_argv_to_format (const char *const *argv, int argc)
    100   1.1  christos {
    101   1.1  christos   int i;
    102   1.8  christos   std::string result;
    103   1.1  christos 
    104  1.11  christos   /* Convert ARGV[0] to format string and save to FORMAT.  */
    105   1.8  christos   result += '\"';
    106  1.11  christos   for (i = 0; argv[0][i] != '\0'; i++)
    107   1.1  christos     {
    108   1.1  christos       switch (argv[0][i])
    109   1.1  christos 	{
    110   1.1  christos 	case '\\':
    111   1.8  christos 	  result += "\\\\";
    112   1.1  christos 	  break;
    113   1.1  christos 	case '\a':
    114   1.8  christos 	  result += "\\a";
    115   1.1  christos 	  break;
    116   1.1  christos 	case '\b':
    117   1.8  christos 	  result += "\\b";
    118   1.1  christos 	  break;
    119   1.1  christos 	case '\f':
    120   1.8  christos 	  result += "\\f";
    121   1.1  christos 	  break;
    122   1.1  christos 	case '\n':
    123   1.8  christos 	  result += "\\n";
    124   1.1  christos 	  break;
    125   1.1  christos 	case '\r':
    126   1.8  christos 	  result += "\\r";
    127   1.1  christos 	  break;
    128   1.1  christos 	case '\t':
    129   1.8  christos 	  result += "\\t";
    130   1.1  christos 	  break;
    131   1.1  christos 	case '\v':
    132   1.8  christos 	  result += "\\v";
    133   1.1  christos 	  break;
    134   1.1  christos 	case '"':
    135   1.8  christos 	  result += "\\\"";
    136   1.1  christos 	  break;
    137   1.1  christos 	default:
    138   1.1  christos 	  if (isprint (argv[0][i]))
    139   1.8  christos 	    result += argv[0][i];
    140   1.1  christos 	  else
    141   1.1  christos 	    {
    142   1.1  christos 	      char tmp[5];
    143   1.1  christos 
    144   1.1  christos 	      xsnprintf (tmp, sizeof (tmp), "\\%o",
    145   1.1  christos 			 (unsigned char) argv[0][i]);
    146   1.8  christos 	      result += tmp;
    147   1.1  christos 	    }
    148   1.1  christos 	  break;
    149   1.1  christos 	}
    150   1.1  christos     }
    151   1.8  christos   result += '\"';
    152   1.1  christos 
    153  1.11  christos   /* Append other arguments.  */
    154   1.1  christos   for (i = 1; i < argc; i++)
    155   1.1  christos     {
    156   1.8  christos       result += ',';
    157   1.8  christos       result += argv[i];
    158   1.1  christos     }
    159   1.1  christos 
    160   1.8  christos   return result;
    161   1.1  christos }
    162   1.1  christos 
    163   1.1  christos /* Insert breakpoint.
    164   1.1  christos    If dprintf is true, it will insert dprintf.
    165   1.1  christos    If not, it will insert other type breakpoint.  */
    166   1.1  christos 
    167   1.1  christos static void
    168  1.11  christos mi_cmd_break_insert_1 (int dprintf, const char *command,
    169  1.11  christos 		       const char *const *argv, int argc)
    170   1.1  christos {
    171   1.8  christos   const char *address = NULL;
    172   1.1  christos   int hardware = 0;
    173   1.1  christos   int temp_p = 0;
    174   1.1  christos   int thread = -1;
    175  1.11  christos   int thread_group = -1;
    176   1.1  christos   int ignore_count = 0;
    177  1.11  christos   const char *condition = NULL;
    178   1.1  christos   int pending = 0;
    179   1.1  christos   int enabled = 1;
    180   1.1  christos   int tracepoint = 0;
    181   1.9  christos   symbol_name_match_type match_type = symbol_name_match_type::WILD;
    182   1.1  christos   enum bptype type_wanted;
    183  1.10  christos   location_spec_up locspec;
    184  1.10  christos   const struct breakpoint_ops *ops;
    185   1.6  christos   int is_explicit = 0;
    186  1.10  christos   std::unique_ptr<explicit_location_spec> explicit_loc
    187  1.10  christos     (new explicit_location_spec ());
    188   1.8  christos   std::string extra_string;
    189  1.10  christos   bool force_condition = false;
    190   1.1  christos 
    191   1.1  christos   enum opt
    192   1.1  christos     {
    193   1.1  christos       HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
    194  1.11  christos       IGNORE_COUNT_OPT, THREAD_OPT, THREAD_GROUP_OPT,
    195  1.11  christos       PENDING_OPT, DISABLE_OPT,
    196   1.1  christos       TRACEPOINT_OPT,
    197  1.10  christos       FORCE_CONDITION_OPT,
    198   1.9  christos       QUALIFIED_OPT,
    199   1.6  christos       EXPLICIT_SOURCE_OPT, EXPLICIT_FUNC_OPT,
    200   1.6  christos       EXPLICIT_LABEL_OPT, EXPLICIT_LINE_OPT
    201   1.1  christos     };
    202   1.1  christos   static const struct mi_opt opts[] =
    203   1.1  christos   {
    204   1.1  christos     {"h", HARDWARE_OPT, 0},
    205   1.1  christos     {"t", TEMP_OPT, 0},
    206   1.1  christos     {"c", CONDITION_OPT, 1},
    207   1.1  christos     {"i", IGNORE_COUNT_OPT, 1},
    208   1.1  christos     {"p", THREAD_OPT, 1},
    209  1.11  christos     {"g", THREAD_GROUP_OPT, 1},
    210   1.1  christos     {"f", PENDING_OPT, 0},
    211   1.1  christos     {"d", DISABLE_OPT, 0},
    212   1.1  christos     {"a", TRACEPOINT_OPT, 0},
    213  1.10  christos     {"-force-condition", FORCE_CONDITION_OPT, 0},
    214   1.9  christos     {"-qualified", QUALIFIED_OPT, 0},
    215   1.6  christos     {"-source" , EXPLICIT_SOURCE_OPT, 1},
    216   1.6  christos     {"-function", EXPLICIT_FUNC_OPT, 1},
    217   1.6  christos     {"-label", EXPLICIT_LABEL_OPT, 1},
    218   1.6  christos     {"-line", EXPLICIT_LINE_OPT, 1},
    219   1.1  christos     { 0, 0, 0 }
    220   1.1  christos   };
    221   1.1  christos 
    222   1.1  christos   /* Parse arguments. It could be -r or -h or -t, <location> or ``--''
    223   1.1  christos      to denote the end of the option list. */
    224   1.1  christos   int oind = 0;
    225  1.11  christos   const char *oarg;
    226   1.1  christos 
    227   1.1  christos   while (1)
    228   1.1  christos     {
    229   1.1  christos       int opt = mi_getopt ("-break-insert", argc, argv,
    230   1.1  christos 			   opts, &oind, &oarg);
    231   1.1  christos       if (opt < 0)
    232   1.1  christos 	break;
    233   1.1  christos       switch ((enum opt) opt)
    234   1.1  christos 	{
    235   1.1  christos 	case TEMP_OPT:
    236   1.1  christos 	  temp_p = 1;
    237   1.1  christos 	  break;
    238   1.1  christos 	case HARDWARE_OPT:
    239   1.1  christos 	  hardware = 1;
    240   1.1  christos 	  break;
    241   1.1  christos 	case CONDITION_OPT:
    242   1.1  christos 	  condition = oarg;
    243   1.1  christos 	  break;
    244   1.1  christos 	case IGNORE_COUNT_OPT:
    245   1.1  christos 	  ignore_count = atol (oarg);
    246   1.1  christos 	  break;
    247   1.1  christos 	case THREAD_OPT:
    248   1.1  christos 	  thread = atol (oarg);
    249  1.11  christos 	  if (!valid_global_thread_id (thread))
    250  1.11  christos 	    error (_("Unknown thread %d."), thread);
    251  1.11  christos 	  break;
    252  1.11  christos 	case THREAD_GROUP_OPT:
    253  1.11  christos 	  thread_group = mi_parse_thread_group_id (oarg);
    254   1.1  christos 	  break;
    255   1.1  christos 	case PENDING_OPT:
    256   1.1  christos 	  pending = 1;
    257   1.1  christos 	  break;
    258   1.1  christos 	case DISABLE_OPT:
    259   1.1  christos 	  enabled = 0;
    260   1.1  christos 	  break;
    261   1.1  christos 	case TRACEPOINT_OPT:
    262   1.1  christos 	  tracepoint = 1;
    263   1.1  christos 	  break;
    264   1.9  christos 	case QUALIFIED_OPT:
    265   1.9  christos 	  match_type = symbol_name_match_type::FULL;
    266   1.9  christos 	  break;
    267   1.6  christos 	case EXPLICIT_SOURCE_OPT:
    268   1.6  christos 	  is_explicit = 1;
    269  1.11  christos 	  explicit_loc->source_filename = make_unique_xstrdup (oarg);
    270   1.6  christos 	  break;
    271   1.6  christos 	case EXPLICIT_FUNC_OPT:
    272   1.6  christos 	  is_explicit = 1;
    273  1.11  christos 	  explicit_loc->function_name = make_unique_xstrdup (oarg);
    274   1.6  christos 	  break;
    275   1.6  christos 	case EXPLICIT_LABEL_OPT:
    276   1.6  christos 	  is_explicit = 1;
    277  1.11  christos 	  explicit_loc->label_name = make_unique_xstrdup (oarg);
    278   1.6  christos 	  break;
    279   1.6  christos 	case EXPLICIT_LINE_OPT:
    280   1.6  christos 	  is_explicit = 1;
    281  1.10  christos 	  explicit_loc->line_offset = linespec_parse_line_offset (oarg);
    282  1.10  christos 	  break;
    283  1.10  christos 	case FORCE_CONDITION_OPT:
    284  1.10  christos 	  force_condition = true;
    285   1.6  christos 	  break;
    286   1.1  christos 	}
    287   1.1  christos     }
    288   1.1  christos 
    289   1.6  christos   if (oind >= argc && !is_explicit)
    290   1.1  christos     error (_("-%s-insert: Missing <location>"),
    291   1.1  christos 	   dprintf ? "dprintf" : "break");
    292   1.1  christos   if (dprintf)
    293   1.1  christos     {
    294   1.6  christos       int format_num = is_explicit ? oind : oind + 1;
    295   1.1  christos 
    296   1.1  christos       if (hardware || tracepoint)
    297   1.1  christos 	error (_("-dprintf-insert: does not support -h or -a"));
    298   1.1  christos       if (format_num >= argc)
    299   1.1  christos 	error (_("-dprintf-insert: Missing <format>"));
    300   1.1  christos 
    301   1.1  christos       extra_string = mi_argv_to_format (argv + format_num, argc - format_num);
    302   1.6  christos       address = argv[oind];
    303   1.1  christos     }
    304   1.1  christos   else
    305   1.1  christos     {
    306   1.6  christos       if (is_explicit)
    307   1.6  christos 	{
    308   1.6  christos 	  if (oind < argc)
    309   1.6  christos 	    error (_("-break-insert: Garbage following explicit location"));
    310   1.6  christos 	}
    311   1.6  christos       else
    312   1.6  christos 	{
    313   1.6  christos 	  if (oind < argc - 1)
    314   1.6  christos 	    error (_("-break-insert: Garbage following <location>"));
    315   1.6  christos 	  address = argv[oind];
    316   1.6  christos 	}
    317   1.1  christos     }
    318   1.1  christos 
    319   1.1  christos   /* Now we have what we need, let's insert the breakpoint!  */
    320   1.8  christos   scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
    321   1.1  christos 
    322   1.1  christos   if (tracepoint)
    323   1.1  christos     {
    324   1.1  christos       /* Note that to request a fast tracepoint, the client uses the
    325   1.1  christos 	 "hardware" flag, although there's nothing of hardware related to
    326   1.1  christos 	 fast tracepoints -- one can implement slow tracepoints with
    327   1.1  christos 	 hardware breakpoints, but fast tracepoints are always software.
    328   1.1  christos 	 "fast" is a misnomer, actually, "jump" would be more appropriate.
    329   1.1  christos 	 A simulator or an emulator could conceivably implement fast
    330   1.1  christos 	 regular non-jump based tracepoints.  */
    331   1.1  christos       type_wanted = hardware ? bp_fast_tracepoint : bp_tracepoint;
    332  1.10  christos       ops = breakpoint_ops_for_location_spec (nullptr, true);
    333   1.1  christos     }
    334   1.1  christos   else if (dprintf)
    335   1.1  christos     {
    336   1.1  christos       type_wanted = bp_dprintf;
    337  1.10  christos       ops = &code_breakpoint_ops;
    338   1.1  christos     }
    339   1.1  christos   else
    340   1.1  christos     {
    341   1.1  christos       type_wanted = hardware ? bp_hardware_breakpoint : bp_breakpoint;
    342  1.10  christos       ops = &code_breakpoint_ops;
    343   1.1  christos     }
    344   1.1  christos 
    345   1.6  christos   if (is_explicit)
    346   1.6  christos     {
    347   1.6  christos       /* Error check -- we must have one of the other
    348   1.6  christos 	 parameters specified.  */
    349  1.10  christos       if (explicit_loc->source_filename != NULL
    350  1.10  christos 	  && explicit_loc->function_name == NULL
    351  1.10  christos 	  && explicit_loc->label_name == NULL
    352  1.10  christos 	  && explicit_loc->line_offset.sign == LINE_OFFSET_UNKNOWN)
    353   1.6  christos 	error (_("-%s-insert: --source option requires --function, --label,"
    354   1.6  christos 		 " or --line"), dprintf ? "dprintf" : "break");
    355   1.6  christos 
    356  1.10  christos       explicit_loc->func_name_match_type = match_type;
    357   1.9  christos 
    358  1.10  christos       locspec = std::move (explicit_loc);
    359   1.6  christos     }
    360   1.6  christos   else
    361   1.6  christos     {
    362  1.10  christos       locspec = string_to_location_spec_basic (&address, current_language,
    363  1.10  christos 					       match_type);
    364   1.6  christos       if (*address)
    365   1.7  christos 	error (_("Garbage '%s' at end of location"), address);
    366   1.6  christos     }
    367   1.6  christos 
    368  1.11  christos   create_breakpoint (get_current_arch (), locspec.get (), condition,
    369  1.11  christos 		     thread, thread_group,
    370   1.8  christos 		     extra_string.c_str (),
    371  1.10  christos 		     force_condition,
    372   1.1  christos 		     0 /* condition and thread are valid.  */,
    373   1.1  christos 		     temp_p, type_wanted,
    374   1.1  christos 		     ignore_count,
    375   1.1  christos 		     pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
    376   1.1  christos 		     ops, 0, enabled, 0, 0);
    377   1.1  christos }
    378   1.1  christos 
    379   1.1  christos /* Implements the -break-insert command.
    380   1.1  christos    See the MI manual for the list of possible options.  */
    381   1.1  christos 
    382   1.1  christos void
    383  1.11  christos mi_cmd_break_insert (const char *command, const char *const *argv, int argc)
    384   1.1  christos {
    385   1.1  christos   mi_cmd_break_insert_1 (0, command, argv, argc);
    386   1.1  christos }
    387   1.1  christos 
    388   1.1  christos /* Implements the -dprintf-insert command.
    389   1.1  christos    See the MI manual for the list of possible options.  */
    390   1.1  christos 
    391   1.1  christos void
    392  1.11  christos mi_cmd_dprintf_insert (const char *command, const char *const *argv, int argc)
    393   1.1  christos {
    394   1.1  christos   mi_cmd_break_insert_1 (1, command, argv, argc);
    395   1.1  christos }
    396   1.1  christos 
    397  1.10  christos /* Implements the -break-condition command.
    398  1.10  christos    See the MI manual for the list of options.  */
    399  1.10  christos 
    400  1.10  christos void
    401  1.11  christos mi_cmd_break_condition (const char *command, const char *const *argv,
    402  1.11  christos 			int argc)
    403  1.10  christos {
    404  1.10  christos   enum option
    405  1.10  christos     {
    406  1.10  christos       FORCE_CONDITION_OPT,
    407  1.10  christos     };
    408  1.10  christos 
    409  1.10  christos   static const struct mi_opt opts[] =
    410  1.10  christos   {
    411  1.10  christos     {"-force", FORCE_CONDITION_OPT, 0},
    412  1.10  christos     { 0, 0, 0 }
    413  1.10  christos   };
    414  1.10  christos 
    415  1.10  christos   /* Parse arguments.  */
    416  1.10  christos   int oind = 0;
    417  1.11  christos   const char *oarg;
    418  1.10  christos   bool force_condition = false;
    419  1.10  christos 
    420  1.10  christos   while (true)
    421  1.10  christos     {
    422  1.10  christos       int opt = mi_getopt ("-break-condition", argc, argv,
    423  1.10  christos 			   opts, &oind, &oarg);
    424  1.10  christos       if (opt < 0)
    425  1.10  christos 	break;
    426  1.10  christos 
    427  1.10  christos       switch (opt)
    428  1.10  christos 	{
    429  1.10  christos 	case FORCE_CONDITION_OPT:
    430  1.10  christos 	  force_condition = true;
    431  1.10  christos 	  break;
    432  1.10  christos 	}
    433  1.10  christos     }
    434  1.10  christos 
    435  1.10  christos   /* There must be at least one more arg: a bpnum.  */
    436  1.10  christos   if (oind >= argc)
    437  1.10  christos     error (_("-break-condition: Missing the <number> argument"));
    438  1.10  christos 
    439  1.10  christos   int bpnum = atoi (argv[oind]);
    440  1.10  christos 
    441  1.10  christos   /* The rest form the condition expr.  */
    442  1.10  christos   std::string expr = "";
    443  1.10  christos   for (int i = oind + 1; i < argc; ++i)
    444  1.10  christos     {
    445  1.10  christos       expr += argv[i];
    446  1.10  christos       if (i + 1 < argc)
    447  1.10  christos 	expr += " ";
    448  1.10  christos     }
    449  1.10  christos 
    450  1.10  christos   set_breakpoint_condition (bpnum, expr.c_str (), 0 /* from_tty */,
    451  1.10  christos 			    force_condition);
    452  1.10  christos }
    453  1.10  christos 
    454   1.1  christos enum wp_type
    455   1.1  christos {
    456   1.1  christos   REG_WP,
    457   1.1  christos   READ_WP,
    458   1.1  christos   ACCESS_WP
    459   1.1  christos };
    460   1.1  christos 
    461   1.1  christos void
    462  1.11  christos mi_cmd_break_passcount (const char *command, const char *const *argv,
    463  1.11  christos 			int argc)
    464   1.1  christos {
    465   1.1  christos   int n;
    466   1.1  christos   int p;
    467   1.1  christos   struct tracepoint *t;
    468   1.1  christos 
    469   1.1  christos   if (argc != 2)
    470   1.1  christos     error (_("Usage: tracepoint-number passcount"));
    471   1.1  christos 
    472   1.1  christos   n = atoi (argv[0]);
    473   1.1  christos   p = atoi (argv[1]);
    474   1.1  christos   t = get_tracepoint (n);
    475   1.1  christos 
    476   1.1  christos   if (t)
    477   1.1  christos     {
    478   1.1  christos       t->pass_count = p;
    479  1.11  christos       notify_breakpoint_modified (t);
    480   1.1  christos     }
    481   1.1  christos   else
    482   1.1  christos     {
    483   1.1  christos       error (_("Could not find tracepoint %d"), n);
    484   1.1  christos     }
    485   1.1  christos }
    486   1.1  christos 
    487   1.1  christos /* Insert a watchpoint. The type of watchpoint is specified by the
    488   1.1  christos    first argument:
    489   1.1  christos    -break-watch <expr> --> insert a regular wp.
    490   1.1  christos    -break-watch -r <expr> --> insert a read watchpoint.
    491   1.1  christos    -break-watch -a <expr> --> insert an access wp.  */
    492   1.1  christos 
    493   1.1  christos void
    494  1.11  christos mi_cmd_break_watch (const char *command, const char *const *argv, int argc)
    495   1.1  christos {
    496  1.11  christos   const char *expr = NULL;
    497   1.1  christos   enum wp_type type = REG_WP;
    498   1.1  christos   enum opt
    499   1.1  christos     {
    500   1.1  christos       READ_OPT, ACCESS_OPT
    501   1.1  christos     };
    502   1.1  christos   static const struct mi_opt opts[] =
    503   1.1  christos   {
    504   1.1  christos     {"r", READ_OPT, 0},
    505   1.1  christos     {"a", ACCESS_OPT, 0},
    506   1.1  christos     { 0, 0, 0 }
    507   1.1  christos   };
    508   1.1  christos 
    509   1.1  christos   /* Parse arguments. */
    510   1.1  christos   int oind = 0;
    511  1.11  christos   const char *oarg;
    512   1.1  christos 
    513   1.1  christos   while (1)
    514   1.1  christos     {
    515   1.1  christos       int opt = mi_getopt ("-break-watch", argc, argv,
    516   1.1  christos 			   opts, &oind, &oarg);
    517   1.1  christos 
    518   1.1  christos       if (opt < 0)
    519   1.1  christos 	break;
    520   1.1  christos       switch ((enum opt) opt)
    521   1.1  christos 	{
    522   1.1  christos 	case READ_OPT:
    523   1.1  christos 	  type = READ_WP;
    524   1.1  christos 	  break;
    525   1.1  christos 	case ACCESS_OPT:
    526   1.1  christos 	  type = ACCESS_WP;
    527   1.1  christos 	  break;
    528   1.1  christos 	}
    529   1.1  christos     }
    530   1.1  christos   if (oind >= argc)
    531   1.1  christos     error (_("-break-watch: Missing <expression>"));
    532   1.1  christos   if (oind < argc - 1)
    533   1.1  christos     error (_("-break-watch: Garbage following <expression>"));
    534   1.1  christos   expr = argv[oind];
    535   1.1  christos 
    536   1.1  christos   /* Now we have what we need, let's insert the watchpoint!  */
    537   1.1  christos   switch (type)
    538   1.1  christos     {
    539   1.1  christos     case REG_WP:
    540  1.10  christos       watch_command_wrapper (expr, FROM_TTY, false);
    541   1.1  christos       break;
    542   1.1  christos     case READ_WP:
    543  1.10  christos       rwatch_command_wrapper (expr, FROM_TTY, false);
    544   1.1  christos       break;
    545   1.1  christos     case ACCESS_WP:
    546  1.10  christos       awatch_command_wrapper (expr, FROM_TTY, false);
    547   1.1  christos       break;
    548   1.1  christos     default:
    549   1.1  christos       error (_("-break-watch: Unknown watchpoint type."));
    550   1.1  christos     }
    551   1.1  christos }
    552   1.1  christos 
    553   1.1  christos void
    554  1.11  christos mi_cmd_break_commands (const char *command, const char *const *argv, int argc)
    555   1.1  christos {
    556   1.8  christos   counted_command_line break_command;
    557   1.1  christos   char *endptr;
    558   1.1  christos   int bnum;
    559   1.1  christos   struct breakpoint *b;
    560   1.1  christos 
    561   1.1  christos   if (argc < 1)
    562   1.1  christos     error (_("USAGE: %s <BKPT> [<COMMAND> [<COMMAND>...]]"), command);
    563   1.1  christos 
    564   1.1  christos   bnum = strtol (argv[0], &endptr, 0);
    565   1.1  christos   if (endptr == argv[0])
    566   1.1  christos     error (_("breakpoint number argument \"%s\" is not a number."),
    567   1.1  christos 	   argv[0]);
    568   1.1  christos   else if (*endptr != '\0')
    569   1.1  christos     error (_("junk at the end of breakpoint number argument \"%s\"."),
    570   1.1  christos 	   argv[0]);
    571   1.1  christos 
    572   1.1  christos   b = get_breakpoint (bnum);
    573   1.1  christos   if (b == NULL)
    574   1.1  christos     error (_("breakpoint %d not found."), bnum);
    575   1.1  christos 
    576   1.8  christos   int count = 1;
    577   1.8  christos   auto reader
    578  1.10  christos     = [&] (std::string &buffer)
    579   1.8  christos       {
    580   1.8  christos 	const char *result = nullptr;
    581   1.8  christos 	if (count < argc)
    582   1.8  christos 	  result = argv[count++];
    583   1.8  christos 	return result;
    584   1.8  christos       };
    585   1.1  christos 
    586   1.1  christos   if (is_tracepoint (b))
    587  1.11  christos     {
    588  1.11  christos       tracepoint *t = gdb::checked_static_cast<tracepoint *> (b);
    589  1.11  christos       break_command = read_command_lines_1 (reader, 1,
    590  1.11  christos 					    [=] (const char *line)
    591   1.8  christos 					    {
    592  1.11  christos 					      validate_actionline (line, t);
    593   1.8  christos 					    });
    594  1.11  christos     }
    595   1.1  christos   else
    596   1.8  christos     break_command = read_command_lines_1 (reader, 1, 0);
    597   1.1  christos 
    598   1.7  christos   breakpoint_set_commands (b, std::move (break_command));
    599   1.1  christos }
    600   1.1  christos 
    601