[patch] Add support for PPC Altivec registers in core files

Carlos Eduardo Seo
2007-10-22T17:51:31Z

[-- Attachment #1: Type: text/plain, Size: 744 bytes --]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Recently, a kernel patch by Mark Nelson added support for Altivec
registers in core dumps under a new note section called NT_PPC_VMX. Two
other patches (by myself and Roland McGrath) added support for the new
note section in binutils. Now, this patch adds support for Altivec
registers debugging in core files, using the contents under NT_PPC_VMX.

Ok to commit?

Regards,

- --
Carlos Eduardo Seo
Software Engineer
IBM Linux Technology Center
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.7 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFHHOMNqvq7Aov/qQARAg+QAJ4veas3SVbtNTRfo4b5688I1l49WwCeNt1P
YaBKs38DoXS6iGm3he2AHg4=
=NkD3
-----END PGP SIGNATURE-----

[-- Attachment #2: altivec-core.diff --]
[-- Type: text/x-patch, Size: 9817 bytes --]

2007-10-22 Carlos Eduardo Seo <cseo@linux.vnet.ibm.com>

* ppc-linux-tdep.c (ppc32_linux_reg_offsets): Corrected
swapped offsets and VRSAVE offset.
(ppc64_linux_reg_offsets): Corrected swapped offsets.
(ppc32_linux_vrregset): Added. Necessary for reading the
Altivec registers from the core file.
(ppc_linux_regset_from_core_section): Added support for
.reg-ppc-vmx section, which contains the Altivec registers.
* ppc-tdep.h (ppc_altivec_support_p): Declare.
(ppc_supply_vrregset): Declare.
(ppc_collect_vrregset): Declare.
* rs6000-tdep.c (ppc_altivec_support_p): Added. Checks if
current arch supports Altivec.
(ppc_supply_vrregset): Added. Supplies the contents of
Altivec registers.
(ppc_collect_vrregset): Added. Collects the contents of
Altivec registers.
* corelow.c (get_core_registers): Added support for
.reg-ppc-vmx section, which contains the Altivec registers.

Index: gdb/ppc-linux-tdep.c
===================================================================
--- gdb/ppc-linux-tdep.c.orig
+++ gdb/ppc-linux-tdep.c
@@ -650,8 +650,8 @@ static const struct ppc_reg_offsets ppc3

/* AltiVec registers. */
/* .vr0_offset = */ 0,
- /* .vrsave_offset = */ 512,
- /* .vscr_offset = */ 512 + 12
+ /* .vscr_offset = */ 512 + 12,
+ /* .vrsave_offset = */ 528
};

static const struct ppc_reg_offsets ppc64_linux_reg_offsets =
@@ -675,8 +675,8 @@ static const struct ppc_reg_offsets ppc6

/* AltiVec registers. */
/* .vr0_offset = */ 0,
- /* .vrsave_offset = */ 528,
- /* .vscr_offset = */ 512 + 12
+ /* .vscr_offset = */ 512 + 12,
+ /* .vrsave_offset = */ 528
};

static const struct regset ppc32_linux_gregset = {
@@ -700,6 +700,13 @@ static const struct regset ppc32_linux_f
NULL
};

+static const struct regset ppc32_linux_vrregset = {
+ &ppc32_linux_reg_offsets,
+ ppc_supply_vrregset,
+ ppc_collect_vrregset,
+ NULL
+};
+
const struct regset *
ppc_linux_gregset (int wordsize)
{
@@ -726,6 +733,8 @@ ppc_linux_regset_from_core_section (stru
}
if (strcmp (sect_name, ".reg2") == 0)
return &ppc32_linux_fpregset;
+ if (strcmp (sect_name, ".reg-ppc-vmx") == 0)
+ return &ppc32_linux_vrregset;
return NULL;
}

Index: gdb/ppc-tdep.h
===================================================================
--- gdb/ppc-tdep.h.orig
+++ gdb/ppc-tdep.h
@@ -73,6 +73,10 @@ int spe_register_p (int regno);
floating-point registers (f0 --- f31 and fpscr). */
int ppc_floating_point_unit_p (struct gdbarch *gdbarch);

+/* 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);
+
/* Register set description. */

struct ppc_reg_offsets
@@ -116,6 +120,14 @@ extern void ppc_supply_fpregset (const s
struct regcache *regcache,
int regnum, const void *fpregs, size_t len);

+/* 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. */
+
+extern void ppc_supply_vrregset (const struct regset *regset,
+ struct regcache *regcache,
+ int regnum, const void *vrregs, size_t len);
+
/* Collect register REGNUM in the general-purpose register set
REGSET. from register cache REGCACHE into the buffer specified by
GREGS and LEN. If REGNUM is -1, do this for all registers in
@@ -134,6 +146,15 @@ extern void ppc_collect_fpregset (const
const struct regcache *regcache,
int regnum, void *fpregs, size_t len);

+/* 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
+ REGSET. */
+
+extern void ppc_collect_vrregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *vrregs, size_t len);
+
/* Private data that this module attaches to struct gdbarch. */

struct gdbarch_tdep
Index: gdb/rs6000-tdep.c
===================================================================
--- gdb/rs6000-tdep.c.orig
+++ gdb/rs6000-tdep.c
@@ -194,6 +194,17 @@ ppc_floating_point_unit_p (struct gdbarc
&& tdep->ppc_fpscr_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)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ return (tdep->ppc_vr0_regnum >= 0
+ && tdep->ppc_vrsave_regnum >= 0
+ && (tdep->ppc_vrsave_regnum - 1) >= 0);
+}

