从list1.c中我们可以看到是子进程通过PTRACE_TRACEME来主动要求被跟踪的,但是,对于一个调试器而言,它必须能够主动的跟踪一个任意的进程而不仅仅是调试那些主动要求被跟踪的进程。接下来我们用list2.c来分析依稀PTRACE_TRACEME对exec系列系统调用的处理
list2.c
#include "ptrace.h"
void main()
{
int pid, status;
if((pid=fork())==0){
ptrace(PTRACE_TRACEME,0,0,0);
execl("/root/child2.o","./child2.o",0);
printf("exec failed...\n");
}
else{
wait(&status);
if(WIFSTOPPED(status)){
printf("child has stopped!\n");
fprintf(stderr,"%s",strsignal(WSTOPSIG(status)));
}
sleep(3);
ptrace(PTRACE_CONT,pid,0,0);
wait(&status);
}
}
child2.c
#include "ptrace.h"
void main()
{
printf("child start...\n");
sleep(1);
//while(1)
//printf("hello!\n");
}
运行结果如下:
接下来我们分析一下程序的输出:
当子进程调用PTRACE_TRACEME时,表明子进程主动申请被跟踪。之后子进程继续执行,当执行exec系统调用时,内核会向子进程发送SIGTRAP。此时父进程的wait被唤醒,同时输出相应信息。其中就包括了子进程当前的状态(Trace/breakpoint trap)。
之后父进程休眠三秒中,调用PTRACE_CONT唤醒子进程让其继续执行。此时子进程打印出相应信息:child start...
在这里我们也可以看到:exec后面跟的printf语句没有执行,说明exec系统调用之后,子进程就去执行自己的代码段去了。
未完待续