From aa3845bca29033c6592d96bb55040921ff00914c Mon Sep 17 00:00:00 2001 From: Luis Pires Date: Thu, 24 May 2018 13:07:58 -0300 Subject: [PATCH 1/3] Altivec/VSX support for PPC/FreeBSD --- gdb/Makefile.in | 2 + gdb/arch/ppc-fbsd-common.c | 59 +++++++++ gdb/arch/ppc-fbsd-common.h | 88 ++++++++++++++ gdb/configure.tgt | 3 +- gdb/ppc-fbsd-nat.c | 237 ++++++++++++++++++++++++++++++++++++- gdb/ppc-fbsd-tdep.c | 91 +++++++++++++- gdb/ppc-fbsd-tdep.h | 2 + 7 files changed, 476 insertions(+), 6 deletions(-) create mode 100644 gdb/arch/ppc-fbsd-common.c create mode 100644 gdb/arch/ppc-fbsd-common.h diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 354a6361b7..8f7810b0bc 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -679,6 +679,7 @@ ALL_TARGET_OBS = \ arch/arm-get-next-pcs.o \ arch/arm-linux.o \ arch/i386.o \ + arch/ppc-fbsd-common.o \ arch/ppc-linux-common.o \ arm-bsd-tdep.o \ arm-fbsd-tdep.o \ @@ -1414,6 +1415,7 @@ HFILES_NO_SRCDIR = \ arch/aarch64-insn.h \ arch/arm.h \ arch/i386.h \ + arch/ppc-fbsd-common.h \ arch/ppc-linux-common.h \ arch/ppc-linux-tdesc.h \ cli/cli-cmds.h \ diff --git a/gdb/arch/ppc-fbsd-common.c b/gdb/arch/ppc-fbsd-common.c new file mode 100644 index 0000000000..2d4fea631b --- /dev/null +++ b/gdb/arch/ppc-fbsd-common.c @@ -0,0 +1,59 @@ +/* Common target dependent code for FreeBSD on PPC systems. + + Copyright (C) 2018 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#include "common-defs.h" +#include "arch/ppc-fbsd-common.h" + +extern struct target_desc *tdesc_powerpc_32; +extern struct target_desc *tdesc_powerpc_altivec32; +extern struct target_desc *tdesc_powerpc_vsx32; +extern struct target_desc *tdesc_powerpc_64; +extern struct target_desc *tdesc_powerpc_altivec64; +extern struct target_desc *tdesc_powerpc_vsx64; + +const struct target_desc * +ppc_fbsd_match_description (struct ppc_fbsd_features features) +{ + struct target_desc *tdesc = NULL; + + if (features.wordsize == 8) + { + if (features.vsx) + tdesc = tdesc_powerpc_vsx64; + else if (features.altivec) + tdesc = tdesc_powerpc_altivec64; + else + tdesc = tdesc_powerpc_64; + } + else + { + gdb_assert (features.wordsize == 4); + + if (features.vsx) + tdesc = tdesc_powerpc_vsx32; + else if (features.altivec) + tdesc = tdesc_powerpc_altivec32; + else + tdesc = tdesc_powerpc_32; + } + + gdb_assert (tdesc != NULL); + + return tdesc; +} diff --git a/gdb/arch/ppc-fbsd-common.h b/gdb/arch/ppc-fbsd-common.h new file mode 100644 index 0000000000..b3448d6f5b --- /dev/null +++ b/gdb/arch/ppc-fbsd-common.h @@ -0,0 +1,88 @@ +/* Common target dependent code for FreeBSD on PPC systems. + + Copyright (C) 2018 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#ifndef ARCH_PPC_FBSD_COMMON_H +#define ARCH_PPC_FBSD_COMMON_H + +#define PPC_FBSD_SIZEOF_GREGSET_32 148 +#define PPC_FBSD_SIZEOF_GREGSET_64 296 +#define PPC_FBSD_SIZEOF_FPREGSET 264 + +/* PT_GETVRREGS returns data as defined in machine/pcb.h: + 32 128-bit registers + 8 spare bytes + VRSAVE (4 bytes) + VSCR (4 bytes) */ +#define PPC_FBSD_SIZEOF_VRREGSET (32*16 + 8 + 4 + 4) + +typedef char gdb_vrregset_t[PPC_FBSD_SIZEOF_VRREGSET]; + +/* This is the layout of the POWER7 VSX registers and the way they overlap + with the existing FPR and VMX registers. + + VSR doubleword 0 VSR doubleword 1 + ---------------------------------------------------------------- + VSR[0] | FPR[0] | | + ---------------------------------------------------------------- + VSR[1] | FPR[1] | | + ---------------------------------------------------------------- + | ... | | + | ... | | + ---------------------------------------------------------------- + VSR[30] | FPR[30] | | + ---------------------------------------------------------------- + VSR[31] | FPR[31] | | + ---------------------------------------------------------------- + VSR[32] | VR[0] | + ---------------------------------------------------------------- + VSR[33] | VR[1] | + ---------------------------------------------------------------- + | ... | + | ... | + ---------------------------------------------------------------- + VSR[62] | VR[30] | + ---------------------------------------------------------------- + VSR[63] | VR[31] | + ---------------------------------------------------------------- + + VSX has 64 128bit registers. The first 32 registers overlap with + the FP registers (doubleword 0) and hence extend them with additional + 64 bits (doubleword 1). The other 32 regs overlap with the VMX + registers. */ +#define PPC_FBSD_SIZEOF_VSXREGSET (32*8) + +typedef char gdb_vsxregset_t[PPC_FBSD_SIZEOF_VSXREGSET]; + +/* Features used to determine the target description. */ +struct ppc_fbsd_features +{ + unsigned int wordsize; + bool altivec; + bool vsx; +}; + +/* Base value for ppc_fbsd_features variables. */ +const struct ppc_fbsd_features ppc_fbsd_no_features = { + 0, + false, + false +}; + +/* Return a target description that matches FEATURES. */ +const struct target_desc * +ppc_fbsd_match_description (struct ppc_fbsd_features features); + +#endif /* ARCH_PPC_FBSD_COMMON_H */ diff --git a/gdb/configure.tgt b/gdb/configure.tgt index f197160896..dc617a1ab4 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -465,7 +465,8 @@ powerpc*-*-freebsd*) # Target: FreeBSD/powerpc gdb_target_obs="rs6000-tdep.o ppc-sysv-tdep.o ppc64-tdep.o \ ppc-fbsd-tdep.o \ - ravenscar-thread.o ppc-ravenscar-thread.o" + ravenscar-thread.o ppc-ravenscar-thread.o \ + arch/ppc-fbsd-common.o" ;; powerpc-*-netbsd* | powerpc-*-knetbsd*-gnu) diff --git a/gdb/ppc-fbsd-nat.c b/gdb/ppc-fbsd-nat.c index 44661e9a24..7e122972aa 100644 --- a/gdb/ppc-fbsd-nat.c +++ b/gdb/ppc-fbsd-nat.c @@ -21,6 +21,7 @@ #include "gdbcore.h" #include "inferior.h" #include "regcache.h" +#include "regset.h" #include #include @@ -37,10 +38,47 @@ #include "inf-ptrace.h" #include "bsd-kvm.h" +#include "arch/ppc-fbsd-common.h" + +/* These definitions should really come from machine/ptrace.h, + but we provide them in case gdb is built on an machine whose + FreeBSD version still doesn't have them. */ + +#ifndef PT_FIRSTMACH +#define PT_FIRSTMACH 64 +#endif + +/* PTRACE requests for Altivec registers. */ +#ifndef PT_GETVRREGS +#define PT_GETVRREGS (PT_FIRSTMACH + 0) +#define PT_SETVRREGS (PT_FIRSTMACH + 1) +#endif + +/* PTRACE requests for POWER7 VSX registers. */ +#ifndef PT_GETVSRREGS +#define PT_GETVSRREGS (PT_FIRSTMACH + 2) +#define PT_SETVSRREGS (PT_FIRSTMACH + 3) +#endif + +/* Non-zero if our kernel may support the PT_GETVSRREGS and + PT_SETVSRREGS requests, for reading and writing the VSX + POWER7 registers 0 through 31. Zero if we've tried one of them and + gotten an error. Note that VSX registers 32 through 63 overlap + with VR registers 0 through 31. */ +int have_ptrace_getsetvsxregs = 1; + +/* Non-zero if our kernel may support the PT_GETVRREGS and + PT_SETVRREGS requests, for reading and writing the Altivec + registers. Zero if we've tried one of them and gotten an + error. */ +int have_ptrace_getvrregs = 1; + struct ppc_fbsd_nat_target final : public fbsd_nat_target { void fetch_registers (struct regcache *, int) override; void store_registers (struct regcache *, int) override; + + const struct target_desc *read_description () override; }; static ppc_fbsd_nat_target the_ppc_fbsd_nat_target; @@ -120,6 +158,137 @@ getfpregs_supplies (struct gdbarch *gdbarch, int regno) || regno == tdep->ppc_fpscr_regnum); } +/* The kernel ptrace interface for AltiVec registers uses the + registers set mechanism, as opposed to the interface for all the + other registers, that stores/fetches each register individually. */ +static void +fetch_altivec_registers (struct regcache *regcache, int tid, + int regno) +{ + int ret; + gdb_vrregset_t regs; + const struct regset *vrregset = ppc_fbsd_vrregset (); + + ret = ptrace (PT_GETVRREGS, tid, (PTRACE_TYPE_ARG3) ®s, 0); + if (ret < 0) + { + if (errno == EINVAL) + { + have_ptrace_getvrregs = 0; + return; + } + perror_with_name (_("Unable to fetch AltiVec registers")); + } + + vrregset->supply_regset (vrregset, regcache, regno, ®s, + PPC_FBSD_SIZEOF_VRREGSET); +} + +/* The kernel ptrace interface for POWER7 VSX registers uses the + registers set mechanism, as opposed to the interface for all the + other registers, that stores/fetches each register individually. */ +static void +fetch_vsx_registers (struct regcache *regcache, int tid, int regno) +{ + int ret; + gdb_vsxregset_t regs; + const struct regset *vsxregset = ppc_fbsd_vsxregset (); + + ret = ptrace (PT_GETVSRREGS, tid, (PTRACE_TYPE_ARG3) ®s, 0); + if (ret < 0) + { + if (errno == EINVAL) + { + have_ptrace_getsetvsxregs = 0; + return; + } + perror_with_name (_("Unable to fetch VSX registers")); + } + + vsxregset->supply_regset (vsxregset, regcache, regno, ®s, + PPC_FBSD_SIZEOF_VSXREGSET); +} + +static void +store_altivec_registers (const struct regcache *regcache, int tid, + int regno) +{ + int ret; + gdb_vrregset_t regs; + const struct regset *vrregset = ppc_fbsd_vrregset (); + + ret = ptrace (PT_GETVRREGS, tid, (PTRACE_TYPE_ARG3) ®s, 0); + if (ret < 0) + { + if (errno == EINVAL) + { + have_ptrace_getvrregs = 0; + return; + } + perror_with_name (_("Unable to fetch AltiVec registers")); + } + + vrregset->collect_regset (vrregset, regcache, regno, ®s, + PPC_FBSD_SIZEOF_VRREGSET); + + ret = ptrace (PT_SETVRREGS, tid, (PTRACE_TYPE_ARG3) ®s, 0); + if (ret < 0) + perror_with_name (_("Unable to store AltiVec registers")); +} + +static void +store_vsx_registers (const struct regcache *regcache, int tid, int regno) +{ + int ret; + gdb_vsxregset_t regs; + const struct regset *vsxregset = ppc_fbsd_vsxregset (); + + ret = ptrace (PT_GETVSRREGS, tid, (PTRACE_TYPE_ARG3) ®s, 0); + if (ret < 0) + { + if (errno == EINVAL) + { + have_ptrace_getsetvsxregs = 0; + return; + } + perror_with_name (_("Unable to fetch VSX registers")); + } + + vsxregset->collect_regset (vsxregset, regcache, regno, ®s, + PPC_FBSD_SIZEOF_VSXREGSET); + + ret = ptrace (PT_SETVSRREGS, tid, (PTRACE_TYPE_ARG3) ®s, 0); + if (ret < 0) + perror_with_name (_("Unable to store VSX registers")); +} + +static int +ppc_fbsd_target_wordsize (int tid) +{ + int wordsize = 4; + +#ifdef __powerpc64__ + /* Check for 64-bit inferior process. This is the case when the host is + 64-bit, and PT_GETREGS returns less data than the length of struct reg. */ + + gdb_gregset_t regs0; + gdb_gregset_t regs1; + + /* Initialize regs0 with 00's and regs1 with ff's. If, after ptrace fills + them, they have the same contents, it means ptrace returned data for a + 64-bit inferior. */ + memset (®s0, 0, sizeof regs0); + memset (®s1, 0xff, sizeof regs1); + + if (ptrace (PT_GETREGS, tid, (PTRACE_TYPE_ARG3) ®s0, 0) >= 0 + && ptrace (PT_GETREGS, tid, (PTRACE_TYPE_ARG3) ®s1, 0) >= 0) + if (memcmp(®s0, ®s1, sizeof regs0) == 0) + wordsize = 8; +#endif + + return wordsize; +} + /* Fetch register REGNO from the child process. If REGNO is -1, do it for all registers. */ @@ -128,13 +297,15 @@ ppc_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regno) { gdb_gregset_t regs; pid_t pid = ptid_get_lwp (regcache->ptid ()); + struct gdbarch *gdbarch = regcache->arch (); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); supply_gregset (regcache, ®s); - if (regno == -1 || getfpregs_supplies (regcache->arch (), regno)) + if (regno == -1 || getfpregs_supplies (gdbarch, regno)) { const struct regset *fpregset = ppc_fbsd_fpregset (); gdb_fpregset_t fpregs; @@ -144,6 +315,16 @@ ppc_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regno) ppc_supply_fpregset (fpregset, regcache, regno, &fpregs, sizeof fpregs); } + + if (have_ptrace_getvrregs) + if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1) + if (regno == -1 || altivec_register_p (gdbarch, regno)) + fetch_altivec_registers (regcache, pid, regno); + + if (have_ptrace_getsetvsxregs) + if (tdep->ppc_vsr0_upper_regnum != -1) + if (regno == -1 || vsx_register_p (gdbarch, regno)) + fetch_vsx_registers (regcache, pid, regno); } /* Store register REGNO back into the child process. If REGNO is -1, @@ -154,6 +335,8 @@ ppc_fbsd_nat_target::store_registers (struct regcache *regcache, int regno) { gdb_gregset_t regs; pid_t pid = ptid_get_lwp (regcache->ptid ()); + struct gdbarch *gdbarch = regcache->arch (); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't get registers")); @@ -163,7 +346,7 @@ ppc_fbsd_nat_target::store_registers (struct regcache *regcache, int regno) if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) perror_with_name (_("Couldn't write registers")); - if (regno == -1 || getfpregs_supplies (regcache->arch (), regno)) + if (regno == -1 || getfpregs_supplies (gdbarch, regno)) { gdb_fpregset_t fpregs; @@ -175,6 +358,56 @@ ppc_fbsd_nat_target::store_registers (struct regcache *regcache, int regno) if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't set FP registers")); } + + if (have_ptrace_getvrregs) + if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1) + if (regno == -1 || altivec_register_p (gdbarch, regno)) + store_altivec_registers (regcache, pid, regno); + + if (have_ptrace_getsetvsxregs) + if (tdep->ppc_vsr0_upper_regnum != -1) + if (regno == -1 || vsx_register_p (gdbarch, regno)) + store_vsx_registers (regcache, pid, regno); +} + +const struct target_desc * +ppc_fbsd_nat_target::read_description () +{ + int tid = ptid_get_lwp (inferior_ptid); + if (tid == 0) + tid = ptid_get_pid (inferior_ptid); + + struct ppc_fbsd_features features = ppc_fbsd_no_features; + + features.wordsize = ppc_fbsd_target_wordsize (tid); + + if (have_ptrace_getsetvsxregs) + { + gdb_vsxregset_t vsxregset; + + if (ptrace (PT_GETVSRREGS, tid, (PTRACE_TYPE_ARG3) &vsxregset, 0) >= 0) + features.vsx = true; + + /* EINVAL means that the PT_GETVSRREGS request isn't supported. + Anything else needs to be reported. */ + else if (errno != EINVAL) + perror_with_name (_("Unable to fetch VSX registers")); + } + + if (have_ptrace_getvrregs) + { + gdb_vrregset_t vrregset; + + if (ptrace (PT_GETVRREGS, tid, (PTRACE_TYPE_ARG3) &vrregset, 0) >= 0) + features.altivec = true; + + /* EINVAL means that the PT_GETVRREGS request isn't supported. + Anything else needs to be reported. */ + else if (errno != EINVAL) + perror_with_name (_("Unable to fetch AltiVec registers")); + } + + return ppc_fbsd_match_description (features); } /* Architecture specific function that reconstructs the diff --git a/gdb/ppc-fbsd-tdep.c b/gdb/ppc-fbsd-tdep.c index 495ccca8f1..f829d4808d 100644 --- a/gdb/ppc-fbsd-tdep.c +++ b/gdb/ppc-fbsd-tdep.c @@ -36,6 +36,8 @@ #include "fbsd-tdep.h" #include "solib-svr4.h" +#include "arch/ppc-fbsd-common.h" + /* 32-bit regset descriptions. */ @@ -105,6 +107,31 @@ static const struct regset ppc32_fbsd_fpregset = { ppc_collect_fpregset }; +static const struct regcache_map_entry ppc32_fbsd_vrregmap[] = { + { 32, PPC_VR0_REGNUM, 16 }, + { 1, REGCACHE_MAP_SKIP, 2}, + { 1, PPC_VRSAVE_REGNUM, 4 }, + { 1, PPC_VSCR_REGNUM, 4 }, + { 0 } +}; + +static const struct regset ppc32_fbsd_vrregset = { + ppc32_fbsd_vrregmap, + regcache_supply_regset, + regcache_collect_regset +}; + +static const struct regcache_map_entry ppc32_fbsd_vsxregmap[] = { + { 32, PPC_VSR0_UPPER_REGNUM, 8 }, + { 0 } +}; + +static const struct regset ppc32_fbsd_vsxregset = { + ppc32_fbsd_vsxregmap, + regcache_supply_regset, + regcache_collect_regset +}; + const struct regset * ppc_fbsd_gregset (int wordsize) { @@ -117,6 +144,18 @@ ppc_fbsd_fpregset (void) return &ppc32_fbsd_fpregset; } +const struct regset * +ppc_fbsd_vrregset (void) +{ + return &ppc32_fbsd_vrregset; +} + +const struct regset * +ppc_fbsd_vsxregset (void) +{ + return &ppc32_fbsd_vsxregset; +} + /* Iterate over core file register note sections. */ static void @@ -126,12 +165,56 @@ ppcfbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, const struct regcache *regcache) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int have_altivec = tdep->ppc_vr0_regnum != -1; + int have_vsx = tdep->ppc_vsr0_upper_regnum != -1; if (tdep->wordsize == 4) - cb (".reg", 148, &ppc32_fbsd_gregset, NULL, cb_data); + cb (".reg", PPC_FBSD_SIZEOF_GREGSET_32, &ppc32_fbsd_gregset, NULL, cb_data); else - cb (".reg", 296, &ppc64_fbsd_gregset, NULL, cb_data); - cb (".reg2", 264, &ppc32_fbsd_fpregset, NULL, cb_data); + cb (".reg", PPC_FBSD_SIZEOF_GREGSET_64, &ppc64_fbsd_gregset, NULL, cb_data); + cb (".reg2", PPC_FBSD_SIZEOF_FPREGSET, &ppc32_fbsd_fpregset, NULL, cb_data); + + if (have_altivec) + cb (".reg-ppc-vmx", PPC_FBSD_SIZEOF_VRREGSET, ppc_fbsd_vrregset (), + "ppc Altivec", cb_data); + + if (have_vsx) + cb (".reg-ppc-vsx", PPC_FBSD_SIZEOF_VSXREGSET, ppc_fbsd_vsxregset (), + "POWER7 VSX", cb_data); +} + +static const struct target_desc * +ppc_fbsd_core_read_description (struct gdbarch *gdbarch, + struct target_ops *target, + bfd *abfd) +{ + struct ppc_fbsd_features features = ppc_fbsd_no_features; + asection *altivec = bfd_get_section_by_name (abfd, ".reg-ppc-vmx"); + asection *vsx = bfd_get_section_by_name (abfd, ".reg-ppc-vsx"); + asection *section = bfd_get_section_by_name (abfd, ".reg"); + + if (! section) + return NULL; + + switch (bfd_section_size (abfd, section)) + { + case PPC_FBSD_SIZEOF_GREGSET_32: + features.wordsize = 4; + break; + case PPC_FBSD_SIZEOF_GREGSET_64: + features.wordsize = 8; + break; + default: + return NULL; + } + + if (altivec) + features.altivec = true; + + if (vsx) + features.vsx = true; + + return ppc_fbsd_match_description (features); } /* Default page size. */ @@ -317,6 +400,8 @@ ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpc"); } + set_gdbarch_core_read_description (gdbarch, ppc_fbsd_core_read_description); + set_gdbarch_iterate_over_regset_sections (gdbarch, ppcfbsd_iterate_over_regset_sections); diff --git a/gdb/ppc-fbsd-tdep.h b/gdb/ppc-fbsd-tdep.h index 356b5941ba..7b28bab73c 100644 --- a/gdb/ppc-fbsd-tdep.h +++ b/gdb/ppc-fbsd-tdep.h @@ -25,5 +25,7 @@ struct regset; /* From ppc-fbsd-tdep.c ... */ const struct regset *ppc_fbsd_gregset (int); const struct regset *ppc_fbsd_fpregset (void); +const struct regset *ppc_fbsd_vrregset (void); +const struct regset *ppc_fbsd_vsxregset (void); #endif /* PPC_FBSD_TDEP_H */ From b96b56416f2262135d5bc15a45af00dd9eab946a Mon Sep 17 00:00:00 2001 From: Luis Pires Date: Fri, 8 Jun 2018 18:33:19 -0300 Subject: [PATCH 2/3] Rework after comments from pedromfc --- gdb/arch/ppc-fbsd-common.h | 6 +-- gdb/ppc-fbsd-nat.c | 86 +++++++++++++++----------------------- gdb/ppc-fbsd-tdep.c | 17 +++++++- 3 files changed, 51 insertions(+), 58 deletions(-) diff --git a/gdb/arch/ppc-fbsd-common.h b/gdb/arch/ppc-fbsd-common.h index b3448d6f5b..997d906a58 100644 --- a/gdb/arch/ppc-fbsd-common.h +++ b/gdb/arch/ppc-fbsd-common.h @@ -20,6 +20,8 @@ #ifndef ARCH_PPC_FBSD_COMMON_H #define ARCH_PPC_FBSD_COMMON_H +struct target_desc; + #define PPC_FBSD_SIZEOF_GREGSET_32 148 #define PPC_FBSD_SIZEOF_GREGSET_64 296 #define PPC_FBSD_SIZEOF_FPREGSET 264 @@ -28,8 +30,6 @@ 32 128-bit registers + 8 spare bytes + VRSAVE (4 bytes) + VSCR (4 bytes) */ #define PPC_FBSD_SIZEOF_VRREGSET (32*16 + 8 + 4 + 4) -typedef char gdb_vrregset_t[PPC_FBSD_SIZEOF_VRREGSET]; - /* This is the layout of the POWER7 VSX registers and the way they overlap with the existing FPR and VMX registers. @@ -64,8 +64,6 @@ typedef char gdb_vrregset_t[PPC_FBSD_SIZEOF_VRREGSET]; registers. */ #define PPC_FBSD_SIZEOF_VSXREGSET (32*8) -typedef char gdb_vsxregset_t[PPC_FBSD_SIZEOF_VSXREGSET]; - /* Features used to determine the target description. */ struct ppc_fbsd_features { diff --git a/gdb/ppc-fbsd-nat.c b/gdb/ppc-fbsd-nat.c index 7e122972aa..9636abcb20 100644 --- a/gdb/ppc-fbsd-nat.c +++ b/gdb/ppc-fbsd-nat.c @@ -60,18 +60,8 @@ #define PT_SETVSRREGS (PT_FIRSTMACH + 3) #endif -/* Non-zero if our kernel may support the PT_GETVSRREGS and - PT_SETVSRREGS requests, for reading and writing the VSX - POWER7 registers 0 through 31. Zero if we've tried one of them and - gotten an error. Note that VSX registers 32 through 63 overlap - with VR registers 0 through 31. */ -int have_ptrace_getsetvsxregs = 1; - -/* Non-zero if our kernel may support the PT_GETVRREGS and - PT_SETVRREGS requests, for reading and writing the Altivec - registers. Zero if we've tried one of them and gotten an - error. */ -int have_ptrace_getvrregs = 1; +typedef char gdb_vrregset_t[PPC_FBSD_SIZEOF_VRREGSET]; +typedef char gdb_vsxregset_t[PPC_FBSD_SIZEOF_VSXREGSET]; struct ppc_fbsd_nat_target final : public fbsd_nat_target { @@ -174,7 +164,9 @@ fetch_altivec_registers (struct regcache *regcache, int tid, { if (errno == EINVAL) { - have_ptrace_getvrregs = 0; + /* Mark registers as unavailable */ + vrregset->supply_regset (vrregset, regcache, regno, NULL, + PPC_FBSD_SIZEOF_VRREGSET); return; } perror_with_name (_("Unable to fetch AltiVec registers")); @@ -199,7 +191,9 @@ fetch_vsx_registers (struct regcache *regcache, int tid, int regno) { if (errno == EINVAL) { - have_ptrace_getsetvsxregs = 0; + /* Mark registers as unavailable */ + vsxregset->supply_regset (vsxregset, regcache, regno, NULL, + PPC_FBSD_SIZEOF_VSXREGSET); return; } perror_with_name (_("Unable to fetch VSX registers")); @@ -222,7 +216,6 @@ store_altivec_registers (const struct regcache *regcache, int tid, { if (errno == EINVAL) { - have_ptrace_getvrregs = 0; return; } perror_with_name (_("Unable to fetch AltiVec registers")); @@ -248,7 +241,6 @@ store_vsx_registers (const struct regcache *regcache, int tid, int regno) { if (errno == EINVAL) { - have_ptrace_getsetvsxregs = 0; return; } perror_with_name (_("Unable to fetch VSX registers")); @@ -316,15 +308,13 @@ ppc_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regno) ppc_supply_fpregset (fpregset, regcache, regno, &fpregs, sizeof fpregs); } - if (have_ptrace_getvrregs) - if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1) - if (regno == -1 || altivec_register_p (gdbarch, regno)) - fetch_altivec_registers (regcache, pid, regno); + if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1) + if (regno == -1 || altivec_register_p (gdbarch, regno)) + fetch_altivec_registers (regcache, pid, regno); - if (have_ptrace_getsetvsxregs) - if (tdep->ppc_vsr0_upper_regnum != -1) - if (regno == -1 || vsx_register_p (gdbarch, regno)) - fetch_vsx_registers (regcache, pid, regno); + if (tdep->ppc_vsr0_upper_regnum != -1) + if (regno == -1 || vsx_register_p (gdbarch, regno)) + fetch_vsx_registers (regcache, pid, regno); } /* Store register REGNO back into the child process. If REGNO is -1, @@ -359,15 +349,13 @@ ppc_fbsd_nat_target::store_registers (struct regcache *regcache, int regno) perror_with_name (_("Couldn't set FP registers")); } - if (have_ptrace_getvrregs) - if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1) - if (regno == -1 || altivec_register_p (gdbarch, regno)) - store_altivec_registers (regcache, pid, regno); + if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1) + if (regno == -1 || altivec_register_p (gdbarch, regno)) + store_altivec_registers (regcache, pid, regno); - if (have_ptrace_getsetvsxregs) - if (tdep->ppc_vsr0_upper_regnum != -1) - if (regno == -1 || vsx_register_p (gdbarch, regno)) - store_vsx_registers (regcache, pid, regno); + if (tdep->ppc_vsr0_upper_regnum != -1) + if (regno == -1 || vsx_register_p (gdbarch, regno)) + store_vsx_registers (regcache, pid, regno); } const struct target_desc * @@ -381,31 +369,25 @@ ppc_fbsd_nat_target::read_description () features.wordsize = ppc_fbsd_target_wordsize (tid); - if (have_ptrace_getsetvsxregs) - { - gdb_vsxregset_t vsxregset; + gdb_vsxregset_t vsxregset; - if (ptrace (PT_GETVSRREGS, tid, (PTRACE_TYPE_ARG3) &vsxregset, 0) >= 0) - features.vsx = true; + if (ptrace (PT_GETVSRREGS, tid, (PTRACE_TYPE_ARG3) &vsxregset, 0) >= 0) + features.vsx = true; - /* EINVAL means that the PT_GETVSRREGS request isn't supported. - Anything else needs to be reported. */ - else if (errno != EINVAL) - perror_with_name (_("Unable to fetch VSX registers")); - } + /* EINVAL means that the PT_GETVSRREGS request isn't supported. + Anything else needs to be reported. */ + else if (errno != EINVAL) + perror_with_name (_("Unable to fetch VSX registers")); - if (have_ptrace_getvrregs) - { - gdb_vrregset_t vrregset; + gdb_vrregset_t vrregset; - if (ptrace (PT_GETVRREGS, tid, (PTRACE_TYPE_ARG3) &vrregset, 0) >= 0) - features.altivec = true; + if (ptrace (PT_GETVRREGS, tid, (PTRACE_TYPE_ARG3) &vrregset, 0) >= 0) + features.altivec = true; - /* EINVAL means that the PT_GETVRREGS request isn't supported. - Anything else needs to be reported. */ - else if (errno != EINVAL) - perror_with_name (_("Unable to fetch AltiVec registers")); - } + /* EINVAL means that the PT_GETVRREGS request isn't supported. + Anything else needs to be reported. */ + else if (errno != EINVAL) + perror_with_name (_("Unable to fetch AltiVec registers")); return ppc_fbsd_match_description (features); } diff --git a/gdb/ppc-fbsd-tdep.c b/gdb/ppc-fbsd-tdep.c index f829d4808d..a1fa7b8aaa 100644 --- a/gdb/ppc-fbsd-tdep.c +++ b/gdb/ppc-fbsd-tdep.c @@ -38,6 +38,19 @@ #include "arch/ppc-fbsd-common.h" +static void +ppc_fbsd_collect_vrregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *buf, size_t len) +{ + gdb_byte *vrregs = (gdb_byte *) buf; + + /* Zero out the unused bytes in ppc32_fbsd_vrregmap + in case they get displayed somewhere (e.g. in core files). */ + memset (&vrregs[32 * 16], 0, 8); + + regcache_collect_regset (regset, regcache, regnum, buf, len); +} /* 32-bit regset descriptions. */ @@ -109,7 +122,7 @@ static const struct regset ppc32_fbsd_fpregset = { static const struct regcache_map_entry ppc32_fbsd_vrregmap[] = { { 32, PPC_VR0_REGNUM, 16 }, - { 1, REGCACHE_MAP_SKIP, 2}, + { 1, REGCACHE_MAP_SKIP, 8}, { 1, PPC_VRSAVE_REGNUM, 4 }, { 1, PPC_VSCR_REGNUM, 4 }, { 0 } @@ -118,7 +131,7 @@ static const struct regcache_map_entry ppc32_fbsd_vrregmap[] = { static const struct regset ppc32_fbsd_vrregset = { ppc32_fbsd_vrregmap, regcache_supply_regset, - regcache_collect_regset + ppc_fbsd_collect_vrregset }; static const struct regcache_map_entry ppc32_fbsd_vsxregmap[] = { From d717de9bc2059e3187433c382ceac5dc0418a6dd Mon Sep 17 00:00:00 2001 From: Luis Pires Date: Thu, 14 Jun 2018 18:54:40 -0300 Subject: [PATCH 3/3] Rework after new comments from pedromfc --- gdb/arch/ppc-fbsd-common.h | 2 +- gdb/ppc-fbsd-nat.c | 54 ++++++++------------------------------ 2 files changed, 12 insertions(+), 44 deletions(-) diff --git a/gdb/arch/ppc-fbsd-common.h b/gdb/arch/ppc-fbsd-common.h index 997d906a58..0a1b199307 100644 --- a/gdb/arch/ppc-fbsd-common.h +++ b/gdb/arch/ppc-fbsd-common.h @@ -27,7 +27,7 @@ struct target_desc; #define PPC_FBSD_SIZEOF_FPREGSET 264 /* PT_GETVRREGS returns data as defined in machine/pcb.h: - 32 128-bit registers + 8 spare bytes + VRSAVE (4 bytes) + VSCR (4 bytes) */ + 32 128-bit registers + 8 spare bytes + VRSAVE (4 bytes) + VSCR (4 bytes). */ #define PPC_FBSD_SIZEOF_VRREGSET (32*16 + 8 + 4 + 4) /* This is the layout of the POWER7 VSX registers and the way they overlap diff --git a/gdb/ppc-fbsd-nat.c b/gdb/ppc-fbsd-nat.c index 9636abcb20..d81b62139a 100644 --- a/gdb/ppc-fbsd-nat.c +++ b/gdb/ppc-fbsd-nat.c @@ -42,7 +42,7 @@ /* These definitions should really come from machine/ptrace.h, but we provide them in case gdb is built on an machine whose - FreeBSD version still doesn't have them. */ + FreeBSD version still doesn't have them. */ #ifndef PT_FIRSTMACH #define PT_FIRSTMACH 64 @@ -161,16 +161,7 @@ fetch_altivec_registers (struct regcache *regcache, int tid, ret = ptrace (PT_GETVRREGS, tid, (PTRACE_TYPE_ARG3) ®s, 0); if (ret < 0) - { - if (errno == EINVAL) - { - /* Mark registers as unavailable */ - vrregset->supply_regset (vrregset, regcache, regno, NULL, - PPC_FBSD_SIZEOF_VRREGSET); - return; - } - perror_with_name (_("Unable to fetch AltiVec registers")); - } + perror_with_name (_("Unable to fetch AltiVec registers")); vrregset->supply_regset (vrregset, regcache, regno, ®s, PPC_FBSD_SIZEOF_VRREGSET); @@ -188,16 +179,7 @@ fetch_vsx_registers (struct regcache *regcache, int tid, int regno) ret = ptrace (PT_GETVSRREGS, tid, (PTRACE_TYPE_ARG3) ®s, 0); if (ret < 0) - { - if (errno == EINVAL) - { - /* Mark registers as unavailable */ - vsxregset->supply_regset (vsxregset, regcache, regno, NULL, - PPC_FBSD_SIZEOF_VSXREGSET); - return; - } - perror_with_name (_("Unable to fetch VSX registers")); - } + perror_with_name (_("Unable to fetch VSX registers")); vsxregset->supply_regset (vsxregset, regcache, regno, ®s, PPC_FBSD_SIZEOF_VSXREGSET); @@ -213,13 +195,7 @@ store_altivec_registers (const struct regcache *regcache, int tid, ret = ptrace (PT_GETVRREGS, tid, (PTRACE_TYPE_ARG3) ®s, 0); if (ret < 0) - { - if (errno == EINVAL) - { - return; - } - perror_with_name (_("Unable to fetch AltiVec registers")); - } + perror_with_name (_("Unable to fetch AltiVec registers")); vrregset->collect_regset (vrregset, regcache, regno, ®s, PPC_FBSD_SIZEOF_VRREGSET); @@ -238,13 +214,7 @@ store_vsx_registers (const struct regcache *regcache, int tid, int regno) ret = ptrace (PT_GETVSRREGS, tid, (PTRACE_TYPE_ARG3) ®s, 0); if (ret < 0) - { - if (errno == EINVAL) - { - return; - } - perror_with_name (_("Unable to fetch VSX registers")); - } + perror_with_name (_("Unable to fetch VSX registers")); vsxregset->collect_regset (vsxregset, regcache, regno, ®s, PPC_FBSD_SIZEOF_VSXREGSET); @@ -261,20 +231,20 @@ ppc_fbsd_target_wordsize (int tid) #ifdef __powerpc64__ /* Check for 64-bit inferior process. This is the case when the host is - 64-bit, and PT_GETREGS returns less data than the length of struct reg. */ + 64-bit, and PT_GETREGS returns less data than the length of gdb_gregset_t. */ gdb_gregset_t regs0; gdb_gregset_t regs1; /* Initialize regs0 with 00's and regs1 with ff's. If, after ptrace fills them, they have the same contents, it means ptrace returned data for a - 64-bit inferior. */ - memset (®s0, 0, sizeof regs0); - memset (®s1, 0xff, sizeof regs1); + 64-bit inferior. */ + memset (®s0, 0, sizeof (regs0)); + memset (®s1, 0xff, sizeof (regs1)); if (ptrace (PT_GETREGS, tid, (PTRACE_TYPE_ARG3) ®s0, 0) >= 0 && ptrace (PT_GETREGS, tid, (PTRACE_TYPE_ARG3) ®s1, 0) >= 0) - if (memcmp(®s0, ®s1, sizeof regs0) == 0) + if (memcmp (®s0, ®s1, sizeof (regs0)) == 0) wordsize = 8; #endif @@ -305,7 +275,7 @@ ppc_fbsd_nat_target::fetch_registers (struct regcache *regcache, int regno) if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) perror_with_name (_("Couldn't get FP registers")); - ppc_supply_fpregset (fpregset, regcache, regno, &fpregs, sizeof fpregs); + ppc_supply_fpregset (fpregset, regcache, regno, &fpregs, sizeof (fpregs)); } if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1) @@ -362,8 +332,6 @@ const struct target_desc * ppc_fbsd_nat_target::read_description () { int tid = ptid_get_lwp (inferior_ptid); - if (tid == 0) - tid = ptid_get_pid (inferior_ptid); struct ppc_fbsd_features features = ppc_fbsd_no_features;