This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH][SH] Implement core-file support for sh-linux
- From: Andrew Stubbs <ams at codesourcery dot com>
- To: Joel Brobecker <brobecker at adacore dot com>
- Cc: gdb-patches at sources dot redhat dot com
- Date: Thu, 15 Oct 2009 14:27:26 +0100
- Subject: Re: [PATCH][SH] Implement core-file support for sh-linux
- References: <4AD33C69.2070301@codesourcery.com> <20091014045558.GT5272@adacore.com>
On 14/10/09 05:55, Joel Brobecker wrote:
Then the code from shnbsd can be moved to sh-tdep.c and the only
remaining bit is to initialize the array appropriately in shbnsd-tdep
and sh-linux-tdep.
I believe this patch should do what you suggest.
I've tested the Linux support, but unfortunately I have now way to test
the NBSD support. I have checked that it builds, but that is all.
OK?
Andrew
2009-10-15 Andrew Stubbs <ams@codesourcery.com>
* configure.tgt (sh*-*-linux*): Add corelow.o to gdb_target_obs.
* sh-linux-tdep.c: Include gdb_string.h, regset.h and sh-tdep.h.
(REGSx16): New macro.
(gregs_table, fpregs_table): New variables.
(sh_linux_regset_from_core_section): New function.
(sh_linux_init_abi): Call set_gdbarch_regset_from_core_section.
* sh-tdep.c: Include regset.h.
(sh_corefile_supply_regset): New function.
(sh_corefile_collect_regset): New function.
(sh_corefile_gregset, sh_corefile_fpregset): New variables.
(sh_init_corefile_regset): New function.
* sh-tdep.h (PC_REGNUM): New enum value.
(struct sh_corefile_regs): New type.
(sh_init_corefile_regset): New prototype.
* shnbsd-tdep.c: Remove include of regcache.h.
(regmap): Use new definition using struct sh_corefile_regs.
(shnbsd_supply_gregset, shnbsd_collect_gregset): Delete.
(shnbsd_gregset): Delete.
(current_regset): New variable.
(shnbsd_regset_from_core_section): Use sh_init_corefile_regset.
(shnbsd_supply_reg, shnbsd_fill_reg): Use new regset interface.
---
src/gdb-mainline/gdb/configure.tgt | 3 -
src/gdb-mainline/gdb/sh-linux-tdep.c | 67 +++++++++++++++
src/gdb-mainline/gdb/sh-tdep.c | 79 ++++++++++++++++++
src/gdb-mainline/gdb/sh-tdep.h | 12 +++
src/gdb-mainline/gdb/shnbsd-tdep.c | 148 +++++++++-------------------------
5 files changed, 199 insertions(+), 110 deletions(-)
diff --git a/src/gdb-mainline/gdb/configure.tgt b/src/gdb-mainline/gdb/configure.tgt
index 20b739e..0d3074a 100644
--- a/src/gdb-mainline/gdb/configure.tgt
+++ b/src/gdb-mainline/gdb/configure.tgt
@@ -407,7 +407,8 @@ score-*-*)
sh*-*-linux*)
# Target: GNU/Linux Super-H
gdb_target_obs="sh-tdep.o sh64-tdep.o sh-linux-tdep.o monitor.o \
- dsrec.o solib.o solib-svr4.o symfile-mem.o glibc-tdep.o"
+ dsrec.o solib.o solib-svr4.o symfile-mem.o \
+ glibc-tdep.o corelow.o"
gdb_sim=../sim/sh/libsim.a
build_gdbserver=yes
;;
diff --git a/src/gdb-mainline/gdb/sh-linux-tdep.c b/src/gdb-mainline/gdb/sh-linux-tdep.c
index 46aad1d..cda968f 100644
--- a/src/gdb-mainline/gdb/sh-linux-tdep.c
+++ b/src/gdb-mainline/gdb/sh-linux-tdep.c
@@ -20,10 +20,72 @@
#include "defs.h"
#include "osabi.h"
+#include "gdb_string.h"
+
#include "solib-svr4.h"
#include "symtab.h"
+#include "regset.h"
#include "glibc-tdep.h"
+#include "sh-tdep.h"
+
+#define REGSx16(base) \
+ {(base), 0, 4}, \
+ {(base) + 1, 4, 4}, \
+ {(base) + 2, 8, 4}, \
+ {(base) + 3, 12, 4}, \
+ {(base) + 4, 16, 4}, \
+ {(base) + 5, 20, 4}, \
+ {(base) + 6, 24, 4}, \
+ {(base) + 7, 28, 4}, \
+ {(base) + 8, 32, 4}, \
+ {(base) + 9, 36, 4}, \
+ {(base) + 10, 40, 4}, \
+ {(base) + 11, 44, 4}, \
+ {(base) + 12, 48, 4}, \
+ {(base) + 13, 52, 4}, \
+ {(base) + 14, 56, 4}, \
+ {(base) + 15, 60, 4}
+
+/* Describe the contents of the .reg section of the core file. */
+
+static const struct sh_corefile_regs gregs_table[] =
+{
+ REGSx16 (R0_REGNUM),
+ {PC_REGNUM, 64, 4},
+ {PR_REGNUM, 68, 4},
+ {SR_REGNUM, 72, 4},
+ {GBR_REGNUM, 76, 4},
+ {MACH_REGNUM, 80, 4},
+ {MACL_REGNUM, 84, 4},
+ {-1 /* Terminator. */, 0, 0}
+};
+
+/* Describe the contents of the .reg2 section of the core file. */
+
+static const struct sh_corefile_regs fpregs_table[] =
+{
+ REGSx16 (FR0_REGNUM),
+ /* REGSx16 xfp_regs omitted. */
+ {FPSCR_REGNUM, 128, 4},
+ {FPUL_REGNUM, 132, 4},
+ {-1 /* Terminator. */, 0, 0}
+};
+
+/* Return the appropriate register set for the core section identified
+ by SECT_NAME and SECT_SIZE. */
+
+static const struct regset *
+sh_linux_regset_from_core_section (struct gdbarch *core_gdbarch,
+ const char *sect_name, size_t sect_size)
+{
+ if (strcmp (sect_name, ".reg") == 0)
+ return sh_init_corefile_regset (gregs_table, 0);
+ else if (strcmp (sect_name, ".reg2") == 0)
+ return sh_init_corefile_regset (fpregs_table, 1);
+
+ return NULL;
+}
static void
sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
@@ -36,6 +98,11 @@ sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
+
+ /* Core files are supported for 32-bit SH only, at present. */
+ if (info.bfd_arch_info->mach != bfd_mach_sh5)
+ set_gdbarch_regset_from_core_section
+ (gdbarch, sh_linux_regset_from_core_section);
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff --git a/src/gdb-mainline/gdb/sh-tdep.c b/src/gdb-mainline/gdb/sh-tdep.c
index 3e509bf..9f4a9dc 100644
--- a/src/gdb-mainline/gdb/sh-tdep.c
+++ b/src/gdb-mainline/gdb/sh-tdep.c
@@ -43,6 +43,7 @@
#include "doublest.h"
#include "osabi.h"
#include "reggroups.h"
+#include "regset.h"
#include "sh-tdep.h"
@@ -2738,6 +2739,84 @@ sh_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
}
return 0;
}
+
+
+/* Supply register REGNUM from the buffer specified by REGS and LEN
+ in the register set REGSET to register cache REGCACHE.
+ REGTABLE specifies where each register can be found in REGS.
+ If REGNUM is -1, do this for all registers in REGSET. */
+
+static void
+sh_corefile_supply_regset (const struct regset *regset,
+ struct regcache *regcache,
+ int regnum, const void *regs, size_t len)
+{
+ const struct sh_corefile_regs *regtable = regset->descr;
+ int i;
+
+ for (i = 0; regtable[i].regnum != -1; i++)
+ {
+ if ((regnum == -1 || regnum == regtable[i].regnum)
+ && regtable[i].offset + regtable[i].size <= len)
+ regcache_raw_supply (regcache, regtable[i].regnum,
+ (char *)regs + regtable[i].offset);
+ }
+}
+
+/* Collect register REGNUM in the register set REGSET from register cache
+ REGCACHE into the buffer specified by REGS and LEN.
+ REGTABLE specifies where each register can be found in REGS.
+ If REGNUM is -1, do this for all registers in REGSET. */
+
+static void
+sh_corefile_collect_regset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *regs, size_t len)
+{
+ const struct sh_corefile_regs *regtable = regset->descr;
+ int i;
+
+ for (i = 0; regtable[i].regnum != -1; i++)
+ {
+ if ((regnum == -1 || regnum == regtable[i].regnum)
+ && regtable[i].offset + regtable[i].size <= len)
+ regcache_raw_collect (regcache, regtable[i].regnum,
+ (char *)regs + regtable[i].offset);
+ }
+}
+
+static struct regset sh_corefile_gregset =
+{
+ NULL, /* Filled in later. */
+ sh_corefile_supply_regset,
+ sh_corefile_collect_regset
+};
+
+static struct regset sh_corefile_fpregset =
+{
+ NULL, /* Filled in later. */
+ sh_corefile_supply_regset,
+ sh_corefile_collect_regset
+};
+
+
+/* Initialize reading registers from core files.
+ This is called from OS specific tdep files. */
+
+struct regset *
+sh_init_corefile_regset (const struct sh_corefile_regs regs[], int fp)
+{
+ if (!fp)
+ {
+ sh_corefile_gregset.descr = regs;
+ return &sh_corefile_gregset;
+ }
+ else
+ {
+ sh_corefile_fpregset.descr = regs;
+ return &sh_corefile_fpregset;
+ }
+}
static struct gdbarch *
diff --git a/src/gdb-mainline/gdb/sh-tdep.h b/src/gdb-mainline/gdb/sh-tdep.h
index dfa928e..ecec578 100644
--- a/src/gdb-mainline/gdb/sh-tdep.h
+++ b/src/gdb-mainline/gdb/sh-tdep.h
@@ -30,6 +30,7 @@ enum
ARG0_REGNUM = 4,
ARGLAST_REGNUM = 7,
FP_REGNUM = 14,
+ PC_REGNUM = 16,
PR_REGNUM = 17,
GBR_REGNUM = 18,
VBR_REGNUM = 19,
@@ -85,4 +86,15 @@ enum
extern gdbarch_init_ftype sh64_gdbarch_init;
extern void sh64_show_regs (struct frame_info *);
+/* This structure describes a register in a core-file. */
+struct sh_corefile_regs
+ {
+ int regnum;
+ unsigned int offset;
+ unsigned int size;
+ };
+
+extern struct regset *sh_init_corefile_regset
+ (const struct sh_corefile_regs regs[], int fp);
+
#endif /* SH_TDEP_H */
diff --git a/src/gdb-mainline/gdb/shnbsd-tdep.c b/src/gdb-mainline/gdb/shnbsd-tdep.c
index a0cddc5..5d1fc4c 100644
--- a/src/gdb-mainline/gdb/shnbsd-tdep.c
+++ b/src/gdb-mainline/gdb/shnbsd-tdep.c
@@ -22,7 +22,6 @@
#include "defs.h"
#include "gdbcore.h"
-#include "regcache.h"
#include "regset.h"
#include "value.h"
#include "osabi.h"
@@ -34,116 +33,39 @@
#include "shnbsd-tdep.h"
#include "solib-svr4.h"
-/* Convert an r0-r15 register number into an offset into a ptrace
+/* Convert a register number into an offset into a ptrace
register structure. */
-static const int regmap[] =
+static const struct sh_corefile_regs regmap[] =
{
- (20 * 4), /* r0 */
- (19 * 4), /* r1 */
- (18 * 4), /* r2 */
- (17 * 4), /* r3 */
- (16 * 4), /* r4 */
- (15 * 4), /* r5 */
- (14 * 4), /* r6 */
- (13 * 4), /* r7 */
- (12 * 4), /* r8 */
- (11 * 4), /* r9 */
- (10 * 4), /* r10 */
- ( 9 * 4), /* r11 */
- ( 8 * 4), /* r12 */
- ( 7 * 4), /* r13 */
- ( 6 * 4), /* r14 */
- ( 5 * 4), /* r15 */
+ {R0_REGNUM, 20 * 4, 4},
+ {R0_REGNUM + 1, 19 * 4, 4},
+ {R0_REGNUM + 2, 18 * 4, 4},
+ {R0_REGNUM + 3, 17 * 4, 4},
+ {R0_REGNUM + 4, 16 * 4, 4},
+ {R0_REGNUM + 5, 15 * 4, 4},
+ {R0_REGNUM + 6, 14 * 4, 4},
+ {R0_REGNUM + 7, 13 * 4, 4},
+ {R0_REGNUM + 8, 12 * 4, 4},
+ {R0_REGNUM + 9, 11 * 4, 4},
+ {R0_REGNUM + 10, 10 * 4, 4},
+ {R0_REGNUM + 11, 9 * 4, 4},
+ {R0_REGNUM + 12, 8 * 4, 4},
+ {R0_REGNUM + 13, 7 * 4, 4},
+ {R0_REGNUM + 14, 6 * 4, 4},
+ {R0_REGNUM + 15, 5 * 4, 4},
+ {PC_REGNUM, 0 * 4, 4},
+ {SR_REGNUM, 1 * 4, 4},
+ {PR_REGNUM, 2 * 4, 4},
+ {MACH_REGNUM, 3 * 4, 4},
+ {MACL_REGNUM, 4 * 4, 4},
+ {-1 /* Terminator. */, 0, 0}
};
/* Sizeof `struct reg' in <machine/reg.h>. */
#define SHNBSD_SIZEOF_GREGS (21 * 4)
-/* Supply register REGNUM from the buffer specified by GREGS and LEN
- in the general-purpose register set REGSET to register cache
- REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
-
-static void
-shnbsd_supply_gregset (const struct regset *regset,
- struct regcache *regcache,
- int regnum, const void *gregs, size_t len)
-{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- const gdb_byte *regs = gregs;
- int i;
-
- gdb_assert (len >= SHNBSD_SIZEOF_GREGS);
-
- if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1)
- regcache_raw_supply (regcache, gdbarch_pc_regnum (gdbarch),
- regs + (0 * 4));
-
- if (regnum == SR_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, SR_REGNUM, regs + (1 * 4));
-
- if (regnum == PR_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, PR_REGNUM, regs + (2 * 4));
-
- if (regnum == MACH_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, MACH_REGNUM, regs + (3 * 4));
-
- if (regnum == MACL_REGNUM || regnum == -1)
- regcache_raw_supply (regcache, MACL_REGNUM, regs + (4 * 4));
-
- for (i = R0_REGNUM; i <= (R0_REGNUM + 15); i++)
- {
- if (regnum == i || regnum == -1)
- regcache_raw_supply (regcache, i, regs + regmap[i - R0_REGNUM]);
- }
-}
-
-/* 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
- REGSET. */
-
-static void
-shnbsd_collect_gregset (const struct regset *regset,
- const struct regcache *regcache,
- int regnum, void *gregs, size_t len)
-{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- gdb_byte *regs = gregs;
- int i;
-
- gdb_assert (len >= SHNBSD_SIZEOF_GREGS);
-
- if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1)
- regcache_raw_collect (regcache, gdbarch_pc_regnum (gdbarch),
- regs + (0 * 4));
-
- if (regnum == SR_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, SR_REGNUM, regs + (1 * 4));
-
- if (regnum == PR_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, PR_REGNUM, regs + (2 * 4));
-
- if (regnum == MACH_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, MACH_REGNUM, regs + (3 * 4));
-
- if (regnum == MACL_REGNUM || regnum == -1)
- regcache_raw_collect (regcache, MACL_REGNUM, regs + (4 * 4));
-
- for (i = R0_REGNUM; i <= (R0_REGNUM + 15); i++)
- {
- if (regnum == i || regnum == -1)
- regcache_raw_collect (regcache, i, regs + regmap[i - R0_REGNUM]);
- }
-}
-
-/* SH register sets. */
-
-static struct regset shnbsd_gregset =
-{
- NULL,
- shnbsd_supply_gregset,
- shnbsd_collect_gregset
-};
+/* Local copy of the regset returned by sh_init_corefile_regset. */
+static struct regset *current_regset = NULL;
/* Return the appropriate register set for the core section identified
by SECT_NAME and SECT_SIZE. */
@@ -153,23 +75,31 @@ shnbsd_regset_from_core_section (struct gdbarch *gdbarch,
const char *sect_name, size_t sect_size)
{
if (strcmp (sect_name, ".reg") == 0 && sect_size >= SHNBSD_SIZEOF_GREGS)
- return &shnbsd_gregset;
+ {
+ current_regset = sh_init_corefile_regset (regmap, 0);
+ return current_regset;
+ }
+ current_regset = NULL;
return NULL;
}
void
shnbsd_supply_reg (struct regcache *regcache, const char *regs, int regnum)
{
- shnbsd_supply_gregset (&shnbsd_gregset, regcache, regnum,
- regs, SHNBSD_SIZEOF_GREGS);
+ gdb_assert (current_regset != NULL);
+
+ current_regset->supply_regset (current_regset, regcache, regnum,
+ regs, SHNBSD_SIZEOF_GREGS);
}
void
shnbsd_fill_reg (const struct regcache *regcache, char *regs, int regnum)
{
- shnbsd_collect_gregset (&shnbsd_gregset, regcache, regnum,
- regs, SHNBSD_SIZEOF_GREGS);
+ gdb_assert (current_regset != NULL);
+
+ current_regset->collect_regset (current_regset, regcache, regnum,
+ regs, SHNBSD_SIZEOF_GREGS);
}