This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH]: Fix syscall restart handling on sparc*-linux


I've just added a change to the Linux kernel so that gdb can cancel
system call restarting just like powerpc and x86 do under Linux.

I've done this by adding a piece of software state, a single bit, into
the processor state register provided to the debugger, that was
otherwise totally unused before.

The write_pc target method simply clears the bit, which does nothing
on previous kernels, but cancels syscall restart on newer kernels.

This fixes 40 or so testsuite failures.

Ok to commit?

2008-05-11  David S. Miller  <davem@davemloft.net>

	* sparc-linux-tdep.c (sparc_linux_write_pc): New.
	(sparc32_linux_init_abi): Register it.
	* sparc64-linux-tdep.c (sparc64_linux_write_pc): New.
	(sparc64_linux_init_abi): Register it.

Index: gdb/sparc-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sparc-linux-tdep.c,v
retrieving revision 1.26
diff -u -r1.26 sparc-linux-tdep.c
--- gdb/sparc-linux-tdep.c	11 May 2008 20:03:25 -0000	1.26
+++ gdb/sparc-linux-tdep.c	11 May 2008 20:12:11 -0000
@@ -211,6 +211,30 @@
   sparc32_collect_fpregset (regcache, regnum, fpregs);
 }
 
+/* Set the program counter for process PTID to PC.  */
+
+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 &= ~0x000004000;
+  regcache_cooked_write_unsigned (regcache, SPARC32_PSR_REGNUM, psr);
+}
+
 
 
 static void
@@ -251,6 +275,8 @@
 
   /* 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: gdb/sparc64-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/sparc64-linux-tdep.c,v
retrieving revision 1.20
diff -u -r1.20 sparc64-linux-tdep.c
--- gdb/sparc64-linux-tdep.c	11 May 2008 20:03:26 -0000	1.20
+++ gdb/sparc64-linux-tdep.c	11 May 2008 20:12:11 -0000
@@ -174,6 +174,30 @@
   sparc64_collect_fpregset (regcache, regnum, fpregs);
 }
 
+/* Set the program counter for process PTID to PC.  */
+
+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 &= ~((ULONGEST)0x20);
+  regcache_cooked_write_unsigned (regcache, SPARC64_STATE_REGNUM, state);
+}
+
 
 
 static void
@@ -211,6 +235,8 @@
 
   /* 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);
 }
 
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]