Workaround when exported function names must have specific ordinals.

By: Vincent Drake

Abstract: Exported function names cannot have their ordinals explicitly assigned when using Builder 3 and 4 linker. This article outlines a workaround for this problem.

Exporting Functions by Ordinal

The version of Ilink32.exe that shipped with Builder 4 and Builder 3 is not able to export names from a dll by specific ordinals. Developers expecting to be able to specify the ordinal they wish to export names to using a def file will not be able to. This can cause a problem for some developers, as programs or 3rd party libraries may require certain functions to be exported at specific ordinals.

The following example illustrates a way of working around this problem.

Situation:

The function foo(void) needs to be accessible at ordinal 5 and also needs to be exported by its name from the dll.

// project started with File|New...|Dll
//CPP file: dll.cpp
//snipping out builder standard code

extern "C"
{
int foo(void){};
void placeholder(void){};
}
//END file

//DEF file: dll.def
LIBRARY DLL.DLL

EXPORTS
_1 = _placeholder
_2 = _placeholder
_3 = _placeholder
_4 = _placeholder
_5 = _foo
_foo

//END file

// result from TDUMP.EXE DLL.DLL -ee
EXPORT ord:0001='_1'
EXPORT ord:0002='_2'
EXPORT ord:0003='_3'
EXPORT ord:0004='_4'
EXPORT ord:0005='_5'
EXPORT ord:0006='___CPPdebugHook'
EXPORT ord:0007='___dll_argc'
EXPORT ord:0008='___dll_argv'
EXPORT ord:0009='_foo'

Result:

The linker sorts the exported names in alphabetical order, then assigns ordinals to the each name in the list from one onward. We have exported five names that will take the ordinals one through five. Since every exported name has to have an internal function associated with it, we create an extra function that does nothing: placeholder(void). We assign _1 through _4 the placeholder function and we associate the external name _5 with _foo, the result being that foo is accessible by its name or by ordinal value 5.

Conclusion:

This should be a viable workaround for developers using Builder 3 or 4. This workaround is best used when symbol names are being exported by their C names (extern "C" declared). A workaround which includes C++ mangled symbol names could be assembled using a similar technique, but would be more complicated, as each name includes parameter information.


Server Response from: ETNASC03