Nusrat Nuriyev
Nusrat Nuriyev

Reputation: 1174

Determining symbol names of the DLL

I have worked with "CPPLoadLibrary" example (from Microsoft All-in-One framework) Okay, there are two ways of export symbols from the sample DLL.

  1. Export symbols from a DLL using .DEF files A module-definition (.DEF) file is a text file containing one or more module statements that describe various attributes of a DLL. Create a .DEF file and use the .def file when building the DLL. Using this approach, we can export functions from the DLL by ordinal rather than by name.
  2. Export symbols from a DLL using __declspec(dllexport) __declspec(dllexport) adds the export directive to the object file so we do not need to use a .def file. This convenience is most apparent when trying to export decorated C++ function names.

And so we have the following code.

typedef int     (_cdecl* LPFNGETSTRINGLENGTH1)      (PCWSTR);
typedef int     (CALLBACK* LPFNGETSTRINGLENGTH2)    (PCWSTR);

LPFNGETSTRINGLENGTH1 lpfnGetStringLength1 = (LPFNGETSTRINGLENGTH1) 
    GetProcAddress(hModule, "GetStringLength1");

LPFNGETSTRINGLENGTH2 lpfnGetStringLength2 = (LPFNGETSTRINGLENGTH2) 
    GetProcAddress(hModule, "_GetStringLength2@4");

So my question is how to determine the name of symbol in order to call GetProcAddress? in first case it's pretty straightforward, we take that symbol name from .DEF file. But what about "_GetStringLength2@4" What is underscore? What is "@4" stand for? Thanks.

Upvotes: 0

Views: 1903

Answers (2)

Adam Rosenfield
Adam Rosenfield

Reputation: 400314

If you don't use a .DEF file, the export names are decorated according to their calling convention in order to support exporting overloaded functions. See Why can't I GetProcAddress a function I dllexport'ed?:

[T]he decoration scheme varies from architecture to architecture and from calling convention to calling convention. So, for example, if the function is exported from a PPC DLL, you would have to do GetProcAddress(hinst, "..SomeFunction"), but if it is exported from an 80386 DLL as extern "C" __stdcall, you would need GetProcAddress(hinst, "_SomeFunction@8"), but if it's __fastcall you would need GetProcAddress(hinst, "@SomeFunction@8").

What's more, C++ decoration varies from compiler vendor to compiler vendor. A C++ exported function might require GetProcAddress(hinst, "?SomeFunction@@YGXHH@Z") if compiled with the Microsoft C++ compiler, but some other decorated string if compiled with the Borland C++ compiler.

So if you intend people to be able to GetProcAddress for functions and you intend your code to be portable to multiple platforms, or if you intend them to be able to use your DLL from a language other than C/C++ or use a C++ compiler different from Microsoft Visual Studio, then you must export the function by its undecorated name.

See The history of calling conventions, part3 for a description of the various name decoration schemes. In this case, the function uses the __stdcall calling convention, so it's decorated by prepending an underscore and appending a @ sign and the number of bytes worth of parameters it takes. It takes one word-sized argument for a total of 4 bytes, so it's decorated as _GetStringLength2@4.

Upvotes: 3

Remy Lebeau
Remy Lebeau

Reputation: 596537

To answer your actual question, use your compiler's TDUMP or similar tool, or any other tool that can display an executable's exports table, so you can see the actual exported names.

Upvotes: -1

Related Questions