Unresolvable `R_X86_64_NONE` relocation - c++

I'm using Devtoolset-7 on CentOS 7 and have built Boost 1.65.1 w/ it.
But when I link my application, I've got the following:
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: /opt/rh/devtoolset-7/root/usr/lib64/libboost_unit_test_framework.a(compiler_log_formatter.o)(.text._ZN5boost9unit_test5utils11string_castINS0_13basic_cstringIKcEEEESsRKT_[_ZN5boost9unit_test5utils11string_castINS0_13basic_cstringIKcEEEESsRKT_]+0x3c): unresolvable R_X86_64_NONE relocation against symbol `_ZTVSt9basic_iosIcSt11char_traitsIcEE##GLIBCXX_3.4'
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
Searching more info about R_X86_64_NONE doesn't give any valuable results: mostly similar questions w/o any answer or precise explanation what is this and how to solve it.
So my questions are:
what is this error really means?
what is R_X86_64_NONE and why "nothing to relocate" (according to bintils sources) type of symbol ever exists in ELF headers?
Addendum:
The error happened on linking unit tests executable which is linked against my static library and Boosts' static libraries (unit tests framework)
All static libraries (Boost and mine one) has built with -fPIC option
PS. I really want this question to be resolved once and forever (already hit it few times, but this time update to latest binutils doesn't help). (will start a bounty on any activity on this question)

From the build log posted to the Red Hat Bugzilla bug:
[19:15:01]W: [Step 8/12] + /usr/lib/rpm/check-buildroot
[19:15:01]W: [Step 8/12] + /usr/lib/rpm/brp-scl-compress /opt/rh/devtoolset-7/root
[19:15:01]W: [Step 8/12] + /usr/lib/rpm/brp-strip-static-archive /usr/bin/strip
[19:16:40]W: [Step 8/12] /usr/bin/strip: /work/build/BUILDROOT/devtoolset-7-boost-1.65.1-4.el7.centos.x86_64/opt/rh/devtoolset-7/root/usr/lib64/libboost_container.a(global_resource.o): invalid relocation type 42
[19:16:40]W: [Step 8/12] /usr/bin/strip: BFD version 2.25.1-32.base.el7_4.2 assertion fail elf64-x86-64.c:341
Note /usr/bin/strip, not /opt/rh/devtoolset-7/root/usr/bin/strip. So the system strip command is used. 42 corresponds to the R_X86_64_REX_GOTPCRELX relocation, which is generated by DTS binutils as an optimization.
A simple way to reproduce this is with this C++ file:
#include <iostream>
void
dot ()
{
std::cout << '.';
}
If compile with -O2 -fpic, it will produce an X86_64_REX_GOTPCRELX relocation for _ZNSt8ios_base4InitD1Ev. Running /usr/bin/strip -g on that will turn that into R_X86_64_NONE. This can be verified using eu-readelf -r.
You can use RPM to tell to use the DTS strip using
%if 0%{?scl:1}
%define __strip %{_bindir}/strip
%endif
in the RPM spec file, or you can add
%undefine __brp_strip_static_archive
to skip stripping the static library completely (which is probably the right thing to do anyway).

Related

g++ failing to link statically when compiling to binary format: "skipping incompatible libm.a when searching for -lm"

While attempting to write a kernel in C++, I've run into a peculiar issue.
When prompting g++ to compile even a very basic C++ file statically and to binary, it simply keeps skipping over the static math library (libm.a), ultimately failing to compile.
Attempting to compile a simple C++ file:
test.cpp
int main() {
return 0;
}
using this g++ command:
g++ -static test.cpp -Wl,--oformat=binary
I receive the following error output:
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: skipping incompatible /usr/lib/x86_64-linux-gnu/libm.a when searching for -lm
/usr/bin/ld: cannot find -lm: No such file or directory
I am running Linux Mint Cinnamon V. 21 (Vanessa) on a VirtualBox VM.
In my attempt to narrow down the issue, I have also attempted to exclude the -static flag:
g++ test.cpp -Wl,--oformat=binary
Which results in a different error entirely:
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/11/libstdc++.so: error adding symbols: file in wrong format
collect2: error: ld returned 1 exit status
After thorough research, I was made aware that this could be caused by an incompatibility between 32-bit libraries and 64-bit files. Everything is supposed to be in 64 bit.
I did attempt to determine bitness of libm.a using file.
When using the file command on /usr/lib/x86_64-linux-gnu/libm.a, I receive the following output:
libm.a: ASCII text
indicating neither bitness. This led me to conclude that perhaps the library is damaged and needs updating. After running sudo apt-get install libc6-dev, the issue persists, however.
I'm not sure what to do at this point.
Update:
I've opened libm.a in a text editor and the entire contents of the file are:
/* GNU ld script
*/
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /usr/lib/x86_64-linux-gnu/libm-2.35.a /usr/lib/x86_64-linux-gnu/libmvec.a )
Update 2: apparently this is a linker script. Both referenced files libm-2.35.a and libmvec.a are present in my directory and are, according to objdump, 64-bit-versions.
Based on the compiler's error output, it seems that in my case, for whatever reason, g++ (or more specifically, ld) fails to use this linker script. What could possibly cause this?
I have come to the conclusion that it is not normally possible to statically link C++ code involving object oriented features into a fully functional binary file, as libm.a can apparently be linked to ELF only.
besides: even the static version of glibc, which is also required, references other dynamic libraries, making it useless for kernel code.
there might be some sort of workaround, but it seems that g++ does not support this functionality by default.

Linker error: "relocation R_X86_64_PC32 against symbol `xmlFree' ... recompile with -fPIC" but offending library was already compiled with -fPIC

