Author Topic: Module Definition File ( *.def ) Problem  (Read 11724 times)

Offline freddie

  • Multiple posting newcomer
  • *
  • Posts: 11
Module Definition File ( *.def ) Problem
« on: February 24, 2011, 10:55:49 pm »
I've lost a lot of time on this, and I believe others have too.  I've done a search here and at other places on the web and still can't get it resolved. 

For what I'm doing, which is COM programming (Microsoft's Component Object Model), I really, really need to have the g++/ld compiler, linker, whatever, place un-mangled, unadorned function names in the Dll I'm creating.  I use CodeBlocks with MinGW for all my Windows C++ coding (I really like it and prefer it to Visual Studio Pro), but try as I might I've never been able to put a dent in this problem with *.def files and MinGW.  For my COM programming if I'm making a COM Dll, I still have to use MS VStudio.

Can anyone actually tell me how to do it?  I've tried both command line compiling and using the Code::Blocks Ide.  When I set up the Code::Blocks Dll project with 8.05 I told it to create a def file.  I've tried all different combinations.  Just today doing a search on this site I found a recommendation to do this...

--def=ForUtils.def

or this...

/def:"ForUtils.def"   

...and I've tried putting these things in the GUI list boxes under 'Linker Settings'. 

No matter what I do, when I open up the produced binary to search for the alpha-numeric labels of various functions, I find mangled/adorned names.  The issue with what I'm doing is that COM Dlls are loaded by the Windows system through a component known as the 'Service Control Manager' usually referred to as SCM or Scum.  When a client requests a COM object SCM does a LoadLibrary() / GetProcAddress() call on the Dll and the function its looking for is one of various exports with very specific names which can't be mangled.  The names are DllRegisterServer, DllUnregisterServer, DllGetClassObject, and DllCanUnloadNow.  If I open up a working Dll produced with any of the Microsoft compilers, here is what I'll find in the Dll...

ForUtils.dll DllRegisterServer DllUnregisterServer DllCanUnloadNow DllGetClassObject

If I open up a MinGw produced binary and root around, this is what I'll eventually find...

ForUtils.dll DllRegisterServer@0 DllUnregisterServer@0 DllCanUnloadNow@0 DllGetClassObject@12 

Naturally, the object can't be used, as the system can't locate it with those names.  I've tried all the extern "C" __declspec(dllexport) stuff, libForUtils.def export definition file stuff, everything I can think of.  Nothing works!  Can anyone help me?   

Offline Jenna

  • Administrator
  • Lives here!
  • *****
  • Posts: 7255
Re: Module Definition File ( *.def ) Problem
« Reply #1 on: February 25, 2011, 08:40:21 am »
Not really C::B related !

But if I create a sample dll with the wizard adn dump the dll with M$'s dumpbin.exe I get the following output:
Code
dumpbin /exports testdll.dll
Microsoft (R) COFF/PE Dumper Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file testdll.dll

File Type: DLL

  Section contains the following exports for testdll.dll

    00000000 characteristics
    4D6758D1 time date stamp Fri Feb 25 08:22:57 2011
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names

    ordinal hint RVA      name

          1    0 00001204 SomeFunction

  Summary

        1000 .CRT
        1000 .bss
        1000 .data
        1000 .debug_abbrev
        1000 .debug_aranges
        1000 .debug_frame
        1000 .debug_info
        1000 .debug_line
        1000 .debug_loc
        1000 .debug_pubnames
        1000 .debug_pubtypes
        1000 .edata
        1000 .idata
        1000 .rdata
        1000 .reloc
        1000 .text
        1000 .tls

The name of the function (SomeFunction) seems to be unmangled.
Even if it has a trailing @1 in the *.def-file

Offline freddie

  • Multiple posting newcomer
  • *
  • Posts: 11
Re: Module Definition File ( *.def ) Problem
« Reply #2 on: February 26, 2011, 06:30:41 pm »
Hi Jens!

   Thank you very much for taking the time to investigate my problem.   In the example you provided everything indeed does work satisfactory.  However, to ‘break’ it is very easy.  All you need to do is insert the __stdcall calling convention modifier in front of your ‘SomeFunction’, clean the project, and re-compile.  What you’ll find is that now a dumpbin of the dll reveals this…

