tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Problem with using PT_SYSCALL.
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;
}
-------------------------------------------------------
Home |
Main Index |
Thread Index |
Old Index