From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5240 invoked by alias); 31 Dec 2003 20:19:25 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 5108 invoked from network); 31 Dec 2003 20:19:22 -0000 Received: from unknown (HELO palrel11.hp.com) (156.153.255.246) by sources.redhat.com with SMTP; 31 Dec 2003 20:19:22 -0000 Received: from hplms2.hpl.hp.com (hplms2.hpl.hp.com [15.0.152.33]) by palrel11.hp.com (Postfix) with ESMTP id 55B711C01D2B; Wed, 31 Dec 2003 12:19:22 -0800 (PST) Received: from napali.hpl.hp.com (napali.hpl.hp.com [15.4.89.123]) by hplms2.hpl.hp.com (8.12.10/8.12.10/HPL-PA Hub) with ESMTP id hBVKJLwf000749; Wed, 31 Dec 2003 12:19:21 -0800 (PST) Received: from napali.hpl.hp.com (napali [127.0.0.1]) by napali.hpl.hp.com (8.12.9/8.12.9/Debian-5) with ESMTP id hBVKJLVR027262; Wed, 31 Dec 2003 12:19:21 -0800 Received: (from davidm@localhost) by napali.hpl.hp.com (8.12.9/8.12.9/Debian-5) id hBVKJKa8027258; Wed, 31 Dec 2003 12:19:20 -0800 From: David Mosberger MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <16371.12104.503371.251351@napali.hpl.hp.com> Date: Wed, 31 Dec 2003 20:19:00 -0000 To: Kevin Buettner , jjohnstn@redhat.com, ac131313@redhat.com, bjorn_helgaas@hp.com Cc: gdb-patches@sources.redhat.com, davidm@hpl.hp.com, linux-ia64@vger.kernel.org Subject: make inferior calls work on ia64 even when syscall is pending In-Reply-To: <1031213040137.ZM23568@localhost.localdomain> Reply-To: davidm@hpl.hp.com X-URL: http://www.hpl.hp.com/personal/David_Mosberger/ X-SW-Source: 2003-12/txt/msg00539.txt.bz2 Problem: $ cat t.c int main () { char ch; return read(0, &ch, 1); } $ gcc -g t.c $ gdb a.out GNU gdb 6.0-debian Copyright 2003 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "ia64-linux"... (gdb) r Starting program: /home/davidm/tmp/a.out [user hits Ctrl-C] Program received signal SIGINT, Interrupt. 0x20000000001cc401 in read () from /lib/tls/libc.so.6.1 (gdb) call write(1, "hello\n", 6) Program received signal SIGSEGV, Segmentation fault. 0x2000000000020650 in __libc_memalign () from /lib/ld-linux-ia64.so.2 The program being debugged was signaled while in a function called from GDB. GDB remains in the frame where the signal was received. To change this behavior use "set unwindonsignal on" Evaluation of the expression containing the function (malloc) will be abandoned. (gdb) The attached patch below fixes this problem. It took me a while to understand what's going on, but in retrospect, the situation is completely analogous to x86 linux: when interrupting execution in a restartable syscall, gdb needs to cancel restarting of the syscall before it can run an inferior call. Otherwise, instead of executing at the desired IP, we'll end up calling IP-1 (in my test-case, this ended up calling into the tail of memalign, when the intended target was malloc() to allocate memory for the string "hello\n"...). The fix is for gdb to clear r10 when changing the IP. This will ensure that the kernel won't treat the value in r8 as an error-code and effectively cancels the system-call restart. It turns out that the kernel also needs a small patch, because it currently checks r10 _before_ waking up the debugger, so that there was no way for the debugger to cancel system-call restart. See this patch: http://lia64.bkbits.net:8080/to-linus-2.5/patch@1.1513 (Bjorn, this is also needed for Linux v2.4.) With both the kernel and gdb fixed, I see four new passes in the GDB test-suite: +PASS: gdb.base/interrupt.exp: call function when asleep +PASS: gdb.base/interrupt.exp: call function a second time +PASS: gdb.base/interrupt.exp: continue +PASS: gdb.base/interrupt.exp: send end of file === gdb Summary === -# of expected passes 9928 +# of expected passes 9932 # of unexpected failures 119 # of unexpected successes 4 # of expected failures 58 If the gdb patch looks OK, please check it in. Thanks! --david 2003-12-31 David Mosberger * ia64-tdep.c (ia64_write_pc): Clear r10 after writing the instruction-pointer (PC) to prevent the kernel from attempting to restart an interrupt system call. Index: ia64-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/ia64-tdep.c,v retrieving revision 1.106 diff -u -r1.106 ia64-tdep.c --- ia64-tdep.c 13 Dec 2003 03:51:56 -0000 1.106 +++ ia64-tdep.c 31 Dec 2003 19:49:49 -0000 @@ -683,6 +683,17 @@ write_register_pid (IA64_PSR_REGNUM, psr_value, ptid); write_register_pid (IA64_IP_REGNUM, new_pc, ptid); + + /* We must be careful with modifying the instruction-pointer: if we + just interrupt a system call, the kernel would ordinarily try to + restart it when we resume the inferior, which typically results + in SIGSEGV or SIGILL. We prevent this by clearing r10, which + will tell the kernel that r8 does NOT contain a valid error code + and hence it will skip system-call restart. + + The clearing of r10 is safe as long as ia64_write_pc() is only + called as part of setting up an inferior call. */ + write_register (IA64_GR10_REGNUM, 0); } #define IS_NaT_COLLECTION_ADDR(addr) ((((addr) >> 3) & 0x3f) == 0x3f)