diff options
author | Pedro Franco de Carvalho <pedromfc@linux.vnet.ibm.com> | 2018-05-22 11:09:05 -0300 |
---|---|---|
committer | Pedro Franco de Carvalho <pedromfc@linux.vnet.ibm.com> | 2018-05-22 11:52:03 -0300 |
commit | 1d75a65809b49d41e97518b99c551a4bb2517500 (patch) | |
tree | fa78d1d569616d20b3ad13629d870d53bbc13a06 /gdb/ppc-linux-tdep.c | |
parent | d078308a2ed1290e587b4365e2d7382d951a26af (diff) | |
download | gdb-1d75a65809b49d41e97518b99c551a4bb2517500.zip gdb-1d75a65809b49d41e97518b99c551a4bb2517500.tar.gz gdb-1d75a65809b49d41e97518b99c551a4bb2517500.tar.bz2 |
[PowerPC] Fix access to VSCR in linux targets
The 4-byte VSCR register is found inside a 16-byte field in the regset
returned by ptrace and in core files. The position of VSCR depends on
the endianess of the target, which was previously assumed to be
big-endian for the purpose of getting VSCR. This patch removes this
assumption to fix access to VSCR in little-endian mode.
gdb/ChangeLog:
2018-05-22 Pedro Franco de Carvalho <pedromfc@linux.vnet.ibm.com>
* ppc-tdep.h (struct ppc_reg_offsets): Remove vector register
offset fields.
* ppc-fbsd-tdep.c (ppc32_fbsd_reg_offsets): Remove initializers
for vector register offset fields.
(ppc64_fbsd_reg_offsets): Likewise.
* ppc-nbsd-tdep.c (_initialize_ppcnbsd_tdep): Remove assignment
to vector register offset fields.
* ppc-obsd-tdep.c (_initialize_ppcnbsd_tdep): Remove assignment
to vector register offset fields.
* ppc-obsd-nat.c (_initialize_ppcobsd_nat): Remove assignment to
vector register offset fields.
* rs6000-aix-tdep.c (rs6000_aix32_reg_offsets): Remove
initializers for vector register offset fields.
(rs6000_aix64_reg_offsets): Likewise.
* rs6000-tdep.c (ppc_vrreg_offset): Remove.
(ppc_supply_vrregset): Remove.
(ppc_collect_vrregset): Remove.
* ppc-linux-tdep.c (ppc_linux_collect_vrregset): New function.
(ppc_linux_vrregset) : New function.
(ppc32_le_linux_vrregmap, ppc32_be_linux_vrregmap)
(ppc32_le_linux_vrregset, ppc32_be_linux_vrregset): New globals.
(ppc32_linux_vrregset): Remove.
(ppc_linux_iterate_over_regset_sections): Call ppc_linux_vrregset
and use result instead of ppc32_linux_vrregset.
(ppc32_linux_reg_offsets): Remove initializers for vector register
offset fields.
(ppc64_linux_reg_offsets): Likewise.
* ppc-linux-tdep.h (ppc_linux_vrregset): New declaration.
* ppc-linux-nat.c: Include regset.h.
(gdb_vrregset_t): Adjust comment to account for little-endian
mode.
(supply_vrregset, fill_vrregset): Remove.
(fetch_altivec_register, store_altivec_register): Remove.
(fetch_altivec_registers): Add regno parameter. Get regset using
ppc_linux_vrregset. Use regset to supply registers.
(store_altivec_registers): Add regno parameter. Get regset using
ppc_linux_vrregset. Use regset to collect registers.
(fetch_register): Call fetch_altivec_registers instead of
fetch_altivec_register.
(store_register): Call store_altivec_registers instead of
store_altivec_register.
(fetch_ppc_registers): Call fetch_altivec_registers with -1 for
the new regno parameter.
(store_ppc_registers): Call store_altivec_registers with -1 for
the new regno parameter.
gdb/gdbserver/ChangeLog:
2018-05-22 Pedro Franco de Carvalho <pedromfc@linux.vnet.ibm.com>
* linux-ppc-low.c (ppc_fill_vrregset): Add vscr_offset variable.
Set vscr_offset to 0 in little-endian mode and 12 in big-endian
mode. Call collect_register_by_name with vscr using
vscr_offset. Zero-pad vscr and vrsave fields in collector buffer.
(ppc_store_vrregset): Add and set vscr_offset variable as in
ppc_fill_vrregset. Call supply_register_by_name with vscr using
vscr_offset.
Diffstat (limited to 'gdb/ppc-linux-tdep.c')
-rw-r--r-- | gdb/ppc-linux-tdep.c | 82 |
1 files changed, 64 insertions, 18 deletions
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 344069d..7362c4b 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -444,6 +444,24 @@ ppc_linux_collect_gregset (const struct regset *regset, } } +static void +ppc_linux_collect_vrregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *buf, size_t len) +{ + gdb_byte *vrregs = (gdb_byte *) buf; + + /* Zero-pad the unused bytes in the fields for vscr and vrsave + in case they get displayed somewhere (e.g. in core files). */ + if (regnum == PPC_VSCR_REGNUM || regnum == -1) + memset (&vrregs[32 * 16], 0, 16); + + if (regnum == PPC_VRSAVE_REGNUM || regnum == -1) + memset (&vrregs[33 * 16], 0, 16); + + regcache_collect_regset (regset, regcache, regnum, buf, len); +} + /* Regset descriptions. */ static const struct ppc_reg_offsets ppc32_linux_reg_offsets = { @@ -462,12 +480,7 @@ static const struct ppc_reg_offsets ppc32_linux_reg_offsets = /* Floating-point registers. */ /* .f0_offset = */ 0, /* .fpscr_offset = */ 256, - /* .fpscr_size = */ 8, - - /* AltiVec registers. */ - /* .vr0_offset = */ 0, - /* .vscr_offset = */ 512 + 12, - /* .vrsave_offset = */ 528 + /* .fpscr_size = */ 8 }; static const struct ppc_reg_offsets ppc64_linux_reg_offsets = @@ -487,12 +500,7 @@ static const struct ppc_reg_offsets ppc64_linux_reg_offsets = /* Floating-point registers. */ /* .f0_offset = */ 0, /* .fpscr_offset = */ 256, - /* .fpscr_size = */ 8, - - /* AltiVec registers. */ - /* .vr0_offset = */ 0, - /* .vscr_offset = */ 512 + 12, - /* .vrsave_offset = */ 528 + /* .fpscr_size = */ 8 }; static const struct regset ppc32_linux_gregset = { @@ -513,10 +521,36 @@ static const struct regset ppc32_linux_fpregset = { ppc_collect_fpregset }; -static const struct regset ppc32_linux_vrregset = { - &ppc32_linux_reg_offsets, - ppc_supply_vrregset, - ppc_collect_vrregset +static const struct regcache_map_entry ppc32_le_linux_vrregmap[] = + { + { 32, PPC_VR0_REGNUM, 16 }, + { 1, PPC_VSCR_REGNUM, 4 }, + { 1, REGCACHE_MAP_SKIP, 12 }, + { 1, PPC_VRSAVE_REGNUM, 4 }, + { 1, REGCACHE_MAP_SKIP, 12 }, + { 0 } + }; + +static const struct regcache_map_entry ppc32_be_linux_vrregmap[] = + { + { 32, PPC_VR0_REGNUM, 16 }, + { 1, REGCACHE_MAP_SKIP, 12}, + { 1, PPC_VSCR_REGNUM, 4 }, + { 1, PPC_VRSAVE_REGNUM, 4 }, + { 1, REGCACHE_MAP_SKIP, 12 }, + { 0 } + }; + +static const struct regset ppc32_le_linux_vrregset = { + ppc32_le_linux_vrregmap, + regcache_supply_regset, + ppc_linux_collect_vrregset +}; + +static const struct regset ppc32_be_linux_vrregset = { + ppc32_be_linux_vrregmap, + regcache_supply_regset, + ppc_linux_collect_vrregset }; static const struct regset ppc32_linux_vsxregset = { @@ -537,6 +571,15 @@ ppc_linux_fpregset (void) return &ppc32_linux_fpregset; } +const struct regset * +ppc_linux_vrregset (struct gdbarch *gdbarch) +{ + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + return &ppc32_be_linux_vrregset; + else + return &ppc32_le_linux_vrregset; +} + /* Iterate over supported core file register note sections. */ static void @@ -557,8 +600,11 @@ ppc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, cb (".reg2", 264, &ppc32_linux_fpregset, NULL, cb_data); if (have_altivec) - cb (".reg-ppc-vmx", PPC_LINUX_SIZEOF_VRREGSET, &ppc32_linux_vrregset, - "ppc Altivec", cb_data); + { + const struct regset *vrregset = ppc_linux_vrregset (gdbarch); + cb (".reg-ppc-vmx", PPC_LINUX_SIZEOF_VRREGSET, vrregset, + "ppc Altivec", cb_data); + } if (have_vsx) cb (".reg-ppc-vsx", PPC_LINUX_SIZEOF_VSXREGSET, |