GDB反向调试AVX2

7
所以我有一颗支持AVX2指令集的新CPU。 这很好,但会破坏GDB反向调试。即使使用无优化编译代码仍然使用共享库,例如调用memset(),然后会调用一个AVX2优化的版本。这很棒,但是GDB Record不支持AVX2。 进程记录不支持地址0x7ffff690dd80处的指令0xc5。 这里的0xc5是VEX前缀。 对于不支持AVX2的CPU,反向调试效果很好。如何让libc等不使用库调用的AVX2优化版本,以便可以使用GDB记录、步进等? 我已经尝试过
LD_BIND_NOW=1
LD_HWCAP_MASK=0
compiling with -static

而且除了在旧机器上进行调试,我已经没有更多的想法了。

1
你使用的GLIBC版本是什么? - Employed Russian
1
2.23是在Ubuntu 16.04 AMD64架构上发布的。CPU是支持AVX2的i7 Xeon。 - Hal
2
已经在这里被问过了:https://dev59.com/SFgQ5IYBdhLWcg3woleo。 - ks1322
可能是使用旧版的GLIBC构建的? - ks1322
你好。按要求,我刚刚在 stackoverflow.com/q/42451492 上记录了我的权宜之计,链接为https://dev59.com/SFgQ5IYBdhLWcg3woleo#44468494(将`jg`位手动修补到`jle`,以禁用`ld-linux.so.2`中的所有 avx2 检测)。 - osgx
显示剩余4条评论
1个回答

2
针对您在ubuntu 16.04 amd64上使用的glibc 2.23,为了同样的原因,我制作了一个二进制修补程序(1位修补)。该修补程序已经适应了您的操作系统版本。包libc6 (2.23-0ubuntu7)可从https://packages.ubuntu.com/xenial/amd64/libc6下载,然后编辑文件ld-2.23.so(请先备份原文件,或将修补后的文件保存到不同路径,并修改自己的二进制文件中的INTERP字段以使用不同的路径)。
 83 3D 5B C9 20 00 06   cmpl $0x6, smth...
 7E 21                  jle  some_forward_label
 B8 07 00 00 00         mov $0x7, %eax
 31 C9                  xor %ecx,%ecx
 0F A2                  cpuid

这里有一段代码get_common_indeces: if (cpu_features->max_cpuid >= 7) __cpuid_count (7, 0, ...,它被从__get_cpu_features调用。根据CPUID的EAX=7 leaf,可以获得检测AVX2支持和启用它所需的所有信息,因此我跳过了带有cpuid eax=0x7,ecx=0的片段,并通过将0x7e 0x21更改为0x7f 0x21来将其结果保存到某些内存部分。

因此,二进制补丁就像将83 3D xx xx xx xx 06 7E xx B8 07 00 00 00 31 C9 0F A2(其中xx可以是任何字节)替换为83 3D xx xx xx xx 06 7F xx B8 07 00 00 00 31 C9 0F A2。您可以使用任何十六进制编辑器或某些二进制差异工具进行此操作。在2.23-0ubuntu7中,此代码位于0x0193B0-0x0193B9处,需要将7e更改为7f。

这个补丁很愚蠢,如果您的根文件系统可能是使用不支持eax=7 cpuid leaf的CPU(早期英特尔Core CPU)启动或在模拟这样的早期英特尔Core CPU的虚拟机中,则无法全局使用已修复的文件("Pentium D 8xx/9xx",Pentium 4,Pentium M-将失败)

您可以将修补程序文件放置在路径中,该路径的名称与原始路径/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2相等或更短(该路径符号链接到/lib/x86_64-linux-gnu/ld-2.23.so文件)。例如,/lib_x86_64-linux-gnu_ld-linux-noAVX2.so.2。然后使用相同的十六进制编辑器,将您的程序可执行文件(ELF)中的字符串“/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2”替换为“/lib_x86_64-linux-gnu_ld-linux-noAVX2.so.2”,或使用来自patchelf软件包的patchelf工具:

cp /lib/x86_64-linux-gnu/ld-2.23.so /lib_x86_64-linux-gnu_ld-linux-noAVX2.so.2

bless  /lib_x86_64-linux-gnu_ld-linux-noAVX2.so.2
# or any other hex editor

patchelf --set-interpreter /lib_x86_64-linux-gnu_ld-linux-no-AVX2.so.2 ./my_program

如果我可以对一个回答进行追溯性的悬赏,那么这个回答就符合条件了。内容非常棒,写得很好,解决方案经过验证并且成功使用。干杯! - Hal
1
@Hal,问题下方应该有一个“开始悬赏”的按钮,原因是“奖励现有答案-其中一个或多个答案是值得额外悬赏的”。答案应该被检查/更新到18.04 LTS;在一些链接的问题中,可能会使用Python的re.sub进行脚本二进制补丁(而不是手动二进制编辑),例如https://dev59.com/SFgQ5IYBdhLWcg3woleo。另一个解决方案:检查Mozilla为Firefox提供的RR反向调试工具https://github.com/mozilla/rr(感谢https://dev59.com/SFgQ5IYBdhLWcg3woleo#comment79266853_42451492)。 - osgx
1
由于某些原因,这种方法在今天的Ubuntu 16.04上对我不起作用(25/04/19)。但是,此答案中的Python脚本修补了略有不同的内容,并且确实有效:https://dev59.com/SFgQ5IYBdhLWcg3woleo?rq=1 - silverscania

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接