This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH]: Fix syscall restart handling on sparc*-linux
- From: David Miller <davem at davemloft dot net>
- To: gdb-patches at sourceware dot org
- Cc: roland at redhat dot com
- Date: Sun, 11 May 2008 13:18:50 -0700 (PDT)
- Subject: [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);
}