gdb/sparc64fbsd-tdep.c - gdb

Global variables defined

Functions defined

Macros defined

Source code

  1. /* Target-dependent code for FreeBSD/sparc64.

  2.    Copyright (C) 2003-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 "frame.h"
  16. #include "frame-unwind.h"
  17. #include "gdbcore.h"
  18. #include "osabi.h"
  19. #include "regcache.h"
  20. #include "regset.h"
  21. #include "target.h"
  22. #include "trad-frame.h"

  23. #include "sparc64-tdep.h"
  24. #include "fbsd-tdep.h"
  25. #include "solib-svr4.h"

  26. /* From <machine/reg.h>.  */
  27. const struct sparc_gregmap sparc64fbsd_gregmap =
  28. {
  29.   26 * 8,                        /* "tstate" */
  30.   25 * 8,                        /* %pc */
  31.   24 * 8,                        /* %npc */
  32.   28 * 8,                        /* %y */
  33.   16 * 8,                        /* %fprs */
  34.   -1,
  35.   1 * 8,                        /* %g1 */
  36.   -1,                                /* %l0 */
  37.   8                                /* sizeof (%y) */
  38. };


  39. static void
  40. sparc64fbsd_supply_gregset (const struct regset *regset,
  41.                             struct regcache *regcache,
  42.                             int regnum, const void *gregs, size_t len)
  43. {
  44.   sparc64_supply_gregset (&sparc64fbsd_gregmap, regcache, regnum, gregs);
  45. }

  46. static void
  47. sparc64fbsd_collect_gregset (const struct regset *regset,
  48.                              const struct regcache *regcache,
  49.                              int regnum, void *gregs, size_t len)
  50. {
  51.   sparc64_collect_gregset (&sparc64fbsd_gregmap, regcache, regnum, gregs);
  52. }

  53. static void
  54. sparc64fbsd_supply_fpregset (const struct regset *regset,
  55.                              struct regcache *regcache,
  56.                              int regnum, const void *fpregs, size_t len)
  57. {
  58.   sparc64_supply_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs);
  59. }

  60. static void
  61. sparc64fbsd_collect_fpregset (const struct regset *regset,
  62.                               const struct regcache *regcache,
  63.                               int regnum, void *fpregs, size_t len)
  64. {
  65.   sparc64_collect_fpregset (&sparc64_bsd_fpregmap, regcache, regnum, fpregs);
  66. }


  67. /* Signal trampolines.  */

  68. static int
  69. sparc64fbsd_pc_in_sigtramp (CORE_ADDR pc, const char *name)
  70. {
  71.   return (name && strcmp (name, "__sigtramp") == 0);
  72. }

  73. static struct sparc_frame_cache *
  74. sparc64fbsd_sigtramp_frame_cache (struct frame_info *this_frame,
  75.                                    void **this_cache)
  76. {
  77.   struct sparc_frame_cache *cache;
  78.   CORE_ADDR addr, mcontext_addr, sp;
  79.   LONGEST fprs;
  80.   int regnum;

  81.   if (*this_cache)
  82.     return *this_cache;

  83.   cache = sparc_frame_cache (this_frame, this_cache);
  84.   gdb_assert (cache == *this_cache);

  85.   cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);

  86.   /* The third argument is a pointer to an instance of `ucontext_t',
  87.      which has a member `uc_mcontext' that contains the saved
  88.      registers.  */
  89.   addr = get_frame_register_unsigned (this_frame, SPARC_O2_REGNUM);
  90.   mcontext_addr = addr + 64;

  91.   /* The following registers travel in the `mc_local' slots of
  92.      `mcontext_t'.  */
  93.   addr = mcontext_addr + 16 * 8;
  94.   cache->saved_regs[SPARC64_FPRS_REGNUM].addr = addr + 0 * 8;
  95.   cache->saved_regs[SPARC64_FSR_REGNUM].addr = addr + 1 * 8;

  96.   /* The following registers travel in the `mc_in' slots of
  97.      `mcontext_t'.  */
  98.   addr = mcontext_addr + 24 * 8;
  99.   cache->saved_regs[SPARC64_NPC_REGNUM].addr = addr + 0 * 8;
  100.   cache->saved_regs[SPARC64_PC_REGNUM].addr = addr + 1 * 8;
  101.   cache->saved_regs[SPARC64_STATE_REGNUM].addr = addr + 2 * 8;
  102.   cache->saved_regs[SPARC64_Y_REGNUM].addr = addr + 4 * 8;

  103.   /* The `global' and `out' registers travel in the `mc_global' and
  104.      `mc_out' slots of `mcontext_t', except for %g0.  Since %g0 is
  105.      always zero, keep the identity encoding.  */
  106.   for (regnum = SPARC_G1_REGNUM, addr = mcontext_addr + 8;
  107.        regnum <= SPARC_O7_REGNUM; regnum++, addr += 8)
  108.     cache->saved_regs[regnum].addr = addr;

  109.   /* The `local' and `in' registers have been saved in the register
  110.      save area.  */
  111.   addr = cache->saved_regs[SPARC_SP_REGNUM].addr;
  112.   sp = get_frame_memory_unsigned (this_frame, addr, 8);
  113.   for (regnum = SPARC_L0_REGNUM, addr = sp + BIAS;
  114.        regnum <= SPARC_I7_REGNUM; regnum++, addr += 8)
  115.     cache->saved_regs[regnum].addr = addr;

  116.   /* The floating-point registers are only saved if the FEF bit in
  117.      %fprs has been set.  */

  118. #define FPRS_FEF        (1 << 2)

  119.   addr = cache->saved_regs[SPARC64_FPRS_REGNUM].addr;
  120.   fprs = get_frame_memory_unsigned (this_frame, addr, 8);
  121.   if (fprs & FPRS_FEF)
  122.     {
  123.       for (regnum = SPARC_F0_REGNUM, addr = mcontext_addr + 32 * 8;
  124.            regnum <= SPARC_F31_REGNUM; regnum++, addr += 4)
  125.         cache->saved_regs[regnum].addr = addr;

  126.       for (regnum = SPARC64_F32_REGNUM;
  127.            regnum <= SPARC64_F62_REGNUM; regnum++, addr += 8)
  128.         cache->saved_regs[regnum].addr = addr;
  129.     }

  130.   return cache;
  131. }

  132. static void
  133. sparc64fbsd_sigtramp_frame_this_id (struct frame_info *this_frame,
  134.                                     void **this_cache,
  135.                                     struct frame_id *this_id)
  136. {
  137.   struct sparc_frame_cache *cache =
  138.     sparc64fbsd_sigtramp_frame_cache (this_frame, this_cache);

  139.   (*this_id) = frame_id_build (cache->base, cache->pc);
  140. }

  141. static struct value *
  142. sparc64fbsd_sigtramp_frame_prev_register (struct frame_info *this_frame,
  143.                                           void **this_cache, int regnum)
  144. {
  145.   struct sparc_frame_cache *cache =
  146.     sparc64fbsd_sigtramp_frame_cache (this_frame, this_cache);

  147.   return trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
  148. }

  149. static int
  150. sparc64fbsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
  151.                                     struct frame_info *this_frame,
  152.                                     void **this_cache)
  153. {
  154.   CORE_ADDR pc = get_frame_pc (this_frame);
  155.   const char *name;

  156.   find_pc_partial_function (pc, &name, NULL, NULL);
  157.   if (sparc64fbsd_pc_in_sigtramp (pc, name))
  158.     return 1;

  159.   return 0;
  160. }

  161. static const struct frame_unwind sparc64fbsd_sigtramp_frame_unwind =
  162. {
  163.   SIGTRAMP_FRAME,
  164.   default_frame_unwind_stop_reason,
  165.   sparc64fbsd_sigtramp_frame_this_id,
  166.   sparc64fbsd_sigtramp_frame_prev_register,
  167.   NULL,
  168.   sparc64fbsd_sigtramp_frame_sniffer
  169. };


  170. static const struct regset sparc64fbsd_gregset =
  171.   {
  172.     NULL, sparc64fbsd_supply_gregset, sparc64fbsd_collect_gregset
  173.   };

  174. static const struct regset sparc64fbsd_fpregset =
  175.   {
  176.     NULL, sparc64fbsd_supply_fpregset, sparc64fbsd_collect_fpregset
  177.   };

  178. static void
  179. sparc64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
  180. {
  181.   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  182.   /* Generic FreeBSD support. */
  183.   fbsd_init_abi (info, gdbarch);

  184.   tdep->gregset = &sparc64fbsd_gregset;
  185.   tdep->sizeof_gregset = 256;

  186.   tdep->fpregset = &sparc64fbsd_fpregset;
  187.   tdep->sizeof_fpregset = 272;

  188.   frame_unwind_append_unwinder (gdbarch, &sparc64fbsd_sigtramp_frame_unwind);

  189.   sparc64_init_abi (info, gdbarch);

  190.   /* FreeBSD/sparc64 has SVR4-style shared libraries.  */
  191.   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
  192.   set_solib_svr4_fetch_link_map_offsets
  193.     (gdbarch, svr4_lp64_fetch_link_map_offsets);
  194. }

  195. /* Provide a prototype to silence -Wmissing-prototypes.  */
  196. void _initialize_sparc64fbsd_tdep (void);

  197. void
  198. _initialize_sparc64fbsd_tdep (void)
  199. {
  200.   gdbarch_register_osabi (bfd_arch_sparc, bfd_mach_sparc_v9,
  201.                           GDB_OSABI_FREEBSD_ELF, sparc64fbsd_init_abi);
  202. }