为什么 ptrace SINGLESTEP 不能正常工作?

发布于 2024-12-09 02:32:38 字数 1791 浏览 0 评论 0原文

我正在尝试使用 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 中的某些错误?非常感谢您的帮助。

I am trying to trace a little program using ptrace API. I figured out that every time the tracer is run, it produces bad results. This is the disassembly of short program that I want to trace:

$ 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

and here is code of the tracer itself:

// 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, ®s);
            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;
}

The tracer's job is to single step the inc_reg16 program and log address of each encountered processor instruction. When I run and check how many times the instruction 'inc ax' has been encountered, it occurs that the numbers are different each time the tracer is run:

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

the second check:

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

The problem is that above results should be both 65536, as the instruction 'inc ax' is executed exactly 65536 times. Now the question is: is there a mistake in my code or it's a matter of some bug in ptrace? Your help is greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

酒解孤独 2024-12-16 02:32:39

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

I tried the same program under both virtualbox and vmware, it seems that only vmware has the correct result, whereas virtualbox has the same problem as you. I used the virtualbox 4.2.1.

烧了回忆取暖 2024-12-16 02:32:39

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

eip is the address to the "current instruction" in user space. You need a ptrace(...PEEKDATA, ...), i.e. following ptrace(...GETREGS, ...), to obtain the actual instruction. Also keep in mind that, with ptrace(...PEEKDATA, ...) you always obtain a machine word, actual opcodes usually only occupy the low 16/32 bits of it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文