Wine and Valgrind

Valgrind (http://www.valgrind.org/) is a set of tools aimed at finding bugs and performance problems in programs. By default, it catches reads of uninitialized memory, accesses to inaccessible memory, and memory leaks. It's useful for debugging wine itself, as well as windows apps running on Wine. (See "Debugging Mozilla with Valgrind")

You need Valgrind 3.8.0 or newer to avoid valgrind bug 275673. If your distribution's version isn't new enough, see "Building Valgrind" below.

To make Wine play properly with valgrind, you need to build Wine yourself after installing Valgrind; see "Building Wine" below.

To ignore errors not due to Wine, you will want to use the Valgrind suppressions file Dan Kegel has put together.

Building Valgrind

If you don't have automake and autoconf installed, install them first, e.g. with 'sudo apt-get install automake autoconf'.

Here's how to build Valgrind from svn:

svn co svn://svn.valgrind.org/valgrind/trunk valgrind
cd valgrind
sh autogen.sh
./configure --prefix=/usr/local/valgrind-svn
make
sudo make install
# Then, optionally, if your system's valgrind include headers are too old:
sudo mv /usr/include/valgrind /usr/include/valgrind.old
sudo ln -s /usr/local/valgrind-svn/include/valgrind /usr/include

Don't link valgrind with binutils.gold; it won't work. You currently have to use plain old binutils.

Additional Valgrind patches

You may want to apply some or all of these when building valgrind:

  • https://bugs.kde.org/show_bug.cgi?id=218689 has a patch that lets you avoid tracing certain child processes (e.g. python)

  • https://bugs.kde.org/show_bug.cgi?id=222604 has a patch that lets you write suppressions with token that indicates end of stack (e.g. if you have mystery stack traces that consist solely of 'calloc', you can suppress those without suppressing all calloc stacks.)

  • https://bugs.kde.org/show_bug.cgi?id=253657 has a patch that lets you fully run wine on valgrind on x86_64 hosts. Valgrind currently doesn't support segment registers (and segmented addresses) that Wine (and Windows) code require on x86_64 machines. If you intend to run Valgrind + Wine on such CPU, you should compile Valgrind yourself including this patchset. Work is underway with Valgrind developers to integrate this code into mainstream Valgrind.

Building Wine

Install Valgrind first, since Wine needs Valgrind's include files.

Configure Wine as normal, but use CFLAGS="-g -O1". (This will slow Wine down slightly, but give better stacks.)

Check that Wine found Valgrind's header files by doing

grep VALGRIND include/config.h

If that doesn't show

#define HAVE_VALGRIND_MEMCHECK_H 1 
#define HAVE_VALGRIND_VALGRIND_H 1

then something went wrong.

Then build Wine as usual with make.

Additional Wine patches

If you want to use one of Valgrind's thread checking tools DRD or Helgrind, it is strongly recommended to apply the patch attached to http://bugs.winehq.org/show_bug.cgi?id=24164 before building Wine. This patch informs Valgrind's data race detection tools that e.g. EnterCriticalSection() and LeaveCriticalSection() are synchronization primitives and also suppresses several reports about uninteresting conflicting memory accesses in Wine itself. Without this patch both tools will report so much conflicting memory accesses that these tools are unusable.

Running Wine under Valgrind

Because of the way Wine is started, you must use the --trace-children option in valgrind to make it work. To make DIB sections work under valgrind, you must also use --vex-iropt-precise-memory-exns=yes. To avoid spurious warnings about writing below the stack, you must also use --workaround-gcc296-bugs=yes. For example:

valgrind --trace-children=yes --vex-iropt-precise-memory-exns=yes --workaround-gcc296-bugs=yes --suppressions=$HOME/valgrind-suppressions wine foo.exe

where $HOME/valgrind-suppressions is http://winezeug.googlecode.com/svn/trunk/valgrind/valgrind-suppressions

Note that this command will also trace the wineserver if this is the first Wine application running. As Valgrind is pretty intensive on CPU, you can speed things up quite a bit by not running the wineserver under Valgrind. Here's the way to do it: 1/ start a dummy program under Wine (I like winemine, pick up your own), 2/ start valgrind for wine as you would normally do.

The wineserver will be started by step 1/, not 2/ and won't be run under Valgrind.

The need for --vex-iropt-precise-memory-exns=yes is documented at http://valgrind.org/docs/manual/manual-core.html#manual-core.signals

Please keep in mind that when analyzing applications built with Microsoft Visual Studio that the debug version of the MSVC runtime library always initializes memory allocated via malloc(). This defeats Valgrind's ability to detect uninitialized memory accesses. See also Memory Management and the Debug Heap for more information.

Controlling Memory Leak logging

Valgrind by default will give you a count of memory leaks at the end of the run. To get more info, add the --leak-check=full flag when running Valgrind, e.g.

valgrind --trace-children=yes --vex-iropt-precise-memory-exns=yes --workaround-gcc296-bugs=yes --leak-check=full wine foo.exe

You'll likely get some generic leak errors: for module loading (some modules are not unloaded, and some glibc version leak memory in dlopen:ed libraries), and wine's X11 drivers loading (the thread data structure is not free upon last thread exit). You can safely ignore those.

You can make Valgrind ignore less-certain memory leaks with the --show-possibly-lost=no option.

You can make Valgrind give you a stack backtrace of the point where the memory block was allocated, which is terrifically helpful. It also makes valgrind run even slower. If you want this, you have to turn it on with --track-origins=yes.

Known Problems

If you see lots of warnings about HEAP_CreateSubHeap, it probably means you're running an old version of Valgrind and are running into wine bug 20303. See 'Building Valgrind' above for how to get a newer version.

If you see lots of warnings about invalid four byte reads in the last three bytes of allocations, this may be false positives from vectorized string operations ( see https://bugs.kde.org/show_bug.cgi?id=264936 ); try --partial-loads-ok=yes

Running Wine's conformance tests under Valgrind

To run Wine tests under Valgrind, set the WINETEST_WRAPPER and VALGRIND_OPTS variables, e.g.

export VALGRIND_OPTS="--trace-children=yes --track-origins=yes --gen-suppressions=all --suppressions=$HOME/valgrind-suppressions --leak-check=no --num-callers=20  --workaround-gcc296-bugs=yes --vex-iropt-precise-memory-exns=yes"
PATH=/usr/local/valgrind-svn/bin:$PATH
WINETEST_WRAPPER=valgrind make -k test > test.log 2>&1

If you want to also look for memory leaks, change --leak-check=no to --leak-check=full. However, memory leak errors are a dime a dozen in conformance tests, and don't always need to be fixed.

That --suppressions=$HOME/valgrind-suppressions refers to the following file, which you have to download separately:

It suppresses warnings known to be bogus, not Wine's fault, or too hard to deal with for now.

If you see lots of spurious errors (e.g. in ld.so or Xlib) just copy the suppressions from the log file into valgrind-suppressions and rerun. If that helped, please email your new suppressions file to dank@kegel.com, and I'll update my copy.

See also MakeTestFailures for some tips on how to set up your system to reduce test failures.

It's a good idea to delete ~/.wine before running tests, just in case you've installed some app that interferes with them somehow (e.g. iTunes).

Here's an example script to build and run the whole test suite under Valgrind, and split up the results:

Here's a script that splits valgrind log files up by wine test:

This puts the warnings from e.g. comctl32/tests/listview.c into the file vg-comctl32_listview.txt.

Test results

See http://kegel.com/wine/valgrind/ for Dan Kegel's Valgrind logs from running the entire wine test suite.

Austin English publishes Valgrind logs from the entire wine test suite too.

Note: WINEDEBUG can expose undefined variables earlier

Valgrind doesn't warn when uninitialized values are simply passed from one place to another; it only warns when they're used to make some decision or produce some output. If you're tracking down a particular warning, you might find it helpful to print out the values involved just to force Valgrind to show you whether they're defined. One easy way to do this is to look at the source files involved for TRACE() statements that already print out the variables of interest. If there are any, you can activate them by setting the environment variable WINEDEBUG=+foo or WINEDEBUG=+foo,+bar, where foo and bar are the argument to the macro WINE_DEFAULT_DEBUG_CHANNEL at the top of the involved source files. So for example, if you're tracking down a warning in test_profile_existing() in kernel32/tests/profile.c, you would look at the top of kernel32/profile.c, see the line WINE_DEFAULT_DEBUG_CHANNEL(profile), and rerun that file's tests with

cd dlls/kernel32/tests
WINEDEBUG=+profile RUNTEST_USE_VALGRIND=1 ../../../tools/runtest -P wine -M kernel32.dll -T ../../.. -p kernel32_test.exe.so profile.c > log 2>&1

That will trigger the TRACE() calls in kernel32/profile.c. Oh, boy will it ever. Sometimes it's a bit overwhelming. In theory, we'd want to fix all the extra Valgrind warnings this produces, but in practice, just grit your teeth and ignore the extra new messages not related to the problem you're tracking down.

Note: Dynamic unloading of libraries confuses Valgrind

Valgrind output can be misleading >:> because it partly resolves addresses to file and line numbers too late, i.e. after a library has been unloaded and the memory re-used for other purposes. That leads to backtraces that don't make sense, here's an example:

 48 bytes in 1 blocks are definitely lost 
    at  notify_alloc (heap.c:254)
    by  RtlAllocateHeap (heap.c:1701)
    by  wodWrite (wavemap.c:329)
    by  wodPrepare (wavemap.c:386)
    by  ??? (in /home/austin/wine-git/dlls/msacm32.drv/msacm32.drv.so)
    by  DRIVER_SendMessage (driver.c:136)
    by  SendDriverMessage (driver.c:156)
    by  MCI_SendCommandFrom32 (mci.c:892)
    by  MCI_FinishOpen (mci.c:927)
    ...
    by  test_openCloseWAVE (mci.c:517)
  1. wodPrepare never calls wodWrite.

  2. MCI_FinishOpen calls Open, not Write.

  3. The line numbers do not match function call sites or allocations (wavemap.c:386 is a goto).

Now comment out the two calls to FreeLibrary in dlls/winmm/driver.c:CloseDriver and the log makes perfect sense:

 48 bytes in 1 blocks are definitely lost
    at  RtlAllocateHeap (heap.c:254)
    by  WAVE_mciOpenFile (mciwave.c:465)
    by  WAVE_mciOpen (mciwave.c:554)
    by  MCIWAVE_DriverProc (mciwave.c:1726)
    by  SendDriverMessage (driver.c:136)
    by  MCI_SendCommandFrom32 (mci.c:892)
    by  MCI_FinishOpen (mci.c:927)
    ...
    by  test_openCloseWAVE (mci.c:517)

Heap Tail Check

Until 29 Jan 2009, Wine's heap wasn't instrumented sufficiently to give best results with valgrind. One problem was that Wine wasn't leaving an inaccessible redzone after each allocation. This was http://bugs.winehq.org/show_bug.cgi?id=21355 This is fixed in the trunk, though there may be a buglet left, see http://bugs.winehq.org/show_bug.cgi?id=21553 (which includes patch to prevent false positives at shutdown).

No special settings are needed to turn on the heap tail check.

Tweaking use-after-free and overrun sensitivity

There are two constants in the Wine sources which might be worth tweaking under some circumstances.

MAX_FREE_PENDING controls how long freed blocks are kept out of circulation (this helps detect use-after-free errors). It is currently 1024. If you think your app is hanging on to freed pointers for a long time, you might want to increase that and recompile Wine.

HEAP_TAIL_EXTRA_SIZE gives the size of the redzone at the end of each block. If your app uses an array or struct of really big structs, this might need to be increased to catch overrun errors. (But watch out; increasing it beyond 32 bytes or so caused strange false positives for me.)

Mac OS X support

Valgrind's trunk now supports the Mac; see Mac OS X now supported on the Valgrind trunk - May 28th, 2009 by Nicholas Nethercote /!\ Note: On the mac, if you want line numbers, don't forget to tell xcode to generate a .dSYM file. You can also use gdb after the fact to look up line numbers.

Alternatives that run on Windows

There are a number of similar tools that run on Windows rather than Linux:

That said, Windows developers might well want to run their apps on Wine just to get Valgrind, since Valgrind offers some features those tools don't (not least of which is, it's free, it's fast and it can handle Mac and Linux apps as well).


CategoryQualityAssurance CategoryDevelopment CategoryThirdParty

Wine and Valgrind (last edited 2013-05-10 20:04:27 by KyleAuble)