From: Andrew Stubbs <ams@codesourcery.com>
To: gdb-patches@sources.redhat.com
Subject: [PATCH][SH] Implement core-file support for sh-linux
Date: Mon, 12 Oct 2009 14:26:00 -0000 [thread overview]
Message-ID: <4AD33C69.2070301@codesourcery.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 241 bytes --]
This patch adds support for debugging core-files on SH Linux targets.
I've added code to read both the general-purpose registers, and the
floating point registers from core files. This code is adapted from the
SH NBSD files.
OK?
Andrew
[-- Attachment #2: corefiles.patch --]
[-- Type: text/x-diff, Size: 8616 bytes --]
2009-10-12 Andrew Stubbs <ams@codesourcery.com>
* configure.tgt (sh*-*-linux*): Add corelow.o to gdb_target_obs.
* sh-linux-tdep.c: Include gdb_assert.h, gdb_string.h, regcache.h,
regset.h and sh-tdep.h.
(struct sh_linux_pt_regs, struct sh_linux_user_fpu_struct): New types.
(sh_linux_supply_gregset, sh_linux_collect_gregset): New functions.
(sh_linux_supply_fpregset, sh_linux_collect_fpregset): New functions.
(sh_linux_gregset, sh_linux_fpregset): New variables.
(sh_linux_regset_from_core_section): New function.
(sh_linux_init_abi): Call set_gdbarch_regset_from_core_section.
---
src/gdb-mainline/gdb/configure.tgt | 3
src/gdb-mainline/gdb/sh-linux-tdep.c | 208 ++++++++++++++++++++++++++++++++++
2 files changed, 210 insertions(+), 1 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..27db8ff 100644
--- a/src/gdb-mainline/gdb/sh-linux-tdep.c
+++ b/src/gdb-mainline/gdb/sh-linux-tdep.c
@@ -20,10 +20,213 @@
#include "defs.h"
#include "osabi.h"
+#include "gdb_assert.h"
+#include "gdb_string.h"
+
#include "solib-svr4.h"
#include "symtab.h"
+#include "regcache.h"
+#include "regset.h"
#include "glibc-tdep.h"
+#include "sh-tdep.h"
+
+/* Copied from asm/ptrace.h, and made 64-bit safe:
+ This struct defines the way the registers are stored on the
+ kernel stack during a system call or other kernel entry. */
+struct sh_linux_pt_regs
+ {
+ uint32_t regs[16];
+ uint32_t pc;
+ uint32_t pr;
+ uint32_t sr;
+ uint32_t gbr;
+ uint32_t mach;
+ uint32_t macl;
+ int32_t tra;
+ };
+
+/* Copied from sys/user.h, and made 64-bit safe. */
+struct sh_linux_user_fpu_struct
+ {
+ uint32_t fp_regs[16];
+ uint32_t xfp_regs[16];
+ uint32_t fpscr;
+ uint32_t fpul;
+ };
+
+/* 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
+sh_linux_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 struct sh_linux_pt_regs *regs = gregs;
+ int i;
+
+ gdb_assert (len >= sizeof (struct sh_linux_pt_regs));
+
+ if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1)
+ regcache_raw_supply (regcache, gdbarch_pc_regnum (gdbarch),
+ ®s->pc);
+
+ if (regnum == SR_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SR_REGNUM, ®s->sr);
+
+ if (regnum == PR_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, PR_REGNUM, ®s->pr);
+
+ if (regnum == GBR_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, PR_REGNUM, ®s->gbr);
+
+ if (regnum == MACH_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, MACH_REGNUM, ®s->mach);
+
+ if (regnum == MACL_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, MACL_REGNUM, ®s->macl);
+
+ for (i = R0_REGNUM; i <= (R0_REGNUM + 15); i++)
+ {
+ if (regnum == i || regnum == -1)
+ regcache_raw_supply (regcache, i, ®s->regs[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
+sh_linux_collect_gregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *gregs, size_t len)
+{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct sh_linux_pt_regs *regs = gregs;
+ int i;
+
+ gdb_assert (len >= sizeof (struct sh_linux_pt_regs));
+
+ if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1)
+ regcache_raw_collect (regcache, gdbarch_pc_regnum (gdbarch),
+ ®s->pc);
+
+ if (regnum == SR_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SR_REGNUM, ®s->sr);
+
+ if (regnum == PR_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, PR_REGNUM, ®s->pr);
+
+ if (regnum == GBR_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, GBR_REGNUM, ®s->gbr);
+
+ if (regnum == MACH_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, MACH_REGNUM, ®s->mach);
+
+ if (regnum == MACL_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, MACL_REGNUM, ®s->macl);
+
+ for (i = R0_REGNUM; i <= (R0_REGNUM + 15); i++)
+ {
+ if (regnum == i || regnum == -1)
+ regcache_raw_collect (regcache, i, ®s->regs[i - R0_REGNUM]);
+ }
+}
+
+/* Supply register REGNUM from the buffer specified by FPREGS and LEN
+ in the floating point register set REGSET to register cache
+ REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
+
+static void
+sh_linux_supply_fpregset (const struct regset *regset,
+ struct regcache *regcache,
+ int regnum, const void *fpregs, size_t len)
+{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ const struct sh_linux_user_fpu_struct *regs = fpregs;
+ int fp0_regnum = gdbarch_fp0_regnum (gdbarch);
+ int i;
+
+ gdb_assert (len >= sizeof (struct sh_linux_user_fpu_struct));
+
+ if (regnum == FPSCR_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, FPSCR_REGNUM, ®s->fpscr);
+
+ if (regnum == FPUL_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, FPUL_REGNUM, ®s->fpul);
+
+ if (fp0_regnum >= 0)
+ for (i = fp0_regnum; i <= (fp0_regnum + 15); i++)
+ if (regnum == i || regnum == -1)
+ regcache_raw_supply (regcache, i, ®s->fp_regs[i - fp0_regnum]);
+}
+
+/* Collect register REGNUM in the floating point register set
+ REGSET. from register cache REGCACHE into the buffer specified by
+ FPREGS and LEN. If REGNUM is -1, do this for all registers in
+ REGSET. */
+
+static void
+sh_linux_collect_fpregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *fpregs, size_t len)
+{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct sh_linux_user_fpu_struct *regs = fpregs;
+ int fp0_regnum = gdbarch_fp0_regnum (gdbarch);
+ int i;
+
+ gdb_assert (len >= sizeof (struct sh_linux_user_fpu_struct));
+
+ if (regnum == FPSCR_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, FPSCR_REGNUM, ®s->fpscr);
+
+ if (regnum == FPUL_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, FPUL_REGNUM, ®s->fpul);
+
+ if (fp0_regnum >= 0)
+ for (i = fp0_regnum; i <= (fp0_regnum + 15); i++)
+ if (regnum == i || regnum == -1)
+ regcache_raw_collect (regcache, i, ®s->fp_regs[i - fp0_regnum]);
+}
+
+/* SH register sets. */
+
+static struct regset sh_linux_gregset =
+{
+ NULL,
+ sh_linux_supply_gregset,
+ sh_linux_collect_gregset
+};
+
+static struct regset sh_linux_fpregset =
+{
+ NULL,
+ sh_linux_supply_fpregset,
+ sh_linux_collect_fpregset
+};
+
+/* 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 *gdbarch,
+ const char *sect_name, size_t sect_size)
+{
+ if (strcmp (sect_name, ".reg") == 0
+ && sect_size >= sizeof (struct sh_linux_pt_regs))
+ return &sh_linux_gregset;
+ else if (strcmp (sect_name, ".reg2") == 0
+ && sect_size >= sizeof (struct sh_linux_user_fpu_struct))
+ return &sh_linux_fpregset;
+
+ return NULL;
+}
static void
sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
@@ -36,6 +239,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. */
next reply other threads:[~2009-10-12 14:26 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-10-12 14:26 Andrew Stubbs [this message]
2009-10-14 4:56 ` Joel Brobecker
2009-10-15 13:27 ` Andrew Stubbs
2009-10-15 16:20 ` Joel Brobecker
2009-10-19 17:27 ` Andrew Stubbs
2009-10-19 19:33 ` Joel Brobecker
2009-10-21 14:18 ` Andrew Stubbs
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4AD33C69.2070301@codesourcery.com \
--to=ams@codesourcery.com \
--cc=gdb-patches@sources.redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox