From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26730 invoked by alias); 19 Oct 2009 17:27:02 -0000 Received: (qmail 26709 invoked by uid 22791); 19 Oct 2009 17:27:00 -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, 19 Oct 2009 17:26:56 +0000 Received: (qmail 2713 invoked from network); 19 Oct 2009 17:26:54 -0000 Received: from unknown (HELO ?192.168.1.100?) (ams@127.0.0.2) by mail.codesourcery.com with ESMTPA; 19 Oct 2009 17:26:54 -0000 Message-ID: <4ADCA15B.6080104@codesourcery.com> Date: Mon, 19 Oct 2009 17:27: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: Joel Brobecker CC: gdb-patches@sources.redhat.com Subject: Re: [PATCH][SH] Implement core-file support for sh-linux References: <4AD33C69.2070301@codesourcery.com> <20091014045558.GT5272@adacore.com> <4AD7233E.9050906@codesourcery.com> <20091015161950.GZ5272@adacore.com> In-Reply-To: <20091015161950.GZ5272@adacore.com> Content-Type: multipart/mixed; boundary="------------070200070406050609090106" 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/msg00430.txt.bz2 This is a multi-part message in MIME format. --------------070200070406050609090106 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 442 On 15/10/09 17:19, Joel Brobecker wrote: > You definitely got the idea, but the implementation does not work > in the case of multi-arch debugging. This is because you are > introducing a global variable. The solution is to rely on the > gdbarch_tdep structure. OK, how about this patch? I've reimplemented it using your ideas. I've tested that sh-linux GDB can read a core file, and I've tested that shnbsd.tdep.c can be built. Andrew --------------070200070406050609090106 Content-Type: text/x-diff; name="corefiles.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="corefiles.patch" Content-length: 15187 2009-10-19 Andrew Stubbs Joel Brobecker * configure.tgt (sh*-*-linux*): Add corelow.o to gdb_target_obs. * sh-linux-tdep.c: Include sh-tdep.h. (REGSx16): New macro. (gregs_table, fpregs_table): New variables. (sh_linux_init_abi): Set core_gregmap and fpregmap. * 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_regset_from_core_section): New function. (sh_gdbarch_init): Set up tdep value. Call set_gdbarch_regset_from_core_section. * sh-tdep.h (PC_REGNUM): New enum value. (struct sh_corefile_regs): New type. (sh_corefile_gregset): Export variable. * shnbsd-tdep.c: Remove include of regcache.h and gdb_assert.h. (regmap): Use new definition using struct sh_corefile_regs. (shnbsd_supply_gregset, shnbsd_collect_gregset): Delete. (shnbsd_gregset): Delete. (shnbsd_regset_from_core_section): Delete. (shnbsd_supply_reg, shnbsd_fill_reg): Use new regset interface. (shnbsd_init_abi): Set core_gregmap. --- src/gdb-mainline/gdb/configure.tgt | 3 - src/gdb-mainline/gdb/sh-linux-tdep.c | 52 +++++++++++ src/gdb-mainline/gdb/sh-tdep.c | 92 ++++++++++++++++++++ src/gdb-mainline/gdb/sh-tdep.h | 22 +++++ src/gdb-mainline/gdb/shnbsd-tdep.c | 155 +++++++--------------------------- 5 files changed, 197 insertions(+), 127 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..1e62f27 100644 --- a/src/gdb-mainline/gdb/sh-linux-tdep.c +++ b/src/gdb-mainline/gdb/sh-linux-tdep.c @@ -24,6 +24,50 @@ #include "symtab.h" #include "glibc-tdep.h" +#include "sh-tdep.h" + +#define REGSx16(base) \ + {(base), 0}, \ + {(base) + 1, 4}, \ + {(base) + 2, 8}, \ + {(base) + 3, 12}, \ + {(base) + 4, 16}, \ + {(base) + 5, 20}, \ + {(base) + 6, 24}, \ + {(base) + 7, 28}, \ + {(base) + 8, 32}, \ + {(base) + 9, 36}, \ + {(base) + 10, 40}, \ + {(base) + 11, 44}, \ + {(base) + 12, 48}, \ + {(base) + 13, 52}, \ + {(base) + 14, 56}, \ + {(base) + 15, 60} + +/* Describe the contents of the .reg section of the core file. */ + +static const struct sh_corefile_regmap gregs_table[] = +{ + REGSx16 (R0_REGNUM), + {PC_REGNUM, 64}, + {PR_REGNUM, 68}, + {SR_REGNUM, 72}, + {GBR_REGNUM, 76}, + {MACH_REGNUM, 80}, + {MACL_REGNUM, 84}, + {-1 /* Terminator. */, 0} +}; + +/* Describe the contents of the .reg2 section of the core file. */ + +static const struct sh_corefile_regmap fpregs_table[] = +{ + REGSx16 (FR0_REGNUM), + /* REGSx16 xfp_regs omitted. */ + {FPSCR_REGNUM, 128}, + {FPUL_REGNUM, 132}, + {-1 /* Terminator. */, 0} +}; static void sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) @@ -36,6 +80,14 @@ 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) + { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + tdep->core_gregmap = (struct sh_corefile_regmap *)gregs_table; + tdep->core_fpregmap = (struct sh_corefile_regmap *)fpregs_table; + } } /* 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..b0a8d81 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,12 +2739,98 @@ 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) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + const struct sh_corefile_regmap *regmap = regset == &sh_corefile_gregset + ? tdep->core_gregmap + : tdep->core_fpregmap; + int i; + + for (i = 0; regmap[i].regnum != -1; i++) + { + if ((regnum == -1 || regnum == regmap[i].regnum) + && regmap[i].offset + 4 <= len) + regcache_raw_supply (regcache, regmap[i].regnum, + (char *)regs + regmap[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) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + const struct sh_corefile_regmap *regmap = regset == &sh_corefile_gregset + ? tdep->core_gregmap + : tdep->core_fpregmap; + int i; + + for (i = 0; regmap[i].regnum != -1; i++) + { + if ((regnum == -1 || regnum == regmap[i].regnum) + && regmap[i].offset + 4 <= len) + regcache_raw_collect (regcache, regmap[i].regnum, + (char *)regs + regmap[i].offset); + } +} + +/* The following two regsets have the same contents, so it is tempting to + unify them, but they are distiguished by their address, so don't. */ + +struct regset sh_corefile_gregset = +{ + NULL, + sh_corefile_supply_regset, + sh_corefile_collect_regset +}; + +static struct regset sh_corefile_fpregset = +{ + NULL, + sh_corefile_supply_regset, + sh_corefile_collect_regset +}; + +static const struct regset * +sh_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name, + size_t sect_size) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + if (tdep->core_gregmap && strcmp (sect_name, ".reg") == 0) + return &sh_corefile_gregset; + + if (tdep->core_fpregmap && strcmp (sect_name, ".reg2") == 0) + return &sh_corefile_fpregset; + + return NULL; +} static struct gdbarch * sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { struct gdbarch *gdbarch; + struct gdbarch_tdep *tdep; sh_show_regs = sh_generic_show_regs; switch (info.bfd_arch_info->mach) @@ -2803,7 +2890,8 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* None found, create a new architecture from the information provided. */ - gdbarch = gdbarch_alloc (&info, NULL); + tdep = XZALLOC (struct gdbarch_tdep); + gdbarch = gdbarch_alloc (&info, tdep); set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT); set_gdbarch_int_bit (gdbarch, 4 * TARGET_CHAR_BIT); @@ -2847,6 +2935,8 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) dwarf2_frame_set_init_reg (gdbarch, sh_dwarf2_frame_init_reg); + set_gdbarch_regset_from_core_section (gdbarch, sh_regset_from_core_section); + switch (info.bfd_arch_info->mach) { case bfd_mach_sh: diff --git a/src/gdb-mainline/gdb/sh-tdep.h b/src/gdb-mainline/gdb/sh-tdep.h index dfa928e..cd2f873 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,25 @@ 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_regmap +{ + int regnum; + unsigned int offset; +}; + +struct gdbarch_tdep +{ + /* Non-NULL when debugging from a core file. Provides the offset + where each general-purpose register is stored inside the associated + core file section. */ + struct sh_corefile_regmap *core_gregmap; + /* Non-NULL when debugging from a core file and when FP registers are + available. Provides the offset where each FP register is stored + inside the associated core file section. */ + struct sh_corefile_regmap *core_fpregmap; +}; + +extern struct regset sh_corefile_gregset; + #endif /* SH_TDEP_H */ diff --git a/src/gdb-mainline/gdb/shnbsd-tdep.c b/src/gdb-mainline/gdb/shnbsd-tdep.c index a0cddc5..6630717 100644 --- a/src/gdb-mainline/gdb/shnbsd-tdep.c +++ b/src/gdb-mainline/gdb/shnbsd-tdep.c @@ -22,154 +22,59 @@ #include "defs.h" #include "gdbcore.h" -#include "regcache.h" #include "regset.h" #include "value.h" #include "osabi.h" -#include "gdb_assert.h" #include "gdb_string.h" #include "sh-tdep.h" #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_regmap 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}, + {R0_REGNUM + 1, 19 * 4}, + {R0_REGNUM + 2, 18 * 4}, + {R0_REGNUM + 3, 17 * 4}, + {R0_REGNUM + 4, 16 * 4}, + {R0_REGNUM + 5, 15 * 4}, + {R0_REGNUM + 6, 14 * 4}, + {R0_REGNUM + 7, 13 * 4}, + {R0_REGNUM + 8, 12 * 4}, + {R0_REGNUM + 9, 11 * 4}, + {R0_REGNUM + 10, 10 * 4}, + {R0_REGNUM + 11, 9 * 4}, + {R0_REGNUM + 12, 8 * 4}, + {R0_REGNUM + 13, 7 * 4}, + {R0_REGNUM + 14, 6 * 4}, + {R0_REGNUM + 15, 5 * 4}, + {PC_REGNUM, 0 * 4}, + {SR_REGNUM, 1 * 4}, + {PR_REGNUM, 2 * 4}, + {MACH_REGNUM, 3 * 4}, + {MACL_REGNUM, 4 * 4}, + {-1 /* Terminator. */, 0} }; /* Sizeof `struct reg' in . */ #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 -}; - -/* Return the appropriate register set for the core section identified - by SECT_NAME and SECT_SIZE. */ - -static const struct regset * -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; - - 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); + sh_corefile_gregset.supply_regset (&sh_corefile_gregset, 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); + sh_corefile_gregset.collect_regset (&sh_corefile_gregset, regcache, regnum, + regs, SHNBSD_SIZEOF_GREGS); } @@ -177,8 +82,8 @@ static void shnbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { - set_gdbarch_regset_from_core_section - (gdbarch, shnbsd_regset_from_core_section); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + tdep->core_gregmap = (struct sh_corefile_regmap *)regmap; set_solib_svr4_fetch_link_map_offsets (gdbarch, svr4_ilp32_fetch_link_map_offsets); --------------070200070406050609090106--