Translations of this page: http://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Flag_of_the_People%27s_Republic_of_China.svg/22px-Flag_of_the_People%27s_Republic_of_China.svg.png简体中文

Debug Logging

WINEDEBUG is an environment variable that turns debugging messages on or off.

Syntax

WINEDEBUG=[class][+/-]channel[,[class2][+/-]channel2]

class is optional and can be one of the following: err, warn, fixme, or trace. If class is not specified, all debugging messages for the specified channel are turned on. Each channel will print messages about a particular component of Wine. The following character can be either + or - to switch the specified channel on or off respectively. If there is no class part before it, a leading + can be omitted. Note that spaces are not allowed any where in the string.

channel specifies which debug channel to turn on or off. For complete list of channels run this command in the source dir

grep -r --include='*.c' --include='*.h' 'WINE_\(DEFAULT\|DECLARE\)_DEBUG_CHANNEL' dlls/ programs/

And with some more work we have sorted and formatted list in BASH (you may want to adjust number 26 near the end of this composite to match your indentation taste):

for modname in $(find dlls/ programs/ -mindepth 1 -type d | sort); do
  echo $(grep -rE --include='*.[ch]' '^WINE_(DEFAULT|DECLARE)_DEBUG_CHANNEL' $modname \
         | awk -F "[()]" '{print $2}' | sort | uniq) \
         | awk -v modname=$modname '{if (NF>0) printf("%-*s%s\n", 26, modname": ", $0)}';
done

Examples

  • WINEDEBUG=warn+all
    • will turn on all warning messages.
  • WINEDEBUG=warn+dll,+heap
    • will turn on DLL warning messages and all heap messages.
  • WINEDEBUG=fixme-all,warn+cursor,+relay
    • will turn off all FIXME messages, turn on cursor warning messages, and turn on all relay messages (API calls).
  • WINEDEBUG=+relay
    • will turn on all relay messages. For more control on including or excluding functions and dlls from the relay trace look into the [HKCU\Software\Wine\Debug] registry key (See UsefulRegistryKeys and the example below).

List of Debug Channels

accel

acledit

actctx

activeds

actxprxy

adpcm

advapi

advpack

alsa

amstream

animate

appbar

appwizcpl

aspi

atl

atom

avicap

avifile

bidi

bitblt

bitmap

browseui

button

cabinet

capi

cards

caret

cdrom

class

clipboard

clipping

clusapi

cmd

cmdlgtst

combo

comboex

comm

commctrl

commdlg

compstui

computername

console

coreaudio

cred

credui

crtdll

crypt

cryptasn

cryptdlg

cryptdll

cryptnet

cryptui

ctapi32

curses

cursor

d3d

d3d10

d3d7

d3d8

d3d9

d3d_caps

d3d_constants

d3d_decl

d3d_draw

d3drm

d3d_shader

d3d_surface

d3d_texture

d3dx

d3dx8

d3dxof

datetime

dbghelp

dbghelp_coff

dbghelp_dwarf

dbghelp_msc

dbghelp_stabs

dbghelp_symt

dc

dciman

ddeml

ddraw

ddraw_thunk

debug_buffer

debugstr

devenum

dialog

dinput

dll

dma

dmband

dmcompos

dmdump

dmfile

dmfileraw

dmime

dmloader

dmscript

dmstyle

dmsynth

dmusic

dmusic32

dnsapi

dosmem

dpa

dplay

dpnet

dpnhpast

driver

ds

dsa

dsalsa

dscapture

dsound

dsound3d

dssenh

dswave

dwmapi

dxdiag

edit

eject

enhmetafile

environ

event

eventlog

exec

explorer

faultrep

fiber

file

fixup

font

fps

fusion

g711

gdi

gdiplus

global

glu

gpkcsp

graphics

handle

header

heap

hid

hlink

hnetcfg

hook

hotkey

htmlhelp

iccvid

icm

icmp

icon

imagehlp

imagelist

imm

imports

inetcomm

inetmib1

infosoft

initpki

inkobj

inseng

int

int21

int31

io

ipaddress

iphlpapi

itircl

itss

jack

joystick

jscript

key

keyboard

listbox

listview

loaddll

local

localspl

localui

lsa

mapi

mci

mciavi

mcicda

mcimidi

mciwave

mdi

menu

menubuilder

message

metafile

midi

mixer

mlang

mmaux

mmio

mmsys

mmtime

module

monthcal

mountmgr

mpeg3

mpr

mprapi

msacm

mscat

mscms

mscoree

msdmo

msftedit

msg

msgbox

mshtml

msi

msidb

msiexec

msimg32

msimtf

msisip

msisys

msnet

msrle32

mssip32

mstask

msvcirt

msvcr71

msvcrt

msvcrt40

msvidc32

msvideo

mswsock

msxml

nativefont

nddeapi

netapi32

netbios

newdev

nls

nonclient

ntdll

ntdsapi

ntlm

ntoskrnl

ntprint

objsel

odbc

ole

oleacc

oledlg

olemalloc

olerelay

olethk32

oleview

opengl

openal32

pager

palette

pdh

pidl

powermgnt

powrprof

print

printui

process

profile

progress

propsheet

propsys

psapi

psdrv

pstores

qcap

qcap_v4l

qedit

qmgr

quartz

query

ras

rebar

recyclebin

reg

regedit

region

relay

resource

resutils

richedit

richedit_check

richedit_lists

richedit_style

rpc

rpcss

rundll32

sblaster

sccbase

schannel

scroll

secur32

seh

selector

sensapi

server

service

setupapi

sfc

share

shdocvw

shell

shlctrl

slbcsp

slc

snmpapi

snoop

sound

spoolss

spoolsv

start

static

statusbar

storage

stress

string

svchost

svrapi

sxs

sync

synchronous

syslevel

system

systray

tab

tape

tapi

task

text

theming

themingcombo

thread

threadpool

thunk

tid

time

toolbar

toolhelp

tooltips

trackbar

trash

treeview

twain

typelib

typelib2

uninstaller

uniscribe

updown

url

urlmon

user

userenv

uxtheme

variant

vdmdbg

ver

virtual

volume

vxd

wave

wavemap

wc_font

wgl

win

wineboot

winebrowser

winecfg

wineconsole

wine_d3d

winedbg

winedevice

winemine

winevdm

wing

winhelp

winhttp

wininet

winmm

winscard

winsock

winspool

winstation

wintab

wintab32

wintrust

wldap32

wnet

wtsapi

x11drv

x11settings

xcopy

xdg

xdnd

xrandr

xrender

xvidmode

Useful Channels

Some of the debug channels can be particularly useful:

  • +all : logs everything, probably gives too much information in most cases, but may come in handy for subtle issues
  • +heap : traces all heap activity in the program and switches on constant integrity checks. If an app is trashing the heap, doing a +relay,+heap trace will let you narrow down exactly where it's happening. If an inconsistency is detected, Wine will dump the contents of the heap and terminate the program. Although many things can lead to trashing the heap, the most common is Wine overrunning an internal buffer. Be sure to remember this channel; most new Wine code uses the HeapAlloc/HeapFree APIs internally, and a primary reason is that Wine's built in heap debugging is so useful.

  • +loaddll : reports each DLL as it's loaded. This is a good, lightwei-ght alternative if you don't have the Windows program Dependency Walker available.

  • +message : logs Windows messages
  • +msgbox : logs when message boxes are displayed
  • +olerelay : dumps calls made through the typelibrary marshaller. It's a bit like +relay but works for a certain class of DCOM calls that wouldn't normally show up. Unfortunately, while this can be useful especially for debugging InstallShield or DCOM issues, this isn't a general COM relay mechanism. Since InstallShield/DCOM issues are quite advanced, it's recommended you ask for help if you want to try using this channel.

  • +relay : logs every call that crosses the DLL boundary of Wine's built-in modules, including calls between (non-native) DLLs. This channel is often the first port of call when you have no idea what's going wrong. It shows you each call into and out of Wine modules at the DLL boundaries. If you're being overwhelmed by certain functions, look into setting the RelayInclude and RelayExclude strings in the Wine registry (under [HKCU\Software\Wine\Debug]). A good initial value for RelayExclude is:

    •   RtlEnterCriticalSection;RtlLeaveCriticalSection;_EnterSysLevel;_LeaveSysLevel;
        _CheckNotSysLevel;RtlAllocateHeap;RtlFreeHeap;LOCAL_Lock;LOCAL_Unlock
        
    These functions are called a lot, but don't usually give any clues as to why a program might be failing.
  • +seh : logs Windows exceptions (Structured Exception Handling). These are invoked either when an application performs an illegal operation (i.e. crashes), or if a program throws its own exceptions. Wine converts UNIX signals into SEH exceptions and outputs them using this channel. This can be useful because applications will often trap their own crash, in order to perform an emergency save for instance. The most common exception to watch for is STATUS_ACCESS_VIOLATION or 0xC0000005 which is the closest equivalent in Win32 to a segfault. You may also see codes which don't appear in the headers; these are typically language-specific exceptions used by whichever compiler was used to produce the EXE. E.g. 0xEEDFADE is the code for a Delphi internal exception, and 0xE06D7363 is a Microsoft Visual C++ exception, which has a magic value (info[0]) of 0x19930520, which is easy to remember because it looks like a date (and probably is). If you see any of these exceptions, it probably means a Win32 API call returned a non-zero error code somewhere.

  • +server : shows each wineserver RPC. You don't normally need this but it may prove helpful when debugging wineserver issues.
  • +snoop : logs every function call between native DLLs. This is similar to +relay but works between two native DLLs, although this channel provides poorer information because parameters aren't reported. +snoop may also break or destabilize an application as it inspects the stack and disassembles function prologues to try and guess parameters.
  • +synchronous : forces X11 into synchronous mode
  • +tid : prefixes each debug output line with the ID of the thread that generated it. This is invaluable for debugging multithreaded applications since a context switch can occur at any time and without it, there's often no way to tell exactly what's going on inside the program. If you aren't sure if a program is concurrent, enable it anyway. Although no channel is free, this one has a very cheap processing cost, and you can always disable it if you're only seeing one thread.

Other Debugging Tips

  • If a program is displaying a message box when it fails, and you don't know what is causing the problem, try performing a +relay,+msgbox trace. Then open the debug log in your favourite editor or text viewer (less is quite good) and search for trace:msgbox. Look at the relay data before the MessageBox API call, although the problem may not be caused by a call that happens immediately before the error. Keep an eye out for failing API calls in particular, and remember that there's little consistency in the Windows API as to what return codes mean. You just have to get used to what the specific API uses, and while many return non-zero for success and zero for fail, some use the opposite convention.

  • If a program fails at startup with nothing to suggest why, you can use an +all trace. If your program seems to be failing a long way from an API call, you might also try disassembling it to see if it's accessing some of the parameters passed in to WinMain (for instance, Dungeon Keeper crashes if you run it without an absolute path for argv[0]).

  • If your logs are becoming too big to work with, try applying the debug delay patch. It lets you toggle logging on and off with the F12 key and also control the debug channels from within the source by using the libwine APIs.

Making +relay less verbose

If you're looking for a problem that happens a couple minutes into the run of an app, +relay can be too verbose. In that case, run it once, then send the log through a script like

# Make grep go fast
LANG=C
# Find top ten calls
freq=`grep ':Ret ' | sed 's/(.*//;s/.* //' | sort | uniq -c | sort -n | tail | awk '{print $2}' | tr '\012' ';'`
cat > quiet.reg << _EOF
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\Debug]
"RelayExclude"="ntdll.RtlEnterCriticalSection;ntdll.RtlLeaveCriticalSection;kernel32.48;kernel32.49;kernel32.94;kernel32.95;kernel32.96;kernel32.97;kernel32.98;$freq"

_EOF

wine regedit quiet.reg

This will tell Wine to not log the ten most frequent calls in your app, which should make your +relay log much more managable in size.

See Also


CategoryListofCommands CategoryQualityAssurance CategoryDevelopment

DebugChannels (last edited 2013-02-08 01:25:42 by ZhenboLi)