我正在尝试使用 ptrace 跟踪程序的系统调用,但是当跟踪的程序有 fork() 并且忽略它时,它不起作用,据说您只需要设置下面的行,它应该遵循发起的进程也来自 fork() 。
ptrace(PTRACE_SETOPTIONS, 子级, NULL, PTRACE_O_TRACEFORK); 我在下面发布了我的代码,用于tracer.c:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/reg.h>
#include <unistd.h>
#include <errno.h>
#include <sys/user.h>
int main(int argc, char* argv[]){
if (argc < 2) {
printf("Usage: %s <program> [args...]\n", argv[0]);
return 1;
}
pid_t child;
struct user_regs_struct regs;
int status;
int notPrinted = 1;
child = fork();
if (child == 0){
if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0){
perror("ptrace");
return 1;
}
execvp(argv[1], &argv[1]);
}
else if (child > 0){
wait(&status);
ptrace(PTRACE_SETOPTIONS, child, NULL, PTRACE_SETOPTIONS | PTRACE_O_TRACEFORK | PTRACE_O_TRACESYSGOOD);
while (WIFSTOPPED(status)){
ptrace(PTRACE_GETREGS, child, NULL, ®s);
if(notPrinted){
if (regs.orig_rax != -1){
notPrinted = 0;
printf("FROM: %d, Syscall %ld: rdi=%ld, rsi=%ld, rdx=%ld, r10=%ld\n",
child, regs.orig_rax, regs.rbx, regs.rcx, regs.rdx, regs.r10);
}
}
else{
notPrinted = 1;
}
if (ptrace(PTRACE_SYSCALL, child, NULL, NULL) < 0){
perror("ptrace");
return 1;
}
wait(&status);
}
}
else{
perror("fork");
return 1;
}
return 0;
}
以及我一直用来测试的一个简单程序,random.c:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
if(fork() == 0){
sleep(1);
}
srand(time(NULL));
for (int i = 0; i < 30; i++) {
printf("%d ", rand() & 0xf);
}
printf("\n");
sleep(5);
return 0;
}
以前我有以下行,只需将选项设置为“PTRACE_O_TRACEFORK”;所以我相信问题仍然是 PTRACE_SETOPTIONS 的错误配置;我的目标是让程序遵循正确使用 fork() 的程序,就像 strace -f 选项那样
ptrace(PTRACE_SETOPTIONS,子级,NULL,PTRACE_SETOPTIONS | PTRACE_O_TRACEFORK | PTRACE_O_TRACESYSGOOD);
ptrace(PTRACE_TRACEME, 0, 0, 0);
。ptrace(PTRACE_CONT, pid, 0, 0);
。(有关简化示例,请参阅此链接中的listing_2和listing_3。)