From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5383 invoked by alias); 30 Apr 2014 05:08:12 -0000 Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org Received: (qmail 5369 invoked by uid 89); 30 Apr 2014 05:08:10 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,RCVD_IN_DNSWL_LOW,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-vc0-f182.google.com Received: from mail-vc0-f182.google.com (HELO mail-vc0-f182.google.com) (209.85.220.182) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Wed, 30 Apr 2014 05:08:09 +0000 Received: by mail-vc0-f182.google.com with SMTP id lf12so1534795vcb.41 for ; Tue, 29 Apr 2014 22:08:07 -0700 (PDT) MIME-Version: 1.0 X-Received: by 10.221.34.7 with SMTP id sq7mr1926233vcb.5.1398834487344; Tue, 29 Apr 2014 22:08:07 -0700 (PDT) Received: by 10.58.243.98 with HTTP; Tue, 29 Apr 2014 22:08:07 -0700 (PDT) In-Reply-To: <53608125.2020103@zytor.com> References: <53554846.3070608@zytor.com> <53608125.2020103@zytor.com> Date: Wed, 30 Apr 2014 05:10:00 -0000 Message-ID: Subject: Re: [PATCH] Fix get ERESTARTSYS with m32 in x86_64 when debug by GDB From: Andrew Pinski To: "H. Peter Anvin" Cc: Hui Zhu , Thomas Gleixner , Ingo Molnar , x86@kernel.org, eparis@redhat.com, Andi Kleen , "linux-kernel@vger.kernel.org" , "gdb@sourceware.org" Content-Type: text/plain; charset=UTF-8 X-IsSubscribed: yes X-SW-Source: 2014-04/txt/msg00090.txt.bz2 On Tue, Apr 29, 2014 at 9:50 PM, H. Peter Anvin wrote: > On 04/29/2014 08:44 PM, Hui Zhu wrote: >> >> 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). > > So gdb just corrupted the system state. Except GDB in 32bit mode does not know the registers are full 64bits so ... > >> 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. > > As it should, because TS_COMPAT *only is meaningful while a system call > is executing*. > >> 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. > > As it shouldn't, because there is no system call entry involved. > >> 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". > > gdb has corrupted the state, and it fails to execute. > > I'm wondering if we need to add additional state here, to carry the > TS_COMPAT bit. We have talked about this kind of issues in the past. > >> 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. >> >> I made a new patch that before call do_notify_resume(will call do_signal) >> in the int3 handler, set TS_COMPAT to status if this task is TIF_IA32. >> Then after GDB call a function of inferior, it will still has TS_COMPAT. > > I'm not sure if I want to label this a gdb bug or not (my main feeling > is that gdb should save and restore the register set presented to it, > and that truncating values to 32 bits is the root of the problem), but > the above is definitely a hack which doesn't really address the real > problem. restoring the values is hard since even the ptrace interface does not allow for that. Thanks, Andrew Pinski > > -hpa >