winedump doc
Eric Pouech
eric.pouech at wanadoo.fr
Fri Sep 20 15:13:00 CDT 2002
this patch adds winedump documentation
(Alexandre, you can delete tools/winedump/README if you want)
A+
-------------- next part --------------
Name: doc_winedump
ChangeLog: added winedump doc to winelib book
License: X11
GenDate: 2002/09/20 20:10:35 UTC
ModifiedFiles: documentation/authors.ent documentation/tools.sgml
AddedFiles:
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/documentation/authors.ent,v
retrieving revision 1.2
diff -u -u -r1.2 authors.ent
--- documentation/authors.ent 24 Jul 2002 03:00:02 -0000 1.2
+++ documentation/authors.ent 20 Sep 2002 20:07:27 -0000
@@ -99,6 +99,9 @@
<!entity name-jeremy-white "Jeremy White">
<!entity email-jeremy-white "jwhite at codeweavers.com">
+<!entity name-jon-griffiths "Jon Griffiths">
+<!entity email-jon-griffiths "jon_p_griffiths at yahoo.com">
+
<!-- *** Coders mentioned in docs, but not doc writers *** -->
<!entity name-francis-beaudet "Francis Beaudet">
Index: documentation/tools.sgml
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/documentation/tools.sgml,v
retrieving revision 1.2
diff -u -u -r1.2 tools.sgml
--- documentation/tools.sgml 13 Dec 2000 21:52:37 -0000 1.2
+++ documentation/tools.sgml 20 Sep 2002 20:08:21 -0000
@@ -45,7 +45,7 @@
filename. <command>bin2res -d bin rsrc.rc</command>
generates binary files from all marked resources. If the
binary file is newer it gets not overwritten. To force
- overwriting use the <parameter>-f</parameter> switch.
+ overwriting use the <option>-f</option> switch.
</para>
</sect2>
@@ -65,7 +65,7 @@
the resources into the <filename>.rc</filename> file if the
binary resources are newer than the.rc file. To force the
resources into the <filename>.rc</filename> file use the
- <parameter>-f</parameter> switch. If there is already a
+ <option>-f</option> switch. If there is already a
resource with the same filename in the
<filename>.rc</filename> file it gets overwritten.
</para>
@@ -83,6 +83,1100 @@
means changed.
</para>
</sect2>
+ </sect1>
+
+ <sect1 id="winedump">
+ <title>winedump</title>
+
+ <para>Generated from tools/winedump/README, written by
+&name-jon-griffiths; &email-jon-griffiths;.</para>
+
+ <sect2 id="overview">
+ <title>Overview</title>
+
+<para>
+<command>winedump</command> is a tool used to manipulate native
+modules. It comes with different usages:
+ <itemizedlist>
+ <listitem>
+<para>
+generating default source files (<filename>.spec</filename>,
+<filename>.c</filename>...) for using a native DLL in Wine
+</para>
+ </listitem>
+ <listitem>
+ <para>
+ demangling MSVC C++ symbol names
+ </para>
+ </listitem>
+ <listitem>
+ <para>dumping the 'PE' files contents</para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <sect3 id="usage">
+ <title>Usage</title>
+
+ <para>
+ <command>winedump</command> is a command line
+ tool. Running it with no arguments or passing it '-h' on
+ the command line lists the available options.
+
+<screen>
+Usage: winedump [-h | sym <sym> | spec <dll> | dump
+ <dll>] [mode options]
+</screen>
+
+ Winedump can be used in several different modes. The first
+ argument to the program determines the mode winedump will
+ run in.
+<screen>
+ -h Help mode. Basic usage help is printed.
+ sym Symbol mode. Used to demangle C++ symbols
+ spec For generating .spec files and stub DLL's
+ dump To dump the contents of a PE file.
+</screen>
+
+[mode options] depend on the mode given as the first argument.
+
+<screen>
+Help mode:
+ No options are used. The program prints help and then exits
+
+Sym mode:
+ <sym> Demangles C++ symbol <sym> and then exits.
+
+Spec mode:
+ <dll> Use dll for input file and generate implementation code
+ -I dir Look for prototypes in 'dir' (implies -c)
+ -c Generate skeleton code (requires -I)
+ -t TRACE arguments (implies -c)
+ -f dll Forward calls to 'dll' (implies -t)
+ -D Generate documentation
+ -o name Set the output dll name (default: dll)
+ -C Assume __cdecl calls (default: __stdcall)
+ -s num Start prototype search after symbol 'num'
+ -e num End prototype search after symbol 'num'
+ -S symfile Search only prototype names found in 'symfile'
+ -q Don't show progress (quiet).
+ -v Show lots of detail while working (verbose).
+
+Dump mode
+ <dll> Dumps the content of the dll named <dll>
+ -C Turns on symbol demangling
+ -f Dumps file header information
+ -j sect_name Dumps only the content of section sect_name (import, export, debug)
+ -x Dumps everything
+</screen>
+ </para>
+
+ <sect4 id="opts">
+ <title>Basic options</title>
+
+ <para>
+<screen>
+OPTION: -o name Set the output dll name (default: dll)
+</screen>
+
+ By default, if <command>winedump</command> is run on DLL
+ '<filename>foo</filename>', it creates files called
+ '<filename>foo.spec</filename>',
+ '<filename>foo_main.c</filename>' etc, and prefixes any
+ functions generated with '<function>FOO_</function>'. If
+ '<option>-o bar</option>' is given, these will
+ become <filename>'bar.spec</filename>',
+ '<filename>bar_main.c</filename>' and
+ '<function>BAR_</function>' respectively.
+ </para>
+ <para>
+ This option is mostly useful when generating a
+ forwarding DLL. See below for more information.
+ </para>
+
+ <para>
+<screen>
+OPTION: -q Don't show progress (quiet).
+ -v Show lots of detail while working (verbose).
+</screen>
+
+ There are 3 levels of output while
+ <command>winedump</command> is running. The default
+ level, when neither <option>-q</option> or
+ <option>-v</option> are given, prints the number
+ of exported functions found in the DLL, followed by the
+ name of each function as it is processed, and a status
+ indication of whether it was processed OK. With
+ <option>-v</option> given, a lot of information is
+ dumped while <command>winedump</command> works: this is
+ intended to help debug any problems. Giving
+ <option>-q</option> means nothing will be printed
+ unless a fatal error occurs, and could be used when
+ calling winedump from a script.
+ </para>
+
+ <para>
+<screen>
+OPTION: -C Assume __cdecl calls (default: __stdcall)
+</screen>
+
+ This option determines the default calling convention
+ used by the functions in the DLL. If
+ <command>winedump</command> cannot determine the
+ convention, <type>__stdcall</type> is used by default,
+ unless this option has been given.
+ </para>
+
+ <para>
+ Unless <option>-q</option> is given, a warning
+ will be printed for every function that
+ <command>winedump</command> determines the calling
+ convention for and which does not match the assumed
+ calling convention.
+ </para>
+ </sect4>
+ </sect3>
+ </sect2>
+
+ <sect2 id="spec">
+ <title>Using native DLLs in Wine</title>
+
+ <sect3 id="background">
+ <title>Background</title>
+
+ <para>
+ Most of the functions available in Windows, and in Windows
+ applications, are made available to applications from
+ DLL's. Wine implements the Win32 API by providing
+ replacement's for the essential Windows DLLs in the form
+ of Unix shared library (<filename>.so</filename>) files,
+ and provides a tool, <command>winebuild</command>, to
+ allow Winelib applications to link to functions exported
+ from shared libraries/DLLs.
+ </para>
+
+ <para>
+ The first thing to note is that there are many DLLs that
+ aren't yet implemented in Wine. Mostly this doesn't
+ present a problem because the native Win32 versions of
+ lots of DLLs can be used without problems, at least on x86
+ platforms. However, one of Wine's goals is the eventual
+ replacement of every essential O/S DLL so that the whole
+ API is implemented. This not only means that a copy of the
+ real O/S is not needed, but also that non-x86 platforms
+ can run most Win32 programs after recompiling.
+ </para>
+
+ <para>
+ The second thing to note is that applications commonly use
+ their own or 3rd party DLLs to provide functionality. In
+ order to call these functions with a Winelib program, some
+ 'glue' is needed. This 'glue' comes in the form of a
+ <filename>.spec</filename> file. The
+ <filename>.spec</filename> file, along with some dummy
+ code, is used to create a Wine <filename>.so</filename>
+ corresponding to the Windows DLL. The
+ <command>winebuild</command> program can then resolve
+ calls made to DLL functions to call your dummy DLL. You
+ then tell Wine to only use the native Win32 version of the
+ DLL, and at runtime your calls will be made to the Win32
+ DLL. If you want to reimplement the dll, you simply add
+ the code for the DLL calls to your stub
+ <filename>.so</filename>, and then tell Wine to use the
+ <filename>.so</filename> version instead.
+ <footnote>
+ <para>
+ See the Wine and Wine.conf man pages for details on
+ how to tell Wine whether to use native (Win32) or
+ internal DLLs.
+ </para>
+ </footnote>
+ </para>
+
+ <para>
+ These two factors mean that if you are:
+ <itemizedlist>
+ <listitem>
+ <para>
+ A: Reimplementing a Win32 DLL for use within Wine,
+ or
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ B: Compiling a Win32 application with Winelib that
+ uses x86 DLLs
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ Then you will need to create a <filename>.spec</filename>
+ file (amongst other things). If you won't be doing either of
+ the above, then you won't need <command>winedump</command>.
+ </para>
+
+ <para>
+ Creating a <filename>.spec</filename> file is a labour
+ intensive task during which it is easy to make a
+ mistake. The idea of <command>winedump</command> is to
+ automate this task and create the majority of the support
+ code needed for your DLL. In addition you can have
+ <command>winedump</command> create code to help you
+ reimplement a DLL, by providing tracing of calls to the
+ DLL, and (in some cases) automatically determining the
+ parameters, calling conventions, and return values of the
+ DLLs functions.
+ </para>
+
+ <para>
+ You can think of <command>winedump</command> as somewhat
+ similar to the <command>IMPLIB</command> tool when only its
+ basic functionality is used.
+ </para>
+
+ </sect3>
+
+ <sect3 id="stubdll">
+ <title>Generating stub DLLS</title>
+
+ <para>
+ If all you want to do is generate a stub DLL to allow you
+ to link your Winelib application to an x86 DLL, the above
+ options are all you need.
+ </para>
+
+ <para>
+ As an example, lets assume the application you are porting
+ uses functions from a 3rd party dll called
+ '<filename>zipextra.dll</filename>', and the functions in
+ the DLL use the <type>__stdcall</type> calling
+ convention. Copy <filename>zipextra.dll</filename> to an
+ empty directory, change to it, and run
+ <command>winedump</command> as follows:
+
+<screen>
+winedump spec zipextra
+</screen>
+ (Note: this assumes <command>winedump</command> is in your
+ path)
+</para>
+
+<para>
+ The output will look something like the following:
+<screen>
+22 named symbols in DLL, 22 in total ...
+Export 1 - '_OpenZipFile' ... [Ignoring]
+Export 2 - '_UnZipFile' ... [Ignoring]
+...
+</screen>
+
+ "[Ignoring]" Just tells you that
+ <command>winedump</command> isn't trying to determine the
+ parameters or return types of the functions, its just
+ creating stubs.
+ </para>
+
+ <para>
+ The following files are created:
+ <itemizedlist>
+ <listitem>
+ <para><filename>zipextra.spec</filename></para>
+ <para>
+ This is the <filename>.spec</filename> file. Each
+ exported function is listed as a stub:
+<screen>
+@ stub _OpenZipFile
+@ stub _UnZipFile
+...
+</screen>
+ </para>
+
+ <para>
+ This means that <command>winebuild</command> will
+ generate dummy code for this function. That doesn't
+ concern us, because all we want is for
+ <command>winebuild</command> to allow the symbols to
+ be resolved. At run-time, the functions in the
+ native DLL will be called; this just allows us to link.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <filename>zipextra_dll.h zipextra_main.c</filename>
+ </para>
+ <para>
+ These are source code files containing the minimum
+ set of code to build a stub DLL. The C file contains
+ one function, <function>ZIPEXTRA_Init</function>,
+ which does nothing (but must be present).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <filename>Makefile.in</filename>
+ </para>
+
+ <para>
+ This is a template for
+ '<command>configure</command>' to produce a
+ <filename>makefile</filename>. It is designed for a
+ DLL that will be inserted into the Wine source
+ tree. If your DLL will not be part of Wine, or you
+ don't wish to build it this way, you should look at
+ the Wine tool '<command>winemaker</command>' to
+ generate a DLL project.
+ </para>
+
+ <para>
+ FIXME: <command>winemaker</command> could run this
+ tool automatically when generating projects that use
+ extra DLL's (*.lib in the "ADD LINK32" line in .dsp)...
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <filename>zipextra_install</filename>
+ </para>
+ <para>
+ A shell script for adding zipextra to the Wine
+ source tree (see below).
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect3>
+
+ <sect3 id="stubwine">
+ <title>Inserting a stub DLL into the Wine tree</title>
+
+ <para>
+ To build your stub DLL as part of Wine, do the following:
+<screen>
+ chmod a+x ./zipextra_install
+ ./zipextra_install <wine-path>
+ cd <wine-path>
+ autoconf
+ ./configure
+ make depend && make
+ make install
+</screen>
+
+ Your application can now link with the DLL.
+ </para>
+
+ <para>
+ If you recieve the following error when running autoconf:
+<screen>
+autoconf: configure.in: No such file or directory
+</screen>
+
+ Then you need to install a newer version of autoconf. At
+ the time of writing version 2.53 or later is required to
+ re-generate configure.
+ </para>
+
+ <para>
+ If you have problems with this step, you can post to the
+ wine-devel mailing list for help. The build process can
+ change regularly and winebuild may lag behind in support.
+ </para>
+
+ <note>
+ <title>Note</title>
+ <para>
+ **DO NOT** submit patches to Wine for 3rd party
+ DLLs! Building DLLs into your copy of the tree is just
+ a simple way for you to link. When you release your
+ application you won't be distributing the Unix
+ <filename>.so</filename> anyway, just the Win32
+ DLL. As you update your version of Wine you can simply
+ re-run the procedure above (Since no patches are
+ involved, it should be pretty resiliant to changes).
+ </para>
+ </note>
+ </sect3>
+
+ <sect3 id="advanced">
+ <title>Advanced Options</title>
+
+ <para>
+ This section discusses features of
+ <command>winedump</command> that are useful to Wine
+ Hackers or developers looking to reimplement a Win32 DLL
+ for Unix. Using these features means you will need to be
+ able to resolve compilation problems and have a general
+ understanding of Wine programming.
+ </para>
+
+ <para>
+<screen>
+OPTION: -I dir Look for prototypes in 'dir' (implies -c)
+</screen>
+
+ For all advanced functionality, you must give
+ <command>winedump</command> a directory or file that
+ contains prototypes for the DLL. In the case of Windows
+ DLLs, this could be either the standard include directory
+ from your compiler, or an SDK include directory. If you
+ have a text document with prototypes (such as
+ documentation) that can be used also, however you may need
+ to delete some non-code lines to ensure that prototypes
+ are parsed correctly.
+ </para>
+
+ <para>
+ The 'dir' argument can also be a file specification
+ (e.g. "include/*"). If it contains wildcards you must
+ quote it to prevent the shell from expanding it.
+ </para>
+
+ <para>
+ If you have no prototypes, specify
+ <filename>/dev/null</filename> for
+ 'dir'. <command>winedump</command> may still be able to
+ generate some working stub code for you.
+ </para>
+
+ <para>
+ Once you have created your DLL, if you generated code (see
+ below), you can backup the DLL header file created and use
+ it for rebuilding the DLL (you should remove the
+ <function>DLLNAME_</function> prefix from the prototypes
+ to make this work). This allows you to add names to the
+ function arguments, for example, so that the comments and
+ prototype in the regenerated DLL will be clearer.
+ </para>
+
+ <para>
+ <command>winedump</command> searches for prototypes using
+ '<command>grep</command>', and then retrieves each
+ prototype by calling
+ '<command>function_grep.pl</command>', a Perl script. When
+ you pass the <option>-v</option> option on the
+ command line, the calls to both of these programs are
+ logged. This allows you to see where each function
+ definition has come from. Should
+ <command>winedump</command> take an excessively long time
+ to locate a prototype, you can check that it is searching
+ the right files; you may want to limit the number of files
+ searched if locating the prototype takes too long.
+ </para>
+
+ <para>
+ You can compile <command>function_grep.pl</command> for a
+ slight increase in performance; see 'man perlcc' for details.
+ </para>
+
+ <para>
+<screen>
+OPTION: -s num Start prototype search after symbol 'num'
+ -e num End prototype search after symbol 'num'
+</screen>
+
+ By passing the <option>-s</option> or
+ <option>-e</option> options you can have
+ <command>winedump</command> try to generate code for only
+ some functions in your DLL. This may be used to generate a
+ single function, for example, if you wanted to add
+ functionality to an existing DLL.
+ </para>
+
+ <para>
+ They is also useful for debugging problems, in conjunction
+ with <option>-v</option>.
+ </para>
+
+ <para>
+<screen>
+OPTION: -D Generate documentation
+</screen>
+
+ By default, <command>winedump</command> generates a
+ standard comment at the header of each function it
+ generates. Passing this option makes
+ <command>winedump</command> output a full header template
+ for standard Wine documentation, listing the parameters
+ and return value of the function.
+ </para>
+
+ <para>
+<screen>
+OPTION: -S symfile Search only prototype names found in '<filename>symfile</filename>'
+</screen>
+
+ If you want to only generate code for a subset of exported
+ functions from your source DLL, you can use this option to
+ provide a text file containing the names of the symbols to
+ extract, one per line. Only the symbols present in this
+ file will be used in your output DLL.
+ </para>
+
+ <para>
+<screen>
+OPTION: -c Generate skeleton code (requires -I)
+</screen>
+
+ This option tells <command>winedump</command> that you
+ want to create function stubs for each function in the
+ DLL. This is the most basic level of code generation. As
+ <command>winedump</command> reads each exported symbol
+ from the source DLL, it first tries to demangle the
+ name. If the name is a C++ symbol, the arguments, class
+ and return value are all encoded into the symbol
+ name. <command>winedump</command> converts this
+ information into a C function prototype. If this fails,
+ the file(s) specified in the <option>-I</option>
+ argument are scanned for a function prototype. If one is
+ found it is used for the next step of the process, code
+ generation.
+ </para>
+
+ <note>
+ <title>Note</title>
+ <para>
+ Note: C++ name demangling is currently under
+ development. Since the algorithm used is not
+ documented, it must be decoded. Many simple prototypes
+ are already working however.
+ </para>
+ </note>
+
+ <para>
+ If <command>winedump</command> does not find a prototype,
+ it emits code like the following:
+ <itemizedlist>
+ <listitem>
+ <para>
+ In the <filename>.spec</filename> file:
+<programlisting>
+ at stub _OpenZipFile
+</programlisting>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ in the header file:
+<programlisting>
+/* __cdecl ZIPEXTRA__OpenZipFile() */
+</programlisting>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ in the C source file:
+<programlisting>
+/*********************************************************************
+ * _OpenZipFile (ZIPEXTRA.@)
+ *
+ */
+#if 0
+__stdcall ZIPEXTRA__OpenZipFile()
+{
+ /* '@Stubbed'ed in .spec */
+}
+#endif
+</programlisting>
+
+ If a prototype is found, or correctly demangled, the
+ following is emitted:
+<programlisting>
+.spec:
+@ stdcall _OpenZipFile ZIPEXTRA__OpenZipFile
+
+.h:
+BOOL __stdcall ZIPEXTRA__OpenZipFile(LPCSTR pszFileName);
+
+.c:
+BOOL __stdcall ZIPEXTRA__OpenZipFile(LPCSTR pszFileName)
+{
+ TRACE("stub\n");
+ return 0;
+}
+</programlisting>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ Note that if the prototype does not contain argument
+ names, <command>winedump</command> will add them following
+ the convention arg0, arg1 ... argN. If the function is
+ demangled C++, the first argument will be called '_this'
+ if an implicit this pointer is passed (i.e. the function
+ is a non-static class member function).
+ </para>
+
+ <para>
+<screen>
+OPTION: -t TRACE arguments (implies -c)
+</screen>
+
+ This option produces the same code as
+ <option>-c</option>, except that arguments are
+ printed out when the function is called, so the FIXME in
+ the above example becomes:
+<programlisting>
+ FIXME("(%s) stub", pszFileName);
+</programlisting>
+ </para>
+
+ <para>
+ Structs that are passed by value are printed as "struct",
+ and functions that take variable argument lists print "...".
+ </para>
+
+ <para>
+<screen>
+OPTION: -f dll Forward calls to 'dll' (implies -t)
+</screen>
+
+ This is the most complicated level of code generation. The
+ same code is generated as <option>-t</option>,
+ however support is added for forwarding calls to another
+ DLL. The DLL to forward to is given as 'dll'. Lets suppose
+ we built the examples above using "<option>-f
+ real_zipextra</option>". The code generated will look
+ like the following:
+ <itemizedlist>
+ <listitem>
+ <para>.spec</para>
+ <para>
+ As for <option>-c</option>, except if a
+ function prototype was not found:</para>
+ <programlisting>
+@ forward _OpenZipFile real_zipextra._OpenZipFile
+</programlisting>
+ <para>
+ In this case the function is forwarded to the
+ destination DLL rather than stubbed.
+ </para>
+ </listitem>
+ <listitem>
+ <para>.h</para>
+ <para>As for <option>-c</option>.</para>
+ </listitem>
+ <listitem>
+ <para>.c</para>
+ <para>
+ A variable "hDLL" is added to hold a pointer to the
+ DLL to forward to, and the initialisation code in
+ <function>ZIPEXTRA_Init</function> is changed to
+ load and free the forward DLL automatically:
+ </para>
+
+<programlisting>
+HMODULE hDLL = 0; /* DLL to call through to */
+
+BOOL WINAPI ZIPEXTRA_Init(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ TRACE("(0x%08x, %ld, %p)\n", hinstDLL, fdwReason, lpvReserved);
+
+ if (fdwReason == DLL_PROCESS_ATTACH)
+ {
+ hDLL = LoadLibraryA( "real_zipextra" );
+ TRACE ("Forwarding DLL (real_zipextra) loaded\n" );
+ }
+ else if (fdwReason == DLL_PROCESS_DETACH)
+ {
+ FreeLibrary( hDLL );
+ TRACE ("Forwarding DLL (real_zipextra) freed\n" );
+ }
+
+ return TRUE;
+}
+</programlisting>
+
+ <para>
+ The stub function is changed to call the forwarding
+ DLL and return that value.
+ </para>
+
+<programlisting>
+BOOL __stdcall ZIPEXTRA__OpenZipFile(LPCSTR pszFileName)
+{
+ BOOL (__stdcall *pFunc)(LPCSTR) = (void*)GetProcAddress(hDLL,"_OpenZipFile");
+ BOOL retVal;
+ TRACE("((LPCSTR)%s) stub\n", pszFileName);
+ retVal = pFunc(pszFileName);
+ TRACE("returned (%ld)\n",(LONG)retVal));
+ return retVal;
+}
+</programlisting>
+
+ <para>
+ This allows you to investigate the workings of a DLL
+ without interfering in its operation in any way
+ (unless you want to).
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ In the example I have been using, we probably should have
+ used the <option>-o</option> option to change the
+ ouput name of our DLL to something else, and used the
+ <option>-f</option> option to forward to the real
+ <filename>zipextra</filename> DLL:
+ </para>
+
+ <para>
+<screen>
+winedump spec zipextra -f zipextra -o myzipextra -I "~/zipextra/include/*h"
+</screen>
+
+ Then in the .spec file for our Winelib application, we add
+ the line:
+<programlisting>
+import myzipextra
+</programlisting>
+ </para>
+
+ <para>
+ When we build our application,
+ <command>winebuild</command> resolves the calls to our
+ Unix <filename>.so</filename>. As our application runs we
+ can see the values of all parameters passed to the DLL,
+ and any values returned, without having to write code to
+ dump them ourselves (see below for a better way to wrap a DLL for forwarding).
+ </para>
+
+ <para>
+ This isn't a very realistic example of the usefulness of
+ this feature, however, since we could print out the
+ results anyway, because it is our application making the
+ calls to the DLL. Where DLL forwarding is most useful is
+ where an application or DLL we didn't write calls
+ functions in the DLL. In this case we can capture the
+ sequence of calls made, and the values passed around. This
+ is an aid in reimplementing the DLL, since we can add code
+ for a function, print the results, and then call the real
+ DLL and compare. Only when our code is the same do we need
+ to remove the function pointer and the call to the real
+ DLL. A similar feature in wine is +relay debugging. Using
+ a fowarding DLL allows more granular reporting of
+ arguments, because you can write code to dump out the
+ contents of types/structures rather than just their
+ address in memory. A future version of
+ <command>winedump</command> may generate this code
+ automatically for common Win32 types.
+ </para>
+
+ <para>
+ See below for more information on setting up a forwarding DLL.
+ </para>
+
+ </sect3>
+
+ <sect3 id="comp">
+ <title>Problems compiling a DLL containing generated code</title>
+
+ <para>
+ Unless you are very lucky, you will need to do a small
+ amount of work to get a DLL generated with
+ <option>-c</option>, <option>-t</option> or
+ <option>-f</option> to compile. The reason for this
+ is that most DLLs will use custom types such as structs
+ whose definition is not known to the code in the DLL.
+ </para>
+
+ <para>
+ Heres an example prototype from crtdll:
+<programlisting>
+double __cdecl _cabs(struct _complex arg0)
+</programlisting>
+ </para>
+
+ <para>
+ The definition for the <type>_complex</type> struct needs
+ to be given. Since it is passed by value, its size also
+ needs to be correct in order to forward the call correctly
+ to a native DLL. In this case the structure is 8 bytes in
+ size, which means that the gcc compile flag
+ <option>-freg-struct-return</option> must be given
+ when compiling the function in order to be compatable with
+ the native DLL. (In general this is not an issue, but you
+ need to be aware of such issues if you encounter problems
+ with your forwarding DLL).
+ </para>
+
+ <para>
+ For third party (non C++) DLL's, the header(s) supplied
+ with the DLL can normally be added as an include to the
+ generated DLL header. For other DLLs I suggest creating a
+ seperate header in the DLL directory and adding any needed
+ types to that. This allows you to rebuild the DLL at whim,
+ for example if a new version of
+ <command>winedump</command> brings increased
+ functionality, then you only have to overwrite the
+ generated files and re-include the header to take
+ advantage of it.
+ </para>
+
+ <para>
+ Usually there isn't much work to do to get the DLL to
+ compile if you have headers. As an example, building a
+ forwarded crtdll, which contains 520 functions, required
+ 20 types to be defined before it compiled. Of these, about
+ half were structures, so about 35 lines of code were
+ needed. The only change to the generated code was one line
+ in the header to include the type definitions.
+ </para>
+
+ <para>
+ To save some typing in case you don't have headers for
+ your DLL type, <command>winedump</command> will dump dummy
+ declarations for unknown classes and types it encounters,
+ if you use the <option>-v</option> option. These can
+ be piped directly into a fix-up header file for use in
+ compiling your DLL. For example, if
+ <command>winedump</command> encounters the (C++ ) symbol:
+<programlisting>
+ ??0foobar@@QAE at ABV0@@Z (Which is a constructor for a foobar object)
+</programlisting>
+
+ It will emit the following with <option>-v</option> set:
+<programlisting>
+struct foobar { int _FIXME; };
+</programlisting>
+
+ (Classes are mapped to C structs when generating code).
+ </para>
+
+ <para>
+ The output should be piped through
+ '<command>sort</command>' and '<command>uniq</command>' to
+ remove multiple declarations, e.g:
+<screen>
+winedump foo -c -I "inc/*.h" -v | grep FIXME | sort | uniq > fixup.h
+</screen>
+ </para>
+
+ <para>
+ By adding '<programlisting>#include
+ "fixup.h"</programlisting>' to
+ <filename>foobar_dll.h</filename> your compile errors will
+ be greatly reduced.
+ </para>
+
+ <para>
+ If <command>winedump</command> encounters a type it doesnt
+ know that is passed by value (as in the
+ <function>_cabs</function> example above), it also prints
+ a FIXME message like:
+<programlisting>
+/* FIXME: By value type: Assumed 'int' */ typedef int ldiv_t;
+</programlisting>
+ </para>
+
+ <para>
+ If the type is not an <type>int</type>, you will need to
+ change the code and possibly the
+ <filename>.spec</filename> entry in order to forward
+ correctly. Otherwise, include the typedef in your fixup
+ header to avoid compile errors.
+ </para>
+ </sect3>
+
+ <sect3 id="forward">
+ <title>Using a forwarding DLL</title>
+
+ <para>
+ To create and use a forwarding DLL to trace DLL calls, you
+ need to first create a DLL using the
+ <option>-f</option> option as outlined above, and
+ get it to compile. In order to forward calls the following
+ procedure can be used (for this example we are going to
+ build a forwarding <filename>msvcrt.dll</filename> for the
+ purpose of reimplementing it).
+ </para>
+
+ <para>
+ First we create the forwarding DLL. We will rename the real
+ <filename>msvcrt.dll</filename> on our system to
+ <filename>ms_msvcrt.dll</filename>, and our msvcrt
+ implementation will call it:
+<screen>
+winedump spec msvcrt -C -f ms_msvcrt -I "inc/*.h"
+</screen>
+ </para>
+
+ <para>
+ We then install this DLL into the Wine tree and add the
+ types we need to make it compile. Once the DLL compiles,
+ we create a dummy <filename>ms_msvcrt</filename> DLL so
+ <command>winebuild</command> will resolve our forward
+ calls to it (for the cases where
+ <command>winedump</command> couldn't generate code and has
+ placed an '<type>@forward</type>' line in the
+ <filename>.spec</filename> file):
+<screen>
+winedump spec msvcrt -C -o ms_msvcrt
+</screen>
+ </para>
+
+ <para>
+ Install this DLL into the wine tree (since its a stub DLL,
+ no changes are needed to the code).
+ </para>
+
+ <para>
+ Now uncomment the line that <command>winedump</command>
+ inserted into <filename>msvcrt.spec</filename>:
+<programlisting>
+#inport ms_msvcrt.dll
+</programlisting>
+ And recompile Wine.
+ </para>
+
+ <para>
+ Finally, we must tell Wine to only use the builtin
+ <filename>msvcrt.dll</filename> and to only use the native
+ (Win32) <filename>ms_msvcrt.dll</filename>. Add the
+ following two lines to <filename>~/.wine/config</filename>
+ under the [DllOverrides] section:
+<screen>
+;Use our implmentation of msvcrt
+"msvcrt" = "builtin, so"
+;Use only the Win32 ms_msvcrt
+"ms_msvcrt" = "native"
+</screen>
+ </para>
+
+ <para>
+ At this point, when any call is made to
+ <filename>msvcrt.dll</filename>, Our
+ <filename>libmsvcrt.so</filename> recieves the call. It
+ then forwards our calls
+ <filename>ms_msvcrt.dll</filename>, which is the native
+ dll. We recieve a return value and pass it back to our
+ caller, having TRACEd the arguments on the way.
+ </para>
+
+ <para>
+ At this point you are ready to start reimplementing the
+ calls.
+ </para>
+ </sect3>
+
+ <sect3 id="final">
+ <title>Final comments</title>
+
+ <para>
+ If you have any suggestions for improving this tool,
+ please let me know. If anyone can help answer the
+ <function>FIXME</function> questions in
+ <filename>msmangle.c</filename> or can fill me in on any
+ aspect of the C++ mangling scheme, I would appreciate
+ it. In particular I want to know what _E and _G
+ represent.
+ </para>
+
+ <para>
+ If you encounter a C++ symbol that doesn't demangle
+ **AND** you have the prototype for it, please send me the
+ symbol as reported by <command>winedump</command> and the
+ prototype. The more examples I have the easier it is to
+ decypher the scheme, and generating them myself is very slow.
+ </para>
+
+ <para>
+ Finally, although it is easy to generate a DLL, I _very
+ strongly_ suggest that you dont submit a generated DLL for
+ inclusion into Wine unless you have actually implemented a
+ fairly reasonable portion of it. Even then, you should
+ only send the portions of the DLL you have
+ implemented. Thousands of lines of stub code don't help the project at all.
+ </para>
+
+ </sect3>
+
+ </sect2>
+
+ <sect2 id="demangl">
+ <title>Demangling</title>
+
+ <para>
+ If you need to demangle a single C++ symbol, you can use the
+ demangling mode of <command>winedump</command>. This is
+ useful for testing the demangler or implementing C++
+ functions in partially implemented wine DLLS. As an example:
+<screen>
+winedump sym "??3 at YAXPAX@Z"
+</screen>
+
+ Gives: <function>void __cdecl _global_operator_delete_1(void
+ * arg0)</function>
+
+ Which is enough information to begin implementing the function.
+ </para>
+ </sect2>
+
+ <sect2 id="dump">
+ <title>Dumping a PE file</title>
+
+ <para>
+ Another use for this tool is to diplay information about a
+ 32bit DLL or PE format image file. When used in this way
+ winedump functions similarly to tools such as
+ <command>pedump</command> provided by many Win32 compiler
+ vendors.
+ </para>
+
+ <para>
+<screen>
+Usage:
+winedump dump <dllname.dll> [switches]
+
+dump mode switches:
+ -h Display this help message
+ -C Turns on symbol demangling
+ -f Dump file header information
+ -j dir_name Dump only the contents of directory dir_name (import, export, debug)
+ -x Dump everything
+</screen>
+
+ </para>
+
+ <sect3 id="dump_opt">
+ <title>Dump mode options</title>
+
+ <para>
+<screen>
+OPTION: -x Dump everything
+</screen>
+
+ This command prints all available information about the
+ file. You may wish to pipe the output through more/less or
+ into a file, since a lot of output will be produced.
+ </para>
+
+ <para>
+ If you are only interested in a subset of the available
+ information, you can use one of the following switches:
+<screen>
+OPTION: -f Dump file header information-x Dump everything
+</screen>
+
+ This option dumps only the standard PE header structures,
+ along with the COFF sections available in the file.
+ </para>
+
+ <para>
+<screen>
+OPTION: -j dir_name Dump directory dir_name (import, export, debug)
+</screen>
+
+ To dump only a given directory, specify them using this
+ option. Currently only the import, export and debug
+ directories are implemented.
+ </para>
+ </sect3>
+ </sect2>
+
</sect1>
</chapter>
More information about the wine-patches
mailing list