1    0 000011D8 SomeFunction@4

instead of this…

1    0 000011D8 SomeFunction

     I agree this is not a Code::Blocks problem.  I guess I posted about it because I didn’t know where else to go and I use Code::Blocks as my primary C++ Ide.  I’m going to see if I can sign up at one of the (maybe there is only one) MinGw related sites.  Maybe someone there who is expert at the use of MinGw compilation/linkage can help.  I have already lost so much time at this that I’ve decided not to give up but to continue with it until I solve the problem or determine with absolute certainty that the MinGw compiler suite simply is incapable of creating COM objects, but can only ‘consume’ those created by the Microsoft compilers.  I just find this hard to believe though, because it is so good!

     I suppose a rephrasing of my question would be that I need to find a way that the g++/ld tool chain will accept and respect the contents of an input *.def file, and will use it to produce exported function names in exact accordance with those found in the ‘input’ *.def file.  The way it now seems to be working is that it is mangling the names of my functions, and creating a *.def file as an ‘output’ file which contains information on the way it mangled my names.

     This simply does not work in the creation of COM components housed in a Windows Dll, as the Dll is loaded by Windows system functions that expect a very specific file name.  When I attempt to register a COM component created with the MinGw compiler tool chain, I get an error message from RegSvr32 to the effect that the LoadLibrary() call on the Dll succeeded, but DllRegisterServer() can not be found within the Dll, and registration failed.  The reason Windows can’t locate DllRegisterServer is that it’s a __stdcall function (not __cdecl) and MinGw is exporting DllRegisterServer@0 instead of DllRegisterServer.

     Here are some output runs of a Code::Blocks created Dll of SomeFunction followed by dumpbin output for versions with and without __stdcall

Code
//Without __stdcall

#include <stdio.h>

extern "C" __declspec(dllexport) void SomeFunction(const char* pTxt)
{
 printf("%s\n",pTxt);
}


C:\Code\CodeBlks\DefFileProblem\DFP3>dumpbin /exports DFP3.dll
Microsoft (R) COFF Binary File Dumper Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.


Dump of file DFP3.dll

File Type: DLL

  Section contains the following exports for DFP3.dll

           0 characteristics
    4D692DED time date stamp Sat Feb 26 11:44:29 2011
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names

    ordinal hint RVA      name

          1    0 000011D8 SomeFunction

  Summary

        1000 .bss
        1000 .data
        1000 .edata
        1000 .idata
        1000 .rdata
        1000 .reloc
        1000 .text

C:\Code\CodeBlks\DefFileProblem\DFP3>

With __stdcall

Code
#include <stdio.h>

extern "C" __declspec(dllexport) void __stdcall SomeFunction(const char* pTxt)
{
 printf("%s\n",pTxt);
}


C:\Code\CodeBlks\DefFileProblem\DFP3>dumpbin /exports DFP3.dll
Microsoft (R) COFF Binary File Dumper Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.


Dump of file DFP3.dll

File Type: DLL

  Section contains the following exports for DFP3.dll

           0 characteristics
    4D692E65 time date stamp Sat Feb 26 11:46:29 2011
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names

    ordinal hint RVA      name

          1    0 000011D8 SomeFunction@4

  Summary

        1000 .bss
        1000 .data
        1000 .edata
        1000 .idata
        1000 .rdata
        1000 .reloc
        1000 .text

C:\Code\CodeBlks\DefFileProblem\DFP3>

Offline freddie

  • Multiple posting newcomer
  • *
  • Posts: 11
Re: Module Definition File ( *.def ) Problem
« Reply #3 on: February 26, 2011, 08:07:51 pm »
Hi Jens!

     Here’s something I just tried, but don’t know if its movement in the right direction or not, or if it will work.  I added this to the ‘Other Options’ in the…

Project >> Build Options >>  Linker Settings >> Other Linker Options   Dialog…

Code
-d C:\Code\CodeBlks\DefFileProblem\DFP4\DFP4.def

