为什么ptrace SINGLESTEP无法正常工作?

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

$ objdump -d -M intel inc_reg16 inc_reg16: file format elf32-i386 Disassembly of section .text: 08048060 : 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  #include  #include  #include  #include  #include  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中的某些错误? 非常感谢您的帮助。

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

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