【问题标题】:Could I get memory access information through X86_64 machine code?我可以通过 X86_64 机器码获取内存访问信息吗?
【发布时间】:2015-02-02 03:24:12
【问题描述】:

我想统计运行在LinuxX86_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

我目前的方法是分析文件,得到所有内存访问指令,如movecmp等。然后计算每条指令的每个访问字节,如mov 0x4(%r15),%edx会加上4字节。

我想知道是否有可能通过machine code进行计算,例如通过分析“41 8b 57 04”,我也可以添加4字节。因为我对X86_64机器码不熟悉,谁能给点线索?或者有没有更好的统计方法?提前致谢!

【问题讨论】:

  • 听起来像是 Valgrind 的工作。
  • @SevaAlekseyev:您能提供详细信息吗?谢谢!
  • 您的要求不清楚。您想知道获取的字节值的分布情况(您知道机器经常获取其他大小的值)?正在运行的程序使用的地址分布? ...在目标代码中找到的地址,忽略执行? FWIW,可以使用“机器代码”来分解单个机器指令,就像您可以使用 C 来做同样的事情一样(C 代码实际上被编译为机器代码,因此执行此操作的 C 程序隐含地提供了一台机器程序来做到这一点)。提供更多解释和更多示例。
  • @IraBaxter:好的,感谢您的 cmets!我会详细说明:我想测量每条指令的平均内存访问字节数。因为程序执行的时候,有很多分支和不确定性,所以我用perf做一个统计。仍然使用上面的例子,每条指令的平均内存访问字节数应该是:2.86% * 4 + ...... + 5.71% * 8。是不是更清楚了?
  • 请注意,应该可以使用 CPU 的性能监控计数器来测量内存访问的实际数量(而不是使用复杂的估计),这会更准确和更具体(例如,你d 能够将其分为几类 - 指令获取、缓存未命中、推测性获取等)。

标签: linux assembly x86-64 machine-code perf


【解决方案1】:

有关解码英特尔指令的信息,请参阅https://stackoverflow.com/a/20319753/120163;其实你真的需要参考英特尔的参考手册:http://download.intel.com/design/intarch/manuals/24319101.pdf如果你只是想手动做一些说明,你可以在这些手册中查找数据。

如果您想自动计算指令总内存访问,您将需要一个将指令映射到访问的数据量的函数。由于指令集比较复杂,对应的函数也会比较复杂,从头开始写要花很长时间。

我的 SO 答案 https://stackoverflow.com/a/23843450/120163 提供了将 x86-32 指令映射到它们的长度的 C 代码,给定一个包含二进制代码块的缓冲区。如果要从目标代码缓冲区中的某个点开始并简单地枚举正在使用的指令,则此类代码是必要的。 (此代码已在生产中使用;它非常可靠)。该例程基本上是通过非常仔细地阅读英特尔参考手册而构建的。对于 OP,这必须扩展到 x86-64,这应该不是很难,主要是您已经考虑了扩展寄存器前缀操作码字节以及与 x86-32 的一些差异。

为了解决 OP 的问题,人们也可以修改这个例程来返回每条指令读取的字节数。后一种数据也必须通过仔细检查英特尔参考手册来提取。

OP 还必须担心他从哪里获得目标代码;如果他不在目标代码本身的地址空间中运行此例程,他将需要以某种方式从 .exe 文件中获取此目标代码。为此,他需要构建或运行相当于 Windows 加载程序的程序,我敢打赌 有一堆黑暗的角落。查看目标代码文件的格式。

【讨论】:

    猜你喜欢
    • 2016-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-24
    相关资源
    最近更新 更多