I am trying to build a shared library. My aim is to pull all dependencies as static libraries into a single shared library. My understanding is that this can be done with the -Wl,--whole-archiveflag. Here is a snippet of my CMake script responsible for configuring the shared library.
# shared library
add_library(semsim SHARED "${SEMSIM_HEADERS}" "${SEMSIM_SOURCES}") # created the shared library
#fPIC for linux shared library strs
set_property(TARGET semsim PROPERTY POSITION_INDEPENDENT_CODE ON) #turn fPIC on
target_compile_options(semsim PRIVATE -Wl,--whole-archive) # enable pulling static libraries into shared library
The error I'm getting whilst trying to compile (verbose mode is on) is:
/usr/bin/c++ -fPIC -std=c++14 -g -shared -Wl,-soname,libsemsim.so -o libsemsim.so CMakeFiles/semsim.dir/CurlGet.cpp.o CMakeFiles/semsim.dir/RDFNode.cpp.o CMakeFiles/semsim.dir/Subject.cpp.o CMakeFiles/semsim.dir/Predicate.cpp.o CMakeFiles/semsim.dir/Resource.cpp.o CMakeFiles/semsim.dir/Triple.cpp.o CMakeFiles/semsim.dir/SemsimUtils.cpp.o CMakeFiles/semsim.dir/MetaID.cpp.o CMakeFiles/semsim.dir/XmlAssistant.cpp.o CMakeFiles/semsim.dir/Reader.cpp.o CMakeFiles/semsim.dir/Editor.cpp.o CMakeFiles/semsim.dir/Writer.cpp.o CMakeFiles/semsim.dir/RDF.cpp.o CMakeFiles/semsim.dir/Participant.cpp.o CMakeFiles/semsim.dir/PhysicalEntity.cpp.o CMakeFiles/semsim.dir/PhysicalPhenomenon.cpp.o CMakeFiles/semsim.dir/PhysicalProcess.cpp.o CMakeFiles/semsim.dir/PhysicalPropertyResource.cpp.o CMakeFiles/semsim.dir/PhysicalForce.cpp.o CMakeFiles/semsim.dir/Query.cpp.o CMakeFiles/semsim.dir/SemsimCombineArchive.cpp.o CMakeFiles/semsim.dir/Triples.cpp.o ../../third_party/libCombine-0.2.3/INSTALL/lib/libcombine-static.a ../../third_party/zipper/INSTALL/lib/libZipper-static.a ../../third_party/zlib-1.2.11/INSTALL/lib/libz.a /usr/local/lib/libbz2.a /usr/local/lib/libxml2.a -ldl -lbz2 -lz -lcurl -lxslt
/usr/bin/ld: /usr/local/lib/libxml2.a(uri.o): relocation R_X86_64_PC32 against symbol `xmlFree' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
However, according to this question, /usr/local/lib/lxml2.a was already compiled fPIC:
(base) ciaran#DESKTOP:/usr/local/lib$ ls
cmake libcharset.so.1.0.0 libraptor2.a librasqal.la librdf.so libxml2.so.2
libbz2.a libcurlcpp.a libraptor2.la librasqal.so librdf.so.0 libxml2.so.2.9.10
libcharset.a libiconv.la libraptor2.so librasqal.so.3 librdf.so.0.0.0 pkgconfig
libcharset.la libiconv.so libraptor2.so.0 librasqal.so.3.0.0 libxml2.a python2.7
libcharset.so libiconv.so.2 libraptor2.so.0.0.0 librdf.a libxml2.la python3.6
libcharset.so.1 libiconv.so.2.6.1 librasqal.a librdf.la libxml2.so xml2Conf.sh
(base) ciaran#DESKTOP:/usr/local/lib$ readelf -d libxml2.a | grep TEXT
(base) ciaran#DESKTOP:/usr/local/lib$
This leads me to believe that perhaps I've misunderstood the error message - could somebody shed some light on what's going on here?
You haven't misunderstood the error message, or at least not significantly.
However, according to this question, /usr/local/lib/lxml2.a was already compiled fPIC
You conclude this because the command:
/usr/local/lib$ readelf -d libxml2.a | grep TEXT
outputs nothing, which shows that you chose the second most popular answer to
that question, although at this writing it is not nearly as up-voted as the most popular answer
I guess you did that because the most popular answer tells you how to test an object file for
PIC-ness, and you want to a test a library, as the second most popular answer does. Or
perhaps because you tried the most popular answer first and it indicated that your libxml2.a
was PIC.
But the second most popular answer tests a shared library, and you use it to test
the object files in a static library. A shared library is very different from
an object file, or a static library of such, and the question to which this answer was given asks how to test
the PIC-ness of an object file. So this answer does not answer the question: really
it suggests how to test whether a file that has a name like a shared library actually is
a shared library.
The most popular answer does answer the question, and if was a correct answer then
it would be the right one for you too, because what the linker has diagnosed:
/usr/local/lib/libxml2.a(uri.o): relocation R_X86_64_PC32 against symbol `xmlFree' \
can not be used when making a shared object; recompile with -fPIC
is that the object file uri.o archived in libxml2.a is not PIC.
But the most popular answer, notwithstanding its popularity, is invalid.
The PIC-ness test that it proposes - with no supporting argument - can
misidentify non-PIC object files as PIC (as perhaps you observed).
None of the answers to that question
is a correct answer for you, and it doesn't really matter why. The system linker itself
is the ultimate authority on whether an object file is or is not position-independent.
Any one-liner test other than attempting to link the object file into a DSO is just an attempt
to second-guess the linker: if its verdict differs from
the linker's it implies that the test is broken, not the linker.
And you already know the linker's verdict. It has tried to link libxml2.a(uri.o)
into a DSO and found that it can't, because the it contains a non-position-independent
relocation record.
The /usr/local/lib/libxml2.a you've got was built on the traditional
default assumption that the object files archived therein need not be compiled to
position-independent code (with -fPIC) because the static library would only
be input to the linkage of non-position-independent executables. If you want to
link some PI binary, then you'll link it with the shared libary libxml2.so,
which is PI by definition. Your libxml2.a was furthermore built with a compiler
that does not emit PI object code by default. It is possible that your current
compiler still has that increasingly antiquated trait, but you don't need to find
out.
You need to replace your local libxml2 install with one in which the object
files in libxml2 have been compiled with fPIC. If you already know how to do that you can skip the rest of this and get on with it.
If you have somewhere got the source package of libxml2 that was built
and installed and you want to stick with that revision, then cd into its root directory and run:
make uninstall
Otherwise, remove the installation by deleting, as root, all files and symlinks matching
/usr/local/lib/libxml2 and the directory /usr/local/include/libxml2
If you want to stick with a source package you've already got (where you ran make uninstall),
then, in its root directory, run:
make distclean
to restore to its pristine state.
If you don't have a source package you want to stick with, then clone or download-and-extract the latest from https://gitlab.gnome.org/GNOME/libxml2/,
then cd into the root directory and run:
./autogen.sh
to generate the build-system.
Whatever you've done thus far, in the package root directory then run:
./configure CFLAGS=-fPIC [any other non-default configuration options]
If that completes successfully, then run:
make
If that completes successfully, then as root run:
make install
If that completes successfully, then /usr/local/lib/libxml2.a will
be recreated containing PI object files and you will be able to link your
shared library against it.
If you are unsure about [any other non-default configuration options] for
the ./configure command, then run:
./configure -h
beforehand for help, and/or seek advice.

