From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12266 invoked by alias); 7 Oct 2008 18:32:13 -0000 Received: (qmail 12054 invoked by uid 22791); 7 Oct 2008 18:32:01 -0000 X-Spam-Check-By: sourceware.org Received: from igw3.br.ibm.com (HELO igw3.br.ibm.com) (32.104.18.26) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 07 Oct 2008 18:31:00 +0000 Received: from d24relay01.br.ibm.com (unknown [9.8.31.16]) by igw3.br.ibm.com (Postfix) with ESMTP id 73EBE39032D for ; Tue, 7 Oct 2008 15:08:15 -0300 (BRST) Received: from d24av01.br.ibm.com (d24av01.br.ibm.com [9.18.232.46]) by d24relay01.br.ibm.com (8.13.8/8.13.8/NCO v9.1) with ESMTP id m97IUlU61658932 for ; Tue, 7 Oct 2008 15:30:47 -0300 Received: from d24av01.br.ibm.com (loopback [127.0.0.1]) by d24av01.br.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id m97IUtjV031506 for ; Tue, 7 Oct 2008 15:30:56 -0300 Received: from [9.18.200.170] ([9.18.200.170]) by d24av01.br.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id m97IUqrU031205 for ; Tue, 7 Oct 2008 15:30:52 -0300 Subject: [PATCH] Improve the fetch/store of general-purpose and floating-point PowerPC registers From: =?ISO-8859-1?Q?S=E9rgio?= Durigan =?ISO-8859-1?Q?J=FAnior?= To: gdb-patches@sourceware.org Content-Type: multipart/mixed; boundary="=-dqxRFCujjjqaKJ9i8TzJ" Date: Tue, 07 Oct 2008 18:32:00 -0000 Message-Id: <1223404355.7030.20.camel@miki> Mime-Version: 1.0 X-Mailer: Evolution 2.22.3.1 X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-10/txt/msg00220.txt.bz2 --=-dqxRFCujjjqaKJ9i8TzJ Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Content-length: 1104 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 * configure.ac: Checking the existence of PTRACE_GETREGS, PTRACE_SETREGS, PTRACE_GETREGS64, PTRACE_SETREGS64, PTRACE_GETFPREGS and PTRACE_SETFPREGS in . * 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. --=-dqxRFCujjjqaKJ9i8TzJ Content-Disposition: attachment; filename=read-regs.patch Content-Type: text/x-patch; name=read-regs.patch; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-length: 10893 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 provides the PTRACE_GETREGS request. AC_MSG_CHECKING(for PTRACE_GETREGS) AC_CACHE_VAL(gdb_cv_have_ptrace_getregs, -[AC_TRY_COMPILE([#include ], +[AC_TRY_COMPILE([#include + #include ], [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 provides the PTRACE_SETREGS request. +AC_MSG_CHECKING(for PTRACE_SETREGS) +AC_CACHE_VAL(gdb_cv_have_ptrace_setregs, +[AC_TRY_COMPILE([#include + #include ], + [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 provides the PTRACE_GETREGS64 request. +AC_MSG_CHECKING(for PTRACE_GETREGS64) +AC_CACHE_VAL(gdb_cv_have_ptrace_getregs64, +[AC_TRY_COMPILE([#include + #include ], + [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 provides the PTRACE_SETREGS64 request. +AC_MSG_CHECKING(for PTRACE_SETREGS64) +AC_CACHE_VAL(gdb_cv_have_ptrace_setregs64, +[AC_TRY_COMPILE([#include + #include ], + [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 provides the PTRACE_GETFPREGS request. +AC_MSG_CHECKING(for PTRACE_GETFPREGS) +AC_CACHE_VAL(gdb_cv_have_ptrace_getfpregs, +[AC_TRY_COMPILE([#include + #include ], + [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 provides the PTRACE_SETFPREGS request. +AC_MSG_CHECKING(for PTRACE_SETFPREGS) +AC_CACHE_VAL(gdb_cv_have_ptrace_setfpregs, +[AC_TRY_COMPILE([#include + #include ], + [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 provides the PTRACE_GETFPXREGS request. AC_MSG_CHECKING(for PTRACE_GETFPXREGS) AC_CACHE_VAL(gdb_cv_have_ptrace_getfpxregs, -[AC_TRY_COMPILE([#include ], +[AC_TRY_COMPILE([#include + #include ], [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 provides the PTRACE_SETFPXREGS request. +AC_MSG_CHECKING(for PTRACE_SETFPXREGS) +AC_CACHE_VAL(gdb_cv_have_ptrace_setfpxregs, +[AC_TRY_COMPILE([#include + #include ], + [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 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); --=-dqxRFCujjjqaKJ9i8TzJ--