Современный x86_64 linux с glibc обнаружит, что у процессора есть поддержка расширения AVX и переключит многие строковые функции из общей реализации на AVX-оптимизированная версия (с помощью диспетчеров ifunc: 1, 2).
Эта функция может быть хорошей для производительности, но она предотвращает использование нескольких инструментов, таких как valgrind (более старые libVEXs, до valgrind-3.8) и gdb "target record
" (Обратное выполнение) от правильной работы (Ubuntu "Z" 17.04 бета, gdb 7.12.50.20170207-0ubuntu2, gcc 6.3.0-8ubuntu1 20170221, Ubuntu GLIBC 2.24-7ubuntu2):
$ cat a.c
#include <string.h>
#define N 1000
int main(){
char src[N], dst[N];
memcpy(dst, src, N);
return 0;
}
$ gcc a.c -o a -fno-builtin
$ gdb -q ./a
Reading symbols from ./a...(no debugging symbols found)...done.
(gdb) start
Temporary breakpoint 1 at 0x724
Starting program: /home/user/src/a
Temporary breakpoint 1, 0x0000555555554724 in main ()
(gdb) record
(gdb) c
Continuing.
Process record does not support instruction 0xc5 at address 0x7ffff7b60d31.
Process record: failed to record execution log.
Program stopped.
__memmove_avx_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:416
416 VMOVU (%rsi), %VEC(4)
(gdb) x/i $pc
=> 0x7ffff7b60d31 <__memmove_avx_unaligned_erms+529>: vmovdqu (%rsi),%ymm4
Из реализации gdb "целевой записи" появляется сообщение об ошибке "Process record does not support instruction 0xc5
", поскольку инструкции AVX не поддерживаются механизмом записи/воспроизведения (иногда проблема обнаруживается в функции _dl_runtime_resolve_avx
): https://sourceware.org/ml/gdb/2016-08/msg00028.html "некоторые инструкции AVX не поддерживаются записью процесса", https://bugs.launchpad.net/ubuntu/+source/gdb/+bug/1573786, https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=836802, https://bugzilla.redhat.com/show_bug.cgi?id=1136403 p >
Решение, предложенное в https://sourceware.org/ml/gdb/2016-08/msg00028.html "Вы можете перекомпилировать libc (таким образом, ld.so) или взломать __init_cpu_features и, следовательно, __cpu_features во время выполнения (см. например strcmp)." или установить LD_BIND_NOW=1
, но перекомпилированный glibc все еще имеет AVX, а ld bind-now не помогает.
Я слышал, что в glibc есть конфигурации /etc/ld.so.nohwcap
и LD_HWCAP_MASK
. Могут ли они использоваться для отключения отправки ifunc на оптимизированные по AVX строковые функции в glibc?
Как glibc (rtld?) обнаруживает AVX, используя cpuid
, с /proc/cpuinfo
(возможно, нет), или HWCAP aux ( Команда LD_SHOW_AUXV=1 /bin/echo |grep HWCAP
дает AT_HWCAP: bfebfbff
)?