linux之使用ptrace 跟踪多线程程序

来源:互联网 发布:mac版千牛窗口 编辑:程序博客网 时间:2024/06/04 18:06

1.ptrace 原型说明

 #include <sys/ptrace.h> long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);

 在使用PTRACE_TRACEME参数时,跟踪多线程程序需要使用PTRACE_SETOPTIONS来设置ptrace相关属性。

 PTRACE_SETOPTIONS 是将父进程内由data指向的值设定为ptrace 选项,data作为掩码来解释,由下面的标志来指定:

    (1) PTRACE_O_EXITKILL:当跟踪进程退出时,向所有被跟踪进程发送SIGKILL信号将其退出,这个参数可以防止被跟踪进程脱离跟踪进程的控制。

    (2) PTRACE_O_TRACECLONE:被跟踪进程在下一次调用clone()时将其停止,并自动跟踪新产生的进程,新产生的进程刚开始收到SIGSTOP信号。其新产生的进程的pid可以  

        通过PTRACE_GETEVENTMSG得到。

    (3) PTRACE_O_TRACEEXEC:被跟踪进程在下一次调用exec()函数时使其停止。

    (4) PTRACE_O_TRACEEXIT:被跟踪进程在退出是停止其执行,被跟踪进程的退出状态可通过PTRACE_GETEVENTMSG获得。

    (5) PTRACE_O_TRACEFORK:被跟踪进程在下次调用fork()时停止执行,并自动跟踪新产生的进程,新产生的进程刚开始收到SIGSTOP信号。其新产生的进程的pid可以  

        通过PTRACE_GETEVENTMSG得到。

    (6) PTRACE_O_TRACEVFORK:被跟踪进程在下次调用vfork()时停止执行,并自动跟踪新产生的进程,新产生的进程刚开始收到SIGSTOP信号。其新产生的进程的pid可以  

          通过PTRACE_GETEVENTMSG得到。

  PTRACE_GETEVENTMSG:获取刚刚发生的ptrace事件消息,并存放在跟踪进程由data指向的位置,addr参数被忽略。对于

  PTRACE_EVENT_FORK,PTRACE_EVENT_VFORK,PTRACE_EVENT_VFORKDOWN和PTRACE_EVENT_CLONE,data是新进程的pid.

#include <stdio.h>#include <sys/ptrace.h>#include <sys/wait.h>#include <sys/types.h>#include <unistd.h>#include <stdlib.h>#include <signal.h>#include <pthread.h>void *thread_function(void *arg);char message[] = "hello";int main(){int res;pthread_t a_thread;void *thread_result;res = pthread_create(&a_thread, NULL, thread_function, (void*) message);if (res != 0){printf("Thread creation failed");exit(EXIT_FAILURE);}printf("Wait for thread to finish...\n");//等待上面线程结束res = pthread_join(a_thread, &thread_result);if (res != 0){perror("Thread join failed");exit(EXIT_FAILURE);}printf("Thread joined, it returned %s\n", (char *) thread_result);exit(EXIT_SUCCESS);//return 0;}void *thread_function(void *arg){printf("thread_function is running ,Argument was %s\n", (char*)arg);pthread_exit("Thank you for the CPU time");}
#include <stdio.h>#include <sys/ptrace.h>#include <sys/user.h>#include <sys/wait.h>#include <sys/types.h>#include <unistd.h>#include <stdlib.h>#include <signal.h>//http://www.xuebuyuan.com/1572720.htmlint main(){pid_t child_pid;int status = 0;if ((child_pid = fork()) == 0) //子进程返回{ptrace(PTRACE_TRACEME, 0, NULL, NULL);execl("/bin/ping", "ping www.baidu.com", 0);//这个路径需要更改printf("child process start failed...\n");}else{wait(NULL); //接收SIGTRAP信号long ptraceOption = PTRACE_O_TRACECLONE;ptrace(PTRACE_SETOPTIONS, child_pid, NULL, ptraceOption); //设置ptrace属性PTRACE_SETOPTIONSptrace(PTRACE_CONT, child_pid, NULL, NULL);while (1){printf("parent process wait child pid \n");pid_t child_waited = waitpid(-1, &status, __WALL);//等待接收信号         if (WIFSTOPPED(status)){printf("child %ld recvied signal %d\n", (long)child_waited, WSTOPSIG(status));}if (WIFSIGNALED(status)){printf("child %ld recvied signal %d\n", (long)child_waited, WTERMSIG(status));}if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP){ //新线程被创建完成后,收到的信号,或者遇到断点时ptrace(PTRACE_CONT, child_waited, 1, NULL);continue;}if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP){    //当一个线程创建另一个线程返回时,收到的信号pid_t new_pid;if (((status >> 16) & 0xffff) == PTRACE_EVENT_CLONE){if (ptrace(PTRACE_GETEVENTMSG, child_waited, 0, &new_pid)        != -1){printf("thread %d created\n", new_pid);}}}if (child_waited == -1)break;if (WIFEXITED(status)){ //线程结束时,收到的信号printf("thread %d exited with status %d\t\n",child_waited,WEXITSTATUS(status));}ptrace(PTRACE_CONT, child_waited, 1, NULL);}}return 0;}






0 0