Blame SOURCES/gdb-rhbz1187581-power8-regs-3of7.patch

4c2ad1
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
4c2ad1
From: Jan Kratochvil <jan.kratochvil@redhat.com>
4c2ad1
Date: Thu, 9 Aug 2018 17:11:09 +0200
4c2ad1
Subject: gdb-rhbz1187581-power8-regs-3of7.patch
4c2ad1
4c2ad1
;; Add GDB support to access/display POWER8 registers (IBM, RH BZ 1187581).
4c2ad1
4c2ad1
commit 3df3a985a475db004706d64f83d9085f99053611
4c2ad1
Author: Pedro Franco de Carvalho <pedromfc@linux.ibm.com>
4c2ad1
Date:   Mon Aug 6 16:24:55 2018 -0300
4c2ad1
4c2ad1
    Use get_remote_packet_size in download_tracepoint
4c2ad1
4c2ad1
    This patch changes the remote target to use the remote packet size to
4c2ad1
    build QTDP packets, and to check if there is enough room for the
4c2ad1
    packet.
4c2ad1
4c2ad1
    I changed the function to raise an error if the packet is too small,
4c2ad1
    instead of aborting gdb (through xsnprintf).  It isn't clear if gdb
4c2ad1
    will be in a consistent state with respect to the stub after this,
4c2ad1
    since it's possible that some packets will be sent but not others, and
4c2ad1
    there could be an incomplete tracepoint on the stub.
4c2ad1
4c2ad1
    The char array used to build the packets is changed to a
4c2ad1
    gdb::char_vector and sized with the result from
4c2ad1
    get_remote_packet_size.
4c2ad1
4c2ad1
    When checking if the buffer is large enough to hold the tracepoint
4c2ad1
    condition agent expression, the length of the expression is multiplied
4c2ad1
    by two, since it is encoded with two hex digits per expression
4c2ad1
    byte.  For simplicity, I assume that the result won't overflow, which
4c2ad1
    can happen for very long condition expressions.
4c2ad1
4c2ad1
    gdb/ChangeLog:
4c2ad1
    2018-08-06  Pedro Franco de Carvalho  <pedromfc@linux.ibm.com>
4c2ad1
4c2ad1
            * remote.c (remote_target::download_tracepoint): Remove BUF_SIZE.
4c2ad1
            Replace array buf with gdb::char_vector buf, of size
4c2ad1
            get_remote_packet_size ().  Replace references to buf and
4c2ad1
            BUF_SIZE to buf.data () and buf.size ().  Replace strcpy, strcat
4c2ad1
            and xsnprintf with snprintf.  Raise errors if the buffer is too
4c2ad1
            small.
