From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16821 invoked by alias); 12 Oct 2009 14:26:00 -0000 Received: (qmail 16770 invoked by uid 22791); 12 Oct 2009 14:25:53 -0000 X-SWARE-Spam-Status: No, hits=-2.6 required=5.0 tests=BAYES_00,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 12 Oct 2009 14:25:49 +0000 Received: (qmail 3557 invoked from network); 12 Oct 2009 14:25:47 -0000 Received: from unknown (HELO ?192.168.1.100?) (ams@127.0.0.2) by mail.codesourcery.com with ESMTPA; 12 Oct 2009 14:25:47 -0000 Message-ID: <4AD33C69.2070301@codesourcery.com> Date: Mon, 12 Oct 2009 14:26:00 -0000 From: Andrew Stubbs User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.1.1) Gecko/20090715 Thunderbird/3.0b3 MIME-Version: 1.0 To: gdb-patches@sources.redhat.com Subject: [PATCH][SH] Implement core-file support for sh-linux Content-Type: multipart/mixed; boundary="------------040904080705010004080805" Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2009-10/txt/msg00231.txt.bz2 This is a multi-part message in MIME format. --------------040904080705010004080805 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 241 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 --------------040904080705010004080805 Content-Type: text/x-diff; name="corefiles.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="corefiles.patch" Content-length: 8616 2009-10-12 Andrew Stubbs * 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. */ --------------040904080705010004080805--