Facebook warpdrive build - D Programming language

Of late, facebook opensourced warp, C/C++ preprocessor.
https://github.com/facebook/warp
I'm trying to build it using dmd and stuck with some build errors.
I downloaded dmd.2.065.0.zip for dmd compiler - dmd2/linux/bin64/dmd
I also see a bunch of libraries, for example libphobos2.a
Then when I build warp, I see some errors from ld, that keep complaining that phobos2.a could not be found. I exported LD_LIBRARY_PATH to the dir where this library is stored but no luck.
I compiled in verbose mode, and it doesn't give more info.
Command:
/path/to//building_stuff/dmd2/linux/bin64/dmd -O -inline -release -ofwarp cmdline.d constexpr.d context.d directive.d expanded.d file.d id.d lexer.d loc.d macros.d main.d number.d outdeps.d ranges.d skip.d sources.d stringlit.d textbuf.d -v
Error excerpt:
function textbuf.Textbuf!char.Textbuf.length
function textbuf.Textbuf!char.Textbuf.resize
gcc warp.o -o warp -m64 -L/path/to/building_stuff/dmd2/linux/bin64/../lib64 -Xlinker --export-dynamic -l:libphobos2.a -lpthread -lm -lrt
/usr/bin/ld: cannot find -l:libphobos2.a
collect2: ld returned 1 exit status
--- errorlevel 1
I was hoping the D language experts here, or those who know about warp already could give me some hint.
I was not on CentOS, as warp demands. I wonder if that could anyway be the reason.
I was not using gcc 4.7.x as warp demands, but, to me, the library could just not be located doesn't look like a problem from old gcc I have.
I was on redhat5.5 machine with 4.1 gcc.
CentOS is basically a RedHat, so everything should work OK. As people commented, your real problem is the -l:libphobos2.a in your link line. Remember, GNU/Linux allows colons in file-names, so :libphobos2.a is a perfectly valid file, and GNU ld won't find it in the library search paths.
Note that they've added a make file to easy on your compilation, I managed to compile it using "make -j" and only editing the dmd command line in the make.
just rename "libphobos2.a" to "lib:libphobos2.a.a"
I faced a similar problem with ld version 2.17, but with version 2.20 this 'l:<libfilename>' kinda syntax works fine.

Incorrect $SystemID in Mathematica

I am trying to link Mathlink libraries in mathematica. I am using a x86_64-suse-linux OS, but when I check $SystemID in Mathematica, it tells me I am using 'Linux' instead of 'Linux-x86-64'.
This is a problem because if I try to link the library as
g++ cpp2mma.cpp -L/usr/local/Wolfram/Mathematica/8.0/SystemFiles/Links/MathLink/DeveloperKit/Linux/CompilerAdditions/ -lML32i3 -lpthread -lstdc++ -lm -lrt
(the 32 bit version - and the only library in Linux/)
I get the following error:
/usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../x86_64-suse-linux/bin/ld: skipping incompatible
/usr/local/Wolfram/Mathematica/8.0/SystemFiles/Links/MathLink/DeveloperKit/Linux/CompilerAdditions//libML32i3.so when searching for -lML32i3
/usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../x86_64-suse-linux/bin/ld: skipping incompatible
/usr/local/Wolfram/Mathematica/8.0/SystemFiles/Links/MathLink/DeveloperKit/Linux/CompilerAdditions//libML32i3.a when searching for -lML32i3
/usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../x86_64-suse-linux/bin/ld: cannot find -lML32i3
collect2: ld returned 1 exit status
however, if I try to link it as
g++ cpp2mma.cpp -L/usr/local/Wolfram/Mathematica/8.0/SystemFiles/Links/MathLink/DeveloperKit/Linux-x86-64/CompilerAdditions/ -lML64i3 -lpthread -lstdc++ -lm -lrt
it compiles just fine, but if I try to run it I get the following error:
./a.out: error while loading shared libraries: libML64i3.so: cannot open shared object file: No such file or directory
This file obviously exists as running 'locate libML64i3.so' yields:
/usr/local/Wolfram/Mathematica/8.0/SystemFiles/Libraries/Linux-x86-64/libML64i3.so
/usr/local/Wolfram/Mathematica/8.0/SystemFiles/Links/MathLink/DeveloperKit/Linux-x86-64/CompilerAdditions/libML64i3.so
Am I correct in assuming that the problem lies in the fact that Mathematica thinks that I am not running a 32 bit system? If so, what do I do?
The problem is not in Mathematica. The kernel is never running -- from the perspective of e system you are compiling and launching an ELF executable. libML64i3 will start a kernel for you, but its not getting loaded here.
There are several ways to get the linker to find libML64i3.so at runtime
Export the directory containing libML64i3.so through LD_LIBRARY_PATH (generally not a good idea)
use an entry in /etc/ld.so.conf.d or /etc/ld.so.conf to indicate that /usr/local/Wolfram/Mathematica/8.0/SystemFiles/Links/MathLink/DeveloperKit/Linux-x86-64/CompilerAdditions should be part of the library search path -- look at ldconfig(8).
Symlink libML64i3.so somewhere already in the library search path
Link to a static version of libML, as described in this StackOverflow post.
To deal with the compile-time linker errors, you could compile your application 32-bit (by passing -m32 to g++). If you did this, you would get a runtime message griping about not being able to find the 32-bit version of libML, which would require the same solution as above.
I'm not sure why $SystemID is returning a value indicating you are running the 32-bit kernel. That probably has something to do with how you are starting Mathematica. On CentOS 5-7-x86_64, I have
host 11% ls -l $(which math)
lrwxrwxrwx 1 root root 51 Nov 8 16:27 /usr/local/bin/math -> \
/usr/local/Wolfram/Mathematica/8.0/Executables/math
host 12% math
Mathematica 8.0 for Linux x86 (64-bit)
Copyright 1988-2011 Wolfram Research, Inc.
In[1]:= $SystemID
Out[1]= Linux-x86-64

