2010-12-28 Hui Zhu <teawater@gmail.com>
authorHui Zhu <teawater@gmail.com>
Tue, 28 Dec 2010 16:00:13 +0000 (16:00 +0000)
committerHui Zhu <teawater@gmail.com>
Tue, 28 Dec 2010 16:00:13 +0000 (16:00 +0000)
* gdbarch.sh (ax_pseudo_register_collect,
ax_pseudo_register_push_stack): new callbacks.
(agent_expr): Forward declare.
* gdbarch.h, gdbarch.c: Regenerate.
* ax-gdb.c (gen_expr): Remove pseudo-register check code.
* ax-general.c (user-regs.h): New include.
(ax_reg): Call gdbarch_ax_pseudo_register_push_stack.
(ax_reg_mask): Call gdbarch_ax_pseudo_register_collect.
* mips-tdep.c (ax.h): New include.
(mips_ax_pseudo_register_collect,
mips_ax_pseudo_register_push_stack): New functions.
(mips_gdbarch_init): Set mips_ax_pseudo_register_collect and
mips_ax_pseudo_register_push_stack.

gdb/ChangeLog
gdb/ax-gdb.c
gdb/ax-general.c
gdb/gdbarch.c
gdb/gdbarch.h
gdb/gdbarch.sh
gdb/mips-tdep.c

index 5beba9aac5b9f12a41c81fcda8d14268e81c82d3..6508a66842e573afb9eefa226c54ec9c7c2af34f 100644 (file)
@@ -1,3 +1,19 @@
+2010-12-28  Hui Zhu  <teawater@gmail.com>
+
+       * gdbarch.sh (ax_pseudo_register_collect,
+       ax_pseudo_register_push_stack): new callbacks.
+       (agent_expr): Forward declare.
+       * gdbarch.h, gdbarch.c: Regenerate.
+       * ax-gdb.c (gen_expr): Remove pseudo-register check code.
+       * ax-general.c (user-regs.h): New include.
+       (ax_reg): Call gdbarch_ax_pseudo_register_push_stack.
+       (ax_reg_mask): Call gdbarch_ax_pseudo_register_collect.
+       * mips-tdep.c (ax.h): New include.
+       (mips_ax_pseudo_register_collect,
+       mips_ax_pseudo_register_push_stack): New functions.
+       (mips_gdbarch_init): Set mips_ax_pseudo_register_collect and
+       mips_ax_pseudo_register_push_stack.
+
 2010-12-28  Yao Qi  <yao@codesourcery.com>
 
        * arm-tdep.c (arm_register_aliases): Remove sp, pc, and fp.
