Wine and Valgrind
Valgrind 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.
- You need Valgrind 3.8.0 or newer to avoid Valgrind Bug #275673 (v3.8 was released in late summer 2012, but just in case there are still a few people that haven't upgraded).
- To get the full power of Valgrind while debugging Wine, you need to build Wine from source after installing Valgrind. You'll also want to switch off certain compiler optimizations; the "developer tools" section of the BuildingWine page has more details.
- Valgrind will work on MacOSX (starting with partial support in MacOSX v10.8 "Mountain Lion"). If you want line numbers with Valgrind on Mac, don't forget to tell Xcode to generate a .dSYM file, though you can also use gdb after the fact to look up line numbers.
- In applications built with the debug version of the MS Visual C/C++ runtime, memory allocated via malloc() is always initialized. This obscures any uninitialized memory accesses that would normally appear from Valgrind (see Memory Management and the Debug Heap at MSDN for the full story).
- 1 Running Wine under Valgrind
- 2 Conformance Tests under Valgrind
- 3 Changes to Wine Source
- 4 Alternatives to Valgrind
- 5 See Also
Running Wine under Valgrind
To analyze a program running on Wine with Valgrind, just call valgrind with the appropriate options in front of the normal wine command. For example:
valgrind --trace-children=yes --vex-iropt-register-updates=allregs-at-mem-access --workaround-gcc296-bugs=yes wine foo.exe
Note that this command will also trace the ["wineserver"] if foo.exe is the first Wine application running. Unless you're specifically looking to debug wineserver (usually you'll be more interested in specific dlls), this is a waste of resources. Valgrind can be pretty intensive on the CPU so you can speed things up quite a bit by not starting the wineserver under Valgrind.
To do that, just start a dummy program under Wine first (e.g. notepad or winemine), then without closing that program, start your desired program through wine and valgrind as you normally would.
Valgrind Options Relevant for Wine
Over the years, several Valgrind options have turned out to be necessary, or at least very helpful, when analyzing Wine. Two in particular are necessary for Wine to function well under Valgrind:
- --trace-children=yes is necessary because wine starts new processes for individual programs
- --vex-iropt-register-updates=allregs-at-mem-access ensures that bitmap-related code, such as GetBitmapBits(), works under Valgrind
Several more are useful for suppressing known bugs or exceptions in Wine:
- --workaround-gcc296-bugs=yes quiets warnings about accesses slightly below the stack pointer. This is due to a known but benign piece of code in Wine's ntdll (see Bug #26263 for details)
- --suppressions=path/to/suppression-file lets you pass a file with custom suppression rules to Valgrind. Austin English maintains a collection of suppression files for Wine at his github repo
This option can be repeated with multiple files
- --partial-loads-ok=yes silences warnings for when bit-alignments overlap both addressable and illegal ranges. In particular, try this if the last three bytes of allocations throw a lot of "Invalid Read of Size N" warnings.
There's a good chance these are false positives from vectorized string operations (Valgrind Bug Report #264936 has more info). In the Valgrind bug report, someone also mentions using GCC with the -fno-builtin-strdup compiler option to make the warnings disappear. It hasn't been tested with Wine, but the "Compiler Optimizations" section of Building Wine has more details about changing compiler flags while building Wine.
Controlling Memory Leak Reports
There are a few more Valgrind options that let you fine-tune how much it reports about memory leaks. By default, Valgrind only gives a count of memory leaks detected at the end of execution.
To get more info, you want to pass the --leak-check=full flag when running Valgrind. This will give you individual reports about certain types of memory leaks (but not all). Once this option is set, you can use several other options to specify which kinds of memory leaks you want detailed reports for:
- --show-leak-kinds=definite,possible only reports unfreed blocks with no pointers or that depend on interior pointers (the default)
- --show-possibly-lost=no or --show-leak-kinds=definite only reports unfreed blocks with no pointers
- --show-reachable=yes or --show-leak-kinds=all reports all forms of unfreed blocks, even trivial ones with clear pointers
Finally, by passing the --track-origins=yes option, you can ask Valgrind to give you stack backtraces to the point where a leaky memory block was allocated. This is terrifically helpful for debugging, but it has the downside of making valgrind run even slower.
Conformance Tests under Valgrind
To run Wine's ConformanceTests under Valgrind, you mainly need to 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-ignore --suppressions=$HOME/valgrind-suppressions-external --num-callers=20 --workaround-gcc296-bugs=yes --vex-iropt-register-updates=allregs-at-mem-access" WINETEST_WRAPPER=valgrind make -k test > test.log 2>&1
Changes to Wine Source
There are also some tweaks you can make to the Wine source code itself that might help you uncover other problems. First, the Wine source defines two constants that can be quickly changed and might reveal more bugs:
- MAX_FREE_PENDING controls how long freed blocks are kept out of circulation and is set to 1024 by default. If you think your app is hanging on to freed pointers longer than it should, increasing it and recompiling wine might help Valgrind detect use-after-free errors.
- HEAP_TAIL_EXTRA_SIZE gives the size of the redzone at the end of each block. If your app nests really big structs within another struct or array, you might need to increase this to catch overrun errors. Watch out though because increasing it beyond 32 or so bytes can cause strange false positives sometimes.
Additional Wine patches
There are also a few patches that have accumulated on Bugzilla over the years to make Wine play better with Valgrind. You might be able to get some use out of them for debugging (or even refine them and help get them accepted into the wine master branch):
- Clear slots in new argv (Bug #14359)
- Co-operate with valgrind at execv (Bug #14361)
- Enhance loader and wine_main_preload_info for valgrind (Bug #14364)
- Do not touch high address space (initial stack, user_space_limit) (Bug #14365)
- Co-operate with valgrind when switching stacks (Bug #14366)
- Adjust timeout interval for virtulaizers (Bug #14370)
If you want to use one of Valgrind's thread checking tools too (DRD or Helgrind), you're strongly recommended to apply the patch from Bug Report #24164 before building Wine. This patch informs these tools that some functions, like EnterCriticalSection() and LeaveCriticalSection(), are synchronization primitives. It also suppresses uninteresting memory access conflicts in Wine itself, and without this patch, either tool will report too many warnings to be useful.
Alternatives to Valgrind
At least on Unix and among free, open-source tools, Valgrind is arguably the gold standard for dynamic analysis suites. It offers many features that most other execution-analysis tools don't (not least of which that it's free, it's fast and it can handle Mac and Linux apps too). In fact, if you're a Windows developer, you might want to consider testing your program on Wine just to get Valgrind.
If for whatever reason you don't want to use Valgrind though, or you want to run a tool natively on Windows, there are several free and commercial ones.
- Dr. Memory (memory checker based on the DynamoRIO framework)
- Supported on all platforms
- gperftools (Google Performance Tools for Unix)
- Includes an efficient malloc implementation, plus heap & call-graph profilers
- FastMM (fast memory-manager for C++ & Delphi programs)
- Also includes memory checking tools
- Only for Windows
- DUMA (memory checker based on Bruce Perens' older Electric Fence library)
- Supported on Unix and Windows
- Should still work but hasn't been updated since 2009
- Visual Leak Detector (memory leak detector for Microsoft Visual C++)
- Only on Windows)
- AMD CodeXL (profiling for both the CPU and GPU)
- Only for AMD processors...
- Consequently not available for Mac
- MS Application Verifier (Windows runtime test-suite)
- Runs several tests, including memory checking, on Windows applications
- Part of the Windows SDK and only available on Windows
- Debugging Tools for Windows (set of debuggers from Microsoft)
- Only for Windows naturally
- Unicom PurifyPlus (originally IBM Rational Purify)
- There are Linux & Mac versions too
- Parasoft Insure++ (memory-error checking suite)
- Also has Linux & Mac versions
- Borland DevPartner (wide set of testing tools)
- Particularly well-known for the BoundsChecker tool
- Only supported on Windows
- Deleaker (memory profiler and leak detector for Microsoft Visual C++)
- Only for Windows
- Software Verify C++ Suite (several different testing tools)
- Only for Windows
- Intel Inspector XE (memory checking and thread debugging)
- Only for Intel processors
- But otherwise supported on Windows, Mac OSX, and Linux
- Glowcode (memory checking, profiling, and tracing)
- Only for Windows
Most separate profiling tools will significantly affect Wine's performance. If this is a problem, you may be able to take a different approach: patch the wine DLL so it can detect errors itself.
This should give you much lower overhead but at the price of much more work for you, the developer. Also note that this will only work on DLLs that never share allocated memory outside the scope of the DLL.
- Debugging Mozilla with Valgrind has a good case-study showing how to use Valgrind
- Wine bugs involving or detected by Valgrind
- Valgrind bugs with Wine mentioned in the comments