gdbserver: Handle 'v' packet while processing qSymbol.
[deliverable/binutils-gdb.git] / gdb / gdbserver / server.c
index 34fcd2b00836dc035f85fc44839a4cbfb9b512e8..9c50929703525f25d06b6ab1ec3a74466ea2ac05 100644 (file)
@@ -1,5 +1,5 @@
 /* Main code for remote server for GDB.
-   Copyright (C) 1989-2015 Free Software Foundation, Inc.
+   Copyright (C) 1989-2016 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -49,7 +49,7 @@ ptid_t general_thread;
 
 int server_waiting;
 
-int extended_protocol;
+static int extended_protocol;
 static int response_needed;
 static int exit_requested;
 
@@ -59,10 +59,21 @@ int run_once;
 int multi_process;
 int report_fork_events;
 int report_vfork_events;
+int report_exec_events;
+int report_thread_events;
+
+/* Whether to report TARGET_WAITKING_NO_RESUMED events.  */
+static int report_no_resumed;
+
 int non_stop;
 int swbreak_feature;
 int hwbreak_feature;
 
+/* True if the "vContSupported" feature is active.  In that case, GDB
+   wants us to report whether single step is supported in the reply to
+   "vCont?" packet.  */
+static int vCont_supported;
+
 /* Whether we should attempt to disable the operating system's address
    space randomization feature before starting an inferior.  */
 int disable_randomization = 1;
@@ -108,7 +119,7 @@ int disable_packet_qfThreadInfo;
 static struct target_waitstatus last_status;
 static ptid_t last_ptid;
 
-static char *own_buf;
+char *own_buf;
 static unsigned char *mem_buf;
 
 /* A sub-class of 'struct notif_event' for stop, holding information
@@ -137,7 +148,7 @@ DEFINE_QUEUE_P (notif_event_p);
 static void
 queue_stop_reply (ptid_t ptid, struct target_waitstatus *status)
 {
-  struct vstop_notif *new_notif = xmalloc (sizeof (*new_notif));
+  struct vstop_notif *new_notif = XNEW (struct vstop_notif);
 
   new_notif->ptid = ptid;
   new_notif->status = *status;
@@ -206,7 +217,7 @@ start_inferior (char **argv)
        count++;
       for (i = 0; argv[i] != NULL; i++)
        count++;
-      new_argv = alloca (sizeof (char *) * count);
+      new_argv = XALLOCAVEC (char *, count);
       count = 0;
       for (i = 0; wrapper_argv[i] != NULL; i++)
        new_argv[count++] = wrapper_argv[i];
@@ -271,7 +282,7 @@ start_inferior (char **argv)
            }
          while (last_status.value.sig != GDB_SIGNAL_TRAP);
        }
-      target_arch_setup ();
+      target_post_create_inferior ();
       return signal_pid;
     }
 
@@ -279,7 +290,7 @@ start_inferior (char **argv)
      (assuming success).  */
   last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
 
-  target_arch_setup ();
+  target_post_create_inferior ();
 
   if (last_status.kind != TARGET_WAITKIND_EXITED
       && last_status.kind != TARGET_WAITKIND_SIGNALLED)
@@ -379,7 +390,7 @@ decode_xfer (char *buf, char **object, char **rw, char **annex, char **offset)
    to as much of DATA/LEN as we could fit.  IS_MORE controls
    the first character of the response.  */
 static int
-write_qxfer_response (char *buf, const void *data, int len, int is_more)
+write_qxfer_response (char *buf, const gdb_byte *data, int len, int is_more)
 {
   int out_len;
 
@@ -409,7 +420,7 @@ handle_btrace_enable_bts (struct thread_info *thread)
   return NULL;
 }
 
-/* Handle btrace enabling in Intel(R) Processor Trace format.  */
+/* Handle btrace enabling in Intel Processor Trace format.  */
 
 static const char *
 handle_btrace_enable_pt (struct thread_info *thread)
@@ -613,6 +624,54 @@ handle_general_set (char *own_buf)
       return;
     }
 