index e01f359bd3fa28576d4facde47ee792041a2e75d..ab6b82918bba1a7fe8f6302f7362ac71cd5583aa 100644 (file)
@@ -1978,10 +1978,6 @@ gen_expr (struct expression *exp, union exp_element **pc,
        if (reg == -1)
          internal_error (__FILE__, __LINE__,
                          _("Register $%s not available"), name);
-       if (reg >= gdbarch_num_regs (exp->gdbarch))
-         error (_("'%s' is a pseudo-register; "
-                  "GDB cannot yet trace pseudoregister contents."),
-                name);
        value->kind = axs_lvalue_register;
        value->u.reg = reg;
        value->type = register_type (exp->gdbarch, reg);
index ab4591fa0886210f70870a3fadef716da96ba2d5..e1269e6ff100408abdeebf1f5c0a160fd5bec932 100644 (file)
@@ -28,6 +28,8 @@
 #include "value.h"
 #include "gdb_string.h"
 
+#include "user-regs.h"
+
 static void grow_expr (struct agent_expr *x, int n);
 
 static void append_const (struct agent_expr *x, LONGEST val, int n);
@@ -272,14 +274,28 @@ ax_const_d (struct agent_expr *x, LONGEST d)
 void
 ax_reg (struct agent_expr *x, int reg)
 {
-  /* Make sure the register number is in range.  */
-  if (reg < 0 || reg > 0xffff)
-    error (_("GDB bug: ax-general.c (ax_reg): register number out of range"));
-  grow_expr (x, 3);
-  x->buf[x->len] = aop_reg;
-  x->buf[x->len + 1] = (reg >> 8) & 0xff;
-  x->buf[x->len + 2] = (reg) & 0xff;
-  x->len += 3;
+  if (reg >= gdbarch_num_regs (x->gdbarch))
+    {
+      /* This is a pseudo-register.  */
+      if (!gdbarch_ax_pseudo_register_push_stack_p (x->gdbarch))
+       error (_("'%s' is a pseudo-register; "
+                "GDB cannot yet trace its contents."),
+              user_reg_map_regnum_to_name (x->gdbarch, reg));
+      if (gdbarch_ax_pseudo_register_push_stack (x->gdbarch, x, reg))
+       error (_("Trace '%s' failed."),
+              user_reg_map_regnum_to_name (x->gdbarch, reg));
+    }
+  else
+    {
+      /* Make sure the register number is in range.  */
+      if (reg < 0 || reg > 0xffff)
+        error (_("GDB bug: ax-general.c (ax_reg): register number out of range"));
+      grow_expr (x, 3);
+      x->buf[x->len] = aop_reg;
+      x->buf[x->len + 1] = (reg >> 8) & 0xff;
+      x->buf[x->len + 2] = (reg) & 0xff;
+      x->len += 3;
+    }
 }
 
 /* Assemble code to operate on a trace state variable.  */
@@ -413,23 +429,38 @@ ax_print (struct ui_file *f, struct agent_expr *x)
 void
 ax_reg_mask (struct agent_expr *ax, int reg)
 {
-  int byte = reg / 8;
-
-  /* Grow the bit mask if necessary.  */
-  if (byte >= ax->reg_mask_len)
+  if (reg >= gdbarch_num_regs (ax->gdbarch))
     {
-      /* It's not appropriate to double here.  This isn't a
-        string buffer.  */
-      int new_len = byte + 1;
-      unsigned char *new_reg_mask = xrealloc (ax->reg_mask,
-                                             new_len * sizeof (ax->reg_mask[0]));
-      memset (new_reg_mask + ax->reg_mask_len, 0,
-             (new_len - ax->reg_mask_len) * sizeof (ax->reg_mask[0]));
-      ax->reg_mask_len = new_len;
-      ax->reg_mask = new_reg_mask;
+      /* This is a pseudo-register.  */
+      if (!gdbarch_ax_pseudo_register_collect_p (ax->gdbarch))
+       error (_("'%s' is a pseudo-register; "
+                "GDB cannot yet trace its contents."),
+              user_reg_map_regnum_to_name (ax->gdbarch, reg));
+      if (gdbarch_ax_pseudo_register_collect (ax->gdbarch, ax, reg))
+       error (_("Trace '%s' failed."),
+              user_reg_map_regnum_to_name (ax->gdbarch, reg));
+    }
+  else
+    {
+      int byte = reg / 8;
+
+      /* Grow the bit mask if necessary.  */
+      if (byte >= ax->reg_mask_len)
+        {
+          /* It's not appropriate to double here.  This isn't a
+            string buffer.  */
+          int new_len = byte + 1;
+          unsigned char *new_reg_mask = xrealloc (ax->reg_mask,
+                                                 new_len
+                                                 * sizeof (ax->reg_mask[0]));
+          memset (new_reg_mask + ax->reg_mask_len, 0,
+                 (new_len - ax->reg_mask_len) * sizeof (ax->reg_mask[0]));
+          ax->reg_mask_len = new_len;
+          ax->reg_mask = new_reg_mask;
+        }
+
+      ax->reg_mask[byte] |= 1 << (reg % 8);
     }
-
-  ax->reg_mask[byte] |= 1 << (reg % 8);
 }
 
 /* Given an agent expression AX, fill in requirements and other descriptive
index 78e5c4869692dbab8fa9611349505642b3b57321..6921f6475f9f7cb1a3035acf961eb48b6e14e8ec 100644 (file)
@@ -164,6 +164,8 @@ struct gdbarch
   gdbarch_pseudo_register_write_ftype *pseudo_register_write;
   int num_regs;
   int num_pseudo_regs;
+  gdbarch_ax_pseudo_register_collect_ftype *ax_pseudo_register_collect;
+  gdbarch_ax_pseudo_register_push_stack_ftype *ax_pseudo_register_push_stack;
   int sp_regnum;
   int pc_regnum;
   int ps_regnum;
@@ -314,6 +316,8 @@ struct gdbarch startup_gdbarch =
   0,  /* pseudo_register_write */
   0,  /* num_regs */
   0,  /* num_pseudo_regs */
+  0,  /* ax_pseudo_register_collect */
+  0,  /* ax_pseudo_register_push_stack */
   -1,  /* sp_regnum */
   -1,  /* pc_regnum */
   -1,  /* ps_regnum */
@@ -594,6 +598,8 @@ verify_gdbarch (struct gdbarch *gdbarch)
   if (gdbarch->num_regs == -1)
     fprintf_unfiltered (log, "\n\tnum_regs");
   /* Skip verify of num_pseudo_regs, invalid_p == 0 */
+  /* Skip verify of ax_pseudo_register_collect, has predicate */
+  /* Skip verify of ax_pseudo_register_push_stack, has predicate */
   /* Skip verify of sp_regnum, invalid_p == 0 */
   /* Skip verify of pc_regnum, invalid_p == 0 */
   /* Skip verify of ps_regnum, invalid_p == 0 */
@@ -760,6 +766,18 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                       "gdbarch_dump: auto_wide_charset = <%s>\n",
                       host_address_to_string (gdbarch->auto_wide_charset));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_ax_pseudo_register_collect_p() = %d\n",
