I'm trying to follow the syscalls of a program using ptrace, but it does not work when the traced program has a fork() and just ignores it, supposedly you just need to set the line below and it should follow the process originating from fork() as well.
ptrace(PTRACE_SETOPTIONS, child, NULL, PTRACE_O_TRACEFORK); I'm posting my code below, for tracer.c:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/reg.h>
#include <unistd.h>
#include <errno.h>
#include <sys/user.h>
int main(int argc, char* argv[]){
if (argc < 2) {
printf("Usage: %s <program> [args...]\n", argv[0]);
return 1;
}
pid_t child;
struct user_regs_struct regs;
int status;
int notPrinted = 1;
child = fork();
if (child == 0){
if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0){
perror("ptrace");
return 1;
}
execvp(argv[1], &argv[1]);
}
else if (child > 0){
wait(&status);
ptrace(PTRACE_SETOPTIONS, child, NULL, PTRACE_SETOPTIONS | PTRACE_O_TRACEFORK | PTRACE_O_TRACESYSGOOD);
while (WIFSTOPPED(status)){
ptrace(PTRACE_GETREGS, child, NULL, ®s);
if(notPrinted){
if (regs.orig_rax != -1){
notPrinted = 0;
printf("FROM: %d, Syscall %ld: rdi=%ld, rsi=%ld, rdx=%ld, r10=%ld\n",
child, regs.orig_rax, regs.rbx, regs.rcx, regs.rdx, regs.r10);
}
}
else{
notPrinted = 1;
}
if (ptrace(PTRACE_SYSCALL, child, NULL, NULL) < 0){
perror("ptrace");
return 1;
}
wait(&status);
}
}
else{
perror("fork");
return 1;
}
return 0;
}
As well as a simple program I've been using to test, random.c:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
if(fork() == 0){
sleep(1);
}
srand(time(NULL));
for (int i = 0; i < 30; i++) {
printf("%d ", rand() & 0xf);
}
printf("\n");
sleep(5);
return 0;
}
Previously I had the following line with just set option to "PTRACE_O_TRACEFORK"; So i believe the issue is still a wrong configuration of PTRACE_SETOPTIONS; my goal is to have the program follow a program that uses fork() correctly, like strace -f option does
ptrace(PTRACE_SETOPTIONS, child, NULL, PTRACE_SETOPTIONS | PTRACE_O_TRACEFORK | PTRACE_O_TRACESYSGOOD);
EDIT:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/reg.h>
#include <sys/user.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char* argv[]){
if (argc < 2){
printf("Usage: %s <program> [args...]\n", argv[0]);
return 1;
}
pid_t child;
struct user_regs_struct regs;
int status;
child = fork();
if (child == 0){
if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0) {
perror("ptrace");
return 1;
}
execvp(argv[1], &argv[1]);
} else if (child > 0){
child = wait(&status);
ptrace(PTRACE_SETOPTIONS, child, NULL, PTRACE_SETOPTIONS | PTRACE_O_TRACEFORK | PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACECLONE);
while (WIFSTOPPED(status)){
ptrace(PTRACE_GETREGS, child, NULL, ®s);
if (regs.orig_rax != -1){
printf("FROM: %d, Syscall %ld: rdi=%ld, rsi=%ld, rdx=%ld, r10=%ld\n",
child, regs.orig_rax, regs.rbx, regs.rcx, regs.rdx, regs.r10);
}
if (ptrace(PTRACE_SYSCALL, child, NULL, NULL) < 0){
perror("ptrace");
return 1;
}
child = wait(&status);
}
} else{
perror("fork");
return 1;
}
return 0;
}
This is the new code with PTRACE_O_TRACECLONE option included, removed notPrinted just for code readability, and with updated child by doing
child = wait(&status);
ptrace(PTRACE_GETREGS, child, NULL, ®s);
to get updated child, and then to read the registers from the process; But I'm still only getting one process as child, any idea why so?
A few issues ...
You need to [also] add PTRACE_O_TRACECLONE
when you set options. You're doing fork
but that's the libc function. (e.g. Under linux) it uses the clone
syscall).
You have to do ptrace(PTRACE_CONT, pid, 0, 0);
to resume the child after the tracer processes the stop.
If you're going to trace an app that calls fork
and you want to also trace any children it created, you have to use the correct pid. You never change the value of child
, so you never get the pid
of any grandchildren.
You have to do: child = wait(&status);
When you're tracing multiple children, you have to know which pid caused the return from wait
.
For some additional info, you could look at some of my ptrace
answers:
UPDATE:
I have edited the code if you could please check again. I have added PTRACE_O_TRACECLONE, I did not add ptrace(PTRACE_CONT, pid, 0, 0); because I believe ptrace(PTRACE_SYSCALL, child, NULL, NULL) already does that and PTRACE_CONT is not required, and changed to record child_pid, but im not getting the grandchild, any ideas on what else I can do? – frazz
Yes, PTRACE_SYSCALL
is sufficient.
I reworked your latest source. In the process, I discovered the bug.
Your PTRACE_SETOPTIONS
call is incorrect. You are doing:
ptrace(PTRACE_SETOPTIONS, pid, NULL, PTRACE_SETOPTIONS |
PTRACE_O_TRACEFORK | PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACECLONE);
You are ORing in PTRACE_SETOPTIONS
into the last argument. This argument should only have PTRACE_O_*
options in it.
This [somehow] breaks things. The correct way is:
ptrace(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEFORK |
PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACECLONE);
I added some extra code to have a per-process control struct to keep track of the state of each process being traced. While not strictly necessary for your example, it is a common thing to do.
I also added a log file for tracing.
And, I refactored your random
a bit to be slightly more trace friendly (not necessary but helped spot the issue).
Here is the tracer:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/reg.h>
#include <sys/user.h>
#include <unistd.h>
#include <errno.h>
#include <syscall.h>
FILE *xflog;
int opt_bug; // 1=show bug
int opt_v; // 1=verbose dump mode
char *opt_L; // logfile name
char *pgmname;
#define logf(_fmt...) \
fprintf(xflog,_fmt)
#if 0
#define DREG(_reg) \
logf(" " #_reg "=%16.16llX/%llu\n",regs._reg,regs._reg)
#else
#define DREG(_reg) \
logf(" " #_reg "=%16.16llX\n",regs._reg)
#endif
struct pidctl {
struct pidctl *ctl_next; // linked list
pid_t ctl_pid; // process id
int ctl_xid; // incremental id (e.g. 1, 2, 3)
unsigned int ctl_seqno; // event sequence number
int ctl_status; // status from last wait call
int ctl_signo; // signal number from last call
int ctl_mode; // mode (0=enter, 1=exit) syscall
};
struct pidctl *pidlist; // list of active processes
int pidcount; // number of entries in pidlist
int pidxid; // incremental id
#if 1
#define WAITFOR(_status) wait(_status)
#else
#define WAITFOR(_status) waitpid(-1,_status,0)
#endif
const char *sysname(int sysno);
// pidfind -- find control for given pid
struct pidctl *
pidfind(pid_t pid,int status)
{
struct pidctl *prev = NULL;
struct pidctl *cur = pidlist;
// find existing entry
for (; cur != NULL; cur = cur->ctl_next) {
if (cur->ctl_pid == pid)
break;
prev = cur;
}
do {
// already exists
if (cur != NULL)
break;
// create new entry
cur = calloc(1,sizeof(*cur));
cur->ctl_pid = pid;
cur->ctl_xid = pidxid++;
logf("pidfind: NEWPID ctl_xid=%d ctl_pid=%8.8X/%d\n",
cur->ctl_xid,cur->ctl_pid,cur->ctl_pid);
// start in "AFT" mode
cur->ctl_mode = 1;
if (prev != NULL)
prev->ctl_next = cur;
else
pidlist = cur;
++pidcount;
} while (0);
cur->ctl_status = status;
if (WIFSTOPPED(status))
cur->ctl_signo = WSTOPSIG(status);
else
cur->ctl_signo = 0;
return cur;
}
void
pidsetup(pid_t pid)
{
// NOTE/BUG: PTRACE_SETOPTIONS must _not_ be or'ed in with PTRACE_O_*
if (opt_bug)
ptrace(PTRACE_SETOPTIONS, pid, NULL, PTRACE_SETOPTIONS |
PTRACE_O_TRACEFORK | PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACECLONE);
else
ptrace(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEFORK |
PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACECLONE);
}
int
main(int argc, char **argv)
{
pgmname = *argv;
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
char *cp = *argv;
if (*cp != '-')
break;
cp += 2;
switch (cp[-1]) {
case 'b':
opt_bug = ! opt_bug;
break;
case 'v':
opt_v = ! opt_v;
break;
case 'L':
opt_L = (*cp != 0) ? cp : NULL;
break;
}
}
if (argc < 1) {
printf("Usage: %s <program> [args...]\n", pgmname);
return 1;
}
pid_t child;
struct user_regs_struct regs;
int status;
if (opt_L == NULL)
opt_L = "LOG";
xflog = fopen(opt_L,"w");
setlinebuf(xflog);
child = fork();
if (child < 0) {
perror("fork");
return 1;
}
if (child == 0) {
if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0) {
perror("ptrace");
return 1;
}
execvp(argv[0], &argv[0]);
perror("execvp");
exit(9);
}
struct pidctl *ctl;
child = WAITFOR(&status);
#if 1
ctl = pidfind(child,status);
#endif
pidsetup(child);
unsigned int seqno = 0;
int sysno;
int exit_count = 0;
while (pidcount > 0) {
logf("\n");
ctl = pidfind(child,status);
if (WIFEXITED(status)) {
logf("EXIT: %d status=%8.8X\n",ctl->ctl_xid,status);
--pidcount;
if (pidcount <= 0)
break;
continue;
}
ptrace(PTRACE_GETREGS, child, NULL, ®s);
sysno = regs.orig_rax;
do {
#if 0
if (sysno == -1)
break;
#endif
#if 0
logf("FROM: %d, Syscall %ld: rdi=%ld, rsi=%ld, rdx=%ld, r10=%ld\n",
child, regs.orig_rax, regs.rbx, regs.rcx, regs.rdx, regs.r10);
#else
logf("%u: %d %s %d/%s\n",
seqno,ctl->ctl_xid,
ctl->ctl_mode ? "AFT" : "BEF",
sysno,sysname(sysno));
if (opt_v) {
DREG(rdi);
DREG(rsi);
DREG(rdx);
DREG(rcx);
DREG(r10);
}
DREG(rax);
#endif
} while (0);
// wait for exit from all ones we're tracing
if (sysno == __NR_exit_group) {
if (++exit_count == pidcount)
break;
}
if (ptrace(PTRACE_SYSCALL, child, NULL, NULL) < 0) {
perror("ptrace");
return 1;
}
ctl->ctl_seqno = seqno++;
ctl->ctl_mode = ! ctl->ctl_mode;
child = WAITFOR(&status);
}
fclose(xflog);
return 0;
}
#define NRALL(_cmd) \
_cmd(read) \
_cmd(write) \
_cmd(open) \
_cmd(close) \
_cmd(stat) \
_cmd(fstat) \
_cmd(lstat) \
_cmd(poll) \
_cmd(lseek) \
_cmd(mmap) \
_cmd(mprotect) \
_cmd(munmap) \
_cmd(brk) \
_cmd(rt_sigaction) \
_cmd(rt_sigprocmask) \
_cmd(rt_sigreturn) \
_cmd(ioctl) \
_cmd(pread64) \
_cmd(pwrite64) \
_cmd(readv) \
_cmd(writev) \
_cmd(access) \
_cmd(pipe) \
_cmd(select) \
_cmd(sched_yield) \
_cmd(mremap) \
_cmd(msync) \
_cmd(mincore) \
_cmd(madvise) \
_cmd(shmget) \
_cmd(shmat) \
_cmd(shmctl) \
_cmd(dup) \
_cmd(dup2) \
_cmd(pause) \
_cmd(nanosleep) \
_cmd(getitimer) \
_cmd(alarm) \
_cmd(setitimer) \
_cmd(getpid) \
_cmd(sendfile) \
_cmd(socket) \
_cmd(connect) \
_cmd(accept) \
_cmd(sendto) \
_cmd(recvfrom) \
_cmd(sendmsg) \
_cmd(recvmsg) \
_cmd(shutdown) \
_cmd(bind) \
_cmd(listen) \
_cmd(getsockname) \
_cmd(getpeername) \
_cmd(socketpair) \
_cmd(setsockopt) \
_cmd(getsockopt) \
_cmd(clone) \
_cmd(fork) \
_cmd(vfork) \
_cmd(execve) \
_cmd(exit) \
_cmd(wait4) \
_cmd(kill) \
_cmd(uname) \
_cmd(semget) \
_cmd(semop) \
_cmd(semctl) \
_cmd(shmdt) \
_cmd(msgget) \
_cmd(msgsnd) \
_cmd(msgrcv) \
_cmd(msgctl) \
_cmd(fcntl) \
_cmd(flock) \
_cmd(fsync) \
_cmd(fdatasync) \
_cmd(truncate) \
_cmd(ftruncate) \
_cmd(getdents) \
_cmd(getcwd) \
_cmd(chdir) \
_cmd(fchdir) \
_cmd(rename) \
_cmd(mkdir) \
_cmd(rmdir) \
_cmd(creat) \
_cmd(link) \
_cmd(unlink) \
_cmd(symlink) \
_cmd(readlink) \
_cmd(chmod) \
_cmd(fchmod) \
_cmd(chown) \
_cmd(fchown) \
_cmd(lchown) \
_cmd(umask) \
_cmd(gettimeofday) \
_cmd(getrlimit) \
_cmd(getrusage) \
_cmd(sysinfo) \
_cmd(times) \
_cmd(ptrace) \
_cmd(getuid) \
_cmd(syslog) \
_cmd(getgid) \
_cmd(setuid) \
_cmd(setgid) \
_cmd(geteuid) \
_cmd(getegid) \
_cmd(setpgid) \
_cmd(getppid) \
_cmd(getpgrp) \
_cmd(setsid) \
_cmd(setreuid) \
_cmd(setregid) \
_cmd(getgroups) \
_cmd(setgroups) \
_cmd(setresuid) \
_cmd(getresuid) \
_cmd(setresgid) \
_cmd(getresgid) \
_cmd(getpgid) \
_cmd(setfsuid) \
_cmd(setfsgid) \
_cmd(getsid) \
_cmd(capget) \
_cmd(capset) \
_cmd(rt_sigpending) \
_cmd(rt_sigtimedwait) \
_cmd(rt_sigqueueinfo) \
_cmd(rt_sigsuspend) \
_cmd(sigaltstack) \
_cmd(utime) \
_cmd(mknod) \
_cmd(uselib) \
_cmd(personality) \
_cmd(ustat) \
_cmd(statfs) \
_cmd(fstatfs) \
_cmd(sysfs) \
_cmd(getpriority) \
_cmd(setpriority) \
_cmd(sched_setparam) \
_cmd(sched_getparam) \
_cmd(sched_setscheduler) \
_cmd(sched_getscheduler) \
_cmd(sched_get_priority_max) \
_cmd(sched_get_priority_min) \
_cmd(sched_rr_get_interval) \
_cmd(mlock) \
_cmd(munlock) \
_cmd(mlockall) \
_cmd(munlockall) \
_cmd(vhangup) \
_cmd(modify_ldt) \
_cmd(pivot_root) \
_cmd(_sysctl) \
_cmd(prctl) \
_cmd(arch_prctl) \
_cmd(adjtimex) \
_cmd(setrlimit) \
_cmd(chroot) \
_cmd(sync) \
_cmd(acct) \
_cmd(settimeofday) \
_cmd(mount) \
_cmd(umount2) \
_cmd(swapon) \
_cmd(swapoff) \
_cmd(reboot) \
_cmd(sethostname) \
_cmd(setdomainname) \
_cmd(iopl) \
_cmd(ioperm) \
_cmd(create_module) \
_cmd(init_module) \
_cmd(delete_module) \
_cmd(get_kernel_syms) \
_cmd(query_module) \
_cmd(quotactl) \
_cmd(nfsservctl) \
_cmd(getpmsg) \
_cmd(putpmsg) \
_cmd(afs_syscall) \
_cmd(tuxcall) \
_cmd(security) \
_cmd(gettid) \
_cmd(readahead) \
_cmd(setxattr) \
_cmd(lsetxattr) \
_cmd(fsetxattr) \
_cmd(getxattr) \
_cmd(lgetxattr) \
_cmd(fgetxattr) \
_cmd(listxattr) \
_cmd(llistxattr) \
_cmd(flistxattr) \
_cmd(removexattr) \
_cmd(lremovexattr) \
_cmd(fremovexattr) \
_cmd(tkill) \
_cmd(time) \
_cmd(futex) \
_cmd(sched_setaffinity) \
_cmd(sched_getaffinity) \
_cmd(set_thread_area) \
_cmd(io_setup) \
_cmd(io_destroy) \
_cmd(io_getevents) \
_cmd(io_submit) \
_cmd(io_cancel) \
_cmd(get_thread_area) \
_cmd(lookup_dcookie) \
_cmd(epoll_create) \
_cmd(epoll_ctl_old) \
_cmd(epoll_wait_old) \
_cmd(remap_file_pages) \
_cmd(getdents64) \
_cmd(set_tid_address) \
_cmd(restart_syscall) \
_cmd(semtimedop) \
_cmd(fadvise64) \
_cmd(timer_create) \
_cmd(timer_settime) \
_cmd(timer_gettime) \
_cmd(timer_getoverrun) \
_cmd(timer_delete) \
_cmd(clock_settime) \
_cmd(clock_gettime) \
_cmd(clock_getres) \
_cmd(clock_nanosleep) \
_cmd(exit_group) \
_cmd(epoll_wait) \
_cmd(epoll_ctl) \
_cmd(tgkill) \
_cmd(utimes) \
_cmd(vserver) \
_cmd(mbind) \
_cmd(set_mempolicy) \
_cmd(get_mempolicy) \
_cmd(mq_open) \
_cmd(mq_unlink) \
_cmd(mq_timedsend) \
_cmd(mq_timedreceive) \
_cmd(mq_notify) \
_cmd(mq_getsetattr) \
_cmd(kexec_load) \
_cmd(waitid) \
_cmd(add_key) \
_cmd(request_key) \
_cmd(keyctl) \
_cmd(ioprio_set) \
_cmd(ioprio_get) \
_cmd(inotify_init) \
_cmd(inotify_add_watch) \
_cmd(inotify_rm_watch) \
_cmd(migrate_pages) \
_cmd(openat) \
_cmd(mkdirat) \
_cmd(mknodat) \
_cmd(fchownat) \
_cmd(futimesat) \
_cmd(newfstatat) \
_cmd(unlinkat) \
_cmd(renameat) \
_cmd(linkat) \
_cmd(symlinkat) \
_cmd(readlinkat) \
_cmd(fchmodat) \
_cmd(faccessat) \
_cmd(pselect6) \
_cmd(ppoll) \
_cmd(unshare) \
_cmd(set_robust_list) \
_cmd(get_robust_list) \
_cmd(splice) \
_cmd(tee) \
_cmd(sync_file_range) \
_cmd(vmsplice) \
_cmd(move_pages) \
_cmd(utimensat) \
_cmd(epoll_pwait) \
_cmd(signalfd) \
_cmd(timerfd_create) \
_cmd(eventfd) \
_cmd(fallocate) \
_cmd(timerfd_settime) \
_cmd(timerfd_gettime) \
_cmd(accept4) \
_cmd(signalfd4) \
_cmd(eventfd2) \
_cmd(epoll_create1) \
_cmd(dup3) \
_cmd(pipe2) \
_cmd(inotify_init1) \
_cmd(preadv) \
_cmd(pwritev) \
_cmd(rt_tgsigqueueinfo) \
_cmd(perf_event_open) \
_cmd(recvmmsg) \
_cmd(fanotify_init) \
_cmd(fanotify_mark) \
_cmd(prlimit64) \
_cmd(name_to_handle_at) \
_cmd(open_by_handle_at) \
_cmd(clock_adjtime) \
_cmd(syncfs) \
_cmd(sendmmsg) \
_cmd(setns) \
_cmd(getcpu) \
_cmd(process_vm_readv) \
_cmd(process_vm_writev) \
_cmd(kcmp) \
_cmd(finit_module) \
_cmd(sched_setattr) \
_cmd(sched_getattr) \
_cmd(renameat2) \
_cmd(seccomp) \
_cmd(getrandom) \
_cmd(memfd_create) \
_cmd(kexec_file_load) \
_cmd(bpf) \
_cmd(execveat) \
_cmd(userfaultfd) \
_cmd(membarrier) \
_cmd(mlock2) \
_cmd(copy_file_range) \
_cmd(preadv2) \
_cmd(pwritev2) \
_cmd(pkey_mprotect) \
_cmd(pkey_alloc) \
_cmd(pkey_free) \
_cmd(statx) \
_cmd(io_pgetevents) \
_cmd(rseq) \
_cmd(pidfd_send_signal) \
_cmd(io_uring_setup) \
_cmd(io_uring_enter) \
_cmd(io_uring_register) \
_cmd(open_tree) \
_cmd(move_mount) \
_cmd(fsopen) \
_cmd(fsconfig) \
_cmd(fsmount) \
_cmd(fspick) \
_cmd(pidfd_open) \
_cmd(clone3)
#define NRSTR(_sym) \
[__NR_##_sym] = #_sym,
const char *NR_name[] = {
NRALL(NRSTR)
};
const char *
sysname(int sysno)
{
return NR_name[sysno];
}
Here is the test program:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/wait.h>
int opt_w; // 1=wait for child
int
main(int argc,char **argv)
{
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
char *cp = *argv;
if (*cp != '-')
break;
cp += 2;
switch (cp[-1]) {
case 'w':
opt_w = ! opt_w;
break;
}
}
int xid = 0;
pid_t child = fork();
if (child == 0) {
sleep(1);
++xid;
}
srand(time(NULL));
pid_t pid = getpid();
setlinebuf(stdout);
printf("%d: pid=%d\n",xid,pid);
for (int i = 0; i < 5; i++) {
printf("%d: %d\n", xid, rand() & 0xf);
}
sleep(5);
if (opt_w && (child != 0))
wait(NULL);
return 0;
}
Here is the LOG
file for the "buggy" case (e.g. -b
). Notice that there is only one process traced and that there are no clone
syscalls.
pidfind: NEWPID ctl_xid=0 ctl_pid=00150066/1376358
0: 0 AFT 59/execve
rax=0000000000000000
1: 0 BEF 12/brk
rax=FFFFFFFFFFFFFFDA
2: 0 AFT 12/brk
rax=000000000159F000
3: 0 BEF 158/arch_prctl
rax=FFFFFFFFFFFFFFDA
4: 0 AFT 158/arch_prctl
rax=FFFFFFFFFFFFFFEA
5: 0 BEF 21/access
rax=FFFFFFFFFFFFFFDA
6: 0 AFT 21/access
rax=FFFFFFFFFFFFFFFE
7: 0 BEF 257/openat
rax=FFFFFFFFFFFFFFDA
8: 0 AFT 257/openat
rax=0000000000000004
9: 0 BEF 5/fstat
rax=FFFFFFFFFFFFFFDA
10: 0 AFT 5/fstat
rax=0000000000000000
11: 0 BEF 9/mmap
rax=FFFFFFFFFFFFFFDA
12: 0 AFT 9/mmap
rax=00007FC42DFE8000
13: 0 BEF 3/close
rax=FFFFFFFFFFFFFFDA
14: 0 AFT 3/close
rax=0000000000000000
15: 0 BEF 257/openat
rax=FFFFFFFFFFFFFFDA
16: 0 AFT 257/openat
rax=0000000000000004
17: 0 BEF 0/read
rax=FFFFFFFFFFFFFFDA
18: 0 AFT 0/read
rax=0000000000000340
19: 0 BEF 8/lseek
rax=FFFFFFFFFFFFFFDA
20: 0 AFT 8/lseek
rax=0000000000000318
21: 0 BEF 0/read
rax=FFFFFFFFFFFFFFDA
22: 0 AFT 0/read
rax=0000000000000044
23: 0 BEF 5/fstat
rax=FFFFFFFFFFFFFFDA
24: 0 AFT 5/fstat
rax=0000000000000000
25: 0 BEF 9/mmap
rax=FFFFFFFFFFFFFFDA
26: 0 AFT 9/mmap
rax=00007FC42DFE6000
27: 0 BEF 8/lseek
rax=FFFFFFFFFFFFFFDA
28: 0 AFT 8/lseek
rax=0000000000000318
29: 0 BEF 0/read
rax=FFFFFFFFFFFFFFDA
30: 0 AFT 0/read
rax=0000000000000044
31: 0 BEF 8/lseek
rax=FFFFFFFFFFFFFFDA
32: 0 AFT 8/lseek
rax=0000000000000360
33: 0 BEF 0/read
rax=FFFFFFFFFFFFFFDA
34: 0 AFT 0/read
rax=0000000000000020
35: 0 BEF 9/mmap
rax=FFFFFFFFFFFFFFDA
36: 0 AFT 9/mmap
rax=00007FC42DE20000
37: 0 BEF 10/mprotect
rax=FFFFFFFFFFFFFFDA
38: 0 AFT 10/mprotect
rax=0000000000000000
39: 0 BEF 9/mmap
rax=FFFFFFFFFFFFFFDA
40: 0 AFT 9/mmap
rax=00007FC42DE42000
41: 0 BEF 9/mmap
rax=FFFFFFFFFFFFFFDA
42: 0 AFT 9/mmap
rax=00007FC42DF8F000
43: 0 BEF 9/mmap
rax=FFFFFFFFFFFFFFDA
44: 0 AFT 9/mmap
rax=00007FC42DFDC000
45: 0 BEF 9/mmap
rax=FFFFFFFFFFFFFFDA
46: 0 AFT 9/mmap
rax=00007FC42DFE2000
47: 0 BEF 3/close
rax=FFFFFFFFFFFFFFDA
48: 0 AFT 3/close
rax=0000000000000000
49: 0 BEF 158/arch_prctl
rax=FFFFFFFFFFFFFFDA
50: 0 AFT 158/arch_prctl
rax=0000000000000000
51: 0 BEF 10/mprotect
rax=FFFFFFFFFFFFFFDA
52: 0 AFT 10/mprotect
rax=0000000000000000
53: 0 BEF 10/mprotect
rax=FFFFFFFFFFFFFFDA
54: 0 AFT 10/mprotect
rax=0000000000000000
55: 0 BEF 10/mprotect
rax=FFFFFFFFFFFFFFDA
56: 0 AFT 10/mprotect
rax=0000000000000000
57: 0 BEF 11/munmap
rax=FFFFFFFFFFFFFFDA
58: 0 AFT 11/munmap
rax=0000000000000000
59: 0 BEF 56/clone
rax=FFFFFFFFFFFFFFDA
60: 0 AFT 56/clone
rax=0000000000150067
61: 0 BEF 39/getpid
rax=FFFFFFFFFFFFFFDA
62: 0 AFT 39/getpid
rax=0000000000150066
63: 0 BEF 5/fstat
rax=FFFFFFFFFFFFFFDA
64: 0 AFT 5/fstat
rax=0000000000000000
65: 0 BEF 12/brk
rax=FFFFFFFFFFFFFFDA
66: 0 AFT 12/brk
rax=000000000159F000
67: 0 BEF 12/brk
rax=FFFFFFFFFFFFFFDA
68: 0 AFT 12/brk
rax=00000000015C0000
69: 0 BEF 12/brk
rax=FFFFFFFFFFFFFFDA
70: 0 AFT 12/brk
rax=00000000015C0000
71: 0 BEF 1/write
rax=FFFFFFFFFFFFFFDA
72: 0 AFT 1/write
rax=000000000000000F
73: 0 BEF 1/write
rax=FFFFFFFFFFFFFFDA
74: 0 AFT 1/write
rax=0000000000000005
75: 0 BEF 1/write
rax=FFFFFFFFFFFFFFDA
76: 0 AFT 1/write
rax=0000000000000006
77: 0 BEF 1/write
rax=FFFFFFFFFFFFFFDA
78: 0 AFT 1/write
rax=0000000000000005
79: 0 BEF 1/write
rax=FFFFFFFFFFFFFFDA
80: 0 AFT 1/write
rax=0000000000000005
81: 0 BEF 1/write
rax=FFFFFFFFFFFFFFDA
82: 0 AFT 1/write
rax=0000000000000005
83: 0 BEF 35/nanosleep
rax=FFFFFFFFFFFFFFDA
84: 0 AFT 35/nanosleep
rax=0000000000000000
85: 0 BEF 231/exit_group
rax=FFFFFFFFFFFFFFDA
Here is the LOG
for the "fixed" case:
pidfind: NEWPID ctl_xid=0 ctl_pid=0015006B/1376363
0: 0 AFT 59/execve
rax=0000000000000000
1: 0 BEF 12/brk
rax=FFFFFFFFFFFFFFDA
2: 0 AFT 12/brk
rax=0000000000F4D000
3: 0 BEF 158/arch_prctl
rax=FFFFFFFFFFFFFFDA
4: 0 AFT 158/arch_prctl
rax=FFFFFFFFFFFFFFEA
5: 0 BEF 21/access
rax=FFFFFFFFFFFFFFDA
6: 0 AFT 21/access
rax=FFFFFFFFFFFFFFFE
7: 0 BEF 257/openat
rax=FFFFFFFFFFFFFFDA
8: 0 AFT 257/openat
rax=0000000000000004
9: 0 BEF 5/fstat
rax=FFFFFFFFFFFFFFDA
10: 0 AFT 5/fstat
rax=0000000000000000
11: 0 BEF 9/mmap
rax=FFFFFFFFFFFFFFDA
12: 0 AFT 9/mmap
rax=00007FEE5BF30000
13: 0 BEF 3/close
rax=FFFFFFFFFFFFFFDA
14: 0 AFT 3/close
rax=0000000000000000
15: 0 BEF 257/openat
rax=FFFFFFFFFFFFFFDA
16: 0 AFT 257/openat
rax=0000000000000004
17: 0 BEF 0/read
rax=FFFFFFFFFFFFFFDA
18: 0 AFT 0/read
rax=0000000000000340
19: 0 BEF 8/lseek
rax=FFFFFFFFFFFFFFDA
20: 0 AFT 8/lseek
rax=0000000000000318
21: 0 BEF 0/read
rax=FFFFFFFFFFFFFFDA
22: 0 AFT 0/read
rax=0000000000000044
23: 0 BEF 5/fstat
rax=FFFFFFFFFFFFFFDA
24: 0 AFT 5/fstat
rax=0000000000000000
25: 0 BEF 9/mmap
rax=FFFFFFFFFFFFFFDA
26: 0 AFT 9/mmap
rax=00007FEE5BF2E000
27: 0 BEF 8/lseek
rax=FFFFFFFFFFFFFFDA
28: 0 AFT 8/lseek
rax=0000000000000318
29: 0 BEF 0/read
rax=FFFFFFFFFFFFFFDA
30: 0 AFT 0/read
rax=0000000000000044
31: 0 BEF 8/lseek
rax=FFFFFFFFFFFFFFDA
32: 0 AFT 8/lseek
rax=0000000000000360
33: 0 BEF 0/read
rax=FFFFFFFFFFFFFFDA
34: 0 AFT 0/read
rax=0000000000000020
35: 0 BEF 9/mmap
rax=FFFFFFFFFFFFFFDA
36: 0 AFT 9/mmap
rax=00007FEE5BD68000
37: 0 BEF 10/mprotect
rax=FFFFFFFFFFFFFFDA
38: 0 AFT 10/mprotect
rax=0000000000000000
39: 0 BEF 9/mmap
rax=FFFFFFFFFFFFFFDA
40: 0 AFT 9/mmap
rax=00007FEE5BD8A000
41: 0 BEF 9/mmap
rax=FFFFFFFFFFFFFFDA
42: 0 AFT 9/mmap
rax=00007FEE5BED7000
43: 0 BEF 9/mmap
rax=FFFFFFFFFFFFFFDA
44: 0 AFT 9/mmap
rax=00007FEE5BF24000
45: 0 BEF 9/mmap
rax=FFFFFFFFFFFFFFDA
46: 0 AFT 9/mmap
rax=00007FEE5BF2A000
47: 0 BEF 3/close
rax=FFFFFFFFFFFFFFDA
48: 0 AFT 3/close
rax=0000000000000000
49: 0 BEF 158/arch_prctl
rax=FFFFFFFFFFFFFFDA
50: 0 AFT 158/arch_prctl
rax=0000000000000000
51: 0 BEF 10/mprotect
rax=FFFFFFFFFFFFFFDA
52: 0 AFT 10/mprotect
rax=0000000000000000
53: 0 BEF 10/mprotect
rax=FFFFFFFFFFFFFFDA
54: 0 AFT 10/mprotect
rax=0000000000000000
55: 0 BEF 10/mprotect
rax=FFFFFFFFFFFFFFDA
56: 0 AFT 10/mprotect
rax=0000000000000000
57: 0 BEF 11/munmap
rax=FFFFFFFFFFFFFFDA
58: 0 AFT 11/munmap
rax=0000000000000000
59: 0 BEF 56/clone
rax=FFFFFFFFFFFFFFDA
60: 0 AFT 56/clone
rax=FFFFFFFFFFFFFFDA
pidfind: NEWPID ctl_xid=1 ctl_pid=0015006C/1376364
61: 1 AFT 56/clone
rax=0000000000000000
62: 0 BEF 56/clone
rax=000000000015006C
63: 0 AFT 39/getpid
rax=FFFFFFFFFFFFFFDA
64: 1 BEF 35/nanosleep
rax=FFFFFFFFFFFFFFDA
65: 0 BEF 39/getpid
rax=000000000015006B
66: 0 AFT 5/fstat
rax=FFFFFFFFFFFFFFDA
67: 0 BEF 5/fstat
rax=0000000000000000
68: 0 AFT 12/brk
rax=FFFFFFFFFFFFFFDA
69: 0 BEF 12/brk
rax=0000000000F4D000
70: 0 AFT 12/brk
rax=FFFFFFFFFFFFFFDA
71: 0 BEF 12/brk
rax=0000000000F6E000
72: 0 AFT 12/brk
rax=FFFFFFFFFFFFFFDA
73: 0 BEF 12/brk
rax=0000000000F6E000
74: 0 AFT 1/write
rax=FFFFFFFFFFFFFFDA
75: 0 BEF 1/write
rax=000000000000000F
76: 0 AFT 1/write
rax=FFFFFFFFFFFFFFDA
77: 0 BEF 1/write
rax=0000000000000005
78: 0 AFT 1/write
rax=FFFFFFFFFFFFFFDA
79: 0 BEF 1/write
rax=0000000000000006
80: 0 AFT 1/write
rax=FFFFFFFFFFFFFFDA
81: 0 BEF 1/write
rax=0000000000000005
82: 0 AFT 1/write
rax=FFFFFFFFFFFFFFDA
83: 0 BEF 1/write
rax=0000000000000006
84: 0 AFT 1/write
rax=FFFFFFFFFFFFFFDA
85: 0 BEF 1/write
rax=0000000000000005
86: 0 AFT 35/nanosleep
rax=FFFFFFFFFFFFFFDA
87: 1 AFT 35/nanosleep
rax=0000000000000000
88: 1 BEF 39/getpid
rax=FFFFFFFFFFFFFFDA
89: 1 AFT 39/getpid
rax=000000000015006C
90: 1 BEF 5/fstat
rax=FFFFFFFFFFFFFFDA
91: 1 AFT 5/fstat
rax=0000000000000000
92: 1 BEF 12/brk
rax=FFFFFFFFFFFFFFDA
93: 1 AFT 12/brk
rax=0000000000F4D000
94: 1 BEF 12/brk
rax=FFFFFFFFFFFFFFDA
95: 1 AFT 12/brk
rax=0000000000F6E000
96: 1 BEF 12/brk
rax=FFFFFFFFFFFFFFDA
97: 1 AFT 12/brk
rax=0000000000F6E000
98: 1 BEF 1/write
rax=FFFFFFFFFFFFFFDA
99: 1 AFT 1/write
rax=000000000000000F
100: 1 BEF 1/write
rax=FFFFFFFFFFFFFFDA
101: 1 AFT 1/write
rax=0000000000000005
102: 1 BEF 1/write
rax=FFFFFFFFFFFFFFDA
103: 1 AFT 1/write
rax=0000000000000005
104: 1 BEF 1/write
rax=FFFFFFFFFFFFFFDA
105: 1 AFT 1/write
rax=0000000000000006
106: 1 BEF 1/write
rax=FFFFFFFFFFFFFFDA
107: 1 AFT 1/write
rax=0000000000000005
108: 1 BEF 1/write
rax=FFFFFFFFFFFFFFDA
109: 1 AFT 1/write
rax=0000000000000006
110: 1 BEF 35/nanosleep
rax=FFFFFFFFFFFFFFDA
111: 0 BEF 35/nanosleep
rax=0000000000000000
112: 0 AFT 61/wait4
rax=FFFFFFFFFFFFFFDA
113: 1 AFT 35/nanosleep
rax=0000000000000000
114: 1 BEF 231/exit_group
rax=FFFFFFFFFFFFFFDA
EXIT: 1 status=00000000
EXIT: 1 status=00000000