Disable AVX-optimized functions in glibc (LD_HWCAP_MASK, /etc/ld.so.nohwcap) for valgrind & gdb record

后端 未结 5 1902
闹比i
闹比i 2020-11-30 07:13

Modern x86_64 linux with glibc will detect that CPU has support of AVX extension and will switch many string functions from generic implementation to AVX-optimized version (

5条回答
  •  甜味超标
    2020-11-30 07:22

    Not the best or complete solution, just a smallest bit-editing kludge to allow valgrind and gdb record for the my task.

    Lekensteyn asks:

    how to mask out AVX/SSE without recompiling glibc

    I did full rebuild of unmodified glibc, which is rather easy in debian and ubuntu: just sudo apt-get source glibc, sudo apt-get build-dep glibc and cd glibc-*/; dpkg-buildpackage -us -uc (manual to get the ld.so without stripped debugging information.

    Then I did binary (bit) patching of the output ld.so file, in the function used by __get_cpu_features. Target function was compiled from get_common_indeces of source file sysdeps/x86/cpu-features.c under the name of get_common_indeces.constprop.1 (it is just next after the __get_cpu_features in the binary code). It has several cpuids, first one is cpuid eax=1 "Processor Info and Feature Bits"; and later there is check "jle 0x6" and jump down around the code "cpuid eax=7 ecx=0 Extended Features" just to get AVX2 status. There is the code which was compiled into this logic:

    get_common_indeces (struct cpu_features *cpu_features,
                unsigned int *family, unsigned int *model,
                unsigned int *extended_model, unsigned int *stepping)
    { ...
      if (cpu_features->max_cpuid >= 7)
        __cpuid_count (7, 0,
               cpu_features->cpuid[COMMON_CPUID_INDEX_7].eax,
               cpu_features->cpuid[COMMON_CPUID_INDEX_7].ebx,
               cpu_features->cpuid[COMMON_CPUID_INDEX_7].ecx,
               cpu_features->cpuid[COMMON_CPUID_INDEX_7].edx);
    

    The cpu_features->max_cpuid was filled in init_cpu_features of the same file in __cpuid (0, cpu_features->max_cpuid, ebx, ecx, edx); line. It was easier to disable the if statement by replacing jle after cmp 0x6 with jg (byte 0x7e to 0x7f). (Actually this binary patch was reapplied manually to the __get_cpu_features function of real system ld-linux.so.2 - first jle before mov 7 eax; xor ecx,ecx; cpuid changed into jg.)

    Recompiled package and modified ld.so were not installed into the system; I used commandline syntax of ld.so ./my_program (or mv ld.so /some/short/path.so and patchelf --set-interpreter ./my_program).

    Other possible solutions:

    • try to use more recent valgrind & gdb record tools
    • try to use older glibc
    • implement missing instruction emulation in gdb record if it is not done
    • do source code patching around if (cpu_features->max_cpuid >= 7) in glibc and recompile
    • do source code patching around avx2-enabled string functions in glibc and recompile

提交回复
热议问题