How to modify options being passed to ld , without recompiling gcc

I'm trying to compile shared library on solaris 2.7 using gcc 3.4.6 and
which is linking to a statically linked c .a and .o files.
Please note that it is using Sun ld from path "/usr/ccs/bin/ld"
At linking time i got a long list of symbols and following error
ld: fatal: relocations remain against allocatable but non-writable sections
collect2: ld returned 1 exit status
Then i tried to build it passing -z textoff option to ld. but i'm getting follwing error
ld: fatal: option -ztextoff and -ztext are incompatible
ld: fatal: Flags processing errors
Is there any other way where i don't need to recompile gcc and still modify the options getting passed to ld.
The errors are the result of linking position-dependent code into a shared library. Such code will result in the library not being shareable, and thus wasting RAM.
If you can rebuild all the objects you are trying to link into the shared library, the simplest (and most correct) solution is to rebuild all of them with -fPIC flag.
However, sometimes you really must link non-PIC object code which you can't rebuild into a shared library, and therefore you need to get rid of the -ztext option. To do that, add -mimpure-text option to your link line.
Run the ld executable from the command line (not via gcc) - you can then pass it whatever parameters you want. I don't think that will solve your underlying problems though - you might want to post a question about them.
Are you using make or some other build system to invoke the compiler?
If you change the options in the build system to specifically use the linker during the link phase rather than using the compiler.
Step 1: Find flags passed by gcc
Add the -v flag. It makes gcc verbose.
CXXFLAGS += -v
Step 2: Modify the link stage to explicitly use the tool that gcc was invoking.