[v2,4/6] Use remote register numbers in tracepoint mask

Message ID 20180727210318.2960-5-pedromfc@linux.ibm.com
State Superseded
Headers show
Series
  • Fix tracepoint register limitations
Related show

Commit Message

Pedro Franco de Carvalho July 27, 2018, 9:03 p.m.
Currently, tracepoint register masks in the QTDP packets include both
internal and remote register numbers, as well as pseudo-register
numbers.

This patch changes this so that the mask only includes remote register
numbers.

Register numbers from agent expressions are already set in the mask
using remote numbers.  Other tracepoint actions used internal numbers,
e.g. "collect $regs" or "collect $<pseudoreg>".  To handle pseudoreg
numbers, an empty agent expression is created and ax_reg_mask is
called for this expression and the pseudoreg.  This will cause the ax
to set its mask with the corresponding remote raw register
numbers (using gdbarch_ax_pseudo_register_collect).

This assumes that all gdbarch_ax_pseudo_register_collect
implementations only use ax_reg_mask themselves to set the mask, and
don't generate more complicated agent expressions to collect
pseudoregs.  This seems to be the case, and seems to be the intended
use of gdbarch_ax_pseudo_register_collect, despite the gdbarch.h
comment for this function.

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

	* tracepoint.h (class collection_list) <add_register>: Remove.
	<add_remote_register, add_ax_registers, add_local_register>:
	Declare.
	<add_memrange>: Add scope parameter.
	* tracepoint.c (collection_list::add_register): Rename to ...
	(collection_list::add_remote_register): ... this.  Update comment.
	(collection_list::add_ax_registers, add_local_register): New
	methods.
	(collection_list::add_memrange): Add scope parameter.  Call
	add_local_register instead of add_register.
	(collection_list::collect_symbol): Update calls to
	add_memrange.  Call add_local_register instead of add_register.
	(collection_list::collect_symbol): Call add_ax_registers.
	(encode_actions_1): Get remote regnos for $reg action.  Call
	add_remote_register, add_ax_registers, and add_local_register.
	Update call to add_memrange.
---
 gdb/tracepoint.c | 142 +++++++++++++++++++++++++++++++------------------------
 gdb/tracepoint.h |   8 +++-
 2 files changed, 85 insertions(+), 65 deletions(-)

-- 
2.13.6

Patch

diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 74d1183386..f06386158a 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -811,10 +811,10 @@  memrange_sortmerge (std::vector<memrange> &memranges)
     }
 }
 
-/* Add a register to a collection list.  */
+/* Add remote register number REGNO to the collection list mask.  */
 
 void
-collection_list::add_register (unsigned int regno)
+collection_list::add_remote_register (unsigned int regno)
 {
   if (info_verbose)
     printf_filtered ("collect register %d\n", regno);
@@ -824,12 +824,62 @@  collection_list::add_register (unsigned int regno)
   m_regs_mask[regno / 8] |= 1 << (regno % 8);
 }
 
+/* Add all the registers from the mask in AEXPR to the mask in the
+   collection list.  Registers in the AEXPR mask are already remote
+   register numbers.  */
+
+void
+collection_list::add_ax_registers (struct agent_expr *aexpr)
+{
+  if (aexpr->reg_mask_len > 0)
+    {
+      for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
+	{
+	  QUIT;	/* Allow user to bail out with ^C.  */
+	  if (aexpr->reg_mask[ndx1] != 0)
+	    {
+	      /* Assume chars have 8 bits.  */
+	      for (int ndx2 = 0; ndx2 < 8; ndx2++)
+		if (aexpr->reg_mask[ndx1] & (1 << ndx2))
+		  /* It's used -- record it.  */
+		  add_remote_register (ndx1 * 8 + ndx2);
+	    }
+	}
+    }
+}
+
+/* If REGNO is raw, add its corresponding remote register number to
+   the mask.  If REGNO is a pseudo-register, figure out the necessary
+   registers using a temporary agent expression.  */
+
+void
+collection_list::add_local_register (struct gdbarch *gdbarch,
+				     unsigned int regno,
+				     CORE_ADDR scope)
+{
+  if (regno < gdbarch_num_regs (gdbarch))
+    {
+      int remote_regno = gdbarch_remote_register_number (gdbarch, regno);
+
+      if (remote_regno < 0)
+	error (_("Can't collect register %d"), regno);
+
+      add_remote_register (remote_regno);
+    }
+  else
+    {
+      struct agent_expr aexpr (gdbarch, scope);
+      ax_reg_mask (&aexpr, regno);
+      add_ax_registers (&aexpr);
+    }
+}
+
 /* Add a memrange to a collection list.  */
 
 void
 collection_list::add_memrange (struct gdbarch *gdbarch,
 			       int type, bfd_signed_vma base,
-			       unsigned long len)
+			       unsigned long len, CORE_ADDR scope)
 {
   if (info_verbose)
     printf_filtered ("(%d,%s,%ld)\n", type, paddress (gdbarch, base), len);
@@ -840,7 +890,7 @@  collection_list::add_memrange (struct gdbarch *gdbarch,
   m_memranges.emplace_back (type, base, base + len);
 
   if (type != memrange_absolute)    /* Better collect the base register!  */
-    add_register (type);
+    add_local_register (gdbarch, type, scope);
 }
 
 /* Add a symbol to a collection list.  */
@@ -882,19 +932,19 @@  collection_list::collect_symbol (struct symbol *sym,
       if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_STRUCT)
 	treat_as_expr = 1;
       else
-	add_memrange (gdbarch, memrange_absolute, offset, len);
+	add_memrange (gdbarch, memrange_absolute, offset, len, scope);
       break;
     case LOC_REGISTER:
       reg = SYMBOL_REGISTER_OPS (sym)->register_number (sym, gdbarch);
       if (info_verbose)
 	printf_filtered ("LOC_REG[parm] %s: ", 
 			 SYMBOL_PRINT_NAME (sym));
-      add_register (reg);
+      add_local_register (gdbarch, reg, scope);
       /* Check for doubles stored in two registers.  */
       /* FIXME: how about larger types stored in 3 or more regs?  */
       if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_FLT &&
 	  len > register_size (gdbarch, reg))
-	add_register (reg + 1);
+	add_local_register (gdbarch, reg + 1, scope);
       break;
     case LOC_REF_ARG:
       printf_filtered ("Sorry, don't know how to do LOC_REF_ARG yet.\n");
@@ -911,7 +961,7 @@  collection_list::collect_symbol (struct symbol *sym,
 			   SYMBOL_PRINT_NAME (sym), len,
 			   paddress (gdbarch, offset), reg);
 	}
-      add_memrange (gdbarch, reg, offset, len);
+      add_memrange (gdbarch, reg, offset, len, scope);
       break;
     case LOC_REGPARM_ADDR:
       reg = SYMBOL_VALUE (sym);
@@ -923,7 +973,7 @@  collection_list::collect_symbol (struct symbol *sym,
 			   SYMBOL_PRINT_NAME (sym), len,
 			   paddress (gdbarch, offset), reg);
 	}
-      add_memrange (gdbarch, reg, offset, len);
+      add_memrange (gdbarch, reg, offset, len, scope);
       break;
     case LOC_LOCAL:
       reg = frame_regno;
@@ -935,7 +985,7 @@  collection_list::collect_symbol (struct symbol *sym,
 			   SYMBOL_PRINT_NAME (sym), len,
 			   paddress (gdbarch, offset), reg);
 	}
-      add_memrange (gdbarch, reg, offset, len);
+      add_memrange (gdbarch, reg, offset, len, scope);
       break;
 
     case LOC_UNRESOLVED:
@@ -973,21 +1023,7 @@  collection_list::collect_symbol (struct symbol *sym,
       report_agent_reqs_errors (aexpr.get ());
 
       /* Take care of the registers.  */
-      if (aexpr->reg_mask_len > 0)
-	{
-	  for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
-	    {
-	      QUIT;	/* Allow user to bail out with ^C.  */
-	      if (aexpr->reg_mask[ndx1] != 0)
-		{
-		  /* Assume chars have 8 bits.  */
-		  for (int ndx2 = 0; ndx2 < 8; ndx2++)
-		    if (aexpr->reg_mask[ndx1] & (1 << ndx2))
-		      /* It's used -- record it.  */
-		      add_register (ndx1 * 8 + ndx2);
-		}
-	    }
-	}
+      add_ax_registers (aexpr.get ());
 
       add_aexpr (std::move (aexpr));
     }
