]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
* sparc64fbsd-tdep.c: Include "frame.h", "frame-unwind.h",
authorMark Kettenis <kettenis@gnu.org>
Fri, 26 Dec 2003 23:19:56 +0000 (23:19 +0000)
committerMark Kettenis <kettenis@gnu.org>
Fri, 26 Dec 2003 23:19:56 +0000 (23:19 +0000)
"trad-frame.h" and "gdb_assert.h".
(BIAS): New define.
(sparc64fbsd_pc_in_sigtramp, sparc64fbsd_sigtramp_frame_cache)
(sparc64fbsd_sigtramp_frame_this_id)
(sparc64fbsd_sigtramp_frame_prev_register): New functions.
(sparc64fbsd_sigtramp_frame_unwind): New variable.
(sparc64fbsd_sigtramp_frame_sniffer): New function.
(sparc64fbsd_init_abi): Set pc_in_sigtramp, append
sparc64fbsd_sigtramp_frame_sniffer.

gdb/ChangeLog
gdb/sparc64fbsd-tdep.c

index 78f3c4608a52411a8a8d17be8d196199e3d8c80f..27dfb9e1d569e37afd6f57eeeca267566abaaf2f 100644 (file)
@@ -1,3 +1,16 @@
+2003-12-27  Mark Kettenis  <kettenis@gnu.org>
+
+       * sparc64fbsd-tdep.c: Include "frame.h", "frame-unwind.h",
+       "trad-frame.h" and "gdb_assert.h".
+       (BIAS): New define.
+       (sparc64fbsd_pc_in_sigtramp, sparc64fbsd_sigtramp_frame_cache)
+       (sparc64fbsd_sigtramp_frame_this_id)
+       (sparc64fbsd_sigtramp_frame_prev_register): New functions.
+       (sparc64fbsd_sigtramp_frame_unwind): New variable.
+       (sparc64fbsd_sigtramp_frame_sniffer): New function.
+       (sparc64fbsd_init_abi): Set pc_in_sigtramp, append
+       sparc64fbsd_sigtramp_frame_sniffer.
+
 2003-12-26  Mark Kettenis  <kettenis@gnu.org>
 
        * sparcbsd-nat.c: Remove file.
index 6c1e0d978337e5c7b4280ae30d3866097812268b..d6c3cd64fc2e28407c7955365841aac69cc0409c 100644 (file)
    Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
+#include "frame.h"
+#include "frame-unwind.h"
 #include "gdbcore.h"
 #include "osabi.h"
 #include "regcache.h"
 #include "target.h"
+#include "trad-frame.h"
 
+#include "gdb_assert.h"
 #include "gdb_string.h"
 
 #include "sparc64-tdep.h"
 
+/* The stack pointer is offset from the stack frame by a BIAS of 2047
+   (0x7ff) for 64-bit code.  BIAS is likely to be defined on SPARC
+   hosts, so undefine it first.  */
+#undef BIAS
+#define BIAS 2047
+
 /* From <machine/reg.h>.  */
 const struct sparc_gregset sparc64fbsd_gregset =
 {
@@ -85,9 +95,140 @@ static struct core_fns sparc64fbsd_core_fns =
 };
 \f
 
