ubsan: z8k: index 10 out of bounds for type 'unsigned int const[10]'
[deliverable/binutils-gdb.git] / gdb / mi / mi-cmd-break.c
index 29e3fb3fb5c29c7af9b2a57cab850f697583a1c3..417f2d82dd3a44265bac6bdfcfe6520a45d289e9 100644 (file)
@@ -1,5 +1,5 @@
 /* MI Command Set - breakpoint and watchpoint commands.
-   Copyright (C) 2000-2014 Free Software Foundation, Inc.
+   Copyright (C) 2000-2020 Free Software Foundation, Inc.
    Contributed by Cygnus Solutions (a Red Hat company).
 
    This file is part of GDB.
 #include "ui-out.h"
 #include "mi-out.h"
 #include "breakpoint.h"
-#include <string.h>
 #include "mi-getopt.h"
-#include "gdb.h"
-#include "exceptions.h"
-#include "observer.h"
+#include "observable.h"
 #include "mi-main.h"
 #include "mi-cmd-break.h"
+#include "language.h"
+#include "location.h"
+#include "linespec.h"
 #include "gdb_obstack.h"
 #include <ctype.h>
+#include "tracepoint.h"
 
 enum
   {
@@ -52,7 +53,16 @@ static void
 breakpoint_notify (struct breakpoint *b)
 {
   if (mi_can_breakpoint_notify)
-    gdb_breakpoint_query (current_uiout, b->number, NULL);
+    {
+      try
+       {
+         print_breakpoint (b);
+       }
+      catch (const gdb_exception &ex)
+       {
+         exception_print (gdb_stderr, ex);
+       }
+    }
 }
 
 enum bp_type
@@ -63,102 +73,91 @@ enum bp_type
   };
 
 /* Arrange for all new breakpoints and catchpoints to be reported to
-   CURRENT_UIOUT until the cleanup returned by this function is run.
+   CURRENT_UIOUT until the destructor of the returned scoped_restore
+   is run.
 
    Note that MI output will be probably invalid if more than one
    breakpoint is created inside one MI command.  */
 
-struct cleanup *
+scoped_restore_tmpl<int>
 setup_breakpoint_reporting (void)
 {
-  struct cleanup *rev_flag;
-
   if (! mi_breakpoint_observers_installed)
     {
-      observer_attach_breakpoint_created (breakpoint_notify);
+      gdb::observers::breakpoint_created.attach (breakpoint_notify);
       mi_breakpoint_observers_installed = 1;
     }
 
-  rev_flag = make_cleanup_restore_integer (&mi_can_breakpoint_notify);
-  mi_can_breakpoint_notify = 1;
-
-  return rev_flag;
+  return make_scoped_restore (&mi_can_breakpoint_notify, 1);
 }
 
 
 /* Convert arguments in ARGV to the string in "format",argv,argv...
    and return it.  */
 
-static char *
+static std::string
 mi_argv_to_format (char **argv, int argc)
 {
   int i;
-  struct obstack obstack;
-  char *ret;
-
-  obstack_init (&obstack);
+  std::string result;
 
   /* Convert ARGV[OIND + 1] to format string and save to FORMAT.  */
-  obstack_1grow (&obstack, '\"');
+  result += '\"';
   for (i = 0; i < strlen (argv[0]); i++)
     {
       switch (argv[0][i])
        {
        case '\\':
-         obstack_grow (&obstack, "\\\\", 2);
+         result += "\\\\";
          break;
        case '\a':
-         obstack_grow (&obstack, "\\a", 2);
+         result += "\\a";
          break;
        case '\b':
-         obstack_grow (&obstack, "\\b", 2);
+         result += "\\b";
          break;
        case '\f':
-         obstack_grow (&obstack, "\\f", 2);
+         result += "\\f";
          break;
        case '\n':
-         obstack_grow (&obstack, "\\n", 2);
+         result += "\\n";
          break;
        case '\r':
-         obstack_grow (&obstack, "\\r", 2);
+         result += "\\r";
          break;
        case '\t':
-         obstack_grow (&obstack, "\\t", 2);
+         result += "\\t";
          break;
        case '\v':
-         obstack_grow (&obstack, "\\v", 2);
+         result += "\\v";
          break;
        case '"':
-         obstack_grow (&obstack, "\\\"", 2);
+         result += "\\\"";
          break;
        default:
          if (isprint (argv[0][i]))
-           obstack_grow (&obstack, argv[0] + i, 1);
+           result += argv[0][i];
          else
            {
              char tmp[5];
 
              xsnprintf (tmp, sizeof (tmp), "\\%o",
                         (unsigned char) argv[0][i]);
-             obstack_grow (&obstack, tmp, strlen (tmp));
+             result += tmp;
            }
          break;
        }
     }
-  obstack_1grow (&obstack, '\"');
+  result += '\"';
 
   /* Apply other argv to FORMAT.  */
   for (i = 1; i < argc; i++)
     {
-      obstack_1grow (&obstack, ',');
-      obstack_grow (&obstack, argv[i], strlen (argv[i]));
+      result += ',';
+      result += argv[i];
     }
-  obstack_1grow (&obstack, '\0');
-
-  ret = xstrdup (obstack_finish (&obstack));
-  obstack_free (&obstack, NULL);
 
-  return ret;
+  return result;
 }
 
 /* Insert breakpoint.
@@ -166,9 +165,9 @@ mi_argv_to_format (char **argv, int argc)
    If not, it will insert other type breakpoint.  */
 
 static void
-mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
+mi_cmd_break_insert_1 (int dprintf, const char *command, char **argv, int argc)
 {
-  char *address = NULL;
+  const char *address = NULL;
   int hardware = 0;
   int temp_p = 0;
   int thread = -1;
@@ -177,16 +176,20 @@ mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
   int pending = 0;
   int enabled = 1;
   int tracepoint = 0;
-  struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
   enum bptype type_wanted;
+  event_location_up location;
   struct breakpoint_ops *ops;
-  char *extra_string = NULL;
+  int is_explicit = 0;
+  struct explicit_location explicit_loc;
+  std::string extra_string;
 
   enum opt
     {
       HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
       IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
       TRACEPOINT_OPT,
+      EXPLICIT_SOURCE_OPT, EXPLICIT_FUNC_OPT,
+      EXPLICIT_LABEL_OPT, EXPLICIT_LINE_OPT
     };
   static const struct mi_opt opts[] =
   {
@@ -198,6 +201,10 @@ mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
     {"f", PENDING_OPT, 0},
     {"d", DISABLE_OPT, 0},
     {"a", TRACEPOINT_OPT, 0},
+    {"-source" , EXPLICIT_SOURCE_OPT, 1},
+    {"-function", EXPLICIT_FUNC_OPT, 1},
+    {"-label", EXPLICIT_LABEL_OPT, 1},
+    {"-line", EXPLICIT_LINE_OPT, 1},
     { 0, 0, 0 }
   };
 
@@ -206,6 +213,8 @@ mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
   int oind = 0;
   char *oarg;
 
+  initialize_explicit_location (&explicit_loc);
+
   while (1)
     {
       int opt = mi_getopt ("-break-insert", argc, argv,
@@ -238,16 +247,31 @@ mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
        case TRACEPOINT_OPT:
          tracepoint = 1;
          break;
+       case EXPLICIT_SOURCE_OPT:
+         is_explicit = 1;
+         explicit_loc.source_filename = oarg;
+         break;
+       case EXPLICIT_FUNC_OPT:
+         is_explicit = 1;
+         explicit_loc.function_name = oarg;
+         break;
+       case EXPLICIT_LABEL_OPT:
+         is_explicit = 1;
+         explicit_loc.label_name = oarg;
+         break;
+       case EXPLICIT_LINE_OPT:
+         is_explicit = 1;
+         explicit_loc.line_offset = linespec_parse_line_offset (oarg);
+         break;
        }
     }
 
-  if (oind >= argc)
+  if (oind >= argc && !is_explicit)
     error (_("-%s-insert: Missing <location>"),
           dprintf ? "dprintf" : "break");
-  address = argv[oind];
   if (dprintf)
     {
-      int format_num = oind + 1;
+      int format_num = is_explicit ? oind : oind + 1;
 
       if (hardware || tracepoint)
        error (_("-dprintf-insert: does not support -h or -a"));
@@ -255,16 +279,25 @@ mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
        error (_("-dprintf-insert: Missing <format>"));
 
       extra_string = mi_argv_to_format (argv + format_num, argc - format_num);
-      make_cleanup (xfree, extra_string);
+      address = argv[oind];
     }
   else
     {
-      if (oind < argc - 1)
-       error (_("-break-insert: Garbage following <location>"));
+      if (is_explicit)
+       {
+         if (oind < argc)
+           error (_("-break-insert: Garbage following explicit location"));
+       }
+      else
+       {
+         if (oind < argc - 1)
+           error (_("-break-insert: Garbage following <location>"));
+         address = argv[oind];
+       }
     }
 
   /* Now we have what we need, let's insert the breakpoint!  */
-  setup_breakpoint_reporting ();
+  scoped_restore restore_breakpoint_reporting = setup_breakpoint_reporting ();
 
   if (tracepoint)
     {
@@ -289,21 +322,41 @@ mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
       ops = &bkpt_breakpoint_ops;
     }
 
-  create_breakpoint (get_current_arch (), address, condition, thread,
-                    extra_string,
+  if (is_explicit)
+    {
+      /* Error check -- we must have one of the other
+        parameters specified.  */
+      if (explicit_loc.source_filename != NULL
+         && explicit_loc.function_name == NULL
+         && explicit_loc.label_name == NULL
+         && explicit_loc.line_offset.sign == LINE_OFFSET_UNKNOWN)
+       error (_("-%s-insert: --source option requires --function, --label,"
+                " or --line"), dprintf ? "dprintf" : "break");
+
+      location = new_explicit_location (&explicit_loc);
+    }
+  else
+    {
+      location = string_to_event_location_basic (&address, current_language,
+                                                symbol_name_match_type::WILD);
+      if (*address)
+       error (_("Garbage '%s' at end of location"), address);
+    }
+
+  create_breakpoint (get_current_arch (), location.get (), condition, thread,
+                    extra_string.c_str (),
                     0 /* condition and thread are valid.  */,
                     temp_p, type_wanted,
                     ignore_count,
                     pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
                     ops, 0, enabled, 0, 0);
-  do_cleanups (back_to);
 }
 
 /* Implements the -break-insert command.
    See the MI manual for the list of possible options.  */
 
 void
-mi_cmd_break_insert (char *command, char **argv, int argc)
+mi_cmd_break_insert (const char *command, char **argv, int argc)
 {
   mi_cmd_break_insert_1 (0, command, argv, argc);
 }
@@ -312,7 +365,7 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
    See the MI manual for the list of possible options.  */
 
 void
-mi_cmd_dprintf_insert (char *command, char **argv, int argc)
+mi_cmd_dprintf_insert (const char *command, char **argv, int argc)
 {
   mi_cmd_break_insert_1 (1, command, argv, argc);
 }
@@ -325,7 +378,7 @@ enum wp_type
 };
 
 void
