Search code examples
valgrind

Suppressing Valgrind warnings


A colleague asked for help finding a tough-to-reproduce SIGSEGV in a program, so I'm running it through valgrind to look for any memory issues.

Unfortunately, I end up with this:

$ valgrind --track-origins=yes sim-server
==128768== 
==128768== More than 10000000 total errors detected.  I'm not reporting any more.
==128768== Final error counts will be inaccurate.  Go fix your program!
==128768== Rerun with --error-limit=no to disable this cutoff.  Note
==128768== that errors may occur in your program without prior warning from
==128768== Valgrind, because errors are no longer being displayed.
==128768==

Everything I can see comes from libasound.2.0.0 or libportaudio.so.2.0.0 and they all have the same warning:

Conditional jump or move depends on uninitialized value(s)

Example:

==130835== Conditional jump or move depends on uninitialised value(s)
==130835==    at 0x483865C: malloc (vg_replace_malloc.c:306)
==130835==    by 0x483ADE7: realloc (vg_replace_malloc.c:834)
==130835==    by 0x48A209A: ??? (in /usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0)
==130835==    by 0x48A251F: ??? (in /usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0)
==130835==    by 0x48A5944: ??? (in /usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0)
==130835==    by 0x4878EA6: start_thread (pthread_create.c:477)
==130835==    by 0x4CECA2E: clone (clone.S:95)
==130835==  Uninitialised value was created by a stack allocation
==130835==    at 0x4E626C0: ??? (in /usr/lib/x86_64-linux-gnu/libasound.so.2.0.0)

After installing libportaudio2-dbysym and libasound2-dbgsym, that becomes:

==135367== Thread 3:
==135367== Conditional jump or move depends on uninitialised value(s)
==135367==    at 0x483865C: malloc (vg_replace_malloc.c:306)
==135367==    by 0x483ADE7: realloc (vg_replace_malloc.c:834)
==135367==    by 0x48A209A: PaAlsaStreamComponent_RegisterChannels (pa_linux_alsa.c:4003)
==135367==    by 0x48A251F: PaAlsaStream_SetUpBuffers (pa_linux_alsa.c:4114)
==135367==    by 0x48A5944: CallbackThreadFunc (pa_linux_alsa.c:4355)
==135367==    by 0x4878EA6: start_thread (pthread_create.c:477)
==135367==    by 0x4CECA2E: clone (clone.S:95)
==135367==  Uninitialised value was created by a stack allocation
==135367==    at 0x4E626C0: refine_back_time_and_size (pcm_ioplug.c:263)

I can see three logical explanations:

  1. libportaudio2+libasound2 are volatile and unusable dependencies that could crash at any moment
    • Since it seems to be widely used, I suspect this is not true.
  2. My integration is to blame
    • All of the uninitialized stack values come from libasound2
    • I even get errors from inside of Pa_Initialize() which is not a function that requires me to set anything up ahead of time.
    • It is still possible, but it wouldn't explain everything.
  3. These messages can be ignored.
    • If I suppress portaudio/asound messages, I can focus on the things my program does wrong

How can I suppress Conditional jump or move... warnings originating from libportaudio.so.2.0.0 in Valgrind?

Using this answer, Valgrind's documentation on supressing errors and Valgrind's documentation on writing suppression files, I've come up with this:

$ cat suppress.val
{
  ignore_asound_cond_jump_0
  Memcheck:Cond
  obj:*/libasound.so*
}
{
  ignore_pa
  Memcheck:Cond
  obj:/usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0
}
{
  ignore_pcm
  Memcheck:Cond
  obj:/usr/lib/x86_64-linux-gnu/alsa-lib/libasound_module_pcm_pulse.so
}
{
  ignore_pa_8
  Memcheck:Value8
  obj:/usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0
}
{
  ignore_pulse
  Memcheck:Cond
  obj:/usr/lib/x86_64-linux-gnu/libpulse.so.0.23.0
}
{
  ignore_pulsecommon
  Memcheck:Cond
  obj:/usr/lib/x86_64-linux-gnu/pulseaudio/libpulsecommon-14.2.so
}
{
  ignore_asound_ioctl
  Memcheck:Param
  ioctl(generic)
  fun:*
  obj:/usr/lib/x86_64-linux-gnu/libasound.so.2.0.0
}
{
  ignore_pa_poll
  Memcheck:Param
  poll(timeout)
  fun:*
  obj:/usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0
}
{
  ignore_pa_malloc
  Memcheck:Param
  malloc
  fun:*
  obj:/usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0
}
$ valgrind --suppressions=suppress.val --track-origins=yes sim-sound
...
--135517-- 
--135517-- used_suppression:  27290 ignore_asound_cond_jump_0 suppress.val:2
--135517-- used_suppression:   7914 ignore_pulsecommon suppress.val:27
--135517-- used_suppression:  17884 ignore_pcm suppress.val:12
--135517-- used_suppression: 471481 ignore_pa suppress.val:7
--135517-- used_suppression:   3518 ignore_pulse suppress.val:22
--135517-- used_suppression:   1760 ignore_pa_8 suppress.val:17
--135517-- used_suppression:    606 ignore_pa_poll suppress.val:45
--135517-- used_suppression:     22 ignore_asound_ioctl suppress.val:38
==135517== 
==135517== ERROR SUMMARY: 60721 errors from 7 contexts (suppressed: 530475 from 1044)

That takes care of a lot of warnings, but the malloc one described above is not suppressed. It's not just malloc, others such as memmove from vg_replace_strmem.c is also an offender. Those source files are not in my program and the stack allocation is not in my program. I've been playing with the ignore_pa_malloc receipie, but I'm really having trouble finding a rule set that will work.


Solution

  • Paul Floyd has a suggestion about how to fix the problem. That's probably better. This answers how to suppress the error. Note that if there is a problem with the portaudio integration, this could mask that problem.

    The trick was to use a literal "..." line in the suppression file.

    The following rule says: Ignore "Conditional jump or move depends on uninitialised value(s)" errors that occur within libportaudio.so.2.0.0.

    {
      ignore_pa
      Memcheck:Cond
      obj:/usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0
    }
    

    However, the following occurs in libc.so:

    ==130835== Conditional jump or move depends on uninitialised value(s)
    ==130835==    at 0x483865C: malloc (vg_replace_malloc.c:306)
    ==130835==    by 0x483ADE7: realloc (vg_replace_malloc.c:834)
    ==130835==    by 0x48A209A: ??? (in /usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0)
    ==130835==    by 0x48A251F: ??? (in /usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0)
    ==130835==    by 0x48A5944: ??? (in /usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0)
    ==130835==    by 0x4878EA6: start_thread (pthread_create.c:477)
    ==130835==    by 0x4CECA2E: clone (clone.S:95)
    

    The answer is a slight change to the recepie:

    {
      ignore_pa
      Memcheck:Cond
      ...
      obj:/usr/lib/x86_64-linux-gnu/libportaudio.so.2.0.0
    }
    

    The ... will cause us to ignore any Memcheck:Cond for any error with libportaudio.so.2.0.0 in the stack. This means errors in libc.so will not be raised if they came through libportaudio.so.2.0.0.

    When reading documentation I thought ... was just a truncation, but it's actually literal. The Valgrind documentation says:

    A location line may also be simply "..." (three dots). This is a frame-level wildcard, which matches zero or more frames. Frame level wildcards are useful because they make it easy to ignore varying numbers of uninteresting frames in between frames of interest. That is often important when writing suppressions which are intended to be robust against variations in the amount of function inlining done by compilers.