/* Check that TABLE[GDB_REGNO] is not already initialized, and then
set it to SIM_REGNO.
@@ -436,6 +447,24 @@ ppc_fpreg_offset (struct gdbarch_tdep *t
return -1;
}

+static int
+ppc_vrreg_offset (struct gdbarch_tdep *tdep,
+ const struct ppc_reg_offsets *offsets,
+ int regnum)
+{
+ if (regnum >= tdep->ppc_vr0_regnum
+ && regnum < tdep->ppc_vr0_regnum + ppc_num_vrs)
+ return offsets->vr0_offset + (regnum - tdep->ppc_vr0_regnum) * 8;
+
+ if (regnum == (tdep->ppc_vrsave_regnum - 1))
+ return offsets->vscr_offset;
+
+ if (regnum == tdep->ppc_vrsave_regnum)
+ return offsets->vrsave_offset;
+
+ return -1;
+}
+
/* Supply register REGNUM in the general-purpose register set REGSET
from the buffer specified by GREGS and LEN to register cache
REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
@@ -518,6 +547,52 @@ ppc_supply_fpregset (const struct regset
regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 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. */
+
+void
+ppc_supply_vrregset (const struct regset *regset, struct regcache *regcache,
+ int regnum, const void *vrregs, size_t len)
+{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep;
+ const struct ppc_reg_offsets *offsets;
+ size_t offset;
+
+ if (!ppc_altivec_support_p (gdbarch))
+ return;
+
+ tdep = gdbarch_tdep (gdbarch);
+ offsets = regset->descr;
+ if (regnum == -1)
+ {
+ int i;
+
+ for (i = tdep->ppc_vr0_regnum, offset = offsets->vr0_offset;
+ i < tdep->ppc_vr0_regnum + ppc_num_vrs;
+ i++, offset += 16)
+ ppc_supply_reg (regcache, i, vrregs, offset, 16);
+
+ ppc_supply_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
+ vrregs, offsets->vscr_offset, 4);
+
+ ppc_supply_reg (regcache, tdep->ppc_vrsave_regnum,
+ vrregs, offsets->vrsave_offset, 4);
+ return;
+ }
+
+ offset = ppc_vrreg_offset (tdep, offsets, regnum);
+ if ((regnum != tdep->ppc_vrsave_regnum) && (regnum != (tdep->ppc_vrsave_regnum - 1)))
+ ppc_supply_reg (regcache, regnum, vrregs, offset, 16);
+ else if (regnum == (tdep->ppc_vrsave_regnum - 1))
+ ppc_supply_reg (regcache, regnum,
+ vrregs, offsets->vscr_offset, 4);
+ else
+ ppc_supply_reg (regcache, regnum,
+ vrregs, offsets->vrsave_offset, 4);
+}
+
/* Collect register REGNUM in the general-purpose register set
REGSET from register cache REGCACHE into the buffer specified by
GREGS and LEN. If REGNUM is -1, do this for all registers in
@@ -603,6 +678,54 @@ ppc_collect_fpregset (const struct regse
ppc_collect_reg (regcache, regnum, fpregs, offset,
regnum == tdep->ppc_fpscr_regnum ? offsets->fpscr_size : 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
+ REGSET. */
+
+void
+ppc_collect_vrregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *vrregs, size_t len)
+{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep;
+ const struct ppc_reg_offsets *offsets;
+ size_t offset;
+
+ if (!ppc_altivec_support_p (gdbarch))
+ return;
+
+ tdep = gdbarch_tdep (gdbarch);
+ offsets = regset->descr;
+ if (regnum == -1)
+ {
+ int i;
+
+ for (i = tdep->ppc_vr0_regnum, offset = offsets->vr0_offset;
+ i < tdep->ppc_vr0_regnum + ppc_num_vrs;
+ i++, offset += 16)
+ ppc_collect_reg (regcache, i, vrregs, offset, 16);
+
+ ppc_collect_reg (regcache, (tdep->ppc_vrsave_regnum - 1),
+ vrregs, offsets->vscr_offset, 4);
+
+ ppc_collect_reg (regcache, tdep->ppc_vrsave_regnum,
+ vrregs, offsets->vrsave_offset, 4);
+ return;
+ }
+
+ offset = ppc_vrreg_offset (tdep, offsets, regnum);
+ if ((regnum != tdep->ppc_vrsave_regnum) && (regnum != (tdep->ppc_vrsave_regnum - 1)))
+ ppc_collect_reg (regcache, regnum, vrregs, offset, 16);
+ else if (regnum == (tdep->ppc_vrsave_regnum - 1))
+ ppc_collect_reg (regcache, regnum,
+ vrregs, offsets->vscr_offset, 4);
+ else
+ ppc_collect_reg (regcache, regnum,
+ vrregs, offsets->vrsave_offset, 4);
+}
\f

/* Read a LEN-byte address from debugged memory address MEMADDR. */
Index: gdb/corelow.c
===================================================================
--- gdb/corelow.c.orig
+++ gdb/corelow.c
@@ -499,6 +499,8 @@ get_core_registers (struct regcache *reg
".reg2", 2, "floating-point", 0);
get_core_register_section (regcache,
".reg-xfp", 3, "extended floating-point", 0);
+ get_core_register_section (regcache,
+ ".reg-ppc-vmx", 3, "ppc Altivec", 0);

/* Supply dummy value for all registers not found in the core. */
for (i = 0; i < gdbarch_num_regs (current_gdbarch); i++)

[-- Attachment #3: altivec-core.diff.sig --]
[-- Type: application/octet-stream, Size: 65 bytes --]