c++ - 在多线程应用程序中使用 ptrace

标签 c++ c linux multithreading 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 不会跟踪子进程启动的线程,但这是另一件事,需要稍后处理。甚至可以检查来自不同 therad 的子进程吗?

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

最佳答案

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

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

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

关于c++ - 在多线程应用程序中使用 ptrace,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13381949/

相关文章:

c++ - 在两个像素的颜色之间找到 "distance"

c++ - For 循环 (C++)

c++ - 接受 vector 并返回数组的函数

android - 用 C 为 Android 编译一个库

c - 显示用 C 分隔的整数逗号?

c++ - QRegExp 一次匹配包含 N 个单词的行,但不考虑顺序(即逻辑与)

c - 文件 c 中的多个结构

linux - 如何使用脚本中的密码从 shell 脚本登录用户帐户?

linux 服务器和 windows 客户端上的 c++ 源代码?

c - 与线程相关的错误文件描述符