* gas/mips/mips.exp (run_dump_test_arch): Check for the presence
[deliverable/binutils-gdb.git] / gdb / remote.c
index ca3aad6ffa9761f073afae3946d6afa2d250fbfe..68e5678bf79a9724097a5433151bc49669897b97 100644 (file)
@@ -212,6 +212,8 @@ static void show_remote_protocol_packet_cmd (struct ui_file *file,
 static char *write_ptid (char *buf, const char *endbuf, ptid_t ptid);
 static ptid_t read_ptid (char *buf, char **obuf);
 
+static void remote_set_permissions (void);
+
 struct remote_state;
 static int remote_get_trace_status (struct trace_status *ts);
 
@@ -320,6 +322,9 @@ struct remote_state
   /* True if the stub reports support for fast tracepoints.  */
   int fast_tracepoints;
 
+  /* True if the stub reports support for static tracepoints.  */
+  int static_tracepoints;
+
   /* True if the stub can continue running a trace while GDB is
      disconnected.  */
   int disconnected_tracing;
@@ -446,7 +451,7 @@ remote_get_noisy_reply (char **buf_p,
          p = buf + strlen ("qRelocInsn:");
          pp = unpack_varlen_hex (p, &ul);
          if (*pp != ';')
-           error (_("invalid qRelocInsn packet: %s\n"), buf);
+           error (_("invalid qRelocInsn packet: %s"), buf);
          from = ul;
 
          p = pp + 1;
@@ -1196,6 +1201,7 @@ enum {
   PACKET_qXfer_spu_write,
   PACKET_qXfer_osdata,
   PACKET_qXfer_threads,
+  PACKET_qXfer_statictrace_read,
   PACKET_qGetTIBAddr,
   PACKET_qGetTLSAddr,
   PACKET_qSupported,
@@ -1210,9 +1216,11 @@ enum {
   PACKET_qAttached,
   PACKET_ConditionalTracepoints,
   PACKET_FastTracepoints,
+  PACKET_StaticTracepoints,
   PACKET_bc,
   PACKET_bs,
   PACKET_TracepointSource,
+  PACKET_QAllow,
   PACKET_MAX
 };
 
@@ -2345,7 +2353,7 @@ remote_get_threadlist (int startflag, threadref *nextthread, int result_limit,
   getpkt (&rs->buf, &rs->buf_size, 0);
 
   if (*rs->buf == '\0')
-    *result_count = 0;
+    return 0;
   else
     *result_count =
       parse_threadlist_response (rs->buf + 2, result_limit, &echo_nextthread,
@@ -2769,6 +2777,98 @@ remote_threads_extra_info (struct thread_info *tp)
 }
 \f
 
+static int
+remote_static_tracepoint_marker_at (CORE_ADDR addr,
+                                   struct static_tracepoint_marker *marker)
+{
+  struct remote_state *rs = get_remote_state ();
+  char *p = rs->buf;
+
+  sprintf (p, "qTSTMat:");
+  p += strlen (p);
+  p += hexnumstr (p, addr);
+  putpkt (rs->buf);
+  getpkt (&rs->buf, &rs->buf_size, 0);
+  p = rs->buf;
+
+  if (*p == 'E')
+    error (_("Remote failure reply: %s"), p);
+
+  if (*p++ == 'm')
+    {
+      parse_static_tracepoint_marker_definition (p, &p, marker);
+      return 1;
+    }
+
+  return 0;
+}
+
+static void
+free_current_marker (void *arg)
+{
+  struct static_tracepoint_marker **marker_p = arg;
+
+  if (*marker_p != NULL)
+    {
+      release_static_tracepoint_marker (*marker_p);
+      xfree (*marker_p);
+    }
+  else
+    *marker_p = NULL;
+}
+
+static VEC(static_tracepoint_marker_p) *
+remote_static_tracepoint_markers_by_strid (const char *strid)
+{
+  struct remote_state *rs = get_remote_state ();
+  VEC(static_tracepoint_marker_p) *markers = NULL;
+  struct static_tracepoint_marker *marker = NULL;
+  struct cleanup *old_chain;
+  char *p;
+
+  /* Ask for a first packet of static tracepoint marker
+     definition.  */
+  putpkt ("qTfSTM");
+  getpkt (&rs->buf, &rs->buf_size, 0);
+  p = rs->buf;
+  if (*p == 'E')
+    error (_("Remote failure reply: %s"), p);
+
+  old_chain = make_cleanup (free_current_marker, &marker);
+
+  while (*p++ == 'm')
+    {
+      if (marker == NULL)
+       marker = XCNEW (struct static_tracepoint_marker);
+
+      do
+       {
+         parse_static_tracepoint_marker_definition (p, &p, marker);
+
+         if (strid == NULL || strcmp (strid, marker->str_id) == 0)
+           {
+             VEC_safe_push (static_tracepoint_marker_p,
+                            markers, marker);
+             marker = NULL;
+           }
+         else
+           {
+             release_static_tracepoint_marker (marker);
+             memset (marker, 0, sizeof (*marker));
+           }
+       }
+      while (*p++ == ',');     /* comma-separated list */
+      /* Ask for another packet of static tracepoint definition.  */
+      putpkt ("qTsSTM");
+      getpkt (&rs->buf, &rs->buf_size, 0);
+      p = rs->buf;
+    }
+
+  do_cleanups (old_chain);
+  return markers;
+}
+
+\f
 /* Implement the to_get_ada_task_ptid function for the remote targets.  */
 
 static ptid_t
@@ -2811,6 +2911,7 @@ remote_close (int quitting)
   /* We don't have a connection to the remote stub anymore.  Get rid
      of all the inferiors and their threads we were controlling.  */
   discard_all_inferiors ();
+  inferior_ptid = null_ptid;
 
   /* We're no longer interested in any of these events.  */
   discard_pending_stop_replies (-1);
@@ -3046,6 +3147,10 @@ remote_start_remote (struct ui_out *uiout, void *opaque)
      which later probes to skip.  */
   remote_query_supported ();
 
+  /* If the stub wants to get a QAllow, compose one and send it.  */
+  if (remote_protocol_packets[PACKET_QAllow].support != PACKET_DISABLE)
+    remote_set_permissions ();
+
   /* Next, we possibly activate noack mode.
 
      If the QStartNoAckMode packet configuration is set to AUTO,
@@ -3392,6 +3497,36 @@ Some events may be lost, rendering further debugging impossible."));
   return serial_open (name);
 }
 
+/* Inform the target of our permission settings.  The permission flags
+   work without this, but if the target knows the settings, it can do
+   a couple things.  First, it can add its own check, to catch cases
+   that somehow manage to get by the permissions checks in target
+   methods.  Second, if the target is wired to disallow particular
+   settings (for instance, a system in the field that is not set up to
+   be able to stop at a breakpoint), it can object to any unavailable
+   permissions.  */
+
+void
+remote_set_permissions (void)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  sprintf (rs->buf, "QAllow:"
+          "WriteReg:%x;WriteMem:%x;"
+          "InsertBreak:%x;InsertTrace:%x;"
+          "InsertFastTrace:%x;Stop:%x",
+          may_write_registers, may_write_memory,
+          may_insert_breakpoints, may_insert_tracepoints,
+          may_insert_fast_tracepoints, may_stop);
+  putpkt (rs->buf);
+  getpkt (&rs->buf, &rs->buf_size, 0);
+
+  /* If the target didn't like the packet, warn the user.  Do not try
+     to undo the user's settings, that would just be maddening.  */
+  if (strcmp (rs->buf, "OK") != 0)
+    warning ("Remote refused setting permissions with: %s", rs->buf);
+}
+
 /* This type describes each known response to the qSupported
    packet.  */
 struct protocol_feature
@@ -3513,6 +3648,16 @@ remote_fast_tracepoint_feature (const struct protocol_feature *feature,
   rs->fast_tracepoints = (support == PACKET_ENABLE);
 }
 
+static void
+remote_static_tracepoint_feature (const struct protocol_feature *feature,
+                                 enum packet_support support,
+                                 const char *value)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  rs->static_tracepoints = (support == PACKET_ENABLE);
+}
+
 static void
 remote_disconnected_tracing_feature (const struct protocol_feature *feature,
                                     enum packet_support support,
@@ -3555,6 +3700,8 @@ static struct protocol_feature remote_protocol_features[] = {
     PACKET_ConditionalTracepoints },
   { "FastTracepoints", PACKET_DISABLE, remote_fast_tracepoint_feature,
     PACKET_FastTracepoints },
+  { "StaticTracepoints", PACKET_DISABLE, remote_static_tracepoint_feature,
+    PACKET_StaticTracepoints },
   { "DisconnectedTracing", PACKET_DISABLE, remote_disconnected_tracing_feature,
     -1 },
   { "ReverseContinue", PACKET_DISABLE, remote_supported_packet,
@@ -3563,6 +3710,8 @@ static struct protocol_feature remote_protocol_features[] = {
     PACKET_bs },
   { "TracepointSource", PACKET_DISABLE, remote_supported_packet,
     PACKET_TracepointSource },
+  { "QAllow", PACKET_DISABLE, remote_supported_packet,
+    PACKET_QAllow },
 };
 
 static char *remote_support_xml;
@@ -4267,6 +4416,12 @@ append_resumption (char *p, char *endp,
   return p;
 }
 
+static int
+currently_stepping_callback (struct thread_info *tp, void *data)
+{
+  return currently_stepping (tp);
+}
+
 /* Resume the remote inferior by using a "vCont" packet.  The thread
    to be resumed is PTID; STEP and SIGGNAL indicate whether the
    resumed thread should be single-stepped and/or signalled.  If PTID
@@ -4309,6 +4464,8 @@ remote_vcont_resume (ptid_t ptid, int step, enum target_signal siggnal)
     }
   else if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid))
     {
+      struct thread_info *tp;
+
       /* Resume all threads (of all processes, or of a single
         process), with preference for INFERIOR_PTID.  This assumes
         inferior_ptid belongs to the set of all threads we are about
@@ -4319,6 +4476,12 @@ remote_vcont_resume (ptid_t ptid, int step, enum target_signal siggnal)
          p = append_resumption (p, endp, inferior_ptid, step, siggnal);
        }
 
+      tp = iterate_over_threads (currently_stepping_callback, NULL);
+      if (tp && !ptid_equal (tp->ptid, inferior_ptid))
+       {
+         p = append_resumption (p, endp, tp->ptid, 1, TARGET_SIGNAL_0);
+       }
+
       /* And continue others without a signal.  */
       p = append_resumption (p, endp, ptid, /*step=*/ 0, TARGET_SIGNAL_0);
     }
@@ -6518,7 +6681,8 @@ readchar (int timeout)
       error (_("Remote connection closed"));
       /* no return */
     case SERIAL_ERROR:
-      perror_with_name (_("Remote communication error"));
+      pop_target ();
+      perror_with_name (_("Remote communication error.  Target disconnected."));
       /* no return */
     case SERIAL_TIMEOUT:
       break;
@@ -7497,7 +7661,8 @@ watchpoint_to_Z_packet (int type)
 }
 
 static int
-remote_insert_watchpoint (CORE_ADDR addr, int len, int type)
+remote_insert_watchpoint (CORE_ADDR addr, int len, int type,
+                         struct expression *cond)
 {
   struct remote_state *rs = get_remote_state ();
   char *p;
@@ -7530,7 +7695,8 @@ remote_insert_watchpoint (CORE_ADDR addr, int len, int type)
 
 
 static int
-remote_remove_watchpoint (CORE_ADDR addr, int len, int type)
+remote_remove_watchpoint (CORE_ADDR addr, int len, int type,
+                         struct expression *cond)
 {
   struct remote_state *rs = get_remote_state ();
   char *p;
@@ -8006,6 +8172,16 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object,
                                   [PACKET_qXfer_siginfo_write]);
     }
 
+  if (object == TARGET_OBJECT_STATIC_TRACE_DATA)
+    {
+      if (readbuf)
+       return remote_read_qxfer (ops, "statictrace", annex, readbuf, offset, len,
+                                 &remote_protocol_packets
+                                 [PACKET_qXfer_statictrace_read]);
+      else
+       return -1;
+    }
+
   /* Only handle flash writes.  */
   if (writebuf != NULL)
     {
@@ -9438,6 +9614,14 @@ remote_supports_fast_tracepoints (void)
   return rs->fast_tracepoints;
 }
 
+static int
+remote_supports_static_tracepoints (void)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  return rs->static_tracepoints;
+}
+
 static void
 remote_trace_init (void)
 {
@@ -9566,6 +9750,25 @@ remote_download_tracepoint (struct breakpoint *t)
               give up on the trace run.  */
            warning (_("Target does not support fast tracepoints, downloading %d as regular tracepoint"), t->number);
        }
