question

CG85 avatar image
0 Votes"
CG85 asked YujianYao-MSFT commented

2 decorated names with same entry point

Hello,

Is there any way to have 2 decorated names for the same entry point of a C function for a DLL created with MSVC?

For example:

 void __declspec(dllexport) foo(void);

So the DLL exports the function foo for entry point 0x00001000 and _foo on this same entry point ?


I ask because I saw a dll with this kind of double naming of decorated names for backwards compatibility issues

Greetings

c++
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RLWA32-6355 avatar image
1 Vote"
RLWA32-6355 answered CG85 commented

One way is to use a .def file to create an alias.

· 6
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I tried, however it does not work when I use a "DEF" file. The exported symbol is not "foo" but "_foo" when I want both.
One thing I left out in my original post is that I generate the DLL from a static lib.

0 Votes 0 ·

DEF file -

 LIBRARY
   EXPORTS
    _foo = foo
    foo = foo


Linker map showing exports -

  Exports
    
   ordinal    name
    
         1    _foo
         2    _foo
                exported name: foo

And output of dumpbin.exe showing both exports

197349-foolibdumpbin.png


1 Vote 1 ·
foolibdumpbin.png (25.4 KiB)

I have isolated the issue:

il you create a function like this:

 void __declspec(dllexport) FOOBar(void);

Then export ignore alias with underscore is ignored

0 Votes 0 ·

Anyway you can write another function which calls the origin function.

0 Votes 0 ·

Following header was included in the creation of FooLib.dll from which above was generated -

 #pragma once
    
 #define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
 // Windows Header Files
 #include <windows.h>
    
    
 extern "C" void __declspec(dllexport) foo(void);
0 Votes 0 ·
CG85 avatar image CG85 RLWA32-6355 ·

I tried, it did not change anything. Here are the sources of my POC, close to our construction system allowing to reproduce my problem.

api.h:

 #ifndef __API_H
 #define __API_H
    
 #ifdef __GNUC__
 #define DEPRECATED __attribute__((deprecated))
 #else
 #define DEPRECATED __declspec(deprecated)
 #endif
    
 # ifdef __API_IMPLEMENTATION
 #  ifdef __GNUC__
 #    define API __attribute__((visibility ("default")))
 #  else
 #    define API __declspec(dllexport)
 #  endif
 # else
 #    define API extern
 # endif
    
 #endif

module.h

 #include "api.h"
    
 API void FOOBar(void);

module.c

 #include <stdio.h>
    
 #include "module.h"
    
    
 API void FOOBar(void)
 {
     printf("%s\n", __FUNCTION__);
 }

version.c

 static const char VERSION[] = "FOO 1.0";

export.def:

 EXPORTS
     FOOBar = FOOBar
     _FOOBar = FOOBar

And commands line close to our build process:

 cl /c /TC /D__API_IMPLEMENTATION=1 /DWIN32_LEAN_AND_MEAN=1 module.c version.c
 lib /OUT:myLib.lib module.obj
 link /MAP /DEF:export.def /MACHINE:X86 /DLL /OUT:theLib.dll version.obj myLib.lib

I get this result:
197717-result.png
regards


0 Votes 0 ·
result.png (128.5 KiB)
CG85 avatar image
0 Votes"
CG85 answered

Thank you very much. I have created a POC to verify this and yes, it does work.
The problem is that my project uses additional options in our (complex) build process that disrupts this part.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

RLWA32-6355 avatar image
0 Votes"
RLWA32-6355 answered RLWA32-6355 commented

I tried to replicate your environment from the command line. Both function names were exported -

 C:\Users\RLWA32\source\repos\Rlwa32\FooLib\FooLib>cl /c foo.c
 Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30143 for x86
 Copyright (C) Microsoft Corporation.  All rights reserved.
    
 foo.c
    
 C:\Users\RLWA32\source\repos\Rlwa32\FooLib\FooLib>lib /out:mylib.lib foo.obj
 Microsoft (R) Library Manager Version 14.29.30143.0
 Copyright (C) Microsoft Corporation.  All rights reserved.
    
    
 C:\Users\RLWA32\source\repos\Rlwa32\FooLib\FooLib>link /map /mapinfo:EXPORTS /def:FooLib.def /machine:x86 /DLL /out:FooLib.dll mylib.lib
 Microsoft (R) Incremental Linker Version 14.29.30143.0
 Copyright (C) Microsoft Corporation.  All rights reserved.
    
 LINK : warning LNK4001: no object files specified; libraries used
    Creating library FooLib.lib and object FooLib.exp
    
 C:\Users\RLWA32\source\repos\Rlwa32\FooLib\FooLib>dumpbin /exports FooLib.dll
 Microsoft (R) COFF/PE Dumper Version 14.29.30143.0
 Copyright (C) Microsoft Corporation.  All rights reserved.
    
    
 Dump of file FooLib.dll
    
 File Type: DLL
    
   Section contains the following exports for FooLib.dll
    
     00000000 characteristics
     FFFFFFFF time date stamp
         0.00 version
            1 ordinal base
            2 number of functions
            2 number of names
    
     ordinal hint RVA      name
    
           1    0 00001000 _foo
           2    1 00001000 foo
    
   Summary
    
         2000 .data
         6000 .rdata
         1000 .reloc
         A000 .text
    
 C:\Users\RLWA32\source\repos\Rlwa32\FooLib\FooLib>

