Description
Contrary to our original expectations, when an i686 DLL exports a stdcall function, the function's name can appear in the library's export table in one of several different ways. I don't know if this list is exhaustive, but I've seen the following variations:
_exported_function@8
(i.e., with leading underscore and trailing argument-list size)exported_function@8
(trailing size only)exported_function
(exactly as it appears in the defining source file)
Which form the symbols take appears to depend on how the DLL is linked. This is another facet of the problem that I don't fully understand, but one variable appears to be whether the function is defined with__declspec(dllexport)
or the function is marked for export in a .DEF file provided to the linker invocation that creates the .DLL file.
To successfully link against such a DLL, the import library has to match not only the name of the symbol as it appears in the exporting DLL, but also the reference to the name (usually of the form __imp_exported_function@8
, at least with rustc/LLVM) by which the importing library/image refers to it.
In an earlier attempt to solve this problem, we did notice that the three variants of the symbol name in the list above correspond to 3 of the 4 possible values of the IMPORT_NAME_TYPE enum defined in the PE-COFF spec, and I created an earlier proposal for adding a new attribute to specify the IMPORT_NAME_TYPE, but this turns out not to work. In particular, an earlier attempt on my part to have rustc supply the function names to LLVM with the decoration specified by the user doesn't work: specifying NAME_TYPE_UNDECORATE
(intended to be the 3rd case above) resulted in an error when attempting to link the .rlib: the symbol __imp__exported_function@8
was not found. To reproduce, run src/test/run-make/raw-dylib-import-name type from the import-name-time branch of my fork of rustc.