Valgrind изменяет значение CPUID

Valgrind изменяет значения, возвращаемые инструкцией кода операции CPUID. Проще говоря, как заставить Valgrind учитывать настоящую инструкцию CPUID?

Для справки, это было обнаружено при возникновении странных ошибок при обнаружении поддержки aes-ni на старом компьютере, который, как я знаю, нет с набором инструкций aes-ni. Однако такое поведение явно меняет несколько значений.

Это поведение можно наблюдать с помощью valgrind-3.10.1, используя следующий код C:

#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, что неверно!


person cegfault    schedule 09.02.2018    source источник
comment
comment
@cegfault, обратите внимание, что valgrind по сути является эмулятором процессора. В отличие от некоторых инструментов профилирования, он считывает и выполняет машинный код, собирая данные (считая инструкции, а не время). Я не уверен, что вы сможете протестировать специфичный для ЦП код на valgrind, но я могу ошибаться.   -  person Myst    schedule 09.02.2018
comment
@Myst Да, Valgrind - это в основном виртуальный интерфейс (невозможно найти утечки памяти без виртуализации и управления библиотеками памяти). Тем не менее, если виртуальная система Valgrind жестко закодирована, то ее нельзя использовать для тестирования резервного кода (как в случае с aes-ni; у меня есть встроенные функции aesni для систем, которые его поддерживают, с необработанным C-кодом в качестве резервного варианта). . Я не могу протестировать этот резервный код на наличие утечек памяти, не переписав, как этот код вызывается, и я был бы разочарован, если бы Valgrind потребовал этого.   -  person cegfault    schedule 09.02.2018
comment
Кроме того, именно поскольку Valgrind является виртуальным, я предполагаю, что его обратная связь и флаги могут быть изменены. Легче изменить это (особенно отключить функцию), чем изменить установку с нуля.   -  person cegfault    schedule 09.02.2018
comment
@cegfault Я не говорю, что это невозможно сделать ... Я не эксперт по valgrind ... однако я бы рассмотрел (в качестве обходного пути) компиляцию кода с флагом компиляции, который вызывает резервный код. Это позволит вам тестировать код независимо от процессора, на котором вы работаете. Я знаю, что это неприятно, но это единственная идея, которая у меня есть, которая может помочь.   -  person Myst    schedule 09.02.2018
comment
Я думаю, что это может быть мой единственный вариант, к сожалению :(   -  person cegfault    schedule 09.02.2018


Ответы (1)


После пары дней отсутствия ответов оказалось, что Valgrind не может разрешить правильный ответ CPUID.

Поскольку Valgrind, по сути, работает внутри виртуальной среды, он ответит информацией CPUID об известном ему виртуальном процессоре, а не о системном процессоре.

Благодаря комментарию @Joe по следующей ссылке показан разговор об этом, начиная с 2014 года: https://sourceforge.net/p/valgrind/mailman/message/31960632/

Короче говоря, для Valgrind было бы неплохо иметь возможность устанавливать флаги CPUID в качестве флага времени выполнения (как было предложено в связанной ветке), но на сегодняшний день (февраль 2018 г.) такого флага не существует.

person cegfault    schedule 11.02.2018