gdb/m68kbsd-tdep.c - gdb

Global variables defined

Functions defined

Macros defined

Source code

  1. /* Target-dependent code for Motorola 68000 BSD's.

  2.    Copyright (C) 2004-2015 Free Software Foundation, Inc.

  3.    This file is part of GDB.

  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 3 of the License, or
  7.    (at your option) any later version.

  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.

  12.    You should have received a copy of the GNU General Public License
  13.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  14. #include "defs.h"
  15. #include "arch-utils.h"
  16. #include "frame.h"
  17. #include "osabi.h"
  18. #include "regcache.h"
  19. #include "regset.h"
  20. #include "trad-frame.h"
  21. #include "tramp-frame.h"
  22. #include "gdbtypes.h"

  23. #include "m68k-tdep.h"
  24. #include "solib-svr4.h"

  25. /* Core file support.  */

  26. /* Sizeof `struct reg' in <machine/reg.h>.  */
  27. #define M68KBSD_SIZEOF_GREGS        (18 * 4)

  28. /* Sizeof `struct fpreg' in <machine/reg.h.  */
  29. #define M68KBSD_SIZEOF_FPREGS        (((8 * 3) + 3) * 4)

  30. int
  31. m68kbsd_fpreg_offset (struct gdbarch *gdbarch, int regnum)
  32. {
  33.   int fp_len = TYPE_LENGTH (gdbarch_register_type (gdbarch, regnum));

  34.   if (regnum >= M68K_FPC_REGNUM)
  35.     return 8 * fp_len + (regnum - M68K_FPC_REGNUM) * 4;

  36.   return (regnum - M68K_FP0_REGNUM) * fp_len;
  37. }

  38. /* Supply register REGNUM from the buffer specified by FPREGS and LEN
  39.    in the floating-point register set REGSET to register cache
  40.    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */

  41. static void
  42. m68kbsd_supply_fpregset (const struct regset *regset,
  43.                          struct regcache *regcache,
  44.                          int regnum, const void *fpregs, size_t len)
  45. {
  46.   struct gdbarch *gdbarch = get_regcache_arch (regcache);
  47.   const gdb_byte *regs = fpregs;
  48.   int i;

  49.   gdb_assert (len >= M68KBSD_SIZEOF_FPREGS);

  50.   for (i = M68K_FP0_REGNUM; i <= M68K_PC_REGNUM; i++)
  51.     {
  52.       if (regnum == i || regnum == -1)
  53.         regcache_raw_supply (regcache, i,
  54.                              regs + m68kbsd_fpreg_offset (gdbarch, i));
  55.     }
  56. }

  57. /* Supply register REGNUM from the buffer specified by GREGS and LEN
  58.    in the general-purpose register set REGSET to register cache
  59.    REGCACHE.  If REGNUM is -1, do this for all registers in REGSET.  */

  60. static void
  61. m68kbsd_supply_gregset (const struct regset *regset,
  62.                         struct regcache *regcache,
  63.                         int regnum, const void *gregs, size_t len)
  64. {
  65.   const gdb_byte *regs = gregs;
  66.   int i;

  67.   gdb_assert (len >= M68KBSD_SIZEOF_GREGS);

  68.   for (i = M68K_D0_REGNUM; i <= M68K_PC_REGNUM; i++)
  69.     {
  70.       if (regnum == i || regnum == -1)
  71.         regcache_raw_supply (regcache, i, regs + i * 4);
  72.     }

  73.   if (len >= M68KBSD_SIZEOF_GREGS + M68KBSD_SIZEOF_FPREGS)
  74.     {
  75.       regs += M68KBSD_SIZEOF_GREGS;
  76.       len -= M68KBSD_SIZEOF_GREGS;
  77.       m68kbsd_supply_fpregset (regset, regcache, regnum, regs, len);
  78.     }
  79. }

  80. /* Motorola 68000 register sets.  */

  81. static const struct regset m68kbsd_gregset =
  82. {
  83.   NULL,
  84.   m68kbsd_supply_gregset
  85. };

  86. static const struct regset m68kbsd_fpregset =
  87. {
  88.   NULL,
  89.   m68kbsd_supply_fpregset
  90. };

  91. /* Iterate over core file register note sections.  */

  92. static void
  93. m68kbsd_iterate_over_regset_sections (struct gdbarch *gdbarch,
  94.                                       iterate_over_regset_sections_cb *cb,
  95.                                       void *cb_data,
  96.                                       const struct regcache *regcache)
  97. {
  98.   cb (".reg", M68KBSD_SIZEOF_GREGS, &m68kbsd_gregset, NULL, cb_data);
  99.   cb (".reg2", M68KBSD_SIZEOF_FPREGS, &m68kbsd_fpregset, NULL, cb_data);
  100. }


  101. /* Signal trampolines.  */

  102. static void
  103. m68kobsd_sigtramp_cache_init (const struct tramp_frame *self,
  104.                               struct frame_info *this_frame,
  105.                               struct trad_frame_cache *this_cache,
  106.                               CORE_ADDR func)
  107. {
  108.   CORE_ADDR addr, base, pc;
  109.   int regnum;

  110.   base = get_frame_register_unsigned (this_frame, M68K_SP_REGNUM);

  111.   /* The 'addql #4,%sp' instruction at offset 8 adjusts the stack
  112.      pointer.  Adjust the frame base accordingly.  */
  113.   pc = get_frame_register_unsigned (this_frame, M68K_PC_REGNUM);
  114.   if ((pc - func) > 8)
  115.     base -= 4;

  116.   /* Get frame pointer, stack pointer, program counter and processor
  117.      state from `struct sigcontext'.  */
  118.   addr = get_frame_memory_unsigned (this_frame, base + 8, 4);
  119.   trad_frame_set_reg_addr (this_cache, M68K_FP_REGNUM, addr + 8);
  120.   trad_frame_set_reg_addr (this_cache, M68K_SP_REGNUM, addr + 12);
  121.   trad_frame_set_reg_addr (this_cache, M68K_PC_REGNUM, addr + 20);
  122.   trad_frame_set_reg_addr (this_cache, M68K_PS_REGNUM, addr + 24);

  123.   /* The sc_ap member of `struct sigcontext' points to additional
  124.      hardware state.  Here we find the missing registers.  */
  125.   addr = get_frame_memory_unsigned (this_frame, addr + 16, 4) + 4;
  126.   for (regnum = M68K_D0_REGNUM; regnum < M68K_FP_REGNUM; regnum++, addr += 4)
  127.     trad_frame_set_reg_addr (this_cache, regnum, addr);

  128.   /* Construct the frame ID using the function start.  */
  129.   trad_frame_set_id (this_cache, frame_id_build (base, func));
  130. }

  131. static const struct tramp_frame m68kobsd_sigtramp = {
  132.   SIGTRAMP_FRAME,
  133.   2,
  134.   {
  135.     { 0x206f, -1 }, { 0x000c, -1},        /* moveal %sp@(12),%a0 */
  136.     { 0x4e90, -1 },                        /* jsr %a0@ */
  137.     { 0x588f, -1 },                        /* addql #4,%sp */
  138.     { 0x4e41, -1 },                        /* trap #1 */
  139.     { 0x2f40, -1 }, { 0x0004, -1 },        /* moveal %d0,%sp@(4) */
  140.     { 0x7001, -1 },                        /* moveq #SYS_exit,%d0 */
  141.     { 0x4e40, -1 },                        /* trap #0 */
  142.     { TRAMP_SENTINEL_INSN, -1 }
  143.   },
  144.   m68kobsd_sigtramp_cache_init
  145. };


  146. static void
  147. m68kbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
  148. {
  149.   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  150.   tdep->jb_pc = 5;
  151.   tdep->jb_elt_size = 4;

  152.   set_gdbarch_decr_pc_after_break (gdbarch, 2);

  153.   set_gdbarch_iterate_over_regset_sections
  154.     (gdbarch, m68kbsd_iterate_over_regset_sections);
  155. }

  156. /* OpenBSD and NetBSD a.out.  */

  157. static void
  158. m68kbsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
  159. {
  160.   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  161.   m68kbsd_init_abi (info, gdbarch);

  162.   tdep->struct_return = reg_struct_return;

  163.   tramp_frame_prepend_unwinder (gdbarch, &m68kobsd_sigtramp);
  164. }

  165. /* NetBSD ELF.  */

  166. static void
  167. m68kbsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
  168. {
  169.   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  170.   m68kbsd_init_abi (info, gdbarch);

  171.   /* NetBSD ELF uses the SVR4 ABI.  */
  172.   m68k_svr4_init_abi (info, gdbarch);
  173.   tdep->struct_return = pcc_struct_return;

  174.   /* NetBSD ELF uses SVR4-style shared libraries.  */
  175.   set_solib_svr4_fetch_link_map_offsets
  176.     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
  177. }


  178. static enum gdb_osabi
  179. m68kbsd_aout_osabi_sniffer (bfd *abfd)
  180. {
  181.   if (strcmp (bfd_get_target (abfd), "a.out-m68k-netbsd") == 0
  182.       || strcmp (bfd_get_target (abfd), "a.out-m68k4k-netbsd") == 0)
  183.     return GDB_OSABI_NETBSD_AOUT;

  184.   return GDB_OSABI_UNKNOWN;
  185. }

  186. static enum gdb_osabi
  187. m68kbsd_core_osabi_sniffer (bfd *abfd)
  188. {
  189.   if (strcmp (bfd_get_target (abfd), "netbsd-core") == 0)
  190.     return GDB_OSABI_NETBSD_AOUT;

  191.   return GDB_OSABI_UNKNOWN;
  192. }


  193. /* Provide a prototype to silence -Wmissing-prototypes.  */
  194. void _initialize_m68kbsd_tdep (void);

  195. void
  196. _initialize_m68kbsd_tdep (void)
  197. {
  198.   gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_aout_flavour,
  199.                                   m68kbsd_aout_osabi_sniffer);

  200.   /* BFD doesn't set a flavour for NetBSD style a.out core files.  */
  201.   gdbarch_register_osabi_sniffer (bfd_arch_m68k, bfd_target_unknown_flavour,
  202.                                   m68kbsd_core_osabi_sniffer);

  203.   gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_AOUT,
  204.                           m68kbsd_aout_init_abi);
  205.   gdbarch_register_osabi (bfd_arch_m68k, 0, GDB_OSABI_NETBSD_ELF,
  206.                           m68kbsd_elf_init_abi);
  207. }