-mi_cmd_break_passcount (char *command, char **argv, int argc)
+mi_cmd_break_passcount (const char *command, char **argv, int argc)
 {
   int n;
   int p;
@@ -341,7 +394,7 @@ mi_cmd_break_passcount (char *command, char **argv, int argc)
   if (t)
     {
       t->pass_count = p;
-      observer_notify_breakpoint_modified (&t->base);
+      gdb::observers::breakpoint_modified.notify (t);
     }
   else
     {
@@ -356,7 +409,7 @@ mi_cmd_break_passcount (char *command, char **argv, int argc)
    -break-watch -a <expr> --> insert an access wp.  */
 
 void
-mi_cmd_break_watch (char *command, char **argv, int argc)
+mi_cmd_break_watch (const char *command, char **argv, int argc)
 {
   char *expr = NULL;
   enum wp_type type = REG_WP;
@@ -415,28 +468,10 @@ mi_cmd_break_watch (char *command, char **argv, int argc)
     }
 }
 
-/* The mi_read_next_line consults these variable to return successive
-   command lines.  While it would be clearer to use a closure pointer,
-   it is not expected that any future code will use read_command_lines_1,
-   therefore no point of overengineering.  */
-
-static char **mi_command_line_array;
-static int mi_command_line_array_cnt;
-static int mi_command_line_array_ptr;
-
-static char *
-mi_read_next_line (void)
-{
-  if (mi_command_line_array_ptr == mi_command_line_array_cnt)
-    return NULL;
-  else
-    return mi_command_line_array[mi_command_line_array_ptr++];
-}
-
 void
-mi_cmd_break_commands (char *command, char **argv, int argc)
+mi_cmd_break_commands (const char *command, char **argv, int argc)
 {
-  struct command_line *break_command;
+  counted_command_line break_command;
   char *endptr;
   int bnum;
   struct breakpoint *b;
@@ -456,16 +491,25 @@ mi_cmd_break_commands (char *command, char **argv, int argc)
   if (b == NULL)
     error (_("breakpoint %d not found."), bnum);
 
-  mi_command_line_array = argv;
-  mi_command_line_array_ptr = 1;
-  mi_command_line_array_cnt = argc;
+  int count = 1;
+  auto reader
+    = [&] ()
+      {
+       const char *result = nullptr;
+       if (count < argc)
+         result = argv[count++];
+       return result;
+      };
 
   if (is_tracepoint (b))
-    break_command = read_command_lines_1 (mi_read_next_line, 1,
-                                         check_tracepoint_command, b);
+    break_command = read_command_lines_1 (reader, 1,
+                                         [=] (const char *line)
+                                           {
+                                             validate_actionline (line, b);
+                                           });
   else
-    break_command = read_command_lines_1 (mi_read_next_line, 1, 0, 0);
+    break_command = read_command_lines_1 (reader, 1, 0);
 
-  breakpoint_set_commands (b, break_command);
+  breakpoint_set_commands (b, std::move (break_command));
 }
 
This page took 0.039686 seconds and 4 git commands to generate.