#include #include #include #include #include #include #include #include #include int main(int argc, char **argv) { const int exitval = 5; const int sigval = SIGSTOP; pid_t child, wpid; int status; struct ptrace_lwpinfo info = {}; printf("Before forking process PID=%d\n", getpid()); assert((child = fork()) != -1); if (child == 0) { printf("Before calling PT_TRACE_ME from child %d\n", getpid()); assert(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); printf("Before raising breakpoint from child\n"); __asm__ __volatile__("int3"); printf("Before exiting of the child process\n"); _exit(exitval); } printf("Parent process PID=%d, child's PID=%d\n", getpid(), child); printf("Before calling waitpid for the child\n"); wpid = waitpid(child, &status, 0); printf("Before calling ptrace(2) with PT_LWPINFO for child\n"); assert(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1); printf("Assert that there exists a thread\n"); assert(info.pl_lwpid > 0); printf("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n", info.pl_lwpid); assert(info.pl_event == PL_EVENT_SIGNAL); printf("signo=%#x errno=%#x code=%#x\n", info.pl_siginfo.si_signo, info.pl_siginfo.si_errno, info.pl_siginfo.si_code); printf("Before calling ptrace(2) with PT_LWPINFO for child\n"); assert(ptrace(PT_LWPINFO, child, &info, sizeof(info)) != -1); printf("Assert that there are no more lwp threads in child\n"); assert(info.pl_lwpid == 0); printf("Before resuming the child process where it left off and " "without signal to be sent\n"); assert(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); printf("Before calling waitpid for the child\n"); wpid = waitpid(child, &status, 0); printf("Before calling waitpid for the child\n"); wpid = waitpid(child, &status, 0); }