From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6446 invoked by alias); 11 May 2008 20:19:21 -0000 Received: (qmail 6438 invoked by uid 22791); 11 May 2008 20:19:20 -0000 X-Spam-Check-By: sourceware.org Received: from 74-93-104-97-Washington.hfc.comcastbusiness.net (HELO sunset.davemloft.net) (74.93.104.97) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sun, 11 May 2008 20:18:57 +0000 Received: from localhost (localhost [127.0.0.1]) by sunset.davemloft.net (Postfix) with ESMTP id 9B174C8C2D6; Sun, 11 May 2008 13:18:50 -0700 (PDT) Date: Sun, 11 May 2008 22:03:00 -0000 Message-Id: <20080511.131850.175173142.davem@davemloft.net> To: gdb-patches@sourceware.org CC: roland@redhat.com Subject: [PATCH]: Fix syscall restart handling on sparc*-linux From: David Miller X-Mailer: Mew version 5.2 on Emacs 22.1 / Mule 5.0 (SAKAKI) Mime-Version: 1.0 Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2008-05/txt/msg00364.txt.bz2 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 * 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); }