Linux runtime linker error - c++

I'm working though the First Steps tutorial on the POCO Project site, and I've successfully built the library (Debian Linux, 2.6.26, gcc 4.3.2) under my home directory
~/Development/POCO
with the shared libraries located in
~/Development/POCO/lib/Linux/x86_64/lib
My problem is that any application I build that depends on these libraries can only be run from the shared library directory.
~/Development/POCO/lib/Linux/x86_64$ ldd ~/Development/Cloud/DateTimeSample/bin/Linux/x86_64/DateTime
linux-vdso.so.1 => (0x00007fffe69fe000)
libPocoFoundation.so.6 (0x00007fa8de44f000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00007fa8de233000)
libdl.so.2 => /lib/libdl.so.2 (0x00007fa8de02f000)
librt.so.1 => /lib/librt.so.1 (0x00007fa8dde26000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007fa8ddb1a000)
libm.so.6 => /lib/libm.so.6 (0x00007fa8dd897000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007fa8dd680000)
libc.so.6 => /lib/libc.so.6 (0x00007fa8dd32d000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa8de7e0000)
And running DateTime from this directory would work as you would expect. However
~/Development/Cloud/DateTimeSample/bin/Linux/x86_64$ ldd DateTime
linux-vdso.so.1 => (0x00007fff24dfe000)
libPocoFoundation.so.6 => not found
libpthread.so.0 => /lib/libpthread.so.0 (0x00007ffc1c7dd000)
libdl.so.2 => /lib/libdl.so.2 (0x00007ffc1c5d9000)
librt.so.1 => /lib/librt.so.1 (0x00007ffc1c3d0000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007ffc1c0c4000)
libm.so.6 => /lib/libm.so.6 (0x00007ffc1be41000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007ffc1bc2a000)
libc.so.6 => /lib/libc.so.6 (0x00007ffc1b8d7000)
/lib64/ld-linux-x86-64.so.2 (0x00007ffc1c9f9000)
so running the executable from any other directory results in
error while loading shared libraries: libPocoFoundation.so.6: cannot open shared object file: No such file or directory
Looking at the output from the make process, the directory is correctly specified
g++ [blah] -L/home/npalko/Development/POCO/lib/Linux/x86_64
-lPocoFoundation
I've tried setting LD_LIBRARY_PATH to /home/npalko/Development/POCO/lib/Linux/x86_64, but it has not changed anything. Any help would be greatly appreciated!

If you don't want to have to deal with the LD_LIBRARY_PATH variable, you can add the linker -rpath option to the gcc command line. In your case, this would be:
gcc ... -Wl,-rpath=/home/npalko/Development/POCO/lib/Linux/x86_64
This effectively hardcodes that path in the executable, so it may or may not be suitable for your purposes.

This fails?
LD_LIBRARY_PATH=/home/npalko/Development/POCO/lib/Linux/x86_64 ~/Development/Cloud/DateTimeSample/bin/Linux/x86_64/DateTime
Just thought you may not be setting LD_LIBRARY_PATH properly
And this?
ls -alh /home/npalko/Development/POCO/lib/Linux/x86_64/libPocoFoundation.so
If both fail I can't see a reason.

You must specify to the linker the path of your library
g++ [blah] -Wl,-rpath=/home/npalko/Development/POCO/lib/Linux/x86_64
-Wl means your pass an option to the linker
-rpath is the linker option
Add a directory to the runtime library search path. This is used
when linking an ELF executable with shared objects. All -rpath
arguments are concatenated and passed to the runtime linker, which
uses them to locate shared objects at runtime. The -rpath option
is also used when locating shared objects which are needed by
shared objects explicitly included in the link;

Related

How to use dynamic linking to implement missing symbol in shared library with additional shared library

