* sparc-linux-tdep.c (PSR_SYSCALL): Define.
authorDavid S. Miller <davem@redhat.com>
Sun, 11 May 2008 22:10:30 +0000 (22:10 +0000)
committerDavid S. Miller <davem@redhat.com>
Sun, 11 May 2008 22:10:30 +0000 (22:10 +0000)
(sparc_linux_write_pc): New function.
(sparc32_linux_init_abi): Register it.
* sparc64-linux-tdep.c (TSTATE_SYSCALL): Define.
(sparc64_linux_write_pc): New function.
(sparc64_linux_init_abi): Register it.

gdb/ChangeLog
gdb/sparc-linux-tdep.c
gdb/sparc64-linux-tdep.c

index ab2dc68216dcee5aa78072d889fe4dd2c7706dd8..0a253595beb2dbbd65b4f192e49e8637edc9bb66 100644 (file)
@@ -1,5 +1,12 @@
 2008-05-11  David S. Miller  <davem@davemloft.net>
 
+       * sparc-linux-tdep.c (PSR_SYSCALL): Define.
+       (sparc_linux_write_pc): New function.
+       (sparc32_linux_init_abi): Register it.
+       * sparc64-linux-tdep.c (TSTATE_SYSCALL): Define.
+       (sparc64_linux_write_pc): New function.
+       (sparc64_linux_init_abi): Register it.
+
        * sparc-linux-tdep.c, sparc64-linux-tdep.c: Use
        dwarf2_append_unwinders(), not dwarf2_frame_sniffer.
 
index 83d7589d1fe12ec0f145fadabd7f93e310621736..c619ab1106bb709980d20ebb8f83a620443b3132 100644 (file)
@@ -211,6 +211,32 @@ sparc32_linux_collect_core_fpregset (const struct regset *regset,
   sparc32_collect_fpregset (regcache, regnum, fpregs);
 }
 
+/* Set the program counter for process PTID to PC.  */
+
+#define PSR_SYSCALL    0x00004000
+
+static void
+sparc_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+  ULONGEST psr;
+
+  regcache_cooked_write_unsigned (regcache, tdep->pc_regnum, pc);
+  regcache_cooked_write_unsigned (regcache, tdep->npc_regnum, pc + 4);
+
+  /* Clear the "in syscall" bit to prevent the kernel from
+     messing with the PCs we just installed, if we happen to be
+     within an interrupted system call that the kernel wants to
+     restart.
+
+     Note that after we return from the dummy call, the PSR et al.
+     registers will be automatically restored, and the kernel
+     continues to restart the system call at this point.  */
+  regcache_cooked_read_unsigned (regcache, SPARC32_PSR_REGNUM, &psr);
+  psr &= ~PSR_SYSCALL;
+  regcache_cooked_write_unsigned (regcache, SPARC32_PSR_REGNUM, psr);
+}
+
 \f
 
 static void
@@ -251,6 +277,8 @@ sparc32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   /* Hook in the DWARF CFI frame unwinder.  */
   dwarf2_append_unwinders (gdbarch);
+
+  set_gdbarch_write_pc (gdbarch, sparc_linux_write_pc);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
index 9f752b38dbb4285dbb22c8cd8dabaae201b124da..05218e117c909425300ed06f5034ad29c998e339 100644 (file)
@@ -174,6 +174,32 @@ sparc64_linux_collect_core_fpregset (const struct regset *regset,
   sparc64_collect_fpregset (regcache, regnum, fpregs);
 }
 
+/* Set the program counter for process PTID to PC.  */
+
+#define TSTATE_SYSCALL 0x0000000000000020ULL
+
+static void
+sparc64_linux_write_pc (struct regcache *regcache, CORE_ADDR pc)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+  ULONGEST state;
+
+  regcache_cooked_write_unsigned (regcache, tdep->pc_regnum, pc);
+  regcache_cooked_write_unsigned (regcache, tdep->npc_regnum, pc + 4);
+
+  /* Clear the "in syscall" bit to prevent the kernel from
+     messing with the PCs we just installed, if we happen to be
+     within an interrupted system call that the kernel wants to
+     restart.
+
+     Note that after we return from the dummy call, the TSTATE et al.
+     registers will be automatically restored, and the kernel
+     continues to restart the system call at this point.  */
+  regcache_cooked_read_unsigned (regcache, SPARC64_STATE_REGNUM, &state);
+  state &= ~TSTATE_SYSCALL;
+  regcache_cooked_write_unsigned (regcache, SPARC64_STATE_REGNUM, state);
+}
+
 \f
 
 static void
@@ -211,6 +237,8 @@ sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   /* Make sure we can single-step over signal return system calls.  */
   tdep->step_trap = sparc64_linux_step_trap;
+
+  set_gdbarch_write_pc (gdbarch, sparc64_linux_write_pc);
 }
 \f