This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers


Hi guys,

Here's the new version of the patch. I've made some modifications in
order to "follow the pattern" already established in this portion of the
code. As a side effect, the code is cleaner now since it has less #ifdef
statements and uses control variables to decide if a ptrace flag is
present or not.

Thanks to Luis Machado for his valuable comments regarding this.

Best regards,

-- 
Sérgio Durigan Júnior
Linux on Power Toolchain - Software Engineer
Linux Technology Center - LTC
IBM Brazil

2009-01-06  Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com>

	* configure.ac: Checking the existence of PTRACE_GETREGS,
	PTRACE_SETREGS, PTRACE_GETREGS64, PTRACE_SETREGS64,
	PTRACE_GETFPREGS and PTRACE_SETFPREGS in <asm/ptrace.h>.
	* ppc-linux-nat.c (have_ptrace_getsetregs): New variable.
	(have_ptrace_getsetfpregs): Likewise.
	(fetch_all_gp_regs): New function.
	(fetch_gp_regs): New function.
	(fetch_all_fp_regs): Likewise.
	(fetch_fp_regs): New function.
	(fetch_ppc_registers): Using the new methods to fetch general-
	purpose and floating-pointer registers.
	(store_all_gp_regs): New function.
	(store_gp_regs): Likewise.
	(store_all_fp_regs): New function.
	(store_fp_regs): Likewise.
	(store_ppc_registers): Using the new methods to store general-
	purpose and floating-pointer registers.

