Discussion:
[PATCH v3 02/13] regcache: Add functions suitable for regset_supply/collect.
(too old to reply)
Andreas Arnez
2014-07-31 10:52:35 UTC
Permalink
Raw Message
These functions are intended to suit all targets that don't require too
special logic in their regset supply/collect methods. Having such
generic functions helps reducing target-specific complexity.

gdb/
* regcache.c: Include "regset.h".
(regcache_transfer_regset): New local function.
(regcache_supply_regset, regcache_collect_regset): New functions.
* regcache.h (struct regcache_map_entry): New structure.
(REGCACHE_MAP_SKIP): New enum value.
(regcache_supply_regset, regcache_collect_regset): New prototypes.
---
gdb/regcache.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
gdb/regcache.h | 45 ++++++++++++++++++++++++++++++
2 files changed, 132 insertions(+)

diff --git a/gdb/regcache.c b/gdb/regcache.c
index 5ee90b0..d5f8e2f 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -30,6 +30,7 @@
#include "exceptions.h"
#include "remote.h"
#include "valprint.h"
+#include "regset.h"

/*
* DATA STRUCTURE
@@ -1068,6 +1069,92 @@ regcache_raw_collect (const struct regcache *regcache, int regnum, void *buf)
memcpy (buf, regbuf, size);
}

+/* Transfer a single or all registers belonging to a certain register
+ set to or from a buffer. This is the main worker function for
+ regcache_supply_regset and regcache_collect_regset. */
+
+static void
+regcache_transfer_regset (const struct regset *regset,
+ const struct regcache *regcache,
+ struct regcache *out_regcache,
+ int regnum, const void *in_buf,
+ void *out_buf, size_t size)
+{
+ const struct regcache_map_entry *map;
+ int offs = 0, count;
+
+ for (map = regset->regmap; (count = map->count) != 0; map++)
+ {
+ int regno = map->regno;
+ int slot_size = map->size;
+
+ if (slot_size == 0 && regno != REGCACHE_MAP_SKIP)
+ slot_size = regcache->descr->sizeof_register[regno];
+
+ if (regno == REGCACHE_MAP_SKIP
+ || (regnum != -1
+ && (regnum < regno || regnum >= regno + count)))
+ offs += count * slot_size;
+
+ else if (regnum == -1)
+ for (; count--; regno++, offs += slot_size)
+ {
+ if (offs + slot_size > size)
+ break;
+
+ if (out_buf)
+ regcache_raw_collect (regcache, regno,
+ (gdb_byte *) out_buf + offs);
+ else
+ regcache_raw_supply (out_regcache, regno, in_buf
+ ? (const gdb_byte *) in_buf + offs
+ : NULL);
+ }
+ else
+ {
+ /* Transfer a single register and return. */
+ offs += (regnum - regno) * slot_size;
+ if (offs + slot_size > size)
+ return;
+
+ if (out_buf)
+ regcache_raw_collect (regcache, regnum,
+ (gdb_byte *) out_buf + offs);
+ else
+ regcache_raw_supply (out_regcache, regnum, in_buf
+ ? (const gdb_byte *) in_buf + offs
+ : NULL);
+ return;
+ }
+ }
+}
+
+/* Supply register REGNUM from BUF to REGCACHE, using the register map
+ in REGSET. If REGNUM is -1, do this for all registers in REGSET.
+ If BUF is NULL, set the register(s) to "unavailable" status. */
+
+void
+regcache_supply_regset (const struct regset *regset,
+ struct regcache *regcache,
+ int regnum, const void *buf, size_t size)
+{
+ regcache_transfer_regset (regset, regcache, regcache, regnum,
+ buf, NULL, size);
+}
+
+/* Collect register REGNUM from REGCACHE to BUF, using the register
+ map in REGSET. If REGNUM is -1, do this for all registers in
+ REGSET. */
+
+void
+regcache_collect_regset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *buf, size_t size)
+{
+ regcache_transfer_regset (regset, regcache, NULL, regnum,
+ NULL, buf, size);
+}
+

/* Special handling for register PC. */

diff --git a/gdb/regcache.h b/gdb/regcache.h
index 8423f57..0361f22 100644
--- a/gdb/regcache.h
+++ b/gdb/regcache.h
@@ -147,6 +147,51 @@ extern void regcache_raw_supply (struct regcache *regcache,
extern void regcache_raw_collect (const struct regcache *regcache,
int regnum, void *buf);

+/* Mapping between register numbers and offsets in a buffer, for use
+ in the '*regset' functions below. In an array of
+ 'regcache_map_entry' each element is interpreted like follows:
+
+ - If 'regno' is a register number: Map register 'regno' to the
+ current offset (starting with 0) and increase the current offset
+ by 'size' (or the register's size, if 'size' is zero). Repeat
+ this with consecutive register numbers up to 'regno+count-1'.
+
+ - If 'regno' is REGCACHE_MAP_SKIP: Add 'count*size' to the current
+ offset.
+
+ - If count=0: End of the map. */
+
+struct regcache_map_entry
+{
+ int count;
+ int regno;
+ int size;
+};
+
+/* Special value for the 'regno' field in the struct above. */
+
+enum
+ {
+ REGCACHE_MAP_SKIP = -1,
+ };
+
+/* Transfer a set of registers (as described by REGSET) between
+ REGCACHE and BUF. If REGNUM == -1, transfer all registers
+ belonging to the regset, otherwise just the register numbered
+ REGNUM. The REGSET's 'regmap' field must point to an array of
+ 'struct regcache_map_entry'.
+
+ These functions are suitable for the 'regset_supply' and
+ 'regset_collect' fields in a regset structure. */
+
+extern void regcache_supply_regset (const struct regset *regset,
+ struct regcache *regcache,
+ int regnum, const void *buf,
+ size_t size);
+extern void regcache_collect_regset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *buf, size_t size);
+

