I am trying to compile openssl but encountering an error. The CFLAGS in use are:
-O2 -fPIC -fno-strict-overflow
Can someone explain to me please what is .rodata and what the following sentence means?
/usr/bin/ld: libcrypto.a(wp_block.o): relocation R_X86_64_32S against `.rodata'
can not be used when making a shared object; recompile with -fPIC
libcrypto.a(wp_block.o): error adding symbols: Bad value
I am unsure what is libcrypto.a but apparently it is part of openssl.
How could this possibly be fixed?
/usr/bin/ld: libcrypto.a(wp_block.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC libcrypto.a(wp_block.o): error adding symbols: Bad value
Effectively, it means you are building a shared object, but you did not specify -fPIC. PIC is position independent code, and it ensures addresses are relative to the program counter, so the code can be easily relocated (the module's base address can be changed easily and stuff just works).
I believe I've seen this issue on Fedora. Since you claim you are using it in your CFLAGS, try this instead:
$ make clean && make dclean
$ export CFLAGS="-fPIC"
$ ./config shared no-ssl2 ...
$ make
...
The make clean && make dclean will ensure all artifacts (including old object files) are cleaned.
Newer versions of OpenSSL respond to make distclean, not make dclean.
I am unsure what is libcrypto.a but apparently it is part of openssl.
That's the library where OpenSSL places the crypto and helper stuff, like AES, Cameilla, SHA, big integers, etc. libssl.a is where the SSL and TLS stuff goes. libssl.a depends upon libcrypto.a.
Newer version of OpenSSL cannot find their shared libraries after install. Also see Issue 3993, libssl.so.1.1: cannot open shared object file in the OpenSSL bug tracker.
You want to use static linking so the libraries do not break your executable. If so, then you may want to find uses of -lssl and -lcrypto in the Makefiles, and change them to -l:libssl.a and -l:libcrypto.a.
try
tar -xf openssl-xxx.tar.gz
instead of
tar -zxvf openssl-xxx.tar.gz
And I don't known why it works for me!
Related
I have inherited a Makefile which builds a .so file. It is linking with -lcrypto from OpenSSL on Ubuntu with gcc 4.7.4. Critically, it is NOT linking with -lssl nor -ldl, and when I run nm -g thelib.so, it only has the ~15 symbols from openssl crypto. However, they are all U (undefined).
I'm refactoring the Makefile on another Ubuntu machine. When I link with -lcrypto, it fails due to undefined symbols needed from dl. When I add linking to -ldl, those errors go away and linking succeeds. However, my .so file is 1.5 MB bigger than the original, and there are at least a hundred symbols related to SSL, which are all T (defined), which seem to indicate that -lssl is happening implicitly somehow.
While it would seem prudent and good that they are all defined in my case, I need to figure out how to produce the same result just as it is.
So, my question is, how does one get GCC to allow the linking of a .so file and accept undefined references? I've compared our commands, and there are little differences which I've tried to eliminate, but nothing seems to work. I read that it might be related to -Wl,--no-as-needed, but i'm using that. Here's my linker flags.
g++ -shared -o mylib.so myobjs.o -fPIC -lstdc++ -lm -z defs -Wl,-soname,mylib -Wl,--no-as-needed -lpthread -lcrypto -lz
On the other system (the one with the larger result), OpenSSL has apparently not been built as a shared object, only as a static library (but maybe as PIC, so that you can link the result into a shared object). You will have to install the packages that provide the shared object and the corresponding .so symbolic link.
I have a question here on how a newly built GLIBC can be used from different machine.
I changed malloc code and compiled a local version of glibc
From : /home/1/glibc/puzzlebox/
Configure:**/eglibc-2.15/configure --prefix=/home/1/glibc/puzzlebox/lib32/ --host=i686-linux-gnu --build=i686-linux-gnu CC="gcc -m32 -g -ggdb -DMALLOC_DEBUG=1 -U__i686" CXX="g++ -m32 -g -ggdb -DMALLOC_DEBUG=1 -U __i686" CFLAGS="-O2 -march=i686 -U_FORTIFY_SOURCE -fno-stack-protector" CXXFLAGS="-O2 -march=i686 -U_FORTIFY_SOURCE -fno-stack-protector"
Make and install**: make clean;make;make install
Since my prefix is /home/1/glibc/puzzlebox/lib32/ , following directories are created under /home/1/glibc/puzzlebox/lib32/
bin etc include lib libexec sbin share
Now i copy library files /home/1/glibc/puzzlebox/lib32/lib/* to another repository /home/2/glibc/puzzlebox/lib32/lib
and pointed my gcc to use the library files from /home/2/glibc/puzzlebox/lib32/lib/* files
But i am getting the following error when compiling from
ld: cannot find /home/1/glibc/puzzlebox/lib32/lib/libc.so.6 inside
ld: cannot find /home/1/glibc/puzzlebox/lib32/lib/libc_nonshared.a inside
ld: cannot find /home/1/glibc/puzzlebox/lib32/lib/ld-linux.so.2 inside
collect2: error: ld returned 1 exit status
I am compilicc on /home/2 repository , but my glibc requires /home/1/glibc/puzzlebox/lib32/lib/libc.so.6
Is this because of static links? How can this be overcome? how can i build a glibc which can be used between repositories without rebuilding in each and every repository? and I dont want to override the already existing glibc so i dint use prefix as /usr
Please suggest!! Thanks in advance!!
Is this because of static links?
No. The most likely reason is that /home/2/glibc/puzzlebox/lib32/lib/libc.so (which is a linker script, i.e. a text file) has /home/1/glibc/puzzlebox/lib32/lib/libc.so.6 etc. in it.
You can edit that file, but really you should not compile GLIBC with --prefix=/foo unless that is where you intend to install it.
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
I'm extremely new to using Makefiles and autoconf. I'm using the Camellia image library and trying to statically link my code against their libraries. When I run "make" on the Camellia image library, I get libCamellia.a, .so, .la, and .so.0.0.0 files inside my /usr/local/lib directory. This is the command I use to compile my code with their libraries:
gcc -L/usr/local/lib -lCamellia -o myprogram myprogram.c
This works fine, but when I try to statically link, this is what I get:
gcc -static -L/usr/local/lib -lCamellia -o myprogram myprogram.c
/tmp/cck0pw70.o: In function `main':
myprogram.c:(.text+0x23): undefined reference to `camLoadPGM'
myprogram.c:(.text+0x55): undefined reference to `camAllocateImage'
myprogram.c:(.text+0x97): undefined reference to `camZoom2x'
myprogram.c:(.text+0x104): undefined reference to `camSavePGM'
collect2: ld returned 1 exit status
I want to statically link because I'm trying to modify the Camellia source code and I want to compare my version against theirs. So after some googling, I tried adding AM_DISABLE_SHARED into the configure.in file. But after running ./configure, I still get the exact same Makefile. After I "make install", I still get the same results above.
What is an easy way to get two versions of my code, one with the original Camellia source code compiled and one with my modified version? I think static libraries should work. There is an easy way to get static libraries working or are there other simple solutions to my problem? I just don't want to re-"make" and re-"make install" everytime I want to compare my version against the original.
Did you re-run autoconf after adding AM_DISABLE_SHARED and before configure, make, make install? You also can just use configure --disable-dynamic to stop it building the shared libraries. Make sure you delete any previously installed ones - make uninstall should do that. I can't see anything else obviously wrong. Try being explicit:
gcc -static -o myprogram myprogram.c /usr/local/lib/libCamellia.a
or break it down into two steps and check the symbols in myprogram.o are what you expect with nm myprogram.o.
I am not skillful with autoconf and I don't know why your attempt to link statically fails, but if linking dynamically works I think using shared libraries would actually solve your problem a little better.
Just make two shared libraries, one with the original Camellia code and one with your modified version. Put them in two different directories, and when you run myprogram you can choose between them either by switching LD_LIBRARY_PATH (or whatever you're using to find libraries) or by keeping a symbolic link in /usr/local/lib and switching it between libraries. The advantage of this over static libraries (apart from the fact that this works) is that you can tinker with your modified code, rebuild the shared library and run without having to rebuild myprogram (as long as you don't modify the signatures).
P.S. An experiment: try removing the shared libraries from /usr/local/lib and rebuilding without the -static flag, just as if you were using the shared libraries. In theory this should cause gcc to use the static libraries instead. The results may give a clue to why the static link is failing.
I am trying to write a matlab mex function which uses libhdf5; My Linux install provides libhdf5-1.8 shared libraries and headers. However, my version of Matlab, r2007b, provides a libhdf5.so from the 1.6 release. (Matlab .mat files bootstrap hdf5, evidently). When I compile the mex, it segfaults in Matlab. If I downgrade my version of libhdf5 to 1.6 (not a long-term option), the code compiles and runs fine.
question: how do I solve this problem? how do I tell the mex compilation process to link against /usr/lib64/libhdf5.so.6 instead of /opt/matlab/bin/glnxa64/libhdf5.so.0 ? When I try to do this using -Wl,-rpath-link,/usr/lib64 in my compilation, I get errors like:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../x86_64-pc-linux-gnu/bin/ld: warning: libhdf5.so.0, needed by /opt/matlab/matlab75/bin/glnxa64/libmat.so, may conflict with libhdf5.so.6
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
mex: link of 'hdf5_read_strings.mexa64' failed.
make: *** [hdf5_read_strings.mexa64] Error 1
ack. the last resort would be to download a local copy of the hdf5-1.6.5 headers and be done with it, but this is not future proof (a Matlab version upgrade is in my future.). any ideas?
EDIT: per Ramashalanka's excellent suggestions, I
A) called mex -v to get the 3 gcc commands; the last is the linker command;
B) called that linker command with a -v to get the collect command;
C) called that collect2 -v -t and the rest of the flags.
The relevant parts of my output:
/usr/bin/ld: mode elf_x86_64
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/crti.o
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/crtbeginS.o
hdf5_read_strings.o
mexversion.o
-lmx (/opt/matlab/matlab75/bin/glnxa64/libmx.so)
-lmex (/opt/matlab/matlab75/bin/glnxa64/libmex.so)
-lhdf5 (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/libhdf5.so)
/lib64/libz.so
-lm (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/libm.so)
-lstdc++ (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/libstdc++.so)
-lgcc_s (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/libgcc_s.so)
/lib64/libpthread.so.0
/lib64/libc.so.6
/lib64/ld-linux-x86-64.so.2
-lgcc_s (/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/libgcc_s.so)
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/crtendS.o
/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/../../../../lib64/crtn.o
So, in fact the libhdf5.so from /usr/lib64 is being referenced. However, this is being overriden, I believe, by the environment variable LD_LIBRARY_PATH, which my version of Matlab automagically sets at run-time so it can locate its own versions of e.g. libmex.so, etc.
I am thinking that the crt_file.c example works either b/c it does not use the functions I am using (H5DOpen, which had a signature change in the move from 1.6 to 1.8 (yes, I am using -DH5_USE_16_API)), or, less likely, b/c it does not hit the parts of Matlab internals that need hdf5. ack.
The following worked on my system:
Install hdf5 version 1.8.4 (you've already done this: I installed the source and compiled to ensure it is compatible with my system, that I get gcc versions and that I get the static libraries - e.g. the binaries offered for my system are icc specific).
Make a target file. You already have your own file. I used the simple h5_crtfile.c from here (a good idea to start with this simple file first a look for warnings). I changed main to mexFunction with the usual args and included mex.h.
Specify the static 1.8.4 library you want to load explicitly (the full path with no -L for it necessary) and don't include -lhdf5 in the LDFLAGS. Include a -t option so you can ensure that there is no dynamic hdf5 library being loaded. You also need -lz, with zlib installed. For darwin we also need a -bundle in LDFLAGS:
mex CFLAGS='-I/usr/local/hdf5/include' LDFLAGS='-t /usr/local/hdf5/lib/libhdf5.a -lz -bundle' h5_crtfile.c -v
For linux, you need an equivalent position-independent call, e.g. fPIC and maybe -shared, but I don't have a linux system with a matlab license, so I can't check:
mex CFLAGS='-fPIC -I/usr/local/hdf5/include' LDFLAGS='-t /usr/local/hdf5/lib/libhdf5.a -lz -shared' h5_crtfile.c -v
Run the h5_crtfile mex file. This runs without problems on my machine. It just does a H5Fcreate and H5Fclose to create "file.h5" in the current directory, and when I call file file.h5 I get file.h5: Hierarchical Data Format (version 5) data.
Note that if I include a -lhdf5 above in step 3, then matlab aborts when I try to run the executable (because it then uses matlab's dynamic libraries which for me are version 1.6.5), so this is definitely solving the problem on my system.
Thanks for the question. My solution above is definitely much easier for me than what I was doing before. Hopefully the above works for you.
I am accepting Ramashalanka's answer because it led me to the exact solution which I will post here for completeness only:
download the hdf5-1.6.5 library from the hdf5 website, and install the header files in a local directory;
tell mex to look for "hdf5.h" in this local directory, rather than in the standard location (e.g. /usr/include.)
tell mex to compile my code and the shared object library provided by matlab, and do not use the -ldfh5 flag in LDFLAGS.
the command I used is, essentially:
/opt/matlab/matlab_default/bin/mex -v CC#gcc CXX#g++ CFLAGS#"-Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include" CXXFLAGS#"-Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include " -O -lmwblas -largeArrayDims -L/usr/lib64 hdf5_read_strings.c /opt/matlab/matlab_default/bin/glnxa64/libhdf5.so.0
this gets translated by mex into the commands:
gcc -c -I/opt/matlab/matlab75/extern/include -DMATLAB_MEX_FILE -Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include -O -DNDEBUG hdf5_read_strings.c
gcc -c -I/opt/matlab/matlab75/extern/include -DMATLAB_MEX_FILE -Wall -O3 -fPIC -I./hdf5_1.6.5/src -I/usr/include -I/opt/matlab/matlab_default/extern/include -O -DNDEBUG /opt/matlab/matlab75/extern/src/mexversion.c
gcc -O -pthread -shared -Wl,--version-script,/opt/matlab/matlab75/extern/lib/glnxa64/mexFunction.map -Wl,--no-undefined -o hdf5_read_strings.mexa64 hdf5_read_strings.o mexversion.o -lmwblas -L/usr/lib64 /opt/matlab/matlab_default/bin/glnxa64/libhdf5.so.0 -Wl,-rpath-link,/opt/matlab/matlab_default/bin/glnxa64 -L/opt/matlab/matlab_default/bin/glnxa64 -lmx -lmex -lmat -lm -lstdc++
this solution should work on all my various target machines and at least until I upgrade to matlab r2009a, which I believe uses hdf5-1.8. thanks for all the help, sorry for being so dense with this--I think I was overly-committed to using the packaged version of hdf5, rather than a local set of header files.
Note this would all have been trivial if Mathworks had provided a set of the header files with the Matlab distribution...