gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / remote.c
index 7453a3b31a7bff7ba90adf3c2c346bae0e6d70e9..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.  */
 
@@ -406,6 +407,8 @@ public:
   const target_info &info () const override
   { return remote_target_info; }
 
+  const char *connection_string () override;
+
   thread_control_capabilities get_thread_control_capabilities () override
   { return tc_schedlock; }
 
@@ -672,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;
@@ -2409,6 +2412,9 @@ remote_target::remote_add_inferior (bool fake_pid_p, int pid, int attached,
   if (try_open_exec && get_exec_file (0) == NULL)
     exec_file_locate_attach (pid, 0, 1);
 
+  /* Check for exec file mismatch, and let the user solve it.  */
+  validate_exec_file (1);
+
   return inf;
 }
 
@@ -2609,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
@@ -3779,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.  */
 
@@ -3818,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);
            }
@@ -4079,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;
@@ -4159,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;
 
@@ -4172,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
@@ -4183,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.  */
@@ -4194,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 "
@@ -4205,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;
@@ -4444,8 +4467,8 @@ remote_target::process_initial_stop_replies (int from_tty)
          || ws.value.sig != GDB_SIGNAL_0)
        evthread->suspend.waitstatus_pending_p = 1;
 
-      set_executing (this, event_ptid, 0);
-      set_running (this, event_ptid, 0);
+      set_executing (this, event_ptid, false);
+      set_running (this, event_ptid, false);
       get_remote_thread_info (evthread)->vcont_resumed = 0;
     }
 
@@ -4853,6 +4876,17 @@ remote_target::start_remote (int from_tty, int extended_p)
     insert_breakpoints ();
 }
 
+const char *
+remote_target::connection_string ()
+{
+  remote_state *rs = get_remote_state ();
+
+  if (rs->remote_desc->name != NULL)
+    return rs->remote_desc->name;
+  else
+    return NULL;
+}
+
 /* Open a connection to a remote debugger.
    NAME is the filename used for communication.  */
 
@@ -5750,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;
@@ -5777,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
@@ -6829,9 +6864,9 @@ remote_console_output (const char *msg)
 
       tb[0] = c;
       tb[1] = 0;
-      fputs_unfiltered (tb, gdb_stdtarg);
+      gdb_stdtarg->puts (tb);
     }
-  gdb_flush (gdb_stdtarg);
+  gdb_stdtarg->flush ();
 }
 
 struct stop_reply : public notif_event
@@ -7386,18 +7421,14 @@ Packet: '%s'\n"),
                     reported expedited registers.  */
                  if (event->ptid == null_ptid)
                    {
+                     /* If there is no thread-id information then leave
+                        the event->ptid as null_ptid.  Later in
+                        process_stop_reply we will pick a suitable
+                        thread.  */
                      const char *thr = strstr (p1 + 1, ";thread:");
                      if (thr != NULL)
                        event->ptid = read_ptid (thr + strlen (";thread:"),
                                                 NULL);
-                     else
-                       {
-                         /* Either the current thread hasn't changed,
-                            or the inferior is not multi-threaded.
-                            The event must be for the thread we last
-                            set as (or learned as being) current.  */
-                         event->ptid = event->rs->general_thread;
-                       }
                    }
 
                  if (rsa == NULL)
@@ -7548,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
@@ -7652,10 +7680,61 @@ remote_target::process_stop_reply (struct stop_reply *stop_reply,
   *status = stop_reply->ws;
   ptid = stop_reply->ptid;
 
-  /* If no thread/process was reported by the stub, assume the current
-     inferior.  */
+  /* If no thread/process was reported by the stub then use the first
+     non-exited thread in the current target.  */
   if (ptid == null_ptid)
-    ptid = inferior_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
+             && (!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 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;
+           }
+
+         /* 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);
+    }
 
   if (status->kind != TARGET_WAITKIND_EXITED
       && status->kind != TARGET_WAITKIND_SIGNALLED
@@ -12638,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 ()
 {
@@ -12798,7 +12871,7 @@ remote_target::download_tracepoint (struct bp_location *loc)
   encode_actions_rsp (loc, &tdp_actions, &stepping_actions);
 
   tpaddr = loc->address;
-  sprintf_vma (addrbuf, tpaddr);
+  strcpy (addrbuf, phex (tpaddr, sizeof (CORE_ADDR)));
   ret = snprintf (buf.data (), buf.size (), "QTDP:%x:%s:%c:%lx:%x",
                  b->number, addrbuf, /* address */
                  (b->enable_state == bp_enabled ? 'E' : 'D'),
@@ -13060,11 +13133,10 @@ void
 remote_target::enable_tracepoint (struct bp_location *location)
 {
   struct remote_state *rs = get_remote_state ();
-  char addr_buf[40];
 
-  sprintf_vma (addr_buf, location->address);
   xsnprintf (rs->buf.data (), get_remote_packet_size (), "QTEnable:%x:%s",
-            location->owner->number, addr_buf);
+            location->owner->number,
+            phex (location->address, sizeof (CORE_ADDR)));
   putpkt (rs->buf);
   remote_get_noisy_reply ();
   if (rs->buf[0] == '\0')
@@ -13077,11 +13149,10 @@ void
 remote_target::disable_tracepoint (struct bp_location *location)
 {
   struct remote_state *rs = get_remote_state ();
-  char addr_buf[40];
 
-  sprintf_vma (addr_buf, location->address);
   xsnprintf (rs->buf.data (), get_remote_packet_size (), "QTDisable:%x:%s",
-            location->owner->number, addr_buf);
+            location->owner->number,
+            phex (location->address, sizeof (CORE_ADDR)));
   putpkt (rs->buf);
   remote_get_noisy_reply ();
   if (rs->buf[0] == '\0')
@@ -14164,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)
 {
@@ -14299,8 +14364,9 @@ set_range_stepping (const char *ignore_args, int from_tty,
     }
 }
 
+void _initialize_remote ();
 void
-_initialize_remote (void)
+_initialize_remote ()
 {
   struct cmd_list_element *cmd;
   const char *cmd_name;
@@ -14321,12 +14387,12 @@ _initialize_remote (void)
 
   /* 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\
@@ -14747,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."),
@@ -14807,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.043739 seconds and 4 git commands to generate.