Symbol lookup error when using -Wl,--defsym GCC option - c++

I've got a question regarding using one of the GCC linker options: -Wl,--defsym.
Some time ago I decided to rewrite one of my projects in C++ but without using its standard library and without even linking to it (I compile .cpp source files to object files using C++ compiler but I link them using C compiler).
For that I used following compiler flags:
-fno-exceptions -fno-rtti -nostdlib -nodefaultlibs
And following linker options:
-Wl,--defsym -Wl,__cxa_pure_virtual=0
Using those flags I got my shared library compiling and linking fine.
But after I try to use my shared library in some simple program (also compiled and linked using above flags) I get following error while running it:
examples/bin/blink: symbol lookup error: examples/bin/libblink.so: undefined symbol: __cxa_pure_virtual
where blink is the name of the executable and libblink.so is the name of my shared library.
I tried to fix it and it looks like replacing --Wl,--defsym linker flag (for both executable and library) with this function:
extern "C" void __cxa_pure_virtual
{
while (true);
}
does the job. Why is the --Wl,--defsym not working in this case?
I'd also like to mention that I tested this under Windows and it works fine there.

I think that I've found an answer to my question.
Changing the symbol address from 0 to any other value fixes my issue.
So instead of having:
--Wl,--defsym --Wl,__cxa_pure_virtual=0
I have:
--Wl,--defsym --Wl,__cxa_pure_virtual=1
This way runtime linker does not look for a symbol (which I think is the case when the address is set to 0).

Related

Mingw64 Linker error when trying to include -lhid [duplicate]