+  if (startswith (own_buf, "QCatchSyscalls:"))
+    {
+      const char *p = own_buf + sizeof ("QCatchSyscalls:") - 1;
+      int enabled = -1;
+      CORE_ADDR sysno;
+      struct process_info *process;
+
+      if (!target_running () || !target_supports_catch_syscall ())
+       {
+         write_enn (own_buf);
+         return;
+       }
+
+      if (strcmp (p, "0") == 0)
+       enabled = 0;
+      else if (p[0] == '1' && (p[1] == ';' || p[1] == '\0'))
+       enabled = 1;
+      else
+       {
+         fprintf (stderr, "Unknown catch-syscalls mode requested: %s\n",
+                  own_buf);
+         write_enn (own_buf);
+         return;
+       }
+
+      process = current_process ();
+      VEC_truncate (int, process->syscalls_to_catch, 0);
+
+      if (enabled)
+       {
+         p += 1;
+         if (*p == ';')
+           {
+             p += 1;
+             while (*p != '\0')
+               {
+                 p = decode_address_to_semicolon (&sysno, p);
+                 VEC_safe_push (int, process->syscalls_to_catch, (int) sysno);
+               }
+           }
+         else
+           VEC_safe_push (int, process->syscalls_to_catch, ANY_SYSCALL);
+       }
+
+      write_ok (own_buf);
+      return;
+    }
+
   if (strcmp (own_buf, "QStartNoAckMode") == 0)
     {
       if (remote_debug)
@@ -717,6 +776,39 @@ handle_general_set (char *own_buf)
   if (handle_btrace_conf_general_set (own_buf))
     return;
 
+  if (startswith (own_buf, "QThreadEvents:"))
+    {
+      char *mode = own_buf + strlen ("QThreadEvents:");
+      enum tribool req = TRIBOOL_UNKNOWN;
+
+      if (strcmp (mode, "0") == 0)
+       req = TRIBOOL_FALSE;
+      else if (strcmp (mode, "1") == 0)
+       req = TRIBOOL_TRUE;
+      else
+       {
+         char *mode_copy = xstrdup (mode);
+
+         /* We don't know what this mode is, so complain to GDB.  */
+         sprintf (own_buf, "E.Unknown thread-events mode requested: %s\n",
+                  mode_copy);
+         xfree (mode_copy);
+         return;
+       }
+
+      report_thread_events = (req == TRIBOOL_TRUE);
+
+      if (remote_debug)
+       {
+         const char *req_str = report_thread_events ? "enabled" : "disabled";
+
+         fprintf (stderr, "[thread events are now %s]\n", req_str);
+       }
+
+      write_ok (own_buf);
+      return;
+    }
+
   /* Otherwise we didn't know what packet it was.  Say we didn't
      understand it.  */
   own_buf[0] = 0;
@@ -761,7 +853,7 @@ get_features_xml (const char *annex)
   return NULL;
 }
 
