| <chapter id="debugging"> |
| <title>Debug Logging</title> |
| |
| <para> |
| To better manage the large volume of debugging messages that |
| Wine can generate, we divide the messages on a component basis, |
| and classify them based on the severity of the reported problem. |
| Therefore a message belongs to a <emphasis>channel</emphasis> |
| and a <emphasis>class</emphasis> respectively. |
| </para> |
| <para> |
| This section will describe the debugging classes, how you can |
| create a new debugging channel, what the debugging API is, |
| and how you can control the debugging output. A picture is |
| worth a thousand words, so here are a few examples of the |
| debugging API in action: |
| <screen> |
| ERR("lock_count == 0 ... please report\n"); |
| FIXME("Unsupported RTL style!\n"); |
| WARN(": file seems to be truncated!\n"); |
| TRACE("[%p]: new horz extent = %d\n", hwnd, extent ); |
| MESSAGE( "Could not create graphics driver '%s'\n", buffer ); |
| </screen> |
| </para> |
| |
| <sect1 id="dbg-classes"> |
| <title>Debugging classes</title> |
| |
| <para> |
| A debugging class categorizes a message based on the severity |
| of the reported problem. There is a fixed set of classes, and |
| you must carefully choose the appropriate one for your messages. |
| There are five classes of messages: |
| </para> |
| <variablelist> |
| <varlistentry> |
| <term><literal>FIXME</literal></term> |
| <listitem> |
| <para> |
| Messages in this class are meant to signal unimplemented |
| features, known bugs, etc. They serve as a constant and |
| active reminder of what needs to be done. |
| </para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><literal>ERR</literal></term> |
| <listitem> |
| <para> |
| Messages in this class indicate serious errors in |
| Wine, such as as conditions that should never happen |
| by design. |
| </para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><literal>WARN</literal></term> |
| <listitem> |
| <para> |
| These are warning messages. You should report a |
| warning when something unwanted happens, and the |
| function can not deal with the condition. This |
| is seldomly used since proper functions can usually |
| report failures back to the caller. Think twice before |
| making the message a warning. |
| </para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><literal>TRACE</literal></term> |
| <listitem> |
| <para> |
| These are detailed debugging messages that are mainly |
| useful to debug a component. These are turned off unless |
| explicitly enabled. |
| </para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term><literal>MESSAGE</literal></term> |
| <listitem> |
| <para> |
| There messages are intended for the end user. They do not |
| belong to any channel. As with warnings, you will seldomly |
| need to output such messages. |
| </para> |
| </listitem> |
| </varlistentry> |
| </variablelist> |
| </sect1> |
| |
| <sect1 id="dbg-channels"> |
| <title>Debugging channels</title> |
| |
| <para> |
| Each component is assigned a debugging channel. The |
| identifier of the channel must be a valid C identifier |
| (reserved word like <type>int</type> or <type>static</type> |
| are premitted). To use a new channel, simply use it in |
| your code. It will be picked up automatically by the build process. |
| </para> |
| |
| <para> |
| Typically, a file contains code pertaining to only one component, |
| and as such, there is only one channel to output to. You can declare |
| a default chanel for the file using the |
| <symbol>WINE_DEFAULT_DEBUG_CHANNEL()</symbol> macro: |
| <programlisting> |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(xxx); |
| ... |
| |
| FIXME("some unimplemented feature", ...); |
| ... |
| if (zero != 0) |
| ERR("This should never be non-null: %d", zero); |
| ... |
| </programlisting> |
| </para> |
| <para> |
| In rare situations there is a need to output to more than one |
| debug channel per file. In such cases, you need to declare |
| all the additional channels at the top of the file, and |
| use the _-version of the debugging macros: |
| <programlisting> |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(xxx); |
| WINE_DECLARE_DEBUG_CHANNEL(yyy); |
| WINE_DECLARE_DEBUG_CHANNEL(zzz); |
| ... |
| |
| FIXME("this one goes to xxx channel"); |
| ... |
| FIXME_(yyy)("Some other msg for the yyy channel"); |
| ... |
| WARN_(zzz)("And yet another msg on another channel!"); |
| ... |
| </programlisting> |
| </para> |
| |
| </sect1> |
| |
| <sect1 id="dbg-checking"> |
| <title>Are we debugging?</title> |
| |
| <para> |
| To test whether the debugging channel <literal>xxx</literal> is |
| enabled, use the <symbol>TRACE_ON</symbol>, <symbol>WARN_ON</symbol>, |
| <symbol>FIXME_ON</symbol>, or <symbol>ERR_ON</symbol> macros. For |
| example: |
| <programlisting> |
| if(TRACE_ON(atom)){ |
| ...blah... |
| } |
| </programlisting> |
| You should normally need to test only if <literal>TRACE_ON</literal>, |
| all the others are very seldomly used. With careful coding, you |
| can avoid the use of these macros, which is generally desired. |
| </para> |
| </sect1> |
| |
| <sect1 id="dbg-helpers"> |
| <title>Helper functions</title> |
| |
| <para> |
| Resource identifiers can be either strings or numbers. To |
| make life a bit easier for outputting these beasts (and to |
| help you avoid the need to build the message in memory), I |
| introduced a new function called <function>debugres</function>. |
| </para> |
| <para> |
| The function is defined in <filename>wine/debug.h</filename> |
| and has the following prototype: |
| </para> |
| <programlisting> |
| LPSTR debugres(const void *id); |
| </programlisting> |
| <para> |
| It takes a pointer to the resource id and returns a nicely |
| formatted string of the identifier (which can be a string or |
| a number, depending on the value of the high word). |
| Numbers are formatted as such: |
| </para> |
| <programlisting> |
| #xxxx |
| </programlisting> |
| <para> |
| while strings as: |
| </para> |
| <programlisting> |
| 'some-string' |
| </programlisting> |
| <para> |
| Simply use it in your code like this: |
| </para> |
| <programlisting> |
| #include "wine/debug.h" |
| |
| ... |
| |
| TRACE("resource is %s", debugres(myresource)); |
| </programlisting> |
| |
| <para> |
| Many times strings need to be massaged before output: |
| they may be <literal>NULL</literal>, contain control |
| characters, or they may be too long. Similarly, Unicode |
| strings need to be converted to ASCII for usage with |
| the debugging API. For all this, you can use the |
| <function>debugstr_[aw]n?</function> familly of functions: |
| <programlisting> |
| HANDLE32 WINAPI YourFunc(LPCSTR s) |
| { |
| FIXME("(%s): stub\n", debugstr_a(s)); |
| } |
| </programlisting> |
| </para> |
| |
| </sect1> |
| |
| <sect1 id="dbg-control"> |
| <title>Controlling the debugging output</title> |
| |
| <para> |
| It is possible to turn on and off debugging output from |
| within the debugger using the set command. Please see the |
| WineDbg Command Reference section for how to do this. |
| </para> |
| |
| <para> |
| Another way to conditionally log debug output (e.g. in case of |
| very large installers which may create gigabytes of log |
| output) is to create a pipe: |
| </para> |
| <screen> |
| <prompt>$</prompt> <userinput>mknod /tmp/debug_pipe p</userinput> |
| </screen> |
| |
| <para> |
| and then to run wine like that: |
| </para> |
| <screen> |
| <prompt>$</prompt> <userinput>wine --debugmsg +relay,+snoop setup.exe &>/tmp/debug_pipe</userinput> |
| </screen> |
| |
| <para> |
| Since the pipe is initially blocking (and thus wine as a whole), |
| you have to activate it by doing: |
| </para> |
| <screen> |
| <prompt>$</prompt> <userinput>cat /tmp/debug_pipe</userinput> |
| </screen> |
| <para> |
| (press Ctrl-C to stop pasting the pipe content) |
| </para> |
| <para> |
| Once you are about to approach the problematic part of the program, |
| you just do: |
| </para> |
| <screen> |
| <prompt>$</prompt> <userinput>cat /tmp/debug_pipe >/tmp/wine.log</userinput> |
| </screen> |
| <para> |
| to capture specifically the part that interests you from the |
| pipe without wasting excessive amounts of HDD space and |
| slowing down installation considerably. |
| </para> |
| <para> |
| The <parameter>WINEDEBUG</parameter> environment variable |
| controls the output of the debug messages. |
| It has the following syntax: |
| <parameter>WINEDEBUG= [yyy]#xxx[,[yyy1]#xxx1]*</parameter> |
| </para> |
| <itemizedlist> |
| <listitem> |
| <para> |
| where |
| <literal>#</literal> is either <literal>+</literal> or |
| <literal>-</literal> |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| when the optional class argument (<literal>yyy</literal>) |
| is not present, then the statement will |
| enable(<literal>+</literal>)/disable(<literal>-</literal>) |
| all messages for the given channel (<literal>xxx</literal>) |
| on all classes. For example: |
| </para> |
| <programlisting> |
| WINEDEBUG=+reg,-file |
| </programlisting> |
| <para> |
| enables all messages on the <literal>reg</literal> |
| channel and disables all messages on the |
| <literal>file</literal> channel. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| when the optional class argument (<literal>yyy</literal>) |
| is present, then the statement will enable |
| (<literal>+</literal>)/disable(<literal>-</literal>) |
| messages for the given channel (<literal>xxx</literal>) |
| only on the given class. For example: |
| </para> |
| <programlisting> |
| WINEDEBUG=trace+reg,warn-file |
| </programlisting> |
| <para> |
| enables trace messages on the <literal>reg</literal> |
| channel and disables warning messages on the |
| <literal>file</literal> channel. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| also, the pseudo-channel all is also supported and it |
| has the intuitive semantics: |
| </para> |
| <screen> |
| WINEDEBUG=+all -- enables all debug messages |
| WINEDEBUG=-all -- disables all debug messages |
| WINEDEBUG=yyy+all -- enables debug messages for class yyy on all |
| channels. |
| WINEDEBUG=yyy-all -- disables debug messages for class yyy on all |
| channels. |
| </screen> |
| <para> |
| So, for example: |
| </para> |
| <screen> |
| WINEDEBUG=warn-all -- disables all warning messages. |
| </screen> |
| </listitem> |
| </itemizedlist> |
| |
| <para> |
| Also, note that at the moment: |
| </para> |
| <itemizedlist> |
| <listitem> |
| <para> |
| the <literal>FIXME</literal> and <literal>ERR</literal> |
| classes are enabled by default |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| the <literal>TRACE</literal> and <literal>WARN</literal> |
| classes are disabled by default |
| </para> |
| </listitem> |
| </itemizedlist> |
| </sect1> |
| |
| <sect1 id="dbg-compiling"> |
| <title>Compiling Out Debugging Messages</title> |
| |
| <para> |
| To compile out the debugging messages, provide |
| <command>configure</command> with the following options: |
| </para> |
| <screen> |
| --disable-debug -- turns off TRACE, WARN, and FIXME (and DUMP). |
| --disable-trace -- turns off TRACE only. |
| </screen> |
| <para> |
| This will result in an executable that, when stripped, is |
| about 15%-20% smaller. Note, however, that you will not be |
| able to effectively debug Wine without these messages. |
| </para> |
| <para> |
| This feature has not been extensively tested--it may subtly |
| break some things. |
| </para> |
| </sect1> |
| |
| <sect1 id="dbg-notes"> |
| <title>A Few Notes on Style</title> |
| |
| <para> |
| This new scheme makes certain things more consistent but |
| there is still room for improvement by using a common style |
| of debug messages. Before I continue, let me note that the |
| output format is the following: |
| </para> |
| <screen> |
| yyy:xxx:fff <message> |
| |
| where: |
| yyy = the class (fixme, err, warn, trace) |
| xxx = the channel (atom, win, font, etc) |
| fff = the function name |
| </screen> |
| <para> |
| these fields are output automatically. All you have to |
| provide is the <message> part. |
| </para> |
| <para> |
| So here are some ideas: |
| </para> |
| |
| <itemizedlist> |
| <listitem> |
| <para> |
| do not include the name of the function: it is included automatically |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| if you want to output the parameters of the function, do |
| it as the first thing and include them in parentheses, |
| like this: |
| <programlisting> |
| TRACE("(%d, %p, ...)\n", par1, par2, ...); |
| </programlisting> |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| for stubs, you should output a <literal>FIXME</literal> |
| message. I suggest this style: |
| <programlisting> |
| FIXME("(%x, %d, ...): stub\n", par1, par2, ...); |
| </programlisting> |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| try to output one line per message. That is, the format |
| string should contain only one <literal>\n</literal> and it |
| should always appear at the end of the string. (there are |
| many reasons for this requirement, one of them is that |
| each debug macro adds things to the beginning of the line) |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| if you want to name a parameter, use <literal>=</literal> : |
| <programlisting> |
| FIXME("(fd=%d, file=%s): stub\n", fd, name); |
| </programlisting> |
| </para> |
| </listitem> |
| </itemizedlist> |
| </sect1> |
| |
| </chapter> |
| |
| <!-- Keep this comment at the end of the file |
| Local variables: |
| mode: sgml |
| sgml-parent-document:("wine-devel.sgml" "set" "book" "part" "chapter" "") |
| End: |
| --> |