diff --git a/gdb/sh-linux-tdep.c b/gdb/sh-linux-tdep.c index 46aad1d..5eba796 100644 --- a/gdb/sh-linux-tdep.c +++ b/gdb/sh-linux-tdep.c @@ -28,6 +28,8 @@ static void sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + /* GNU/Linux uses SVR4-style shared libraries. */ set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); set_solib_svr4_fetch_link_map_offsets @@ -36,6 +38,12 @@ 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 tdep->core_regmap and tdep->core_fpregmap here. */ + } } /* Provide a prototype to silence -Wmissing-prototypes. */ diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c index 3e509bf..5d8d5a3 100644 --- a/gdb/sh-tdep.c +++ b/gdb/sh-tdep.c @@ -2740,6 +2740,102 @@ sh_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) } +/* 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_supply_gregset (const struct regset *regset, struct regcache *regcache, + int regnum, const void *gregs, size_t len) +{ + struct gdbarch *gdbarch = get_regcache_arch (regcache); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + /* Use the tdep data to fill in the regset. */ +} + +/* 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_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 gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int i; + + /* Use the tdep data to fill in the regset. */ +} + +/* SH register sets. */ + +static struct regset sh_gregset = +{ + NULL, + sh_supply_gregset, + sh_collect_gregset +}; + +/* 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_supply_fpregset (const struct regset *regset, struct regcache *regcache, + int regnum, const void *fpregs, size_t len) +{ + /* Same as above. */ +} + +/* 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_collect_fpregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *fpregs, size_t len) +{ + /* Same as above. */ +} + +/* SH register sets. */ + +static struct regset sh_fpregset = +{ + NULL, + sh_supply_fpregset, + sh_collect_fpregset +}; + +/* Return the appropriate register set for the core section identified + by SECT_NAME and SECT_SIZE. */ + +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_regmap == NULL) + return NULL; /* core files not supported on this architecture. */ + + if (strcmp (sect_name, ".reg") == 0 && sect_size >= SH_SIZEOF_GREGS) + return &sh_gregset; + + if (tdep->core_fp_regmap + && strcmp (sect_name, ".reg2") == 0 + && sect_size >= SH_SIZEOF_FP_GREGS) + return &sh_fpregset; + + return NULL; +} + static struct gdbarch * sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) { @@ -2803,7 +2899,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 +2944,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/gdb/sh-tdep.h b/gdb/sh-tdep.h index dfa928e..37a8f8c 100644 --- a/gdb/sh-tdep.h +++ b/gdb/sh-tdep.h @@ -82,6 +82,18 @@ enum FV_LAST_REGNUM = 79 }; +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. */ + int *core_regmap; + /* 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. */ + int *core_fp_regmap; +}; + extern gdbarch_init_ftype sh64_gdbarch_init; extern void sh64_show_regs (struct frame_info *); diff --git a/gdb/shnbsd-tdep.c b/gdb/shnbsd-tdep.c index a0cddc5..633770d 100644 --- a/gdb/shnbsd-tdep.c +++ b/gdb/shnbsd-tdep.c @@ -59,105 +59,6 @@ static const int regmap[] = /* 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) { @@ -177,11 +78,12 @@ 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); set_solib_svr4_fetch_link_map_offsets (gdbarch, svr4_ilp32_fetch_link_map_offsets); + + /* Set tdep->core_regmap here. */ }