Context: I'm using Qt 5.9.3 on Windows, building for MinGW 32-bit. The Qt part is a side issue though - the problem seems to be with MinGW. The version of MinGW is 4.3.0, supplied prebuilt as part of the Qt installation.
I'm building a library which talks to a USB device over HID. Everything compiles fine, but it fails at the link stage with
./..\..\object\debug\usb_hid_device.o: In function `ZN8MyApp3USB5Win3213getDevicePathB5cxx11Ell':
<MYPATH>/../../source/win32/usb_hid_device.cpp:99: undefined reference to `HidD_GetAttributes(void*, _HIDD_ATTRIBUTES*)#8'
./..\..\object\debug\usb_hid_device.o: In function `ZN8MyApp3USB5Win3214CHIDDeviceImplC2EllRNS_15LogPerComponentE':
<MYPATH>/../../source/win32/usb_hid_device.cpp:200: undefined reference to `HidD_FlushQueue(void*)#4'
The linker command is
g++ -shared -mthreads -Wl,-subsystem,windows -Wl,--out-implib,<MYPATH>\bin\debug\libusb_hid_comms.a -o <MYPATH>\bin\debug\usb_hid_comms.dll object_script.usb_hid_comms.Debug -lhid -lsetupapi -LC:\Qt\Qt5.9.3\5.9.3\mingw53_32\lib C:\Qt\Qt5.9.3\5.9.3\mingw53_32\lib\libQt5Guid.a C:\Qt\Qt5.9.3\5.9.3\mingw53_32\lib\libQt5Cored.a
If I omit -lhid I get the same errors. I also get the same errors if I remove -lhid and explicitly set the path and filename to libhid.a. If I deliberately mistype the path and filename, it comes up with an error, so I know the command-line is getting parsed correctly. But for whatever reason, MinGW appears to not be linking with one of its own library files.
I've also tried removing -lsetupapi and I get the linker errors I'd expect for the functions defined in there. Likewise the Qt library files. But it seems that specifically for libhid.a, MinGW can see the library file but just isn't going to link with it.
Has anyone else seen this? Or can anyone else with the same (or similar) version of MinGW confirm or deny that they can link with libhid.a? Or is there something obviously wrong with what I'm doing?
I've just found the answer. I'm posting an answer myself so that other people know in future, because I think this is still a valid question which people might want to know about.
The problem is the include file hidsdi.h. The majority of other header files which pull in Win32 API calls have extern "C" around the function declarations. However this one doesn't! The result is that we end up with C++ name mangling for linker symbols, instead of the C-style "_" in front of the linker symbols.
The solution is to use
extern "C"
{
#include <hidsdi.h>
}
and then everything works fine.
The version of hidsdi.h with the older version of MinGW (which I'm porting from) did have that protection around the function declarations. However it looks like it's gone in the newer version.

Yet another linking issue with unresolved symbols

I am trying to build my program in OpenCL for ARM GPU - Mali.
I have a library libMali.so, which contains necessary symbols:
arm-v7a15v4r3-linux-gnueabi-nm *root_to_lib*/libMali.so
returns lines such as
002525b4 t clCreateKernel
and many others with all the expected OpenCL symbols.
However, compiling with
arm-v7a15v4r3-linux-gnueabi-g++ -c -Wall mandelbrot.cpp -o mandelbrot.o
arm-v7a15v4r3-linux-gnueabi-g++ mandelbrot.o -o mandelbrot -L*root_to_lib* -lMali
gives me errors like
mandelbrot.cpp:(.text+0x2e4): undefined reference toclCreateKernel'`
and others with all the symbols, which are actually present in libMali.so!
So, I kept the correct order of librabies in linking command, library is on the specified path (it is indeed) and it has the symbols.
Mangling is not the issue in this case as well: extern C specifiers were used in place and you can see that the raw entries of both lib and object file are not mangled.
Trying to accomplish the same thing using the arm-v7a15v4r3-linux-gnueabi-gcc didn't bring any change apart from necessity to link more c++ libs by hand (with -L*path* -llib).
libMali.so was built with arm-v7a15v4r3-linux-gnueabi-g++/gcc/ld, so this is not the matter of toolchain version.
I've ran out of ideas. May be someone here knows more tricky parts of linking process?
EDIT:
In fact, mandelbrot.cpp is a sample code from Mali-SDK. I'm just showing my linker problem on this example, since there obviously are no problems in the code. You can see the code here:
http://malideveloper.arm.com/downloads/deved/tutorial/SDK/opencl/mandelbrot_8cpp_source.html
http://malideveloper.arm.com/downloads/deved/tutorial/SDK/opencl/mandelbrot_8cl_source.html
If you look closely at the nm output:
002525b4 t clCreateKernel
you'll notice that the symbol is marked with a lowercase 't' which indicates that the symbol has a local binding (for example a static function) so it's not considered for binding to a undefined symbol in another object file. You can find an explanation of most of the cryptic "symbol type" letters used by nm here: https://sourceware.org/binutils/docs/binutils/nm.html
The readelf utility's output is more clear about symbols types.
Maybe the library was built incorrectly?

Undefined reference to MySQL libraries using g++

I am getting undefined reference to 'mysql_suchandsuch##' messages when trying to link my program with the MySQL libraries supplied with the 5.5 server. When MySQL was installed, I used the default path, which for me on Windows is C:\Program Files\MySQL\MySQL Server 5.5\. Originally, I had thought that the spaces are causing my grief, but I think I've correctly worked out how to point to the library path without spaces (still with no luck). If there's another probable cause, please let me know.
I have reviewed a series of questions on this site trying to resolve my issue...
Question 1
Question 2
Question 3
Question 4
Question 5
Question 6
Question 7
Using mingw/g++, I have tried to link using the following options, based on my own research as well as suggestions here:
-L"C:\Program Files\MySQL\MySQL Server 5.5\lib\" -llibmysql.lib
-L"C:\Program Files\MySQL\MySQL Server 5.5\lib\" -lmysqlclient.lib
-L"C:\Progra~1\MySQL\MySQLS~1.5\lib\" -llibmysql.lib
-LC:\Progra~1\MySQL\MySQLS~1.5\lib\ -lmysqlclient.lib
-L"C:\Progra~1\MySQL\MySQLS~1.5\lib\" -lmysql
In all cases, I have put the -L/-l options at the right-most part of the statement, as I understand this can matter.
I have confirmed the libraries do exist. In the /lib dir, I have libmysql.lib, mysqlclient.lib, and libmysql.dll. I have not tried to link with the .dll, as no tutorial/forum I've reviewed suggested that.
I am not using MAKEFILES.
Does anyone have specific experience with g++/MySQL?
The following commands work fine for me using a GCC 4.6.1 from November 2011:
g++ my.cpp -I D:\Opt\MySQL5.5\include ^
D:\Opt\MySQL5.5\lib\libmysql.dll -o myWithDll.exe
g++ my.cpp -I D:\Opt\MySQL5.5\include ^
-L D:\Opt\MySQL5.5\lib -lmysql -o myWithLib.exe
So both linking against the LIB and the DLL do work.
You may get a warning (see Gaffi's comment). This is because the linker does fuzzy linking for you without you having it specified; normally, it would have failed to link. It is being nice, though, and making it work for you, at the same time warning you about things happening without your having requested them. The way to suppress the warning is to make fuzzy linking explicit:
g++ -Wl,--enable-stdcall-fixup my.cpp -I D:\Opt\MySQL5.5\include ^
D:\Opt\MySQL5.5\lib\libmysql.dll -o myWithDll.exe
g++ -Wl,--enable-stdcall-fixup my.cpp -I D:\Opt\MySQL5.5\include ^
-L D:\Opt\MySQL5.5\lib -lmysql -o myWithLib.exe
This is a Cygwin/RedHat/MinGW extension to the linker; the docs are here:
--enable-stdcall-fixup
--disable-stdcall-fixup
If the link[er] finds a symbol that it cannot resolve, it will attempt to
do “fuzzy linking” by looking for another defined symbol that differs
only in the format of the symbol name (cdecl vs stdcall) and will
resolve that symbol by linking to the match. For example, the
undefined symbol _foo might be linked to the function _foo#12, or the
undefined symbol _bar#16 might be linked to the function _bar. When
the linker does this, it prints a warning, since it normally should
have failed to link, but sometimes import libraries generated from
third-party dlls may need this feature to be usable. If you specify
--enable-stdcall-fixup, this feature is fully enabled and warnings
are not printed. If you specify --disable-stdcall-fixup, this feature is
disabled and such mismatches are considered to be errors. [This option
is specific to the i386 PE targeted port of the linker]
did you try -lmysql as the linker automatically prepends lib and appends .lib

How can I find the calling routine for a symbol in case of a linker error "undefined reference"?

I have a problem linking an application for an embedded target. I'm developing on a windows box using Min-GW for an ARM9 target that runs under Linux.
Actually I'm switching from static linking to dynamic linking with .so-libraries to save memory space.
I get the error message
libT3Printer.so: undefined reference to `__ASSERT'
I checked all the sources for the lib and I have no idea where this function could be called. Is there any possibility to find out, who (which source file or function) could be the caller of the missing function?
The reference is probably being hidden by a macro. If you run the compiler with the -E option to generate predecessor output you might have a better chance of tracking it down.
Try to add definition NDEBUG.
In C, compiling with NDEBUG defined:
gcc -DNDEBUG foo.c
disables all calls to assert(), and this behavior is identical in C++:
g++ -DNDEBUG foo.cpp

C/C++ linker CALL16 reloc at xxxxx not against global symbol

I'm getting these errors while linking, both messages have to do with the same object file.
CALL16 reloc at 0x5f8 not against global symbol
and
could not read symbols: Bad value
The 2nd message seems to be the reason I'm getting the CALL16 error, but the file compiles just fine.
Any tips on fixing this?
FYI, I'm cross compiling for a MIPS target and using gcc 4.1.2
EDIT: No luck so far:
Here are my flags used:
-fPIC,-Wl,-rpath,-Wl,-O1
I've also tried the following without success:
-mno-explicit-relocs
-mexplicit-relocs
-mlong-calls
-mno-long-calls
-mxgot
-mno-xgot
Meanwhile, I'll go back to the source at this point and investigate more.
Aha!
Thanks to a colleague of mine, we found the issue.
Here was the issue:
There was a forward declaration/prototype of a function.
void FooBarIsBest(void);
Later on in the file the function was defined.
static void FooBarIsBest(void)
{
// do the best
}
The issue here was that in the prototype the keyword static was left out. So it was like a whole new function was being defined.
The CALL16 reference is used by gcc for relocatable code. The assembly code of the file showed that CALL16 was being used on this function... Which is wrong, as this function is local.
Interestingly, this code used to compile & link just fine with an older version of gcc (3.2.2).
Another lessoned learned. :)
Try -mlong-calls flag to the compiler.
Also see the manual for more specific MIPS options.