* sparc-tdep.h (struct gdbarch_tdep): Add step_trap member.
authorMark Kettenis <kettenis@gnu.org>
Sun, 22 Jan 2006 20:07:38 +0000 (20:07 +0000)
committerMark Kettenis <kettenis@gnu.org>
Sun, 22 Jan 2006 20:07:38 +0000 (20:07 +0000)
(sparc_address_from_register): New prototype.
(sparcnbsd_step_trap): New prototype.
* sparc-tdep.c (sparc_address_from_register): Make globally
visible.
(sparc_analyze_control_transfer): Change prototype to accept
`struct gdbarch *' as first argument.  Allow for optional hnadling
for trap instructions.
(sparc_step_trap): New function.
(sparc_software_single_step): Adjust call to
sparc_analyze_control_trabsfer.
(sparc32_gdbarch_init): Initialize TDEP->step_trap.
* sparcnbsd-tdep.c (sparcnbsd_step_trap): New function.
(sparc32nbsd_init_abi): Set TDEP->step_trap.
* sparc64obsd-tdep.c (sparc64obsd_init_abi): Set TDEP->step_trap.
* sparc64nbsd-tdep.c (sparc64nbsd_init_abi): Set TDEP->step_trap.

gdb/ChangeLog
gdb/sparc-tdep.c
gdb/sparc-tdep.h
gdb/sparc64nbsd-tdep.c
gdb/sparc64obsd-tdep.c
gdb/sparcnbsd-tdep.c

index 94ad4e7e65f1aee34d252e7ba1452bd825c0f0f5..830d4a9434b2ba5f1bfaf465b92ce4c101ba4c3f 100644 (file)
@@ -1,5 +1,22 @@
 2006-01-22  Mark Kettenis  <kettenis@gnu.org>
 
+       * sparc-tdep.h (struct gdbarch_tdep): Add step_trap member.
+       (sparc_address_from_register): New prototype.
+       (sparcnbsd_step_trap): New prototype.
+       * sparc-tdep.c (sparc_address_from_register): Make globally
+       visible.
+       (sparc_analyze_control_transfer): Change prototype to accept
+       `struct gdbarch *' as first argument.  Allow for optional hnadling
+       for trap instructions.
+       (sparc_step_trap): New function.
+       (sparc_software_single_step): Adjust call to
+       sparc_analyze_control_trabsfer.
+       (sparc32_gdbarch_init): Initialize TDEP->step_trap.
+       * sparcnbsd-tdep.c (sparcnbsd_step_trap): New function.
+       (sparc32nbsd_init_abi): Set TDEP->step_trap.
+       * sparc64obsd-tdep.c (sparc64obsd_init_abi): Set TDEP->step_trap.
+       * sparc64nbsd-tdep.c (sparc64nbsd_init_abi): Set TDEP->step_trap.
+
        * sparc-tdep.c (sparc32_return_value): Convert to use
        RETURN_VALUE_ABI_PRESERVES_ADDRESS instead of
        RETURN_VALUE_STRUCT_CONVENTION.
index ab9f1044c10caa183a6b64bf115742fcd9e74e2f..dc6c5347a55de2dd527404366251d5501de5e5c9 100644 (file)
@@ -170,7 +170,7 @@ sparc_fetch_wcookie (void)
 
 /* Return the contents if register REGNUM as an address.  */
 
-static CORE_ADDR
+CORE_ADDR
 sparc_address_from_register (int regnum)
 {
   ULONGEST addr;
@@ -1000,7 +1000,8 @@ sparc32_stabs_argument_has_addr (struct gdbarch *gdbarch, struct type *type)
    software single-step mechanism.  */
 
 static CORE_ADDR
-sparc_analyze_control_transfer (CORE_ADDR pc, CORE_ADDR *npc)
+sparc_analyze_control_transfer (struct gdbarch *arch,
+                               CORE_ADDR pc, CORE_ADDR *npc)
 {
   unsigned long insn = sparc_fetch_instruction (pc);
   int conditional_p = X_COND (insn) & 0x7;
@@ -1038,11 +1039,14 @@ sparc_analyze_control_transfer (CORE_ADDR pc, CORE_ADDR *npc)
       branch_p = 1;
       offset = 4 * X_DISP19 (insn);
     }
+  else if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3a)
+    {
+      /* Trap instruction (TRAP).  */
+      return gdbarch_tdep (arch)->step_trap (insn);
+    }
 
   /* FIXME: Handle DONE and RETRY instructions.  */
 
-  /* FIXME: Handle the Trap instruction.  */
-
   if (branch_p)
     {
       if (conditional_p)
@@ -1070,10 +1074,17 @@ sparc_analyze_control_transfer (CORE_ADDR pc, CORE_ADDR *npc)
   return 0;
 }
 
+static CORE_ADDR
+sparc_step_trap (unsigned long insn)
+{
+  return 0;
+}
+
 void
 sparc_software_single_step (enum target_signal sig, int insert_breakpoints_p)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  struct gdbarch *arch = current_gdbarch;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
   static CORE_ADDR npc, nnpc;
   static gdb_byte npc_save[4], nnpc_save[4];
 
@@ -1085,7 +1096,7 @@ sparc_software_single_step (enum target_signal sig, int insert_breakpoints_p)
       orig_npc = npc = sparc_address_from_register (tdep->npc_regnum);
 
       /* Analyze the instruction at PC.  */
-      nnpc = sparc_analyze_control_transfer (pc, &npc);
+      nnpc = sparc_analyze_control_transfer (arch, pc, &npc);
       if (npc != 0)
        target_insert_breakpoint (npc, npc_save);
       if (nnpc != 0)
