title: Disable AVX-optimized functions in glibc (LD_HWCAP_MASK, /etc/ld.so.nohwcap) for valgrind & gdb record
body: <p>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 <a href="http://code.metager.de/source/xref/gnu/glibc/sysdeps/x86_64/multiarch/memcpy-avx-unaligned.S" rel="noreferrer">AVX-optimized</a> version (with help of ifunc dispatchers: <a href="http://www.agner.org/optimize/blog/read.php?i=167" rel="noreferrer">1</a>, <a href="https://lwn.net/Articles/691932/" rel="noreferrer">2</a>). </p>
  
  <p>This feature can be good for performance, but it prevents several tool like valgrind (<a href="https://sourceforge.net/p/valgrind/mailman/message/29184629/" rel="noreferrer">older libVEXs</a>, before <a href="https://lwn.net/Articles/511556/" rel="noreferrer">valgrind-3.8</a>) and gdb's "<code>target record</code>" (<a href="https://sourceware.org/gdb/onlinedocs/gdb/Reverse-Execution.html" rel="noreferrer">Reverse Execution</a>) from working correctly (Ubuntu "Z" 17.04 beta, <strong>gdb 7.12</strong>.50.20170207-0ubuntu2, gcc 6.3.0-8ubuntu1 20170221, Ubuntu GLIBC 2.24-7ubuntu2):</p>
  
  <pre><code>$ cat a.c
  #include &lt;string.h&gt;
  #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
  =&gt; 0x7ffff7b60d31 &lt;__memmove_avx_unaligned_erms+529&gt;:   vmovdqu (%rsi),%ymm4
  </code></pre>
  
  <p>There is error message "<code>Process record does not support instruction 0xc5</code>" from gdb's implementation of "target record", because AVX instructions are not supported by the record/replay engine (sometimes the problem is detected on <code>_dl_runtime_resolve_avx</code> function): <a href="https://sourceware.org/ml/gdb/2016-08/msg00028.html" rel="noreferrer">https://sourceware.org/ml/gdb/2016-08/msg00028.html</a> "some AVX instructions are not supported by process record", <a href="https://bugs.launchpad.net/ubuntu/+source/gdb/+bug/1573786" rel="noreferrer">https://bugs.launchpad.net/ubuntu/+source/gdb/+bug/1573786</a>, <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=836802" rel="noreferrer">https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=836802</a>, <a href="https://bugzilla.redhat.com/show_bug.cgi?id=1136403" rel="noreferrer">https://bugzilla.redhat.com/show_bug.cgi?id=1136403</a></p>
  
  <p>Solution proposed in <a href="https://sourceware.org/ml/gdb/2016-08/msg00028.html" rel="noreferrer">https://sourceware.org/ml/gdb/2016-08/msg00028.html</a> "You can recompile libc (thus ld.so), or hack __init_cpu_features and thus __cpu_features at runtime (see e.g. strcmp)." or set <code>LD_BIND_NOW=1</code>, but recompiled glibc still has AVX, and ld bind-now doesn't help.</p>
  
  <p>I heard that there are <code>/etc/ld.so.nohwcap</code> and <code>LD_HWCAP_MASK</code> configurations in glibc. Can they be used to disable ifunc dispatching to AVX-optimized string functions in glibc? </p>
  
  <p>How does glibc (rtld?) detects AVX, using <code>cpuid</code>, with <code>/proc/cpuinfo</code> (probably not), or HWCAP <a href="https://lwn.net/Articles/519085/" rel="noreferrer">aux</a> (<code>LD_SHOW_AUXV=1 /bin/echo |grep HWCAP</code> command gives <code>AT_HWCAP: bfebfbff</code>)?</p>