Shuzheng
Shuzheng

Reputation: 13840

How to specify a "clean" name of DLL exports?

I have defined a DLL-export as follows:

__declspec(dllexport) 
DWORD WINAPI DllBootstrap(LPVOID addr) {
    return 0;
}

Now, using DUMPBIN, the symbol is displayed as follows:

  1    0 0001100A ?DllBootstrap@@YGKPAX@Z = @ILT+5(?DllBootstrap@@YGKPAX@Z)

And this is how the memory looks in Visual Studio:

¡}....ReflectDLL.dll.?DllBootstrap@@YGKPAX@Z..........................................

when inspecting PIMAGE_EXPORT_DIRECTORY.AddressOfNames.

What I need is a clean symbol, i.e., DUMPBIN should output something like:

  1    0 0001100A DllBootstrap

and PIMAGE_EXPORT_DIRECTORY.AddressOfNames should point to:

DllBootstrap..........................................

How can I achieve this?

Upvotes: 0

Views: 1501

Answers (1)

byteptr
byteptr

Reputation: 1385

WIN32 BUILDS:

As @RbMm indicated, to retain your function name as-is and get no name decoration, you must use a .DEF file (and remove the __declspec(dllexport) specifier). Then create a DEF file with the line below and either specify it with the /DEF linker option or add it to your Visual Studio project and it will be picked up automatically by the linker:

EXPORTS DllBootstrap

If you don't want to deal with an external .DEF file and you will be using the Visual C++ compiler, the simplest way to limit decoration using just code is to declare your function with 'extern "C"'. This results in decoration including a preceding underscore and appends an "@" along with the argument's byte count in decimal. The following code for example:

extern "C" __declspec(dllexport)
DWORD WINAPI DllBootstrap(LPVOID addr) {
    return 0;
}

produces an exported name of:

_DllBootstrap@4

This is how stdcall functions are decorated when C++ name-mangling is disabled with 'extern "C"'. NOTE: WINAPI maps to __stdcall. Retaining 'extern "C"' and changing the convention to __cdecl, you won't get any decoration whatsoever, but module entrypoints should generally remain stdcall as you have it listed in your sample.

If you still want to avoid a .DEF file, there is one last hack you can employ. Add the following line to your code:

#pragma comment(linker,"/EXPORT:DllBootstrap=_DllBootstrap@4")

This will pass an argument to the linker creating a new undecorated name symbol which maps to the decorated name. This isn't very clean as the original name will still exist in your DLL, but you will get your clean exported name.

WIN64 BUILDS (UPDATE):

As Hans Passant commented, for anyone using the Visual C++ 64-bit compiler, there is only the 64-bit calling convention (stdcall, cdecl, etc. keywords are ignored). While C++ mangling will still occur under this compiler, no additional decoration is made to the exported names. In this case, 'extern "C"' would be enough when the sample is compiled as C++ code; if compiled as C, no modifications would be necessary.

Upvotes: 1

Related Questions