为什么ptrace无法识别该功能?

时间:2014-05-29 17:12:40

标签: c ptrace

我无法弄清楚为什么函数返回"没有这样的过程"每次运行它时都会出现错误消息,但只需使用相同的内联指令就可以生成所需的输出。

#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/user.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

void getregs(pid_t proc, struct user_regs_struct *regs);

int main() {
        pid_t proc = fork();

        if(proc == 0) {
                if(ptrace(PTRACE_TRACEME, 0, NULL, NULL) == -1) {
                       perror("traceme");
                       exit(0);
                }

                if(execl("child", "child", NULL) == -1) {
                       perror("execl");
                       exit(0);
                }
        } else {
                wait(&proc);
                struct user_regs_struct regs;
                ptrace(PTRACE_GETREGS, proc, NULL, &regs);
                printf("eax: %08x\n", (unsigned int)regs.eax);
                getregs(proc, &regs);
                ptrace(PTRACE_CONT, proc, NULL, NULL);
        }

        return 0;
}

void getregs(pid_t proc, struct user_regs_struct *regs) {
        if(ptrace(PTRACE_GETREGS, proc, NULL, &regs) == -1) {
                perror("GETREGS");
                exit(1);
        }

        printf("eax: %08x\n", (unsigned int)regs->eax);
}

当我跑步时,我得到了

~$ ./tracer 
eax: 0000002f 
GETREGS: No such process

我不明白为什么getregs()会返回该错误。它几乎就像是在某种范围之外?

此外,有些不相关的内容:无论我尝试0000002f的过程是什么,EAX始终设置为execl()。这很自然吗?我不知道我是否正确分配了孩子的过程。我是否需要就此问题提出新的问题?

3 个答案:

答案 0 :(得分:5)

您遇到此错误是因为您正在通过将其地址传递给wait(2)系统调用来修改变量proc中包含的进程标识符(PID)的值。

wait系统调用将在子进程终止时更改proc的值以及子进程的返回状态。因此,当您使用ptraceproc中引用您的子流程时,其值可能无效并且不会引用任何现有流程。

@lornix 注意到时,请确保将正确的指针传递给ptrace函数中的getregs

答案 1 :(得分:3)

void getregs(pid_t proc, struct user_regs_struct *regs) {
        if(ptrace(PTRACE_GETREGS, proc, NULL, &regs) == -1) {

您需要在ptrace调用中取消引用regs。 (在这种情况下删除&amp;

        if(ptrace(PTRACE_GETREGS, proc, NULL, regs) == -1) {

你用regs的ADDRESS调用getregs,所以getregs&#39; regs不是主代码中的结构,它是指向结构的指针。


编辑:想通了

您在等待通话中使用/重新分配 proc ,不应该这样做。要等待的参数是状态值,而不是特定子项的pid。等待等待 任何子项,请参阅 waitpid 以获取特定于pid的等待。

尝试:

int wait_status;
wait(&wait_status);

代替当前的等待函数调用。

答案 2 :(得分:1)

您的ptrace来电都表现得一样。不同之处在于您忽略了内联函数的返回值,而检查了函数中的函数。

EAX值是一个红色鲱鱼:由于PTRACE_GETREGS失败,结构未初始化。

wait函数不带进程ID。它等待某个进程终止并将其状态置于由指针传入的整数值中。

您想要waitpid(如果您想等待特定的子进程)。当您知道只有一个函数时,简单函数wait很有用:

int status;
if (wait(&status)) { ... }
相关问题