And from the linker map -

  Exports
    
   ordinal    name
    
         1    _foo
         2    _foo
                exported name: foo
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

with "foo" function name yes, it works.
But if your function is named "FOOBar" (uppercase prefix) like in my sample code , you may reproduce the issue.

0 Votes 0 ·

Issue reproduced with FOOBar. Potential workaround posted below to avoid 1600 character limitation in comments.

0 Votes 0 ·
RLWA32-6355 avatar image
1 Vote"
RLWA32-6355 answered YujianYao-MSFT commented

I found a workaround by compiling as C++ instead of C.

 C:\Users\RLWA32\source\repos\Rlwa32\FooLib\FooLib>cl /c /MD /Tp FOOBar.c
 Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30143 for x86
 Copyright (C) Microsoft Corporation.  All rights reserved.
    
 FOOBar.c
    
 C:\Users\RLWA32\source\repos\Rlwa32\FooLib\FooLib>lib /out:mylib.lib FOOBar.obj
 Microsoft (R) Library Manager Version 14.29.30143.0
 Copyright (C) Microsoft Corporation.  All rights reserved.
    
    
 C:\Users\RLWA32\source\repos\Rlwa32\FooLib\FooLib>link /map /mapinfo:exports /def:FooLib.def /machine:x86 /DLL /out:FooLib.dll mylib.lib msvcrt.lib
 Microsoft (R) Incremental Linker Version 14.29.30143.0
 Copyright (C) Microsoft Corporation.  All rights reserved.
    
 LINK : warning LNK4001: no object files specified; libraries used
    Creating library FooLib.lib and object FooLib.exp
    
 C:\Users\RLWA32\source\repos\Rlwa32\FooLib\FooLib>dumpbin /exports FooLib.dll
 Microsoft (R) COFF/PE Dumper Version 14.29.30143.0
 Copyright (C) Microsoft Corporation.  All rights reserved.
    
    
 Dump of file FooLib.dll
    
 File Type: DLL
    
   Section contains the following exports for FooLib.dll
    
     00000000 characteristics
     FFFFFFFF time date stamp
         0.00 version
            1 ordinal base
            2 number of functions
            2 number of names
    
     ordinal hint RVA      name
    
           1    0 00001C90 FOOBar
           2    1 00001C90 _FOOBar
    
   Summary
    
         1000 .data
         1000 .rdata
         1000 .reloc
         1000 .text
    
 C:\Users\RLWA32\source\repos\Rlwa32\FooLib\FooLib>


FOOBar.c

 #include "framework.h"
    
 void FOOBar(void)
 {
     OutputDebugStringW(L"Function body for FOOBar\n");
 }

Header -

 #pragma once
    
 #define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
 // Windows Header Files
 #include <windows.h>
    
    
 __declspec(dllexport) void FOOBar(void);


FooLib.def -

 LIBRARY
   EXPORTS
     _FOOBar=?FOOBar@@YAXXZ
     FOOBar=?FOOBar@@YAXXZ

Linker map -

  Exports
    
   ordinal    name
    
         1    ?FOOBar@@YAXXZ (void __cdecl FOOBar(void))
                exported name: FOOBar
         2    ?FOOBar@@YAXXZ (void __cdecl FOOBar(void))
                exported name: _FOOBar




· 5
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@CG85 Any updates?

0 Votes 0 ·

Thanks for your comment, this workaround works for this POC :)
Unfortunately, I can't switch from C to C++ due to compile-time side effects (multiple errors that I can't fix for various reasons).

0 Votes 0 ·

Although I have answered your question two different ways I'm sorry to hear that neither answer works for you in your particular circumstances.

1 Vote 1 ·
CG85 avatar image CG85 RLWA32-6355 ·

I thank you for the time you spent to help me, it allowed me to advance my problem :)

On the other hand, I am very curious to know the difference of treatment between C and C++ made by MSVC, contrary to GCC where I have no problem.

Is there a doc not listed on MSVN about this ?

Anyway, thanks for everything!

0 Votes 0 ·
Show more comments