2009-10-15 Andrew Stubbs * 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 . */ #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); }