forked from Imagelibrary/binutils-gdb
[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.
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user