public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] [PR gdb/13463] linux-nat: Stop lwp before xfer if running
@ 2013-08-08 19:57 simark
  0 siblings, 0 replies; 7+ messages in thread
From: simark @ 2013-08-08 19:57 UTC (permalink / raw)
  To: gdb-patches

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. 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).

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;
 }
-- 
1.7.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] [PR gdb/13463] linux-nat: Stop lwp before xfer if running
  2013-08-30 12:48   ` Simon Marchi
  2013-09-02 19:03     ` Pedro Alves
@ 2013-09-18 18:35     ` Doug Evans
  1 sibling, 0 replies; 7+ messages in thread
From: Doug Evans @ 2013-09-18 18:35 UTC (permalink / raw)
  To: Simon Marchi, Pedro Alves; +Cc: gdb-patches

Simon Marchi writes:
 > On 27 August 2013 15:33, Pedro Alves <palves@redhat.com> wrote:
 > > 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 saw the gdbserver version, it seems to be handled quite cleanly.
 > Should I add an equivalent to prepare_to_access_memory to gdb? This
 > way other platforms could do apply the same fix if the bug applies to
 > them. Either way, this gives me a sense of the code duplication
 > between gdb and gdbserver. Scary!
 > 
 > >> 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.
 > 
 > I believe my fix handles already stopped threads correctly. If the
 > thread is meant to be stopped, should I simply stop it and not resume
 > it after, will it be in a valid state? What is the right way to check
 > if a thread is meant to be stopped?
 > 
 > > - 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.)
 > 
 > I wouldn't consider it a critical bug if the read/write failed because
 > the thread stopped right before we peek/poke it, as it does not
 > "break" a feature. I suppose it could be addressed in a different
 > patch.
 > 
 > Thanks,
 > 
 > Simon
 > 
 > >
 > >>
 > >> 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

Hi.
Just curious what the status of this is.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] [PR gdb/13463] linux-nat: Stop lwp before xfer if running
  2013-08-30 12:48   ` Simon Marchi
@ 2013-09-02 19:03     ` Pedro Alves
  2013-09-18 18:35     ` Doug Evans
  1 sibling, 0 replies; 7+ messages in thread
From: Pedro Alves @ 2013-09-02 19:03 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

On 08/30/2013 01:48 PM, Simon Marchi wrote:
> On 27 August 2013 15:33, Pedro Alves <palves@redhat.com> wrote:
>> 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 saw the gdbserver version, it seems to be handled quite cleanly.
> Should I add an equivalent to prepare_to_access_memory to gdb? This
> way other platforms could do apply the same fix if the bug applies to
> them.

I think we could try that.

> Either way, this gives me a sense of the code duplication
> between gdb and gdbserver. Scary!

Yeah...  http://sourceware.org/gdb/wiki/LocalRemoteFeatureParity

> 
>>> 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.
> 
> I believe my fix handles already stopped threads correctly. If the
> thread is meant to be stopped, should I simply stop it and not resume
> it after, will it be in a valid state?

Supposedly, it'll end up with a cached state that will be
reported later (and something will wake up the event loop,
resulting in a target_wait call to collect the status).
But please confirm.

> What is the right way to check
> if a thread is meant to be stopped?

Same as GDBserver.  last_resume_kind will be resume_stop.  You'll
see that right after "interrupt"/target_stop, and before the LWP
actually reporting a stop to target_wait.

> 
>> - 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.)
> 
> I wouldn't consider it a critical bug if the read/write failed because
> the thread stopped right before we peek/poke it, as it does not
> "break" a feature. I suppose it could be addressed in a different
> patch.

Not sure I follow.  Did you mean if the thread "exited" instead
of "stopped"?  I don't see why that'd be part of a separate patch.
It seems quite related to me.

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] [PR gdb/13463] linux-nat: Stop lwp before xfer if running
  2013-08-27 19:33 ` Pedro Alves
  2013-08-27 19:36   ` Pedro Alves
@ 2013-08-30 12:48   ` Simon Marchi
  2013-09-02 19:03     ` Pedro Alves
  2013-09-18 18:35     ` Doug Evans
  1 sibling, 2 replies; 7+ messages in thread
From: Simon Marchi @ 2013-08-30 12:48 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

On 27 August 2013 15:33, Pedro Alves <palves@redhat.com> wrote:
> 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 saw the gdbserver version, it seems to be handled quite cleanly.
Should I add an equivalent to prepare_to_access_memory to gdb? This
way other platforms could do apply the same fix if the bug applies to
them. Either way, this gives me a sense of the code duplication
between gdb and gdbserver. Scary!

>> 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.

I believe my fix handles already stopped threads correctly. If the
thread is meant to be stopped, should I simply stop it and not resume
it after, will it be in a valid state? What is the right way to check
if a thread is meant to be stopped?

> - 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.)

I wouldn't consider it a critical bug if the read/write failed because
the thread stopped right before we peek/poke it, as it does not
"break" a feature. I suppose it could be addressed in a different
patch.

Thanks,

Simon

>
>>
>> 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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] [PR gdb/13463] linux-nat: Stop lwp before xfer if running
  2013-08-27 19:33 ` Pedro Alves
@ 2013-08-27 19:36   ` Pedro Alves
  2013-08-30 12:48   ` Simon Marchi
  1 sibling, 0 replies; 7+ messages in thread
From: Pedro Alves @ 2013-08-27 19:36 UTC (permalink / raw)
  To: simon.marchi; +Cc: gdb-patches

On 08/27/2013 08:33 PM, Pedro Alves wrote:

> 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.

Grrr, in case it isn't obvious, I meant:
"but I _haven't_ thought all the way through all that."

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] [PR gdb/13463] linux-nat: Stop lwp before xfer if running
  2013-08-08 19:59 simon.marchi
@ 2013-08-27 19:33 ` Pedro Alves
  2013-08-27 19:36   ` Pedro Alves
  2013-08-30 12:48   ` Simon Marchi
  0 siblings, 2 replies; 7+ messages in thread
From: Pedro Alves @ 2013-08-27 19:33 UTC (permalink / raw)
  To: simon.marchi; +Cc: gdb-patches

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

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH] [PR gdb/13463] linux-nat: Stop lwp before xfer if running
@ 2013-08-08 19:59 simon.marchi
  2013-08-27 19:33 ` Pedro Alves
  0 siblings, 1 reply; 7+ messages in thread
From: simon.marchi @ 2013-08-08 19:59 UTC (permalink / raw)
  To: gdb-patches

(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. 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).

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;
 }
-- 
1.7.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2013-09-18 18:35 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-08 19:57 [PATCH] [PR gdb/13463] linux-nat: Stop lwp before xfer if running simark
2013-08-08 19:59 simon.marchi
2013-08-27 19:33 ` Pedro Alves
2013-08-27 19:36   ` Pedro Alves
2013-08-30 12:48   ` Simon Marchi
2013-09-02 19:03     ` Pedro Alves
2013-09-18 18:35     ` Doug Evans

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).