* [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers
@ 2008-10-07 18:32 Sérgio Durigan Júnior
2008-10-16 20:07 ` Sérgio Durigan Júnior
2008-11-17 23:22 ` [PATCH] Improve the fetch/store of general-purpose and floating-point " Sérgio Durigan Júnior
0 siblings, 2 replies; 15+ messages in thread
From: Sérgio Durigan Júnior @ 2008-10-07 18:32 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1106 bytes --]
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.
[-- Attachment #2: read-regs.patch --]
[-- Type: text/x-patch, Size: 10893 bytes --]
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, ®s);
}
+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);
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers 2008-10-07 18:32 [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers Sérgio Durigan Júnior @ 2008-10-16 20:07 ` Sérgio Durigan Júnior 2009-01-07 0:44 ` Sérgio Durigan Júnior 2008-11-17 23:22 ` [PATCH] Improve the fetch/store of general-purpose and floating-point " Sérgio Durigan Júnior 1 sibling, 1 reply; 15+ messages in thread From: Sérgio Durigan Júnior @ 2008-10-16 20:07 UTC (permalink / raw) To: gdb-patches Hey guys, Ping? Regards, On Tue, 2008-10-07 at 15:32 -0300, Sérgio Durigan Júnior wrote: > 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 ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers 2008-10-16 20:07 ` Sérgio Durigan Júnior @ 2009-01-07 0:44 ` Sérgio Durigan Júnior 2009-01-07 9:56 ` Mark Kettenis 0 siblings, 1 reply; 15+ messages in thread From: Sérgio Durigan Júnior @ 2009-01-07 0:44 UTC (permalink / raw) To: gdb-patches [-- Attachment #1: Type: text/plain, Size: 1310 bytes --] 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. [-- Attachment #2: read-regs.patch --] [-- Type: text/x-patch, Size: 13073 bytes --] 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, ®s); } +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); ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers 2009-01-07 0:44 ` Sérgio Durigan Júnior @ 2009-01-07 9:56 ` Mark Kettenis 2009-01-07 16:09 ` Sérgio Durigan Júnior 0 siblings, 1 reply; 15+ messages in thread From: Mark Kettenis @ 2009-01-07 9:56 UTC (permalink / raw) To: sergiodj; +Cc: gdb-patches > From: =?ISO-8859-1?Q?S=E9rgio?= Durigan =?ISO-8859-1?Q?J=FAnior?= <sergiodj@br.ibm.com> > Date: Tue, 06 Jan 2009 22:43:38 -0200 > > 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. Hi Sergio, Do you really need those autoconf checks for PTRACE_GETREGS & friends? I don't see things like HAVE_PTRACE_GETREGS used in the code at all, which makes sense since you can just check whether PTRACE_GETREGS is defined in your code. The reason that there are some autoconf checks for PTRACE_XXX symbols is that at some point there were some (broken) versions of glibc that had the PTRACE_XXX symbols as enums, but not as #defines. But those versions predate the introduction of PTRACE_GETREGS & friends on Linux for PowerPC by almost a decade now. Th reason I'm somewhat concerned with adding new autoconf checks is that on slow systems running the autoconf checks can take quite a while. ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers 2009-01-07 9:56 ` Mark Kettenis @ 2009-01-07 16:09 ` Sérgio Durigan Júnior 2009-01-08 17:46 ` Sérgio Durigan Júnior 0 siblings, 1 reply; 15+ messages in thread From: Sérgio Durigan Júnior @ 2009-01-07 16:09 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches Hi Mark, On Wed, 2009-01-07 at 10:55 +0100, Mark Kettenis wrote: > Do you really need those autoconf checks for PTRACE_GETREGS & friends? > I don't see things like HAVE_PTRACE_GETREGS used in the code at all, > which makes sense since you can just check whether PTRACE_GETREGS is > defined in your code. Hmm, I think you're right. I'm going to remove those checks and resubmit the patch. Thanks! -- Sérgio Durigan Júnior Linux on Power Toolchain - Software Engineer Linux Technology Center - LTC IBM Brazil ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers 2009-01-07 16:09 ` Sérgio Durigan Júnior @ 2009-01-08 17:46 ` Sérgio Durigan Júnior 2009-01-09 12:26 ` Luis Machado 0 siblings, 1 reply; 15+ messages in thread From: Sérgio Durigan Júnior @ 2009-01-08 17:46 UTC (permalink / raw) To: gdb-patches [-- Attachment #1: Type: text/plain, Size: 837 bytes --] Hey guys, Here's the new version, without the modifications in configure.ac. Thanks, -- Sérgio Durigan Júnior Linux on Power Toolchain - Software Engineer Linux Technology Center - LTC IBM Brazil 2009-01-08 Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com> * 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. [-- Attachment #2: read-regs.patch --] [-- Type: text/x-patch, Size: 8553 bytes --] 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, ®s); } +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); ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers 2009-01-08 17:46 ` Sérgio Durigan Júnior @ 2009-01-09 12:26 ` Luis Machado 2009-01-21 17:28 ` Sérgio Durigan Júnior 0 siblings, 1 reply; 15+ messages in thread From: Luis Machado @ 2009-01-09 12:26 UTC (permalink / raw) To: Sérgio Durigan Júnior; +Cc: gdb-patches, Mark Kettenis On Thu, 2009-01-08 at 15:45 -0200, Sérgio Durigan Júnior wrote: > Hey guys, > > Here's the new version, without the modifications in configure.ac. > > Thanks, > The patch looks good to me, except for two little comments on the error messages. Switch "write" to "set" and "status" to "register", nothing critical, just for the sake of keeping a standard. Else OK. Luis ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers 2009-01-09 12:26 ` Luis Machado @ 2009-01-21 17:28 ` Sérgio Durigan Júnior 2009-04-28 20:07 ` Joel Brobecker 0 siblings, 1 reply; 15+ messages in thread From: Sérgio Durigan Júnior @ 2009-01-21 17:28 UTC (permalink / raw) To: luisgpm; +Cc: gdb-patches, Mark Kettenis [-- Attachment #1: Type: text/plain, Size: 880 bytes --] Hi Luis, This version of the patch fixes what you suggested. Also, I removed some unecessary checks regarding PPC32/64. Regards, -- Sérgio Durigan Júnior Linux on Power Toolchain - Software Engineer Linux Technology Center - LTC IBM Brazil 2009-01-21 Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com> * 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. [-- Attachment #2: read-regs.patch --] [-- Type: text/x-patch, Size: 7991 bytes --] diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c index b946093..bc1b767 100644 --- a/gdb/ppc-linux-nat.c +++ b/gdb/ppc-linux-nat.c @@ -108,6 +108,21 @@ #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 + /* 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 +233,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 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 +628,84 @@ fetch_altivec_registers (struct regcache *regcache, int tid) supply_vrregset (regcache, ®s); } +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); + gdb_gregset_t gregset; + + if (ptrace (PTRACE_GETREGS, 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 registers.")); + } + + 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 +713,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 +1072,114 @@ 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); + gdb_gregset_t gregset; + + if (ptrace (PTRACE_GETREGS, 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 (PTRACE_SETREGS, tid, 0, (void *) &gregset) < 0) + { + if (errno == EIO) + { + have_ptrace_getsetregs = 0; + return 0; + } + perror_with_name (_("Couldn't set 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 registers.")); + } + + 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 set floating-point registers.")); + } + + 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); ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers 2009-01-21 17:28 ` Sérgio Durigan Júnior @ 2009-04-28 20:07 ` Joel Brobecker 2009-04-29 2:16 ` Sérgio Durigan Júnior 0 siblings, 1 reply; 15+ messages in thread From: Joel Brobecker @ 2009-04-28 20:07 UTC (permalink / raw) To: S?rgio Durigan J?nior; +Cc: luisgpm, gdb-patches, Mark Kettenis Sergio, > 2009-01-21 Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com> > > * 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. Sorry for the delay in reviewing this. I don't know much about ptrace except as a user, but this seems to make sense. The only request I have is for you to write a small comment describing each new function you introduce. The patch is OK with those changes. PS: I assume you tested the change on 2 systems, one with the functionality, and one without? Thanks, -- Joel ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers 2009-04-28 20:07 ` Joel Brobecker @ 2009-04-29 2:16 ` Sérgio Durigan Júnior 2009-04-29 4:05 ` Joel Brobecker 0 siblings, 1 reply; 15+ messages in thread From: Sérgio Durigan Júnior @ 2009-04-29 2:16 UTC (permalink / raw) To: Joel Brobecker; +Cc: luisgpm, gdb-patches, Mark Kettenis Hi Joel, On Tue, 2009-04-28 at 13:07 -0700, Joel Brobecker wrote: > Sergio, > > > 2009-01-21 Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com> > > > > * 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. > > Sorry for the delay in reviewing this. I don't know much about ptrace > except as a user, but this seems to make sense. The only request I have > is for you to write a small comment describing each new function you > introduce. The patch is OK with those changes. So the request is about the ChangeLog, right? Ok, I'll resubmit it with the modifications as soon as possible. > PS: I assume you tested the change on 2 systems, one with the > functionality, and one without? Yes, I did :-). Thanks, -- Sérgio Durigan Júnior Linux on Power Toolchain - Software Engineer Linux Technology Center - LTC IBM Brazil ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers 2009-04-29 2:16 ` Sérgio Durigan Júnior @ 2009-04-29 4:05 ` Joel Brobecker 2009-05-05 18:34 ` Sérgio Durigan Júnior 0 siblings, 1 reply; 15+ messages in thread From: Joel Brobecker @ 2009-04-29 4:05 UTC (permalink / raw) To: S?rgio Durigan J?nior; +Cc: luisgpm, gdb-patches, Mark Kettenis > > Sorry for the delay in reviewing this. I don't know much about ptrace > > except as a user, but this seems to make sense. The only request I have > > is for you to write a small comment describing each new function you > > introduce. The patch is OK with those changes. > > So the request is about the ChangeLog, right? Ok, I'll resubmit it with > the modifications as soon as possible. Actually, no. The comments are for the functions themselves. We're trying to make sure that every new function gets in with some documentation of what it does. It doesn't have to be very long, but sometimes writing what the return value is about is very useful. For instance, I remember that some of your functions will return zero if the operation failed, I think. That's an interesting piece of information to put in the documentation. When the function is obvious, or when it implements a routine that's part of the gdbarch vector, then what we've been doing, lately, is just say "Implements the "bla_bla_bla" gdbarch method." or somesuch (we try not to repeat the documentation to avoid maintenance issues). -- Joel ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers 2009-04-29 4:05 ` Joel Brobecker @ 2009-05-05 18:34 ` Sérgio Durigan Júnior 2009-05-06 16:58 ` Joel Brobecker 0 siblings, 1 reply; 15+ messages in thread From: Sérgio Durigan Júnior @ 2009-05-05 18:34 UTC (permalink / raw) To: Joel Brobecker; +Cc: luisgpm, gdb-patches, Mark Kettenis [-- Attachment #1: Type: text/plain, Size: 1665 bytes --] Hi Joel, On Tue, 2009-04-28 at 21:05 -0700, Joel Brobecker wrote: > Actually, no. The comments are for the functions themselves. We're > trying to make sure that every new function gets in with some > documentation of what it does. It doesn't have to be very long, > but sometimes writing what the return value is about is very useful. > For instance, I remember that some of your functions will return > zero if the operation failed, I think. That's an interesting piece > of information to put in the documentation. When the function is > obvious, or when it implements a routine that's part of the gdbarch > vector, then what we've been doing, lately, is just say "Implements > the "bla_bla_bla" gdbarch method." or somesuch (we try not to repeat > the documentation to avoid maintenance issues). Here goes the reviewed version of the patch, addressing your observations. Is it OK to check in now? Thanks, -- Sérgio Durigan Júnior Linux on Power Toolchain - Software Engineer Linux Technology Center - LTC IBM Brazil 2009-05-05 Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com> * 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. [-- Attachment #2: read-regs-ppc.patch --] [-- Type: text/x-patch, Size: 11130 bytes --] diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c index 8710d51..297365b 100644 --- a/gdb/ppc-linux-nat.c +++ b/gdb/ppc-linux-nat.c @@ -108,6 +108,21 @@ #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 + /* 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 +233,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 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 +628,112 @@ fetch_altivec_registers (struct regcache *regcache, int tid) supply_vrregset (regcache, ®s); } +/* This function actually issues the request to ptrace, telling + it to get all general-purpose registers and put them into the + specified regset. + + If the ptrace request does not exist, this function returns 0 + and properly sets the have_ptrace_* flag. If the request fails, + this function calls perror_with_name. Otherwise, if the request + succeeds, then the regcache gets filled and 1 is returned. */ +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); + gdb_gregset_t gregset; + + if (ptrace (PTRACE_GETREGS, 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; +} + +/* This is a wrapper for the fetch_all_gp_regs function. It is + responsible for verifying if this target has the ptrace request + that can be used to fetch all general-purpose registers at one + shot. If it doesn't, then we should fetch them using the + old-fashioned way, which is to iterate over the registers and + request them one by one. */ +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); +} + +/* This function actually issues the request to ptrace, telling + it to get all floating-point registers and put them into the + specified regset. + + If the ptrace request does not exist, this function returns 0 + and properly sets the have_ptrace_* flag. If the request fails, + this function calls perror_with_name. Otherwise, if the request + succeeds, then the regcache gets filled and 1 is returned. */ +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 registers.")); + } + + supply_fpregset (regcache, (const gdb_fpregset_t *) &fpregs); + + return 1; +} + +/* This is a wrapper for the fetch_all_fp_regs function. It is + responsible for verifying if this target has the ptrace request + that can be used to fetch all floating-point registers at one + shot. If it doesn't, then we should fetch them using the + old-fashioned way, which is to iterate over the registers and + request them one by one. */ +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 +741,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); @@ -970,18 +1101,142 @@ store_altivec_registers (const struct regcache *regcache, int tid) perror_with_name (_("Couldn't write AltiVec registers")); } +/* This function actually issues the request to ptrace, telling + it to store all general-purpose registers present in the specified + regset. + + If the ptrace request does not exist, this function returns 0 + and properly sets the have_ptrace_* flag. If the request fails, + this function calls perror_with_name. Otherwise, if the request + succeeds, then the regcache is stored and 1 is returned. */ +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); + gdb_gregset_t gregset; + + if (ptrace (PTRACE_GETREGS, 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 (PTRACE_SETREGS, tid, 0, (void *) &gregset) < 0) + { + if (errno == EIO) + { + have_ptrace_getsetregs = 0; + return 0; + } + perror_with_name (_("Couldn't set general-purpose registers.")); + } + + return 1; +} + +/* This is a wrapper for the store_all_gp_regs function. It is + responsible for verifying if this target has the ptrace request + that can be used to store all general-purpose registers at one + shot. If it doesn't, then we should store them using the + old-fashioned way, which is to iterate over the registers and + store them one by one. */ 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); +} + +/* This function actually issues the request to ptrace, telling + it to store all floating-point registers present in the specified + regset. + + If the ptrace request does not exist, this function returns 0 + and properly sets the have_ptrace_* flag. If the request fails, + this function calls perror_with_name. Otherwise, if the request + succeeds, then the regcache is stored and 1 is returned. */ +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 registers.")); + } + + 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 set floating-point registers.")); + } + + return 1; +} + +/* This is a wrapper for the store_all_fp_regs function. It is + responsible for verifying if this target has the ptrace request + that can be used to store all floating-point registers at one + shot. If it doesn't, then we should store them using the + old-fashioned way, which is to iterate over the registers and + store them one by one. */ +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); ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers 2009-05-05 18:34 ` Sérgio Durigan Júnior @ 2009-05-06 16:58 ` Joel Brobecker 2009-05-09 3:20 ` [PATCH] Improve the fetch/store of general-purpose andfloating-point " Sérgio Durigan Júnior 0 siblings, 1 reply; 15+ messages in thread From: Joel Brobecker @ 2009-05-06 16:58 UTC (permalink / raw) To: S?rgio Durigan J?nior; +Cc: luisgpm, gdb-patches, Mark Kettenis > Here goes the reviewed version of the patch, addressing your > observations. Is it OK to check in now? Perfect. Thank you very much :) > 2009-05-05 Sergio Durigan Junior <sergiodj@linux.vnet.ibm.com> > > * 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. -- Joel ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Improve the fetch/store of general-purpose andfloating-point PowerPC registers 2009-05-06 16:58 ` Joel Brobecker @ 2009-05-09 3:20 ` Sérgio Durigan Júnior 0 siblings, 0 replies; 15+ messages in thread From: Sérgio Durigan Júnior @ 2009-05-09 3:20 UTC (permalink / raw) To: Joel Brobecker; +Cc: luisgpm, gdb-patches, Mark Kettenis Hi Joel, On Wed, 2009-05-06 at 09:58 -0700, Joel Brobecker wrote: > > Here goes the reviewed version of the patch, addressing your > > observations. Is it OK to check in now? > > Perfect. Thank you very much :) Just FYI, the patch has been commited today. Thank you very much, -- Sérgio Durigan Júnior Linux on Power Toolchain - Software Engineer Linux Technology Center - LTC IBM Brazil ^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers 2008-10-07 18:32 [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers Sérgio Durigan Júnior 2008-10-16 20:07 ` Sérgio Durigan Júnior @ 2008-11-17 23:22 ` Sérgio Durigan Júnior 1 sibling, 0 replies; 15+ messages in thread From: Sérgio Durigan Júnior @ 2008-11-17 23:22 UTC (permalink / raw) To: gdb-patches Ping again. On Tue, 2008-10-07 at 15:32 -0300, Sérgio Durigan Júnior wrote: > 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 ^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2009-05-09 3:20 UTC | newest] Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2008-10-07 18:32 [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers Sérgio Durigan Júnior 2008-10-16 20:07 ` Sérgio Durigan Júnior 2009-01-07 0:44 ` Sérgio Durigan Júnior 2009-01-07 9:56 ` Mark Kettenis 2009-01-07 16:09 ` Sérgio Durigan Júnior 2009-01-08 17:46 ` Sérgio Durigan Júnior 2009-01-09 12:26 ` Luis Machado 2009-01-21 17:28 ` Sérgio Durigan Júnior 2009-04-28 20:07 ` Joel Brobecker 2009-04-29 2:16 ` Sérgio Durigan Júnior 2009-04-29 4:05 ` Joel Brobecker 2009-05-05 18:34 ` Sérgio Durigan Júnior 2009-05-06 16:58 ` Joel Brobecker 2009-05-09 3:20 ` [PATCH] Improve the fetch/store of general-purpose andfloating-point " Sérgio Durigan Júnior 2008-11-17 23:22 ` [PATCH] Improve the fetch/store of general-purpose and floating-point " Sérgio Durigan Júnior
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox