README 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. Winedump - A Wine DLL tool
  2. --------------------------
  3. Background
  4. ----------
  5. Most of the functions available in Windows, and in Windows applications, are
  6. made available to applications from DLLs. Wine implements the Win32 API by
  7. providing replacements for the essential Windows DLLs in the form of Unix
  8. shared library (.so) files, and provides a tool, winebuild, to allow Winelib
  9. applications to link to functions exported from shared libraries/DLLs.
  10. The first thing to note is that there are many DLLs that aren't yet
  11. implemented in Wine. Mostly this doesn't present a problem because the native
  12. Win32 versions of lots of DLLs can be used without problems, at least on
  13. x86 platforms. However, one of Wine's goals is the eventual replacement of
  14. every essential O/S DLL so that the whole API is implemented. This not only
  15. means that a copy of the real O/S is not needed, but also that non-x86
  16. platforms can run most Win32 programs after recompiling.
  17. The second thing to note is that applications commonly use their own or 3rd
  18. party DLLs to provide functionality. In order to call these functions with
  19. a Winelib program, some 'glue' is needed. This 'glue' comes in the form of
  20. a .spec file. The .spec file, along with some dummy code, is used to create
  21. a Wine .so corresponding to the Windows DLL. The winebuild program can then
  22. resolve calls made to DLL functions to call your dummy DLL. You then tell
  23. Wine to only use the native Win32 version of the DLL, and at runtime your
  24. calls will be made to the Win32 DLL. If you want to re-implement the dll,
  25. you simply add the code for the DLL calls to your stub .so, and then tell
  26. Wine to use the .so version instead [1].
  27. These two factors mean that if you are:
  28. A: Reimplementing a Win32 DLL for use within Wine, or
  29. B: Compiling a Win32 application with Winelib that uses x86 DLLs
  30. Then you will need to create a .spec file (amongst other things). If you
  31. won't be doing either of the above, then you won't need winedump.
  32. Creating a .spec file is a labour intensive task during which it is easy
  33. to make a mistake. The idea of winedump is to automate this task and create
  34. the majority of the support code needed for your DLL. In addition you can
  35. have winedump create code to help you re-implement a DLL, by providing
  36. tracing of calls to the DLL, and (in some cases) automatically determining
  37. the parameters, calling conventions, and return values of the DLL's functions.
  38. You can think of winedump as somewhat similar to the IMPLIB tool when
  39. only its basic functionality is used. In addition, winedump can be used to
  40. dump other information from PE files; See the section 'Dumping' below.
  41. Usage
  42. -----
  43. Winedump is a command line tool. For the list of options and the basic usage
  44. see the winedump(1) man page.
  45. Spec mode: Generating stub DLLs
  46. -------------------------------
  47. If all you want to do is generate a stub DLL to allow you to link your
  48. Winelib application to an x86 DLL, the above options are all you need.
  49. As an example, lets assume the application you are porting uses functions
  50. from a 3rd party dll called 'zipextra.dll', and the functions in the DLL
  51. use the __stdcall calling convention. Copy zipextra.dll to an empty directory,
  52. change to it, and run winedump as follows:
  53. winedump spec zipextra (Note: this assumes winedump is in your path)
  54. The output will look something like the following:
  55. 22 named symbols in DLL, 22 in total ...
  56. Export 1 - '_OpenZipFile' ... [Ignoring]
  57. Export 2 - '_UnZipFile' ... [Ignoring]
  58. ...
  59. "[Ignoring]" Just tells you that winedump isn't trying to determine the
  60. parameters or return types of the functions, it's just creating stubs.
  61. The following files are created:
  62. zipextra.spec
  63. This is the .spec file. Each exported function is listed as a stub:
  64. @ stub _OpenZipFile
  65. @ stub _UnZipFile
  66. ...
  67. This means that winebuild will generate dummy code for this function. That
  68. doesn't concern us, because all we want is for winebuild to allow the symbols
  69. to be resolved when linking. At run-time, the functions in the native DLL will
  70. be called; this just allows us to link.
  71. zipextra_dll.h zipextra_main.c
  72. These are source code files containing the minimum set of code to build
  73. a stub DLL. The C file contains one function, ZIPEXTRA_Init, which does
  74. nothing (but must be present).
  75. Makefile.in
  76. This is a template for 'configure' to produce a makefile. It is designed
  77. for a DLL that will be inserted into the Wine source tree. If your DLL
  78. will not be part of Wine, or you don't wish to build it this way,
  79. you should look at the Wine tool 'winemaker' to generate a DLL project.
  80. FIXME: winemaker could run this tool automatically when generating projects
  81. that use extra DLLs (*.lib in the "ADD LINK32" line in .dsp) ....
  82. zipextra_install
  83. A shell script for adding zipextra to the Wine source tree (see below).
  84. Spec mode: Inserting a stub DLL into the Wine tree
  85. --------------------------------------------------
  86. To build your stub DLL as part of Wine, do the following:
  87. chmod a+x ./zipextra_install
  88. ./zipextra_install <wine-path>
  89. cd <wine-path>
  90. autoconf
  91. ./configure
  92. make depend && make
  93. make install
  94. Your application can now link with the DLL.
  95. If you receive the following error when running autoconf:
  96. autoconf: configure.in: No such file or directory
  97. Then you need to install a newer version of autoconf. At the time of writing
  98. version 2.53 or later is required to re-generate configure.
  99. If you have problems with this step, you can post to the wine-devel mailing
  100. list for help. The build process can change regularly and winebuild may lag
  101. behind in support.
  102. NOTE: **DO NOT** submit patches to Wine for 3rd party DLLs! Building DLLs
  103. into your copy of the tree is just a simple way for you to link. When
  104. you release your application you won't be distributing the Unix .so
  105. anyway, just the Win32 DLL. As you update your version of Wine
  106. you can simply re-run the procedure above (Since no patches are
  107. involved, it should be pretty resilient to changes).
  108. Spec mode: Advanced Options
  109. ---------------------------
  110. This section discusses features of winedump that are useful to Wine Hackers
  111. or developers looking to re-implement a Win32 DLL for Unix. Using these
  112. features means you will need to be able to resolve compilation problems and
  113. have a general understanding of Wine programming.
  114. For all advanced functionality, you must give winedump a directory or file that
  115. contains prototypes for the DLL.
  116. Once you have created your DLL, if you generated code (see below), you can
  117. backup the DLL header file created and use it for rebuilding the DLL (you
  118. should remove the DLLNAME_ prefix from the prototypes to make this work). This
  119. allows you to add names to the function arguments, for example, so that the
  120. comments and prototype in the regenerated DLL will be clearer.
  121. Winedump searches for prototypes using 'grep', and then retrieves each
  122. prototype by calling 'function_grep.pl', a Perl script. When you pass the -v
  123. option on the command line, the calls to both of these programs are logged.
  124. This allows you to see where each function definition has come from. Should
  125. winedump take an excessively long time to locate a prototype, you can check
  126. that it is searching the right files; you may want to limit the number of files
  127. searched if locating the prototype takes too long.
  128. You can compile function_grep.pl for a slight increase in performance; see
  129. 'man perlcc' for details.
  130. If winedump does not find a prototype, it emits code like the following:
  131. In the .spec file:
  132. @stub _OpenZipFile
  133. in the header file:
  134. /* __cdecl ZIPEXTRA__OpenZipFile() */
  135. in the C source file:
  136. /*********************************************************************
  137. * _OpenZipFile (ZIPEXTRA.@)
  138. *
  139. */
  140. #if 0
  141. __stdcall ZIPEXTRA__OpenZipFile()
  142. {
  143. /* '@Stubbed'ed in .spec */
  144. }
  145. #endif
  146. If a prototype is found, or correctly demangled, the following is emitted:
  147. .spec:
  148. @ stdcall _OpenZipFile ZIPEXTRA__OpenZipFile
  149. .h:
  150. BOOL __stdcall ZIPEXTRA__OpenZipFile(const char *filename);
  151. .c:
  152. BOOL __stdcall ZIPEXTRA__OpenZipFile(const char *filename)
  153. {
  154. TRACE("stub\n");
  155. return 0;
  156. }
  157. Note that if the prototype does not contain argument names, winedump will
  158. add them following the convention arg0, arg1 ... argN. If the function is
  159. demangled C++, the first argument will be called '_this' if an implicit this
  160. pointer is passed (i.e. the function is a non-static class member function).
  161. OPTION: -f dll Forward calls to 'dll' (implies -t)
  162. This is the most complicated level of code generation. The same code is
  163. generated as -t, however support is added for forwarding calls to another
  164. DLL. The DLL to forward to is given as 'dll'. Lets suppose we built the
  165. examples above using "-f real_zipextra". The code generated will look like
  166. the following:
  167. .spec
  168. As for -c, except if a function prototype was not found:
  169. @ forward _OpenZipFile real_zipextra._OpenZipFile
  170. In this case the function is forwarded to the destination DLL rather
  171. than stubbed.
  172. .h
  173. As for -c.
  174. .c
  175. A variable "hDLL" is added to hold a pointer to the DLL to forward to, and
  176. the initialization code in ZIPEXTRA_Init is changed to load and free the
  177. forward DLL automatically:
  178. HMODULE hDLL = 0; /* DLL to call through to */
  179. BOOL WINAPI ZIPEXTRA_Init(HINSTANCE dll, DWORD reason, void *reserved)
  180. {
  181. TRACE("(0x%08x, %u, %p)\n", dll, reason, reserved);
  182. if (reason == DLL_PROCESS_ATTACH)
  183. {
  184. hDLL = LoadLibraryA( "real_zipextra" );
  185. TRACE ("Forwarding DLL (real_zipextra) loaded\n" );
  186. }
  187. else if (reason == DLL_PROCESS_DETACH)
  188. {
  189. FreeLibrary( hDLL );
  190. TRACE ("Forwarding DLL (real_zipextra) freed\n" );
  191. }
  192. return TRUE;
  193. }
  194. The stub function is changed to call the forwarding DLL and return that value.
  195. BOOL __stdcall ZIPEXTRA__OpenZipFile(const char *filename)
  196. {
  197. BOOL (__stdcall *pFunc)(const char *) = (void*)GetProcAddress(hDLL,"_OpenZipFile");
  198. BOOL retVal;
  199. TRACE("((const char *)%s) stub\n", filename);
  200. retVal = pFunc(filename);
  201. TRACE("returned (%ld)\n",(LONG)retVal));
  202. return retVal;
  203. }
  204. This allows you to investigate the workings of a DLL without interfering in
  205. its operation in any way (unless you want to).
  206. In the example I have been using, we probably should have used the -o option
  207. to change the output name of our DLL to something else, and used the -f
  208. option to forward to the real zipextra DLL:
  209. winedump spec zipextra -f zipextra -o myzipextra -I "~/zipextra/include/*h"
  210. Then in the .spec file for our Winelib application, we add the line:
  211. import myzipextra
  212. When we build our application, winebuild resolves the calls to our Unix .so.
  213. As our application runs we can see the values of all parameters passed to
  214. the DLL, and any values returned, without having to write code to dump
  215. them ourselves (see below for a better way to wrap a DLL for forwarding).
  216. This isn't a very realistic example of the usefulness of this feature,
  217. however, since we could print out the results anyway, because it is our
  218. application making the calls to the DLL. Where DLL forwarding is most useful
  219. is where an application or DLL we didn't write calls functions in the DLL.
  220. In this case we can capture the sequence of calls made, and the values passed
  221. around. This is an aid in reimplementing the DLL, since we can add code for a
  222. function, print the results, and then call the real DLL and compare. Only
  223. when our code is the same do we need to remove the function pointer and the
  224. call to the real DLL. A similar feature in wine is +relay debugging. Using a
  225. forwarding DLL allows more granular reporting of arguments, because you can
  226. write code to dump out the contents of types/structures rather than just
  227. their address in memory. A future version of winedump may generate this
  228. code automatically for common Win32 types.
  229. See below for more information on setting up a forwarding DLL.
  230. Spec mode: Problems compiling a DLL containing generated code
  231. -------------------------------------------------------------
  232. Unless you are very lucky, you will need to do a small amount of work to
  233. get a DLL generated with -c, -t or -f to compile. The reason for this is
  234. that most DLLs will use custom types such as structs whose definition
  235. is not known to the code in the DLL.
  236. Heres an example prototype from crtdll:
  237. double __cdecl _cabs(struct _complex arg0)
  238. The definition for the _complex struct needs to be given. Since it is passed
  239. by value, its size also needs to be correct in order to forward the call
  240. correctly to a native DLL. In this case the structure is 8 bytes in size, which
  241. means that the gcc compile flag -freg-struct-return must be given when
  242. compiling the function in order to be compatible with the native DLL. (In
  243. general this is not an issue, but you need to be aware of such issues if you
  244. encounter problems with your forwarding DLL).
  245. For third party (non C++) DLLs, the header(s) supplied with the DLL can
  246. normally be added as an include to the generated DLL header. For other DLLs
  247. I suggest creating a separate header in the DLL directory and adding any
  248. needed types to that. This allows you to rebuild the DLL at whim, for example
  249. if a new version of winedump brings increased functionality, then you
  250. only have to overwrite the generated files and re-include the header to take
  251. advantage of it.
  252. Usually there isn't much work to do to get the DLL to compile if you have
  253. headers. As an example, building a forwarded crtdll, which contains 520
  254. functions, required 20 types to be defined before it compiled. Of these,
  255. about half were structures, so about 35 lines of code were needed. The only
  256. change to the generated code was one line in the header to include the type
  257. definitions.
  258. To save some typing in case you don't have headers for your DLL type, winedump
  259. will dump dummy declarations for unknown classes and types it encounters,
  260. if you use the -v option. These can be piped directly into a fix-up header
  261. file for use in compiling your DLL. For example, if winedump encounters the
  262. (C++ ) symbol:
  263. ??0foobar@@QAE@ABV0@@Z (Which is a constructor for a foobar object)
  264. It will emit the following with -v set:
  265. struct foobar { int _FIXME; };
  266. (Classes are mapped to C structs when generating code).
  267. The output should be piped through 'sort' and 'uniq' to remove multiple
  268. declarations, e.g:
  269. winedump foo -c -I "inc/*.h" -v | grep FIXME | sort | uniq > fixup.h
  270. By adding '#include "fixup.h"' to foobar_dll.h your compile errors will be
  271. greatly reduced.
  272. If winedump encounters a type it doesn't know that is passed by value (as in
  273. the _cabs example above), it also prints a FIXME message like:
  274. /* FIXME: By value type: Assumed 'int' */ typedef int ldiv_t;
  275. If the type is not an int, you will need to change the code and possibly
  276. the .spec entry in order to forward correctly. Otherwise, include the typedef
  277. in your fixup header to avoid compile errors.
  278. Spec mode: Using a forwarding DLL
  279. ---------------------------------
  280. To create and use a forwarding DLL to trace DLL calls, you need to first
  281. create a DLL using the -f option as outlined above, and get it to compile.
  282. In order to forward calls the following procedure can be used (for this
  283. example we are going to build a forwarding msvcrt.dll for the purpose
  284. of reimplementing it).
  285. First we create the forwarding DLL. We will rename the real msvcrt.dll on our
  286. system to ms_msvcrt.dll, and our msvcrt implementation will call it:
  287. winedump spec msvcrt -C -f ms_msvcrt -I "inc/*.h"
  288. We then install this DLL into the Wine tree and add the types we need to
  289. make it compile. Once the DLL compiles, we create a dummy ms_msvcrt DLL so
  290. winebuild will resolve our forward calls to it (for the cases where winedump
  291. couldn't generate code and has placed an '@forward' line in the .spec file):
  292. winedump spec msvcrt -C -o ms_msvcrt
  293. Install this DLL into the wine tree (since it's a stub DLL, no changes are
  294. needed to the code).
  295. Now uncomment the line that winedump inserted into msvcrt.spec:
  296. #import ms_msvcrt.dll
  297. And recompile Wine.
  298. Finally, we must tell Wine to only use the built in msvcrt.dll and to only use
  299. the native (Win32) ms_msvcrt.dll. Add the following two lines to ~/.wine/config
  300. under the [DllOverrides] section:
  301. ;Use our implementation of msvcrt
  302. "msvcrt" = "builtin, so"
  303. ;Use only the Win32 ms_msvcrt
  304. "ms_msvcrt" = "native"
  305. At this point, when any call is made to msvcrt.dll, Our libmsvcrt.so receives
  306. the call. It then forwards or calls ms_msvcrt.dll, which is the native dll. We
  307. receive a return value and pass it back to our caller, having TRACEd the
  308. arguments on the way.
  309. At this point you are ready to start reimplementing the calls.
  310. Final comments
  311. --------------
  312. If you have any suggestions for improving this tool, please let me know.
  313. If anyone can help answer the FIXME questions in msmangle.c or can fill me in
  314. on any aspect of the C++ mangling scheme, I would appreciate it. In particular
  315. I want to know what _E and _G represent.
  316. If you encounter a C++ symbol that doesn't demangle **AND** you have the
  317. prototype for it, please send me the symbol as reported by winedump and the
  318. prototype. The more examples I have the easier it is to decipher the scheme,
  319. and generating them myself is very slow.
  320. Finally, although it is easy to generate a DLL, I _very strongly_ suggest that
  321. you don't submit a generated DLL for inclusion into Wine unless you have
  322. actually implemented a fairly reasonable portion of it. Even then, you should
  323. only send the portions of the DLL you have implemented. Thousands of lines of
  324. stub code don't help the project at all.
  325. Please send questions and bug reports to jon_p_griffiths@yahoo.com.
  326. References
  327. ----------
  328. [1] See the wine man page for details on how to tell Wine
  329. whether to use native (Win32) or internal DLL's.