The Windows' debugging API uses a registry entry to know which debugger to invoke when an unhandled exception occurs (see On exceptions for some details). Two values in key
[MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug]
Determine the behavior:
This is the command line used to launch the debugger
(it uses two printf
formats
(%ld) to pass context dependent
information to the debugger). You should put here a
complete path to your debugger
(winedbg can of course be used, but
any other Windows' debugging API aware debugger will do).
The path to the debugger you choose to use must be reachable
via one of the DOS drives configured under /dosdevices in
your $WINEPREFIX or ~/.wine folder.
If this value is zero, a message box will ask the user if he/she wishes to launch the debugger when an unhandled exception occurs. Otherwise, the debugger is automatically started.
A regular Wine registry looks like:
[MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug] 957636538 "Auto"=dword:00000001 "Debugger"="winedbg %ld %ld"
Note 1: Creating this key is mandatory. Not doing so will not fire the debugger when an exception occurs.
Note 2: wineinstall (available in Wine source) sets up this correctly. However, due to some limitation of the registry installed, if a previous Wine installation exists, it's safer to remove the whole
[MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug]key before running again wineinstall to regenerate this key.
winedbg can be configured through a number of options. Those options are stored in the registry, on a per user basis. The key is (in my registry)
[HKCU\\Software\\Wine\\WineDbg]
Those options can be read/written while inside winedbg, as part of the debugger expressions. To refer to one of these options, its name must be prefixed by a $ sign. For example,
set $BreakAllThreadsStartup = 1
sets the option BreakAllThreadsStartup
to
TRUE.
All the options are read from the registry when winedbg starts (if no corresponding value is found, a default value is used), and are written back to the registry when winedbg exits (hence, all modifications to those options are automatically saved when winedbg terminates).
Here's the list of all options:
BreakAllThreadsStartup
Set to TRUE if at all threads start-up the debugger stops set to FALSE if only at the first thread startup of a given process the debugger stops. FALSE by default.
BreakOnCritSectTimeOut
Set to TRUE if the debugger stops when a critical section times out (5 minutes); TRUE by default.
BreakOnAttach
Set to TRUE if when winedbg attaches to an existing process after an unhandled exception, winedbg shall be entered on the first attach event. Since the attach event is meaningless in the context of an exception event (the next event which is the exception event is of course relevant), that option is likely to be FALSE.
BreakOnFirstChance
An exception can generate two debug events. The first
one is passed to the debugger (known as a first
chance) just after the exception. The debugger can
then decide either to resume execution (see
winedbg's cont
command) or pass the exception up to the exception
handler chain in the program (if it exists)
(winedbg implements this through
the pass command). If none of the
exception handlers takes care of the exception, the
exception event is sent again to the debugger (known
as last chance exception). You cannot pass on a last
exception. When the
BreakOnFirstChance
exception is
TRUE, then winedbg is entered for
both first and last chance execptions (to
FALSE, it's only entered for last
chance exceptions).
AlwaysShowThunk
Set to TRUE if the debugger, when looking up for a symbol from its name, displays all the thunks with that name. The default value (FALSE) allows not to have to choose between a symbol and all the import thunks from all the DLLs using that symbols.
When setting WINEDEBUG
to +relay and debugging,
you might get a lot of output. You can limit the output by
configuring the value RelayExclude in the registry, located
under the key:
[HKCU\\Software\\Wine\\Debug]
Set the value of RelayExclude to a semicolon-separated list of calls to exclude. Example: "RtlEnterCriticalSection;RtlLeaveCriticalSection;kernel32.97;kernel32.98".
RelayInclude is an option similar to RelayExclude, except that functions listed here will be the only ones included in the output. Also see section 3.4.3.5 for more options.
If your application runs too slow with +relay to get meaningful output and you're stuck with multi-GB relay log files, but you're not sure what to exclude, here's a trick to get you started. First, run your application for a minute or so, piping it's output to a file on disk:
WINEDEBUG=+relay wine <appname.exe> &>relay.log
Then run this command to see which calls are performed the most:
awk -F'(' '{print $1}' < relay.log | awk '{print $2}' | sort | uniq -c | sort
Exclude the bottom-most calls with RelayExclude after making sure that they are irrelevant, then run your application again.