@@ -1188,6 +1199,7 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->fpregset = NULL;
   tdep->sizeof_fpregset = 0;
   tdep->plt_entry_size = 0;
+  tdep->step_trap = sparc_step_trap;
 
   set_gdbarch_long_double_bit (gdbarch, 128);
   set_gdbarch_long_double_format (gdbarch, &floatformat_sparc_quad);
index 502b5244bdb374b69779ff9508b59b960b46c862..06555e9b89b92ad4ecc5cfa17944351d6be7b958 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for SPARC.
 
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -65,6 +65,9 @@ struct gdbarch_tdep
   /* Size of an Procedure Linkage Table (PLT) entry, 0 if we shouldn't
      treat the PLT special when doing prologue analysis.  */
   size_t plt_entry_size;
+
+  /* Alternative location for trap return.  Used for single-stepping.  */
+  CORE_ADDR (*step_trap) (unsigned long insn);
 };
 
 /* Register numbers of various important registers.  */
@@ -147,6 +150,9 @@ struct sparc_frame_cache
 /* Fetch the instruction at PC.  */
 extern unsigned long sparc_fetch_instruction (CORE_ADDR pc);
 
+/* Return the contents if register REGNUM as an address.  */
+extern CORE_ADDR sparc_address_from_register (int regnum);
+
 /* Fetch StackGhost Per-Process XOR cookie.  */
 extern ULONGEST sparc_fetch_wcookie (void);
 
@@ -198,6 +204,10 @@ extern void sparc32_sol2_init_abi (struct gdbarch_info info,
 /* Register offsets for NetBSD.  */
 extern const struct sparc_gregset sparc32nbsd_gregset;
 
+/* Return the address of a system call's alternative return
+   address.  */
+extern CORE_ADDR sparcnbsd_step_trap (unsigned long insn);
+
 extern void sparc32nbsd_elf_init_abi (struct gdbarch_info info,
                                      struct gdbarch *gdbarch);
 
index 22bafcbfa9b1e1e84993922a2055683000f5ea6d..5c7ef16844942784b5675f25b2915d15c43ee435 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for NetBSD/sparc64.
 
-   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
    Based on code contributed by Wasabi Systems, Inc.
 
    This file is part of GDB.
@@ -249,6 +249,9 @@ sparc64nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->fpregset = regset_alloc (gdbarch, sparc64nbsd_supply_fpregset, NULL);
   tdep->sizeof_fpregset = 272;
 
+  /* Make sure we can single-step "new" syscalls.  */
+  tdep->step_trap = sparcnbsd_step_trap;
+
   frame_unwind_append_sniffer (gdbarch, sparc64nbsd_sigtramp_frame_sniffer);
 
   sparc64_init_abi (info, gdbarch);
index bc21df282cf18fc034bbdde9e18197dfdfbb1250..d2e10fdf0679128f8c776307667690ece769adb4 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for OpenBSD/sparc64.
 
-   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -295,6 +295,9 @@ sparc64obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->gregset = regset_alloc (gdbarch, sparc64obsd_supply_gregset, NULL);
   tdep->sizeof_gregset = 832;
 
+  /* Make sure we can single-step "new" syscalls.  */
+  tdep->step_trap = sparcnbsd_step_trap;
+
   frame_unwind_append_sniffer (gdbarch, sparc64obsd_sigtramp_frame_sniffer);
 
   sparc64_init_abi (info, gdbarch);
index 6862bdce3c308f70a63c8d3bd111e6d4b326e20f..73dee1409b9b34aa97b5b332e82b5fcd0e85293e 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for NetBSD/sparc.
 
-   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
    Contributed by Wasabi Systems, Inc.
 
    This file is part of GDB.
 #include "sparc-tdep.h"
 #include "nbsd-tdep.h"
 
+/* Macros to extract fields from SPARC instructions.  */
+#define X_RS1(i) (((i) >> 14) & 0x1f)
+#define X_RS2(i) ((i) & 0x1f)
+#define X_I(i) (((i) >> 13) & 1)
+
 const struct sparc_gregset sparc32nbsd_gregset =
 {
   0 * 4,                       /* %psr */
@@ -256,6 +261,30 @@ sparc32nbsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
   return NULL;
 }
 \f
+/* Return the address of a system call's alternative return
+   address.  */
+
+CORE_ADDR
+sparcnbsd_step_trap (unsigned long insn)
+{
+  if ((X_I (insn) == 0 && X_RS1 (insn) == 0 && X_RS2 (insn) == 0)
+      || (X_I (insn) == 1 && X_RS1 (insn) == 0 && (insn & 0x7f) == 0))
+    {
+      /* "New" system call.  */
+      ULONGEST number;
+
+      regcache_cooked_read_unsigned (current_regcache,
+                                    SPARC_G1_REGNUM, &number);
+
+      if (number & 0x400)
+       return sparc_address_from_register (SPARC_G2_REGNUM);
+      if (number & 0x800)
+       return sparc_address_from_register (SPARC_G7_REGNUM);
+    }
+
+  return 0;
+}
+\f
 
 static void
 sparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
@@ -272,6 +301,9 @@ sparc32nbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->fpregset = regset_alloc (gdbarch, sparc32nbsd_supply_fpregset, NULL);
   tdep->sizeof_fpregset = 33 * 4;
 
+  /* Make sure we can single-step "new" syscalls.  */
+  tdep->step_trap = sparcnbsd_step_trap;
+
   frame_unwind_append_sniffer (gdbarch, sparc32nbsd_sigtramp_frame_sniffer);
 }