[PATCH 2/7] Fixes for aarch64-linux gdb core file support

Omair Javaid
2014-06-04T16:21:37Z

This patch fixes aarch64 linux core file support by adding/updating
aarch64-linux supply/collect methods for aarch64 register set.

gdb:

2014-06-04 Omair Javaid <omair.javaid@linaro.org>

* aarch64-linux-tdep.c (aarch64_linux_supply_gregset): Updated.
(aarch64_linux_supply_fpregset): Updated.
(supply_gregset_from_core): Removed.
(aarch64_linux_collect_gregset): New function.
(supply_fpregset_from_core): Removed.
(aarch64_linux_collect_fpregset): New function.
(struct regset aarch64_linux_gregset): Updated.
(struct core_regset_section aarch64_linux_regset_sections[]): Declared.
* aarch64-linux-tdep.h (aarch64_linux_supply_gregset): Updated extern.
(aarch64_linux_supply_fpregset): New extern declaration.
(aarch64_linux_collect_gregset): New extern declaration.
(aarch64_linux_collect_fpregset): New extern declaration.
* aarch64-linux-nat.c (aarch64_linux_supply_gregset): Updated.
(aarch64_linux_supply_fpregset): Updated.

---
gdb/aarch64-linux-nat.c | 4 +--
gdb/aarch64-linux-tdep.c | 91 +++++++++++++++++++++++++++++++++---------------
gdb/aarch64-linux-tdep.h | 22 +++++++++---
3 files changed, 83 insertions(+), 34 deletions(-)

diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 877e702..f631d9e 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -632,7 +632,7 @@ 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);
+ aarch64_linux_supply_gregset (NULL, regcache, -1, gregsetp, 0);
}

/* Fill register REGNO (if it is a floating-point register) in
@@ -667,7 +667,7 @@ 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);
+ aarch64_linux_supply_fpregset (NULL, regcache, -1, fpregsetp, 0);
}

/* Called when resuming a thread.
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 30ed73f..b285818 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -191,70 +191,93 @@ static const struct tramp_frame aarch64_linux_rt_sigframe =
};

/* Fill GDB's register array with the general-purpose register values
- in the buffer pointed by GREGS_BUF. */
+ in the buffer pointed by gregs_buf. */

void
-aarch64_linux_supply_gregset (struct regcache *regcache,
- const gdb_byte *gregs_buf)
+aarch64_linux_supply_gregset (const struct regset *regset,
+ struct regcache *regcache, int regnum,
+ const void *gregs_buf, size_t len)
{
+ gdb_byte *gregs_bufp = (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
+ gregs_bufp + X_REGISTER_SIZE
* (regno - AARCH64_X0_REGNUM));
}

-/* The "supply_regset" function for the general-purpose register set. */
+/* Fill registers in *gregs_buf with the values in GDB's register cache. */

-static void
-supply_gregset_from_core (const struct regset *regset,
- struct regcache *regcache,
- int regnum, const void *regbuf, size_t len)
+void
+aarch64_linux_collect_gregset (const struct regset *regset,
+ const struct regcache *regcache, int regnum,
+ void *gregs_buf, size_t len)
{
- aarch64_linux_supply_gregset (regcache, (const gdb_byte *) regbuf);
+ gdb_byte *gregs_bufp = (gdb_byte *) gregs_buf;
+ int regno;
+
+ for (regno = AARCH64_X0_REGNUM; regno <= AARCH64_CPSR_REGNUM; regno++)
+ if (regnum == -1 || regnum == regno)
+ regcache_raw_collect (regcache, regno, gregs_bufp + X_REGISTER_SIZE *
+ (regno - AARCH64_X0_REGNUM));
}

/* Fill GDB's register array with the floating-point register values
- in the buffer pointed by FPREGS_BUF. */
+ in the buffer pointed by fpregs_buf. */

void
-aarch64_linux_supply_fpregset (struct regcache *regcache,
- const gdb_byte *fpregs_buf)
+aarch64_linux_supply_fpregset (const struct regset *regset,
+ struct regcache *regcache, int regnum,
+ const void *fpregs_buf, size_t len)
{
+ gdb_byte *fpregs_bufp = (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, regno, fpregs_bufp + 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);
+ regcache_raw_supply (regcache, AARCH64_FPSR_REGNUM, fpregs_bufp +
+ V_REGISTER_SIZE * 32);
+ regcache_raw_supply (regcache, AARCH64_FPCR_REGNUM, fpregs_bufp +
+ V_REGISTER_SIZE * 32 + 4);
}

