In Visual Studio I want to export function from dll by ordinal only. In source I define function to be:
int my_function() { return 101; } // without declspec(dllexport)
In the .def file:
LIBRARY MyDll
EXPORTS
my_function @ 1 NONAME // NONAME, export directory will not contain function name
In main program I use it like this:
#pragma comment(lib, "MyDll.lib")
declspec(dllimport) int my_function();
int main(int argc, char* argv[])
{
int a = my_function();
return 0;
}
The code compiles and links fine. NONAME
attribute is documented to export function by ordinal only.
Export directory of MyDll has NumberOfNames
set to zero, so dll itself does not contain name information. Exe file imports function by ordinal value, so exe also does not contain name information.
I tried different configurations (debug, release), still program links fine. Maybe lib file contains some sort of mapping between function names and ordinals? I read that lib file contains function thunks, so we can have something like this inside lib file:
my_function @ 1:
jmp IAT[0]
my_another_function @ 2:
jmp IAT[1]
And in-file exe import table:
OriginalFirstThunk FirstThunk
0x80000001 (@ 1) 0x80000001 (@ 1) // ordinal 1 will go through IAT[0]
0x80000002 (@ 2) 0x80000002 (@ 2) // ordinal 2 will go through IAT[1]
And in-memory exe import table:
OriginalFirstThunk FirstThunk
0x80000001 (@ 1) IAT[0]
0x80000002 (@ 2) IAT[1]
If so then in order to hide function name we should provide only dll file, and that means user will need to load dll with LoadLibrary
and use GetProcessAddress
? What I am missing here?
From Exporting Functions from a DLL by Ordinal Rather Than by Name on MSDN:
In other words, NONAME only affects the DLL, not the import library. So the behaviour you are observing is as-intended.
From the documentation for EXPORTS:
So if you use both PRIVATE and NONAME you should get the results you want. However, this defeats the purpose of providing an import library in the first place, at least as far as that particular function goes. It might be useful if you want some functions that can be accessed via the import library, and some that can only be accessed via GetProcAddress.
You might prefer to provide an alias for the function that the end users can use to link to it, e.g.,
This should put the fake names "function1" and "function2" into the import library so that the end users can link to the functions using those names, while still hiding the secret names "my_function" and "my_other_function" in both the import library and the DLL. (Not that I understand why the names need to be secret in the first place, but YMMV.)
Disclaimer: I haven't tried this myself, this answer is based solely on the documentation.