diff --git a/gdb/configure.ac b/gdb/configure.ac
index 4e0cf7d..ff50f40 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -943,7 +943,8 @@ AC_CHECK_MEMBERS([struct reg.r_fs, struct reg.r_gs], [], [],
 # See if <sys/ptrace.h> provides the PTRACE_GETREGS request.
 AC_MSG_CHECKING(for PTRACE_GETREGS)
 AC_CACHE_VAL(gdb_cv_have_ptrace_getregs,
-[AC_TRY_COMPILE([#include <sys/ptrace.h>],
+[AC_TRY_COMPILE([#include <sys/ptrace.h>
+ #include <asm/ptrace.h>],
 		[PTRACE_GETREGS;],
 		[gdb_cv_have_ptrace_getregs=yes],
 		[gdb_cv_have_ptrace_getregs=no])])
@@ -953,10 +954,81 @@ if test $gdb_cv_have_ptrace_getregs = yes; then
   [Define if sys/ptrace.h defines the PTRACE_GETREGS request.])
 fi
 
+# See if <sys/ptrace.h> provides the PTRACE_SETREGS request.
+AC_MSG_CHECKING(for PTRACE_SETREGS)
+AC_CACHE_VAL(gdb_cv_have_ptrace_setregs,
+[AC_TRY_COMPILE([#include <sys/ptrace.h>
+ #include <asm/ptrace.h>],
+		[PTRACE_SETREGS;],
+		[gdb_cv_have_ptrace_setregs=yes],
+		[gdb_cv_have_ptrace_setregs=no])])
+AC_MSG_RESULT($gdb_cv_have_ptrace_setregs)
+if test $gdb_cv_have_ptrace_setregs = yes; then
+  AC_DEFINE(HAVE_PTRACE_SETREGS, 1, 
+  [Define if sys/ptrace.h defines the PTRACE_SETREGS request.])
+fi
+
+# See if <sys/ptrace.h> provides the PTRACE_GETREGS64 request.
+AC_MSG_CHECKING(for PTRACE_GETREGS64)
+AC_CACHE_VAL(gdb_cv_have_ptrace_getregs64,
+[AC_TRY_COMPILE([#include <sys/ptrace.h>
+ #include <asm/ptrace.h>],
+		[PTRACE_GETREGS64;],
+		[gdb_cv_have_ptrace_getregs64=yes],
+		[gdb_cv_have_ptrace_getregs64=no])])
+AC_MSG_RESULT($gdb_cv_have_ptrace_getregs64)
+if test $gdb_cv_have_ptrace_getregs64 = yes; then
+  AC_DEFINE(HAVE_PTRACE_GETREGS64, 1, 
+  [Define if sys/ptrace.h defines the PTRACE_GETREGS64 request.])
+fi
+
+# See if <sys/ptrace.h> provides the PTRACE_SETREGS64 request.
+AC_MSG_CHECKING(for PTRACE_SETREGS64)
+AC_CACHE_VAL(gdb_cv_have_ptrace_setregs64,
+[AC_TRY_COMPILE([#include <sys/ptrace.h>
+ #include <asm/ptrace.h>],
+		[PTRACE_SETREGS64;],
+		[gdb_cv_have_ptrace_setregs64=yes],
+		[gdb_cv_have_ptrace_setregs64=no])])
+AC_MSG_RESULT($gdb_cv_have_ptrace_setregs64)
+if test $gdb_cv_have_ptrace_setregs64 = yes; then
+  AC_DEFINE(HAVE_PTRACE_SETREGS64, 1, 
+  [Define if sys/ptrace.h defines the PTRACE_SETREGS64 request.])
+fi
+
+# See if <sys/ptrace.h> provides the PTRACE_GETFPREGS request.
+AC_MSG_CHECKING(for PTRACE_GETFPREGS)
+AC_CACHE_VAL(gdb_cv_have_ptrace_getfpregs,
+[AC_TRY_COMPILE([#include <sys/ptrace.h>
+ #include <asm/ptrace.h>],
+		[PTRACE_GETFPREGS;],
+		[gdb_cv_have_ptrace_getfpregs=yes],
+		[gdb_cv_have_ptrace_getfpregs=no])])
+AC_MSG_RESULT($gdb_cv_have_ptrace_getfpregs)
+if test $gdb_cv_have_ptrace_getfpregs = yes; then
+  AC_DEFINE(HAVE_PTRACE_GETFPREGS, 1, 
+  [Define if sys/ptrace.h defines the PTRACE_GETFPREGS request.])
+fi
+
+# See if <sys/ptrace.h> provides the PTRACE_SETFPREGS request.
+AC_MSG_CHECKING(for PTRACE_SETFPREGS)
+AC_CACHE_VAL(gdb_cv_have_ptrace_setfpregs,
+[AC_TRY_COMPILE([#include <sys/ptrace.h>
+ #include <asm/ptrace.h>],
+		[PTRACE_SETFPREGS;],
+		[gdb_cv_have_ptrace_setfpregs=yes],
+		[gdb_cv_have_ptrace_setfpregs=no])])
+AC_MSG_RESULT($gdb_cv_have_ptrace_setfpregs)
+if test $gdb_cv_have_ptrace_setfpregs = yes; then
+  AC_DEFINE(HAVE_PTRACE_SETFPREGS, 1, 
+  [Define if sys/ptrace.h defines the PTRACE_SETFPREGS request.])
+fi
+
 # See if <sys/ptrace.h> provides the PTRACE_GETFPXREGS request.
 AC_MSG_CHECKING(for PTRACE_GETFPXREGS)
 AC_CACHE_VAL(gdb_cv_have_ptrace_getfpxregs,
-[AC_TRY_COMPILE([#include <sys/ptrace.h>],
+[AC_TRY_COMPILE([#include <sys/ptrace.h>
+ #include <asm/ptrace.h>],
 		[PTRACE_GETFPXREGS;],
 		[gdb_cv_have_ptrace_getfpxregs=yes],
 		[gdb_cv_have_ptrace_getfpxregs=no])])
@@ -966,6 +1038,20 @@ if test $gdb_cv_have_ptrace_getfpxregs = yes; then
   [Define if sys/ptrace.h defines the PTRACE_GETFPXREGS request.])
 fi
 
+# See if <sys/ptrace.h> provides the PTRACE_SETFPXREGS request.
+AC_MSG_CHECKING(for PTRACE_SETFPXREGS)
+AC_CACHE_VAL(gdb_cv_have_ptrace_setfpxregs,
+[AC_TRY_COMPILE([#include <sys/ptrace.h>
+ #include <asm/ptrace.h>],
+		[PTRACE_SETFPXREGS;],
+		[gdb_cv_have_ptrace_setfpxregs=yes],
+		[gdb_cv_have_ptrace_setfpxregs=no])])
+AC_MSG_RESULT($gdb_cv_have_ptrace_setfpxregs)
+if test $gdb_cv_have_ptrace_setfpxregs = yes; then
+  AC_DEFINE(HAVE_PTRACE_SETFPXREGS, 1,
+  [Define if sys/ptrace.h defines the PTRACE_SETFPXREGS request.])
+fi
+
 # See if <sys/ptrace.h> provides the PT_GETDBREGS request.
 AC_MSG_CHECKING(for PT_GETDBREGS)
 AC_CACHE_VAL(gdb_cv_have_pt_getdbregs,
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index b946093..f2ecf7c 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -108,6 +108,27 @@
 #define PTRACE_GETSIGINFO    0x4202
 #endif
 
+/* Similarly for the general-purpose (gp0 -- gp31)
+   and floating-point registers (fp0 -- fp31).  */
+#ifndef PTRACE_GETREGS
+#define PTRACE_GETREGS 12
+#endif
+#ifndef PTRACE_SETREGS
+#define PTRACE_SETREGS 13
+#endif
+#ifndef PTRACE_GETFPREGS
+#define PTRACE_GETFPREGS 14
+#endif
+#ifndef PTRACE_SETFPREGS
+#define PTRACE_SETFPREGS 15
+#endif
+#ifndef PTRACE_GETREGS64
+#define PTRACE_GETREGS64 22
+#endif
+#ifndef PTRACE_SETREGS64
+#define PTRACE_SETREGS64 23
+#endif
+
 /* This oddity is because the Linux kernel defines elf_vrregset_t as
    an array of 33 16 bytes long elements.  I.e. it leaves out vrsave.
    However the PTRACE_GETVRREGS and PTRACE_SETVRREGS requests return
@@ -218,6 +239,18 @@ int have_ptrace_getvrregs = 1;
    error.  */
 int have_ptrace_getsetevrregs = 1;
 
+/* Non-zero if our kernel may support the PTRACE_GETREGS and
+   PTRACE_SETREGS (for both 32- and 64-bit) requests, for
+   reading and writing the general-purpose registers.  Zero if
+   we've tried one of them and gotten an error.  */
+int have_ptrace_getsetregs = 1;
+
+/* Non-zero if our kernel may support the PTRACE_GETFPREGS and
+   PTRACE_SETFPREGS requests, for reading and writing the
+   floating-pointers registers.  Zero if we've tried one of
+   them and gotten an error.  */
+int have_ptrace_getsetfpregs = 1;
+
 /* *INDENT-OFF* */
 /* registers layout, as presented by the ptrace interface:
 PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5, PT_R6, PT_R7,
@@ -601,6 +634,89 @@ fetch_altivec_registers (struct regcache *regcache, int tid)
   supply_vrregset (regcache, &regs);
 }
 
+static int
+fetch_all_gp_regs (struct regcache *regcache, int tid)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int get_req;
+  gdb_gregset_t gregset;
+
+  gdb_assert (tdep->wordsize == 4 || tdep->wordsize == 8);
+
+  get_req = (tdep->wordsize == 4) ? PTRACE_GETREGS : PTRACE_GETREGS64;
+
+  if (ptrace (get_req, tid, 0, (void *) &gregset) < 0)
+    {
+      if (errno == EIO)
+        {
+          have_ptrace_getsetregs = 0;
+          return 0;
+        }
+      perror_with_name (_("Couldn't get general-purpose registers."));
+    }
+
+  supply_gregset (regcache, (const gdb_gregset_t *) &gregset);
+
+  return 1;
+}
+
+static void
+fetch_gp_regs (struct regcache *regcache, int tid)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int i;
+
+  if (have_ptrace_getsetregs)
+    if (fetch_all_gp_regs (regcache, tid))
+      return;
+
+  /* If we've hit this point, it doesn't really matter which
+     architecture we are using.  We just need to read the
+     registers in the "old-fashioned way".  */
+  for (i = 0; i < ppc_num_gprs; i++)
+    fetch_register (regcache, tid, tdep->ppc_gp0_regnum + i);
+}
+
+static int
+fetch_all_fp_regs (struct regcache *regcache, int tid)
+{
+  gdb_fpregset_t fpregs;
+
+  if (ptrace (PTRACE_GETFPREGS, tid, 0, (void *) &fpregs) < 0)
+    {
+      if (errno == EIO)
+        {
+          have_ptrace_getsetfpregs = 0;
+          return 0;
+        }
+      perror_with_name (_("Couldn't get floating point status"));
+    }
+
+  supply_fpregset (regcache, (const gdb_fpregset_t *) &fpregs);
+
+  return 1;
+}
+
+static void
+fetch_fp_regs (struct regcache *regcache, int tid)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int i;
+
+  if (have_ptrace_getsetfpregs)
+    if (fetch_all_fp_regs (regcache, tid))
+      return;
+ 
+  /* If we've hit this point, it doesn't really matter which
+     architecture we are using.  We just need to read the
+     registers in the "old-fashioned way".  */
+  for (i = 0; i < ppc_num_fprs; i++)
+    fetch_register (regcache, tid, tdep->ppc_fp0_regnum + i);
+}
+
 static void 
 fetch_ppc_registers (struct regcache *regcache, int tid)
 {
@@ -608,11 +724,9 @@ fetch_ppc_registers (struct regcache *regcache, int tid)
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
-  for (i = 0; i < ppc_num_gprs; i++)
-    fetch_register (regcache, tid, tdep->ppc_gp0_regnum + i);
+  fetch_gp_regs (regcache, tid);
   if (tdep->ppc_fp0_regnum >= 0)
-    for (i = 0; i < ppc_num_fprs; i++)
-      fetch_register (regcache, tid, tdep->ppc_fp0_regnum + i);
+    fetch_fp_regs (regcache, tid);
   fetch_register (regcache, tid, gdbarch_pc_regnum (gdbarch));
   if (tdep->ppc_ps_regnum != -1)
     fetch_register (regcache, tid, tdep->ppc_ps_regnum);
@@ -969,18 +1083,121 @@ store_altivec_registers (const struct regcache *regcache, int tid)
     perror_with_name (_("Couldn't write AltiVec registers"));
 }
 
+static int
+store_all_gp_regs (const struct regcache *regcache, int tid, int regno)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  /* Get/set requisitions depending on the arch.  */
+  int get_req, set_req;
+  gdb_gregset_t gregset;
+
+  gdb_assert (tdep->wordsize == 4 || tdep->wordsize == 8);
+
+  get_req = (tdep->wordsize == 4) ? PTRACE_GETREGS : PTRACE_GETREGS64;
+  set_req = (tdep->wordsize == 4) ? PTRACE_SETREGS : PTRACE_SETREGS64;
+
+  if (ptrace (get_req, tid, 0, (void *) &gregset) < 0)
+    {
+      if (errno == EIO)
+        {
+          have_ptrace_getsetregs = 0;
+          return 0;
+        }
+      perror_with_name (_("Couldn't get general-purpose registers."));
+    }
+
+  fill_gregset (regcache, &gregset, regno);
+
+  if (ptrace (set_req, tid, 0, (void *) &gregset) < 0)
+    {
+      if (errno == EIO)
+        {
+          have_ptrace_getsetregs = 0;
+          return 0;
+        }
+      perror_with_name (_("Couldn't write general-purpose registers."));
+    }
+
+  return 1;
+}
+
 static void
-store_ppc_registers (const struct regcache *regcache, int tid)
+store_gp_regs (const struct regcache *regcache, int tid, int regno)
 {
-  int i;
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  
+  int i;
+
+  if (have_ptrace_getsetregs)
+    if (store_all_gp_regs (regcache, tid, regno))
+      return;
+
+  /* If we hit this point, it doesn't really matter which
+     architecture we are using.  We just need to store the
+     registers in the "old-fashioned way".  */
   for (i = 0; i < ppc_num_gprs; i++)
     store_register (regcache, tid, tdep->ppc_gp0_regnum + i);
+}
+
+static int
+store_all_fp_regs (const struct regcache *regcache, int tid, int regno)
+{
+  gdb_fpregset_t fpregs;
+
+  if (ptrace (PTRACE_GETFPREGS, tid, 0, (void *) &fpregs) < 0)
+    {
+      if (errno == EIO)
+        {
+          have_ptrace_getsetfpregs = 0;
+          return 0;
+        }
+      perror_with_name (_("Couldn't get floating point status"));
+    }
+
+  fill_fpregset (regcache, &fpregs, regno);
+
+  if (ptrace (PTRACE_SETFPREGS, tid, 0, (void *) &fpregs) < 0)
+    {
+      if (errno == EIO)
+        {
+          have_ptrace_getsetfpregs = 0;
+          return 0;
+        }
+      perror_with_name (_("Couldn't write floating point status"));
+    }
+
+  return 1;
+}
+
+static void
+store_fp_regs (const struct regcache *regcache, int tid, int regno)
+{
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int i;
+
+  if (have_ptrace_getsetfpregs)
+    if (store_all_fp_regs (regcache, tid, regno))
+      return;
+
+  /* If we hit this point, it doesn't really matter which
+     architecture we are using.  We just need to store the
+     registers in the "old-fashioned way".  */
+  for (i = 0; i < ppc_num_fprs; i++)
+    store_register (regcache, tid, tdep->ppc_fp0_regnum + i);
+}
+
+static void
+store_ppc_registers (const struct regcache *regcache, int tid)
+{
+  int i;
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ 
+  store_gp_regs (regcache, tid, -1);
   if (tdep->ppc_fp0_regnum >= 0)
-    for (i = 0; i < ppc_num_fprs; i++)
-      store_register (regcache, tid, tdep->ppc_fp0_regnum + i);
+    store_fp_regs (regcache, tid, -1);
   store_register (regcache, tid, gdbarch_pc_regnum (gdbarch));
   if (tdep->ppc_ps_regnum != -1)
     store_register (regcache, tid, tdep->ppc_ps_regnum);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]