0

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_?

AlastairG
  • 4,119
  • 5
  • 26
  • 41
  • Did you `dll_export` the library functions? – ssbssa Aug 19 '21 at 10:27
  • @ssbssa The problem library is the third party library. Not my code, not my build system. So no, I didn't because I couldn't. However the library functions clearly are exported because they are found when I use `dumpbin \exports` on the DLL. – AlastairG Aug 19 '21 at 10:48
  • If the third party `.lib` wasn't built using same compiler and version, you probably can't use it. Try late binding to the DLL (and hope the author didn't do non-portable things in the DLL), if that works then you can probably make up a new import library – M.M Aug 19 '21 at 11:14
  • How do I do late binding? Do you mean explicitly loading it as a dynamic library at runtime? – AlastairG Aug 19 '21 at 11:21

1 Answers1

1

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".

AlastairG
  • 4,119
  • 5
  • 26
  • 41