+      else if (t->type == bp_static_tracepoint)
+       {
+         /* Only test for support at download time; we may not know
+            target capabilities at definition time.  */
+         if (remote_supports_static_tracepoints ())
+           {
+             struct static_tracepoint_marker marker;
+
+             if (target_static_tracepoint_marker_at (tpaddr, &marker))
+               strcat (buf, ":S");
+             else
+               error (_("Static tracepoint not valid during download"));
+           }
+         else
+           /* Fast tracepoints are functionally identical to regular
+              tracepoints, so don't take lack of support as a reason
+              to give up on the trace run.  */
+           error (_("Target does not support static tracepoints"));
+       }
       /* If the tracepoint has a conditional, make it into an agent
         expression and append to the definition.  */
       if (loc->cond)
@@ -10060,6 +10263,11 @@ Specify the serial device it is connected to\n\
   remote_ops.to_core_of_thread = remote_core_of_thread;
   remote_ops.to_verify_memory = remote_verify_memory;
   remote_ops.to_get_tib_address = remote_get_tib_address;
+  remote_ops.to_set_permissions = remote_set_permissions;
+  remote_ops.to_static_tracepoint_marker_at
+    = remote_static_tracepoint_marker_at;
+  remote_ops.to_static_tracepoint_markers_by_strid
+    = remote_static_tracepoint_markers_by_strid;
 }
 
 /* Set up the extended remote vector by making a copy of the standard
@@ -10535,6 +10743,15 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
   add_packet_config_cmd (&remote_protocol_packets[PACKET_TracepointSource],
                         "TracepointSource", "TracepointSource", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_QAllow],
+                        "QAllow", "allow", 0);
+
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_StaticTracepoints],
+                        "StaticTracepoints", "static-tracepoints", 0);
+
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_statictrace_read],
+                         "qXfer:statictrace:read", "read-sdata-object", 0);
+
   /* Keep the old ``set remote Z-packet ...'' working.  Each individual
      Z sub-packet has its own set and show commands, but users may
      have sets to this variable in their .gdbinit files (or in their
This page took 0.028502 seconds and 4 git commands to generate.