From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9191 invoked by alias); 27 Aug 2013 19:33:28 -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 9162 invoked by uid 89); 27 Aug 2013 19:33:28 -0000 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 27 Aug 2013 19:33:28 +0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-6.1 required=5.0 tests=AWL,BAYES_00,KHOP_THREADED,RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r7RJXILx019508 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 27 Aug 2013 15:33:18 -0400 Received: from [127.0.0.1] (ovpn01.gateway.prod.ext.ams2.redhat.com [10.39.146.11]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r7RJXGnC016504; Tue, 27 Aug 2013 15:33:17 -0400 Message-ID: <521CFEFC.5050008@redhat.com> Date: Tue, 27 Aug 2013 19:33:00 -0000 From: Pedro Alves User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130625 Thunderbird/17.0.7 MIME-Version: 1.0 To: simon.marchi@polymtl.ca CC: gdb-patches@sourceware.org Subject: Re: [PATCH] [PR gdb/13463] linux-nat: Stop lwp before xfer if running References: <5203f8bd.SBEnufg91ES5VgBo%simon.marchi@polymtl.ca> In-Reply-To: <5203f8bd.SBEnufg91ES5VgBo%simon.marchi@polymtl.ca> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-SW-Source: 2013-08/txt/msg00799.txt.bz2 On 08/08/2013 08:59 PM, simon.marchi@polymtl.ca wrote: > (err, resending with setting From: correctly, sorry about that) > > Hi, > > This is an attempt at finding a solution for PR 13463: > http://sourceware.org/bugzilla/show_bug.cgi?id=13463 > > IMO, this is a serious bug (at least on x86 Linux). Inserting breakpoints > while the inferior is running does not work. It can be triggered very easily: > > 1. Start a simple program in non-stop/async mode. > 2. Put a breakpoint anywhere in the program. > > You should get an error like > > Cannot access memory at address 0x400504 > > What happens is that GDB tries to ptrace read/write the inferior's memory > while the process is not stopped, which is not supported. > > The obvious/naive solution is to stop the process and resume it whenever > we want to do a memory transfer while it is executing. Yeah, gdbserver does this. Starts with prepare_to_access_memory. A prepare -> do -> "unprepare" sequence is possibly more efficient, as we can batch several "do"s over a single pause sequence. I've considered before pushing that prepare/unprepare sequence all the way to gdb core, in order to batch e.g., the whole of prologue analysis + breakpoint insertion, or of shared library list reading, etc., but I thought all the way through all that. > I gave it a shot, > and it seems to work for me, but there is probably some cases it does not > cover, maybe other things it breaks or some better way to do it. I ran a > make check and gdb.sum was identical before and after (minus the time). Points I believe should be handled: - it should not resume threads that were meant to be stopped, or were already stopped. target_resume blindly does that. - it's quite possible the thread you just tried to stop disappears/exit just as you tried to stop it, and then the xfer fails. On the latter issue, and considering that there's no real guarantee some other thread could be simultaneously poking the same address gdbserver is (there's no ptrace atomic write), gdbserver takes the easy route and always pauses all threads. (the opposite end of the scale would be if gdb/gdbserver force-cloned a thread in the inferior to use it as proxy to peek/poke through.) > > What do you think about it? > > * linux-nat.c (linux_nat_xfer_partial): Interrupt during the > memory transfer, if it is running. > > --- > gdb/linux-nat.c | 18 ++++++++++++++++-- > 1 files changed, 16 insertions(+), 2 deletions(-) > > diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c > index 45a6e5f..b8c0d1c 100644 > --- a/gdb/linux-nat.c > +++ b/gdb/linux-nat.c > @@ -294,8 +294,9 @@ static void linux_nat_async (void (*callback) > void *context), > void *context); > static int kill_lwp (int lwpid, int signo); > - > +static int linux_nat_stop_lwp (struct lwp_info *lwp, void *data); > static int stop_callback (struct lwp_info *lp, void *data); > +static void cleanup_target_stop(void *arg); > > static void block_child_signals (sigset_t *prev_mask); > static void restore_child_signals_mask (sigset_t *prev_mask); > @@ -4205,11 +4206,24 @@ linux_nat_xfer_partial (struct target_ops *ops, enum target_object object, > old_chain = save_inferior_ptid (); > > if (is_lwp (inferior_ptid)) > - inferior_ptid = pid_to_ptid (GET_LWP (inferior_ptid)); > + { > + struct lwp_info* lwp; > + inferior_ptid = pid_to_ptid (GET_LWP (inferior_ptid)); > + > + lwp = find_lwp_pid (inferior_ptid); > + if (target_async_permitted && lwp != NULL && !lwp->stopped) > + { > + make_cleanup (cleanup_target_stop, &lwp->ptid); > + linux_nat_stop_lwp (lwp, NULL); > + stop_wait_callback (lwp, NULL); > + } > + } > + > > xfer = linux_ops->to_xfer_partial (ops, object, annex, readbuf, writebuf, > offset, len); > do_cleanups (old_chain); > return xfer; > } > -- Pedro Alves