From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6608 invoked by alias); 7 Jan 2009 00:44:00 -0000 Received: (qmail 6597 invoked by uid 22791); 7 Jan 2009 00:43:58 -0000 X-SWARE-Spam-Status: No, hits=-2.6 required=5.0 tests=BAYES_00,SPF_PASS X-Spam-Check-By: sourceware.org Received: from igw1.br.ibm.com (HELO igw1.br.ibm.com) (32.104.18.24) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 07 Jan 2009 00:43:50 +0000 Received: from d24relay01.br.ibm.com (unknown [9.8.31.16]) by igw1.br.ibm.com (Postfix) with ESMTP id DFDF932C006 for ; Tue, 6 Jan 2009 22:38:18 -0200 (BRDT) 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 n071hJsk3936500 for ; Tue, 6 Jan 2009 22:43:19 -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 n070hkXR022955 for ; Tue, 6 Jan 2009 22:43:47 -0200 Received: from [9.18.202.234] ([9.18.202.234]) by d24av01.br.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id n070hhQV022909 for ; Tue, 6 Jan 2009 22:43:46 -0200 Subject: Re: [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 In-Reply-To: <1224184035.27672.64.camel@miki> References: <1223404355.7030.20.camel@miki> <1224184035.27672.64.camel@miki> Content-Type: multipart/mixed; boundary="=-wDhLIFbwMqSWJN3Cs5u7" Date: Wed, 07 Jan 2009 00:44:00 -0000 Message-Id: <1231289020.2026.3.camel@miki> Mime-Version: 1.0 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: 2009-01/txt/msg00064.txt.bz2 --=-wDhLIFbwMqSWJN3Cs5u7 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Content-length: 1308 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 * configure.ac: Checking the existence of PTRACE_GETREGS, PTRACE_SETREGS, PTRACE_GETREGS64, PTRACE_SETREGS64, PTRACE_GETFPREGS and PTRACE_SETFPREGS in . * 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. --=-wDhLIFbwMqSWJN3Cs5u7 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: 13073 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 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])]) @@ -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 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])]) @@ -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 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 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); --=-wDhLIFbwMqSWJN3Cs5u7--