我想统计运行 /bin/ls 时执行的指令总数。
我使用了 3 种方法,其结果差异很大,我不知道为什么。
1. 使用 ptrace 进行指令计数
我编写了一段代码,调用 ls 的实例并使用 ptrace 单步执行它:
#include <stdio.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/user.h>
#include <sys/reg.h>
#include <sys/syscall.h>
int main()
{
pid_t child;
child = fork(); //create child
if(child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
char* child_argv[] = {"/bin/ls", NULL};
execv("/bin/ls", child_argv);
}
else {
int status;
long long ins_count = 0;
while(1)
{
//stop tracing if child terminated successfully
wait(&status);
if(WIFEXITED(status))
break;
ins_count++;
ptrace(PTRACE_SINGLESTEP, child, NULL, NULL);
}
printf("\n%lld Instructions executed.\n", ins_count);
}
return 0;
}
运行此代码会执行 516.678 条指令。
2.QEMU单步执行
我在单步模式下使用 qemu 模拟了 ls,并使用以下命令将所有传入指令记录到日志文件中:qemu-x86_64 -singlestep -D 日志文件 -d in_asm /bin/ls
根据 qemu ls 执行 16.836 条指令。
3. perf
sudo perf stat ls
该命令执行了 8.162.180 条指令。
我知道这些指令大部分来自动态链接器,并且对它们进行计数是很好的。但为什么这些数字相差如此之大呢?它们不应该都是一样的吗?
你用qemu计算指令数的方法是错误的,in_asm
选项只显示编译块中的翻译指令,因此在 qemu 中进行 tb 链接处理后,它会直接跳转到翻译块,导致 qemu 中的计数少于其他工具,因此实践中的一个好方法是-d nochain,exec
with -singlestep
选项。
不过,这些工具之间也存在指令数差异,我尝试过在不同目录中运行 qemu 来生成这些日志,qemu guest 程序是静态链接的,日志文件在计算指令数时显示不同的结果,可能是某些 glibc 启动或者 init 的东西参与环境参数来导致这种差异。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)