我想对Linux
(X86_64
架构)上运行的程序进行内存字节访问统计。我使用perf
工具转储文件,如下所示:
: ffffffff81484700 <load2+0x484700>:
2.86 : ffffffff8148473b: 41 8b 57 04 mov 0x4(%r15),%edx
5.71 : ffffffff81484800: 65 8b 3c 25 1c b0 00 mov %gs:0xb01c,%edi
22.86 : ffffffff814848a0: 42 8b b4 39 80 00 00 mov 0x80(%rcx,%r15,1),%esi
25.71 : ffffffff814848d8: 42 8b b4 39 80 00 00 mov 0x80(%rcx,%r15,1),%esi
2.86 : ffffffff81484947: 80 bb b0 00 00 00 00 cmpb $0x0,0xb0(%rbx)
2.86 : ffffffff81484954: 83 bb 88 03 00 00 01 cmpl $0x1,0x388(%rbx)
5.71 : ffffffff81484978: 80 79 40 00 cmpb $0x0,0x40(%rcx)
2.86 : ffffffff8148497e: 48 8b 7c 24 08 mov 0x8(%rsp),%rdi
5.71 : ffffffff8148499b: 8b 71 34 mov 0x34(%rcx),%esi
5.71 : ffffffff814849a4: 0f af 34 24 imul (%rsp),%esi
我当前的方法是分析文件并获取所有内存访问指令,例如move
,cmp
等。然后计算每条指令的每个访问字节,例如mov 0x4(%r15),%edx
将添加4
个字节。
我想知道是否有可能通过machine code
计算的方法,例如通过分析“41 8b 57 04
”,我还可以添加4
个字节。因为我不熟悉X86_64
机器代码,任何人都可以提供任何线索吗?或者有更好的方法来统计吗?提前谢谢!
答案 0 :(得分:1)
有关解码英特尔指令的信息,请参阅https://stackoverflow.com/a/20319753/120163;事实上,您确实需要参考英特尔参考手册:http://download.intel.com/design/intarch/manuals/24319101.pdf如果您只想手动执行此操作以获得一些说明,您可以在这些手册中查找数据。
如果要自动计算指令总内存访问,则需要一个将指令映射到访问数据量的函数。由于指令集很复杂,相应的功能会很复杂,需要很长时间才能从头开始编写。
我的答案https://stackoverflow.com/a/23843450/120163提供了将x86-32指令映射到其长度的C代码,给定一个包含二进制代码块的缓冲区。如果要在目标代码缓冲区中的某个点开始并简单地枚举正在使用的指令,则必须使用这样的代码。 (此代码已用于生产;它非常可靠)。这个例程基本上是通过仔细阅读英特尔参考手册而构建的。对于OP,这必须扩展到x86-64,这应该不是很难,主要是你考虑了扩展寄存器前缀操作码字节和x86-32的一些区别。
要解决OP的问题,还可以修改此例程,以返回每条指令的字节读取次数。后面的数据也必须通过英特尔参考手册的仔细检查来提取。
OP还必须担心他从何处获取目标代码;如果他没有在目标代码本身的地址空间中运行此例程,他将需要以某种方式从.exe文件中获取此对象代码。为此,他需要构建或运行相当于Windows的加载器,我敢打赌 有一堆黑暗的角落。查看目标代码文件的格式。