[PATCH] Linux/ptrace: don't convert ptids when asking inf-ptrace layer to resume LWP

Mark Kettenis mark.kettenis@xs4all.nl
Tue Mar 3 16:04:00 GMT 2015


> Date: Tue, 03 Mar 2015 15:12:48 +0000
> From: Pedro Alves <palves@redhat.com>
> 
> On 03/03/2015 02:39 PM, Mark Kettenis wrote:
> >> From: Pedro Alves <palves@redhat.com>
> >> Date: Tue, 3 Mar 2015 13:33:44 +0000
> >>
> >> Tested on x86-64 Fedora 20, -m32.
> >>
> >> gdb/ChangeLog:
> >> 2015-03-03  Pedro Alves  <palves@redhat.com>
> >>
> >> 	* i386-linux-nat.c (i386_linux_resume): Get the ptrace PID out of
> >> 	the lwp field of ptid.  Pass the full ptid to get_thread_regcache.
> >> 	* inf-ptrace.c (get_ptrace_pid): New function.
> >> 	(inf_ptrace_resume): Use it.
> >> 	* linux-nat.c (linux_resume_one_lwp): Pass the LWP's ptid ummodified
> >> 	to the lower layer.
> >> ---
> >>  gdb/ChangeLog        |  9 +++++++++
> >>  gdb/i386-linux-nat.c |  5 ++---
> >>  gdb/inf-ptrace.c     | 25 ++++++++++++++++++++++---
> >>  gdb/linux-nat.c      |  6 +-----
> >>  4 files changed, 34 insertions(+), 11 deletions(-)
> > 
> > I have some fear this is going to break non-Linux targets.
> > 
> >> --- a/gdb/inf-ptrace.c
> >> +++ b/gdb/inf-ptrace.c
> >> -  if (pid == -1)
> >> +  if (ptid_equal (minus_one_ptid, ptid))
> >>      /* Resume all threads.  Traditionally ptrace() only supports
> >>         single-threaded processes, so simply resume the inferior.  */
> >> -    pid = ptid_get_pid (inferior_ptid);
> >> +    pid = get_ptrace_pid (inferior_ptid);
> > 
> > This defenitely should remain ptid_get_pid(); you want to resume the
> > entire process and not an individual thread.
> 
> My thinking is that it doesn't matter in practice.
> 
> Or is it that if there are multiple kernel threads in the
> process, ptrace(PTRACE_CONT, PID) on bsd actually resumes
> them all?  Then other things must be broken anyway.

I can only speak for OpenBSD here, but yes, on OpenBSD, if you pass
"PID" here, all threads within a process are resumed.  If you want to
resume an individual thread, you need to pass its thread ID.  Thread
IDs are also integers, but start at THREAD_PID_OFFSET, which is
currently defined as 1000000.

Are things broken?  Perhaps.  GDB used to properly support an
all-stop/all-go model, and things still seem to work mostly ok.
Perhaps this diff will actually make things better if there are places
where GDB wants to resume or step a single thread that isn't the
thread that stopped the process in the first place.

I've always considered it a serious flaw that Linux doesn't have a way
to resume the entire process and that we need almost 5000 lines of
code to deal with the consequences.

> I was assuming that on BSD targets that use this method,
> there would only be one thread in the core thread list, and
> it would either have LWPID==0, or have PID==LWPID, thus it didn't
> matter if get_ptrace_pid returned the PID or the LWPID.

That assumption is incorrect.  I see that this assumption has made its
way into infrun.c:

          inferior_ptid = ptid_build (child_pid, child_pid, 0);

That's wrong.  The OS-specific code should fill in the LWPID part with
the appropriate value by using thread_change_ptid().  AFAICT, the
linux-nat.c code does that properly.

> If there anything that actually creates other threads with
> a different LWPID on these targets?

The initial thread ID of an OpenBSD process will be PID + THREAD_PID_OFFSET.



More information about the Gdb-patches mailing list