On Linux MMU architectures this traces vfork children without changing their behaviour to fork (which is quite a big change even though all applications are supposed to not care). On Linux no-MMU architectures it allows child processes to be traced. Before this, all attempts to trace non-thread children got stuck at vfork. If we're really lucky and the kernel is sensible, this might let us trace CLONE_NEWPID grandchildren too.
* util.c [LINUX] (setbpt): When forking, try to enable the PTRACE_EVENT_{FORK,VFORK,CLONE} events using PTRACE_SETOPTIONS. If successful, instead of converting fork and vfork to clone equivalents, and vfork to fork, just leave them as they are. Always return with tcp->u_arg[arg0_index] set to appropriate clone flags in all cases, even if clone wasn't actually used. Signed-off-by: Jamie Lokier <ja...@shareable.org> --- util.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 53 insertions(+), 0 deletions(-) diff --git a/util.c b/util.c index 0c4a882..beb397e 100644 --- a/util.c +++ b/util.c @@ -1517,6 +1517,59 @@ setbpt(struct tcb *tcp) return -1; } +# ifdef PTRACE_EVENT_FORK + /* + * If are able to set these options, we don't need a + * breakpoint. FIXME: Kernel bugs mean we might need to check + * the kernel version number. See Red Hat Bugzilla bug 246330 + * - "ptrace looses track of a forked child". It says it was + * broken for a certain range of versions. See also Red Had + * Bugzilla bug 162774 - "strace ignores int3 SIGTRAP" It + * includes a patch, and mentions kernels, and a comment in + * the patch about when PTRACE_O_TRACESYSGOOD doesn't work + * completely, which might be related. + */ + if (ptrace (PTRACE_SETOPTIONS, tcp->pid, (void *) 1, + (long) (PTRACE_O_TRACEFORK + | PTRACE_O_TRACEVFORK + | PTRACE_O_TRACECLONE)) == 0) { + /* + * Save the clone flags, or fake them, in case no + * event is received and internal_fork_child() needs to be + * called with these flags. + */ + switch (real_scno) { +# ifdef SYS_vfork + case SYS_vfork: + tcp->u_arg[arg0_index] = CLONE_VM|CLONE_VFORK|SIGCHLD; + return 0; +# endif +# ifdef SYS_fork + case SYS_fork: + tcp->u_arg[arg0_index] = SIGCHLD; + return 0; +# endif + + default: /* clone, clone2 */ + /* + * No breakpoint, but we still need to save + * the clone flags for deciding how to linking + * up the child and parent processes. + * CHECK: Do we need to call get_arg0? The + * old version of the clone/clone2 code down below + * just read tcp->u_arg[arg0_index] without + * calling get_arg0. Was that a bug? + */ + if (arg_setup (tcp, &state) < 0 + || get_arg0 (tcp, &state, &tcp->inst[0]) < 0 + || get_arg1 (tcp, &state, &tcp->inst[1]) < 0) + return -1; + tcp->u_arg[arg0_index] = tcp->inst[0]; + return 0; + } + } +# endif /* PTRACE_EVENT_FORK */ + if (arg_setup (tcp, &state) < 0 || get_arg0 (tcp, &state, &tcp->inst[0]) < 0 || get_arg1 (tcp, &state, &tcp->inst[1]) < 0) -- 1.7.0.4 _______________________________________________ uClinux-dev mailing list uClinux-dev@uclinux.org http://mailman.uclinux.org/mailman/listinfo/uclinux-dev This message was resent by uclinux-dev@uclinux.org To unsubscribe see: http://mailman.uclinux.org/mailman/options/uclinux-dev