Big update to the debug logging section.

This commit is contained in:
Dimitrie O. Paun 2003-09-22 21:14:23 +00:00 committed by Alexandre Julliard
parent 3d0e432678
commit 036bb85bb5
1 changed files with 85 additions and 191 deletions

View File

@ -1,33 +1,36 @@
<chapter id="debugging">
<title>Debug Logging</title>
<para>
Written by &name-dimitrie-paun; <email>&email-dimitrie-paun;</email>, 28 Mar 1998
</para>
<para>
(Extracted from <filename>wine/documentation/debug-msgs</filename>)
</para>
<note>
<para>
It is possible to turn on and of debugging output from
within the debugger using the set command. Please see the
WineDbg Command Reference section for how to do this.
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>
</note>
<important>
<para>
At the end of the document, there is a "Style Guide" for
debugging messages. Please read it.
</para>
</important>
<sect1 id="dbg-classes">
<title>Debugging classes</title>
<para>
There are 4 types (or classes) of messages:
A debugging class categorizes a message based on the severity
of the reported problem. There is a fixed set of classes, and
you must carefuly choose the appropriate one for your messages.
There are five classes of messages:
</para>
<variablelist>
<varlistentry>
@ -38,22 +41,15 @@
features, known bugs, etc. They serve as a constant and
active reminder of what needs to be done.
</para>
<para>
Examples: stubs, semi-implemented features, etc.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>ERR</literal></term>
<listitem>
<para>
Messages in this class relate to serious errors in
Wine. This sort of messages signal an inconsistent
internal state, or more general, a condition which
should never happen by design.
</para>
<para>
Examples: unexpected change in internal state, etc.
Messages in this class indicate serious errors in
Wine, such as as conditions that should never happen
by design.
</para>
</listitem>
</varlistentry>
@ -62,15 +58,11 @@
<listitem>
<para>
These are warning messages. You should report a
warning when something unwanted happen but the
function behaves properly. That is, output a warning
when you encounter something unexpected (ex: could not
open a file) but the function deals correctly with the
situation (that is, according to the docs). If you do
not deal correctly with it, output a fixme.
</para>
<para>
Examples: fail to access a resource required by the app.
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>
@ -79,13 +71,18 @@
<listitem>
<para>
These are detailed debugging messages that are mainly
useful to debug a component. These are usually turned
off.
useful to debug a component. These are turned off unless
explicitly enabled.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>MESSAGE</literal></term>
<listitem>
<para>
Examples: everything else that does not fall in one of
the above mentioned categories and the user does not
need to know about it.
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>
@ -96,35 +93,18 @@
<title>Debugging channels</title>
<para>
To better manage the large volume of debugging messages that
Wine can generate, we divide them also on a component basis.
Each component is assigned a debugging channel. The
identifier of the channel must be a valid C identifier but
note that it may also be a reserved word like
<type>int</type> or <type>static</type>.
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>
Examples of debugging channels:
<simplelist type="inline">
<member><literal>reg</literal></member>
<member><literal>updown</literal></member>
<member><literal>string</literal></member>
</simplelist>
</para>
<para>
We will refer to a generic channel as <literal>xxx</literal>.
</para>
</sect1>
<sect1 id="dbg-using">
<title>How to use it</title>
<para>
Typically, a file contains code pertaining to only one component,
and as such, there is only one channel to output to. To simplify
usage, you can declare that channel at the beginning of the file,
and simply write FIXMEs, ERRs, etc. as such:
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"
@ -160,48 +140,29 @@ WINE_DECLARE_DEBUG_CHANNEL(zzz);
</programlisting>
</para>
<para>
If you need to declare a new debugging channel, simply use it in
your code. It will be picked up automatically by the build process.
</para>
</sect1>
<sect1 id="dbg-checking">
<title>Are we debugging?</title>
<para>
To test whether the debugging output of class
<literal>yyy</literal> on channel <literal>xxx</literal> is
enabled, use:
</para>
<screen>
TRACE_ON to test if TRACE is enabled
WARN_ON to test if WARN is enabled
FIXME_ON to test if FIXME is enabled
ERR_ON to test if ERR is enabled
</screen>
<para>
Examples:
</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...
...blah...
}
</programlisting>
<note>
<para>
You should normally need to test only if
<literal>TRACE_ON</literal>. At present, none of the other
3 tests (except for <literal>ERR_ON</literal> which is
used only once!) are used in Wine.
</para>
</note>
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-resource-ids">
<title>Resource identifiers</title>
<sect1 id="dbg-helpers">
<title>Helper functions</title>
<para>
Resource identifiers can be either strings or numbers. To
@ -241,10 +202,32 @@ LPSTR debugres(const void *id);
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-param">
<title>The <parameter>--debugmsg</parameter> command line option</title>
<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>
The <parameter>--debugmsg</parameter> command line
@ -385,7 +368,7 @@ where:
<itemizedlist>
<listitem>
<para>
do NOT include the name of the function: it is included automatically
do not include the name of the function: it is included automatically
</para>
</listitem>
<listitem>
@ -418,99 +401,10 @@ FIXME("(%x, %d, ...): stub\n", par1, par2, ...);
</listitem>
<listitem>
<para>
if you want to name a value, use <literal>=</literal> and
NOT <literal>:</literal>. That is, instead of saying:
<programlisting>
FIXME("(fd: %d, file: %s): stub\n", fd, name);
</programlisting>
say:
if you want to name a parameter, use <literal>=</literal> :
<programlisting>
FIXME("(fd=%d, file=%s): stub\n", fd, name);
</programlisting>
use <literal>:</literal> to separate categories.
</para>
</listitem>
<listitem>
<para>
try to avoid the style:
<programlisting>
FIXME(xxx, "(fd=%d, file=%s)\n", fd, name);
</programlisting>
instead use:
<programlisting>
FIXME(xxx, "(fd=%d, file=%s): stub\n", fd, name);
</programlisting>
The reason is that if you want to <command>grep</command>
for things, you would search for <literal>FIXME</literal>
but in the first case there is no additional information
available, where in the second one, there is (e.g. the word
stub)
</para>
</listitem>
<listitem>
<para>
if you output a string s that might contain control
characters, or if <parameter>s</parameter> may be
<literal>NULL</literal>, use
<function>debugstr_a</function> (for ASCII strings, or
<function>debugstr_w</function> for Unicode strings) to
convert <parameter>s</parameter> to a C string, like this:
<programlisting>
HANDLE32 WINAPI YourFunc(LPCSTR s)
{
FIXME("(%s): stub\n", debugstr_a(s));
}
</programlisting>
</para>
</listitem>
<listitem>
<para>
if you want to output a resource identifier, use debugres to
convert it to a string first, like this:
<programlisting>
HANDLE32 WINAPI YourFunc(LPCSTR res)
{
FIXME("(res=%s): stub\n", debugres(s));
}
</programlisting>
if the resource identifier is a <type>SEGPTR</type>, use
<function>PTR_SEG_TO_LIN</function> to get a
liner pointer first:
<programlisting>
HRSRC16 WINAPI FindResource16( HMODULE16 hModule, SEGPTR name, SEGPTR type )
{
[...]
TRACE(resource, "module=%04x name=%s type=%s\n",
hModule, debugres(PTR_SEG_TO_LIN(name)),
debugres(PTR_SEG_TO_LIN(type)) );
[...]
}
</programlisting>
</para>
</listitem>
<listitem>
<para>
for messages intended for the user (specifically those that
report errors in the wine config file), use the
<literal>MSG</literal> macro. Use it like a
<function>printf</function>:
<programlisting>
MSG( "Definition of drive %d is incorrect!\n", drive );
</programlisting>
However, note that there are <emphasis>very</emphasis> few
valid uses of this macro. Most messages are debugging
messages, so chances are you will not need to use this
macro. Grep the source to get an idea where it is
appropriate to use it.
</para>
</listitem>
<listitem>
<para>
For structure dumps, use the <function>DUMP</function>
macro. Use it like a <function>printf</function>, just like
the <literal>MSG</literal> macro. Similarly, there are only
a few valid uses of this macro. Grep the source to see when
to use it.
</para>
</listitem>
</itemizedlist>