Hi! I've been experimenting with ptrace() and found out that simply following man (2) ptrace is not enough.
The attached problem is supposed to run "/bin/ls /" and stop at every system call it makes. The problem is that ptrace(PT_SYSCALL,...) at the end of the main loop seems simply to resume the child and make it run until it exits, but not until it makes a system call. Attached program works as expected under FreeBSD and Linux, so I believe there is some detail that needs to be taken into account for NetBSD and that I have missed. Can you please give a hint how to correct this program? ------------------------------- #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/ptrace.h> #include <errno.h> #if defined(BSD) #define REQ_TRACE_ME PT_TRACE_ME #define REQ_SYSCALL PT_SYSCALL #define REQ_KILL PT_KILL #define CONT_ADDR (caddr_t)1 #elif defined(LINUX) #define REQ_TRACE_ME PTRACE_TRACEME #define REQ_SYSCALL PTRACE_SYSCALL #define REQ_KILL PTRACE_KILL #define CONT_ADDR NULL #else #error "Define BSD or LINUX." #endif static void die(const char *msg) { printf("%s, errno=%d\n",msg,errno); _exit(1); } static void child() { const char *args[] = {"/bin/ls","/",NULL}; const char *env[] = {NULL}; if(0>ptrace(REQ_TRACE_ME,0,NULL,0)) die("failed to trace myself"); execve(args[0],(char * const *)args,(char * const *)env); die("failed to start the child"); } int main() { pid_t p; int status; int sig; p=fork(); if(p<0) die("failed to fork"); if(!p) child(); for(;;) { if(0>waitpid(p,&status,0)) die("failed to wait for child"); if(WIFSTOPPED(status)) { sig=WSTOPSIG(status); printf("child stopped by signal %d (%s)\n",sig,strsignal(sig)); if(sig!=SIGTRAP) { printf("signal is not SIGTRAP; killing child\n"); if(0>ptrace(REQ_KILL,p,NULL,0)) die("failed to kill the child"); break; } } else if(WIFSIGNALED(status)) { sig=WTERMSIG(status); printf("child was signaled by signal %d (%d)\n", sig,strsignal(sig)); if(0>ptrace(REQ_KILL,p,NULL,0)) die("failed to kill the child"); break; } else if(WIFEXITED(status)) { printf("child exited with status %d\n",WEXITSTATUS(status)); break; } else { printf("neither stopped, nor signaled, nor killed?\n"); if(0>ptrace(PT_KILL,p,NULL,0)) die("failed to kill the child"); break; } printf("resuming the child\n"); if(0>ptrace(REQ_SYSCALL,p,CONT_ADDR,0)) die("failed to resume the child"); } return 0; } -------------------------------------------------------