AlastairG
AlastairG

Reputation: 4314

MSys/MinGW linking to __imp__ which don't exist in lib/dll

I am building a program, which uses a library I wrote, which uses a third party library distributed as a .lib import file and a .dll file. I am building using MinGW in the MSys environment with CMake.

When I try to link my program I get the following errors (cleaned for readability):

ld.exe: libMyLib.a(mylib.cpp.obj): in function `MangledFnName':
src/mylib.cpp:297: undefined reference to `_imp__hasp_get_info@16'
ld.exe: src/mylib.cpp:326: undefined reference to `_imp__hasp_free@4'

Using objdump on the import file (and removing the extra stuff) I see:

[33291](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x001f3cb4 _hasp_get_info@16
[56900](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x001ee4bf _hasp_free@4

Note the lack of _imp_ at the start of the symbol.

Similarly, but differently, when I look at the FTDI libraries which do link correctly in this environment, I see:

[  2](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000 __imp__FT_Write@16
[  4](sec  2)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x00000000 _FT_Write@16
00000002 dir32             __imp__FT_Write@16

It has the symbol both with and without _imp_ at the start.


UPDATE: I wrote a script to extract the symbols from the original import library and use dlltool to generate a new one. It now links...but doesn't run. I get the error:

The procedure entry point _hasp_free could not be located in the dynamic link library.

If I ask the third party to rebuild their library, what do I have to ask them to do to provide the extra symbol?

How can I tell ld to look for the symbol name without prepending _imp_?

Upvotes: 0

Views: 610

Answers (1)

AlastairG
AlastairG

Reputation: 4314

So the answer is to regenerate the import library. There are various hints here and there on StackOverflow, and an article here on how to do it in a Windows command prompt using MSVC tools, but for future reference, here is an MSys bash script:

#!/bin/bash

if [ -z "$2" ]
then
    echo "Syntax: $(basename $0) <import library> <dll file>"
    exit
fi

RAW_DLL_NAME=$(basename "$2" | sed 's#.dll$##')

echo "LIBRARY ${RAW_DLL_NAME}" > tmp.def
echo "EXPORTS" >> tmp.def

for SYMBOL in $(objdump -t "$1" | grep "sec  1" | grep @ | awk '{ print $9 }' | sed 's#^_##')
do
    echo "    ${SYMBOL}" >> tmp.def
done


dlltool -k -d tmp.def -l "${RAW_DLL_NAME}.dll.a" -D "${RAW_DLL_NAME}.dll"

rm tmp.def

My first attempt failed because I wasn't stripping off the leading underscore on the symbols that objdump was producing, and was then using the --no-leading-underscore option on dlltool. This was wrong.

I am also filtering the exported symbols to only include those that contain an "@". Using MSVCs dumpbin utility shows more symbols that can be exported. I filtered on the @ symbol because I didn't care about the additional symbols, and it prevented me getting a large number of symbols like "__WBPT2660959813".

Upvotes: 1

Related Questions