From patchwork Thu May 10 19:58:38 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: pedromfc X-Patchwork-Id: 27213 Received: (qmail 52681 invoked by alias); 10 May 2018 20:00:59 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 52526 invoked by uid 89); 10 May 2018 20:00:44 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.8 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, KAM_SHORT, NO_DNS_FOR_FROM, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy= X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0b-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.158.5) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 10 May 2018 20:00:41 +0000 Received: from pps.filterd (m0098417.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w4AJx0Ci038628 for ; Thu, 10 May 2018 16:00:30 -0400 Received: from e37.co.us.ibm.com (e37.co.us.ibm.com [32.97.110.158]) by mx0a-001b2d01.pphosted.com with ESMTP id 2hvusctam6-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Thu, 10 May 2018 16:00:30 -0400 Received: from localhost by e37.co.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 10 May 2018 14:00:29 -0600 Received: from b03cxnp08028.gho.boulder.ibm.com (9.17.130.20) by e37.co.us.ibm.com (192.168.1.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 10 May 2018 14:00:27 -0600 Received: from b03ledav006.gho.boulder.ibm.com (b03ledav006.gho.boulder.ibm.com [9.17.130.237]) by b03cxnp08028.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w4AJxBdD12059112 for ; Thu, 10 May 2018 12:59:12 -0700 Received: from b03ledav006.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4934AC6051 for ; Thu, 10 May 2018 13:59:12 -0600 (MDT) Received: from pedro.localdomain (unknown [9.18.235.221]) by b03ledav006.gho.boulder.ibm.com (Postfix) with ESMTP id 09AA0C6043 for ; Thu, 10 May 2018 13:59:12 -0600 (MDT) Received: by pedro.localdomain (Postfix, from userid 1000) id 7D7A73C03E4; Thu, 10 May 2018 16:59:07 -0300 (-03) From: Pedro Franco de Carvalho To: gdb-patches@sourceware.org Subject: [PATCH 6/8] [PowerPC] Fix VSX registers in linux core files Date: Thu, 10 May 2018 16:58:38 -0300 In-Reply-To: <20180510195840.17734-1-pedromfc@linux.vnet.ibm.com> References: <20180510195840.17734-1-pedromfc@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18051020-0024-0000-0000-000018624FE8 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00009001; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000259; SDB=6.01030393; UDB=6.00526596; IPR=6.00809524; MB=3.00021034; MTD=3.00000008; XFM=3.00000015; UTC=2018-05-10 20:00:28 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18051020-0025-0000-0000-00004FEA0886 Message-Id: <20180510195840.17734-7-pedromfc@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:, , definitions=2018-05-10_06:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=4 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1805100185 X-IsSubscribed: yes The functions used by the VSX regset to collect and supply registers from core files where incorrect. This patch changes the regset to use the standard regset collect/supply functions to fix this. The native target is also changed to use the same regset. gdb/ChangeLog: yyyy-mm-dd Pedro Franco de Carvalho * ppc-linux-tdep.c (ppc_linux_vsxregset): New function. (ppc32_linux_vsxregmap): New global. (ppc32_linux_vsxregset): Initialize with ppc32_linux_vsxregmap, regcache_supply_regset, and regcache_collect_regset. * ppc-linux-tdep.h (ppc_linux_vsxregset): Declare. * ppc-linux-nat.c (supply_vsxregset, fill_vsxregset): Remove. (fetch_vsx_register, store_vsx_register): Remove. (fetch_vsx_registers): Add regno parameter. Get regset using ppc_linux_vsxregset. Use regset to supply registers. (store_vsx_registers): Add regno parameter. Get regset using ppc_linux_vsxregset. Use regset to collect registers. (fetch_register): Call fetch_vsx_registers instead of fetch_vsx_register. (store_register): Call store_vsx_registers instead of store_vsx_register. (fetch_ppc_registers): Call fetch_vsx_registers with -1 for the new regno parameter. (store_ppc_registers): Call store_vsx_registers with -1 for the new regno parameter. * rs6000-tdep.c (ppc_vsx_support_p, ppc_supply_vsxreget) (ppc_collect_vsxregset): Remove. gdb/testsuite/ChangeLog: yyyy-mm-dd Pedro Franco de Carvalho * gdb.arch/powerpc-vsx-gcore.exp: New file. --- gdb/ppc-linux-nat.c | 106 ++++----------------------- gdb/ppc-linux-tdep.c | 18 ++++- gdb/ppc-linux-tdep.h | 1 + gdb/rs6000-tdep.c | 75 ------------------- gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp | 90 +++++++++++++++++++++++ 5 files changed, 121 insertions(+), 169 deletions(-) create mode 100644 gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c index 85cd08cd8e..59c5f0c4b9 100644 --- a/gdb/ppc-linux-nat.c +++ b/gdb/ppc-linux-nat.c @@ -409,13 +409,11 @@ ppc_register_u_addr (struct gdbarch *gdbarch, int regno) registers set mechanism, as opposed to the interface for all the other registers, that stores/fetches each register individually. */ static void -fetch_vsx_register (struct regcache *regcache, int tid, int regno) +fetch_vsx_registers (struct regcache *regcache, int tid, int regno) { int ret; gdb_vsxregset_t regs; - struct gdbarch *gdbarch = regcache->arch (); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum); + const struct regset *vsxregset = ppc_linux_vsxregset (); ret = ptrace (PTRACE_GETVSXREGS, tid, 0, ®s); if (ret < 0) @@ -425,12 +423,11 @@ fetch_vsx_register (struct regcache *regcache, int tid, int regno) have_ptrace_getsetvsxregs = 0; return; } - perror_with_name (_("Unable to fetch VSX register")); + perror_with_name (_("Unable to fetch VSX registers")); } - regcache_raw_supply (regcache, regno, - regs + (regno - tdep->ppc_vsr0_upper_regnum) - * vsxregsize); + vsxregset->supply_regset(vsxregset, regcache, regno, ®s, + PPC_LINUX_SIZEOF_VSXREGSET); } /* The Linux kernel ptrace interface for AltiVec registers uses the @@ -563,7 +560,7 @@ fetch_register (struct regcache *regcache, int tid, int regno) { if (have_ptrace_getsetvsxregs) { - fetch_vsx_register (regcache, tid, regno); + fetch_vsx_registers (regcache, tid, regno); return; } } @@ -624,40 +621,6 @@ fetch_register (struct regcache *regcache, int tid, int regno) gdbarch_byte_order (gdbarch)); } -static void -supply_vsxregset (struct regcache *regcache, gdb_vsxregset_t *vsxregsetp) -{ - int i; - struct gdbarch *gdbarch = regcache->arch (); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum); - - for (i = 0; i < ppc_num_vshrs; i++) - { - regcache_raw_supply (regcache, tdep->ppc_vsr0_upper_regnum + i, - *vsxregsetp + i * vsxregsize); - } -} - -static void -fetch_vsx_registers (struct regcache *regcache, int tid) -{ - int ret; - gdb_vsxregset_t regs; - - ret = ptrace (PTRACE_GETVSXREGS, tid, 0, ®s); - if (ret < 0) - { - if (errno == EIO) - { - have_ptrace_getsetvsxregs = 0; - return; - } - perror_with_name (_("Unable to fetch VSX registers")); - } - supply_vsxregset (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. @@ -799,7 +762,7 @@ fetch_ppc_registers (struct regcache *regcache, int tid) fetch_altivec_registers (regcache, tid, -1); if (have_ptrace_getsetvsxregs) if (tdep->ppc_vsr0_upper_regnum != -1) - fetch_vsx_registers (regcache, tid); + fetch_vsx_registers (regcache, tid, -1); if (tdep->ppc_ev0_upper_regnum >= 0) fetch_spe_register (regcache, tid, -1); } @@ -818,15 +781,12 @@ ppc_linux_nat_target::fetch_registers (struct regcache *regcache, int regno) fetch_register (regcache, tid, regno); } -/* Store one VSX register. */ static void -store_vsx_register (const struct regcache *regcache, int tid, int regno) +store_vsx_registers (const struct regcache *regcache, int tid, int regno) { int ret; gdb_vsxregset_t regs; - struct gdbarch *gdbarch = regcache->arch (); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum); + const struct regset *vsxregset = ppc_linux_vsxregset (); ret = ptrace (PTRACE_GETVSXREGS, tid, 0, ®s); if (ret < 0) @@ -836,15 +796,15 @@ store_vsx_register (const struct regcache *regcache, int tid, int regno) have_ptrace_getsetvsxregs = 0; return; } - perror_with_name (_("Unable to fetch VSX register")); + perror_with_name (_("Unable to fetch VSX registers")); } - regcache_raw_collect (regcache, regno, regs + - (regno - tdep->ppc_vsr0_upper_regnum) * vsxregsize); + vsxregset->collect_regset (vsxregset, regcache, regno, ®s, + PPC_LINUX_SIZEOF_VSXREGSET); ret = ptrace (PTRACE_SETVSXREGS, tid, 0, ®s); if (ret < 0) - perror_with_name (_("Unable to store VSX register")); + perror_with_name (_("Unable to store VSX registers")); } static void @@ -980,7 +940,7 @@ store_register (const struct regcache *regcache, int tid, int regno) } if (vsx_register_p (gdbarch, regno)) { - store_vsx_register (regcache, tid, regno); + store_vsx_registers (regcache, tid, regno); return; } else if (spe_register_p (gdbarch, regno)) @@ -1038,42 +998,6 @@ store_register (const struct regcache *regcache, int tid, int regno) } } -static void -fill_vsxregset (const struct regcache *regcache, gdb_vsxregset_t *vsxregsetp) -{ - int i; - struct gdbarch *gdbarch = regcache->arch (); - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - int vsxregsize = register_size (gdbarch, tdep->ppc_vsr0_upper_regnum); - - for (i = 0; i < ppc_num_vshrs; i++) - regcache_raw_collect (regcache, tdep->ppc_vsr0_upper_regnum + i, - *vsxregsetp + i * vsxregsize); -} - -static void -store_vsx_registers (const struct regcache *regcache, int tid) -{ - int ret; - gdb_vsxregset_t regs; - - ret = ptrace (PTRACE_GETVSXREGS, tid, 0, ®s); - if (ret < 0) - { - if (errno == EIO) - { - have_ptrace_getsetvsxregs = 0; - return; - } - perror_with_name (_("Couldn't get VSX registers")); - } - - fill_vsxregset (regcache, ®s); - - if (ptrace (PTRACE_SETVSXREGS, tid, 0, ®s) < 0) - perror_with_name (_("Couldn't write VSX registers")); -} - /* This function actually issues the request to ptrace, telling it to store all general-purpose registers present in the specified regset. @@ -1235,7 +1159,7 @@ store_ppc_registers (const struct regcache *regcache, int tid) store_altivec_registers (regcache, tid, -1); if (have_ptrace_getsetvsxregs) if (tdep->ppc_vsr0_upper_regnum != -1) - store_vsx_registers (regcache, tid); + store_vsx_registers (regcache, tid, -1); if (tdep->ppc_ev0_upper_regnum >= 0) store_spe_register (regcache, tid, -1); } diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 3c8ba26f8e..54de34d0b7 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -560,10 +560,16 @@ static const struct regset ppc32_be_linux_vrregset = { ppc_linux_collect_vrregset }; +static const struct regcache_map_entry ppc32_linux_vsxregmap[] = + { + { 32, PPC_VSR0_UPPER_REGNUM, 8 }, + { 0 } + }; + static const struct regset ppc32_linux_vsxregset = { - &ppc32_linux_reg_offsets, - ppc_supply_vsxregset, - ppc_collect_vsxregset + ppc32_linux_vsxregmap, + regcache_supply_regset, + regcache_collect_regset }; const struct regset * @@ -587,6 +593,12 @@ ppc_linux_vrregset (struct gdbarch *gdbarch) return &ppc32_le_linux_vrregset; } +const struct regset * +ppc_linux_vsxregset (void) +{ + return &ppc32_linux_vsxregset; +} + /* Iterate over supported core file register note sections. */ static void diff --git a/gdb/ppc-linux-tdep.h b/gdb/ppc-linux-tdep.h index a8715bd418..51f4b506a1 100644 --- a/gdb/ppc-linux-tdep.h +++ b/gdb/ppc-linux-tdep.h @@ -30,6 +30,7 @@ const struct regset *ppc_linux_fpregset (void); /* Get the vector regset that matches the target byte order. */ const struct regset *ppc_linux_vrregset (struct gdbarch *gdbarch); +const struct regset *ppc_linux_vsxregset (void); /* Extra register number constants. The Linux kernel stores a "trap" code and the original value of r3 into special "registers"; diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index c5b49c5f46..3f0b7f77a1 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -224,16 +224,6 @@ ppc_floating_point_unit_p (struct gdbarch *gdbarch) } /* Return non-zero if the architecture described by GDBARCH has - VSX registers (vsr0 --- vsr63). */ -static int -ppc_vsx_support_p (struct gdbarch *gdbarch) -{ - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - - return tdep->ppc_vsr0_regnum >= 0; -} - -/* Return non-zero if the architecture described by GDBARCH has Altivec registers (vr0 --- vr31, vrsave and vscr). */ int ppc_altivec_support_p (struct gdbarch *gdbarch) @@ -591,37 +581,6 @@ ppc_supply_fpregset (const struct regset *regset, struct regcache *regcache, regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8); } -/* Supply register REGNUM in the VSX register set REGSET - from the buffer specified by VSXREGS and LEN to register cache - REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ - -void -ppc_supply_vsxregset (const struct regset *regset, struct regcache *regcache, - int regnum, const void *vsxregs, size_t len) -{ - struct gdbarch *gdbarch = regcache->arch (); - struct gdbarch_tdep *tdep; - - if (!ppc_vsx_support_p (gdbarch)) - return; - - tdep = gdbarch_tdep (gdbarch); - - if (regnum == -1) - { - int i; - - for (i = tdep->ppc_vsr0_upper_regnum; - i < tdep->ppc_vsr0_upper_regnum + 32; - i++) - ppc_supply_reg (regcache, i, (const gdb_byte *) vsxregs, 0, 8); - - return; - } - else - ppc_supply_reg (regcache, regnum, (const gdb_byte *) vsxregs, 0, 8); -} - /* Supply register REGNUM in the Altivec register set REGSET from the buffer specified by VRREGS and LEN to register cache REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */ @@ -757,40 +716,6 @@ ppc_collect_fpregset (const struct regset *regset, regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 8); } -/* Collect register REGNUM in the VSX register set - REGSET from register cache REGCACHE into the buffer specified by - VSXREGS and LEN. If REGNUM is -1, do this for all registers in - REGSET. */ - -void -ppc_collect_vsxregset (const struct regset *regset, - const struct regcache *regcache, - int regnum, void *vsxregs, size_t len) -{ - struct gdbarch *gdbarch = regcache->arch (); - struct gdbarch_tdep *tdep; - - if (!ppc_vsx_support_p (gdbarch)) - return; - - tdep = gdbarch_tdep (gdbarch); - - if (regnum == -1) - { - int i; - - for (i = tdep->ppc_vsr0_upper_regnum; - i < tdep->ppc_vsr0_upper_regnum + 32; - i++) - ppc_collect_reg (regcache, i, (gdb_byte *) vsxregs, 0, 8); - - return; - } - else - ppc_collect_reg (regcache, regnum, (gdb_byte *) vsxregs, 0, 8); -} - - /* Collect register REGNUM in the Altivec register set REGSET from register cache REGCACHE into the buffer specified by VRREGS and LEN. If REGNUM is -1, do this for all registers in diff --git a/gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp b/gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp new file mode 100644 index 0000000000..e9bdfcdd44 --- /dev/null +++ b/gdb/testsuite/gdb.arch/powerpc-vsx-gcore.exp @@ -0,0 +1,90 @@ +# Copyright (C) 2018 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# This file is part of the gdb testsuite. + +# This test checks that generating and loading a core file preserves +# the correct VSX register state. + +if {![istarget "powerpc*-*-linux*"] || [skip_vsx_tests]} then { + verbose "Skipping PowerPC test for corefiles with VSX registers." + return +} + +standard_testfile .c + +set gen_src [standard_output_file $srcfile] + +gdb_produce_source $gen_src { + int main() { + return 0; + } +} + +if {[build_executable "compile" $binfile $gen_src] == -1} { + return -1 +} + +clean_restart $binfile + +if ![runto_main] then { + fail "could not run to main" + return -1 +} + +# Check if VSX register access through gdb is supported +proc check_vsx_access {} { + global gdb_prompt + + set test "vsx register access" + gdb_test_multiple "info reg vs0" "$test" { + -re "Invalid register.*\r\n$gdb_prompt $" { + unsupported "$test" + return 0 + } + -re "\r\nvs0.*\r\n$gdb_prompt $" { + pass "$test" + return 1 + } + } + return 0 +} + +if { ![check_vsx_access] } { + return -1 +} + +for {set i 0} {$i < 64} {incr i 1} { + gdb_test_no_output "set \$vs$i.uint128 = $i" +} + +set core_filename [standard_output_file "$testfile.core"] +set core_generated [gdb_gcore_cmd "$core_filename" "generate core file"] + +if { !$core_generated } { + return -1 +} + +clean_restart + +set core_loaded [gdb_core_cmd "$core_filename" "load core file"] + +if { $core_loaded != 1 } { + return -1 +} + +for {set i 0} {$i < 64} {incr i 1} { + gdb_test "print \$vs$i.uint128" ".* = $i" "print vs$i" +}