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?
Related
I have an unresolved symbol error when trying to compile my program which complains that it cannot find __dso_handle. Which library is this function usually defined in?
Does the following result from nm on libstdc++.so.6 mean it contains that?
I tried to link against it but the error still occurs.
nm libstdc++.so.6 | grep dso
00000000002fc480 d __dso_handle
__dso_handle is a "guard" that is used to identify dynamic shared objects during global destruction.
Realistically, you should stop reading here. If you're trying to defeat object identification by messing with __dso_handle, something is likely very wrong.
However, since you asked where it is defined: the answer is complex. To surface the location of its definition (for GCC), use iostream in a C++ file, and, after that, do extern int __dso_handle;. That should surface the location of the declaration due to a type conflict (see this forum thread for a source).
Sometimes, it is defined manually.
Sometimes, it is defined/supplied by the "runtime" installed by the compiler (in practice, the CRT is usually just a bunch of binary header/entry-point-management code, and some exit guards/handlers). In GCC (not sure if other compilers support this; if so, it'll be in their sources):
Main definition
Testing __dso_handle replacement/tracker example 1
Testing __dso_handle replacement/tracker example 2
Often, it is defined in the stdlib:
Android
BSD
Further reading:
Subtle bugs caused by __dso_handle being unreachable in some compilers
I ran into this problem. Here are the conditions which seem to reliably generate the trouble:
g++ linking without the C/C++ standard library: -nostdlib (typical small embedded scenario).
Defining a statically allocated standard library object; specific to my case is std::vector. Previously this was std::array statically allocated without any problems. Apparently not all std:: statically allocated objects will cause the problem.
Note that I am not using a shared library of any type.
GCC/ARM cross compiler is in use.
If this is your use case then merely add the command line option to your compile/link command line: -fno-use-cxa-atexit
Here is a very good link to the __dso_handle usage as 'handle to dynamic shared object'.
There appears to be a typo in the page, but I have no idea who to contact to confirm:
After you have called the objects' constructor destructors GCC automatically calls the function ...
I think this should read "Once all destructors have been called GCC calls the function" ...
One way to confirm this would be to implement the __cxa_atexit function as mentioned and then single step the program and see where it gets called. I'll try that one of these days, but not right now.
Adding to #natersoz's answer-
For me, using -Wabi-tag -D_GLIBCXX_USE_CXX11_ABI=0 alongside -fno-use-cxa-atexit helped compile an old lib. A telltale is if the C++ functions in the error message have std::__cxx11 in them, due to an ABI change.
I am compiling legacy code using gcc compiler 4.8.5 on RHEL7. All C and C++ files have "-unsigned" as one of the default flags for both gcc and g++ compilation. The compiler accepts this option and compiles successfully. However, I cannot find any documentation of this option anywhere either in gcc manual or online. Does anyone know what this option is? I have to port the code and am confused whether this compiler option needs to be ported or not.
I suspect it was just a mistake in the Makefile, or whatever is used to compile the code.
gcc does not support a -unsigned option. However, it does pass options to the linker, and GNU ld has a -u option:
'-u SYMBOL'
'--undefined=SYMBOL'
Force SYMBOL to be entered in the output file as an undefined
symbol. Doing this may, for example, trigger linking of additional
modules from standard libraries. '-u' may be repeated with
different option arguments to enter additional undefined symbols.
This option is equivalent to the 'EXTERN' linker script command.
The space between -u and the symbol name is optional.
So the intent might have been to do something with unsigned types, but the effect, at least with modern versions of gcc, is to enter nsigned in the output file as an undefined symbol.
This seems to have no effect in the quick test I did (compiling and running a small "hello, world" program). The program runs correctly, and the output of nm hello includes:
U nsigned
With an older version of gcc (2.95.2) on a different system, I get a fatal link-time error about the undefined symbol.
I suspect the intention is for the program to be compiled with -funsigned-char. I don't know whether this instead used to be -unsigned, back in dinosaur times, and perhaps GCC actually still heeds that spelling; there's no way to know from the manual because, if it does, it's an undocumented feature.
I'd ask the original author for the intention here, since they didn't see fit to document.
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).
I am writing a fairly large C++ shared-object library, and have run into a small issue that makes debugging a pain:
If I define a function/method in a header file, and forget to create a stub for it (during development), since I am building as a shared object library rather than an executable, no errors appear at compile-time telling me I have forgotten to implement that function. The only way I find out something is wrong is at runtime, when eventually an application linking against this library falls over with an 'undefined symbol' error.
I am looking for an easy way to check if I have all the symbols I need at compile time, perhaps something I can add to my Makefile.
One solution I did come up with is to run the compiled library through nm -C -U to get a demangled list of all undefined references. The problem is this also comes up with the list of all references that are in other libraries, such as GLibC, which of course will be linked against along with this library when the final application is put together. It would be possible to use the output of nm to grep through all my header files and see if any of the names corresponding.. but this seems insane. Surely this is not an uncommon issue and there is a better way of solving it?
Check out the linker option -z defs / --no-undefined. When creating a shared object, it will cause the link to fail if there are unresolved symbols.
If you are using gcc to invoke the linker, you'll use the compiler -Wl option to pass the option to the linker:
gcc -shared ... -Wl,-z,defs
As an example, consider the following file:
#include <stdio.h>
void forgot_to_define(FILE *fp);
void doit(const char *filename)
{
FILE *fp = fopen(filename, "r");
if (fp != NULL)
{
forgot_to_define(fp);
fclose(fp);
}
}
Now, if you build that into a shared object, it will succeed:
> gcc -shared -fPIC -o libsilly.so silly.c && echo succeeded || echo failed
succeeded
But if you add -z defs, the link will fail and tell you about your missing symbol:
> gcc -shared -fPIC -o libsilly.so silly.c -Wl,-z,defs && echo succeeded || echo failed
/tmp/cccIwwbn.o: In function `doit':
silly.c:(.text+0x2c): undefined reference to `forgot_to_define'
collect2: ld returned 1 exit status
failed
On Linux (which you appear to be using) ldd -r a.out should give you exactly the answer you are looking for.
UPDATE: a trivial way to create a.out against which to check:
echo "int main() { return 0; }" | g++ -xc++ - ./libMySharedLib.so
ldd -r ./a.out
What about a testsuite ? You create mock executables that link to the symbols you need. If the linking fails, it means that your library interface is incomplete.
I had the same problem once. I was developing a component model in C++, and, of course, components should load at runtime dynamically. Three solutions come to mind, that were the ones I applied:
Take some time to define a build system that is able to compile statically. You'll lose some time engineering it, but it will save you much time catching these annoying runtime errors.
Group your functions in well-known and well-understood sections, so that you can group of functions/stubs to be sure that each corresponding function has its stub. If you take the time on documenting it well, you can write perhaps a script that checks the definitions (via, for example, its doxygen comments) and check the corresponding .cpp file for it.
Do several test executables that load the same set of libraries and specify the RTLD_NOW flag to dlopen (if you're under *NIX). They will signal the missing symbols.
Hope that helps.
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