I have a shared library in linux that was compiled using glibc and I want to run it in Alpine linux without recompiling it against Alpaine C libraries.
I found that there is solution to install gcompat - which is wrapper to Alpine C library to glibc and than with
patchelf --add-needed libgcompat.so.0 /var/lib/libdyn_MyLib.so
I can add the gcompat library into the my own library without compilation and it will tell the dynamic loader to look for symbols also in libgcompat.so
It worked partially and the ldd output of the shared library is:
ldd /var/lib/libdyn_MyLib.so
/lib/ld-musl-x86_64.so.1 (0x7f79007cc000)
libgcompat.so.0 => /lib/libgcompat.so.0 (0x7f78ff278000)
libicudata.so.50 => /lib/libicudata.so.50 (0x7f78fdca4000)
libicui18n.so.50 => /lib/libicui18n.so.50 (0x7f78fd8a6000)
libicuuc.so.50 => /lib/libicuuc.so.50 (0x7f78fd52d000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x7f78fd2df000)
libm.so.6 => /lib/ld-musl-x86_64.so.1 (0x7f79007cc000)
libgomp.so.1 => /usr/lib/libgomp.so.1 (0x7f78fd298000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7f78fd27a000)
libpthread.so.0 => /lib/ld-musl-x86_64.so.1 (0x7f79007cc000)
libc.so.6 => /lib/ld-musl-x86_64.so.1 (0x7f79007cc000)
ld-linux-x86-64.so.2 => /lib/ld-linux-x86-64.so.2 (0x7f78fd274000)
libucontext.so.1 => /lib/libucontext.so.1 (0x7f78fd26f000)
libobstack.so.1 => /usr/lib/libobstack.so.1 (0x7f78fd26a000)
libdl.so.2 => /lib/ld-musl-x86_64.so.1 (0x7f79007cc000)
Error relocating libdyn_MyLib.so: feenableexcept: symbol not found
I can see that libgcompat.so is listed and there are no "not found" libraries.
All the "symbol not found" disappeared except for "feenableexecpt".
After referring to documentation, feenableexecpt is extension of glibc and not supported in gcompat package and I can understand why it's hard to support it.
I want to ignore this function call so I tried to implement "feenableexecpt" that does nothing and add this library to libdyn_MyLib.so (like implementing my own feenableexecpt that does nothing as they implement glibc library using different library).
Here is my code:
glibc_extension.h:
#ifndef __ALPINE_GLIBC__
#define __ALPINE_GLIBC__
extern int feenableexcept(int __excepts) throw ();
#endif
lib_ext.cpp:
#include "glibc_extension.h"
int feenableexcept(int e) throw () {
return 0;
}
complied it as share library:
gcc -Wall -Werror -shared -o libalpine.so lib_ext.cpp
I can see feenableexecpt in the symbols table using nm.
I had also used patchelf to add this library to my shared library, here is the output of the shared library again:
ldd /var/lib/libdyn_MyLib.so
/lib/ld-musl-x86_64.so.1 (0x7f79007cc000)
libalpine.so => /lib/libalpine.so (0x7f78ff28b000)
libgcompat.so.0 => /lib/libgcompat.so.0 (0x7f78ff278000)
libicudata.so.50 => /lib/libicudata.so.50 (0x7f78fdca4000)
libicui18n.so.50 => /lib/libicui18n.so.50 (0x7f78fd8a6000)
libicuuc.so.50 => /lib/libicuuc.so.50 (0x7f78fd52d000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x7f78fd2df000)
libm.so.6 => /lib/ld-musl-x86_64.so.1 (0x7f79007cc000)
libgomp.so.1 => /usr/lib/libgomp.so.1 (0x7f78fd298000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7f78fd27a000)
libpthread.so.0 => /lib/ld-musl-x86_64.so.1 (0x7f79007cc000)
libc.so.6 => /lib/ld-musl-x86_64.so.1 (0x7f79007cc000)
ld-linux-x86-64.so.2 => /lib/ld-linux-x86-64.so.2 (0x7f78fd274000)
libucontext.so.1 => /lib/libucontext.so.1 (0x7f78fd26f000)
libobstack.so.1 => /usr/lib/libobstack.so.1 (0x7f78fd26a000)
libdl.so.2 => /lib/ld-musl-x86_64.so.1 (0x7f79007cc000)
Error relocating libdyn_MyLib.so: feenableexcept: symbol not found
I can see libalpaine.so in the ldd output but still "feenableexecpt" is missing.
What have I done wrong?
Thanks
I was expecting the feenableexecpt symbol to be found by the dynamic program executer.

libstdc++.so not found when using patchelf and alternate glibc version

I am working on a system with a system wide glibc 2.27 and am using pathelf to patch some executable to a customized version of glibc 2.23. The executables are compiled with a custom version of LLVM. This has been working fine on C programs, but doesn't work on C++ programs.
# cp Xalan_base.cc-v2 Xalan_base.cc-v2_patched
# /usr/bin/patchelf --set-interpreter /path_to/glibc-2.23_install/lib/ld-2.23.so --set-rpath /path_to/glibc-2.23_install/lib Xalan_base.cc-v2_patched
# ./Xalan_base.cc-v2_patched -v t5.xml xalanc.xsl
/path_to/Xalan_base.cc-v2_patched: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory
# ldd Xalan_base.cc-v2
linux-vdso.so.1 (0x00007ffe9efb8000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f8db1524000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f8db1186000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f8db0f6e000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8db0b7d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8db18ad000)
# ldd Xalan_base.cc-v2_patched
linux-vdso.so.1 (0x00007ffe08b7c000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f43a5af0000)
libm.so.6 => /path_to/glibc-2.23_install/lib/libm.so.6 (0x00007f43a57eb000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f43a55d3000)
libc.so.6 => /path_to/glibc-2.23_install/lib/libc.so.6 (0x00007f43a5233000)
/path_to/glibc-2.23_install/lib/ld-2.23.so => /lib64/ld-linux-x86-64.so.2 (0x00007f43a5e79000)
# ls -lah /usr/lib/x86_64-linux-gnu/libstdc++.so.6
lrwxrwxrwx 1 root root 19 May 8 08:51 /usr/lib/x86_64-linux-gnu/libstdc++.so.6 -> libstdc++.so.6.0.25
As I understand, libstdc++ is a compiler library. I'm not seeing any paths to my LLVM installation here, and those I do see all appear valid.
Can you explain why this is happening? What do I need to do?
Can you explain why this is happening?
Your /path_to/glibc-2.23_install/lib/ld-2.23.so does not look in /usr/lib/x86_64-linux-gnu, and thus doesn't find /usr/lib/x86_64-linux-gnu/libstdc++.so.6.
You should learn to never use ldd on your patched binary, as it will lie to you. Instead, use /path_to/glibc-2.23_install/bin/ldd, and it should tell you the same thing (that it can't find libstdc++.so.6).
What do I need to do?
You need to arrange for libstdc++.so.6 to be found someplace where /path_to/glibc-2.23_install/lib/ld-2.23.so is actually looking.
Something like:
ln -s /usr/lib/x86_64-linux-gnu/libstdc++.so.6 /path_to/glibc-2.23_install/lib
should do the trick. You will likely need to repeat this for libgcc_s.so.1 as well.

Building library on Ubuntu, using it in a project on Arch - doesn't build

I'm building a dynamic library on Ubuntu 14.04.5, that depends on some static libraries (Boost and OpenSSL).
If I use this library in a project on another Ubuntu machine, it works perfectly. However, if I build it and use it in a project on an Arch machine (Antergos), it says the following during the build process:
main.cpp.o: In function `init()':
main.cpp:(.text+0xf8): undefined reference to `Util::generateString[abi:cxx11](int)'
I'm building my project with the following:
g++ -Ldeps -Ideps/include main.cpp -lmylib
deps contains libmylib.so and the required header files in deps/include.
If I run ldd on my mylib.so on Ubuntu, I get the following:
linux-vdso.so.1 => (0x00007ffdd24cf000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f10b2f97000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f10b2c91000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f10b2a73000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f10b26ab000)
/lib64/ld-linux-x86-64.so.2 (0x00007f10b3ff3000)
If I run ldd on mylib.so on Antergos, I get the following:
linux-vdso.so.1 (0x00007ffcce115000)
libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f5a42fef000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007f5a42cdc000)
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f5a42abe000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f5a4271a000)
/usr/lib64/ld-linux-x86-64.so.2 (0x000055ced49a7000)
I'm probably missing something easy, but I can't seem to get it to work. What am I doing wrong?
I'm assuming that Util::generateString[abi:cxx11](int) is a function exported by your libmylib.so library? If so, you may want to recompile that library first and then reattempt the compilation/linking of main.cpp.
I suggest this to ensure that the c++ standard library that each component is linked against is the same version. It looks like libmylib.so was compiled against the c++11 standard library, you'll want to ensure main.cpp matches that. You can always specify which one you're linking against using --std= option (e.g. --std=c++11, --std=c++0x, --std=c++17).

How to configure shared library search path after building GCC on my own?

I just built GCC 5.1 on Ubuntu 14.04, which has gcc 4.8 as default. When I try to build things with it, I find that ld will use the default libstdc++ instead of the newly build one.
Here is the output:
drizzlex#dx ~/test
$ g++ hello.cpp
drizzlex#dx ~/test
$ ldd a.out
linux-vdso.so.1 => (0x00007ffde0d25000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fa181ad2000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa1817cc000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa1815b5000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa1811f0000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa181dfd000)
And if I use $ export LD_LIBRARY_PATH=/usr/local/lib64/, it will find the right one.
drizzlex#dx ~/test
$ ldd a.out
linux-vdso.so.1 => (0x00007fffeeaf5000)
libstdc++.so.6 => /usr/local/lib64/libstdc++.so.6 (0x00007f4583d92000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4583a67000)
libgcc_s.so.1 => /usr/local/lib64/libgcc_s.so.1 (0x00007f4583850000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f458348b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f458410e000)
I would like to know what should I do to make it correct? Since I know set LD_LIBRARY_PATH is not the best choice.
For building with g++ 5.1 use this:
$ g++5.1 hello.cpp -Wl,-rpath,/usr/local/lib64
And you will not need set LD_LIBRARY_PATH.
This is from https://en.wikipedia.org/wiki/Rpath
rpath is a term in programming which refers to a run-time search path
hard-coded in an executable file or library, used during dynamic
linking to find the libraries the executable or library requires.

Asterisk module app_transcoder failed for libavcodec.so (undefined symbol avacodec_init)

I am trying to integrate the 3G video gateway with Asterisk(1.4.0).
When i load the module "app_transcoder.so" (which does the actual video transcoding), then
asterisk hangs and with "asterisk -vvvvvc" i got
asterisk: symbol lookup error: /usr/lib/asterisk/modules/app_transcoder.so: undefined symbol: avcodec_init
Showing the dependencies of app_transcoder.so by "ldd /usr/lib/asterisk/modules/app_transcoder.so" gives:
linux-vdso.so.1 => (0x00007fff851ff000)
libavcodec.so.54 => /usr/local/lib/libavcodec.so.54 (0x00007f8604ec3000)
libswscale.so.2 => /usr/local/lib/libswscale.so.2 (0x00007f8604c6e000)
libc.so.6 => /lib64/libc.so.6 (0x00007f86048d9000)
libavutil.so.52 => /usr/local/lib/libavutil.so.52 (0x00007f86046a7000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f860448a000)
libx264.so.142 => /usr/local/lib/libx264.so.142 (0x00007f86040d1000)
libgsm.so.1 => /usr/lib/libgsm.so.1 (0x00007f8603ec6000)
libm.so.6 => /lib64/libm.so.6 (0x00007f8603c42000)
libz.so.1 => /lib64/libz.so.1 (0x00007f8603a2b000)
/lib64/ld-linux-x86-64.so.2 (0x0000003b14200000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f8603827000)
"avcodec_init" comes from libavcodec.so file but it has no symbols as from the commands:
nm -a /usr/local/lib/libavcodec.so.54
gives:
nm: /usr/local/lib/libavcodec.so.54: no symbols
i am following the instructions from Medooze
CentOS-6.4
ffmpeg-1.2.6
asterisk-1.4.0
x264- 0.142x
ptlib-2.6.7
mpeg4ip-1.6.1
Any advice is appreciated.
add /usr/local/lib to your library path /etc/ld.so.conf
after that, execute "ldconfig"
recompile asterisk.
Found this ffmpeg mailing list: avcodec_init() isn't used nowadays. Instead avcodec_register_all() is used. It seems you may need to downgrade ffmpeg.