首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >动态确定流氓AVX-512指令的执行位置

动态确定流氓AVX-512指令的执行位置
EN

Stack Overflow用户
提问于 2018-08-25 00:53:33
回答 1查看 1.5K关注 0票数 16

我有一个运行在支持AVX-512的英特尔机器上的进程,但这个进程不直接使用任何AVX-512指令(asm或内部),并且是用-mno-avx512f编译的,所以编译器不会插入任何AVX-512指令。

然而,它正在以降低的AVX涡轮频率无限运行。毫无疑问,有一条AVX-512指令通过库,(不太可能)系统调用或类似的东西潜入到某个地方。

而不是尝试“二进制搜索”的AVX-512指令来自哪里,有没有什么方法可以立即找到它,例如,陷阱在这样的指令上?

操作系统为Ubuntu 16.04。

EN

回答 1

Stack Overflow用户

发布于 2018-09-12 17:07:26

正如注释中所建议的,您可以搜索系统的所有ELF文件并反汇编它们,以检查它们是否使用AVX-512指令:

代码语言:javascript
复制
$ objdump -d /lib64/ld-linux-x86-64.so.2 | grep %zmm0
14922:       62 f1 fd 48 7f 44 24    vmovdqa64 %zmm0,0xc0(%rsp)
14a2d:       62 f1 fd 48 6f 44 24    vmovdqa64 0xc0(%rsp),%zmm0
14c2c:       62 f1 fd 48 7f 81 50    vmovdqa64 %zmm0,0x50(%rcx)
14ca0:       62 f1 fd 48 6f 84 24    vmovdqa64 0x50(%rsp),%zmm0

(顺便说一句,libc和ld.so确实包含AVX-512指令,它们不是你要找的指令吧?)

然而,你可能会发现你甚至没有执行的二进制代码,并且错过了动态未压缩的代码,等等。

如果你对进程有疑问(因为perf报告CORE_POWER.LVL*_TURBO_LICENSE事件),我建议这个进程生成一个核心转储并反汇编它(注意第一行也允许转储代码):

代码语言:javascript
复制
$ echo 0xFF > /proc/<PID>/coredump_filter 
$ gdb --pid=<PID>
[...]
(gdb) gcore
Saved corefile core.19602
(gdb) quit
Detaching from program: ..., process ...
$ objdump -d core.19602 | grep %zmm0
7f73db8187cb:       62 f1 7c 48 10 06       vmovups (%rsi),%zmm0
7f73db818802:       62 f1 7c 48 11 07       vmovups %zmm0,(%rdi)
7f73db81883f:       62 f1 7c 48 10 06       vmovups (%rsi),%zmm0
[...]

接下来,您可以轻松地编写一个小python脚本,以便在每个AVX-512指令上添加断点(或跟踪点)。就像这样

代码语言:javascript
复制
(gdb) python
>import os
>with os.popen('objdump -d core.19602 | grep %zmm0 | cut -f1 -d:') as pipe:
>    for line in pipe:
>         gdb.Breakpoint("*" + line)

当然,它会创建数百(或数千)个断点。然而,断点的开销对于gdb来说已经足够小了(我认为每个断点的开销小于1kb)。

另一种方法是在虚拟机中运行代码。特别是,我建议使用libvex。libvex用于动态检测代码(内存泄漏、内存分析等)。libvex解释机器代码,将其转换为中间表示形式,然后重新编码机器代码以供CPU执行。使用libvex的最著名的项目是valgrind (公平地说,libvex是valgrind的后端)。

因此,您可以使用libvex运行您的应用程序,而无需使用以下工具:

代码语言:javascript
复制
$ valgrind --tool=none YOUR_APP

现在,您必须围绕libvex编写一个工具来检测AVX-512的使用情况。然而,libVEX (目前)还不支持AVX-512。因此,一旦它必须执行AVX-512指令,它就会失败并返回非法指令。

代码语言:javascript
复制
$ valgrind --tool=none YOUR_APP
[...]   
vex amd64->IR: unhandled instruction bytes: 0x62 0xF1 0xFD 0x48 0x28 0x84 0x24 0x8 0x1 0x0
vex amd64->IR:   REX=0 REX.W=0 REX.R=0 REX.X=0 REX.B=0
vex amd64->IR:   VEX=0 VEX.L=0 VEX.nVVVV=0x0 ESC=NONE
vex amd64->IR:   PFX.66=0 PFX.F2=0 PFX.F3=0
==20061== valgrind: Unrecognised instruction at address 0x10913e.
==20061==    at 0x10913E: main (in ...)
==20061== Your program just tried to execute an instruction that Valgrind
==20061== did not recognise.  There are two possible reasons for this.
==20061== 1. Your program has a bug and erroneously jumped to a non-code
==20061==    location.  If you are running Memcheck and you just saw a
==20061==    warning about a bad jump, it's probably your program's fault.
==20061== 2. The instruction is legitimate but Valgrind doesn't handle it,
==20061==    i.e. it's Valgrind's fault.  If you think this is the case or
==20061==    you are not sure, please let us know and we'll try to fix it.
==20061== Either way, Valgrind will now raise a SIGILL signal which will
==20061== probably kill your program.
==20061== 
==20061== Process terminating with default action of signal 4 (SIGILL)
==20061==  Illegal opcode at address 0x10913E
==20061==    at 0x10913E: main (in ...)
==20061== 

注意:这个答案已经过测试:

代码语言:javascript
复制
#include <immintrin.h>
int main(int argc, char *argv[]) {
    __m512d a, b, c;
    _mm512_fnmadd_pd(a, b, c);
}
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52008788

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档