4c2ad1
4c2ad1
diff --git a/gdb/remote.c b/gdb/remote.c
4c2ad1
--- a/gdb/remote.c
4c2ad1
+++ b/gdb/remote.c
4c2ad1
@@ -12799,26 +12799,35 @@ remote_target::remote_download_command_source (int num, ULONGEST addr,
4c2ad1
 void
4c2ad1
 remote_target::download_tracepoint (struct bp_location *loc)
4c2ad1
 {
4c2ad1
-#define BUF_SIZE 2048
4c2ad1
-
4c2ad1
   CORE_ADDR tpaddr;
4c2ad1
   char addrbuf[40];
4c2ad1
-  char buf[BUF_SIZE];
4c2ad1
   std::vector<std::string> tdp_actions;
4c2ad1
   std::vector<std::string> stepping_actions;
4c2ad1
   char *pkt;
4c2ad1
   struct breakpoint *b = loc->owner;
4c2ad1
   struct tracepoint *t = (struct tracepoint *) b;
4c2ad1
   struct remote_state *rs = get_remote_state ();
4c2ad1
+  int ret;
4c2ad1
+  char *err_msg = _("Tracepoint packet too large for target.");
4c2ad1
+  size_t size_left;
4c2ad1
+
4c2ad1
+  /* We use a buffer other than rs->buf because we'll build strings
4c2ad1
+     across multiple statements, and other statements in between could
4c2ad1
+     modify rs->buf.  */
4c2ad1
+  gdb::char_vector buf (get_remote_packet_size ());
4c2ad1
 
4c2ad1
   encode_actions_rsp (loc, &tdp_actions, &stepping_actions);
4c2ad1
 
4c2ad1
   tpaddr = loc->address;
4c2ad1
   sprintf_vma (addrbuf, tpaddr);
4c2ad1
-  xsnprintf (buf, BUF_SIZE, "QTDP:%x:%s:%c:%lx:%x", b->number,
4c2ad1
-	     addrbuf, /* address */
4c2ad1
-	     (b->enable_state == bp_enabled ? 'E' : 'D'),
4c2ad1
-	     t->step_count, t->pass_count);
4c2ad1
+  ret = snprintf (buf.data (), buf.size (), "QTDP:%x:%s:%c:%lx:%x",
4c2ad1
+		  b->number, addrbuf, /* address */
4c2ad1
+		  (b->enable_state == bp_enabled ? 'E' : 'D'),
4c2ad1
+		  t->step_count, t->pass_count);
4c2ad1
+
4c2ad1
+  if (ret < 0 || ret >= buf.size ())
4c2ad1
+    error (err_msg);
4c2ad1
+
4c2ad1
   /* Fast tracepoints are mostly handled by the target, but we can
4c2ad1
      tell the target how big of an instruction block should be moved
4c2ad1
      around.  */
4c2ad1
@@ -12830,8 +12839,15 @@ remote_target::download_tracepoint (struct bp_location *loc)
4c2ad1
 	{
4c2ad1
 	  if (gdbarch_fast_tracepoint_valid_at (loc->gdbarch, tpaddr,
4c2ad1
 						NULL))
4c2ad1
-	    xsnprintf (buf + strlen (buf), BUF_SIZE - strlen (buf), ":F%x",
4c2ad1
-		       gdb_insn_length (loc->gdbarch, tpaddr));
4c2ad1
+	    {
4c2ad1
+	      size_left = buf.size () - strlen (buf.data ());
4c2ad1
+	      ret = snprintf (buf.data () + strlen (buf.data ()),
4c2ad1
+			      size_left, ":F%x",
4c2ad1
+			      gdb_insn_length (loc->gdbarch, tpaddr));
4c2ad1
+
4c2ad1
+	      if (ret < 0 || ret >= size_left)
4c2ad1
+		error (err_msg);
4c2ad1
+	    }
4c2ad1
 	  else
4c2ad1
 	    /* If it passed validation at definition but fails now,
4c2ad1
 	       something is very wrong.  */
4c2ad1
@@ -12855,7 +12871,14 @@ remote_target::download_tracepoint (struct bp_location *loc)
4c2ad1
 	  struct static_tracepoint_marker marker;
4c2ad1
 
4c2ad1
 	  if (target_static_tracepoint_marker_at (tpaddr, &marker))
4c2ad1
-	    strcat (buf, ":S");
4c2ad1
+	    {
4c2ad1
+	      size_left = buf.size () - strlen (buf.data ());
4c2ad1
+	      ret = snprintf (buf.data () + strlen (buf.data ()),
4c2ad1
+			      size_left, ":S");
4c2ad1
+
4c2ad1
+	      if (ret < 0 || ret >= size_left)
4c2ad1
+		error (err_msg);
4c2ad1
+	    }
4c2ad1
 	  else
4c2ad1
 	    error (_("Static tracepoint not valid during download"));
4c2ad1
 	}
4c2ad1
@@ -12873,10 +12896,26 @@ remote_target::download_tracepoint (struct bp_location *loc)
4c2ad1
 	 capabilities at definition time.  */
4c2ad1
       if (remote_supports_cond_tracepoints ())
4c2ad1
 	{
4c2ad1
-	  agent_expr_up aexpr = gen_eval_for_expr (tpaddr, loc->cond.get ());
4c2ad1
-	  xsnprintf (buf + strlen (buf), BUF_SIZE - strlen (buf), ":X%x,",
4c2ad1
-		     aexpr->len);
4c2ad1
-	  pkt = buf + strlen (buf);
4c2ad1
+	  agent_expr_up aexpr = gen_eval_for_expr (tpaddr,
4c2ad1
+						   loc->cond.get ());
4c2ad1
+
4c2ad1
+	  size_left = buf.size () - strlen (buf.data ());
4c2ad1
+
4c2ad1
+	  ret = snprintf (buf.data () + strlen (buf.data ()),
4c2ad1
+			  size_left, ":X%x,", aexpr->len);
4c2ad1
+
4c2ad1
+	  if (ret < 0 || ret >= size_left)
4c2ad1
+	    error (err_msg);
4c2ad1
+
4c2ad1
+	  size_left = buf.size () - strlen (buf.data ());
4c2ad1
+
4c2ad1
+	  /* Two bytes to encode each aexpr byte, plus the terminating
4c2ad1
+	     null byte.  */
4c2ad1
+	  if (aexpr->len * 2 + 1 > size_left)
4c2ad1
+	    error (err_msg);
4c2ad1
+
4c2ad1
+	  pkt = buf.data () + strlen (buf.data ());
4c2ad1
+
4c2ad1
 	  for (int ndx = 0; ndx < aexpr->len; ++ndx)
4c2ad1
 	    pkt = pack_hex_byte (pkt, aexpr->buf[ndx]);
4c2ad1
 	  *pkt = '\0';
4c2ad1
@@ -12887,8 +12926,17 @@ remote_target::download_tracepoint (struct bp_location *loc)
4c2ad1
     }
4c2ad1
 
4c2ad1
   if (b->commands || *default_collect)
4c2ad1
-    strcat (buf, "-");
4c2ad1
-  putpkt (buf);
4c2ad1
+    {
4c2ad1
+      size_left = buf.size () - strlen (buf.data ());
4c2ad1
+
4c2ad1
+      ret = snprintf (buf.data () + strlen (buf.data ()),
4c2ad1
+		      size_left, "-");
4c2ad1
+
4c2ad1
+      if (ret < 0 || ret >= size_left)
4c2ad1
+	error (err_msg);
4c2ad1
+    }
4c2ad1
+
4c2ad1
+  putpkt (buf.data ());
4c2ad1
   remote_get_noisy_reply ();
4c2ad1
   if (strcmp (rs->buf, "OK"))
4c2ad1
     error (_("Target does not support tracepoints."));
4c2ad1
@@ -12902,11 +12950,15 @@ remote_target::download_tracepoint (struct bp_location *loc)
4c2ad1
       bool has_more = ((action_it + 1) != tdp_actions.end ()
4c2ad1
 		       || !stepping_actions.empty ());
4c2ad1
 
4c2ad1
-      xsnprintf (buf, BUF_SIZE, "QTDP:-%x:%s:%s%c",
4c2ad1
-		 b->number, addrbuf, /* address */
4c2ad1
-		 action_it->c_str (),
4c2ad1
-		 has_more ? '-' : 0);
4c2ad1
-      putpkt (buf);
4c2ad1
+      ret = snprintf (buf.data (), buf.size (), "QTDP:-%x:%s:%s%c",
4c2ad1
+		      b->number, addrbuf, /* address */
4c2ad1
+		      action_it->c_str (),
4c2ad1
+		      has_more ? '-' : 0);
4c2ad1
+
4c2ad1
+      if (ret < 0 || ret >= buf.size ())
4c2ad1
+	error (err_msg);
4c2ad1
+
4c2ad1
+      putpkt (buf.data ());
4c2ad1
       remote_get_noisy_reply ();
4c2ad1
       if (strcmp (rs->buf, "OK"))
4c2ad1
 	error (_("Error on target while setting tracepoints."));
4c2ad1
@@ -12920,12 +12972,16 @@ remote_target::download_tracepoint (struct bp_location *loc)
4c2ad1
       bool is_first = action_it == stepping_actions.begin ();
4c2ad1
       bool has_more = (action_it + 1) != stepping_actions.end ();
4c2ad1
 
4c2ad1
-      xsnprintf (buf, BUF_SIZE, "QTDP:-%x:%s:%s%s%s",
4c2ad1
-		 b->number, addrbuf, /* address */
4c2ad1
-		 is_first ? "S" : "",
4c2ad1
-		 action_it->c_str (),
4c2ad1
-		 has_more ? "-" : "");
4c2ad1
-      putpkt (buf);
4c2ad1
+      ret = snprintf (buf.data (), buf.size (), "QTDP:-%x:%s:%s%s%s",
4c2ad1
+		      b->number, addrbuf, /* address */
4c2ad1
+		      is_first ? "S" : "",
4c2ad1
+		      action_it->c_str (),
4c2ad1
+		      has_more ? "-" : "");
4c2ad1
+
4c2ad1
+      if (ret < 0 || ret >= buf.size ())
4c2ad1
+	error (err_msg);
4c2ad1
+
4c2ad1
+      putpkt (buf.data ());
4c2ad1
       remote_get_noisy_reply ();
4c2ad1
       if (strcmp (rs->buf, "OK"))
4c2ad1
 	error (_("Error on target while setting tracepoints."));
4c2ad1
@@ -12935,22 +12991,32 @@ remote_target::download_tracepoint (struct bp_location *loc)
4c2ad1
     {
4c2ad1
       if (b->location != NULL)
4c2ad1
 	{
4c2ad1
-	  strcpy (buf, "QTDPsrc:");
4c2ad1
+	  ret = snprintf (buf.data (), buf.size (), "QTDPsrc:");
4c2ad1
+
4c2ad1
+	  if (ret < 0 || ret >= buf.size ())
4c2ad1
+	    error (err_msg);
4c2ad1
+
4c2ad1
 	  encode_source_string (b->number, loc->address, "at",
4c2ad1
 				event_location_to_string (b->location.get ()),
4c2ad1
-				buf + strlen (buf), 2048 - strlen (buf));
4c2ad1
-	  putpkt (buf);
4c2ad1
+				buf.data () + strlen (buf.data ()),
4c2ad1
+				buf.size () - strlen (buf.data ()));
4c2ad1
+	  putpkt (buf.data ());
4c2ad1
 	  remote_get_noisy_reply ();
4c2ad1
 	  if (strcmp (rs->buf, "OK"))
4c2ad1
 	    warning (_("Target does not support source download."));
4c2ad1
 	}
4c2ad1
       if (b->cond_string)
4c2ad1
 	{
4c2ad1
-	  strcpy (buf, "QTDPsrc:");
4c2ad1
+	  ret = snprintf (buf.data (), buf.size (), "QTDPsrc:");
4c2ad1
+
4c2ad1
+	  if (ret < 0 || ret >= buf.size ())
4c2ad1
+	    error (err_msg);
4c2ad1
+
4c2ad1
 	  encode_source_string (b->number, loc->address,
4c2ad1
-				"cond", b->cond_string, buf + strlen (buf),
4c2ad1
-				2048 - strlen (buf));
4c2ad1
-	  putpkt (buf);
4c2ad1
+				"cond", b->cond_string,
4c2ad1
+				buf.data () + strlen (buf.data ()),
4c2ad1
+				buf.size () - strlen (buf.data ()));
4c2ad1
+	  putpkt (buf.data ());
4c2ad1
 	  remote_get_noisy_reply ();
4c2ad1
 	  if (strcmp (rs->buf, "OK"))
4c2ad1
 	    warning (_("Target does not support source download."));