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]

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


Hi guys,

The following patch improves the way GDB does fetch/store operations on
general-purpose and floating-point registers on the PowerPC
architecture. Basically, it uses the ptrace() options
PTRACE_{GET,SET}REGS, PTRACE_{GET,SET}FPREGS and PTRACE_{GET,SET}REGS64.

I've tested it running a regression test on various machines/kernel
combinations, and it does not cause any regression.

Comments, as always, are welcome.

Regards,

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


2008-10-07  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 (fetch_gp_regs): New.
	(fetch_fp_regs): New.
	(fetch_ppc_registers): Using the new method to fetch general-
	purpose and floating-pointer registers.
	(store_gp_regs): New.
	(store_fp_regs): New.
	(store_ppc_registers): Using the new method to store general-
	purpose and floating-pointer registers.

diff --git a/gdb/configure.ac b/gdb/configure.ac
index 680fba0..5263edb 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -924,7 +924,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])])
@@ -934,10 +935,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])])
@@ -947,6 +1019,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 ed197f1..ffb1e79 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -588,6 +588,70 @@ fetch_altivec_registers (struct regcache *regcache, int tid)
   supply_vrregset (regcache, &regs);
 }
 
+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;
+  gdb_gregset_t gregset;
+
+  gdb_assert (tdep->wordsize == 4 || tdep->wordsize == 8);
+
+  if (tdep->wordsize == 4)
+    {
+#ifdef HAVE_PTRACE_GETREGS
+      /* PPC 32-bit.  */
+      if (ptrace (PTRACE_GETREGS, tid, 0, (void *) &gregset) < 0)
+        perror_with_name (_("Couldn't get general-purpose registers."));
+
+      supply_gregset (regcache, (const gdb_gregset_t *) &gregset);
+      return;
+#endif /* HAVE_PTRACE_GETREGS */
+    }
+  else if (tdep->wordsize == 8)
+    {
+#ifdef HAVE_PTRACE_GETREGS64
+      /* PPC 64-bit.  */
+      if (ptrace (PTRACE_GETREGS64, tid, 0, (void *) &gregset) < 0)
+        perror_with_name (_("Couldn't get general-purpose registers."));
+
+      supply_gregset (regcache, (const gdb_gregset_t *) &gregset);
+      return;
+#endif /* HAVE_PTRACE_GETREGS64 */
+    }
+
+  /* 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);
+}
+
+#ifdef HAVE_PTRACE_GETFPREGS
+
+static void
+fetch_fp_regs (struct regcache *regcache, int tid)
+{
+  gdb_fpregset_t fpregs;
+
+  if (ptrace (PTRACE_GETFPREGS, tid, 0, (void *) &fpregs) < 0)
+    perror_with_name (_("Couldn't get floating point status"));
+
+  supply_fpregset (regcache, (const gdb_fpregset_t *) &fpregs);
+}
+
+#else /* HAVE_PTRACE_GETFPREGS */
+
+static void
+fetch_fp_regs (struct regcache *regcache, int tid)
+{
+  internal_error (__FILE__, __LINE__,
+                  "The function should not be called.");
+}
+
+#endif /* HAVE_PTRACE_GEFPTREGS */
+
 static void 
 fetch_ppc_registers (struct regcache *regcache, int tid)
 {
@@ -595,11 +659,14 @@ 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)
+#ifdef HAVE_PTRACE_GETFPREGS
+    fetch_fp_regs (regcache, tid);
+#else /* HAVE_PTRACE_GETFPREGS */
     for (i = 0; i < ppc_num_fprs; i++)
       fetch_register (regcache, tid, tdep->ppc_fp0_regnum + i);
+#endif /* HAVE_PTRACE_GETFPREGS */
   fetch_register (regcache, tid, gdbarch_pc_regnum (gdbarch));
   if (tdep->ppc_ps_regnum != -1)
     fetch_register (regcache, tid, tdep->ppc_ps_regnum);
@@ -957,17 +1024,92 @@ store_altivec_registers (const struct regcache *regcache, int tid)
 }
 
 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;
+  gdb_gregset_t gregset;
+
+  gdb_assert (tdep->wordsize == 4 || tdep->wordsize == 8);
+
+  if (tdep->wordsize == 4)
+    {
+#if defined(HAVE_PTRACE_SETREGS) && defined(HAVE_PTRACE_GETREGS)
+      /* PPC 32-bit.  */
+      if (ptrace (PTRACE_GETREGS, tid, 0, (void *) &gregset) < 0)
+        perror_with_name (_("Couldn't get general-purpose registers."));
+
+      fill_gregset (regcache, &gregset, regno);
+
+      if (ptrace (PTRACE_SETREGS, tid, 0, (void *) &gregset) < 0)
+        perror_with_name (_("Couldn't get general-purpose registers."));
+      return;
+#endif /* HAVE_PTRACE_SETREGS && HAVE_PTRACE_GETREGS */
+    }
+  else if (tdep->wordsize == 8)
+    {
+#if defined(HAVE_PTRACE_SETREGS64) && defined(HAVE_PTRACE_GETREGS64)
+      /* PPC 64-bit.  */
+      if (ptrace (PTRACE_GETREGS64, tid, 0, (void *) &gregset) < 0)
+        perror_with_name (_("Couldn't get general-purpose registers."));
+
+      fill_gregset (regcache, &gregset, regno);
+
+      if (ptrace (PTRACE_SETREGS64, tid, 0, (void *) &gregset) < 0)
+        perror_with_name (_("Couldn't get general-purpose registers."));
+      return;
+#endif /* HAVE_PTRACE_SETREGS64 && HAVE_PTRACE_GETREGS64 */
+    }
+  /* If we've 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);
+}
+
+#if defined(HAVE_PTRACE_SETFPREGS) && defined(HAVE_PTRACE_GETFPREGS)
+
+static void
+store_fp_regs (const struct regcache *regcache, int tid, int regno)
+{
+  gdb_fpregset_t fpregs;
+
+  if (ptrace (PTRACE_GETFPREGS, tid, 0, (void *) &fpregs) < 0)
+    perror_with_name (_("Couldn't get floating point status"));
+
+  fill_fpregset (regcache, &fpregs, regno);
+
+  if (ptrace (PTRACE_SETFPREGS, tid, 0, (void *) &fpregs) < 0)
+    perror_with_name (_("Couldn't write floating point status"));
+}
+
+#else /* HAVE_PTRACE_SETFPREGS && HAVE_PTRACE_GETFPREGS */
+
+static void
+store_fp_regs (const struct regcache *regcache, int tid)
+{
+  internal_error (__FILE__, __LINE__,
+                  "The function should not be called.");
+}
+
+#endif /* HAVE_PTRACE_SETFPREGS && HAVE_PTRACE_GETFPREGS */
+
+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)
+#if defined(HAVE_PTRACE_SETFPREGS) && defined(HAVE_PTRACE_GETFPREGS)
+    store_fp_regs (regcache, tid, -1);
+#else /* HAVE_PTRACE_SETFPREGS && HAVE_PTRACE_GETFPREGS */
     for (i = 0; i < ppc_num_fprs; i++)
       store_register (regcache, tid, tdep->ppc_fp0_regnum + i);
+#endif /* HAVE_PTRACE_SETFPREGS && HAVE_PTRACE_GETFPREGS */
   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]