+/* Signal trampolines.  */
+
+static int
+sparc64fbsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
+{
+  return (name && strcmp (name, "__sigtramp") == 0);
+}
+
+static struct sparc_frame_cache *
+sparc64fbsd_sigtramp_frame_cache (struct frame_info *next_frame,
+                                  void **this_cache)
+{
+  struct sparc_frame_cache *cache;
+  CORE_ADDR addr, mcontext_addr, sp;
+  LONGEST fprs;
+  int regnum;
+
+  if (*this_cache)
+    return *this_cache;
+
+  cache = sparc_frame_cache (next_frame, this_cache);
+  gdb_assert (cache == *this_cache);
+
+  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+
+  /* The third argument is a pointer to an instance of `ucontext_t',
+     which has a member `uc_mcontext' that contains the saved
+     registers.  */
+  addr = frame_unwind_register_unsigned (next_frame, SPARC_O2_REGNUM);
+  mcontext_addr = addr + 64;
+
+  /* The following registers travel in the `mc_local' slots of
+     `mcontext_t'.  */
+  addr = mcontext_addr + 16 * 8;
+  cache->saved_regs[SPARC64_FPRS_REGNUM].addr = addr + 0 * 8;
+  cache->saved_regs[SPARC64_FSR_REGNUM].addr = addr + 1 * 8;
+
+  /* The following registers travel in the `mc_in' slots of
+     `mcontext_t'.  */
+  addr = mcontext_addr + 24 * 8;
+  cache->saved_regs[SPARC64_NPC_REGNUM].addr = addr + 0 * 8;
+  cache->saved_regs[SPARC64_PC_REGNUM].addr = addr + 1 * 8;
+  cache->saved_regs[SPARC64_STATE_REGNUM].addr = addr + 2 * 8;
+  cache->saved_regs[SPARC64_Y_REGNUM].addr = addr + 4 * 8;
+
+  /* The `global' and `out' registers travel in the `mc_global' and
+     `mc_out' slots of `mcontext_t', except for %g0.  Since %g0 is
+     always zero, keep the identity encoding.  */
+  for (regnum = SPARC_G1_REGNUM, addr = mcontext_addr + 8;
+       regnum <= SPARC_O7_REGNUM; regnum++, addr += 8)
+    cache->saved_regs[regnum].addr = addr;
+
+  /* The `local' and `in' registers have been saved in the register
+     save areas.  */
+  addr = cache->saved_regs[SPARC_SP_REGNUM].addr;
+  sp = get_frame_memory_unsigned (next_frame, addr, 8);
+  for (regnum = SPARC_L0_REGNUM, addr = sp + BIAS;
+       regnum <= SPARC_I7_REGNUM; regnum++, addr += 8)
+    cache->saved_regs[regnum].addr = addr;
+
+  /* The floating-point registers are only saved if the FEF bit in
+     %fprs has been set.  */
+
+#define FPRS_FEF       (1 << 2)
+
+  addr = cache->saved_regs[SPARC64_FPRS_REGNUM].addr;
+  fprs = get_frame_memory_unsigned (next_frame, addr, 8);
+  if (fprs & (1 << 2))
+    {
+      for (regnum = SPARC_F0_REGNUM, addr = mcontext_addr + 32 * 8;
+          regnum <= SPARC_F31_REGNUM; regnum++, addr += 4)
+       cache->saved_regs[regnum].addr = addr;
+
+      for (regnum = SPARC64_F32_REGNUM;
+          regnum <= SPARC64_F62_REGNUM; regnum++, addr += 8)
+       cache->saved_regs[regnum].addr = addr;
+    }
+
+  return cache;
+}
+
+static void
+sparc64fbsd_sigtramp_frame_this_id (struct frame_info *next_frame,
+                                   void **this_cache,
+                                   struct frame_id *this_id)
+{
+  struct sparc_frame_cache *cache =
+    sparc64fbsd_sigtramp_frame_cache (next_frame, this_cache);
+
+  (*this_id) = frame_id_build (cache->base, cache->pc);
+}
+
+static void
+sparc64fbsd_sigtramp_frame_prev_register (struct frame_info *next_frame,
+                                         void **this_cache,
+                                         int regnum, int *optimizedp,
+                                         enum lval_type *lvalp,
+                                         CORE_ADDR *addrp,
+                                         int *realnump, void *valuep)
+{
+  struct sparc_frame_cache *cache =
+    sparc64fbsd_sigtramp_frame_cache (next_frame, this_cache);
+
+  trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
+                           optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind sparc64fbsd_sigtramp_frame_unwind =
+{
+  SIGTRAMP_FRAME,
+  sparc64fbsd_sigtramp_frame_this_id,
+  sparc64fbsd_sigtramp_frame_prev_register
+};
+
+static const struct frame_unwind *
+sparc64fbsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
+{
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  char *name;
+
+  find_pc_partial_function (pc, &name, NULL, NULL);
+  if (sparc64fbsd_pc_in_sigtramp (pc, name))
+    return &sparc64fbsd_sigtramp_frame_unwind;
+
+  return NULL;
+}
+\f
+
 static void
 sparc64fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
+  set_gdbarch_pc_in_sigtramp (gdbarch, sparc64fbsd_pc_in_sigtramp);
+  frame_unwind_append_sniffer (gdbarch, sparc64fbsd_sigtramp_frame_sniffer);
+
   sparc64_init_abi (info, gdbarch);
 }