#include #include #include #include #include #include #include #include #include #include static int ptrace_do_op(pid_t pid, int op); static int ptrace_attach_child(pid_t pid, bool detach); int main(int argc, char *argv[]) { pid_t child; child = fork(); if (child == 0) { sigset_t mask; sigemptyset(&mask); for (;;) sigsuspend(&mask); return (0); } for (;;) ptrace_attach_child(child, true); return (0); } static int ptrace_attach_child(pid_t pid, bool detach) { struct ptrace_lwpinfo lwpinfo; int err, status; struct reg regs; if (ptrace(PT_ATTACH, pid, (caddr_t)1, 0) == -1) { fprintf(stderr, "attach failed\n"); return (1); } if (waitpid(pid, &status, 0) == -1) { fprintf(stderr, "waitpid failed\n"); return (errno); } ptrace(PT_LWPINFO, pid, (caddr_t)&lwpinfo, sizeof(lwpinfo)); ptrace(PT_FOLLOW_FORK, pid, 0, 1); ptrace(PT_GETREGS, pid, (caddr_t)®s, 0); kill(pid, SIGCONT); if ((err = ptrace_do_op(pid, PT_TO_SCE)) != 0) { fprintf(stderr, "op failed %u\n", errno); return (err); } if (detach) ptrace(PT_DETACH, pid, (caddr_t)1, 0); return (0); } static int ptrace_do_op(pid_t pid, int op) { struct ptrace_lwpinfo lwpinfo; int flags, mask, status; if (op == PT_TO_SCE) mask = PL_FLAG_SCE; else if (op == PT_TO_SCX) mask = PL_FLAG_SCX; do { if (ptrace(op, pid, (caddr_t)1, 0) == -1) return (errno); if (waitpid(pid, &status, 0) == -1) return (errno); ptrace(PT_LWPINFO, pid, (caddr_t)&lwpinfo, sizeof(lwpinfo)); flags = lwpinfo.pl_flags; } while ((flags & mask) == 0); return (0); }