From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 42763 invoked by alias); 8 Dec 2015 19:02:35 -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 41868 invoked by uid 89); 8 Dec 2015 19:02:34 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.6 required=5.0 tests=AWL,BAYES_00,SPF_HELO_PASS,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Tue, 08 Dec 2015 19:02:33 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (Postfix) with ESMTPS id 45E0D14CAB4; Tue, 8 Dec 2015 19:02:31 +0000 (UTC) Received: from [10.3.113.200] (ovpn-113-200.phx2.redhat.com [10.3.113.200]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id tB8J2SsE000812; Tue, 8 Dec 2015 14:02:29 -0500 Subject: Re: [PATCH v3 2/2] Implement 'catch syscall' for gdbserver To: Pedro Alves , gdb-patches@sourceware.org References: <1448506425-24691-1-git-send-email-jistone@redhat.com> <1449196006-13759-1-git-send-email-jistone@redhat.com> <1449196006-13759-2-git-send-email-jistone@redhat.com> <5661929E.7020406@redhat.com> <566248F2.5020908@redhat.com> <5666DBAC.5030401@redhat.com> Cc: philippe.waroquiers@skynet.be, sergiodj@redhat.com, eliz@gnu.org, xdje42@gmail.com From: Josh Stone Message-ID: <56672944.1080603@redhat.com> Date: Tue, 08 Dec 2015 19:02:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 In-Reply-To: <5666DBAC.5030401@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-SW-Source: 2015-12/txt/msg00169.txt.bz2 On 12/08/2015 05:31 AM, Pedro Alves wrote: > On 12/05/2015 02:16 AM, Josh Stone wrote: >> On a total tangent, is it ever possible that GDB/GDBserver might try to >> read and modify registers from a PTRACE_EVENT stop? > > Do "catch fork", and you'll be given a prompt right inside a > PTRACE_EVENT_FORK, where you can try to poke at registers at will. > >> If so, you should >> beware that registers may actually be in flux. I ran into this with >> Dyninst, which I fixed here[1] though I can't find the discussion now. >> > > Ouch. > >> The gist was that in a PTRACE_EVENT, the kernel may not have written the >> return register yet. Dyninst wanted to save registers, resume in a bit >> of instrumentation code, then restore registers and resume the normal >> program. So the saved registers got an intermediate RAX, and when it >> resumed into instrumentation the kernel finally wrote the good RAX >> return value to complete the syscall (which the instrumentation >> ignored). Then when dyninst restored registers the bad RAX was written >> back, and thus the normal program code didn't get the correct value for >> its fork return. My solution was to step out of the event with >> PTRACE_SYSCALL before doing anything else. >> >> [1] >> http://git.dyninst.org/?p=dyninst.git;a=commit;h=b89ea1d19677fa0dd9c605ef492c5f6dabf15752 > > Just to be clear, doesn't $orig_rax help here? Are you saving/restoring that? $orig_rax only keeps the value $rax had upon entry, which will be the syscall number. The problem is the return value, which will eventually go into $rax, but at the moment of a PTRACE_EVENT stop this value only exists in kernel state. It's not visible in any user state at all. Just now I had the thought that perhaps you could kludge the return $rax by using the pid from PTRACE_GETEVENTMSG. (In the kernel, that comes from the task_struct: child->ptrace_message.) However, this is subject to pid namespace translation. So if gdb and the child are different, say the latter is in a container, then PTRACE_GETEVENTMSG's pid will be different than the return pid the child should see. That said, the PTRACE_SYSCALL step isn't foolproof either. In theory this should be fine, but arm and aarch64 kernels had bugs that they wouldn't report the syscall return if you hadn't already caught the entry. They would get on the syscall fast path and not check again for tracing when they returned. Fixed in 4.1 for arm, 4.2 for aarch64. PTRACE_SINGLESTEP may be a safer option to get out of the event syscall. In a brief experiment with stepi on x86_64, this case doesn't even advance the user $rip, but I can't be sure for all architectures. At least we should expect it won't run away like a broken return PTRACE_SYSCALL might. > Otherwise, it sounds like trying to run an inferior function > call [(gdb) p foo_func()] when the program is stopped for "catch fork" > may misbehave too. OK, I'll play with it this way to see what happens... but I ought to finish QCatchSyscalls before I tackle new problems. :)