valgrind正在更改CPUID OPCODE指令返回的值。简而言之
供参考,当在旧计算机上检测AES-NI支持时遇到奇怪的错误时,我知道不是具有AES-NI指令集。但是,这种行为显然正在改变多个值。
使用以下C代码可以使用valgrind-3.10.1
观察此行为:
#include <stdio.h>
int main() {
unsigned eax, ebx, ecx, edx;
eax = 1;
__asm__ volatile("cpuid"
: "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
: "0" (eax), "2" (ecx)
);
if(ecx & (1<<25)) {
printf("aes-ni enabled (ecx=%08x)n", ecx);
} else {
printf("no aes-ni support (ecx=%08x)n", ecx);
}
return 1;
}
以这样的编译和运行:
$ gcc -o test test.c
$ ./test
no aes-ni support (ecx=0098e3fd)
$ valgrind ./test
==25361== Memcheck, a memory error detector
==25361== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==25361== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==25361== Command: ./test
==25361==
aes-ni enabled (ecx=0298e3ff)
==25361==
==25361== HEAP SUMMARY:
==25361== in use at exit: 0 bytes in 0 blocks
==25361== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==25361==
==25361== All heap blocks were freed -- no leaks are possible
==25361==
==25361== For counts of detected and suppressed errors, rerun with: -v
==25361== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
请注意,相同的二进制返回 0098E3FD 正常,但是 0298E3FF 在Valgrind下,这是错误的!
几天后没有答案,Valgrind似乎无法允许正确的CPUID响应。
由于Valgrind本质上是在虚拟环境中运行的,因此它将响应有关 virtual 处理器的CPUID信息,而不是系统的处理器。
感谢@joe的评论以下链接显示了有关此日期的对话:https://sourceforge.net/p/valgrind/mailman/message/message/31960632/
简而言之,Valgrind可以选择将CPUID标志设置为运行时标志(如链接线程中建议(,但是到目前为止(2018年2月(没有此类标志。
我厌倦了关于选项和哲学是对与错的无尽讨论。我下载了代码,并修改了Guest_amd64_helpers.c,在CPUID的仿真的所有情况下,我更改了代码,使用指令将代码读取为本地阵列,并用指令替换了第一个和第二个set_abcd,并用本地阵列的值,local阵列的值,这样:
unsigned int intelId[8];
__get_cpuid(0, intelId , intelId + 1, intelId + 2, intelId + 3);
__get_cpuid(1, intelId + 4 , intelId + 5, intelId + 6, intelId + 7);
switch (0xFFFFFFFF & st->guest_RAX) {
case 0x00000000:
SET_ABCD(intelId[0], intelId[1], intelId[2], intelId[3]);
// SET_ABCD(0x00000001, 0x68747541, 0x444d4163, 0x69746e65);
break;
case 0x00000001:
SET_ABCD(intelId[4], intelId[5], intelId[6], intelId[7]);
// SET_ABCD(0x00000f5a, 0x01000800, 0x00000000, 0x078bfbff);
break;
当然,不要忘记在guest_amd64_helpers.c的顶部,包括&lt; cpuid.h&gt;