/* The type of a register. This function is slightly more efficient
then its gdbarch vector counterpart since it returns a precomputed
--
1.8.4.2
Andreas Arnez
2014-07-31 10:52:34 UTC
Permalink
Raw Message
The regset structure's 'descr' field is intended to represent some
kind of "register map". Thus, before making more use of it, this
change renames it to 'regmap' and adjusts the comment appropriately.

(See: https://sourceware.org/ml/gdb-patches/2014-05/msg00664.html)

gdb/
* regset.h (struct regset): Rename 'descr' field to 'regmap'.
* ppc-linux-tdep.c (ppc_linux_supply_gregset)
(ppc_linux_collect_gregset ): Likewise.
* rs6000-tdep.c (ppc_supply_gregset, ppc_supply_fpregset)
(ppc_supply_vrregset, ppc_collect_gregset, ppc_collect_fpregset)
(ppc_collect_vrregset): Likewise.
* s390-linux-tdep.c (s390_supply_regset, s390_collect_regset):
Likewise.
---
gdb/ppc-linux-tdep.c | 4 ++--
gdb/regset.h | 7 ++++---
gdb/rs6000-tdep.c | 12 ++++++------
gdb/s390-linux-tdep.c | 4 ++--
4 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 6e46765..316b254 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -395,7 +395,7 @@ ppc_linux_supply_gregset (const struct regset *regset,
struct regcache *regcache,
int regnum, const void *gregs, size_t len)
{
- const struct ppc_reg_offsets *offsets = regset->descr;
+ const struct ppc_reg_offsets *offsets = regset->regmap;

ppc_supply_gregset (regset, regcache, regnum, gregs, len);

@@ -420,7 +420,7 @@ ppc_linux_collect_gregset (const struct regset *regset,
const struct regcache *regcache,
int regnum, void *gregs, size_t len)
{
- const struct ppc_reg_offsets *offsets = regset->descr;
+ const struct ppc_reg_offsets *offsets = regset->regmap;

/* Clear areas in the linux gregset not written elsewhere. */
if (regnum == -1)
diff --git a/gdb/regset.h b/gdb/regset.h
index 03dbdaa..37ed99a 100644
--- a/gdb/regset.h
+++ b/gdb/regset.h
@@ -41,9 +41,10 @@ typedef void (collect_regset_ftype) (const struct regset *,

struct regset
{
- /* Data pointer for private use by the methods below, presumably
- providing some sort of description of the register set. */
- const void *descr;
+ /* Pointer to a "register map", for private use by the methods
+ below. Typically describes how the regset's registers are
+ arranged in the buffer collected to or supplied from. */
+ const void *regmap;

/* Function supplying values in a register set to a register cache. */
supply_regset_ftype *supply_regset;
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index c4ce51c..85919e4 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -506,7 +506,7 @@ ppc_supply_gregset (const struct regset *regset, struct regcache *regcache,
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- const struct ppc_reg_offsets *offsets = regset->descr;
+ const struct ppc_reg_offsets *offsets = regset->regmap;
size_t offset;
int regsize;

@@ -558,7 +558,7 @@ ppc_supply_fpregset (const struct regset *regset, struct regcache *regcache,
return;

tdep = gdbarch_tdep (gdbarch);
- offsets = regset->descr;
+ offsets = regset->regmap;
if (regnum == -1)
{
int i;
@@ -626,7 +626,7 @@ ppc_supply_vrregset (const struct regset *regset, struct regcache *regcache,
return;

tdep = gdbarch_tdep (gdbarch);
- offsets = regset->descr;
+ offsets = regset->regmap;
if (regnum == -1)
{
int i;
@@ -665,7 +665,7 @@ ppc_collect_gregset (const struct regset *regset,
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- const struct ppc_reg_offsets *offsets = regset->descr;
+ const struct ppc_reg_offsets *offsets = regset->regmap;
size_t offset;
int regsize;

@@ -719,7 +719,7 @@ ppc_collect_fpregset (const struct regset *regset,
return;

tdep = gdbarch_tdep (gdbarch);
- offsets = regset->descr;
+ offsets = regset->regmap;
if (regnum == -1)
{
int i;
@@ -792,7 +792,7 @@ ppc_collect_vrregset (const struct regset *regset,
return;

tdep = gdbarch_tdep (gdbarch);
- offsets = regset->descr;
+ offsets = regset->regmap;
if (regnum == -1)
{
int i;
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index ea743b5..3658033 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -610,7 +610,7 @@ s390_supply_regset (const struct regset *regset, struct regcache *regcache,
int regnum, const void *regs, size_t len)
{
const short *map;
- for (map = regset->descr; map[0] >= 0; map += 2)
+ for (map = regset->regmap; map[0] >= 0; map += 2)
if (regnum == -1 || regnum == map[1])
regcache_raw_supply (regcache, map[1],
regs ? (const char *)regs + map[0] : NULL);
@@ -643,7 +643,7 @@ s390_collect_regset (const struct regset *regset,
int regnum, void *regs, size_t len)
{
const short *map;
- for (map = regset->descr; map[0] >= 0; map += 2)
+ for (map = regset->regmap; map[0] >= 0; map += 2)
if (regnum == -1 || regnum == map[1])
regcache_raw_collect (regcache, map[1], (char *)regs + map[0]);
}
--
1.8.4.2
Andreas Arnez
2014-07-31 10:52:39 UTC
Permalink
Raw Message
gdb/
* frv-linux-tdep.c (FRV_PT_PSR, FRV_PT_ISR, FRV_PT_CCR)
(FRV_PT_CCCR, FRV_PT_LR, FRV_PT_LCR, FRV_PT_PC, FRV_PT_GNER0)
(FRV_PT_GNER1, FRV_PT_IACC0H, FRV_PT_IACC0L, FRV_PT_GR)
(FRV_PT_TBR, FRV_PT_GR, FRV_PT_EXEC_FDPIC_LOADMAP)
(FRV_PT_INTERP_FDPIC_LOADMAP): Delete macros.
(frv_linux_gregmap, frv_linux_fpregmap): New register maps.
(frv_linux_supply_gregset): Replace main logic by call to
regcache_supply_regset, but keep clearing gr32-gr63.
(frv_linux_supply_fpregset): Delete function.
(frv_linux_gregset): Refer to appropriate register map and add
regcache_collect_regset as the collect method.
(frv_linux_fpregset): Likewise. Also exchange the supply method
by regcache_supply_regset.
---
gdb/frv-linux-tdep.c | 141 ++++++++++++++++++++-------------------------------
1 file changed, 54 insertions(+), 87 deletions(-)

diff --git a/gdb/frv-linux-tdep.c b/gdb/frv-linux-tdep.c
index fb163a8..dba6db9 100644
--- a/gdb/frv-linux-tdep.c
+++ b/gdb/frv-linux-tdep.c
@@ -360,37 +360,52 @@ typedef struct
frv_elf_fpreg_t fsr[1];
} frv_elf_fpregset_t;

-/* Constants for accessing elements of frv_elf_gregset_t. */
-
-#define FRV_PT_PSR 0
-#define FRV_PT_ISR 1
-#define FRV_PT_CCR 2
-#define FRV_PT_CCCR 3
-#define FRV_PT_LR 4
-#define FRV_PT_LCR 5
-#define FRV_PT_PC 6
-#define FRV_PT_GNER0 10
-#define FRV_PT_GNER1 11
-#define FRV_PT_IACC0H 12
-#define FRV_PT_IACC0L 13
-
-/* Note: Only 32 of the GRs will be found in the corefile. */
-#define FRV_PT_GR(j) ( 14 + (j)) /* GRj for 0<=j<=63. */
-
-#define FRV_PT_TBR FRV_PT_GR(0) /* gr0 is always 0, so TBR is stuffed
- there. */
-
-/* Technically, the loadmap addresses are not part of `pr_reg' as
- found in the elf_prstatus struct. The fields which communicate the
- loadmap address appear (by design) immediately after `pr_reg'
- though, and the BFD function elf32_frv_grok_prstatus() has been
- implemented to include these fields in the register section that it
- extracts from the core file. So, for our purposes, they may be
- viewed as registers. */
-
-#define FRV_PT_EXEC_FDPIC_LOADMAP 46
-#define FRV_PT_INTERP_FDPIC_LOADMAP 47
-
+/* Register maps. */
+
+static const struct regcache_map_entry frv_linux_gregmap[] =
+ {
+ { 1, psr_regnum, 4 },
+ { 1, REGCACHE_MAP_SKIP, 4 }, /* isr */
+ { 1, ccr_regnum, 4 },
+ { 1, cccr_regnum, 4 },
+ { 1, lr_regnum, 4 },
+ { 1, lcr_regnum, 4 },
+ { 1, pc_regnum, 4 },
+ { 1, REGCACHE_MAP_SKIP, 4 }, /* __status */
+ { 1, REGCACHE_MAP_SKIP, 4 }, /* syscallno */
+ { 1, REGCACHE_MAP_SKIP, 4 }, /* orig_gr8 */
+ { 1, gner0_regnum, 4 },
+ { 1, gner1_regnum, 4 },
+ { 1, REGCACHE_MAP_SKIP, 8 }, /* iacc0 */
+ { 1, tbr_regnum, 4 },
+ { 31, first_gpr_regnum + 1, 4 }, /* gr1 ... gr31 */
+
+ /* Technically, the loadmap addresses are not part of `pr_reg' as
+ found in the elf_prstatus struct. The fields which communicate
+ the loadmap address appear (by design) immediately after
+ `pr_reg' though, and the BFD function elf32_frv_grok_prstatus()
+ has been implemented to include these fields in the register
+ section that it extracts from the core file. So, for our
+ purposes, they may be viewed as registers. */
+
+ { 1, fdpic_loadmap_exec_regnum, 4 },
+ { 1, fdpic_loadmap_interp_regnum, 4 },
+ { 0 }
+ };
+
+static const struct regcache_map_entry frv_linux_fpregmap[] =
+ {
+ { 64, first_fpr_regnum, 4 }, /* fr0 ... fr63 */
+ { 1, fner0_regnum, 4 },
+ { 1, fner1_regnum, 4 },
+ { 1, msr0_regnum, 4 },
+ { 1, msr1_regnum, 4 },
+ { 8, acc0_regnum, 4 }, /* acc0 ... acc7 */
+ { 1, accg0123_regnum, 4 },
+ { 1, accg4567_regnum, 4 },
+ { 1, fsr0_regnum, 4 },
+ { 0 }
+ };

/* Unpack an frv_elf_gregset_t into GDB's register cache. */

@@ -401,7 +416,6 @@ frv_linux_supply_gregset (const struct regset *regset,
{
int regi;
char zerobuf[MAX_REGISTER_SIZE];
- const frv_elf_gregset_t *gregsetp = gregs;

memset (zerobuf, 0, MAX_REGISTER_SIZE);

@@ -409,72 +423,25 @@ frv_linux_supply_gregset (const struct regset *regset,
this slot. */
regcache_raw_supply (regcache, first_gpr_regnum, zerobuf);

- for (regi = first_gpr_regnum + 1; regi <= last_gpr_regnum; regi++)
- {
- if (regi >= first_gpr_regnum + 32)
- regcache_raw_supply (regcache, regi, zerobuf);
- else
- regcache_raw_supply (regcache, regi,
- gregsetp->reg[FRV_PT_GR (regi
- - first_gpr_regnum)]);
- }
-
- regcache_raw_supply (regcache, pc_regnum, gregsetp->reg[FRV_PT_PC]);
- regcache_raw_supply (regcache, psr_regnum, gregsetp->reg[FRV_PT_PSR]);
- regcache_raw_supply (regcache, ccr_regnum, gregsetp->reg[FRV_PT_CCR]);
- regcache_raw_supply (regcache, cccr_regnum, gregsetp->reg[FRV_PT_CCCR]);
- regcache_raw_supply (regcache, lr_regnum, gregsetp->reg[FRV_PT_LR]);
- regcache_raw_supply (regcache, lcr_regnum, gregsetp->reg[FRV_PT_LCR]);
- regcache_raw_supply (regcache, gner0_regnum, gregsetp->reg[FRV_PT_GNER0]);
- regcache_raw_supply (regcache, gner1_regnum, gregsetp->reg[FRV_PT_GNER1]);
- regcache_raw_supply (regcache, tbr_regnum, gregsetp->reg[FRV_PT_TBR]);
- regcache_raw_supply (regcache, fdpic_loadmap_exec_regnum,
- gregsetp->reg[FRV_PT_EXEC_FDPIC_LOADMAP]);
- regcache_raw_supply (regcache, fdpic_loadmap_interp_regnum,
- gregsetp->reg[FRV_PT_INTERP_FDPIC_LOADMAP]);
-}
-
-/* Unpack an frv_elf_fpregset_t into GDB's register cache. */
-
-static void
-frv_linux_supply_fpregset (const struct regset *regset,
- struct regcache *regcache,
- int regnum, const void *gregs, size_t len)
-{
- int regi;
- const frv_elf_fpregset_t *fpregsetp = gregs;
-
- for (regi = first_fpr_regnum; regi <= last_fpr_regnum; regi++)
- regcache_raw_supply (regcache, regi,
- fpregsetp->fr[regi - first_fpr_regnum]);
-
- regcache_raw_supply (regcache, fner0_regnum, fpregsetp->fner[0]);
- regcache_raw_supply (regcache, fner1_regnum, fpregsetp->fner[1]);
-
- regcache_raw_supply (regcache, msr0_regnum, fpregsetp->msr[0]);
- regcache_raw_supply (regcache, msr1_regnum, fpregsetp->msr[1]);
+ /* Fill gr32, ..., gr63 with zeros. */
+ for (regi = first_gpr_regnum + 32; regi <= last_gpr_regnum; regi++)
+ regcache_raw_supply (regcache, regi, zerobuf);

- for (regi = acc0_regnum; regi <= acc7_regnum; regi++)
- regcache_raw_supply (regcache, regi, fpregsetp->acc[regi - acc0_regnum]);
-
- regcache_raw_supply (regcache, accg0123_regnum, fpregsetp->accg);
- regcache_raw_supply (regcache, accg4567_regnum, fpregsetp->accg + 4);
-
- regcache_raw_supply (regcache, fsr0_regnum, fpregsetp->fsr[0]);
+ regcache_supply_regset (regset, regcache, regnum, gregs, len);
}

/* FRV Linux kernel register sets. */

static const struct regset frv_linux_gregset =
{
- NULL,
- frv_linux_supply_gregset
+ frv_linux_gregmap,
+ frv_linux_supply_gregset, regcache_collect_regset
};

static const struct regset frv_linux_fpregset =
{
- NULL,
- frv_linux_supply_fpregset
+ frv_linux_fpregmap,
+ regcache_supply_regset, regcache_collect_regset
};

static const struct regset *
--
1.8.4.2
Andreas Arnez
2014-07-31 10:52:38 UTC
Permalink
Raw Message
gdb/
* alpha-linux-tdep.c (alpha_linux_supply_gregset): Replace logic
by call to alpha_supply_int_regs.
(alpha_linux_collect_gregset): New function.
(alpha_linux_supply_fpregset): Replace logic by call to
alpha_supply_fp_regs.
(alpha_linux_collect_fpregset): New function.
(alpha_linux_gregset, alpha_linux_fpregset): Add collect method.
---
gdb/alpha-linux-tdep.c | 56 +++++++++++++++++++++++++++++++-------------------
1 file changed, 35 insertions(+), 21 deletions(-)

diff --git a/gdb/alpha-linux-tdep.c b/gdb/alpha-linux-tdep.c
index 52f19d0..51bce4f 100644
--- a/gdb/alpha-linux-tdep.c
+++ b/gdb/alpha-linux-tdep.c
@@ -166,21 +166,27 @@ alpha_linux_supply_gregset (const struct regset *regset,
int regnum, const void *gregs, size_t len)
{
const gdb_byte *regs = gregs;
- int i;
+
gdb_assert (len >= 32 * 8);
+ alpha_supply_int_regs (regcache, regnum, regs, regs + 31 * 8,
+ len >= 33 * 8 ? regs + 32 * 8 : NULL);
+}

- for (i = 0; i < ALPHA_ZERO_REGNUM; i++)
- {
- if (regnum == i || regnum == -1)
- regcache_raw_supply (regcache, i, regs + i * 8);
- }
+/* Collect register REGNUM from the register cache REGCACHE and store
+ it in the buffer specified by GREGS and LEN as described by the
+ general-purpose register set REGSET. If REGNUM is -1, do this for
+ all registers in REGSET. */

- if (regnum == ALPHA_PC_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, ALPHA_PC_REGNUM, regs + 31 * 8);
+static void
+alpha_linux_collect_gregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *gregs, size_t len)
+{
+ gdb_byte *regs = gregs;

- if (regnum == ALPHA_UNIQUE_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, ALPHA_UNIQUE_REGNUM,
- len >= 33 * 8 ? regs + 32 * 8 : NULL);
+ gdb_assert (len >= 32 * 8);
+ alpha_fill_int_regs (regcache, regnum, regs, regs + 31 * 8,
+ len >= 33 * 8 ? regs + 32 * 8 : NULL);
}

/* Supply register REGNUM from the buffer specified by FPREGS and LEN
@@ -193,29 +199,37 @@ alpha_linux_supply_fpregset (const struct regset *regset,
int regnum, const void *fpregs, size_t len)
{
const gdb_byte *regs = fpregs;
- int i;
+
gdb_assert (len >= 32 * 8);
+ alpha_supply_fp_regs (regcache, regnum, regs, regs + 31 * 8);
+}

- for (i = ALPHA_FP0_REGNUM; i < ALPHA_FP0_REGNUM + 31; i++)
- {
- if (regnum == i || regnum == -1)
- regcache_raw_supply (regcache, i, regs + (i - ALPHA_FP0_REGNUM) * 8);
- }
+/* Collect register REGNUM from the register cache REGCACHE and store
+ it in the buffer specified by FPREGS and LEN as described by the
+ general-purpose register set REGSET. If REGNUM is -1, do this for
+ all registers in REGSET. */

- if (regnum == ALPHA_FPCR_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, ALPHA_FPCR_REGNUM, regs + 31 * 8);
+static void
+alpha_linux_collect_fpregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *fpregs, size_t len)
+{
+ gdb_byte *regs = fpregs;
+
+ gdb_assert (len >= 32 * 8);
+ alpha_fill_fp_regs (regcache, regnum, regs, regs + 31 * 8);
}

static const struct regset alpha_linux_gregset =
{
NULL,
- alpha_linux_supply_gregset
+ alpha_linux_supply_gregset, alpha_linux_collect_gregset
};

static const struct regset alpha_linux_fpregset =
{
NULL,
- alpha_linux_supply_fpregset
+ alpha_linux_supply_fpregset, alpha_linux_collect_fpregset
};

/* Return the appropriate register set for the core section identified
--
1.8.4.2
Andreas Arnez
2014-07-31 10:52:41 UTC
Permalink
Raw Message
gdb/
* m32r-linux-tdep.c (m32r_linux_supply_gregset): Make
platform-independent and don't write to read-only input buffer.
(m32r_linux_collect_gregset): New function.
(m32r_linux_gregset): Add collect method.
---
gdb/m32r-linux-tdep.c | 79 +++++++++++++++++++++++++++++++++++++++------------
1 file changed, 61 insertions(+), 18 deletions(-)

diff --git a/gdb/m32r-linux-tdep.c b/gdb/m32r-linux-tdep.c
index bf1ffff..8cbf2f5 100644
--- a/gdb/m32r-linux-tdep.c
+++ b/gdb/m32r-linux-tdep.c
@@ -351,14 +351,19 @@ m32r_linux_supply_gregset (const struct regset *regset,
struct regcache *regcache, int regnum,
const void *gregs, size_t size)
{
- const char *regs = gregs;
- unsigned long psw, bbpsw;
+ const gdb_byte *regs = gregs;
+ enum bfd_endian byte_order =
+ gdbarch_byte_order (get_regcache_arch (regcache));
+ ULONGEST psw, bbpsw;
+ gdb_byte buf[4];
+ const gdb_byte *p;
int i;

- psw = *((unsigned long *) (regs + PSW_OFFSET));
- bbpsw = *((unsigned long *) (regs + BBPSW_OFFSET));
+ psw = extract_unsigned_integer (regs + PSW_OFFSET, 4, byte_order);
+ bbpsw = extract_unsigned_integer (regs + BBPSW_OFFSET, 4, byte_order);
+ psw = ((0x00c1 & bbpsw) << 8) | ((0xc100 & psw) >> 8);

- for (i = 0; i < sizeof (m32r_pt_regs_offset) / 4; i++)
+ for (i = 0; i < ARRAY_SIZE (m32r_pt_regs_offset); i++)
{
if (regnum != -1 && regnum != i)
continue;
@@ -366,30 +371,68 @@ m32r_linux_supply_gregset (const struct regset *regset,
switch (i)
{
case PSW_REGNUM:
- *((unsigned long *) (regs + m32r_pt_regs_offset[i])) =
- ((0x00c1 & bbpsw) << 8) | ((0xc100 & psw) >> 8);
+ store_unsigned_integer (buf, 4, byte_order, psw);
+ p = buf;
break;
case CBR_REGNUM:
- *((unsigned long *) (regs + m32r_pt_regs_offset[i])) =
- ((psw >> 8) & 1);
+ store_unsigned_integer (buf, 4, byte_order, psw & 1);
+ p = buf;
break;
case M32R_SP_REGNUM:
- if (psw & 0x8000)
- *((unsigned long *) (regs + m32r_pt_regs_offset[i])) =
- *((unsigned long *) (regs + SPU_OFFSET));
- else
- *((unsigned long *) (regs + m32r_pt_regs_offset[i])) =
- *((unsigned long *) (regs + SPI_OFFSET));
+ p = regs + ((psw & 0x80) ? SPU_OFFSET : SPI_OFFSET);
break;
+ default:
+ p = regs + m32r_pt_regs_offset[i];
}

- regcache_raw_supply (regcache, i,
- regs + m32r_pt_regs_offset[i]);
+ regcache_raw_supply (regcache, i, p);
+ }
+}
+
+static void
+m32r_linux_collect_gregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *gregs, size_t size)
+{
+ gdb_byte *regs = gregs;
+ int i;
+ enum bfd_endian byte_order =
+ gdbarch_byte_order (get_regcache_arch (regcache));
+ ULONGEST psw;
+ gdb_byte buf[4];
+
+ regcache_raw_collect (regcache, PSW_REGNUM, buf);
+ psw = extract_unsigned_integer (buf, 4, byte_order);
+
+ for (i = 0; i < ARRAY_SIZE (m32r_pt_regs_offset); i++)
+ {
+ if (regnum != -1 && regnum != i)
+ continue;
+
+ switch (i)
+ {
+ case PSW_REGNUM:
+ store_unsigned_integer (regs + PSW_OFFSET, 4, byte_order,
+ (psw & 0xc1) << 8);
+ store_unsigned_integer (regs + BBPSW_OFFSET, 4, byte_order,
+ (psw >> 8) & 0xc1);
+ break;
+ case CBR_REGNUM:
+ break;
+ case M32R_SP_REGNUM:
+ regcache_raw_collect (regcache, i, regs
+ + ((psw & 0x80) ? SPU_OFFSET : SPI_OFFSET));
+ break;
+ default:
+ regcache_raw_collect (regcache, i,
+ regs + m32r_pt_regs_offset[i]);
+ }
}
}

static const struct regset m32r_linux_gregset = {
- NULL, m32r_linux_supply_gregset
+ NULL,
+ m32r_linux_supply_gregset, m32r_linux_collect_gregset
};

static const struct regset *
--
1.8.4.2
Andreas Arnez
2014-07-31 10:52:36 UTC
Permalink
Raw Message
Rather than supplying own supply/collect functions, use the generic
functions regcache_supply_regset and regcache_collect_regset instead.
The register maps are rewritten accordingly and become much shorter
(and better readable) than before.

gdb/
* s390-linux-nat.c: Include "regset.h".
(regmap_gregset): Delete macro.
(s390_64_regmap_gregset): New register map for
regcache_supply/_collect_regset.
(s390_64_gregset): New regset.
(S390_PSWM_OFFSET, S390_PSWA_OFFSET): New macros.
(regmap_fpregset): Delete macro.
(s390_native_supply, s390_native_collect): Delete functions.
(supply_gregset, fill_gregset): Replace s390-specific regmap
handling by a call to regcache_supply/_collect_regset.
(supply_fpregset, fill_fpregset): Call regcache_supply/
_collect_regset instead of s390_native_supply/_collect.
(fetch_regset, store_regset): Likewise. Also change the last
parameter to a regset instead of a regmap.
(s390_linux_fetch_inferior_registers)
(390_linux_store_inferior_registers): Adjust last parameter in
calls to fetch_regset and store_regset.
* s390-linux-tdep.c (s390_regmap_gregset): Rename to...
(s390_gregmap): ... this. Also make static const and convert to
regcache_map_entry format.
(s390x_regmap_gregset): Delete.
(s390_regmap_fpregset): Rename to...
(s390_fpregmap): ... this. Make static const and convert to
regcache_map_entry format.
(s390_regmap_upper, s390_regmap_last_break)
(s390x_regmap_last_break, s390_regmap_system_call)
(s390_regmap_tdb): Likewise.
(s390_supply_regset, s390_collect_regset): Remove functions.
(s390_supply_tdb_regset): Call regcache_supply_regset instead of
s390_supply_regset.
(s390_gregset, s390_fpregset, s390_upper_regset)
(s390_last_break_regset, s390x_last_break_regset)
(s390_system_call_regset, s390_tdb_regset): Make global and
replace s390_supply/_collect_regset by regcache_supply/
_collect_regset.
(s390x_gregset): Delete.
(s390_gdbarch_init): Replace s390x_gregset by s390_gregset.
* s390-linux-tdep.h (s390_regmap_gregset, s390x_regmap_gregset)
(s390_regmap_fpregset, s390_regmap_last_break)
(s390x_regmap_last_break, s390_regmap_system_call)
(s390_regmap_tdb): Delete global variable declarations.
(s390_gregset, s390_fpregset, s390_last_break_regset)
(s390x_last_break_regset, s390_system_call_regset)
(s390_tdb_regset): New global variable declarations.
---
gdb/s390-linux-nat.c | 177 ++++++++++++++------------------
gdb/s390-linux-tdep.c | 279 +++++++++++---------------------------------------
gdb/s390-linux-tdep.h | 13 ++-
3 files changed, 141 insertions(+), 328 deletions(-)

diff --git a/gdb/s390-linux-nat.c b/gdb/s390-linux-nat.c
index 45db7c9..755cadb 100644
--- a/gdb/s390-linux-nat.c
+++ b/gdb/s390-linux-nat.c
@@ -26,6 +26,7 @@
#include "linux-nat.h"
#include "auxv.h"
#include "gregset.h"
+#include "regset.h"

#include "s390-linux-tdep.h"
#include "elf/common.h"
@@ -49,42 +50,46 @@ static int have_regset_last_break = 0;
static int have_regset_system_call = 0;
static int have_regset_tdb = 0;

-/* Map registers to gregset/ptrace offsets.
- These arrays are defined in s390-tdep.c. */
+/* Register map for 32-bit executables running under a 64-bit
+ kernel. */

#ifdef __s390x__
-#define regmap_gregset s390x_regmap_gregset
-#else
-#define regmap_gregset s390_regmap_gregset
+static const struct regcache_map_entry s390_64_regmap_gregset[] =
+ {
+ /* Skip PSWM and PSWA, since they must be handled specially. */
+ { 2, REGCACHE_MAP_SKIP, 8 },
+ { 1, S390_R0_UPPER_REGNUM, 4 }, { 1, S390_R0_REGNUM, 4 },
+ { 1, S390_R1_UPPER_REGNUM, 4 }, { 1, S390_R1_REGNUM, 4 },
+ { 1, S390_R2_UPPER_REGNUM, 4 }, { 1, S390_R2_REGNUM, 4 },
+ { 1, S390_R3_UPPER_REGNUM, 4 }, { 1, S390_R3_REGNUM, 4 },
+ { 1, S390_R4_UPPER_REGNUM, 4 }, { 1, S390_R4_REGNUM, 4 },
+ { 1, S390_R5_UPPER_REGNUM, 4 }, { 1, S390_R5_REGNUM, 4 },
+ { 1, S390_R6_UPPER_REGNUM, 4 }, { 1, S390_R6_REGNUM, 4 },
+ { 1, S390_R7_UPPER_REGNUM, 4 }, { 1, S390_R7_REGNUM, 4 },
+ { 1, S390_R8_UPPER_REGNUM, 4 }, { 1, S390_R8_REGNUM, 4 },
+ { 1, S390_R9_UPPER_REGNUM, 4 }, { 1, S390_R9_REGNUM, 4 },
+ { 1, S390_R10_UPPER_REGNUM, 4 }, { 1, S390_R10_REGNUM, 4 },
+ { 1, S390_R11_UPPER_REGNUM, 4 }, { 1, S390_R11_REGNUM, 4 },
+ { 1, S390_R12_UPPER_REGNUM, 4 }, { 1, S390_R12_REGNUM, 4 },
+ { 1, S390_R13_UPPER_REGNUM, 4 }, { 1, S390_R13_REGNUM, 4 },
+ { 1, S390_R14_UPPER_REGNUM, 4 }, { 1, S390_R14_REGNUM, 4 },
+ { 1, S390_R15_UPPER_REGNUM, 4 }, { 1, S390_R15_REGNUM, 4 },
+ { 16, S390_A0_REGNUM, 4 },
+ { 1, REGCACHE_MAP_SKIP, 4 }, { 1, S390_ORIG_R2_REGNUM, 4 },
+ { 0 }
+ };
+
+static const struct regset s390_64_gregset =
+ {
+ s390_64_regmap_gregset,
+ regcache_supply_regset,
+ regcache_collect_regset
+ };
+
+#define S390_PSWM_OFFSET 0
+#define S390_PSWA_OFFSET 8
#endif

-#define regmap_fpregset s390_regmap_fpregset
-
-/* Fill the regset described by MAP into REGCACHE, using the values
- from REGP. The MAP array represents each register as a pair
- (offset, regno) of short integers and is terminated with -1. */
-
-static void
-s390_native_supply (struct regcache *regcache, const short *map,
- const gdb_byte *regp)
-{
- for (; map[0] >= 0; map += 2)
- regcache_raw_supply (regcache, map[1], regp ? regp + map[0] : NULL);
-}
-
-/* Collect the register REGNO out of the regset described by MAP from
- REGCACHE into REGP. If REGNO == -1, do this for all registers in
- this regset. */
-
-static void
-s390_native_collect (const struct regcache *regcache, const short *map,
- int regno, gdb_byte *regp)
-{
- for (; map[0] >= 0; map += 2)
- if (regno == -1 || regno == map[1])
- regcache_raw_collect (regcache, map[1], regp + map[0]);
-}
-
/* Fill GDB's register array with the general-purpose register values
in *REGP.

@@ -100,28 +105,15 @@ supply_gregset (struct regcache *regcache, const gregset_t *regp)
if (gdbarch_ptr_bit (gdbarch) == 32)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- ULONGEST pswm = 0, pswa = 0;
+ ULONGEST pswm, pswa;
gdb_byte buf[4];
- const short *map;
-
- for (map = regmap_gregset; map[0] >= 0; map += 2)
- {
- const gdb_byte *p = (const gdb_byte *) regp + map[0];
- int regno = map[1];
-
- if (regno == S390_PSWM_REGNUM)
- pswm = extract_unsigned_integer (p, 8, byte_order);
- else if (regno == S390_PSWA_REGNUM)
- pswa = extract_unsigned_integer (p, 8, byte_order);
- else
- {
- if ((regno >= S390_R0_REGNUM && regno <= S390_R15_REGNUM)
- || regno == S390_ORIG_R2_REGNUM)
- p += 4;
- regcache_raw_supply (regcache, regno, p);
- }
- }

+ regcache_supply_regset (&s390_64_gregset, regcache, -1,
+ regp, sizeof (gregset_t));
+ pswm = extract_unsigned_integer ((const gdb_byte *) regp
+ + S390_PSWM_OFFSET, 8, byte_order);
+ pswa = extract_unsigned_integer ((const gdb_byte *) regp
+ + S390_PSWA_OFFSET, 8, byte_order);
store_unsigned_integer (buf, 4, byte_order, (pswm >> 32) | 0x80000);
regcache_raw_supply (regcache, S390_PSWM_REGNUM, buf);
store_unsigned_integer (buf, 4, byte_order,
@@ -131,7 +123,8 @@ supply_gregset (struct regcache *regcache, const gregset_t *regp)
}
#endif

- s390_native_supply (regcache, regmap_gregset, (const gdb_byte *) regp);
+ regcache_supply_regset (&s390_gregset, regcache, -1, regp,
+ sizeof (gregset_t));
}

/* Fill register REGNO (if it is a general-purpose register) in
@@ -145,28 +138,8 @@ fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
struct gdbarch *gdbarch = get_regcache_arch (regcache);
if (gdbarch_ptr_bit (gdbarch) == 32)
{
- gdb_byte *psw_p[2];
- const short *map;
-
- for (map = regmap_gregset; map[0] >= 0; map += 2)
- {
- gdb_byte *p = (gdb_byte *) regp + map[0];
- int reg = map[1];
-
- if (reg >= S390_PSWM_REGNUM && reg <= S390_PSWA_REGNUM)
- psw_p[reg - S390_PSWM_REGNUM] = p;
-
- else if (regno == -1 || regno == reg)
- {
- if ((reg >= S390_R0_REGNUM && reg <= S390_R15_REGNUM)
- || reg == S390_ORIG_R2_REGNUM)
- {
- memset (p, 0, 4);
- p += 4;
- }
- regcache_raw_collect (regcache, reg, p);
- }
- }
+ regcache_collect_regset (&s390_64_gregset, regcache, regno,
+ regp, sizeof (gregset_t));

if (regno == -1
|| regno == S390_PSWM_REGNUM || regno == S390_PSWA_REGNUM)
@@ -181,18 +154,19 @@ fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
pswa = extract_unsigned_integer (buf, 4, byte_order);

if (regno == -1 || regno == S390_PSWM_REGNUM)
- store_unsigned_integer (psw_p[0], 8, byte_order,
- ((pswm & 0xfff7ffff) << 32) |
+ store_unsigned_integer ((gdb_byte *) regp + S390_PSWM_OFFSET, 8,
+ byte_order, ((pswm & 0xfff7ffff) << 32) |
(pswa & 0x80000000));
if (regno == -1 || regno == S390_PSWA_REGNUM)
- store_unsigned_integer (psw_p[1], 8, byte_order,
- pswa & 0x7fffffff);
+ store_unsigned_integer ((gdb_byte *) regp + S390_PSWA_OFFSET, 8,
+ byte_order, pswa & 0x7fffffff);
}
return;
}
#endif

- s390_native_collect (regcache, regmap_gregset, regno, (gdb_byte *) regp);
+ regcache_collect_regset (&s390_gregset, regcache, regno, regp,
+ sizeof (gregset_t));
}

/* Fill GDB's register array with the floating-point register values
@@ -200,7 +174,8 @@ fill_gregset (const struct regcache *regcache, gregset_t *regp, int regno)
void
supply_fpregset (struct regcache *regcache, const fpregset_t *regp)
{
- s390_native_supply (regcache, regmap_fpregset, (const gdb_byte *) regp);
+ regcache_supply_regset (&s390_fpregset, regcache, -1, regp,
+ sizeof (fpregset_t));
}

/* Fill register REGNO (if it is a general-purpose register) in
@@ -209,7 +184,8 @@ supply_fpregset (struct regcache *regcache, const fpregset_t *regp)
void
fill_fpregset (const struct regcache *regcache, fpregset_t *regp, int regno)
{
- s390_native_collect (regcache, regmap_fpregset, regno, (gdb_byte *) regp);
+ regcache_collect_regset (&s390_fpregset, regcache, regno, regp,
+ sizeof (fpregset_t));
}

/* Find the TID for the current inferior thread to use with ptrace. */
@@ -298,12 +274,13 @@ store_fpregs (const struct regcache *regcache, int tid, int regnum)
perror_with_name (_("Couldn't write floating point status"));
}

-/* Fetch all registers in the kernel's register set whose number is REGSET,
- whose size is REGSIZE, and whose layout is described by REGMAP, from
- process/thread TID and store their values in GDB's register cache. */
+/* Fetch all registers in the kernel's register set whose number is
+ REGSET_ID, whose size is REGSIZE, and whose layout is described by
+ REGSET, from process/thread TID and store their values in GDB's
+ register cache. */
static void
fetch_regset (struct regcache *regcache, int tid,
- int regset, int regsize, const short *regmap)
+ int regset_id, int regsize, const struct regset *regset)
{
gdb_byte *buf = alloca (regsize);
struct iovec iov;
@@ -311,23 +288,23 @@ fetch_regset (struct regcache *regcache, int tid,
iov.iov_base = buf;
iov.iov_len = regsize;

- if (ptrace (PTRACE_GETREGSET, tid, (long) regset, (long) &iov) < 0)
+ if (ptrace (PTRACE_GETREGSET, tid, (long) regset_id, (long) &iov) < 0)
{
if (errno == ENODATA)
- s390_native_supply (regcache, regmap, NULL);
+ regcache_supply_regset (regset, regcache, -1, NULL, regsize);
else
perror_with_name (_("Couldn't get register set"));
}
else
- s390_native_supply (regcache, regmap, buf);
+ regcache_supply_regset (regset, regcache, -1, buf, regsize);
}

-/* Store all registers in the kernel's register set whose number is REGSET,
- whose size is REGSIZE, and whose layout is described by REGMAP, from
- GDB's register cache back to process/thread TID. */
+/* Store all registers in the kernel's register set whose number is
+ REGSET_ID, whose size is REGSIZE, and whose layout is described by
+ REGSET, from GDB's register cache back to process/thread TID. */
static void
store_regset (struct regcache *regcache, int tid,
- int regset, int regsize, const short *regmap)
+ int regset_id, int regsize, const struct regset *regset)
{
gdb_byte *buf = alloca (regsize);
struct iovec iov;
@@ -335,12 +312,12 @@ store_regset (struct regcache *regcache, int tid,
iov.iov_base = buf;
iov.iov_len = regsize;

- if (ptrace (PTRACE_GETREGSET, tid, (long) regset, (long) &iov) < 0)
+ if (ptrace (PTRACE_GETREGSET, tid, (long) regset_id, (long) &iov) < 0)
perror_with_name (_("Couldn't get register set"));

- s390_native_collect (regcache, regmap, -1, buf);
+ regcache_collect_regset (regset, regcache, -1, buf, regsize);

- if (ptrace (PTRACE_SETREGSET, tid, (long) regset, (long) &iov) < 0)
+ if (ptrace (PTRACE_SETREGSET, tid, (long) regset_id, (long) &iov) < 0)
perror_with_name (_("Couldn't set register set"));
}

@@ -379,17 +356,17 @@ s390_linux_fetch_inferior_registers (struct target_ops *ops,
if (regnum == -1 || regnum == S390_LAST_BREAK_REGNUM)
fetch_regset (regcache, tid, NT_S390_LAST_BREAK, 8,
(gdbarch_ptr_bit (get_regcache_arch (regcache)) == 32
- ? s390_regmap_last_break : s390x_regmap_last_break));
+ ? &s390_last_break_regset : &s390x_last_break_regset));

if (have_regset_system_call)
if (regnum == -1 || regnum == S390_SYSTEM_CALL_REGNUM)
fetch_regset (regcache, tid, NT_S390_SYSTEM_CALL, 4,
- s390_regmap_system_call);
+ &s390_system_call_regset);

if (have_regset_tdb)
if (regnum == -1 || S390_IS_TDBREGSET_REGNUM (regnum))
fetch_regset (regcache, tid, NT_S390_TDB, s390_sizeof_tdbregset,
- s390_regmap_tdb);
+ &s390_tdb_regset);
}

/* Store register REGNUM back into the child process. If REGNUM is
@@ -411,7 +388,7 @@ s390_linux_store_inferior_registers (struct target_ops *ops,
if (have_regset_system_call)
if (regnum == -1 || regnum == S390_SYSTEM_CALL_REGNUM)
store_regset (regcache, tid, NT_S390_SYSTEM_CALL, 4,
- s390_regmap_system_call);
+ &s390_system_call_regset);
}


diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index 3658033..1399bb2 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -420,204 +420,62 @@ s390_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,

/* Maps for register sets. */

-const short s390_regmap_gregset[] =
+static const struct regcache_map_entry s390_gregmap[] =
{
- 0x00, S390_PSWM_REGNUM,
- 0x04, S390_PSWA_REGNUM,
- 0x08, S390_R0_REGNUM,
- 0x0c, S390_R1_REGNUM,
- 0x10, S390_R2_REGNUM,
- 0x14, S390_R3_REGNUM,
- 0x18, S390_R4_REGNUM,
- 0x1c, S390_R5_REGNUM,
- 0x20, S390_R6_REGNUM,
- 0x24, S390_R7_REGNUM,
- 0x28, S390_R8_REGNUM,
- 0x2c, S390_R9_REGNUM,
- 0x30, S390_R10_REGNUM,
- 0x34, S390_R11_REGNUM,
- 0x38, S390_R12_REGNUM,
- 0x3c, S390_R13_REGNUM,
- 0x40, S390_R14_REGNUM,
- 0x44, S390_R15_REGNUM,
- 0x48, S390_A0_REGNUM,
- 0x4c, S390_A1_REGNUM,
- 0x50, S390_A2_REGNUM,
- 0x54, S390_A3_REGNUM,
- 0x58, S390_A4_REGNUM,
- 0x5c, S390_A5_REGNUM,
- 0x60, S390_A6_REGNUM,
- 0x64, S390_A7_REGNUM,
- 0x68, S390_A8_REGNUM,
- 0x6c, S390_A9_REGNUM,
- 0x70, S390_A10_REGNUM,
- 0x74, S390_A11_REGNUM,
- 0x78, S390_A12_REGNUM,
- 0x7c, S390_A13_REGNUM,
- 0x80, S390_A14_REGNUM,
- 0x84, S390_A15_REGNUM,
- 0x88, S390_ORIG_R2_REGNUM,
- -1, -1
+ { 1, S390_PSWM_REGNUM },
+ { 1, S390_PSWA_REGNUM },
+ { 16, S390_R0_REGNUM },
+ { 16, S390_A0_REGNUM },
+ { 1, S390_ORIG_R2_REGNUM },
+ { 0 }
};

-const short s390x_regmap_gregset[] =
+static const struct regcache_map_entry s390_fpregmap[] =
{
- 0x00, S390_PSWM_REGNUM,
- 0x08, S390_PSWA_REGNUM,
- 0x10, S390_R0_REGNUM,
- 0x18, S390_R1_REGNUM,
- 0x20, S390_R2_REGNUM,
- 0x28, S390_R3_REGNUM,
- 0x30, S390_R4_REGNUM,
- 0x38, S390_R5_REGNUM,
- 0x40, S390_R6_REGNUM,
- 0x48, S390_R7_REGNUM,
- 0x50, S390_R8_REGNUM,
- 0x58, S390_R9_REGNUM,
- 0x60, S390_R10_REGNUM,
- 0x68, S390_R11_REGNUM,
- 0x70, S390_R12_REGNUM,
- 0x78, S390_R13_REGNUM,
- 0x80, S390_R14_REGNUM,
- 0x88, S390_R15_REGNUM,
- 0x90, S390_A0_REGNUM,
- 0x94, S390_A1_REGNUM,
- 0x98, S390_A2_REGNUM,
- 0x9c, S390_A3_REGNUM,
- 0xa0, S390_A4_REGNUM,
- 0xa4, S390_A5_REGNUM,
- 0xa8, S390_A6_REGNUM,
- 0xac, S390_A7_REGNUM,
- 0xb0, S390_A8_REGNUM,
- 0xb4, S390_A9_REGNUM,
- 0xb8, S390_A10_REGNUM,
- 0xbc, S390_A11_REGNUM,
- 0xc0, S390_A12_REGNUM,
- 0xc4, S390_A13_REGNUM,
- 0xc8, S390_A14_REGNUM,
- 0xcc, S390_A15_REGNUM,
- 0x10, S390_R0_UPPER_REGNUM,
- 0x18, S390_R1_UPPER_REGNUM,
- 0x20, S390_R2_UPPER_REGNUM,
- 0x28, S390_R3_UPPER_REGNUM,
- 0x30, S390_R4_UPPER_REGNUM,
- 0x38, S390_R5_UPPER_REGNUM,
- 0x40, S390_R6_UPPER_REGNUM,
- 0x48, S390_R7_UPPER_REGNUM,
- 0x50, S390_R8_UPPER_REGNUM,
- 0x58, S390_R9_UPPER_REGNUM,
- 0x60, S390_R10_UPPER_REGNUM,
- 0x68, S390_R11_UPPER_REGNUM,
- 0x70, S390_R12_UPPER_REGNUM,
- 0x78, S390_R13_UPPER_REGNUM,
- 0x80, S390_R14_UPPER_REGNUM,
- 0x88, S390_R15_UPPER_REGNUM,
- 0xd0, S390_ORIG_R2_REGNUM,
- -1, -1
+ { 1, S390_FPC_REGNUM, 8 },
+ { 16, S390_F0_REGNUM, 8 },
+ { 0 }
};

-const short s390_regmap_fpregset[] =
+static const struct regcache_map_entry s390_regmap_upper[] =
{
- 0x00, S390_FPC_REGNUM,
- 0x08, S390_F0_REGNUM,
- 0x10, S390_F1_REGNUM,
- 0x18, S390_F2_REGNUM,
- 0x20, S390_F3_REGNUM,
- 0x28, S390_F4_REGNUM,
- 0x30, S390_F5_REGNUM,
- 0x38, S390_F6_REGNUM,
- 0x40, S390_F7_REGNUM,
- 0x48, S390_F8_REGNUM,
- 0x50, S390_F9_REGNUM,
- 0x58, S390_F10_REGNUM,
- 0x60, S390_F11_REGNUM,
- 0x68, S390_F12_REGNUM,
- 0x70, S390_F13_REGNUM,
- 0x78, S390_F14_REGNUM,
- 0x80, S390_F15_REGNUM,
- -1, -1
+ { 16, S390_R0_UPPER_REGNUM, 4 },
+ { 0 }
};

-const short s390_regmap_upper[] =
+static const struct regcache_map_entry s390_regmap_last_break[] =
{
- 0x00, S390_R0_UPPER_REGNUM,
- 0x04, S390_R1_UPPER_REGNUM,
- 0x08, S390_R2_UPPER_REGNUM,
- 0x0c, S390_R3_UPPER_REGNUM,
- 0x10, S390_R4_UPPER_REGNUM,
- 0x14, S390_R5_UPPER_REGNUM,
- 0x18, S390_R6_UPPER_REGNUM,
- 0x1c, S390_R7_UPPER_REGNUM,
- 0x20, S390_R8_UPPER_REGNUM,
- 0x24, S390_R9_UPPER_REGNUM,
- 0x28, S390_R10_UPPER_REGNUM,
- 0x2c, S390_R11_UPPER_REGNUM,
- 0x30, S390_R12_UPPER_REGNUM,
- 0x34, S390_R13_UPPER_REGNUM,
- 0x38, S390_R14_UPPER_REGNUM,
- 0x3c, S390_R15_UPPER_REGNUM,
- -1, -1
+ { 1, REGCACHE_MAP_SKIP, 4 },
+ { 1, S390_LAST_BREAK_REGNUM, 4 },
+ { 0 }
};

-const short s390_regmap_last_break[] =
+static const struct regcache_map_entry s390x_regmap_last_break[] =
{
- 0x04, S390_LAST_BREAK_REGNUM,
- -1, -1
+ { 1, S390_LAST_BREAK_REGNUM, 8 },
+ { 0 }
};

-const short s390x_regmap_last_break[] =
+static const struct regcache_map_entry s390_regmap_system_call[] =
{
- 0x00, S390_LAST_BREAK_REGNUM,
- -1, -1
+ { 1, S390_SYSTEM_CALL_REGNUM, 4 },
+ { 0 }
};

-const short s390_regmap_system_call[] =
+static const struct regcache_map_entry s390_regmap_tdb[] =
{
- 0x00, S390_SYSTEM_CALL_REGNUM,
- -1, -1
+ { 1, S390_TDB_DWORD0_REGNUM, 8 },
+ { 1, S390_TDB_ABORT_CODE_REGNUM, 8 },
+ { 1, S390_TDB_CONFLICT_TOKEN_REGNUM, 8 },
+ { 1, S390_TDB_ATIA_REGNUM, 8 },
+ { 12, REGCACHE_MAP_SKIP, 8 },
+ { 16, S390_TDB_R0_REGNUM, 8 },
+ { 0 }
};

-const short s390_regmap_tdb[] =
- {
- 0x00, S390_TDB_DWORD0_REGNUM,
- 0x08, S390_TDB_ABORT_CODE_REGNUM,
- 0x10, S390_TDB_CONFLICT_TOKEN_REGNUM,
- 0x18, S390_TDB_ATIA_REGNUM,
- 0x80, S390_TDB_R0_REGNUM,
- 0x88, S390_TDB_R1_REGNUM,
- 0x90, S390_TDB_R2_REGNUM,
- 0x98, S390_TDB_R3_REGNUM,
- 0xa0, S390_TDB_R4_REGNUM,
- 0xa8, S390_TDB_R5_REGNUM,
- 0xb0, S390_TDB_R6_REGNUM,
- 0xb8, S390_TDB_R7_REGNUM,
- 0xc0, S390_TDB_R8_REGNUM,
- 0xc8, S390_TDB_R9_REGNUM,
- 0xd0, S390_TDB_R10_REGNUM,
- 0xd8, S390_TDB_R11_REGNUM,
- 0xe0, S390_TDB_R12_REGNUM,
- 0xe8, S390_TDB_R13_REGNUM,
- 0xf0, S390_TDB_R14_REGNUM,
- 0xf8, S390_TDB_R15_REGNUM,
- -1, -1
- };
-
-
-/* Supply register REGNUM from the register set REGSET to register cache
- REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
-static void
-s390_supply_regset (const struct regset *regset, struct regcache *regcache,
- int regnum, const void *regs, size_t len)
-{
- const short *map;
- for (map = regset->regmap; map[0] >= 0; map += 2)
- if (regnum == -1 || regnum == map[1])
- regcache_raw_supply (regcache, map[1],
- regs ? (const char *)regs + map[0] : NULL);
-}

-/* Supply the TDB regset. Like s390_supply_regset, but invalidate the
- TDB registers unless the TDB format field is valid. */
+/* Supply the TDB regset. Like regcache_supply_regset, but invalidate
+ the TDB registers unless the TDB format field is valid. */

static void
s390_supply_tdb_regset (const struct regset *regset, struct regcache *regcache,
@@ -627,73 +485,52 @@ s390_supply_tdb_regset (const struct regset *regset, struct regcache *regcache,
enum register_status ret;
int i;

- s390_supply_regset (regset, regcache, regnum, regs, len);
+ regcache_supply_regset (regset, regcache, regnum, regs, len);
ret = regcache_cooked_read_unsigned (regcache, S390_TDB_DWORD0_REGNUM, &tdw);
if (ret != REG_VALID || (tdw >> 56) != 1)
- s390_supply_regset (regset, regcache, regnum, NULL, len);
+ regcache_supply_regset (regset, regcache, regnum, NULL, len);
}

-/* Collect register REGNUM from the register cache REGCACHE and store
- it in the buffer specified by REGS and LEN as described by the
- general-purpose register set REGSET. If REGNUM is -1, do this for
- all registers in REGSET. */
-static void
-s390_collect_regset (const struct regset *regset,
- const struct regcache *regcache,
- int regnum, void *regs, size_t len)
-{
- const short *map;
- for (map = regset->regmap; map[0] >= 0; map += 2)
- if (regnum == -1 || regnum == map[1])
- regcache_raw_collect (regcache, map[1], (char *)regs + map[0]);
-}
-
-static const struct regset s390_gregset = {
- s390_regmap_gregset,
- s390_supply_regset,
- s390_collect_regset
+const struct regset s390_gregset = {
+ s390_gregmap,
+ regcache_supply_regset,
+ regcache_collect_regset
};

-static const struct regset s390x_gregset = {
- s390x_regmap_gregset,
- s390_supply_regset,
- s390_collect_regset
-};
-
-static const struct regset s390_fpregset = {
- s390_regmap_fpregset,
- s390_supply_regset,
- s390_collect_regset
+const struct regset s390_fpregset = {
+ s390_fpregmap,
+ regcache_supply_regset,
+ regcache_collect_regset
};

static const struct regset s390_upper_regset = {
s390_regmap_upper,
- s390_supply_regset,
- s390_collect_regset
+ regcache_supply_regset,
+ regcache_collect_regset
};

-static const struct regset s390_last_break_regset = {
+const struct regset s390_last_break_regset = {
s390_regmap_last_break,
- s390_supply_regset,
- s390_collect_regset
+ regcache_supply_regset,
+ regcache_collect_regset
};

-static const struct regset s390x_last_break_regset = {
+const struct regset s390x_last_break_regset = {
s390x_regmap_last_break,
- s390_supply_regset,
- s390_collect_regset
+ regcache_supply_regset,
+ regcache_collect_regset
};

-static const struct regset s390_system_call_regset = {
+const struct regset s390_system_call_regset = {
s390_regmap_system_call,
- s390_supply_regset,
- s390_collect_regset
+ regcache_supply_regset,
+ regcache_collect_regset
};

-static const struct regset s390_tdb_regset = {
+const struct regset s390_tdb_regset = {
s390_regmap_tdb,
s390_supply_tdb_regset,
- s390_collect_regset
+ regcache_collect_regset
};

static struct core_regset_section s390_linux32_regset_sections[] =
@@ -3371,7 +3208,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
break;

case ABI_LINUX_ZSERIES:
- tdep->gregset = &s390x_gregset;
+ tdep->gregset = &s390_gregset;
tdep->sizeof_gregset = s390x_sizeof_gregset;
tdep->fpregset = &s390_fpregset;
tdep->sizeof_fpregset = s390_sizeof_fpregset;
diff --git a/gdb/s390-linux-tdep.h b/gdb/s390-linux-tdep.h
index 52bed9d..1e12000 100644
--- a/gdb/s390-linux-tdep.h
+++ b/gdb/s390-linux-tdep.h
@@ -150,15 +150,14 @@

/* Core file register sets, defined in s390-tdep.c. */
#define s390_sizeof_gregset 0x90
-extern const short s390_regmap_gregset[];
#define s390x_sizeof_gregset 0xd8
-extern const short s390x_regmap_gregset[];
+extern const struct regset s390_gregset;
#define s390_sizeof_fpregset 0x88
-extern const short s390_regmap_fpregset[];
-extern const short s390_regmap_last_break[];
-extern const short s390x_regmap_last_break[];
-extern const short s390_regmap_system_call[];
-extern const short s390_regmap_tdb[];
+extern const struct regset s390_fpregset;
+extern const struct regset s390_last_break_regset;
+extern const struct regset s390x_last_break_regset;
+extern const struct regset s390_system_call_regset;
+extern const struct regset s390_tdb_regset;
#define s390_sizeof_tdbregset 0x100

/* GNU/Linux target descriptions. */
--
1.8.4.2
Andreas Arnez
2014-07-31 10:52:37 UTC
Permalink
Raw Message
In order to provide 'collect_regset' support, the generic function
regcache_collect_regset is exploited. Since this requires writing
appropriate register maps, these can be used for supply_regset as
well.

gdb/
* aarch64-linux-nat.c (fill_gregset, fill_fpregset): Replace logic
by call to regcache_collect_regset.
(supply_gregset, supply_fpregset): Call regcache_supply_regset
instead of aarch64_linux_supply_gregset/_fpregset.
* aarch64-linux-tdep.c (AARCH64_LINUX_SIZEOF_GREGSET)
(AARCH64_LINUX_SIZEOF_FPREGSET): Delete macros here, move to
header file instead.
(aarch64_linux_supply_gregset, supply_gregset_from_core)
(aarch64_linux_suply_fpregset, supply_fpregset_from_core): Delete
functions. Move logic to ...
(aarch64_linux_gregmap, aarch64_linux_fpregmap): ... these new
register maps.
(aarch64_linux_gregset, aarch64_linux_fpregset): Make global,
refer to new register maps, replace *_regset_from_core by
regcache_supply_regset, and also use regcache_collect_regset.
* aarch64-linux-tdep.h: Include "regset.h".
(aarch64_linux_supply_gregset, aarch64_linux_supply_fpregset):
Delete prototypes.
(AARCH64_LINUX_SIZEOF_GREGSET, AARCH64_LINUX_SIZEOF_FPREGSET): New
macros, moved from C source file.
(aarch64_linux_gregset, aarch64_linux_fpregset): New global
variable declarations.
---
gdb/aarch64-linux-nat.c | 38 +++++++-------------
gdb/aarch64-linux-tdep.c | 90 +++++++++++++-----------------------------------
gdb/aarch64-linux-tdep.h | 18 +++++++---
3 files changed, 48 insertions(+), 98 deletions(-)

diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 877e702..4ae789b 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -616,14 +616,9 @@ void
fill_gregset (const struct regcache *regcache,
gdb_gregset_t *gregsetp, int regno)
{
- gdb_byte *gregs_buf = (gdb_byte *) gregsetp;
- int i;
-
- for (i = AARCH64_X0_REGNUM; i <= AARCH64_CPSR_REGNUM; i++)
- if (regno == -1 || regno == i)
- regcache_raw_collect (regcache, i,
- gregs_buf + X_REGISTER_SIZE
- * (i - AARCH64_X0_REGNUM));
+ regcache_collect_regset (&aarch64_linux_gregset, regcache,
+ regno, (gdb_byte *) gregsetp,
+ AARCH64_LINUX_SIZEOF_GREGSET);
}

/* Fill GDB's register array with the general-purpose register values
@@ -632,7 +627,9 @@ fill_gregset (const struct regcache *regcache,
void
supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
{
- aarch64_linux_supply_gregset (regcache, (const gdb_byte *) gregsetp);
+ regcache_supply_regset (&aarch64_linux_gregset, regcache, -1,
+ (const gdb_byte *) gregsetp,
+ AARCH64_LINUX_SIZEOF_GREGSET);
}

/* Fill register REGNO (if it is a floating-point register) in
@@ -643,22 +640,9 @@ void
fill_fpregset (const struct regcache *regcache,
gdb_fpregset_t *fpregsetp, int regno)
{
- gdb_byte *fpregs_buf = (gdb_byte *) fpregsetp;
- int i;
-
- for (i = AARCH64_V0_REGNUM; i <= AARCH64_V31_REGNUM; i++)
- if (regno == -1 || regno == i)
- regcache_raw_collect (regcache, i,
- fpregs_buf + V_REGISTER_SIZE
- * (i - AARCH64_V0_REGNUM));
-
- if (regno == -1 || regno == AARCH64_FPSR_REGNUM)
- regcache_raw_collect (regcache, AARCH64_FPSR_REGNUM,
- fpregs_buf + V_REGISTER_SIZE * 32);
-
- if (regno == -1 || regno == AARCH64_FPCR_REGNUM)
- regcache_raw_collect (regcache, AARCH64_FPCR_REGNUM,
- fpregs_buf + V_REGISTER_SIZE * 32 + 4);
+ regcache_collect_regset (&aarch64_linux_fpregset, regcache,
+ regno, (gdb_byte *) fpregsetp,
+ AARCH64_LINUX_SIZEOF_FPREGSET);
}

/* Fill GDB's register array with the floating-point register values
@@ -667,7 +651,9 @@ fill_fpregset (const struct regcache *regcache,
void
supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
{
- aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) fpregsetp);
+ regcache_supply_regset (&aarch64_linux_fpregset, regcache, -1,
+ (const gdb_byte *) fpregsetp,
+ AARCH64_LINUX_SIZEOF_FPREGSET);
}

/* Called when resuming a thread.
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 30ed73f..6377977 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -41,16 +41,6 @@
#include "user-regs.h"
#include <ctype.h>

-/* The general-purpose regset consists of 31 X registers, plus SP, PC,
- and PSTATE registers, as defined in the AArch64 port of the Linux
- kernel. */
-#define AARCH64_LINUX_SIZEOF_GREGSET (34 * X_REGISTER_SIZE)
-
-/* The fp regset consists of 32 V registers, plus FPCR and FPSR which
- are 4 bytes wide each, and the whole structure is padded to 128 bit
- alignment. */
-#define AARCH64_LINUX_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE)
-
/* Signal frame handling.

+------------+ ^
@@ -190,71 +180,37 @@ static const struct tramp_frame aarch64_linux_rt_sigframe =
aarch64_linux_sigframe_init
};

-/* Fill GDB's register array with the general-purpose register values
- in the buffer pointed by GREGS_BUF. */
-
-void
-aarch64_linux_supply_gregset (struct regcache *regcache,
- const gdb_byte *gregs_buf)
-{
- int regno;
-
- for (regno = AARCH64_X0_REGNUM; regno <= AARCH64_CPSR_REGNUM; regno++)
- regcache_raw_supply (regcache, regno,
- gregs_buf + X_REGISTER_SIZE
- * (regno - AARCH64_X0_REGNUM));
-}
-
-/* The "supply_regset" function for the general-purpose register set. */
-
-static void
-supply_gregset_from_core (const struct regset *regset,
- struct regcache *regcache,
- int regnum, const void *regbuf, size_t len)
-{
- aarch64_linux_supply_gregset (regcache, (const gdb_byte *) regbuf);
-}
-
-/* Fill GDB's register array with the floating-point register values
- in the buffer pointed by FPREGS_BUF. */
+/* Register maps. */

-void
-aarch64_linux_supply_fpregset (struct regcache *regcache,
- const gdb_byte *fpregs_buf)
-{
- int regno;
-
- for (regno = AARCH64_V0_REGNUM; regno <= AARCH64_V31_REGNUM; regno++)
- regcache_raw_supply (regcache, regno,
- fpregs_buf + V_REGISTER_SIZE
- * (regno - AARCH64_V0_REGNUM));
-
- regcache_raw_supply (regcache, AARCH64_FPSR_REGNUM,
- fpregs_buf + V_REGISTER_SIZE * 32);
- regcache_raw_supply (regcache, AARCH64_FPCR_REGNUM,
- fpregs_buf + V_REGISTER_SIZE * 32 + 4);
-}
-
-/* The "supply_regset" function for the floating-point register set. */
+static const struct regcache_map_entry aarch64_linux_gregmap[] =
+ {
+ { 31, AARCH64_X0_REGNUM, 8 }, /* x0 ... x30 */
+ { 1, AARCH64_SP_REGNUM, 8 },
+ { 1, AARCH64_PC_REGNUM, 8 },
+ { 1, AARCH64_CPSR_REGNUM, 8 },
+ { 0 }
+ };

-static void
-supply_fpregset_from_core (const struct regset *regset,
- struct regcache *regcache,
- int regnum, const void *regbuf, size_t len)
-{
- aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) regbuf);
-}
+static const struct regcache_map_entry aarch64_linux_fpregmap[] =
+ {
+ { 32, AARCH64_V0_REGNUM, 16 }, /* v0 ... v31 */
+ { 1, AARCH64_FPSR_REGNUM, 4 },
+ { 1, AARCH64_FPCR_REGNUM, 4 },
+ { 0 }
+ };

-/* Register set definitions. */
+/* Register set definitions. */

-static const struct regset aarch64_linux_gregset =
+const struct regset aarch64_linux_gregset =
{
- NULL, supply_gregset_from_core, NULL
+ aarch64_linux_gregmap,
+ regcache_supply_regset, regcache_collect_regset
};

-static const struct regset aarch64_linux_fpregset =
+const struct regset aarch64_linux_fpregset =
{
- NULL, supply_fpregset_from_core, NULL
+ aarch64_linux_fpregmap,
+ regcache_supply_regset, regcache_collect_regset
};

/* Implement the "regset_from_core_section" gdbarch method. */
diff --git a/gdb/aarch64-linux-tdep.h b/gdb/aarch64-linux-tdep.h
index 48c7092..2e1de60 100644
--- a/gdb/aarch64-linux-tdep.h
+++ b/gdb/aarch64-linux-tdep.h
@@ -18,9 +18,17 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */

-struct regcache;
+#include "regset.h"

-extern void aarch64_linux_supply_gregset (struct regcache *regcache,
- const gdb_byte *gregs_buf);
-extern void aarch64_linux_supply_fpregset (struct regcache *regcache,
- const gdb_byte *fpregs_buf);
+/* The general-purpose regset consists of 31 X registers, plus SP, PC,
+ and PSTATE registers, as defined in the AArch64 port of the Linux
+ kernel. */
+#define AARCH64_LINUX_SIZEOF_GREGSET (34 * X_REGISTER_SIZE)
+
+/* The fp regset consists of 32 V registers, plus FPCR and FPSR which
+ are 4 bytes wide each, and the whole structure is padded to 128 bit
+ alignment. */
+#define AARCH64_LINUX_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE)
+
+extern const struct regset aarch64_linux_gregset;
+extern const struct regset aarch64_linux_fpregset;
--
1.8.4.2
Andreas Arnez
2014-07-31 10:52:40 UTC
Permalink
Raw Message
gdb/
* hppa-linux-tdep.c (greg_map): Rename to...
(hppa_linux_gregmap): ... this. Also convert to
regcache_map_entry format.
(hppa_linux_supply_regset): Delete function.
(hppa_linux_supply_fpregset): Delete function. Move logic to...
(hppa_linux_fpregmap): ... this new register map.
(hppa_linux_regset, hppa_linux_fpregset): Refer to appropriate
register map, replace supply method by regcache_supply_regset, and
add collect method regcache_collect_regset.
---
gdb/hppa-linux-tdep.c | 103 ++++++++++++++++++--------------------------------
1 file changed, 36 insertions(+), 67 deletions(-)

diff --git a/gdb/hppa-linux-tdep.c b/gdb/hppa-linux-tdep.c
index 7a765a2..6bc604b 100644
--- a/gdb/hppa-linux-tdep.c
+++ b/gdb/hppa-linux-tdep.c
@@ -423,84 +423,53 @@ hppa_linux_find_global_pointer (struct gdbarch *gdbarch,
* cr10, cr15
*/

-#define GR_REGNUM(_n) (HPPA_R0_REGNUM+_n)
-#define TR_REGNUM(_n) (HPPA_TR0_REGNUM+_n)
-static const int greg_map[] =
+static const struct regcache_map_entry hppa_linux_gregmap[] =
{
- GR_REGNUM(0), GR_REGNUM(1), GR_REGNUM(2), GR_REGNUM(3),
- GR_REGNUM(4), GR_REGNUM(5), GR_REGNUM(6), GR_REGNUM(7),
- GR_REGNUM(8), GR_REGNUM(9), GR_REGNUM(10), GR_REGNUM(11),
- GR_REGNUM(12), GR_REGNUM(13), GR_REGNUM(14), GR_REGNUM(15),
- GR_REGNUM(16), GR_REGNUM(17), GR_REGNUM(18), GR_REGNUM(19),
- GR_REGNUM(20), GR_REGNUM(21), GR_REGNUM(22), GR_REGNUM(23),
- GR_REGNUM(24), GR_REGNUM(25), GR_REGNUM(26), GR_REGNUM(27),
- GR_REGNUM(28), GR_REGNUM(29), GR_REGNUM(30), GR_REGNUM(31),
-
- HPPA_SR4_REGNUM+1, HPPA_SR4_REGNUM+2, HPPA_SR4_REGNUM+3, HPPA_SR4_REGNUM+4,
- HPPA_SR4_REGNUM, HPPA_SR4_REGNUM+5, HPPA_SR4_REGNUM+6, HPPA_SR4_REGNUM+7,
-
- HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM,
- HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM,
-
- HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM,
- HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM,
-
- TR_REGNUM(0), TR_REGNUM(1), TR_REGNUM(2), TR_REGNUM(3),
- TR_REGNUM(4), TR_REGNUM(5), TR_REGNUM(6), TR_REGNUM(7),
-
- HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM,
- HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM,
+ { 32, HPPA_R0_REGNUM },
+ { 1, HPPA_SR4_REGNUM+1 },
+ { 1, HPPA_SR4_REGNUM+2 },
+ { 1, HPPA_SR4_REGNUM+3 },
+ { 1, HPPA_SR4_REGNUM+4 },
+ { 1, HPPA_SR4_REGNUM },
+ { 1, HPPA_SR4_REGNUM+5 },
+ { 1, HPPA_SR4_REGNUM+6 },
+ { 1, HPPA_SR4_REGNUM+7 },
+ { 1, HPPA_PCOQ_HEAD_REGNUM },
+ { 1, HPPA_PCOQ_TAIL_REGNUM },
+ { 1, HPPA_PCSQ_HEAD_REGNUM },
+ { 1, HPPA_PCSQ_TAIL_REGNUM },
+ { 1, HPPA_SAR_REGNUM },
+ { 1, HPPA_IIR_REGNUM },
+ { 1, HPPA_ISR_REGNUM },
+ { 1, HPPA_IOR_REGNUM },
+ { 1, HPPA_IPSW_REGNUM },
+ { 1, HPPA_RCR_REGNUM },
+ { 8, HPPA_TR0_REGNUM },
+ { 4, HPPA_PID0_REGNUM },
+ { 1, HPPA_CCR_REGNUM },
+ { 1, HPPA_EIEM_REGNUM },
+ { 0 }
};

-static void
-hppa_linux_supply_regset (const struct regset *regset,
- struct regcache *regcache,
- int regnum, const void *regs, size_t len)
-{
- struct gdbarch *arch = get_regcache_arch (regcache);
- struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
- const char *buf = regs;
- int i, offset;
-
- offset = 0;
- for (i = 0; i < ARRAY_SIZE (greg_map); i++)
- {
- if (regnum == greg_map[i] || regnum == -1)
- regcache_raw_supply (regcache, greg_map[i], buf + offset);
-
- offset += tdep->bytes_per_address;
- }
-}
-
-static void
-hppa_linux_supply_fpregset (const struct regset *regset,
- struct regcache *regcache,
- int regnum, const void *regs, size_t len)
-{
- const char *buf = regs;
- int i, offset;
-
- offset = 0;
- for (i = 0; i < 64; i++)
- {
- if (regnum == HPPA_FP0_REGNUM + i || regnum == -1)
- regcache_raw_supply (regcache, HPPA_FP0_REGNUM + i,
- buf + offset);
- offset += 4;
- }
-}
+static const struct regcache_map_entry hppa_linux_fpregmap[] =
+ {
+ /* FIXME: Only works for 32-bit mode. In 64-bit mode there should
+ be 32 fpregs, 8 bytes each. */
+ { 64, HPPA_FP0_REGNUM, 4 },
+ { 0 }
+ };

/* HPPA Linux kernel register set. */
static const struct regset hppa_linux_regset =
{
- NULL,
- hppa_linux_supply_regset
+ hppa_linux_gregmap,
+ regcache_supply_regset, regcache_collect_regset
};

static const struct regset hppa_linux_fpregset =
{
- NULL,
- hppa_linux_supply_fpregset
+ hppa_linux_fpregmap,
+ regcache_supply_regset, regcache_collect_regset
};

static const struct regset *
--
1.8.4.2
Andreas Arnez
2014-07-31 10:52:42 UTC
Permalink
Raw Message
gdb/
* nios2-linux-tdep.c (nios2_collect_gregset): New function.
(nios2_core_regset): Add collect method.
---
gdb/nios2-linux-tdep.c | 21 ++++++++++++++++++++-
1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/gdb/nios2-linux-tdep.c b/gdb/nios2-linux-tdep.c
index 84ab576..0f53477 100644
--- a/gdb/nios2-linux-tdep.c
+++ b/gdb/nios2-linux-tdep.c
@@ -73,11 +73,30 @@ nios2_supply_gregset (const struct regset *regset,
}
}

+/* Implement the collect_regset hook for core files. */
+
+static void
+nios2_collect_gregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *gregs_buf, size_t len)
+{
+ gdb_byte *gregs = gregs_buf;
+ int regno;
+
+ for (regno = NIOS2_Z_REGNUM; regno <= NIOS2_MPUACC_REGNUM; regno++)
+ if (regnum == -1 || regnum == regno)
+ {
+ if (reg_offsets[regno] != -1)
+ regcache_raw_collect (regcache, regno,
+ gregs + 4 * reg_offsets[regno]);
+ }
+}
+
static const struct regset nios2_core_regset =
{
NULL,
nios2_supply_gregset,
- NULL,
+ nios2_collect_gregset
};

/* Implement the regset_from_core_section gdbarch method. */
--
1.8.4.2
Andreas Arnez
2014-07-31 10:52:43 UTC
Permalink
Raw Message
Also rewrite the 'supply_regset' method, making it platform
independent. To avoid code duplication, move the logic for both to a
register map in regcache_map_entry format.

gdb/
* score-tdep.c (score7_linux_supply_gregset): Reduce to small stub
that calls regcache_supply_regset and handles the EPC register
separately. Move main logic to...
(score7_linux_gregmap): ... this new register map.
(SCORE7_LINUX_SIZEOF_GREGSET, SCORE7_LINUX_EPC_OFFSET): New macros.
(score7_linux_gregset): Refer to register map. Add collect method.
(score7_linux_regset_from_core_section): Replace
sizeof elf_gregset_t by SCORE7_LINUX_SIZEOF_GREGSET.
* score-tdep.h (enum gdb_regnum): New enum value SCORE_EPC_REGNUM.
(struct regset): Delete unused forward declaraction.
(struct pt_regs): Delete structure definition.
(elf_gregset_t): Delete typedef.
---
gdb/score-tdep.c | 86 ++++++++++++++++++++++++++------------------------------
gdb/score-tdep.h | 34 +---------------------
2 files changed, 41 insertions(+), 79 deletions(-)

diff --git a/gdb/score-tdep.c b/gdb/score-tdep.c
index c224189..77b8a8c 100644
--- a/gdb/score-tdep.c
+++ b/gdb/score-tdep.c
@@ -1398,59 +1398,52 @@ score_prologue_frame_base_sniffer (struct frame_info *this_frame)
return &score_prologue_frame_base;
}

-/* Core file support (dirty hack)
-
- The core file MUST be generated by GNU/Linux on S+core. */
+/* Core file support. */
+
+static const struct regcache_map_entry score7_linux_gregmap[] =
+ {
+ /* FIXME: According to the current Linux kernel, r0 is preceded by
+ 9 rather than 7 words. */
+ { 7, REGCACHE_MAP_SKIP, 4 },
+ { 32, 0, 4 }, /* r0 ... r31 */
+ { 1, 55, 4 }, /* CEL */
+ { 1, 54, 4 }, /* CEH */
+ { 1, 53, 4 }, /* sr0, i.e. cnt or COUNTER */
+ { 1, 52, 4 }, /* sr1, i.e. lcr or LDCR */
+ { 1, 51, 4 }, /* sr2, i.e. scr or STCR */
+ { 1, 49, 4 }, /* PC (same slot as EPC) */
+ { 1, 38, 4 }, /* EMA */
+ { 1, 32, 4 }, /* PSR */
+ { 1, 34, 4 }, /* ECR */
+ { 1, 33, 4 }, /* COND */
+ { 0 }
+ };
+
+#define SCORE7_LINUX_EPC_OFFSET (44 * 4)
+#define SCORE7_LINUX_SIZEOF_GREGSET (49 * 4)

static void
score7_linux_supply_gregset(const struct regset *regset,
- struct regcache *regcache,
- int regnum, const void *gregs_buf, size_t len)
+ struct regcache *regcache,
+ int regnum, const void *buf,
+ size_t size)
{
- int regno;
- elf_gregset_t *gregs;
-
- gdb_assert (regset != NULL);
- gdb_assert ((regcache != NULL) && (gregs_buf != NULL));
-
- gregs = (elf_gregset_t *) gregs_buf;
-
- for (regno = 0; regno < 32; regno++)
- if (regnum == -1 || regnum == regno)
- regcache_raw_supply (regcache, regno, gregs->regs + regno);
-
- {
- struct sreg {
- int regnum;
- void *buf;
- } sregs [] = {
- { 55, &(gregs->cel) }, /* CEL */
- { 54, &(gregs->ceh) }, /* CEH */
- { 53, &(gregs->sr0) }, /* sr0, i.e. cnt or COUNTER */
- { 52, &(gregs->sr1) }, /* sr1, i.e. lcr or LDCR */
- { 51, &(gregs->sr1) }, /* sr2, i.e. scr or STCR */
-
- /* Exception occured at this address, exactly the PC we want */
- { 49, &(gregs->cp0_epc) }, /* PC */
-
- { 38, &(gregs->cp0_ema) }, /* EMA */
- { 37, &(gregs->cp0_epc) }, /* EPC */
- { 34, &(gregs->cp0_ecr) }, /* ECR */
- { 33, &(gregs->cp0_condition) }, /* COND */
- { 32, &(gregs->cp0_psr) }, /* PSR */
- };
-
- for (regno = 0; regno < sizeof(sregs)/sizeof(sregs[0]); regno++)
- if (regnum == -1 || regnum == sregs[regno].regnum)
- regcache_raw_supply (regcache,
- sregs[regno].regnum, sregs[regno].buf);
- }
+ regcache_supply_regset (regset, regcache, regnum, buf, size);
+
+ /* Supply the EPC from the same slot as the PC. Note that the
+ collect function will store the PC in that slot. */
+ if ((regnum == -1 || regnum == SCORE_EPC_REGNUM)
+ && size >= SCORE7_LINUX_EPC_OFFSET + 4)
+ regcache_raw_supply (regcache, SCORE_EPC_REGNUM,
+ (const gdb_byte *) buf
+ + SCORE7_LINUX_EPC_OFFSET);
}

static const struct regset score7_linux_gregset =
{
- NULL,
- score7_linux_supply_gregset, NULL
+ score7_linux_gregmap,
+ score7_linux_supply_gregset,
+ regcache_collect_regset
};

/* Return the appropriate register set from the core section identified
@@ -1463,7 +1456,8 @@ score7_linux_regset_from_core_section(struct gdbarch *gdbarch,
gdb_assert (gdbarch != NULL);
gdb_assert (sect_name != NULL);

- if (strcmp(sect_name, ".reg") == 0 && sect_size == sizeof(elf_gregset_t))
+ if (strcmp(sect_name, ".reg") == 0
+ && sect_size == SCORE7_LINUX_SIZEOF_GREGSET)
return &score7_linux_gregset;

return NULL;
diff --git a/gdb/score-tdep.h b/gdb/score-tdep.h
index 02a334e..cef0e6a 100644
--- a/gdb/score-tdep.h
+++ b/gdb/score-tdep.h
@@ -32,6 +32,7 @@ enum gdb_regnum
SCORE_RA_REGNUM = 3,
SCORE_A0_REGNUM = 4,
SCORE_AL_REGNUM = 7,
+ SCORE_EPC_REGNUM = 37,
SCORE_PC_REGNUM = 49,
};

@@ -46,37 +47,4 @@ enum gdb_regnum
#define SCORE_INSTLEN 4
#define SCORE16_INSTLEN 2

-/* Forward declarations. */
-struct regset;
-
-/* Linux Core file support (dirty hack)
-
- S+core Linux register set definition, copy from S+core Linux. */
-struct pt_regs {
- /* Pad bytes for argument save space on the stack. */
- unsigned long pad0[6]; /* may be 4, MIPS accept 6var, SCore
- accepts 4 Var--yuchen */
-
- /* Saved main processor registers. */
- unsigned long orig_r4;
- unsigned long regs[32];
-
- /* Other saved registers. */
- unsigned long cel;
- unsigned long ceh;
-
- unsigned long sr0; /*cnt*/
- unsigned long sr1; /*lcr*/
- unsigned long sr2; /*scr*/
-
- /* saved cp0 registers */
- unsigned long cp0_epc;
- unsigned long cp0_ema;
- unsigned long cp0_psr;
- unsigned long cp0_ecr;
- unsigned long cp0_condition;
-};
-
-typedef struct pt_regs elf_gregset_t;
-
#endif /* SCORE_TDEP_H */
--
1.8.4.2
Andreas Arnez
2014-07-31 10:52:45 UTC
Permalink
Raw Message
gdb/
* m68klinux-tdep.c: Include "regset.h".
(m68k_linux_gregmap, m68k_linux_fpregmap): New register maps.
(M68K_LINUX_GREGS_SIZE, M68K_LINUX_FPREGS_SIZE): New macros.
(m68k_linux_gregset, m68k_linux_fpregset): New regsets.
(m68k_linux_regset_from_core_section): New function.
(m68k_linux_init_abi): Set regset_from_core_section gdbarch
method.
---
gdb/m68klinux-tdep.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)

diff --git a/gdb/m68klinux-tdep.c b/gdb/m68klinux-tdep.c
index f6fed38..d2c4bb0 100644
--- a/gdb/m68klinux-tdep.c
+++ b/gdb/m68klinux-tdep.c
@@ -38,6 +38,7 @@
#include "observer.h"
#include "elf/common.h"
#include "linux-tdep.h"
+#include "regset.h"

/* Offsets (in target ints) into jmp_buf. */

@@ -327,6 +328,67 @@ static const struct frame_unwind m68k_linux_sigtramp_frame_unwind =
m68k_linux_sigtramp_frame_sniffer
};

+/* Register maps for supply/collect regset functions. */
+
+static const struct regcache_map_entry m68k_linux_gregmap[] =
+ {
+ { 7, M68K_D1_REGNUM, 4 }, /* d1 ... d7 */
+ { 7, M68K_A0_REGNUM, 4 }, /* a0 ... a6 */
+ { 1, M68K_D0_REGNUM, 4 },
+ { 1, M68K_SP_REGNUM, 4 },
+ { 1, REGCACHE_MAP_SKIP, 4 }, /* orig_d0 (skip) */
+ { 1, M68K_PS_REGNUM, 4 },
+ { 1, M68K_PC_REGNUM, 4 },
+ /* Ignore 16-bit fields 'fmtvec' and '__fill'. */
+ { 0 }
+ };
+
+#define M68K_LINUX_GREGS_SIZE (20 * 4)
+
+static const struct regcache_map_entry m68k_linux_fpregmap[] =
+ {
+ { 8, M68K_FP0_REGNUM, 12 }, /* fp0 ... fp7 */
+ { 1, M68K_FPC_REGNUM, 4 },
+ { 1, M68K_FPS_REGNUM, 4 },
+ { 1, M68K_FPI_REGNUM, 4 },
+ { 0 }
+ };
+
+#define M68K_LINUX_FPREGS_SIZE (27 * 4)
+
+/* Register sets. */
+
+static const struct regset m68k_linux_gregset =
+ {
+ m68k_linux_gregmap,
+ regcache_supply_regset, regcache_collect_regset
+ };
+
+static const struct regset m68k_linux_fpregset =
+ {
+ m68k_linux_fpregmap,
+ regcache_supply_regset, regcache_collect_regset
+ };
+
+/* Return the appropriate register set for the core section identified
+ by SECT_NAME and SECT_SIZE. */
+
+static const struct regset *
+m68k_linux_regset_from_core_section (struct gdbarch *gdbarch,
+ const char *sect_name,
+ size_t sect_size)
+{
+ if (strcmp (sect_name, ".reg") == 0
+ && sect_size >= M68K_LINUX_GREGS_SIZE)
+ return &m68k_linux_gregset;
+
+ if (strcmp (sect_name, ".reg2") == 0
+ && sect_size >= M68K_LINUX_FPREGS_SIZE)
+ return &m68k_linux_fpregset;
+
+ return NULL;
+}
+
static void
m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
@@ -361,6 +423,10 @@ m68k_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)

set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);

+ /* Core file support. */
+ set_gdbarch_regset_from_core_section
+ (gdbarch, m68k_linux_regset_from_core_section);
+
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
--
1.8.4.2
Andreas Arnez
2014-07-31 10:52:44 UTC
Permalink
Raw Message
gdb/
* tilegx-linux-tdep.c (tilegx_linux_supply_regset): Delete
function. Move logic to...
(tilegx_linux_regmap): ... this new register map.
(tilegx_linux_regset): Refer to register map, replace supply
method by regcache_supply_regset, and add collect method.
* tilegx-tdep.h (enum tilegx_regnum): New enum value
TILEGX_FIRST_EASY_REGNUM.
---
gdb/tilegx-linux-tdep.c | 34 +++++++++++-----------------------
gdb/tilegx-tdep.h | 1 +
2 files changed, 12 insertions(+), 23 deletions(-)

diff --git a/gdb/tilegx-linux-tdep.c b/gdb/tilegx-linux-tdep.c
index 98b03db..184d00c 100644
--- a/gdb/tilegx-linux-tdep.c
+++ b/gdb/tilegx-linux-tdep.c
@@ -73,34 +73,22 @@ static const struct tramp_frame tilegx_linux_rt_sigframe =
tilegx_linux_sigframe_init
};

-/* Supply raw registers from REGCACHE to REGS. */
+/* Register map; must match struct pt_regs in "ptrace.h". */

-static void
-tilegx_linux_supply_regset (const struct regset *regset,
- struct regcache *regcache,
- int regnum, const void *regs, size_t len)
-{
- struct gdbarch *arch = get_regcache_arch (regcache);
- const char *ptr = regs;
- int i;
-
- /* This logic must match that of struct pt_regs in "ptrace.h". */
- for (i = 0; i < TILEGX_NUM_EASY_REGS + 2; i++, ptr += tilegx_reg_size)
- {
- int gri = (i < TILEGX_NUM_EASY_REGS)
- ? i : (i == TILEGX_NUM_EASY_REGS)
- ? TILEGX_PC_REGNUM : TILEGX_FAULTNUM_REGNUM;
-
- if (regnum == gri || regnum == -1)
- regcache_raw_supply (regcache, gri, ptr);
- }
-}
+static const struct regcache_map_entry tilegx_linux_regmap[] =
+ {
+ { TILEGX_NUM_EASY_REGS, TILEGX_FIRST_EASY_REGNUM, 8 },
+ { 1, TILEGX_PC_REGNUM, 8 },
+ { 1, TILEGX_FAULTNUM_REGNUM, 8 },
+ { 0 }
+ };

/* TILE-Gx Linux kernel register set. */
+
static const struct regset tilegx_linux_regset =
{
- NULL,
- tilegx_linux_supply_regset
+ tilegx_linux_regmap,
+ regcache_supply_regset, regcache_collect_regset
};

static const struct regset *
diff --git a/gdb/tilegx-tdep.h b/gdb/tilegx-tdep.h
index e24655c..864c798 100644
--- a/gdb/tilegx-tdep.h
+++ b/gdb/tilegx-tdep.h
@@ -31,6 +31,7 @@
enum tilegx_regnum
{
TILEGX_R0_REGNUM,
+ TILEGX_FIRST_EASY_REGNUM = TILEGX_R0_REGNUM,
TILEGX_R1_REGNUM,
TILEGX_R2_REGNUM,
TILEGX_R3_REGNUM,
--
1.8.4.2
Andreas Arnez
2014-07-31 10:52:46 UTC
Permalink
Raw Message
gdb/
* ia64-linux-tdep.c: Include "regset.h".
(ia64_linux_gregmap, ia64_linux_fpregmap): New register maps.
(IA64_LINUX_GREGS_SIZE, IA64_LINUX_FPREGS_SIZE): New macros.
(ia64_linux_supply_fpregset): New function.
(ia64_linux_gregset, ia64_linux_fpregset): New regsets.
(ia64_linux_regset_from_core_section): New function.
(ia64_linux_init_abi): Set regset_from_core_section gdbarch
method.
---
gdb/ia64-linux-tdep.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 90 insertions(+)

diff --git a/gdb/ia64-linux-tdep.c b/gdb/ia64-linux-tdep.c
index 128924e..3bdf2a1 100644
--- a/gdb/ia64-linux-tdep.c
+++ b/gdb/ia64-linux-tdep.c
@@ -26,6 +26,7 @@
#include "solib-svr4.h"
#include "symtab.h"
#include "linux-tdep.h"
+#include "regset.h"

#include <ctype.h>

@@ -131,6 +132,91 @@ ia64_linux_stap_is_single_operand (struct gdbarch *gdbarch, const char *s)
|| isdigit (*s)); /* Literal number. */
}

+/* Core file support. */
+
+static const struct regcache_map_entry ia64_linux_gregmap[] =
+ {
+ { 32, IA64_GR0_REGNUM, 8 }, /* r0 ... r31 */
+ { 1, REGCACHE_MAP_SKIP, 8 }, /* FIXME: NAT collection bits? */
+ { 1, IA64_PR_REGNUM, 8 },
+ { 8, IA64_BR0_REGNUM, 8 }, /* b0 ... b7 */
+ { 1, IA64_IP_REGNUM, 8 },
+ { 1, IA64_CFM_REGNUM, 8 },
+ { 1, IA64_PSR_REGNUM, 8 },
+ { 1, IA64_RSC_REGNUM, 8 },
+ { 1, IA64_BSP_REGNUM, 8 },
+ { 1, IA64_BSPSTORE_REGNUM, 8 },
+ { 1, IA64_RNAT_REGNUM, 8 },
+ { 1, IA64_CCV_REGNUM, 8 },
+ { 1, IA64_UNAT_REGNUM, 8 },
+ { 1, IA64_FPSR_REGNUM, 8 },
+ { 1, IA64_PFS_REGNUM, 8 },
+ { 1, IA64_LC_REGNUM, 8 },
+ { 1, IA64_EC_REGNUM, 8 },
+ { 0 }
+ };
+
+/* Size of 'gregset_t', as defined by the Linux kernel. Note that
+ this is more than actually mapped in the regmap above. */
+
+#define IA64_LINUX_GREGS_SIZE (128 * 8)
+
+static const struct regcache_map_entry ia64_linux_fpregmap[] =
+ {
+ { 128, IA64_FR0_REGNUM, 16 }, /* f0 ... f127 */
+ { 0 }
+ };
+
+#define IA64_LINUX_FPREGS_SIZE (128 * 16)
+
+static void
+ia64_linux_supply_fpregset (const struct regset *regset,
+ struct regcache *regcache,
+ int regnum, const void *regs, size_t len)
+{
+ const gdb_byte f_zero[16] = { 0 };
+ const gdb_byte f_one[16] =
+ { 0, 0, 0, 0, 0, 0, 0, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0 };
+
+ regcache_supply_regset (regset, regcache, regnum, regs, len);
+
+ /* Kernel generated cores have fr1==0 instead of 1.0. Older GDBs
+ did the same. So ignore whatever might be recorded in fpregset_t
+ for fr0/fr1 and always supply their expected values. */
+ if (regnum == -1 || regnum == IA64_FR0_REGNUM)
+ regcache_raw_supply (regcache, IA64_FR0_REGNUM, f_zero);
+ if (regnum == -1 || regnum == IA64_FR1_REGNUM)
+ regcache_raw_supply (regcache, IA64_FR1_REGNUM, f_one);
+}
+
+static const struct regset ia64_linux_gregset =
+ {
+ ia64_linux_gregmap,
+ regcache_supply_regset, regcache_collect_regset
+ };
+
+static const struct regset ia64_linux_fpregset =
+ {
+ ia64_linux_fpregmap,
+ ia64_linux_supply_fpregset, regcache_collect_regset
+ };
+
+static const struct regset *
+ia64_linux_regset_from_core_section (struct gdbarch *gdbarch,
+ const char *sect_name,
+ size_t sect_size)
+{
+ if (strcmp (sect_name, ".reg") == 0
+ && sect_size >= IA64_LINUX_GREGS_SIZE)
+ return &ia64_linux_gregset;
+
+ if (strcmp (sect_name, ".reg2") == 0
+ && sect_size >= IA64_LINUX_FPREGS_SIZE)
+ return &ia64_linux_fpregset;
+
+ return NULL;
+}
+
static void
ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
@@ -161,6 +247,10 @@ ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);

+ /* Core file support. */
+ set_gdbarch_regset_from_core_section (gdbarch,
+ ia64_linux_regset_from_core_section);
+
/* SystemTap related. */
set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes);
set_gdbarch_stap_register_indirection_prefixes (gdbarch,
--
1.8.4.2
Andreas Arnez
2014-07-31 11:13:31 UTC
Permalink
Raw Message
Oops, sorry, this shouldn't have gone here. Excuse the double-post.
See gdb-patches instead.

Loading...