/* * Sample program for ptrace system call - No.26 * * This program is cited from * Process Tracing Using Ptrace, By Sandeep S, Linux Gazette, * http://liunxgazette.net/issue81/sandeep.html * * ptrace - process trace * * Synopsis * #include * * long ptrace(enum __ptrace_request request, pid_t pid, void * *addr, void *data); * * Description * The ptrace system call provides a means by which a prarent * process may observe and control the execution of another * process, and examine and change its core image and registers. * It is primarily used to implement breakpoint debugging * and system call tracing. * * The parent can initiate a trace by calling fork(2) and * having the resulting child do a PTRACE_TRACEME followed * (typically) by an exec(2). Alternatively, the parent may * commence trace of an existing process using PTRACE_ATTACH. * While being traced, the child will stop each time a signal * is delivered, even if the signal is being ignored. (The * exception is SIGKILL, which has its usual effect.) The * parent will be notified at its next wait(2) and may * inspect and modify the child process while it is stopped. * The parent the causes the child to continue, optionally * ignoring the delivered signal (or even delivering a * different signal instead). * * When the parent is finished tracing, it can terminate the * child with PTRACE_KILL or cause it to continue executing * in a normal, untraced mode via PTRACE_DETACH. * * The value of request determines the action to be performed: * * PTRACE_TRACEME * PTRACE_PEEKTEXT, PTRACE_PEEKDATA * PTRACE_PEEKUSER * PTRACE_POKETEXT, PTRACE_POKEDATA * PTRACE_POKEUSER * PTRACE_GETREGS, PTREACE_GETFPREGS * PTRACE_SETREGS, PTRACE_SETFPREGS * PTRACE_CONT * PTRACE_SYSCALL, PTRACE_SINGLESTEP * PTRACE_KILL * PTRACE_ATTACH * PTRACE_DETACH */ #include #include #include #include #include #include #include #include #include int main(void) { long long counter = 0; /* machine instruction counter */ int wait_val; /* child's return value */ int pid; /* child's process id */ puts("Please wait"); switch (pid = fork()) { case -1: perror("fork"); break; case 0: /* child process starts */ ptrace(PTRACE_TRACEME, 0, 0, 0); /* * must be called in order to allow the * control over the child process */ execl("/bin/ls", "ls", NULL); /* * executes the program and causes * the child to stop and send a signal * to the parent, the parent can now * switch to PTRACE_SINGLESTEP */ break; /* child process ends */ default:/* parent process starts */ wait(&wait_val); /* * parent waits for child to stop at next * instruction (execl()) */ while (wait_val == 1407 ) { counter++; if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0) perror("ptrace"); /* * switch to singlestep tracing and * release child * if unable call error. */ wait(&wait_val); /* wait for next instruction to complete */ } /* * continue to stop, wait and release until * the child is finished; wait_val != 1407 * Low=0177L(STPCODE=0x7f) and High=05 (SIGTRAP) */ } printf("Number of machine instructions : %lld\n", counter); return 0; }