Diff for "Wine and Valgrind"

Differences between revisions 86 and 87

Deletions are marked like this. Additions are marked like this.
Line 46: Line 46:

Even with the latest Wine from git, you'll probably want to apply one patch to Wine:
 * Valgrind mangles the environment (see https://bugs.kde.org/show_bug.cgi?id=215914). To work around this, apply the patch from http://www.winehq.org/pipermail/wine-patches/2009-November/081801.html

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.

You must build Valgrind from svn to work around wine bug 20303; 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

Note: As of this writing, you must build Valgrind from svn to work around wine bug 20303.

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

I usually do "svn info" to find out the revision number rrrrr of valgrind, then install it into /usr/local/valgrind-rrrrr. That way I can have multiple copies installed if I need it.

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:

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 depend && 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. For example:

valgrind --trace-children=yes --vex-iropt-precise-memory-exns=yes wine foo.exe

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 --tool=memcheck --trace-children=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.

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=full --num-callers=20  --workaround-gcc296-bugs=yes"
PATH=/usr/local/valgrind-svn/bin:$PATH
WINETEST_WRAPPER=valgrind make -k test > test.log 2>&1

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.

Note: WINEDEBUG can expose undefined variables earlier

Valgrind doesn't warn when uninitialised 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.

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

Wine and Valgrind (last edited 2010-09-06 17:08:26 by DanKegel)