@@ -1257,8 +1293,18 @@  encode_actions_1 (struct command_line *action,
 
 	      if (0 == strncasecmp ("$reg", action_exp, 4))
 		{
-		  for (i = 0; i < gdbarch_num_regs (target_gdbarch ()); i++)
-		    collect->add_register (i);
+		  for (i = 0; i < gdbarch_num_regs (target_gdbarch ());
+		       i++)
+		    {
+		      int remote_regno = (gdbarch_remote_register_number
+					  (target_gdbarch (), i));
+
+		      /* Ignore arch regnos without a corresponding
+			 remote regno.  This can happen for regnos not
+			 in the tdesc.  */
+		      if (remote_regno >= 0)
+			collect->add_remote_register (remote_regno);
+		    }
 		  action_exp = strchr (action_exp, ',');	/* more? */
 		}
 	      else if (0 == strncasecmp ("$arg", action_exp, 4))
@@ -1292,23 +1338,7 @@  encode_actions_1 (struct command_line *action,
 		  report_agent_reqs_errors (aexpr.get ());
 
 		  /* take care of the registers */
-		  if (aexpr->reg_mask_len > 0)
-		    {
-		      for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
-			{
-			  QUIT;	/* allow user to bail out with ^C */
-			  if (aexpr->reg_mask[ndx1] != 0)
-			    {
-			      /* assume chars have 8 bits */
-			      for (int ndx2 = 0; ndx2 < 8; ndx2++)
-				if (aexpr->reg_mask[ndx1] & (1 << ndx2))
-				  {
-				    /* It's used -- record it.  */
-				    collect->add_register (ndx1 * 8 + ndx2);
-				  }
-			    }
-			}
-		    }
+		  collect->add_ax_registers (aexpr.get ());
 
 		  collect->add_aexpr (std::move (aexpr));
 		  action_exp = strchr (action_exp, ',');	/* more? */
@@ -1340,7 +1370,8 @@  encode_actions_1 (struct command_line *action,
 					  name);
 			if (info_verbose)
 			  printf_filtered ("OP_REGISTER: ");
-			collect->add_register (i);
+			collect->add_local_register (target_gdbarch (),
+						     i, tloc->address);
 			break;
 		      }
 
@@ -1352,7 +1383,8 @@  encode_actions_1 (struct command_line *action,
 		      check_typedef (exp->elts[1].type);
 		      collect->add_memrange (target_gdbarch (),
 					     memrange_absolute, addr,
-					     TYPE_LENGTH (exp->elts[1].type));
+					     TYPE_LENGTH (exp->elts[1].type),
+					     tloc->address);
 		      collect->append_exp (exp.get ());
 		      break;
 
@@ -1381,23 +1413,7 @@  encode_actions_1 (struct command_line *action,
 		      report_agent_reqs_errors (aexpr.get ());
 
 		      /* Take care of the registers.  */
-		      if (aexpr->reg_mask_len > 0)
-			{
-			  for (int ndx1 = 0; ndx1 < aexpr->reg_mask_len; ndx1++)
-			    {
-			      QUIT;	/* Allow user to bail out with ^C.  */
-			      if (aexpr->reg_mask[ndx1] != 0)
-				{
-				  /* Assume chars have 8 bits.  */
-				  for (int ndx2 = 0; ndx2 < 8; ndx2++)
-				    if (aexpr->reg_mask[ndx1] & (1 << ndx2))
-				      {
-					/* It's used -- record it.  */
-					collect->add_register (ndx1 * 8 + ndx2);
-				      }
-				}
-			    }
-			}
+		      collect->add_ax_registers (aexpr.get ());
 
 		      collect->add_aexpr (std::move (aexpr));
 		      collect->append_exp (exp.get ());
diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h
index 42e413018a..8bdad3567e 100644
--- a/gdb/tracepoint.h
+++ b/gdb/tracepoint.h
@@ -262,10 +262,14 @@  public:
   /* Add AEXPR to the list, taking ownership.  */
   void add_aexpr (agent_expr_up aexpr);
 
-  void add_register (unsigned int regno);
+  void add_remote_register (unsigned int regno);
+  void add_ax_registers (struct agent_expr *aexpr);
+  void add_local_register (struct gdbarch *gdbarch,
+			   unsigned int regno,
+			   CORE_ADDR scope);
   void add_memrange (struct gdbarch *gdbarch,
 		     int type, bfd_signed_vma base,
-		     unsigned long len);
+		     unsigned long len, CORE_ADDR scope);
   void collect_symbol (struct symbol *sym,
 		       struct gdbarch *gdbarch,
 		       long frame_regno, long frame_offset,