Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Pedro Franco de Carvalho <pedromfc@linux.ibm.com>
To: gdb-patches@sourceware.org
Cc: uweigand@de.ibm.com
Subject: [PATCH v2 3/6] Use get_remote_packet_size in download_tracepoint
Date: Fri, 03 Aug 2018 21:41:00 -0000	[thread overview]
Message-ID: <20180803214124.1033-1-pedromfc@linux.ibm.com> (raw)
In-Reply-To: <20180802164652.16707D802AB@oc3748833570.ibm.com>

This patch changes the remote target to use the remote packet size to
build QTDP packets, and to check if there is enough room for the
packet.

I changed the function to raise an error if the packet is too small,
instead of aborting gdb (through xsnprintf).  It isn't clear if gdb
will be in a consistent state with respect to the stub after this,
since it's possible that some packets will be sent but not others, and
there could be an incomplete tracepoint on the stub.

The char array used to build the packets is changed to a
gdb::char_vector and sized with the result from
get_remote_packet_size.

When checking if the buffer is large enough to hold the tracepoint
condition agent expression, the length of the expression is multiplied
by two, since it is encoded with two hex digits per expression
byte.  For simplicity, I assume that the result won't overflow, which
can happen for very long condition expressions.

gdb/ChangeLog:
YYYY-MM-DD  Pedro Franco de Carvalho  <pedromfc@linux.ibm.com>

	* remote.c (remote_target::download_tracepoint): Remove BUF_SIZE.
	Replace array buf with gdb::char_vector buf, of size
	get_remote_packet_size ().  Replace references to buf and BUF_SIZE
	to buf.data () and buf.size ().  Replace strcpy, strcat and
	pack_hex_byte with snprintf.  Raise errors if the buffer is too
	small.
---
 gdb/remote.c | 134 ++++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 100 insertions(+), 34 deletions(-)

