gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / remote.c
index 0f78b1be1b50e5a5b548481d35b15abad8a41cbb..c73eb6e9e136f4d611aeb631b3641ceda5b238b1 100644 (file)
@@ -49,7 +49,7 @@
 
 #include "gdbsupport/gdb_sys_time.h"
 
-#include "event-loop.h"
+#include "gdbsupport/event-loop.h"
 #include "event-top.h"
 #include "inf-loop.h"
 
@@ -77,6 +77,7 @@
 #include "gdbsupport/byte-vector.h"
 #include <algorithm>
 #include <unordered_map>
+#include "async-event.h"
 
 /* The remote target.  */
 
@@ -674,7 +675,7 @@ public:
 
   const struct btrace_config *btrace_conf (const struct btrace_target_info *) override;
   bool augmented_libraries_svr4_read () override;
-  int follow_fork (int, int) override;
+  bool follow_fork (bool, bool) override;
   void follow_exec (struct inferior *, const char *) override;
   int insert_fork_catchpoint (int) override;
   int remove_fork_catchpoint (int) override;
@@ -2614,8 +2615,7 @@ remote_target::pass_signals (gdb::array_view<const unsigned char> pass_signals)
          putpkt (pass_packet);
          getpkt (&rs->buf, 0);
          packet_ok (rs->buf, &remote_protocol_packets[PACKET_QPassSignals]);
-         if (rs->last_pass_packet)
-           xfree (rs->last_pass_packet);
+         xfree (rs->last_pass_packet);
          rs->last_pass_packet = pass_packet;
        }
       else
@@ -3784,6 +3784,18 @@ remote_target::remote_get_threads_with_qthreadinfo (threads_listing_context *con
   return 0;
 }
 
+/* Return true if INF only has one non-exited thread.  */
+
+static bool
+has_single_non_exited_thread (inferior *inf)
+{
+  int count = 0;
+  for (thread_info *tp ATTRIBUTE_UNUSED : inf->non_exited_threads ())
+    if (++count > 1)
+      break;
+  return count == 1;
+}
+
 /* Implement the to_update_thread_list function for the remote
    targets.  */
 
@@ -3823,6 +3835,14 @@ remote_target::update_thread_list ()
 
          if (!context.contains_thread (tp->ptid))
            {
+             /* Do not remove the thread if it is the last thread in
+                the inferior.  This situation happens when we have a
+                pending exit process status to process.  Otherwise we
+                may end up with a seemingly live inferior (i.e.  pid
+                != 0) that has no threads.  */
+             if (has_single_non_exited_thread (tp->inf))
+               continue;
+
              /* Not found.  */
              delete_thread (tp);
            }
@@ -4084,7 +4104,6 @@ remote_target::get_offsets ()
   char *ptr;
   int lose, num_segments = 0, do_sections, do_segments;
   CORE_ADDR text_addr, data_addr, bss_addr, segments[2];
-  struct symfile_segment_data *data;
 
   if (symfile_objfile == NULL)
     return;
@@ -4164,7 +4183,8 @@ remote_target::get_offsets ()
 
   section_offsets offs = symfile_objfile->section_offsets;
 
-  data = get_symfile_segment_data (symfile_objfile->obfd);
+  symfile_segment_data_up data
+    = get_symfile_segment_data (symfile_objfile->obfd);
   do_segments = (data != NULL);
   do_sections = num_segments == 0;
 
@@ -4177,10 +4197,10 @@ remote_target::get_offsets ()
      by assuming that the .text and .data offsets apply to the whole
      text and data segments.  Convert the offsets given in the packet
      to base addresses for symfile_map_offsets_to_segments.  */
-  else if (data && data->num_segments == 2)
+  else if (data != nullptr && data->segments.size () == 2)
     {
-      segments[0] = data->segment_bases[0] + text_addr;
-      segments[1] = data->segment_bases[1] + data_addr;
+      segments[0] = data->segments[0].base + text_addr;
+      segments[1] = data->segments[1].base + data_addr;
       num_segments = 2;
     }
   /* If the object file has only one segment, assume that it is text
@@ -4188,9 +4208,9 @@ remote_target::get_offsets ()
      but programs with no code are useless.  Of course the code might
      have ended up in the data segment... to detect that we would need
      the permissions here.  */
-  else if (data && data->num_segments == 1)
+  else if (data && data->segments.size () == 1)
     {
-      segments[0] = data->segment_bases[0] + text_addr;
+      segments[0] = data->segments[0].base + text_addr;
       num_segments = 1;
     }
   /* There's no way to relocate by segment.  */
@@ -4199,8 +4219,9 @@ remote_target::get_offsets ()
 
   if (do_segments)
     {
-      int ret = symfile_map_offsets_to_segments (symfile_objfile->obfd, data,
-                                                offs, num_segments, segments);
+      int ret = symfile_map_offsets_to_segments (symfile_objfile->obfd,
+                                                data.get (), offs,
+                                                num_segments, segments);
 
       if (ret == 0 && !do_sections)
        error (_("Can not handle qOffsets TextSeg "
@@ -4210,9 +4231,6 @@ remote_target::get_offsets ()
        do_sections = 0;
     }
 
-  if (data)
-    free_symfile_segment_data (data);
-
   if (do_sections)
     {
       offs[SECT_OFF_TEXT (symfile_objfile)] = text_addr;
@@ -5766,8 +5784,8 @@ extended_remote_target::detach (inferior *inf, int from_tty)
    it is named remote_follow_fork in anticipation of using it for the
    remote target as well.  */
 
-int
-remote_target::follow_fork (int follow_child, int detach_fork)
+bool
+remote_target::follow_fork (bool follow_child, bool detach_fork)
 {
   struct remote_state *rs = get_remote_state ();
   enum target_waitkind kind = inferior_thread ()->pending_follow.kind;
@@ -5793,7 +5811,8 @@ remote_target::follow_fork (int follow_child, int detach_fork)
          remote_detach_pid (child_pid);
        }
     }
-  return 0;
+
+  return false;
 }
 
 /* Target follow-exec function for remote targets.  Save EXECD_PATHNAME
@@ -7560,9 +7579,6 @@ Packet: '%s'\n"),
       event->ptid = minus_one_ptid;
       break;
     }
-
-  if (target_is_non_stop_p () && event->ptid == null_ptid)
-    error (_("No process or thread specified in stop reply: %s"), buf);
 }
 
 /* When the stub wants to tell GDB about a new notification reply, it
@@ -7668,28 +7684,54 @@ remote_target::process_stop_reply (struct stop_reply *stop_reply,
      non-exited thread in the current target.  */
   if (ptid == null_ptid)
     {
+      /* Some stop events apply to all threads in an inferior, while others
+        only apply to a single thread.  */
+      bool is_stop_for_all_threads
+       = (status->kind == TARGET_WAITKIND_EXITED
+          || status->kind == TARGET_WAITKIND_SIGNALLED);
+
       for (thread_info *thr : all_non_exited_threads (this))
        {
-         if (ptid != null_ptid)
+         if (ptid != null_ptid
+             && (!is_stop_for_all_threads
+                 || ptid.pid () != thr->ptid.pid ()))
            {
              static bool warned = false;
 
              if (!warned)
                {
                  /* If you are seeing this warning then the remote target
-                    has multiple threads and either sent an 'S' stop
-                    packet, or a 'T' stop packet without a thread-id.  In
-                    both of these cases GDB is unable to know which thread
-                    just stopped and is now having to guess.  The correct
-                    action is to fix the remote target to send the correct
-                    packet (a 'T' packet and include a thread-id).  */
-                 warning (_("multi-threaded target stopped without sending "
-                            "a thread-id, using first non-exited thread"));
+                    has stopped without specifying a thread-id, but the
+                    target does have multiple threads (or inferiors), and
+                    so GDB is having to guess which thread stopped.
+
+                    Examples of what might cause this are the target
+                    sending and 'S' stop packet, or a 'T' stop packet and
+                    not including a thread-id.
+
+                    Additionally, the target might send a 'W' or 'X
+                    packet without including a process-id, when the target
+                    has multiple running inferiors.  */
+                 if (is_stop_for_all_threads)
+                   warning (_("multi-inferior target stopped without "
+                              "sending a process-id, using first "
+                              "non-exited inferior"));
+                 else
+                   warning (_("multi-threaded target stopped without "
+                              "sending a thread-id, using first "
+                              "non-exited thread"));
                  warned = true;
                }
              break;
            }
-         ptid = thr->ptid;
+
+         /* If this is a stop for all threads then don't use a particular
+            threads ptid, instead create a new ptid where only the pid
+            field is set.  */
+         if (is_stop_for_all_threads)
+           ptid = ptid_t (thr->ptid.pid ());
+         else
+           ptid = thr->ptid;
        }
       gdb_assert (ptid != null_ptid);
     }
@@ -12675,12 +12717,6 @@ remote_delete_command (const char *args, int from_tty)
   remote_file_delete (argv[0], from_tty);
 }
 
-static void
-remote_command (const char *args, int from_tty)
-{
-  help_list (remote_cmdlist, "remote ", all_commands, gdb_stdout);
-}
-
 bool
 remote_target::can_execute_reverse ()
 {
@@ -14199,12 +14235,6 @@ remote_target::thread_events (int enable)
     }
 }
 
-static void
-set_remote_cmd (const char *args, int from_tty)
-{
-  help_list (remote_set_cmdlist, "set remote ", all_commands, gdb_stdout);
-}
-
 static void
 show_remote_cmd (const char *args, int from_tty)
 {
@@ -14357,12 +14387,12 @@ _initialize_remote ()
 
   /* set/show remote ...  */
 
-  add_prefix_cmd ("remote", class_maintenance, set_remote_cmd, _("\
+  add_basic_prefix_cmd ("remote", class_maintenance, _("\
 Remote protocol specific variables.\n\
 Configure various remote-protocol specific variables such as\n\
 the packets being used."),
-                 &remote_set_cmdlist, "set remote ",
-                 0 /* allow-unknown */, &setlist);
+                       &remote_set_cmdlist, "set remote ",
+                       0 /* allow-unknown */, &setlist);
   add_prefix_cmd ("remote", class_maintenance, show_remote_cmd, _("\
 Remote protocol specific variables.\n\
 Configure various remote-protocol specific variables such as\n\
@@ -14783,11 +14813,11 @@ packets."),
                                   `Z' packets is %s.  */
                                &remote_set_cmdlist, &remote_show_cmdlist);
 
-  add_prefix_cmd ("remote", class_files, remote_command, _("\
+  add_basic_prefix_cmd ("remote", class_files, _("\
 Manipulate files on the remote system.\n\
 Transfer files to and from the remote target system."),
-                 &remote_cmdlist, "remote ",
-                 0 /* allow-unknown */, &cmdlist);
+                       &remote_cmdlist, "remote ",
+                       0 /* allow-unknown */, &cmdlist);
 
   add_cmd ("put", class_files, remote_put_command,
           _("Copy a local file to the remote system."),
@@ -14843,5 +14873,5 @@ Specify \"unlimited\" to display all the characters."),
                                       &setdebuglist, &showdebuglist);
 
   /* Eventually initialize fileio.  See fileio.c */
-  initialize_remote_fileio (remote_set_cmdlist, remote_show_cmdlist);
+  initialize_remote_fileio (&remote_set_cmdlist, &remote_show_cmdlist);
 }
This page took 0.030999 seconds and 4 git commands to generate.