From: "Sérgio Durigan Júnior" <sergiodj@linux.vnet.ibm.com>
To: gdb-patches@sourceware.org
Subject: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers
Date: Tue, 07 Oct 2008 18:32:00 -0000 [thread overview]
Message-ID: <1223404355.7030.20.camel@miki> (raw)
[-- 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);
next reply other threads:[~2008-10-07 18:32 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-10-07 18:32 Sérgio Durigan Júnior [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1223404355.7030.20.camel@miki \
--to=sergiodj@linux.vnet.ibm.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox