【问题标题】:Using ptrace from multithreaded applications在多线程应用程序中使用 ptrace
【发布时间】:2012-11-14 15:35:39
【问题描述】:

我想使用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不会跟踪子进程启动的线程,但这是另一件事需要稍后处理。甚至可以从不同的therad检查子进程吗?

另一个奇怪的事情是,在我的实际应用程序中,我基本上做同样的事情(但来自更复杂的上下文:类、互斥体等),但我得到了不同类型的错误。 ptrace 没有返回错误,wait 甚至不会返回子进程的系统调用(子进程甚至不会停止)。另一方面,wait 在子进程退出时按预期工作。

【问题讨论】:

    标签: c++ c linux multithreading ptrace


    【解决方案1】:

    据我所知,ptrace 每个进程只允许一个跟踪器。这意味着如果您尝试附加,您可以尝试使用PTRACE_ATTACH 强制附加,您将收到一个错误,告诉您ptrace 无法附加到指定的进程。

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

    此外,您可以查看this post here,它可能会回答您可能遇到的其他一些问题。

    【讨论】:

      猜你喜欢
      • 2011-07-25
      • 1970-01-01
      • 2012-05-15
      • 2012-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多