Valgrind更改CPUID值

jyztefdp  于 2023-03-29  发布在  其他
关注(0)|答案(2)|浏览(180)

Valgrind正在更改CPUID opcode instruction返回的值。简单地说,如何让Valgrind遵守实际的CPUID指令?
作为参考,这是我在一台旧电脑上检测aes-ni支持时发现的奇怪错误,我知道这台电脑没有aes-ni指令集。然而,这种行为显然改变了多个值。
使用以下C代码,可以在valgrind-3.10.1中观察到这种行为:

  1. #include <stdio.h>
  2. int main() {
  3. unsigned eax, ebx, ecx, edx;
  4. eax = 1;
  5. __asm__ volatile("cpuid"
  6. : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
  7. : "0" (eax), "2" (ecx)
  8. );
  9. if(ecx & (1<<25)) {
  10. printf("aes-ni enabled (ecx=%08x)n", ecx);
  11. } else {
  12. printf("no aes-ni support (ecx=%08x)\n", ecx);
  13. }
  14. return 1;
  15. }

它的编译和运行方式如下:

  1. $ gcc -o test test.c
  2. $ ./test
  3. no aes-ni support (ecx=0098e3fd)
  4. $ valgrind ./test
  5. ==25361== Memcheck, a memory error detector
  6. ==25361== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
  7. ==25361== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
  8. ==25361== Command: ./test
  9. ==25361==
  10. aes-ni enabled (ecx=0298e3ff)
  11. ==25361==
  12. ==25361== HEAP SUMMARY:
  13. ==25361== in use at exit: 0 bytes in 0 blocks
  14. ==25361== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
  15. ==25361==
  16. ==25361== All heap blocks were freed -- no leaks are possible
  17. ==25361==
  18. ==25361== For counts of detected and suppressed errors, rerun with: -v
  19. ==25361== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

请注意,同样的二进制文件在正常情况下返回0098 e3 fd,但在valgrind下返回0298 e3 ff,这是错误的!

bcs8qyzn

bcs8qyzn1#

经过几天没有答案,似乎Valgrind无法允许正确的CPUID响应。
因为Valgrind本质上是在虚拟环境中运行的,所以它将响应有关它所知道的 * 虚拟 * 处理器的CPUID信息,而不是系统的处理器。
感谢@Joe的评论,下面的链接显示了一段可以追溯到2014年的对话:https://sourceforge.net/p/valgrind/mailman/message/31960632/
简而言之,Valgrind可以选择将CPUID标志设置为运行时标志(如链接线程中所建议的那样),但到目前为止(2018年2月)还不存在这样的标志。

hfyxw5xn

hfyxw5xn2#

我厌倦了无休止的讨论什么是对的和错的选项和哲学.我下载的代码,并修改guest_amd64_helpers.c和在所有的模拟cpuid的示例中,我改变了代码读取到一个本地数组使用的指令,真实的的cpuid和替换第一和第二SET_ABCD与本地数组的值,像这样:

  1. unsigned int intelId[8];
  2. __get_cpuid(0, intelId , intelId + 1, intelId + 2, intelId + 3);
  3. __get_cpuid(1, intelId + 4 , intelId + 5, intelId + 6, intelId + 7);
  4. switch (0xFFFFFFFF & st->guest_RAX) {
  5. case 0x00000000:
  6. SET_ABCD(intelId[0], intelId[1], intelId[2], intelId[3]);
  7. // SET_ABCD(0x00000001, 0x68747541, 0x444d4163, 0x69746e65);
  8. break;
  9. case 0x00000001:
  10. SET_ABCD(intelId[4], intelId[5], intelId[6], intelId[7]);
  11. // SET_ABCD(0x00000f5a, 0x01000800, 0x00000000, 0x078bfbff);
  12. break;

当然,不要忘记在guest_amd64_helpers.c的顶部包含<cpuid.h>

相关问题