-/* The "supply_regset" function for the floating-point register set. */
+/* Fill registers in *fpregs_buf with the values in GDB's register cache. */

-static void
-supply_fpregset_from_core (const struct regset *regset,
- struct regcache *regcache,
- int regnum, const void *regbuf, size_t len)
+void
+aarch64_linux_collect_fpregset (const struct regset *regset,
+ const struct regcache *regcache, int regnum,
+ void *fpregs_buf, size_t len)
{
- aarch64_linux_supply_fpregset (regcache, (const gdb_byte *) regbuf);
+ gdb_byte *fpregs_bufp = (gdb_byte *) fpregs_buf;
+ int regno;
+
+ for (regno = AARCH64_V0_REGNUM; regno <= AARCH64_V31_REGNUM; regno++)
+ if (regnum == -1 || regnum == regno)
+ regcache_raw_collect (regcache, regno, fpregs_bufp + V_REGISTER_SIZE *
+ (regno - AARCH64_V0_REGNUM));
+
+ if (regnum == -1 || regnum == AARCH64_FPSR_REGNUM)
+ regcache_raw_collect (regcache, AARCH64_FPSR_REGNUM, fpregs_bufp +
+ V_REGISTER_SIZE * 32);
+
+ if (regnum == -1 || regnum == AARCH64_FPCR_REGNUM)
+ regcache_raw_collect (regcache, AARCH64_FPCR_REGNUM, fpregs_bufp +
+ V_REGISTER_SIZE * 32 + 4);
}

/* Register set definitions. */

static const struct regset aarch64_linux_gregset =
{
- NULL, supply_gregset_from_core, NULL
+ NULL, aarch64_linux_supply_gregset, aarch64_linux_collect_gregset
};

static const struct regset aarch64_linux_fpregset =
{
- NULL, supply_fpregset_from_core, NULL
+ NULL, aarch64_linux_supply_fpregset, aarch64_linux_collect_fpregset
};

/* Implement the "regset_from_core_section" gdbarch method. */
@@ -275,6 +298,15 @@ aarch64_linux_regset_from_core_section (struct gdbarch *gdbarch,
return NULL;
}

+/* Core file register set sections. */
+
+static struct core_regset_section aarch64_linux_regset_sections[] =
+{
+ { ".reg", AARCH64_LINUX_SIZEOF_GREGSET, "general-purpose" },
+ { ".reg2", AARCH64_LINUX_SIZEOF_FPREGSET, "floating-point" },
+ { NULL, 0}
+};
+
/* Implementation of `gdbarch_stap_is_single_operand', as defined in
gdbarch.h. */

@@ -420,6 +452,9 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
/* Enable longjmp. */
tdep->jb_pc = 11;

+ /* Install supported register note sections. */
+ set_gdbarch_core_regset_sections (gdbarch, aarch64_linux_regset_sections);
+
set_gdbarch_regset_from_core_section (gdbarch,
aarch64_linux_regset_from_core_section);

diff --git a/gdb/aarch64-linux-tdep.h b/gdb/aarch64-linux-tdep.h
index 48c7092..e3d7ed7 100644
--- a/gdb/aarch64-linux-tdep.h
+++ b/gdb/aarch64-linux-tdep.h
@@ -20,7 +20,21 @@

struct regcache;

-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);
+/* Function prototypes for function transferring the general-purpose
+ registers between GDB, inferiors and core files. */
+
+/* Fill GDB's register array with the general-purpose register values
+ in *gregs_buf. */
+
+extern void aarch64_linux_supply_gregset (const struct regset *regset,
+ struct regcache *regcache, int regnum,
+ const void *gregs_buf, size_t len);
+extern void aarch64_linux_collect_gregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *gregs_buf, size_t len);
+extern void aarch64_linux_supply_fpregset (const struct regset *regset,
+ struct regcache *regcache, int regnum,
+ const void *fpregs_buf, size_t len);
+extern void aarch64_linux_collect_fpregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *fpregs_buf, size_t len);
--
1.9.1