【问题标题】:Child process not continuing execution when ptrace'ingptrace 时子进程不继续执行
【发布时间】:2014-10-25 22:00:13
【问题描述】:

我做了以下简单的例子来使用 ptrace 从子进程中读取内存。

我想在执行小型矩阵乘法程序期间每秒查看特定地址 0x601050 处的值。我使用 PTRACE_PEEKDATA 后跟 PTRACE_CONT 并在无限循环中休眠 1 秒钟。

然而,矩阵乘法程序永远不会继续——它应该在第一条指令中打印到标准输出,但它似乎永远不会执行。我知道 ptrace(PTRACE_CONT,pid) 会通知孩子恢复执行,而 sleep(1) 会允许它执行一秒钟(直到下一次 ptrace 调用),但事实并非如此。

#include <string.h>
#include <errno.h>
#include <inttypes.h>

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

int read_mem(long *out, pid_t pid, long addr, size_t sz)
{
    long tmp;
    size_t copied = 0;

    while(copied < sz)
    {
        tmp = ptrace(PTRACE_PEEKDATA, pid, addr+copied);

        if(errno)
        { 
            fprintf(stderr,"ptrace: error : %s\n",strerror(errno));
            return copied;
        }

        memcpy(out,&tmp,sizeof(long));

        copied += sizeof(long);
        out++;

        printf("ptrace: copied %d bytes\n",copied);
    }

    return copied;
}

int main()
{   
    pid_t child;
    long result;
    struct user_regs_struct regs;
    int status;

    long addr = 0x601050;
    size_t sz = sizeof(double);
    long *buf = (long*)malloc(sz);

    child = fork();

    if(child == 0) 
    {
        ptrace(PTRACE_TRACEME);
        execl("./matmul", "matmul", NULL);
    }
    else 
    {
        ptrace(PTRACE_GETREGS, child, &regs);
        printf("ptrace: regs.rip : 0x%lx\n", regs.rip);

        while(1)
        {
            read_mem(buf, child, addr, sz);
            printf("ptrace: read(0x%lx) : %f\n", addr, (double)(*buf));

            ptrace(PTRACE_CONT, child);

            sleep(1);
        }
    }
    return 0;
}

【问题讨论】:

  • 你怎么能用可变数量的参数调用ptrace
  • 它编译/运行良好,我认为 ptrace 将剩余值默认为 0 或 NULL
  • 我应该早点发布这个,但@ooga 这正是问题所在。出于某种原因,它允许我使用可变数量的参数来编译和运行 ptrace,但它没有按预期执行。添加 0/NULL 参数修复它。

标签: c linux debugging ptrace


【解决方案1】:

您似乎没有设置 PTRACE_O_TRACEEXEC 选项。不这样做会导致在调用 exec 时将 SIGTRAP 发送到 tracee;如果未准备好,则默认操作是使用核心转储终止。

【讨论】:

  • 我知道使用 ptrace(PTRACE_TRACEME) 会在下一次调用 exec 时捕获 tracee,但不应该 ptrace(PTRACE_CONT,child) 让它恢复执行吗?
猜你喜欢
  • 2018-10-29
  • 2020-02-02
  • 1970-01-01
  • 2018-07-13
  • 2015-01-21
  • 2013-03-05
  • 1970-01-01
  • 2019-08-05
  • 1970-01-01
相关资源
最近更新 更多