我想使用 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/