-/* Target-dependent code for SuperH running NetBSD, for GDB.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Target-dependent code for NetBSD/sh.
+
+ Copyright (C) 2002, 2003, 2006, 2007 Free Software Foundation, Inc.
+
Contributed by Wasabi Systems, Inc.
This file is part of GDB.
#include "defs.h"
#include "gdbcore.h"
#include "regcache.h"
+#include "regset.h"
#include "value.h"
#include "osabi.h"
-#include "solib-svr4.h"
+#include "gdb_assert.h"
+#include "gdb_string.h"
-#include "nbsd-tdep.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
register structure. */
( 5 * 4), /* r15 */
};
-#define SIZEOF_STRUCT_REG (21 * 4)
+/* Sizeof `struct reg' in <machine/reg.h>. */
+#define SHNBSD_SIZEOF_GREGS (21 * 4)
-void
-shnbsd_supply_reg (char *regs, int regno)
+/* 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)
{
+ const gdb_byte *regs = gregs;
int i;
- if (regno == PC_REGNUM || regno == -1)
- regcache_raw_supply (current_regcache, PC_REGNUM, regs + (0 * 4));
+ gdb_assert (len >= SHNBSD_SIZEOF_GREGS);
- if (regno == SR_REGNUM || regno == -1)
- regcache_raw_supply (current_regcache, SR_REGNUM, regs + (1 * 4));
+ if (regnum == gdbarch_pc_regnum (current_gdbarch) || regnum == -1)
+ regcache_raw_supply (regcache,
+ gdbarch_pc_regnum (current_gdbarch),
+ regs + (0 * 4));
- if (regno == PR_REGNUM || regno == -1)
- regcache_raw_supply (current_regcache, PR_REGNUM, regs + (2 * 4));
+ if (regnum == SR_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, SR_REGNUM, regs + (1 * 4));
- if (regno == MACH_REGNUM || regno == -1)
- regcache_raw_supply (current_regcache, MACH_REGNUM, regs + (3 * 4));
+ if (regnum == PR_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, PR_REGNUM, regs + (2 * 4));
- if (regno == MACL_REGNUM || regno == -1)
- regcache_raw_supply (current_regcache, MACL_REGNUM, regs + (4 * 4));
+ if (regnum == MACH_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, MACH_REGNUM, regs + (3 * 4));
- if ((regno >= R0_REGNUM && regno <= (R0_REGNUM + 15)) || regno == -1)
+ if (regnum == MACL_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, MACL_REGNUM, regs + (4 * 4));
+
+ for (i = R0_REGNUM; i <= (R0_REGNUM + 15); i++)
{
- for (i = R0_REGNUM; i <= (R0_REGNUM + 15); i++)
- if (regno == i || regno == -1)
- regcache_raw_supply (current_regcache, i,
- regs + regmap[i - R0_REGNUM]);
+ if (regnum == i || regnum == -1)
+ regcache_raw_supply (regcache, i, regs + regmap[i - R0_REGNUM]);
}
}
-void
-shnbsd_fill_reg (char *regs, int regno)
+/* 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)
{
+ gdb_byte *regs = gregs;
int i;
- if (regno == PC_REGNUM || regno == -1)
- regcache_raw_collect (current_regcache, PC_REGNUM, regs + (0 * 4));
+ gdb_assert (len >= SHNBSD_SIZEOF_GREGS);
+
+ if (regnum == gdbarch_pc_regnum (current_gdbarch) || regnum == -1)
+ regcache_raw_collect (regcache, gdbarch_pc_regnum (current_gdbarch),
+ regs + (0 * 4));
- if (regno == SR_REGNUM || regno == -1)
- regcache_raw_collect (current_regcache, SR_REGNUM, regs + (1 * 4));
+ if (regnum == SR_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, SR_REGNUM, regs + (1 * 4));
- if (regno == PR_REGNUM || regno == -1)
- regcache_raw_collect (current_regcache, PR_REGNUM, regs + (2 * 4));
+ if (regnum == PR_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, PR_REGNUM, regs + (2 * 4));
- if (regno == MACH_REGNUM || regno == -1)
- regcache_raw_collect (current_regcache, MACH_REGNUM, regs + (3 * 4));
+ if (regnum == MACH_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, MACH_REGNUM, regs + (3 * 4));
- if (regno == MACL_REGNUM || regno == -1)
- regcache_raw_collect (current_regcache, MACL_REGNUM, regs + (4 * 4));
+ if (regnum == MACL_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, MACL_REGNUM, regs + (4 * 4));
- if ((regno >= R0_REGNUM && regno <= (R0_REGNUM + 15)) || regno == -1)
+ for (i = R0_REGNUM; i <= (R0_REGNUM + 15); i++)
{
- for (i = R0_REGNUM; i <= (R0_REGNUM + 15); i++)
- if (regno == i || regno == -1)
- regcache_raw_collect (current_regcache, i,
- regs + regmap[i - R0_REGNUM]);
+ if (regnum == i || regnum == -1)
+ regcache_raw_collect (regcache, i, regs + regmap[i - R0_REGNUM]);
}
}
-static void
-fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
- int which, CORE_ADDR ignore)
-{
- /* We get everything from the .reg section. */
- if (which != 0)
- return;
+/* SH register sets. */
- if (core_reg_size < SIZEOF_STRUCT_REG)
- {
- warning (_("Wrong size register set in core file."));
- return;
- }
+static struct regset shnbsd_gregset =
+{
+ NULL,
+ shnbsd_supply_gregset,
+ shnbsd_collect_gregset
+};
- /* Integer registers. */
- shnbsd_supply_reg (core_reg_sect, -1);
-}
+/* Return the appropriate register set for the core section identified
+ by SECT_NAME and SECT_SIZE. */
-static void
-fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size,
- int which, CORE_ADDR ignore)
+const struct regset *
+shnbsd_regset_from_core_section (struct gdbarch *gdbarch,
+ const char *sect_name, size_t sect_size)
{
- switch (which)
- {
- case 0: /* Integer registers. */
- if (core_reg_size != SIZEOF_STRUCT_REG)
- warning (_("Wrong size register set in core file."));
- else
- shnbsd_supply_reg (core_reg_sect, -1);
- break;
-
- default:
- /* Don't know what kind of register request this is; just ignore it. */
- break;
- }
+ if (strcmp (sect_name, ".reg") == 0 && sect_size >= SHNBSD_SIZEOF_GREGS)
+ return &shnbsd_gregset;
+
+ return NULL;
}
-static struct core_fns shnbsd_core_fns =
+void
+shnbsd_supply_reg (struct regcache *regcache, const char *regs, int regnum)
{
- bfd_target_unknown_flavour, /* core_flavour */
- default_check_format, /* check_format */
- default_core_sniffer, /* core_sniffer */
- fetch_core_registers, /* core_read_registers */
- NULL /* next */
-};
+ shnbsd_supply_gregset (&shnbsd_gregset, regcache, regnum,
+ regs, SHNBSD_SIZEOF_GREGS);
+}
-static struct core_fns shnbsd_elfcore_fns =
+void
+shnbsd_fill_reg (const struct regcache *regcache, char *regs, int regnum)
{
- bfd_target_elf_flavour, /* core_flavour */
- default_check_format, /* check_format */
- default_core_sniffer, /* core_sniffer */
- fetch_elfcore_registers, /* core_read_registers */
- NULL /* next */
-};
+ shnbsd_collect_gregset (&shnbsd_gregset, regcache, regnum,
+ regs, SHNBSD_SIZEOF_GREGS);
+}
+\f
static void
shnbsd_init_abi (struct gdbarch_info info,
struct gdbarch *gdbarch)
{
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- nbsd_ilp32_solib_svr4_fetch_link_map_offsets);
+ set_gdbarch_regset_from_core_section
+ (gdbarch, shnbsd_regset_from_core_section);
+
+ set_solib_svr4_fetch_link_map_offsets
+ (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+}
+\f
+
+/* OpenBSD uses uses the traditional NetBSD core file format, even for
+ ports that use ELF. */
+#define GDB_OSABI_NETBSD_CORE GDB_OSABI_OPENBSD_ELF
+
+static enum gdb_osabi
+shnbsd_core_osabi_sniffer (bfd *abfd)
+{
+ if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
+ return GDB_OSABI_NETBSD_CORE;
+
+ return GDB_OSABI_UNKNOWN;
}
void
_initialize_shnbsd_tdep (void)
{
- deprecated_add_core_fns (&shnbsd_core_fns);
- deprecated_add_core_fns (&shnbsd_elfcore_fns);
+ /* BFD doesn't set a flavour for NetBSD style a.out core files. */
+ gdbarch_register_osabi_sniffer (bfd_arch_sh, bfd_target_unknown_flavour,
+ shnbsd_core_osabi_sniffer);
gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_NETBSD_ELF,
shnbsd_init_abi);
+ gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_OPENBSD_ELF,
+ shnbsd_init_abi);
}