【问题标题】:Why doesn't ptrace SINGLESTEP work properly?为什么 ptrace SINGLESTEP 不能正常工作?
【发布时间】:2011-10-08 14:08:47
【问题描述】:

我正在尝试使用 ptrace API 跟踪一个小程序。我发现每次运行跟踪器时,都会产生不好的结果。这是我要追踪的短程序的反汇编:

$ objdump -d -M intel inc_reg16
inc_reg16:     file format elf32-i386

Disassembly of section .text:

08048060 <.text>:
 8048060:   b8 00 00 00 00          mov    eax,0x0
 8048065:   66 40                   inc    ax
 8048067:   75 fc                   jne    0x8048065
 8048069:   89 c3                   mov    ebx,eax
 804806b:   b8 01 00 00 00          mov    eax,0x1
 8048070:   cd 80                   int    0x80

这是追踪器本身的代码:

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

int main() {
    pid_t child;
    child = fork();
    if (child == 0) {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        execv("inc_reg16", NULL);
    }
    else {

        int status;
        wait(&status);
        struct user_regs_struct regs;
        while (1) {
            ptrace(PTRACE_GETREGS, child, NULL, &regs);
            printf("eip: %x\n", (unsigned int) regs.eip);
            ptrace(PTRACE_SINGLESTEP, child, NULL, NULL);
            waitpid(child, &status, 0);
            if(WIFEXITED(status)) break;
        }
        printf("end\n");
    }
    return 0;
}

跟踪器的工作是单步执行 inc_reg16 程序并记录每个遇到的处理器指令的地址。当我运行并检查遇到指令“inc ax”的次数时,每次运行跟踪器时数字都不同:

$ gcc ezptrace.c -Wall -o ezptrace
$ ./ezptrace > inc_reg16.log
$ grep '8048065' inc_reg16.log | wc -l
65498

第二次检查:

$ ./ezptrace > inc_reg16.log
$ grep '8048065' inc_reg16.log | wc -l
65494

问题是上面的结果应该都是 65536,因为指令“inc ax”被执行了 65536 次。现在的问题是:我的代码中有错误还是 ptrace 中的一些错误问题?非常感谢您的帮助。

【问题讨论】:

  • ./ezptrace | grep 8048065 | wc -l 在我的机器上给出 65536。 (顺便说一句,您使用无效参数调用 execv,它应该类似于 char* argv[] = { "inc_reg16", NULL }; execv(argv[0], argv);
  • 这很有趣。由于我在虚拟化环境(VirtualBox 上的 Debian)中运行跟踪器,是否有可能收到不好的结果?
  • 刚刚在 qemu 下运行的 32 位 ubuntu 11.04 中尝试过(托管在 ubuntu 11.04 x86_64 上,我在那里进行了其他测试),但仍然得到 65536。

标签: c ptrace


【解决方案1】:

我在virtualbox和vmware下都试过同样的程序,似乎只有vmware有正确的结果,而virtualbox和你有同样的问题。我用的是virtualbox 4.2.1。

【讨论】:

    【解决方案2】:

    eip 是用户空间中“当前指令”的地址。您需要一个 ptrace(...PEEKDATA, ...),即遵循 ptrace(...GETREGS, ...) 来获取实际指令。还要记住,使用 ptrace(...PEEKDATA, ...) 你总是得到一个机器字,实际的操作码通常只占用它的低 16/32 位。

    【讨论】:

      猜你喜欢
      • 2016-07-16
      • 2019-01-04
      • 2020-09-03
      • 2016-10-10
      • 2016-10-24
      • 2017-02-27
      • 2017-07-08
      • 2014-11-23
      • 2021-03-07
      相关资源
      最近更新 更多