Added spec generation tool specmaker.
[wine.git] / tools / specmaker / README
blobe720b7922c91b60cb239e1cb70206d146b57e6e2
1 Specmaker - A Wine DLL tool
2 ---------------------------
4 Background
5 ----------
7 Most of the functions available in Windows, and in Windows applications, are
8 made available to applications from DLL's. Wine implements the Win32 API by
9 providing replacement's for the essential Windows DLLs in the form of Unix
10 shared library (.so) files, and provides a tool, winebuild, to allow Winelib
11 applications to link to functions exported from shared libraries/DLLs.
13 The first thing to note is that there are many DLLs that aren't yet
14 implemented in Wine. Mostly this doesn't present a problem because the native
15 Win32 versions of lots of DLLs can be used without problems, at least on
16 x86 platforms. However, one of Wine's goals is the eventual replacement of
17 every essential O/S DLL so that the whole API is implemented. This not only
18 means that a copy of the real O/S is not needed, but also that non-x86
19 platforms can run most Win32 programs after recompiling.
21 The second thing to note is that applications commonly use their own or 3rd
22 party DLLs to provide functionality. In order to call these functions with
23 a Winelib program, some 'glue' is needed. This 'glue' comes in the form of
24 a .spec file. The .spec file, along with some dummy code, is used to create
25 a Wine .so corresponding to the Windows DLL. The winebuild program can then
26 resolve calls made to DLL functions to call your dummy DLL. You then tell
27 Wine to only use the native Win32 version of the DLL, and at runtime your
28 calls will be made to the Win32 DLL. If you want to reimplement the dll,
29 you simply add the code for the DLL calls to your stub .so, and then tell
30 Wine to use the .so version instead [1].
32 These two factors mean that if you are:
34 A: Reimplementing a Win32 DLL for use within Wine, or
35 B: Compiling a Win32 application with Winelib that uses x86 DLLs
37 Then you will need to create a .spec file (amongst other things). If you
38 won't be doing either of the above, then you won't need specmaker.
40 Creating a .spec file is a labour intensive task during which it is easy
41 to make a mistake. The idea of specmaker is to automate this task and create
42 the majority of the support code needed for your DLL. In addition you can
43 have specmaker create code to help you reimplement a DLL, by providing
44 tracing of calls to the DLL, and (in some cases) automatically determining
45 the parameters, calling conventions, and return values of the DLLs functions.
47 You can think of specmaker as somewhat similar to the IMPLIB tool when
48 only its basic functionality is used.
51 Usage
52 -----
54 Specmaker is a command line tool. Running it with no arguments or passing
55 it '-h' on the command line lists the available options:
57 Usage: specmaker [options] -d dll
59 Options:
60    -d dll   Use dll for input file (mandatory)
61    -h       Display this help message
62    -I dir   Look for prototypes in 'dir' (implies -c)
63    -o name  Set the output dll name (default: dll)
64    -c       Generate skeleton code (requires -I)
65    -t       TRACE arguments (implies -c)
66    -f dll   Forward calls to 'dll' (implies -t)
67    -D       Generate documentation
68    -C       Assume __cdecl calls (default: __stdcall)
69    -s num   Start prototype search after symbol 'num'
70    -e num   End prototype search after symbol 'num'
71    -q       Don't show progress (quiet).
72    -v       Show lots of detail while working (verbose).
75 Basic options
76 -------------
78 OPTION: -d dll   Use dll for input file (mandatory)
80 The -d option tells specmaker which DLL you want to create a .spec file
81 for. You *must* give this option.
83 16 bit DLL's are not currently supported (Note that Winelib is intended
84 only for Win32 programs).
86 OPTION: -o name  Set the output dll name (default: dll)
88 By default, if specmaker is run on DLL 'foo', it creates files called
89 'foo.spec', 'foo_main.c' etc, and prefixes any functions generated
90 with 'FOO_'. If '-o bar' is given, these will become 'bar.spec',
91 'bar_main.c' and 'BAR_' respectively.
93 This option is mostly useful when generating a forwarding DLL. See below
94 for more information.
96 OPTION: -q       Don't show progress (quiet).
97         -v       Show lots of detail while working (verbose).
99 There are 3 levels of output while specmaker is running. The default level,
100 when neither -q or -v are given, prints the number of exported functions
101 found in the dll, followed by the name of each function as it is processed,
102 and a status indication of whether it was processed OK. With -v given, a
103 lot of information is dumped while specmaker works: this is intended to help
104 debug any problems. Giving -q means nothing will be printed unless a fatal
105 error occurs, and could be used when calling specmaker from a script.
108 OPTION: -C       Assume __cdecl calls (default: __stdcall)
110 This option determines the default calling convention used by the functions
111 in the DLL. If specbuild cannot determine the convention, __stdcall is
112 used by default, unless this option has been given.
114 Unless -q is given, a warning will be printed for every function that
115 specmaker determines the calling convention for and which does not match
116 the assumed calling convention.
119 Generating stub DLLS
120 --------------------
122 If all you want to do is generate a stub DLL to allow you to link your
123 Winelib application to an x86 DLL, the above options are all you need.
125 As an example, lets assume the application you are porting uses functions
126 from a 3rd party dll called 'zipextra.dll', and the functions in the DLL
127 use the __stdcall calling convention. Copy zipextra.dll to an empty directory,
128 change to it, and run specmaker as follows:
130 specmaker -d zipextra  (Note: this assumes specmaker is in your path)
132 The output will look something like the following:
134 22 exported symbols in DLL ...
135 Export    1 - '_OpenZipFile' ... [Ignoring]
136 Export    2 - '_UnZipFile' ... [Ignoring]
139 "[Ignoring]" Just tells you that specmaker isn't trying to determine the
140 parameters or return types of the functions, its just creating stubs.
142 The following files are created:
144 zipextra.spec
145 This is the .spec file. Each exported function is listed as a stub:
147 @ stub _OpenZipFile
148 @ stub _UnZipFile
151 This means that winebuild will generate dummy code for this function. That
152 doesn't concern us, because all we want is for winebuild to allow the
153 symbols to be resolved. At run-time, the functions in the native DLL will
154 be called; this just allows us to link.
156 zipextra_dll.h zipextra_main.c
157 These are source code files containing the minimum set of code to build
158 a stub DLL. The C file contains one function, ZIPEXTRA_Init, which does
159 nothing.
161 Makefile.in
162 This is a template for 'configure' to produce a makefile. It is designed
163 for a DLL that will be inserted into the Wine source tree. If your DLL
164 will not be part of Wine, or you don't wish to build it this way,
165 you should look at the Wine tool 'winemaker' to generate a DLL project.
167 FIXME: winemaker could run this tool automatically when generating projects
168 that use extra DLL's (*.lib in the "ADD LINK32" line in .dsp) ....
170 zipextra_install
171 A shell script for adding zipextra to the Wine source tree (see below).
174 Inserting a stub DLL into the Wine tree
175 ---------------------------------------
177 To build your stub DLL as part of Wine, do the following:
179  chmod a+x ./zipextra_install
180  ./zipextra_install <wine-path>
181  cd <wine-path>
182  autoconf
183  ./configure
184  make depend && make
185  make install
187 Your application can now link with the DLL.
189 NOTE: **DO NOT** submit patches to Wine for 3rd party DLLs! Building DLLs
190       into your copy of the tree is just a simple way for you to link. When
191       you release your application you won't be distributing the Unix .so
192       anyway, just the Win32 DLL. As you update your version of Wine
193       you can simply re-run the procedure above (Since no patches are
194       involved, it should be pretty resiliant to changes).
197 Advanced Options
198 ----------------
200 This section discusses features of specmaker that are useful to Wine Hackers
201 or developers looking to reimplement a Win32 DLL for Unix. Using these
202 features means you will need to be able to resolve compilation problems and
203 have a general understanding of Wine programming.
206 OPTION: -I dir   Look for prototypes in 'dir' (implies -c)
208 For all advanced functionality, you must give specmaker a directoryor file that
209 contains prototypes for the DLL. In the case of Windows DLLs, this could be
210 either the standard include directory from your compiler, or an SDK include
211 directory. If you have a text document with prototypes (such as documentation)
212 that can be used also, however you may need to delete some non-code lines to
213 ensure that prototypes are parsed correctly.
215 The 'dir' argument can also be a file specification (e.g. "include/*"). If
216 it contains wildcards you must quote it to prevent the shell from expanding it.
218 If you have no prototypes, specify /dev/null for 'dir'. Specmaker may still
219 be able to generate some working stub code for you.
221 Once you have created your DLL, if you generated code (see below), you can
222 backup the DLL header file created and use it for rebuilding the DLL (you
223 should remove the DLLNAME_ prefix from the prototypes to make this work). This
224 allows you to add names to the function arguments, for example, so that the
225 comments and prototype in the regenerated DLL will be clearer.
227 Specmaker searches for prototypes using 'grep', and then retrieves each
228 prototype by calling 'function_grep.pl', a Perl script. When you pass the -v
229 option on the command line, the calls to both of these programs are logged.
230 This allows you to see where each function definition has come from. Should
231 specmaker take an excessively long time to locate a prototype, you can check
232 that it is searching the right files; you may want to limit the number of files
233 searched if locating the prototype takes too long.
235 You can compile function_grep.pl for a slight increase in performance; see
236 'man perlcc' for details.
239 OPTION: -s num   Start prototype search after symbol 'num'
240         -e num   End prototype search after symbol 'num'
242 By passing the -s or -e options you can have specmaker try to generate code
243 for only some functions in your DLL. This may be used to generate a single
244 function, for example, if you wanted to add functionality to an existing DLL.
246 They is also useful for debugging problems, in conjunction with -v.
249 OPTION: -D       Generate documentation
251 By default, specmaker generates a standard comment at the header of each
252 function it generates. Passing this option makes specmaker output a full
253 header template for standard Wine documentation, listing the parameters
254 and return value of the function.
257 OPTION: -c       Generate skeleton code (requires -I)
259 This option tells specmaker that you want to create function stubs for
260 each function in the DLL. This is the most basic level of code generation.
261 As specmaker reads each exported symbol from the source DLL, it first tries
262 to demangle the name. If the name is a C++ symbol, the arguments, class and
263 return value are all encoded into the symbol name. Specmaker converts this
264 information into a C function prototype. If this fails, the file(s) specified
265 in the -I argument are scanned for a function prototype. If one is found it
266 is used for the next step of the process, code generation.
268 Note: C++ name demangling is currently under development. Since the algorithm
269 used is not documented, it must be decoded. Many simple prototypes are already
270 working however.
272 If specmaker does not find a prototype, it emits code like the following:
274 In the .spec file:
276 @stub _OpenZipFile
278 in the header file:
280 /* __cdecl ZIPEXTRA__OpenZipFile() */
282 in the C source file:
284 /*********************************************************************
285  *      _OpenZipFile     (ZIPEXTRA.@)
287  */
288 #if 0
289 __stdcall ZIPEXTRA__OpenZipFile()
291     /* '@Stubbed'ed in .spec */
293 #endif
295 If a prototype is found, or correctly demangled, the following is emitted:
297 .spec:
298 @ stdcall _OpenZipFile ZIPEXTRA__OpenZipFile
301 BOOL __stdcall ZIPEXTRA__OpenZipFile(LPCSTR pszFileName);
304 BOOL __stdcall ZIPEXTRA__OpenZipFile(LPCSTR pszFileName)
306   TRACE("stub");
307   return 0;
310 Note that if the prototype does not contain argument names, specmaker will
311 add them following the convention arg0, arg1 ... argN. If the function is
312 demangled C++, the first argument will be called '_this' if an implicit this
313 pointer is passed (i.e. the function is a non-static class member function).
316 OPTION: -t       TRACE arguments (implies -c)
318 This option produces the same code as -c, except that arguments are printed
319 out when the function is called, so the FIXME in the above example becomes:
321   FIXME("(%s) stub", pszFileName);
323 Structs that are passed by value are printed as "struct", and functions
324 that take variable argument lists print "...".
327 OPTION: -f dll   Forward calls to 'dll' (implies -t)
329 This is the most complicated level of code generation. The same code is
330 generated as -t, however support is added for forwarding calls to another
331 DLL. The DLL to forward to is given as 'dll'. Lets suppose we built the
332 examples above using "-f real_zipextra". The code generated will look like
333 the following:
335 .spec
336 As for -c, except if a function prototype was not found:
338 @ forward _OpenZipFile real_zipextra._OpenZipFile
340 In this case the function is forwarded to the destination DLL rather
341 than stubbed.
344 As for -c.
348 A variable "hDLL" is added to hold a pointer to the DLL to forward to, and
349 the initialisation code in ZIPEXTRA_Init is changed to load and free the
350 forward DLL automatically:
352 HMODULE hDLL = 0; /* DLL to call through to */
354 BOOL WINAPI ZIPEXTRA_Init(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
356     TRACE("(0x%08x, %ld, %p)\n", hinstDLL, fdwReason, lpvReserved);
358     if (fdwReason == DLL_PROCESS_ATTACH)
359     {
360         hDLL = LoadLibraryA( "real_zipextra" );
361         TRACE ("Forwarding DLL (real_zipextra) loaded\n" );
362     }
363     else if (fdwReason == DLL_PROCESS_DETACH)
364     {
365         FreeLibrary( hDLL );
366         TRACE ("Forwarding DLL (real_zipextra) freed\n" );
367     }
369     return TRUE;
372 The stub function is changed to call the forwarding DLL and return that value.
374 BOOL __stdcall ZIPEXTRA__OpenZipFile(LPCSTR pszFileName)
376   BOOL (__stdcall *pFunc)(LPCSTR) = (void*)GetProcAddress(hDLL,"_OpenZipFile");
377   BOOL retVal;
378   TRACE("((LPCSTR)%s) stub", pszFileName);
379   retVal = pFunc(pszFileName);
380   TRACE("returned (%ld)\n",(LONG)retVal));
381   return retVal;
384 This allows you to investigate the workings of a DLL without interfering in
385 its operation in any way (unless you want to).
387 In the example I have been using, we probably should have used the -o option
388 to change the ouput name of our DLL to something else, and used the -f
389 option to forward to the real zipextra DLL:
391 specmaker -d zipextra -f zipextra -o myzipextra -I "~/zipextra/include/*h"
393 Then in the .spec file for our Winelib application, we add the line:
395 import myzipextra
397 When we build our application, winebuild resolves the calls to our Unix .so.
398 As our application runs we can see the values of all parameters passed to
399 the DLL, and any values returned, without having to write code to dump
400 them ourselves (see below for a better way to wrap a DLL for forwarding).
402 This isn't a very realistic example of the usefulness of this feature,
403 however, since we could print out the results anyway, because it is our
404 application making the calls to the DLL. Where DLL forwarding is most useful
405 is where an application or DLL we didn't write calls functions in the DLL.
406 In this case we can capture the sequence of calls made, and the values passed
407 around. This is an aid in reimplementing the DLL, since we can add code for a
408 function, print the results, and then call the real DLL and compare. Only
409 when our code is the same do we need to remove the function pointer and the
410 call to the real DLL. A similar feature in wine is +relay debugging. Using a
411 fowarding DLL allows more granular reporting of arguments, because you can
412 write code to dump out the contents of types/structures rather than just
413 their address in memory. A future version of specmaker may generate this
414 code automatically for common Win32 types.
416 See below for more information on setting up a forwarding DLL.
419 Problems compiling a DLL containing generated code
420 --------------------------------------------------
422 Unless you are very lucky, you will need to do a small amount of work to
423 get a DLL generated with -c, -t or -f to compile. The reason for this is
424 that most DLLs will use custom types such as structs whose definition
425 is not known to the code in the DLL.
427 Heres an example prototype from crtdll:
429 double __cdecl _cabs(struct _complex arg0)
431 The definition for the _complex struct needs to be given. Since it is passed
432 by value, its size also needs to be correct in order to forward the call
433 correctly to a native DLL. In this case the structure is 8 bytes in size, which
434 means that the gcc compile flag -freg-struct-return must be given when
435 compiling the function in order to be compatable with the native DLL. (In 
436 general this is not an issue, but you need to be aware of such issues if you
437 encounter problems with your forwarding DLL).
439 For third party (non C++) DLL's, the header(s) supplied with the DLL  can
440 normally be added as an include to the generated DLL header. For other DLLs
441 I suggest creating a seperate header in the DLL directory and adding any
442 needed types to that. This allows you to rebuild the DLL at whim, for example
443 if a new version of specmaker brings increased functionality, then you
444 only have to overwrite the generated files and re-include the header to take
445 advantage of it.
447 Usually there isn't much work to do to get the DLL to compile if you have
448 headers. As an example, building a forwarded crtdll, which contains 520
449 functions, required 20 types to be defined before it compiled. Of these,
450 about half were structures, so about 35 lines of code were needed. The only
451 change to the generated code was one line in the header to include the type
452 definitions.
454 To save some typing in case you don't have headers for your DLL type, specmaker
455 will dump dummy declarations for unknown classes and types it encounters,
456 if you use the -v option. These can be piped directly into a fix-up header
457 file for use in compiling your DLL. For example, if specmaker encounters the
458 (C++ ) symbol:
460 ??0foobar@@QAE@ABV0@@Z   (Which is a constructor for a foobar object)
462 It will emit the following with -v set:
464 struct foobar { int _FIXME; };
466 (Classes are mapped to C structs when generating code).
468 The output should be piped through 'sort' and 'uniq' to remove multiple
469 declarations, e.g:
471 specmaker -d foo -c -I "inc/*.h" -v | grep FIXME | sort | uniq > fixup.h
473 By adding '#include "fixup.h"' to foobar_dll.h your compile errors will be
474 greatly reduced.
476 If specmaker encounters a type it doesnt know that is passed by value (as in
477 the _cabs example above), it also prints a FIXME message like:
479 /* FIXME: By value type: Assumed 'int' */ typedef int ldiv_t;
481 If the type is not an int, you will need to change the code and possibly
482 the .spec entry in order to forward correctly. Otherwise, include the typedef
483 in your fixup header to avoid compile errors.
486 Using a forwarding DLL
487 ----------------------
489 To create and use a forwarding DLL to trace DLL calls, you need to first
490 create a DLL using the -f option as outlined above, and get it to compile.
491 In order to forward calls the following procedure can be used (for this
492 example we are going to build a forwarding msvcrt.dll for the purpose
493 of reimplementing it).
495 First we create the forwarding DLL. We will rename the real msvcrt.dll on our
496 system to ms_msvcrt.dll, and our msvcrt implementation will call it:
498 specmaker -d msvcrt -C -f ms_msvcrt -I "inc/*.h"
500 We then install this DLL into the Wine tree and add the types we need to
501 make it compile. Once the DLL compiles, we create a dummy ms_msvcrt DLL so
502 winebuild will resolve our forward calls to it (for the cases where specmaker
503 couldn't generate code and has placed an '@forward' line in the .spec file):
505 specmaker -d msvcrt -C -o ms_msvcrt
507 Install this DLL into the wine tree (since its a stub DLL, no changes are
508 needed to the code).
510 Now uncomment the line that specmaker inserted into msvcrt.spec:
512 #inport ms_msvcrt.dll
514 And recompile Wine.
516 Finally, we must tell Wine to only use the builtin msvcrt.dll and to only use
517 the native (Win32) ms_msvcrt.dll. Add the following two lines to ~/.wine/config
518 under the [DllOverrides] section:
520 ;Use our implmentation of msvcrt
521 "msvcrt" = "builtin, so"
522 ;Use only the Win32 ms_msvcrt
523 "ms_msvcrt" = "native"
525 At this point, when any call is made to msvcrt.dll, Our libmsvcrt.so recieves
526 the call. It then forwards or calls ms_msvcrt.dll, which is the native dll. We
527 recieve a return value and pass it back to our caller, having TRACEd the
528 arguments on the way.
530 At this point you are ready to start reimplementing the calls.
533 Final comments
534 --------------
536 If you have any suggestions for improving this tool, please let me know.
537 If anyone can help answer the FIXME questions in msmangle.c or can fill me in
538 on any aspect of the C++ mangling scheme, I would appreciate it. In particular
539 I want to know what _E and _G represent.
541 If you encounter a C++ symbol that doesn't demangle **AND** you have the
542 prototype for it, please send me the symbol as reported by specmaker and the
543 prototype. The more examples I have the easier it is to decypher the scheme,
544 and generating them myself is very slow.
546 Finally, although it is easy to generate a DLL, I _very strongly_ suggest that
547 you dont submit a generated DLL for inclusion into Wine unless you have
548 actually implemented a fairly reasonable portion of it. Even then, you should
549 only send the portions of the DLL you have implemented. Thousands of lines of
550 stub code don't help the project at all.
552 Please send questions and bug reports to jon_p_griffiths@yahoo.com.
555 References
556 ----------
558 [1] See the Wine and Wine.conf man pages for details on how to tell Wine
559     whether to use native (Win32) or internal DLLs.