From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 32225 invoked by alias); 8 Jan 2009 17:46:50 -0000 Received: (qmail 32195 invoked by uid 22791); 8 Jan 2009 17:46:49 -0000 X-SWARE-Spam-Status: No, hits=-2.7 required=5.0 tests=AWL,BAYES_00,J_CHICKENPOX_92 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; Thu, 08 Jan 2009 17:46:42 +0000 Received: from d24relay01.br.ibm.com (unknown [9.8.31.16]) by igw1.br.ibm.com (Postfix) with ESMTP id 2293F32C45A for ; Thu, 8 Jan 2009 15:41:06 -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 n08IkBq93502114 for ; Thu, 8 Jan 2009 15:46:11 -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 n08Hkdh2023727 for ; Thu, 8 Jan 2009 15:46:39 -0200 Received: from [9.8.0.105] ([9.8.0.105]) by d24av01.br.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id n08HkcO2020491 for ; Thu, 8 Jan 2009 15:46:39 -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: <1231344540.2026.7.camel@miki> References: <1223404355.7030.20.camel@miki> <1224184035.27672.64.camel@miki> <1231289020.2026.3.camel@miki> <200901070955.n079twBj014790@brahms.sibelius.xs4all.nl> <1231344540.2026.7.camel@miki> Content-Type: multipart/mixed; boundary="=-0Cdx/WBuR/yeot99p8tf" Date: Thu, 08 Jan 2009 17:46:00 -0000 Message-Id: <1231436749.2026.19.camel@miki> Mime-Version: 1.0 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: 2009-01/txt/msg00167.txt.bz2 --=-0Cdx/WBuR/yeot99p8tf Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit Content-length: 835 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 * 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. --=-0Cdx/WBuR/yeot99p8tf 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: 8553 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); --=-0Cdx/WBuR/yeot99p8tf--