Re: [ptrace] please review follow fork/exec changes
--lmWPTIvm4M7zUP/T
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
On Mon, Feb 06, 2012 at 01:19:30PM -0800, Dmitry Mikulin wrote:
>=20
> >I see what is going on. The wait loop for P_PPWAIT in do_fork() simply
> >do not allow the ptracestop() in the syscall return path to be reached.
> >There seems to be more problems. In particular, I do not see anything
> >which would prevent the child from being reapped while the loop is
> >executing (assume that the parent is multithreaded and other thread
> >processed SIGCHLD and called wait).
> >
> >Lets deal with these bugs after your proposal for interface changes is
> >dealt with.
>=20
> OK.
>=20
> >
> >Yes, I agree with the proposal to add flag to the child lwp info.
> >I think it will be easier if the flag is different from PL_FLAG_FORKED.
> >I named it PL_FLAG_CHILD.
> >
> >PT_FOLLOW_EXEC is easy to implement, but my question is, how can debugger
> >operate (correctly) if it ignores exec events ? After exec, the whole
> >cached state of the debuggee must be invalidated, and since debugger
> >ignores the notification when the invalidation shall be done, it probably
> >gets very confused.
>=20
> You're right, the debugger needs to handle exec() events implicitly when =
it=20
> starts up executables. The problem is that there is OS-independent=20
> machinery in gdb which handles statup fork-exec sequence differently from=
=20
> when the debuggee itself does an exec(). Basically in the event handling=
=20
> code I need to be able to distinguish app startup by gdb from an exec don=
e=20
> by the app. Other OS-es have flags like PL_FLAG_EXEC set on demand: they=
=20
> have an equivalent of PT_FOLLOW_EXEC. I attached a modified patch that=20
> solves the problem. It tries to separate the always-on TDB_EXEC from the=
=20
> on-demand TDB_FOLLOWEXEC without changing existing functionality. Let me=
=20
> know if it's acceptable.
So, do you in fact need to distinguish exec stops from syscall exit
against exec stops from PT_FOLLOW_EXEC, or do you need to only get stops
at exec returns from PT_CONTINUE when explicitely requested them ?
I would prefer to not introduce another PL_FLAG_<something>EXEC with the
same semantic as PL_FLAG_EXEC. Instead, would the following patch be fine
for your purposes ? With it, stop on exec should only occur if PT_SCX
is requested, or PT_CONTINUE and PT_FOLLOW_EXEC.
[I am unable to fully test this until tomorrow].
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 135f798..67cb1b2 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/pioctl.h>
#include <sys/namei.h>
+#include <sys/ptrace.h>
#include <sys/resourcevar.h>
#include <sys/sdt.h>
#include <sys/sf_buf.h>
@@ -889,7 +890,9 @@ exec_fail_dealloc:
=20
if (error =3D=3D 0) {
PROC_LOCK(p);
- td->td_dbgflags |=3D TDB_EXEC;
+ if ((p->p_flag & P_TRACED) !=3D 0 &&
+ ((P_FOLLOWEXEC) !=3D 0 || (p->p_stops & S_PT_SCX) !=3D 0))
+ td->td_dbgflags |=3D TDB_EXEC;
PROC_UNLOCK(p);
=20
/*
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 60639c9..e447c93 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -1035,7 +1035,9 @@ fork_return(struct thread *td, struct trapframe *fram=
e)
p->p_oppid =3D p->p_pptr->p_pid;
proc_reparent(p, dbg);
sx_xunlock(&proctree_lock);
+ td->td_dbgflags |=3D TDB_CHILD;
ptracestop(td, SIGSTOP);
+ td->td_dbgflags &=3D ~TDB_CHILD;
} else {
/*
* ... otherwise clear the request.
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 4510380..79bbaed 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -660,6 +660,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void=
*addr, int data)
case PT_TO_SCX:
case PT_SYSCALL:
case PT_FOLLOW_FORK:
+ case PT_FOLLOW_EXEC:
case PT_DETACH:
sx_xlock(&proctree_lock);
proctree_locked =3D 1;
@@ -873,6 +874,12 @@ kern_ptrace(struct thread *td, int req, pid_t pid, voi=
d *addr, int data)
else
p->p_flag &=3D ~P_FOLLOWFORK;
break;
+ case PT_FOLLOW_EXEC:
+ if (data)
+ p->p_flag |=3D P_FOLLOWEXEC;
+ else
+ p->p_flag &=3D ~P_FOLLOWEXEC;
+ break;
=20
case PT_STEP:
case PT_CONTINUE:
@@ -936,7 +943,8 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void=
*addr, int data)
p->p_sigparent =3D SIGCHLD;
}
p->p_oppid =3D 0;
- p->p_flag &=3D ~(P_TRACED | P_WAITED | P_FOLLOWFORK);
+ p->p_flag &=3D ~(P_TRACED | P_WAITED | P_FOLLOWFORK |
+ P_FOLLOWEXEC);
=20
/* should we send SIGCHLD? */
/* childproc_continued(p); */
@@ -1145,6 +1153,8 @@ kern_ptrace(struct thread *td, int req, pid_t pid, vo=
id *addr, int data)
pl->pl_flags |=3D PL_FLAG_FORKED;
pl->pl_child_pid =3D td2->td_dbg_forked;
}
+ if (td2->td_dbgflags & TDB_CHILD)
+ pl->pl_flags |=3D PL_FLAG_CHILD;
pl->pl_sigmask =3D td2->td_sigmask;
pl->pl_siglist =3D td2->td_siglist;
strcpy(pl->pl_tdname, td2->td_name);
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 9ebfe83..bec7223 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -384,6 +384,7 @@ do { \
process */
#define TDB_STOPATFORK 0x00000080 /* Stop at the return from fork (child
only) */
+#define TDB_CHILD 0x00000100 /* New child indicator for ptrace() */
=20
/*
* "Private" flags kept in td_pflags:
@@ -613,6 +614,7 @@ struct proc {
#define P_HWPMC 0x800000 /* Process is using HWPMCs */
=20
#define P_JAILED 0x1000000 /* Process is in jail. */
+#define P_FOLLOWEXEC 0x2000000 /* Report execs with ptrace. */
#define P_INEXEC 0x4000000 /* Process is in execve(). */
#define P_STATCHILD 0x8000000 /* Child process stopped or exited. */
#define P_INMEM 0x10000000 /* Loaded into memory. */
diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h
index 2583d59..05c758c 100644
--- a/sys/sys/ptrace.h
+++ b/sys/sys/ptrace.h
@@ -64,6 +64,7 @@
#define PT_SYSCALL 22
=20
#define PT_FOLLOW_FORK 23
+#define PT_FOLLOW_EXEC 24
=20
#define PT_GETREGS 33 /* get general-purpose registers */
#define PT_SETREGS 34 /* set general-purpose registers */
@@ -106,7 +107,8 @@ struct ptrace_lwpinfo {
#define PL_FLAG_SCX 0x08 /* syscall leave point */
#define PL_FLAG_EXEC 0x10 /* exec(2) succeeded */
#define PL_FLAG_SI 0x20 /* siginfo is valid */
-#define PL_FLAG_FORKED 0x40 /* new child */
+#define PL_FLAG_FORKED 0x40 /* child born */
+#define PL_FLAG_CHILD 0x80 /* I am from child */
sigset_t pl_sigmask; /* LWP signal mask */
sigset_t pl_siglist; /* LWP pending signal */
struct __siginfo pl_siginfo; /* siginfo for signal */
--lmWPTIvm4M7zUP/T
Content-Type: application/pgp-signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (FreeBSD)
iEYEARECAAYFAk8xFK4ACgkQC3+MBN1Mb4gpWwCbB1kzJxlazKuClYS12oyoeggT
gz8AoKZMLnE/W9E/eIzEzGJK7kP7I9fu
=EncL
-----END PGP SIGNATURE-----
--lmWPTIvm4M7zUP/T--
討論串 (同標題文章)
完整討論串 (本文為第 15 之 33 篇):