+                      gdbarch_ax_pseudo_register_collect_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: ax_pseudo_register_collect = <%s>\n",
+                      host_address_to_string (gdbarch->ax_pseudo_register_collect));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_ax_pseudo_register_push_stack_p() = %d\n",
+                      gdbarch_ax_pseudo_register_push_stack_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: ax_pseudo_register_push_stack = <%s>\n",
+                      host_address_to_string (gdbarch->ax_pseudo_register_push_stack));
   fprintf_unfiltered (file,
                       "gdbarch_dump: believe_pcc_promotion = %s\n",
                       plongest (gdbarch->believe_pcc_promotion));
@@ -1740,6 +1758,54 @@ set_gdbarch_num_pseudo_regs (struct gdbarch *gdbarch,
   gdbarch->num_pseudo_regs = num_pseudo_regs;
 }
 
+int
+gdbarch_ax_pseudo_register_collect_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->ax_pseudo_register_collect != NULL;
+}
+
+int
+gdbarch_ax_pseudo_register_collect (struct gdbarch *gdbarch, struct agent_expr *ax, int reg)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->ax_pseudo_register_collect != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_ax_pseudo_register_collect called\n");
+  return gdbarch->ax_pseudo_register_collect (gdbarch, ax, reg);
+}
+
+void
+set_gdbarch_ax_pseudo_register_collect (struct gdbarch *gdbarch,
+                                        gdbarch_ax_pseudo_register_collect_ftype ax_pseudo_register_collect)
+{
+  gdbarch->ax_pseudo_register_collect = ax_pseudo_register_collect;
+}
+
+int
+gdbarch_ax_pseudo_register_push_stack_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->ax_pseudo_register_push_stack != NULL;
+}
+
+int
+gdbarch_ax_pseudo_register_push_stack (struct gdbarch *gdbarch, struct agent_expr *ax, int reg)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->ax_pseudo_register_push_stack != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_ax_pseudo_register_push_stack called\n");
+  return gdbarch->ax_pseudo_register_push_stack (gdbarch, ax, reg);
+}
+
+void
+set_gdbarch_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
+                                           gdbarch_ax_pseudo_register_push_stack_ftype ax_pseudo_register_push_stack)
+{
+  gdbarch->ax_pseudo_register_push_stack = ax_pseudo_register_push_stack;
+}
+
 int
 gdbarch_sp_regnum (struct gdbarch *gdbarch)
 {
index 443e1d5fd81acfd5ce391ada62b4cf9b479cc802..4017f482a7e90d568361993dca5030441d60ad84 100644 (file)
@@ -53,6 +53,7 @@ struct target_desc;
 struct displaced_step_closure;
 struct core_regset_section;
 struct syscall;
+struct agent_expr;
 
 /* The architecture associated with the connection to the target.
  
@@ -232,6 +233,25 @@ extern void set_gdbarch_num_regs (struct gdbarch *gdbarch, int num_regs);
 extern int gdbarch_num_pseudo_regs (struct gdbarch *gdbarch);
 extern void set_gdbarch_num_pseudo_regs (struct gdbarch *gdbarch, int num_pseudo_regs);
 
+/* Assemble agent expression bytecode to collect pseudo-register REG.
+   Return -1 if something goes wrong, 0 otherwise. */
+
+extern int gdbarch_ax_pseudo_register_collect_p (struct gdbarch *gdbarch);
+
+typedef int (gdbarch_ax_pseudo_register_collect_ftype) (struct gdbarch *gdbarch, struct agent_expr *ax, int reg);
+extern int gdbarch_ax_pseudo_register_collect (struct gdbarch *gdbarch, struct agent_expr *ax, int reg);
+extern void set_gdbarch_ax_pseudo_register_collect (struct gdbarch *gdbarch, gdbarch_ax_pseudo_register_collect_ftype *ax_pseudo_register_collect);
+
+/* Assemble agent expression bytecode to push the value of pseudo-register
+   REG on the interpreter stack.
+   Return -1 if something goes wrong, 0 otherwise. */
+
+extern int gdbarch_ax_pseudo_register_push_stack_p (struct gdbarch *gdbarch);
+
+typedef int (gdbarch_ax_pseudo_register_push_stack_ftype) (struct gdbarch *gdbarch, struct agent_expr *ax, int reg);
+extern int gdbarch_ax_pseudo_register_push_stack (struct gdbarch *gdbarch, struct agent_expr *ax, int reg);
+extern void set_gdbarch_ax_pseudo_register_push_stack (struct gdbarch *gdbarch, gdbarch_ax_pseudo_register_push_stack_ftype *ax_pseudo_register_push_stack);
+
 /* GDB's standard (or well known) register numbers.  These can map onto
    a real register or a pseudo (computed) register or not be defined at
    all (-1).
index 5b661167123180790f3527cda69951f6786afdbd..fe3a8d3deea3b51e717f7e0110a58fcbd9b4a3a3 100755 (executable)
@@ -427,6 +427,15 @@ v:int:num_regs:::0:-1
 # combinations of other registers, or they may be computed by GDB.
 v:int:num_pseudo_regs:::0:0::0
 
+# Assemble agent expression bytecode to collect pseudo-register REG.
+# Return -1 if something goes wrong, 0 otherwise.
+M:int:ax_pseudo_register_collect:struct agent_expr *ax, int reg:ax, reg
+
+# Assemble agent expression bytecode to push the value of pseudo-register
+# REG on the interpreter stack.
+# Return -1 if something goes wrong, 0 otherwise.
+M:int:ax_pseudo_register_push_stack:struct agent_expr *ax, int reg:ax, reg
+
 # GDB's standard (or well known) register numbers.  These can map onto
 # a real register or a pseudo (computed) register or not be defined at
 # all (-1).
@@ -919,6 +928,7 @@ struct target_desc;
 struct displaced_step_closure;
 struct core_regset_section;
 struct syscall;
+struct agent_expr;
 
 /* The architecture associated with the connection to the target.
  
index e6df5f56a6899d6ba69e5af611cf6aa588fb781d..9b384ac17879bb64e9446cbedddbd5ea9d6fbd4f 100644 (file)
@@ -58,6 +58,7 @@
 #include "dwarf2-frame.h"
 #include "user-regs.h"
 #include "valprint.h"
+#include "ax.h"
 
 static const struct objfile_data *mips_pdr_data;
 
@@ -616,6 +617,48 @@ mips_pseudo_register_write (struct gdbarch *gdbarch,
     internal_error (__FILE__, __LINE__, _("bad register size"));
 }
 
+static int
+mips_ax_pseudo_register_collect (struct gdbarch *gdbarch,
+                                struct agent_expr *ax, int reg)
+{
+  int rawnum = reg % gdbarch_num_regs (gdbarch);
+  gdb_assert (reg >= gdbarch_num_regs (gdbarch)
+             && reg < 2 * gdbarch_num_regs (gdbarch));
+
+  ax_reg_mask (ax, rawnum);
+
+  return 0;
+}
+
+static int
+mips_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
+                                   struct agent_expr *ax, int reg)
+{
+  int rawnum = reg % gdbarch_num_regs (gdbarch);
+  gdb_assert (reg >= gdbarch_num_regs (gdbarch)
+             && reg < 2 * gdbarch_num_regs (gdbarch));
+  if (register_size (gdbarch, rawnum) >= register_size (gdbarch, reg))
+    {
+      ax_reg (ax, rawnum);
+
+      if (register_size (gdbarch, rawnum) > register_size (gdbarch, reg))
+        {
+         if (!gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p
+             || gdbarch_byte_order (gdbarch) != BFD_ENDIAN_BIG)
+           {
+             ax_const_l (ax, 32);
+             ax_simple (ax, aop_lsh);
+           }
+         ax_const_l (ax, 32);
+         ax_simple (ax, aop_rsh_signed);
+       }
+    }
+  else
+    internal_error (__FILE__, __LINE__, _("bad register size"));
+
+  return 0;
+}
+
 /* Table to translate MIPS16 register field to actual register number.  */
 static int mips16_to_32_reg[8] = { 16, 17, 2, 3, 4, 5, 6, 7 };
 
@@ -5933,6 +5976,11 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_pseudo_register_read (gdbarch, mips_pseudo_register_read);
   set_gdbarch_pseudo_register_write (gdbarch, mips_pseudo_register_write);
 
+  set_gdbarch_ax_pseudo_register_collect (gdbarch,
+                                         mips_ax_pseudo_register_collect);
+  set_gdbarch_ax_pseudo_register_push_stack
+      (gdbarch, mips_ax_pseudo_register_push_stack);
+
   set_gdbarch_elf_make_msymbol_special (gdbarch,
                                        mips_elf_make_msymbol_special);