diff --git a/gdb/remote.c b/gdb/remote.c
index e3180923ee..4974c2e8f0 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -12832,26 +12832,35 @@ remote_target::remote_download_command_source (int num, ULONGEST addr,
 void
 remote_target::download_tracepoint (struct bp_location *loc)
 {
-#define BUF_SIZE 2048
-
   CORE_ADDR tpaddr;
   char addrbuf[40];
-  char buf[BUF_SIZE];
   std::vector<std::string> tdp_actions;
   std::vector<std::string> stepping_actions;
   char *pkt;
   struct breakpoint *b = loc->owner;
   struct tracepoint *t = (struct tracepoint *) b;
   struct remote_state *rs = get_remote_state ();
+  int ret;
+  char *err_msg = _("Tracepoint packet too large for target.");
+  size_t size_left;
+
+  /* We use a buffer other than rs->buf because we'll build strings
+     across multiple statements, and other statements in between could
+     modify rs->buf.  */
+  gdb::char_vector buf (get_remote_packet_size ());
 
   encode_actions_rsp (loc, &tdp_actions, &stepping_actions);
 
   tpaddr = loc->address;
   sprintf_vma (addrbuf, tpaddr);
-  xsnprintf (buf, BUF_SIZE, "QTDP:%x:%s:%c:%lx:%x", b->number,
-	     addrbuf, /* address */
-	     (b->enable_state == bp_enabled ? 'E' : 'D'),
-	     t->step_count, t->pass_count);
+  ret = snprintf (buf.data (), buf.size (), "QTDP:%x:%s:%c:%lx:%x",
+		  b->number, addrbuf, /* address */
+		  (b->enable_state == bp_enabled ? 'E' : 'D'),
+		  t->step_count, t->pass_count);
+
+  if (ret < 0 || ret >= buf.size ())
+    error (err_msg);
+
   /* Fast tracepoints are mostly handled by the target, but we can
      tell the target how big of an instruction block should be moved
      around.  */
@@ -12863,8 +12872,15 @@ remote_target::download_tracepoint (struct bp_location *loc)
 	{
 	  if (gdbarch_fast_tracepoint_valid_at (loc->gdbarch, tpaddr,
 						NULL))
-	    xsnprintf (buf + strlen (buf), BUF_SIZE - strlen (buf), ":F%x",
-		       gdb_insn_length (loc->gdbarch, tpaddr));
+	    {
+	      size_left = buf.size () - strlen (buf.data ());
+	      ret = snprintf (buf.data () + strlen (buf.data ()),
+			      size_left, ":F%x",
+			      gdb_insn_length (loc->gdbarch, tpaddr));
+
+	      if (ret < 0 || ret >= size_left)
+		error (err_msg);
+	    }
 	  else
 	    /* If it passed validation at definition but fails now,
 	       something is very wrong.  */
@@ -12888,7 +12904,14 @@ remote_target::download_tracepoint (struct bp_location *loc)
 	  struct static_tracepoint_marker marker;
 
 	  if (target_static_tracepoint_marker_at (tpaddr, &marker))
-	    strcat (buf, ":S");
+	    {
+	      size_left = buf.size () - strlen (buf.data ());
+	      ret = snprintf (buf.data () + strlen (buf.data ()),
+			      size_left, ":S");
+
+	      if (ret < 0 || ret >= size_left)
+		error (err_msg);
+	    }
 	  else
 	    error (_("Static tracepoint not valid during download"));
 	}
@@ -12906,10 +12929,26 @@ remote_target::download_tracepoint (struct bp_location *loc)
 	 capabilities at definition time.  */
       if (remote_supports_cond_tracepoints ())
 	{
-	  agent_expr_up aexpr = gen_eval_for_expr (tpaddr, loc->cond.get ());
-	  xsnprintf (buf + strlen (buf), BUF_SIZE - strlen (buf), ":X%x,",
-		     aexpr->len);
-	  pkt = buf + strlen (buf);
+	  agent_expr_up aexpr = gen_eval_for_expr (tpaddr,
+						   loc->cond.get ());
+
+	  size_left = buf.size () - strlen (buf.data ());
+
+	  ret = snprintf (buf.data () + strlen (buf.data ()),
+			  size_left, ":X%x,", aexpr->len);
+
+	  if (ret < 0 || ret >= size_left)
+	    error (err_msg);
+
+	  size_left = buf.size () - strlen (buf.data ());
+
+	  /* Two bytes to encode each aexpr byte, plus the terminating
+	     null byte.  */
+	  if (aexpr->len * 2 + 1 > size_left)
+	    error (err_msg);
+
+	  pkt = buf.data () + strlen (buf.data ());
+
 	  for (int ndx = 0; ndx < aexpr->len; ++ndx)
 	    pkt = pack_hex_byte (pkt, aexpr->buf[ndx]);
 	  *pkt = '\0';
@@ -12920,8 +12959,17 @@ remote_target::download_tracepoint (struct bp_location *loc)
     }
 
   if (b->commands || *default_collect)
-    strcat (buf, "-");
-  putpkt (buf);
+    {
+      size_left = buf.size () - strlen (buf.data ());
+
+      ret = snprintf (buf.data () + strlen (buf.data ()),
+		      size_left, "-");
+
+      if (ret < 0 || ret >= size_left)
+	error (err_msg);
+    }
+
+  putpkt (buf.data ());
   remote_get_noisy_reply ();
   if (strcmp (rs->buf, "OK"))
     error (_("Target does not support tracepoints."));
@@ -12935,11 +12983,15 @@ remote_target::download_tracepoint (struct bp_location *loc)
       bool has_more = ((action_it + 1) != tdp_actions.end ()
 		       || !stepping_actions.empty ());
 
-      xsnprintf (buf, BUF_SIZE, "QTDP:-%x:%s:%s%c",
-		 b->number, addrbuf, /* address */
-		 action_it->c_str (),
-		 has_more ? '-' : 0);
-      putpkt (buf);
+      ret = snprintf (buf.data (), buf.size (), "QTDP:-%x:%s:%s%c",
+		      b->number, addrbuf, /* address */
+		      action_it->c_str (),
+		      has_more ? '-' : 0);
+
+      if (ret < 0 || ret >= buf.size ())
+	error (err_msg);
+
+      putpkt (buf.data ());
       remote_get_noisy_reply ();
       if (strcmp (rs->buf, "OK"))
 	error (_("Error on target while setting tracepoints."));
@@ -12953,12 +13005,16 @@ remote_target::download_tracepoint (struct bp_location *loc)
       bool is_first = action_it == stepping_actions.begin ();
       bool has_more = (action_it + 1) != stepping_actions.end ();
 
-      xsnprintf (buf, BUF_SIZE, "QTDP:-%x:%s:%s%s%s",
-		 b->number, addrbuf, /* address */
-		 is_first ? "S" : "",
-		 action_it->c_str (),
-		 has_more ? "-" : "");
-      putpkt (buf);
+      ret = snprintf (buf.data (), buf.size (), "QTDP:-%x:%s:%s%s%s",
+		      b->number, addrbuf, /* address */
+		      is_first ? "S" : "",
+		      action_it->c_str (),
+		      has_more ? "-" : "");
+
+      if (ret < 0 || ret >= buf.size ())
+	error (err_msg);
+
+      putpkt (buf.data ());
       remote_get_noisy_reply ();
       if (strcmp (rs->buf, "OK"))
 	error (_("Error on target while setting tracepoints."));
@@ -12968,22 +13024,32 @@ remote_target::download_tracepoint (struct bp_location *loc)
     {
       if (b->location != NULL)
 	{
-	  strcpy (buf, "QTDPsrc:");
+	  ret = snprintf (buf.data (), buf.size (), "QTDPsrc:");
+
+	  if (ret < 0 || ret >= buf.size ())
+	    error (err_msg);
+
 	  encode_source_string (b->number, loc->address, "at",
 				event_location_to_string (b->location.get ()),
-				buf + strlen (buf), 2048 - strlen (buf));
-	  putpkt (buf);
+				buf.data () + strlen (buf.data ()),
+				buf.size () - strlen (buf.data ()));
+	  putpkt (buf.data ());
 	  remote_get_noisy_reply ();
 	  if (strcmp (rs->buf, "OK"))
 	    warning (_("Target does not support source download."));
 	}
       if (b->cond_string)
 	{
-	  strcpy (buf, "QTDPsrc:");
+	  ret = snprintf (buf.data (), buf.size (), "QTDPsrc:");
+
+	  if (ret < 0 || ret >= buf.size ())
+	    error (err_msg);
+
 	  encode_source_string (b->number, loc->address,
-				"cond", b->cond_string, buf + strlen (buf),
-				2048 - strlen (buf));
-	  putpkt (buf);
+				"cond", b->cond_string,
+				buf.data () + strlen (buf.data ()),
+				buf.size () - strlen (buf.data ()));
+	  putpkt (buf.data ());
 	  remote_get_noisy_reply ();
 	  if (strcmp (rs->buf, "OK"))
 	    warning (_("Target does not support source download."));
-- 
2.13.6


  reply	other threads:[~2018-08-03 21:41 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-27 21:03 [PATCH v2 0/6] Fix tracepoint register limitations Pedro Franco de Carvalho
2018-07-27 21:03 ` [PATCH v2 1/6] Fix indentation in remote_target::download_tracepoint Pedro Franco de Carvalho
2018-08-02 16:43   ` Ulrich Weigand
2018-07-27 21:03 ` [PATCH v2 2/6] Remove trailing '-' from the last QTDP action packet Pedro Franco de Carvalho
2018-08-02 16:44   ` Ulrich Weigand
2018-07-27 21:03 ` [PATCH v2 4/6] Use remote register numbers in tracepoint mask Pedro Franco de Carvalho
2018-08-02 16:58   ` Ulrich Weigand
2018-08-03 22:09     ` Pedro Franco de Carvalho
2018-08-03 22:10     ` Pedro Franco de Carvalho
2018-08-06 12:42       ` Ulrich Weigand
2018-08-06 20:18         ` Pedro Franco de Carvalho
2018-07-27 21:03 ` [PATCH v2 6/6] Allow larger regblock sizes when saving tracefiles Pedro Franco de Carvalho
2018-08-02 17:04   ` Ulrich Weigand
2018-07-27 21:03 ` [PATCH v2 5/6] Variable size for regs mask in collection list Pedro Franco de Carvalho
2018-08-02 17:01   ` Ulrich Weigand
2018-07-27 21:03 ` [PATCH v2 3/6] Use get_remote_packet_size in download_tracepoint Pedro Franco de Carvalho
2018-08-02 16:47   ` Ulrich Weigand
2018-08-03 21:41     ` Pedro Franco de Carvalho [this message]
2018-08-06 12:40       ` Ulrich Weigand
     [not found]       ` <feb8623a-b89e-7519-22de-0d6ede3d5768@arm.com>
2018-08-08 10:33         ` [committed] Fix gdb/remote.c build failure Szabolcs Nagy
2018-08-08 12:25           ` Ulrich Weigand
2018-08-08 15:55         ` [PATCH v2 3/6] Use get_remote_packet_size in download_tracepoint Pedro Franco de Carvalho
2018-08-03 21:41     ` Pedro Franco de Carvalho

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180803214124.1033-1-pedromfc@linux.ibm.com \
    --to=pedromfc@linux.ibm.com \
    --cc=gdb-patches@sourceware.org \
    --cc=uweigand@de.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox