From: Wu Y. <ad...@ne...> - 2004-09-06 03:41:56
|
I summarized in my "Stdcall and DLL tools in MSVC and MinGW" article that neither MS LIB nor GNU dlltool currently honours the part after "=" in a DEF file. Both MS LINK and GNU ld WILL honour that, but that is a different story --- as Aaron correctly stated, there are three names (internal, exported in DLL, and output to import library) existent, and DEF files only specify the first two of them. I suppose it might be for this reason that LIB and dlltool ignored the part after "=". The only lib tool I know that will treat the relationship between the DLL names and ImpLib names in a manual way is the Digital Mars implib tool, but in the way a little counterintuitive. My ws2_32.def reads: LIBRARY WS2_32 EXETYPE NT EXPORTS _accept@12=accept ; @1 _bind@12=bind ; @2 _closesocket@4=closesocket ; @3 _connect@12=connect ; @4 _getpeername@12=getpeername ; @5 _getsockname@12=getsockname ; @6 ... Please notice the parts before and after the "=" sign are just the opposite way to what we normally expect. I guess there is a reason. Best regards, Yongwei |
From: Wu Y. <ad...@ne...> - 2004-09-08 06:24:36
|
Carlo Wood wrote: > Of course that works - then you are using only MSVC to generate the > import library. Yes. Since you wanted to use a DLL produced by MSVC, I see no reason to generate the import library with MinGW. The differnences in behaviour are quite delicate, and I think it is better to avoid them. Take Aaron's new examples: 1) Change llama_implementation to __stdcall; 2) Add a prototype to declare llama as __stdcall in main.c; 3) Modify l. 3 of llama.def to "llama@0=_llama_implementation@0". build_msvc.bat will seem to work flawlessly. However, if we skip the step "link /lib /machine:x86 /def:llama.def", "cl main.c llama.lib" will not work like the previous case. We must modify l. 3 of llama.def to "_llama@0=_llama_implementation@0" to make it work again without the lib step (and then llama has a leading underline, and requires a different def file and the --add-underscore option of dlltool to work with MinGW). Why? Because link knows of __stdcall and maps the internal name "llama@0" to an library name "llama@0" ("_llama@0" is the expected name), but lib knows of only __cdecl, and blindly maps the exported name "llama@0" to an library name "_llama@0". The conclusion is that MSVC lib is not consistent with MSVC link, and thus not worth imitating. What's the current usage of the IMPORTS section? I do not see MS document it, and I have had no success with Danny's example. Could it be used to alias names in the DMC implib way? Best regards, Yongwei |
From: Carlo W. <ca...@al...> - 2004-09-08 09:49:11
|
On Wed, Sep 08, 2004 at 02:01:46PM +0800, Wu Yongwei wrote: > Carlo Wood wrote: > >Of course that works - then you are using only MSVC to generate the > >import library. > > Yes. Since you wanted to use a DLL produced by MSVC, I see no reason to > generate the import library with MinGW. One reason is that under mingw, for example when using libtool, libraries passed on the command line have the form -lfoo, and that searches for libfoo.a and libfoo.dll.a. Using a library with a name like 'foo.lib' would give a lot of headaches when using libtool. But perhaps you are right, because one can also do: cp foo.lib libfoo.dll.a > The differnences in behaviour are quite delicate, and I think it is > better to avoid them. Take Aaron's new examples: > > 1) Change llama_implementation to __stdcall; > 2) Add a prototype to declare llama as __stdcall in main.c; > 3) Modify l. 3 of llama.def to "llama@0=_llama_implementation@0". > > build_msvc.bat will seem to work flawlessly. However, if we skip the > step "link /lib /machine:x86 /def:llama.def", "cl main.c llama.lib" will > not work like the previous case. We must modify l. 3 of llama.def to > "_llama@0=_llama_implementation@0" to make it work again without the lib > step (and then llama has a leading underline, and requires a different > def file and the --add-underscore option of dlltool to work with MinGW). Exactly! And that is why we need a different option for dlltool. --add-underscore is changing the meaning of the names in the .def file from 'exported name' (which *is* _llama@0) into 'imported name' (or whatever we should call the visible symbols of the import library). That is at least confusing behaviour, but it also requires that we change the .def file before it can be used with dlltool. > Why? Because link knows of __stdcall and maps the internal name > "llama@0" to an library name "llama@0" ("_llama@0" is the expected > name), but lib knows of only __cdecl, and blindly maps the exported name > "llama@0" to an library name "_llama@0". The conclusion is that MSVC lib > is not consistent with MSVC link, and thus not worth imitating. Thanks :). So that is why a change of dlltool is a Good Thing(tm): we need to change it to match link in a logical way - and ignore the brokeness of MSVC lib. I think I will write a patch that does the following: Add a new option `--gcc-stdcall', which will treat a line like "_llama@0=_llama_implementation@0" as follows: the internal name will be ignored; "_llama@0" will be (correctly) treated as exported name and it will strip off the underscore to form the library name (imported name). Note that symbols without '@<n>', for example: "_foo=_foo@8" will result in "_foo" for both imported and exported names, because the left hand side (_foo) lacks a '@<n>' and is therefore not considered to be a stdcall. -- Carlo Wood <ca...@al...> |
From: Aaron W. L. <aar...@aa...> - 2004-09-08 19:14:57
|
Carlo Wood wrote: > Add a new option `--gcc-stdcall', which will treat a line like > "_llama@0=_llama_implementation@0" as follows: the internal name will > be ignored; "_llama@0" will be (correctly) treated as exported > name and it will strip off the underscore to form the library name > (imported name). Note that symbols without '@<n>', for example: > "_foo=_foo@8" will result in "_foo" for both imported and exported > names, because the left hand side (_foo) lacks a '@<n>' and is therefore > not considered to be a stdcall. This is good. However, I would prefer the option named something more generic, such as --msvc-translation. The option would mean that binutils would do the special-case function type translations similar to what MS LINK does, including this particular stdcall special casing. C++ cdecl functions also have special casing in Microsoft linker, and possibly other things, and it might be nice to add proper translations for these also at some point. (I'm not asking you to actually implement that, though.) It might also make sense to add a similar option to the linker, to allow direct usage to do the right thing: gcc -o artichoke.exe artichoke.c msvc_stdcall_stuff.dll -Wl,--msvc-translation It might even make sense to have such an ld option on by default. Aaron W. LaFramboise |
From: Carlo W. <ca...@al...> - 2004-09-06 11:13:51
|
On Mon, Sep 06, 2004 at 11:40:55AM +0800, Wu Yongwei wrote: > I summarized in my "Stdcall and DLL tools in MSVC and MinGW" article > that neither MS LIB nor GNU dlltool currently honours the part after "=" > in a DEF file. Can you explain what the correct way to honour that part is? Is this documented in some online document? > Both MS LINK and GNU ld WILL honour that, but that is a > different story --- as Aaron correctly stated, there are three names > (internal, exported in DLL, and output to import library) existent, and > DEF files only specify the first two of them. I still cannot place the three in the picture I have of how things work. Can you please point out which is which in the below? 1) The source code of "msvc.c" contains: //=========================================================== // Header __declspec( dllexport ) int __stdcall msvclibstdcall(int); __declspec( dllexport ) int msvclibfunc(int); // Source code int msvclibfunc(int p) { return (p == 12345) ? 54321 : 0; } int __stdcall msvclibstdcall(int p) { return (p == 12345) ? 54321 : 0; } //=========================================================== 2) The object code "msvc.obj" contains: When compiling this with cl.exe, which results in a msvc.obj, then according to 'nm msvc.obj' this object file contains symbols: 00000000 T _msvclibfunc 00000020 T _msvclibstdcall@4 When compiling this with gcc.exe, which results in a msvc.o, then that object file contains, according to 'nm msvc.o', the symbols: 00000000 T _msvclibfunc 00000024 T _msvclibstdcall@4 3) The command 'cl -LDd msvc.c' results in three more files: - msvc.exp, msvc.lib and msvc.dll. The .dll file contains the following symbols (according to 'nm msvc.dll'): $ nm msvc.dll c:\mingw\bin\nm.exe: msvc.dll: no symbols But, we can find back the following strings inside the .dll file: $ strings msvc.dll | grep msvclib msvclibfunc _msvclibstdcall@4 Note that there is NO underscore for msvclibfunc here! But the underscore for _msvclibstdcall@4 is still there. Also, if we run the following command: $ link -dump -exports msvc.dll then we see the following symbols as being exported: Section contains the following exports for msvc.dll [..snip..] ordinal hint RVA name 2 0 00001020 _msvclibstdcall@4 1 1 00001000 msvclibfunc 4) The msvc.lib (the import library) file contains the following symbols according to 'nm': $ nm msvc.lib | grep msvclib 00000000 I __imp__msvclibfunc 00000000 T _msvclibfunc 00000000 I __imp__msvclibstdcall@4 00000000 T _msvclibstdcall@4 Note that the __imp__* symbols are of type 'I', not 'T'. The real symbols are thus the same as what is 'exported' from the .obj file (point 2 above). Also note that 'strings' gives: $ strings msvc.lib | grep msvclib __imp__msvclibfunc _msvclibfunc __imp__msvclibstdcall@4 _msvclibstdcall@4 __imp__msvclibfunc __imp__msvclibstdcall@4 _msvclibfunc _msvclibstdcall@4 _msvclibfunc _msvclibstdcall@4 So, although each string occurs multiple times - there is no variation (when compiling with cl.exe). And we can state that the .lib file speaks of only _msvclibfunc and _msvclibstdcall@4. 5) However - if we use dlltool (with my patch, otherwise it simply never results in a working .dll.a file; and we use a .def file with the following contents: $ cat msvc.def LIBRARY msvc.dll EXPORTS msvclibstdcall@4 = _msvclibstdcall@4 msvclibfunc ) then the resulting .a.dll (mingw imported library) contains the following: $ ../dlltool/dlltool -S as -d msvc.def -l libmsvc.dll.a $ nm libmsvc.dll.a | grep msvclib 00000000 I __imp__msvclibstdcall@4 00000000 T _msvclibstdcall@4 00000000 I __imp__msvclibfunc 00000000 T _msvclibfunc $ strings libmsvc.dll.a | grep msvclib _msvclibstdcall@4 __imp__msvclibstdcall@4 _msvclibfunc __imp__msvclibfunc _msvclibstdcall@4 _msvclibstdcall@4 __imp__msvclibstdcall@4 msvclibfunc _msvclibfunc __imp__msvclibfunc Note that now there is ALSO a 'msvclibfunc' string, without underscore. This is what occurs in the idata$6 section, link -dump -all gives us: SECTION HEADER #7 .idata$6 name [...] RAW DATA #7 00000000: 01 00 5F 6D 73 76 63 6C 69 62 73 74 64 63 61 6C .._msvclibstdcal 00000010: 6C 40 34 00 l@4. [...] SECTION HEADER #7 .idata$6 name [...] RAW DATA #7 00000000: 00 00 6D 73 76 63 6C 69 62 66 75 6E 63 00 ..msvclibfunc. 6) A .exe, compiled (with gcc) from a foo.c file that includes the header file for msvclibfunc and msvclibstdcall with the correct (above) prototypes, results in the following symbols in foo.o: $ nm foo.o 00000000 b .bss 00000000 d .data 00000000 t .text U _msvclibfunc U _msvclibstdcall@4 Ok - I know that was a lot. But please point out exactly which symbols in the above are each of the three types that you mentioned. > I suppose it might be for > this reason that LIB and dlltool ignored the part after "=". I don't understand that. > The only lib tool I know that will treat the relationship between the > DLL names and ImpLib names in a manual way is the Digital Mars implib > tool, but in the way a little counterintuitive. My ws2_32.def reads: > > LIBRARY WS2_32 > EXETYPE NT > EXPORTS > _accept@12=accept ; @1 > _bind@12=bind ; @2 > _closesocket@4=closesocket ; @3 > _connect@12=connect ; @4 > _getpeername@12=getpeername ; @5 > _getsockname@12=getsockname ; @6 > ... > > Please notice the parts before and after the "=" sign are just the > opposite way to what we normally expect. I guess there is a reason. But what is what according to you? Isn't in the above the '_bind@12' what is exported, and 'bind' the internal name used in the .dll? Well, I guess we can only talk about that after it got clear what is what in the first please, after you answered the first part of the mail in detai. -- Carlo Wood <ca...@al...> |