-void
+static void
 monitor_show_help (void)
 {
   monitor_output ("The following monitor commands are supported:\n");
@@ -885,7 +977,8 @@ handle_search_memory_1 (CORE_ADDR start_addr, CORE_ADDR search_space_len,
                                  ? search_space_len
                                  : search_buf_size);
 
-      found_ptr = memmem (search_buf, nr_search_bytes, pattern, pattern_len);
+      found_ptr = (gdb_byte *) memmem (search_buf, nr_search_bytes, pattern,
+                                      pattern_len);
 
       if (found_ptr != NULL)
        {
@@ -953,7 +1046,7 @@ handle_search_memory (char *own_buf, int packet_len)
   CORE_ADDR found_addr;
   int cmd_name_len = sizeof ("qSearch:memory:") - 1;
 
-  pattern = malloc (packet_len);
+  pattern = (gdb_byte *) malloc (packet_len);
   if (pattern == NULL)
     {
       error ("Unable to allocate memory to perform the search");
@@ -977,7 +1070,7 @@ handle_search_memory (char *own_buf, int packet_len)
   if (search_space_len < search_buf_size)
     search_buf_size = search_space_len;
 
-  search_buf = malloc (search_buf_size);
+  search_buf = (gdb_byte *) malloc (search_buf_size);
   if (search_buf == NULL)
     {
       free (pattern);
@@ -1205,7 +1298,7 @@ handle_qxfer_exec_file (const char *const_annex,
     }
   else
     {
-      char *annex = alloca (strlen (const_annex) + 1);
+      char *annex = (char *) alloca (strlen (const_annex) + 1);
 
       strcpy (annex, const_annex);
       annex = unpack_varlen_hex (annex, &pid);
@@ -1274,7 +1367,7 @@ static void
 accumulate_file_name_length (struct inferior_list_entry *inf, void *arg)
 {
   struct dll_info *dll = (struct dll_info *) inf;
-  unsigned int *total_len = arg;
+  unsigned int *total_len = (unsigned int *) arg;
 
   /* Over-estimate the necessary memory.  Assume that every character
      in the library name must be escaped.  */
@@ -1288,7 +1381,7 @@ static void
 emit_dll_description (struct inferior_list_entry *inf, void *arg)
 {
   struct dll_info *dll = (struct dll_info *) inf;
-  char **p_ptr = arg;
+  char **p_ptr = (char **) arg;
   char *p = *p_ptr;
   char *name;
 
@@ -1328,7 +1421,7 @@ handle_qxfer_libraries (const char *annex,
   for_each_inferior_with_data (&all_dlls, accumulate_file_name_length,
                               &total_len);
 
-  document = malloc (total_len);
+  document = (char *) malloc (total_len);
   if (document == NULL)
     return -1;
 
@@ -1444,25 +1537,27 @@ static void
 handle_qxfer_threads_worker (struct inferior_list_entry *inf, void *arg)
 {
   struct thread_info *thread = (struct thread_info *) inf;
-  struct buffer *buffer = arg;
+  struct buffer *buffer = (struct buffer *) arg;
   ptid_t ptid = thread_to_gdb_id (thread);
   char ptid_s[100];
   int core = target_core_of_thread (ptid);
   char core_s[21];
+  const char *name = target_thread_name (ptid);
 
   write_ptid (ptid_s, ptid);
 
+  buffer_xml_printf (buffer, "<thread id=\"%s\"", ptid_s);
+
   if (core != -1)
     {
       sprintf (core_s, "%d", core);
-      buffer_xml_printf (buffer, "<thread id=\"%s\" core=\"%s\"/>\n",
-                        ptid_s, core_s);
-    }
-  else
-    {
-      buffer_xml_printf (buffer, "<thread id=\"%s\"/>\n",
-                        ptid_s);
+      buffer_xml_printf (buffer, " core=\"%s\"", core_s);
     }
+
+  if (name != NULL)
+    buffer_xml_printf (buffer, " name=\"%s\"", name);
+
+  buffer_xml_printf (buffer, "/>\n");
 }
 
 /* Helper for handle_qxfer_threads.  */
@@ -1602,7 +1697,8 @@ handle_qxfer_btrace (const char *annex,
 {
   static struct buffer cache;
   struct thread_info *thread;
-  int type, result;
+  enum btrace_read_type type;
+  int result;
 
   if (the_target->read_btrace == NULL || writebuf != NULL)
     return -2;
@@ -1789,7 +1885,7 @@ handle_qxfer (char *own_buf, int packet_len, int *new_packet_len_p)
                 more.  */
              if (len > PBUFSIZ - 2)
                len = PBUFSIZ - 2;
-             data = malloc (len + 1);
+             data = (unsigned char *) malloc (len + 1);
              if (data == NULL)
                {
                  write_enn (own_buf);
@@ -1823,7 +1919,7 @@ handle_qxfer (char *own_buf, int packet_len, int *new_packet_len_p)
              unsigned char *data;
 
              strcpy (own_buf, "E00");
-             data = malloc (packet_len - (offset - own_buf));
+             data = (unsigned char *) malloc (packet_len - (offset - own_buf));
              if (data == NULL)
                {
                  write_enn (own_buf);
@@ -1863,11 +1959,6 @@ handle_qxfer (char *own_buf, int packet_len, int *new_packet_len_p)
   return 0;
 }
 
-/* Table used by the crc32 function to calcuate the checksum.  */
-
-static unsigned int crc32_table[256] =
-{0, 0};
-
 /* Compute 32 bit CRC from inferior memory.
 
    On success, return 32 bit CRC.
@@ -1876,20 +1967,6 @@ static unsigned int crc32_table[256] =
 static unsigned long long
 crc32 (CORE_ADDR base, int len, unsigned int crc)
 {
-  if (!crc32_table[1])
-    {
-      /* Initialize the CRC table and the decoding table.  */
-      int i, j;
-      unsigned int c;
-
-      for (i = 0; i < 256; i++)
-       {
-         for (c = i << 24, j = 8; j > 0; --j)
-           c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
-         crc32_table[i] = c;
-       }
-    }
-
   while (len--)
     {
       unsigned char byte = 0;
@@ -1898,7 +1975,7 @@ crc32 (CORE_ADDR base, int len, unsigned int crc)
       if (read_inferior_memory (base, &byte, 1) != 0)
        return (unsigned long long) -1;
 
-      crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ byte) & 255];
+      crc = xcrc32 (&byte, 1, crc);
       base++;
     }
   return (unsigned long long) crc;
@@ -1937,7 +2014,7 @@ supported_btrace_packets (char *buf)
 
 /* Handle all of the extended 'q' packets.  */
 
-void
+static void
 handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
 {
   static struct inferior_list_entry *thread_ptr;
@@ -1965,6 +2042,28 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
 
   if (strcmp ("qSymbol::", own_buf) == 0)
     {
+      struct thread_info *save_thread = current_thread;
+
+      /* For qSymbol, GDB only changes the current thread if the
+        previous current thread was of a different process.  So if
+        the previous thread is gone, we need to pick another one of
+        the same process.  This can happen e.g., if we followed an
+        exec in a non-leader thread.  */
+      if (current_thread == NULL)
+       {
+         current_thread
+           = find_any_thread_of_pid (ptid_get_pid (general_thread));
+
+         /* Just in case, if we didn't find a thread, then bail out
+            instead of crashing.  */
+         if (current_thread == NULL)
+           {
+             write_enn (own_buf);
+             current_thread = save_thread;
+             return;
+           }
+       }
+
       /* GDB is suggesting new symbols have been loaded.  This may
         mean a new shared library has been detected as loaded, so
         take the opportunity to check if breakpoints we think are
@@ -1983,6 +2082,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       if (current_thread != NULL && the_target->look_up_symbols != NULL)
        (*the_target->look_up_symbols) ();
 
+      current_thread = save_thread;
+
       strcpy (own_buf, "OK");
       return;
     }
@@ -2046,9 +2147,6 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       char *p = &own_buf[10];
       int gdb_supports_qRelocInsn = 0;
 
-      /* Start processing qSupported packet.  */
-      target_process_qsupported (NULL);
-
       /* Process each feature being provided by GDB.  The first
         feature will follow a ':', and latter features will follow
         ';'.  */
@@ -2056,6 +2154,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
        {
          char **qsupported = NULL;
          int count = 0;
+         int unknown = 0;
          int i;
 
          /* Two passes, to avoid nested strtok calls in
@@ -2065,7 +2164,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
               p = strtok (NULL, ";"))
            {
              count++;
-             qsupported = xrealloc (qsupported, count * sizeof (char *));
+             qsupported = XRESIZEVEC (char *, qsupported, count);
              qsupported[count - 1] = xstrdup (p);
            }
 
@@ -2111,12 +2210,37 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
                  if (target_supports_vfork_events ())
                    report_vfork_events = 1;
                }
+             else if (strcmp (p, "exec-events+") == 0)
+               {
+                 /* GDB supports and wants exec events if possible.  */
+                 if (target_supports_exec_events ())
+                   report_exec_events = 1;
+               }
+             else if (strcmp (p, "vContSupported+") == 0)
+               vCont_supported = 1;
+             else if (strcmp (p, "QThreadEvents+") == 0)
+               ;
+             else if (strcmp (p, "no-resumed+") == 0)
+               {
+                 /* GDB supports and wants TARGET_WAITKIND_NO_RESUMED
+                    events.  */
+                 report_no_resumed = 1;
+               }
              else
-               target_process_qsupported (p);
-
-             free (p);
+               {
+                 /* Move the unknown features all together.  */
+                 qsupported[i] = NULL;
+                 qsupported[unknown] = p;
+                 unknown++;
+               }
            }
 
+         /* Give the target backend a chance to process the unknown
+            features.  */
+         target_process_qsupported (qsupported, unknown);
+
+         for (i = 0; i < count; i++)
+           free (qsupported[i]);
          free (qsupported);
        }
 
@@ -2124,6 +2248,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
               "PacketSize=%x;QPassSignals+;QProgramSignals+",
               PBUFSIZ - 1);
 
+      if (target_supports_catch_syscall ())
+       strcat (own_buf, ";QCatchSyscalls+");
+
       if (the_target->qxfer_libraries_svr4 != NULL)
        strcat (own_buf, ";qXfer:libraries-svr4:read+"
                ";augmented-libraries-svr4-read+");
@@ -2167,6 +2294,9 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       if (target_supports_vfork_events ())
        strcat (own_buf, ";vfork-events+");
 
+      if (target_supports_exec_events ())
+       strcat (own_buf, ";exec-events+");
+
       if (target_supports_non_stop ())
        strcat (own_buf, ";QNonStop+");
 
@@ -2192,9 +2322,11 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
          strcat (own_buf, ";tracenz+");
        }
 
-      /* Support target-side breakpoint conditions and commands.  */
-      if (target_supports_conditional_breakpoints ())
-       strcat (own_buf, ";ConditionalBreakpoints+");
+      if (target_supports_hardware_single_step ()
+         || target_supports_software_single_step () )
+       {
+         strcat (own_buf, ";ConditionalBreakpoints+");
+       }
       strcat (own_buf, ";BreakpointCommands+");
 
       if (target_supports_agent ())
@@ -2211,6 +2343,12 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
       if (the_target->pid_to_exec_file != NULL)
        strcat (own_buf, ";qXfer:exec-file:read+");
 
+      strcat (own_buf, ";vContSupported+");
+
+      strcat (own_buf, ";QThreadEvents+");
+
+      strcat (own_buf, ";no-resumed+");
+
       /* Reinitialize components as needed for the new connection.  */
       hostio_handle_new_gdb_connection ();
       target_handle_new_gdb_connection ();
@@ -2309,7 +2447,7 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
   /* Handle "monitor" commands.  */
   if (startswith (own_buf, "qRcmd,"))
     {
-      char *mon = malloc (PBUFSIZ);
+      char *mon = (char *) malloc (PBUFSIZ);
       int len = strlen (own_buf + 6);
 
       if (mon == NULL)
@@ -2434,7 +2572,8 @@ struct visit_actioned_threads_data
 static int
 visit_actioned_threads (struct inferior_list_entry *entry, void *datap)
 {
-  struct visit_actioned_threads_data *data = datap;
+  struct visit_actioned_threads_data *data
+    = (struct visit_actioned_threads_data *) datap;
   const struct thread_resume *actions = data->actions;
   size_t num_actions = data->num_actions;
   visit_actioned_threads_callback_ftype *callback = data->callback;
@@ -2480,7 +2619,7 @@ handle_pending_status (const struct thread_resume *resumption,
 }
 
 /* Parse vCont packets.  */
-void
+static void
 handle_v_cont (char *own_buf)
 {
   char *p, *q;
@@ -2498,7 +2637,7 @@ handle_v_cont (char *own_buf)
       p = strchr (p, ';');
     }
 
-  resume_info = malloc (n * sizeof (resume_info[0]));
+  resume_info = (struct thread_resume *) malloc (n * sizeof (resume_info[0]));
   if (resume_info == NULL)
     goto err;
 
@@ -2528,9 +2667,9 @@ handle_v_cont (char *own_buf)
            goto err;
          p = q;
 
-         if (!gdb_signal_to_host_p (sig))
+         if (!gdb_signal_to_host_p ((enum gdb_signal) sig))
            goto err;
-         resume_info[i].sig = gdb_signal_to_host (sig);
+         resume_info[i].sig = gdb_signal_to_host ((enum gdb_signal) sig);
        }
       else if (p[0] == 'r')
        {
@@ -2617,10 +2756,11 @@ resume (struct thread_resume *actions, size_t num_actions)
     {
       last_ptid = mywait (minus_one_ptid, &last_status, 0, 1);
 
-      if (last_status.kind == TARGET_WAITKIND_NO_RESUMED)
+      if (last_status.kind == TARGET_WAITKIND_NO_RESUMED
+         && !report_no_resumed)
        {
-         /* No proper RSP support for this yet.  At least return
-            error.  */
+         /* The client does not support this stop reply.  At least
+            return error.  */
          sprintf (own_buf, "E.No unwaited-for children left.");
          disable_async_io ();
          return;
@@ -2646,7 +2786,7 @@ resume (struct thread_resume *actions, size_t num_actions)
 }
 
 /* Attach to a new program.  Return 1 if successful, 0 if failure.  */
-int
+static int
 handle_v_attach (char *own_buf)
 {
   int pid;
@@ -2693,7 +2833,7 @@ handle_v_run (char *own_buf)
       new_argc++;
     }
 
-  new_argv = calloc (new_argc + 2, sizeof (char *));
+  new_argv = (char **) calloc (new_argc + 2, sizeof (char *));
   if (new_argv == NULL)
     {
       write_enn (own_buf);
@@ -2712,7 +2852,7 @@ handle_v_run (char *own_buf)
       else
        {
          /* FIXME: Fail request if out of memory instead of dying.  */
-         new_argv[i] = xmalloc (1 + (next_p - p) / 2);
+         new_argv[i] = (char *) xmalloc (1 + (next_p - p) / 2);
          hex2bin (p, (gdb_byte *) new_argv[i], (next_p - p) / 2);
          new_argv[i][(next_p - p) / 2] = '\0';
        }
@@ -2769,7 +2909,7 @@ handle_v_run (char *own_buf)
 }
 
 /* Kill process.  Return 1 if successful, 0 if failure.  */
-int
+static int
 handle_v_kill (char *own_buf)
 {
   int pid;
@@ -2800,6 +2940,13 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
 {
   if (!disable_packet_vCont)
     {
+      if (strcmp (own_buf, "vCtrlC") == 0)
+       {
+         (*the_target->request_interrupt) ();
+         write_ok (own_buf);
+         return;
+       }
+
       if (startswith (own_buf, "vCont;"))
        {
          require_running (own_buf);
@@ -2809,7 +2956,18 @@ handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
 
       if (startswith (own_buf, "vCont?"))
        {
-         strcpy (own_buf, "vCont;c;C;s;S;t");
+         strcpy (own_buf, "vCont;c;C;t");
+
+         if (target_supports_hardware_single_step () || !vCont_supported)
+           {
+             /* If target supports hardware single step, add actions s
+                and S to the list of supported actions.  On the other
+                hand, if GDB doesn't request the supported vCont actions
+                in qSupported packet, add s and S to the list too.  */
+             own_buf = own_buf + strlen (own_buf);
+             strcpy (own_buf, ";s;S");
+           }
+
          if (target_supports_range_stepping ())
            {
              own_buf = own_buf + strlen (own_buf);
@@ -2915,7 +3073,7 @@ queue_stop_reply_callback (struct inferior_list_entry *entry, void *arg)
      manage the thread's last_status field.  */
   if (the_target->thread_stopped == NULL)
     {
-      struct vstop_notif *new_notif = xmalloc (sizeof (*new_notif));
+      struct vstop_notif *new_notif = XNEW (struct vstop_notif);
 
       new_notif->ptid = entry->id;
       new_notif->status = thread->last_status;
@@ -3111,7 +3269,7 @@ static void
 gdbserver_version (void)
 {
   printf ("GNU gdbserver %s%s\n"
-         "Copyright (C) 2015 Free Software Foundation, Inc.\n"
+         "Copyright (C) 2016 Free Software Foundation, Inc.\n"
          "gdbserver is free software, covered by the "
          "GNU General Public License.\n"
          "This gdbserver was configured as \"%s\"\n",
@@ -3488,15 +3646,15 @@ captured_main (int argc, char *argv[])
     initialize_tracepoint ();
   initialize_notif ();
 
-  own_buf = xmalloc (PBUFSIZ + 1);
-  mem_buf = xmalloc (PBUFSIZ);
+  own_buf = (char *) xmalloc (PBUFSIZ + 1);
+  mem_buf = (unsigned char *) xmalloc (PBUFSIZ);
 
   if (pid == 0 && *next_arg != NULL)
     {
       int i, n;
 
       n = argc - (next_arg - argv);
-      program_argv = xmalloc (sizeof (char *) * (n + 1));
+      program_argv = XNEWVEC (char *, n + 1);
       for (i = 0; i < n; i++)
        program_argv[i] = xstrdup (next_arg[i]);
       program_argv[i] = NULL;
@@ -3544,11 +3702,13 @@ captured_main (int argc, char *argv[])
       multi_process = 0;
       report_fork_events = 0;
       report_vfork_events = 0;
+      report_exec_events = 0;
       /* Be sure we're out of tfind mode.  */
       current_traceframe = -1;
       cont_thread = null_ptid;
       swbreak_feature = 0;
       hwbreak_feature = 0;
+      vCont_supported = 0;
 
       remote_open (port);
 
@@ -3559,11 +3719,21 @@ captured_main (int argc, char *argv[])
          start_event_loop ();
 
          /* If an exit was requested (using the "monitor exit"
-            command), terminate now.  The only other way to get
-            here is for getpkt to fail; close the connection
-            and reopen it at the top of the loop.  */
+            command), terminate now.  */
+         if (exit_requested)
+           throw_quit ("Quit");
+
+         /* The only other way to get here is for getpkt to fail:
 
-         if (exit_requested || run_once)
+             - If --once was specified, we're done.
+
+             - If not in extended-remote mode, and we're no longer
+               debugging anything, simply exit: GDB has disconnected
+               after processing the last process exit.
+
+             - Otherwise, close the connection and reopen it at the
+               top of the loop.  */
+         if (run_once || (!extended_protocol && !target_running ()))
            throw_quit ("Quit");
 
          fprintf (stderr,
@@ -3650,15 +3820,6 @@ main (int argc, char *argv[])
   gdb_assert_not_reached ("captured_main should never return");
 }
 
-/* Skip PACKET until the next semi-colon (or end of string).  */
-
-static void
-skip_to_semicolon (char **packet)
-{
-  while (**packet != '\0' && **packet != ';')
-    (*packet)++;
-}
-
 /* Process options coming from Z packets for a breakpoint.  PACKET is
    the packet buffer.  *PACKET is updated to point to the first char
    after the last processed option.  */
@@ -3686,7 +3847,7 @@ process_point_options (struct breakpoint *bp, char **packet)
          if (debug_threads)
            debug_printf ("Found breakpoint condition.\n");
          if (!add_breakpoint_condition (bp, &dataptr))
-           skip_to_semicolon (&dataptr);
+           dataptr = strchrnul (dataptr, ';');
        }
       else if (startswith (dataptr, "cmds:"))
        {
@@ -3696,14 +3857,14 @@ process_point_options (struct breakpoint *bp, char **packet)
          persist = (*dataptr == '1');
          dataptr += 2;
          if (add_breakpoint_commands (bp, &dataptr, persist))
-           skip_to_semicolon (&dataptr);
+           dataptr = strchrnul (dataptr, ';');
        }
       else
        {
          fprintf (stderr, "Unknown token %c, ignoring.\n",
                   *dataptr);
          /* Skip tokens until we find one that we recognize.  */
-         skip_to_semicolon (&dataptr);
+         dataptr = strchrnul (dataptr, ';');
        }
     }
   *packet = dataptr;
@@ -3728,13 +3889,6 @@ process_serial_event (void)
   int packet_len;
   int new_packet_len = -1;
 
-  /* Used to decide when gdbserver should exit in
-     multi-mode/remote.  */
-  static int have_ran = 0;
-
-  if (!have_ran)
-    have_ran = target_running ();
-
   disable_async_io ();
 
   response_needed = 0;
@@ -3824,9 +3978,11 @@ process_serial_event (void)
          discard_queued_stop_replies (pid_to_ptid (pid));
          write_ok (own_buf);
 
-         if (extended_protocol)
+         if (extended_protocol || target_running ())
            {
-             /* Treat this like a normal program exit.  */
+             /* There is still at least one inferior remaining or
+                we are in extended mode, so don't terminate gdbserver,
+                and instead treat this like a normal program exit.  */
              last_status.kind = TARGET_WAITKIND_EXITED;
              last_status.value.integer = 0;
              last_ptid = pid_to_ptid (pid);
@@ -3999,8 +4155,8 @@ process_serial_event (void)
     case 'C':
       require_running (own_buf);
       hex2bin (own_buf + 1, &sig, 1);
-      if (gdb_signal_to_host_p (sig))
-       signal = gdb_signal_to_host (sig);
+      if (gdb_signal_to_host_p ((enum gdb_signal) sig))
+       signal = gdb_signal_to_host ((enum gdb_signal) sig);
       else
        signal = 0;
       myresume (own_buf, 0, signal);
@@ -4008,8 +4164,8 @@ process_serial_event (void)
     case 'S':
       require_running (own_buf);
       hex2bin (own_buf + 1, &sig, 1);
-      if (gdb_signal_to_host_p (sig))
-       signal = gdb_signal_to_host (sig);
+      if (gdb_signal_to_host_p ((enum gdb_signal) sig))
+       signal = gdb_signal_to_host ((enum gdb_signal) sig);
       else
        signal = 0;
       myresume (own_buf, 1, signal);
@@ -4030,20 +4186,20 @@ process_serial_event (void)
       {
        char *dataptr;
        ULONGEST addr;
-       int len;
+       int kind;
        char type = own_buf[1];
        int res;
        const int insert = ch == 'Z';
        char *p = &own_buf[3];
 
        p = unpack_varlen_hex (p, &addr);
-       len = strtol (p + 1, &dataptr, 16);
+       kind = strtol (p + 1, &dataptr, 16);
 
        if (insert)
          {
            struct breakpoint *bp;
 
-           bp = set_gdb_breakpoint (type, addr, len, &res);
+           bp = set_gdb_breakpoint (type, addr, kind, &res);
            if (bp != NULL)
              {
                res = 0;
@@ -4058,7 +4214,7 @@ process_serial_event (void)
              }
          }
        else
-         res = delete_gdb_breakpoint (type, addr, len);
+         res = delete_gdb_breakpoint (type, addr, kind);
 
        if (res == 0)
          write_ok (own_buf);
@@ -4173,21 +4329,6 @@ process_serial_event (void)
 
   response_needed = 0;
 
-  if (!extended_protocol && have_ran && !target_running ())
-    {
-      /* In non-stop, defer exiting until GDB had a chance to query
-        the whole vStopped list (until it gets an OK).  */
-      if (QUEUE_is_empty (notif_event_p, notif_stop.queue))
-       {
-         /* Be transparent when GDB is connected through stdio -- no
-            need to spam GDB's console.  */
-         if (!remote_connection_is_stdio ())
-           fprintf (stderr, "GDBserver exiting\n");
-         remote_close ();
-         exit (0);
-       }
-    }
-
   if (exit_requested)
     return -1;
 
@@ -4213,6 +4354,19 @@ handle_serial_event (int err, gdb_client_data client_data)
   return 0;
 }
 
+/* Push a stop notification on the notification queue.  */
+
+static void
+push_stop_notification (ptid_t ptid, struct target_waitstatus *status)
+{
+  struct vstop_notif *vstop_notif = XNEW (struct vstop_notif);
+
+  vstop_notif->status = *status;
+  vstop_notif->ptid = ptid;
+  /* Push Stop notification.  */
+  notif_push (&notif_stop, (struct notif_event *) vstop_notif);
+}
+
 /* Event-loop callback for target events.  */
 
 int
@@ -4226,7 +4380,8 @@ handle_target_event (int err, gdb_client_data client_data)
 
   if (last_status.kind == TARGET_WAITKIND_NO_RESUMED)
     {
-      /* No RSP support for this yet.  */
+      if (gdb_connected () && report_no_resumed)
+       push_stop_notification (null_ptid, &last_status);
     }
   else if (last_status.kind != TARGET_WAITKIND_IGNORE)
     {
@@ -4240,6 +4395,8 @@ handle_target_event (int err, gdb_client_data client_data)
          mark_breakpoints_out (process);
          mourn_inferior (process);
        }
+      else if (last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
+       ;
       else
        {
          /* We're reporting this thread as stopped.  Update its
@@ -4257,7 +4414,11 @@ handle_target_event (int err, gdb_client_data client_data)
              exit (0);
            }
 
-         if (last_status.kind == TARGET_WAITKIND_STOPPED)
+         if (last_status.kind == TARGET_WAITKIND_EXITED
+             || last_status.kind == TARGET_WAITKIND_SIGNALLED
+             || last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
+           ;
+         else
            {
              /* A thread stopped with a signal, but gdb isn't
                 connected to handle it.  Pass it down to the
@@ -4272,25 +4433,15 @@ handle_target_event (int err, gdb_client_data client_data)
 
              resume_info.thread = last_ptid;
              resume_info.kind = resume_continue;
-             resume_info.sig = gdb_signal_to_host (last_status.value.sig);
+             if (last_status.kind == TARGET_WAITKIND_STOPPED)
+               resume_info.sig = gdb_signal_to_host (last_status.value.sig);
+             else
+               resume_info.sig = 0;
              (*the_target->resume) (&resume_info, 1);
            }
-         else if (debug_threads)
-           debug_printf ("GDB not connected; ignoring event %d for [%s]\n",
-                         (int) last_status.kind,
-                         target_pid_to_str (last_ptid));
        }
       else
-       {
-         struct vstop_notif *vstop_notif
-           = xmalloc (sizeof (struct vstop_notif));
-
-         vstop_notif->status = last_status;
-         vstop_notif->ptid = last_ptid;
-         /* Push Stop notification.  */
-         notif_push (&notif_stop,
-                     (struct notif_event *) vstop_notif);
-       }
+       push_stop_notification (last_ptid, &last_status);
     }
 
   /* Be sure to not change the selected thread behind GDB's back.
This page took 0.03935 seconds and 4 git commands to generate.