2012-11-14 50 views
5

我想用ptrace检查什么系统调用我的计划催生了一个程序使得使用ptrace的。我从this tutorial开始,因为它是在对我的previous question的回答中解释的。我被它适应我使用的平台修改代码(SLES 11 64位),并放在一起打印出每一个系统下面的测试代码中调用产生的进程,使得:从多线程应用程序

#include <sys/ptrace.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <sys/reg.h> 
#include <sys/syscall.h> /* For SYS_write etc */ 

pid_t child; 

void run() 
{ 
    long orig_eax; 
    int status; 

    while(1) { 
      int pid = wait(&status); 
      if (pid == -1) { 
       perror("wait"); 
       kill(child, SIGKILL); 
       return; 
      } 
      printf("Got event from %d.\n", pid); 
      if(WIFEXITED(status)) 
       break; 
      orig_eax = ptrace(PTRACE_PEEKUSER, 
        pid, 8 * ORIG_RAX, NULL); 
      if (orig_eax == -1) { 
       perror("ptrace"); 
       kill(child, SIGKILL); 
       return; 
      } else { 
       printf("Syscall %ld called.\n", orig_eax); 
      } 
      ptrace(PTRACE_SYSCALL, 
        pid, NULL, NULL); 
    } 
} 

int main(int /*argc*/, char* argv[]) 
{ 

    child = fork(); 
    if(child == 0) { 
     ptrace(PTRACE_TRACEME, 0, NULL, NULL); 
     execl(argv[1], argv[1], NULL); 
    } 
    else { 
     printf("Child process id = %d.\n", child); 
     run(); 

    } 
    return 0; 
} 

它工作得很好:它打印由程序进行的系统调用的ID(实际上它打印每个两次,一次在入口处,一次用于退出,但现在无关紧要)。但是,除了检查系统调用之外,我的程序还需要做其他事情,所以我决定将检查移至单独的线程中(我比C更适合使用C++,所以我使用C++方式,但是我不要以为重要)。当然,在这个最新的程序中,我只启动线程然后加入它。

#include <sys/ptrace.h> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <stdio.h> 
#include <sys/reg.h> 
#include <sys/syscall.h> /* For SYS_write etc */ 

#include <boost/thread.hpp> 


pid_t child; 

void run() 
{ 
    long orig_eax; 
    int status; 

    while(1) { 
      int pid = wait(&status); 
      if (pid == -1) { 
       perror("wait"); 
       kill(child, SIGKILL); 
       return; 
      } 
      printf("Got event from %d.\n", pid); 
      if(WIFEXITED(status)) 
       break; 
      orig_eax = ptrace(PTRACE_PEEKUSER, 
        pid, 8 * ORIG_RAX, NULL); 
      if (orig_eax == -1) { 
       perror("ptrace"); 
       kill(child, SIGKILL); 
       return; 
      } else { 
       printf("Syscall %ld called.\n", orig_eax); 
      } 
      ptrace(PTRACE_SYSCALL, 
        pid, NULL, NULL); 
    } 
} 

int main(int /*argc*/, char* argv[]) 
{ 

    child = fork(); 
    if(child == 0) { 
     ptrace(PTRACE_TRACEME, 0, NULL, NULL); 
     execl(argv[1], argv[1], NULL); 
    } 
    else { 
     printf("Child process id = %d.\n", child); 
     boost::thread t(run); 
     t.join(); 
    } 
    return 0; 
} 

这一次,我得到一个错误信息:

Child process id = 24682. 
Got event from 24682. 
ptrace: No such process 

这是为什么?我试图寻找答案,但没有发现这样的事情。我发现ptrace不会跟踪由子进程启动的线程,但这是另一件事情需要以后处理。这甚至有可能从一个不同的战场检查孩子进程吗?

另一个奇怪的是,我在实际应用中我做的基本上是同样的事情(但是从一个更复杂的背景:类,互斥等),我也得到一个不同类型的错误。而不是ptrace返回一个错误,wait甚至不会返回子进程上的系统调用(并且子进程甚至不会停止)。另一方面,当子进程退出时,wait按预期工作。

回答

1

据我所知,ptrace允许每个过程只是一种示踪剂。这意味着,如果你试图连接,你可以试着和PTRACE_ATTACH迫使它,您将收到一条错误,告诉ptrace是无法连接到指定的进程。

因此,您的错误出现是因为您的线程未附加到子进程,并且这样,当您尝试ptrace它时,它会失败,并发送-ESRCH代码。

此外,还可以在this post here看看,它可能会回答一些其他问题,你可能有除了这一个。

+0

有一个专门的线程来处理我的帮助。 – petersohn