Papers/Dynamic Instrumentation

ptrace

tomato13 2009. 4. 14. 13:41

http://linuxgazette.net/issue81/sandeep.html

http://linuxgazette.net/issue83/sandeep.html


ptrace() is a system call that enables one process to control the execution of another. It also enables a process to change the core image of another process. The traced process behaves normally until a signal is caught. When that occurs the process enters stopped state and informs the tracing process by a wait() call. Then tracing process decides how the traced process should respond. The only exception is SIGKILL which surely kill the process.


The traced process may also enter the stopped state in response to some specific events during its course of execution. This happens only if the tracing process has set any event flags in the context of the traced process. The tracing process can even kill the traced one by setting the exit code of the traced process. After tracing, the tracer process may kill the traced one or leave to continue with its execution.



#include <stdio.h>

#include <stdlib.h>

#include <signal.h>

#include <syscall.h>

#include <sys/ptrace.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <unistd.h>

#include <errno.h>



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 and High=05 (SIGTRAP)

                 */

        }

        printf("Number of machine instructions : %lld\n", counter);

        return 0;

}