The ‘-d’ is actually a switch from dlltools.exe from the \bin subdirectory of MinGw…

Code
C:\Code\CodeBlks\ForUtils>dlltool -h
Usage dlltool <option(s)> <object-file(s)>
   -m --machine <machine>    Create as DLL for <machine>.  [default: i386]
        possible <machine>: arm[_interwork], i386, mcore[-elf]{-le|-be}, ppc, thumb
   -e --output-exp <outname> Generate an export file.
   -l --output-lib <outname> Generate an interface library.
   -a --add-indirect         Add dll indirects to export file.
   -D --dllname <name>       Name of input dll to put into interface lib.
   -d --input-def <deffile>  Name of .def file to be read in.
   -z --output-def <deffile> Name of .def file to be created.
      --export-all-symbols   Export all symbols to .def
      --no-export-all-symbols  Only export listed symbols
      --exclude-symbols <list> Don't export <list>
      --no-default-excludes  Clear default exclude symbols
   -b --base-file <basefile> Read linker generated base file.
   -x --no-idata4            Don't generate idata$4 section.
   -c --no-idata5            Don't generate idata$5 section.
   -U --add-underscore       Add underscores to all symbols in interface library.
      --add-stdcall-underscore Add underscores to stdcall symbols in interface library.
   -k --kill-at              Kill @<n> from exported names.
   -A --add-stdcall-alias    Add aliases without @<n>.
   -p --ext-prefix-alias <prefix> Add aliases with <prefix>.
   -S --as <name>            Use <name> for assembler.
   -f --as-flags <flags>     Pass <flags> to the assembler.
   -C --compat-implib        Create backward compatible import library.
   -n --no-delete            Keep temp files (repeat for extra preservation).
   -t --temp-prefix <prefix> Use <prefix> to construct temp file names.
   -v --verbose              Be verbose.
   -V --version              Display the program version.
   -h --help                 Display this information.
   @<file>                   Read options from <file>.

When I compiled Code::Blocks produced my dll but with this warning…

Code
||Warning: resolving _SomeFunction by linking to _SomeFunction@4|
||=== Build finished: 0 errors, 1 warnings ===|

When I dumped the dll I got this…

Code
C:\Code\CodeBlks\DefFileProblem\DFP4>dumpbin /exports dfp4.dll
Microsoft (R) COFF Binary File Dumper Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

Dump of file dfp4.dll
File Type: DLL

  Section contains the following exports for DFP4.dll

           0 characteristics
    4D694701 time date stamp Sat Feb 26 13:31:29 2011
        0.00 version
           1 ordinal base
           2 number of functions
           2 number of names

    ordinal hint RVA      name

          1    0 000011D8 SomeFunction
          2    1 000011D8 SomeFunction@4

  Summary

        1000 .bss
        1000 .data
        1000 .edata
        1000 .idata
        1000 .rdata
        1000 .reloc
        1000 .text

C:\Code\CodeBlks\DefFileProblem\DFP4>dlltool -h
'dlltool' is not recognized as an internal or external command,
operable program or batch file.

C:\Code\CodeBlks\DefFileProblem\DFP4>

As can be seen they both point to the same address, and the one (top one) is what I need.  It might work.  I think I’m going to try it on the real COM component and see what happens!

Offline cbexaminr

  • Multiple posting newcomer
  • *
  • Posts: 104
Re: Module Definition File ( *.def ) Problem
« Reply #4 on: March 01, 2011, 06:06:08 pm »
Might take a look at info at following URL, in case it would provide useful info:
http://www.transmissionzero.co.uk/computing/building-dlls-with-mingw/

According to that page, _stdcall results in decorated names by both mingw and M$, although decoration is different.

[edit1]
Buried in that page is also the following reference which may be useful:
http://wyw.dcweb.cn/stdcall.htm

[edit2]
perhaps --add-stdcall-alias or --kill-at switches to ld would be helpful...

[edit3]
mod dates on that last page are 5+ years, so info may be out-of-date...
« Last Edit: March 01, 2011, 06:17:23 pm by cbexaminr »