为什么qemu有时比ptrace计数更多,有时计数更少?

为什么qemu有时比ptrace计数更多,有时计数更少?,c,linux,qemu,instructions,ptrace,C,Linux,Qemu,Instructions,Ptrace,我希望在每次执行指令后将寄存器与qemu产生的寄存器转储进行比较。 因此,我编写了一个程序,它使用ptrace迭代程序的每个执行指令,并且能够在每个指令之后转储寄存器。我已经将程序简化为只对/bin/ls工作,而不是转储寄存器,它只统计执行的指令数 扰流板:qemu和ptrace的指令计数不匹配,并且相差几千条指令 以下是我编写的代码: #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 int main() { pid_t儿童; child=fork();//创建子对象 如果

我希望在每次执行指令后将寄存器与qemu产生的寄存器转储进行比较。 因此,我编写了一个程序,它使用ptrace迭代程序的每个执行指令,并且能够在每个指令之后转储寄存器。我已经将程序简化为只对/bin/ls工作,而不是转储寄存器,它只统计执行的指令数

扰流板:qemu和ptrace的指令计数不匹配,并且相差几千条指令

以下是我编写的代码:

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main()
{   
pid_t儿童;
child=fork();//创建子对象
如果(子项==0){
ptrace(ptrace_TRACEME,0,NULL,NULL);
char*child_argv[]={“/bin/ls”,NULL};
execv(“/bin/ls”,child_argv);
}
否则{
智力状态;
长ins_计数=0;
而(1)
{
//如果子级成功终止,则停止跟踪
等待(&状态);
如果(妻子退出(状态))
打破
ins_计数++;
ptrace(ptrace_SINGLESTEP,child,NULL,NULL);
}
printf(“\n执行了%lld条指令。\n”,ins\U计数);
}
返回0;
}
运行这段代码可以执行492611条指令。我知道这些指令中的大多数都是来自于动态链接器的工作。如果我在每条指令之后转储寄存器,/bin/ls的第一个寄存器转储将准备就绪

现在我想用qemu在每条指令之后转储寄存器。我使用以下命令单步执行来自/bin/ls的每条指令,并在进入每个转换块之前转储寄存器状态。我禁用了qemu的转换块链接,以便在每条实际指令之前转储寄存器

qemu-x86_64-单步-D日志文件-D nochain,cpu/bin/ls

查看日志文件,每条指令的寄存器转储由20行组成,例如:

RAX=0000000000000000 RBX=0000000000000000 RCX=0000000000000000 RDX=0000000000000000
RSI=0000000000000000 RDI=0000000000000000 RBP=0000000000000000 RSP=0000004000805180
R8 =0000000000000000 R9 =0000000000000000 R10=0000000000000000 R11=0000000000000000
R12=0000000000000000 R13=0000000000000000 R14=0000000000000000 R15=0000000000000000
RIP=0000004000807100 RFL=00000202 [-------] CPL=3 II=0 A20=1 SMM=0 HLT=0
ES =0000 0000000000000000 00000000 00000000
CS =0033 0000000000000000 ffffffff 00effb00 DPL=3 CS64 [-RA]
SS =002b 0000000000000000 ffffffff 00cff300 DPL=3 DS   [-WA]
DS =0000 0000000000000000 00000000 00000000
FS =0000 0000000000000000 00000000 00000000
GS =0000 0000000000000000 00000000 00000000
LDT=0000 0000000000000000 0000ffff 00008200 DPL=0 LDT
TR =0000 0000000000000000 0000ffff 00008b00 DPL=0 TSS64-busy
GDT=     0000004000837000 0000007f
IDT=     0000004000836000 000001ff
CR0=80010001 CR2=0000000000000000 CR3=0000000000000000 CR4=00000220
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
CCS=0000000000000000 CCD=0000000000000000 CCO=EFLAGS  
EFER=0000000000000500
我用以下方法计算日志文件的行数:

wc-l日志文件

这给了我9.873.540行,这导致9.873.540/20=493.677指令的寄存器转储

因此,对于/bin/ls,qemu比我的ptrace程序多计算1.066条指令。 我对一个“returnnull”程序和一个打印数字0-9的程序做了同样的事情。结果如下:

returnnull:
qemu counts 105.351 instructions vs ptrace counts 109.308 -> qemu counts 3.957 instructions less than ptrace

printf 0-9:
qemu counts 2.188.344 instructions vs ptrace counts 2.194.793 -> qemu counts 6.449 instructions less than ptrace
为什么qemu和ptrace的指令数不完全相同。为什么qemu有时比ptrace计数更多,有时计数更少?我该怎么做才能拥有相同指令的寄存器转储
为了能够比较这些?

如果在使用ptrace单步执行时确实转储了指令地址,执行一些基本的文本处理,并运行
diff-u
(请确保也关闭ASLR,例如通过在
setarch linux64-R…
下运行),那么您应该能够自己回答这个问题


一种可能是,由于内核与qemu加载程序时的不同入口点状态(auxv等),在启动序列中(在动态链接器中或通过
\uu libc\u start\u main
或等效程序到达的对象中)实际执行不同的代码。减少这种情况的一种快速方法是使用静态链接进行测试。如果这消除了差异,那可能是唯一的原因;如果只是改变了它,那么可能涉及多个原因。

使用ptrace或qemu运行时的指令数是相同的吗?程序的执行不一定是完全确定的。是的,在qemu和PTRACE中,它们在不同的运行中是相同的。我想知道的是,不同的环境变量是由一个或另一个设置的。启动代码可能会扫描或复制环境,这需要根据长度使用不同数量的指令。也可能存在一些问题,比如qemu没有模拟某些系统调用,或者以不同的方式模拟它们,导致程序根据结果执行不同。我刚刚在一个静态链接的“return null”程序上测试了这两个运行,同样,qemu的指令数比ptrace少3589条(33388对29799)。如果我使用ptrace转储指令地址,我将无法将它们与qemu进行比较,因为我无法访问qemu指令地址(in_asm不会跟踪所有执行的指令),您在qemu日志文件中有指令地址——请查看每个跟踪块中的“RIP=”值。QEMU可能会在不同的地址加载程序,但在每种情况下都很容易找出加载位置之间的映射。我发现在启动时实际上执行的指令不同。我试图强制qemu使用标准的
ld-linux-x86-64.so.2
链接器和
-L/lib64/
,但这并没有改变输出。