From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13452 invoked by alias); 29 Apr 2014 15:57:39 -0000 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 Received: (qmail 13441 invoked by uid 89); 29 Apr 2014 15:57:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-oa0-f51.google.com Received: from mail-oa0-f51.google.com (HELO mail-oa0-f51.google.com) (209.85.219.51) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Tue, 29 Apr 2014 15:57:37 +0000 Received: by mail-oa0-f51.google.com with SMTP id l6so458014oag.38 for ; Tue, 29 Apr 2014 08:57:35 -0700 (PDT) X-Received: by 10.182.33.6 with SMTP id n6mr8545745obi.48.1398787055436; Tue, 29 Apr 2014 08:57:35 -0700 (PDT) MIME-Version: 1.0 Received: by 10.60.79.133 with HTTP; Tue, 29 Apr 2014 08:56:55 -0700 (PDT) In-Reply-To: <201404211827.s3LIRL6a007871@glazunov.sibelius.xs4all.nl> References: <53554475.3010201@mentor.com> <201404211827.s3LIRL6a007871@glazunov.sibelius.xs4all.nl> From: Hui Zhu Date: Tue, 29 Apr 2014 15:57:00 -0000 Message-ID: Subject: Re: [PATCH] Fix interrupt.exp fails with m32 in x86_64 To: Mark Kettenis Cc: Hui Zhu , gdb-patches ml Content-Type: text/plain; charset=ISO-8859-1 X-IsSubscribed: yes X-SW-Source: 2014-04/txt/msg00620.txt.bz2 I am sorry that the root cause of issue has something wrong. The right root cause is: When inferior call 32 bits syscall "read", Linux kernel function "ia32_cstar_target" will set TS_COMPAT to current_thread_info->status. syscall read is interrupt by ctrl-c. Then the $rax will be set to errno -512 in 64 bits. And the inferior will be stopped by Linux kernel function ptrace_stop, the call trace is: #0 freezable_schedule () at include/linux/freezer.h:172 #1 ptrace_stop (exit_code=exit_code@entry=5, why=why@entry=262148, clear_code=clear_code@entry=0, info=info@entry=0xffff88001d833e78) at kernel/signal.c:1920 #2 0xffffffff8107ec33 in ptrace_signal (info=0xffff88001d833e78, signr=5) at kernel/signal.c:2157 #3 get_signal_to_deliver (info=info@entry=0xffff88001d833e78, return_ka=return_ka@entry=0xffff88001d833e58, regs=, cookie=cookie@entry=0x0 ) at kernel/signal.c:2269 #4 0xffffffff81013438 in do_signal (regs=regs@entry=0xffff88001d833f58) at arch/x86/kernel/signal.c:696 #5 0xffffffff81013a40 in do_notify_resume (regs=0xffff88001d833f58, unused=, thread_info_flags=4) at arch/x86/kernel/signal.c:747 #6 #7 0x0000000000000000 in irq_stack_union () After that, GDB can control the stopped inferior. To call function "func1()" of inferior, GDB need: Step 1, save current values of registers ($rax 0xfffffffffffffe00(64 bits -512) is cut to 0xfffffe00(32 bits -512) because inferior is a 32 bits program). Step 2, change the values of registers. Step 3, Push a dummy frame to stack. Step 4, set a breakpint in the return address. When GDB resume the inferior, it will keep execut from ptrace_stop with new values of registers that set by GDB. And TS_COMPAT inside current_thread_info->status will be cleared when inferior switch back to user space. When function "func1()" return, inferior will be stoped by breakpoint inferior will be stopped by Linux kernel function "ptrace_stop" again. current_thread_info->status will not set TS_COMPAT when inferior swith from user space to kernel space because breakpoint handler "int3" doesn't has code for that. GDB begin to set saved values of registers back to inferior that use function "amd64_collect_native_gregset". Because this function just zero-extend each 32 bits value to 64 bits value before put them to inferior. $rax's value is set to 0xfffffe00(32 bits -512) but not 0xfffffffffffffe00(64 bits -512). When GDB continue syscall "read" that is interrupted by "ctrl-c", it will keep execute from ptrace_stop without "TS_COMPAT". Then in Linux kernel function "syscall_get_error", current_thread_info->status doesn't have TS_COMPAT and $rax is 0xfffffe00(32 bits -512). Then in function do_signal will not handle this -ERESTARTSYS. -ERESTARTSYS will be return back to inferior, that is why inferior got a errno -ERESTARTSYS. On Tue, Apr 22, 2014 at 2:27 AM, Mark Kettenis wrote: >> Date: Tue, 22 Apr 2014 00:16:53 +0800 >> From: Hui Zhu >> >> I make a patch that let eax sign-extend in function >> amd64_collect_native_gregset >> that can handle this issue. >> It can handle the issue and pass the regression test. >> Please help me review it. > > I don't think the generic amd64 target code is the proper place to > work around Linux kernel bugs. If you really want to work around this > bug in GDB, it should probably be done in the Linux-specific > i386/amd64 native code. > > Mark > >> 2014-04-21 Hui Zhu >> >> * amd64-nat.c(amd64_collect_native_gregset): Make %eax sign-extended. >> --- a/gdb/amd64-nat.c >> +++ b/gdb/amd64-nat.c >> @@ -131,10 +131,12 @@ amd64_collect_native_gregset (const stru >> { >> num_regs = amd64_native_gregset32_num_regs; >> >> - /* Make sure %eax, %ebx, %ecx, %edx, %esi, %edi, %ebp, %esp and >> + /* Make sure %ebx, %ecx, %edx, %esi, %edi, %ebp, %esp and >> %eip get zero-extended to 64 bits. */ >> for (i = 0; i <= I386_EIP_REGNUM; i++) >> { >> + if (i == I386_EAX_REGNUM) >> + continue; >> if (regnum == -1 || regnum == i) >> memset (regs + amd64_native_gregset_reg_offset (gdbarch, i), >> 0, 8); >> } >> @@ -156,7 +158,24 @@ amd64_collect_native_gregset (const stru >> int offset = amd64_native_gregset_reg_offset (gdbarch, i); >> >> if (offset != -1) >> - regcache_raw_collect (regcache, i, regs + offset); >> + { >> + if (i == I386_EAX_REGNUM >> + && gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32) >> + { >> + /* Make sure %eax get sign-extended to 64 bits. */ >> + LONGEST val; >> + >> + regcache_raw_collect (regcache, I386_EAX_REGNUM, >> + regs + offset); >> + val = extract_signed_integer ((gdb_byte *)(regs + offset), >> + 4, >> + gdbarch_byte_order (gdbarch)); >> + store_signed_integer ((gdb_byte *)(regs + offset), 8, >> + gdbarch_byte_order (gdbarch), val); >> + } >> + else >> + regcache_raw_collect (regcache, i, regs + offset); >> + } >> } >> } >> } >> >>