binutils bfd links against system iberty instead of built iberty - makefile

When building binutils, the bfd component is failing to link because it is linking against the system version of libiberty instead of the built version under binutuils/libiberty/lib64/libiberty.a.
I can't see a configure argument to allow me to override this. What's the best way to instruct configure to construct an LD_LIBRARY_PATH that prefers libraries from other components of its build over system versions? Obviously, it needs system libraries that are prerequisites, so I can't exclude this path entirely.
This is the error, due to the system version having not been compiled correctly. The version under binutils/libiberty/lib64 is compiled with -fPIC, so I need to tell configure to use that.
/lib64/libiberty.a(cplus-dem.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
It doesn't seem as trivial to specify .:/usr/lib64:/lib64 since . is binutils/bfd.

I had a look at the generated automakefile and LDFLAGS was only specifying the system libraries:
LDFLAGS := -L/usr/lib64 -L/usr/lib
So I specified this as an argument to configure. Slightly hacky, but can't see a better way out:
LDFLAGS="-L./ -L../ -L../libiberty/pic -L/usr/lib64 -L/usr/lib" ./confgiure --enable-shared

Related

GCC gprof complaining GLIBC_2.16 is not found

I have a code running on a PowerPC e500v2 embedded Linux and I want to measure its performance since it is running in an infinite loop. I tried gcc's gprof which was simply by adding -pg option to gcc. When I run the binary on the target device I get this:
./main: /lib/libc.so.6: version GLIBC_2.16 not found (required by ./main)
I am using ELDK 5.6 toolchain with the default CFLAGS and LDFLAGS and these flags: -Wall -lrt -pthread -D_GNU_SOURCE nothing else. Some article suggested defining FORTIFY_SOURCE along with an optimization level but it did not work. I searched for some gcc's feature test macros and tried defining some GLIBC 2.16 specific macros but it did not work.
I faced similar issue with GLIBC 2.17 when I used some structures and functions from <sched.h>, adding _GNU_SOURCE resolved it. Any idea on how to resolve it?
When I run the binary on the target device I get this
Your tool chain targets a version of GLIBC that is newer than what is installed on the target.
This doesn't bite you in non-pg compiles only by accident. An "innocent" change to your source can cause the same problem.
You need to upgrade your target to the version of GLIBC which your toolchain actually builds for.

Symbol relocation from one compiler version to another

I'm compiling a static library, let's call it static.a which is later linked by a shared library shared.so and by a final executable binary file (shared.so uses just a few functions from static.a maybe later this can be further splited). If I try to compile it suing gcc 7.4 I get this linker error:
/usr/bin/ld: ../../static.a(file.cpp.o): relocation R_X86_64_TPOFF32 against symbol `_ZGVZN6spdlog7details2os9thread_idEvE3tid' can not be used when making a shared object; recompile with -fPIC
I decided to try also gcc 9.1 and this error doesn't apear anymore.
should I always use -fpic when building a static library that will be used in a shared library? I know fpic adds some overhead.
how come a newer version of gcc can relocate the symbols of the static.a inside the shared library? Is this safe?
Thank you.
All code in shared library should be compiled with -fPIC so your static library should too. -fPIC does indeed introduce an overhead but to a large extent it can be mitigated with options like -fno-semantic-interposition and/or -fvisibility=hidden.
The error that you see is coming from the linker so it seems that the newer GCC does not use the problematic relocation. You can inspect the generated assembly to find out the difference in generated code.

Building shared library with ffmpeg results in relocation error

I need to create a custom shared library that internally uses ffmpeg functions. The idea is to create one fat shared library, say, myffmpeg.so.
I first build ffmpeg code (3.3.1 as of this post). During configuration, I specify -fPIC via --extra-cflags and --extra-cxxflags. I also specify -enable-pic during the configuration. After running configure and make, various archive files such as libswscale.a, libavformat.a, etc. are successfully created.
Next, I try to build my shared library:
gcc -fPIC -Ixxx mywrapper.cpp
gcc -shared -o myffmpeg.so mywrapper.o -Lxxx -lswscale -lavformat...
However, this results in an error:
Relocation R_X86_64_PC32 against symbol ff_M24A can not be
used when making a shared object;
Looks like I am missing some compiler/linker setting. Can someone please point me in the right direction? Regards.
Here is how I solved the problem. You need to add "-Wl,-Bsymbolic" to ldflags during configuration. Also, when you create the shared library, you need to pass the same parameter to the linker. Regards.
If you need shared libraries, build ffmpeg with --enable-shared, which will generate shared objects libswscale.so, libavformat.so, etc. The .a files are static libraries built by default configuration.

Why is the CMake solution for "R_X86_64_32 can not be used when making a shared object" specific to x86_64?

I just got this error when compiling some plugins for my new toy (on gcc/g++ on Linux):
relocation R_X86_64_32 can not be used when making a shared object; recompile with -fPIC
I basically understand why PIC is needed but, within the CMake system, the solution seems to be this:
IF (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
SET_TARGET_PROPERTIES (${PLUGIN_BASE_LIB} PROPERTIES COMPILE_FLAGS "-fPIC")
ENDIF (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
I don't understand why this solution is conditional.
The follow-up seems to suggest that -fPIC should be used basically everywhere except 32-bit Linux, which suggests that the above is not portable.
Should I always use -fPIC? Will there be any adverse effects?
${PLUGIN_BASE_LIB} needs to be statically linked to both the main executable, and statically the various shared libraries which are the plugins.
Ideally you want to build two versions of code: one for the main executable and one for the library. The first will need to be compiled with -fPIE (which is default in modern distros) and the second with -fPIC. As you point out this does not depend on target architecture.
You can compile only one version with -fPIC but then main executable will be suboptimal because -fPIC forces compiler to obey symbol interposition rules which significantly limits it's ability to optimize code e.g. inline and clone functions.

GCC link order changed?

I am trying to link a C++ module using GCC, essentially like this:
gcc -c hello.c
g++ -c world.cpp
gcc -ohello -lstdc++ hello.o world.o
Note that I use -lstdc++ to link the C++ module in, so that I can use gcc instead of g++. The problem is that I'm getting the error:
undefined reference to `operator new(unsigned long)'
(Assuming that world.cpp contains at least one call to new.)
This error is fixed if I put -lstdc++ at the end of the linker line, like this:
gcc -ohello hello.o world.o -lstdc++
I am aware that this question has been asked many times here, but I have a special requirement. I am not directly calling GCC. I am using a build system for a different programming language (Mercury) which is calling GCC on my behalf, and I can't easily modify the way it calls GCC (though I can specify additional libraries using the LDFLAGS environment variable). So I have two additional requirements:
I cannot use g++ to link (only gcc) -- that is why I am doing the -lstdc++ trick above rather than simply linking with g++).
I don't think that I can control the order of the linker commands -- Mercury will put the .o files on the command-line after any libraries.
I understand the basic reason why the order is important, but what is baffling me is why did this break now? I just updated to Ubuntu 11.10 / GCC 4.6.1. I have been successfully compiling this program for years using precisely the above technique (putting -lstdc++ first). Only now has this error come up. An unrelated program of mine links against OpenGL using -lgl and that too broke when I upgraded and I had to move -lgl to the end of the command-line. I'm probably going to discover that dozens of my programs no longer compile. Why did this change? Is there something wrong with my new system or is that the way it is now? Note that these are ordinary shared libraries, not statically linked.
Is there anything I can do to make GCC go back to the old way, where the order of libraries doesn't matter? Is there any other way I can convince GCC to link libstdc++ properly without moving it after the .o files on the command-line?
If Mercury puts object files after libraries, Mercury is broken. Libraries belong after object files - always. You may sometimes get away with the reverse order, but not reliably. (Static libraries must go after the object files that reference symbols in the static library. Sometimes, a linker will note the symbols defined by a shared library even when none of the symbols are used; sometimes, the linker will only note the shared library symbols if the shared library provides at least one symbol.)

Resources