In my Linux Mint i have a program, an executable file.
With ldd in terminal i can take dependensies of this executable.
ldd file
When move program in another system it dont runs.
ldd file gives something like ...
linux-vdso.so.1 => (0x00007ffc2a36d000)
libwx_gtk2u_stc-3.0.so.0 => /usr/lib/x86_64-linux-gnu/libwx_gtk2u_stc-3.0.so.0 (0x00007f2919d55000)
libwx_gtk2u_adv-3.0.so.0 => /usr/lib/x86_64-linux-gnu/libwx_gtk2u_adv-3.0.so.0 (0x00007f291996f000)
libwx_gtk2u_core-3.0.so.0 => /usr/lib/x86_64-linux-gnu/libwx_gtk2u_core-3.0.so.0 (0x00007f29190f5000)
libwx_baseu-3.0.so.0 => /usr/lib/x86_64-linux-gnu/libwx_baseu-3.0.so.0 (0x00007f2918c63000)
libsqlite3.so.0 => /usr/lib/x86_64-linux-gnu/libsqlite3.so.0 (0x00007f291898e000)
...............
How i can know all that libraries and install only it needs to run to other system.
Using objdump -p /path/to/program | grep NEEDED i can get only libs that i need?
Thanks!
ldd's output says that you have got all the library dependencies installed on your system.
The reason it doesn't run on another system is most likely due to the difference in linking table of those libraries, so your program simply cannot find symbols it is looking for by that addresses.
As a simple solution, I would recommend to recompile program on a new machine.
Related
I have a compiled binary file.bin, which is dynamically linked to others.
$ ldd file.bin
linux-vdso.so.1 (0x00007ffc017c6000)
so.6 => /usr/lib/libm.so.6 (0x00007f3af51d7000)
so.2 => /usr/lib/libdl.so.2 (0x00007f3af51d1000)
so.6 => /usr/lib/libc.so.6 (0x00007f3af5008000)
ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f3af61a7000)
I need to be lib-independent, because my target system uses different version of those libraries. (executing file.bin on the target yields errors: /lib64/libm.so.6: version 'GLIBC_2.27' not found). I do not have the source code of file.bin.
My attempt is to add those dynamically linked files into that binary, I could not find any tools to do that. Is it even possible?
If that's helping: I can run the file.bin on a kernel 5.10.6-arch1-1 and the target is a kernel 3.10.0-1062.9.1.el7.x86_64
Without the source code for file.bin, you cannot build a static binary.
However, there are a number of tools such as Statifier and Ermine which can help you package the existing dynamic binary and its dependencies into a single binary.
Quoting from the Ermine website:
What can Ermine do for you?
Ermine packs a GNU/Linux application together with any needed shared libraries and data files into a single executable. This file can be copied to any GNU/Linux host and run without further modifications.
Basic functionality:
Only one file is installed
Escape from “dependency hell”
Independence from package management (RPM, DEB, TGZ, ...)
No version mismatch between the executable and its auxiliary files
No host-dependent side-effects: the application and the target host's software environment do not interfere with each other
I've just compiled an executable with stack build and then just copying over the executable to a different machine, however running the application results in:
./app: error while loading shared libraries: libcrypto.so.1.1: cannot open shared object file: No such file or directory
I'm guessing I need to install some packages from the appropriate Linux distro's packages - but is there more efficient way then googling for each error that comes up and trying to identify the package?
I've tried running executable within some docker images:
fpco/haskell-scratch, debian:stretch-slim which all result in the same behaviour:
sudo docker run --rm -it -v $(pwd):/abcxyz fpco/haskell-scratch sh
# /abcxyz/app
/abcxyz/app: error while loading shared libraries: libcrypto.so.1.1: cannot open shared object file: No such file or directory
Update
With the debian image I installed openssl:
apt-get install openssl
New error:
/abcxyz/app: error while loading shared libraries: libgmp.so.10: cannot open shared object file: No such file or directory
apt-get install libgmp-dev
And it works...
This is actually not specific to Haskell, but rather to the way Linux dynamically links shared libraries. You can use ldd <file>:
% ldd ./StateSort
linux-vdso.so.1 (0x00007ffd29385000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007fd986bd1000)
libgmp.so.10 => /usr/lib/libgmp.so.10 (0x00007fd98693e000)
librt.so.1 => /usr/lib/librt.so.1 (0x00007fd986736000)
libdl.so.2 => /usr/lib/libdl.so.2 (0x00007fd986532000)
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007fd986314000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007fd985f5c000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007fd986f1d000)
If there are missing libraries, you will notice them right away: the right hand side with the path to the so file will be absent.
You will then have to refer to your Linux distro's package management system to find out what package may contain the desired so file. For Ubuntu you would use apt-file, for ArchLinux − pkgfile, and so on.
I must warn you that ldd actually executes some of the code found in a file, so a malicious program may take over and wreak havoc. If you want to dissect an executable of unknown origin this way, you must do so in a disposable forensic containment. As I understand, this is not applicable in the case at hand, but nevertheless I must warn you.
I have a question and I hope some guru here could help me out :) My goal is simple : (GOAL1) build a older glibc on a newer system and (GOAL2) build old software that can run on older glibc. I am on gcc4.9, glibc2.19, amd64 system. I did compile glibc2.14 and gcc4.7.3 on my system.
(convention : /path/to/libc2.14_dir = $LIBC214, /path/to/gcc4.7.3 = $GCC473)
I am trying to compile bash4.2.53 ( and other softwares coreutil, binutil, qt3.3...) using newly built glibc2.14. My configure and make looks like this : ( I am being in object/build directory )
$ cd /path/to/build/bash-4.2.53
$ CC=$GCC473/bin/gcc CXX=$GCC473/bin/g++ CPP=$GCC473/bin/cpp \
/path/to/source/bash-4.2.53/configure \
--prefix=/path/to/installation/bash-4.2.53
$ make all V=1 \
CFLAGS="-Wl,--rpath=$LIBC214/lib -Wl,--dynamic-linker=$LIBC214/lib/ld-linux-x86-64.so.2" \
CPPFLAGS="-Wl,--rpath=$LIBC214/lib -Wl,--dynamic-linker=$LIBC214/lib/ld-linux-x86-64.so.2" \
CXXFLAGS="-Wl,--rpath=$LIBC214/lib -Wl,--dynamic-linker=$LIBC214/lib/ld-linux-x86-64.so.2"
When make is done in bash4.2.53 build (object) directory, I tried 2 scenarios :
SCENARIO1. Use system's libc2.19
$ ldd ./bash
linux-vdso.so.1 (0x00007ffe677c3000)
libtinfo.so.5 => $MY_PREBUILT_NCURSE/lib/libtinfo.so.5 (0x00007f5d108e3000)
libdl.so.2 => $LIBC214/lib/libdl.so.2 (0x00007f5d106df000)
libc.so.6 => $LIBC214/lib/libc.so.6 (0x00007f5d10354000)
$LIBC214/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f5d10b0a000)
This line is weird :$LIBC214/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f5d10b0a000)
$ $LIBC214/bin/ldd ./bash
not a dynamic executable
SCENARIO2. Add $LIBC214/bin to my PATH, $LIBC214/lib to my LD_LIBRARY_PATH
$ ldd ./bash
/bin/bash: $LIBC214/lib/libc.so.6: version `GLIBC_2.15' not found (required by /bin/bash)
$ export SHELL=$PWD/bash
$ ldd --version
/bin/bash: $LIBC214/lib/libc.so.6: version `GLIBC_2.15' not found (required by /bin/bash)
$ ldd ./bash
/bin/bash: $LIBC214/lib/libc.so.6: version `GLIBC_2.15' not found (required by /bin/bash)
As far as I can tell, SCENARIO2 is the right way to run commands. My assumption is that I built glibc2.14 wrongly, that it uses /bin/bash which in turn uses glibc2.19. I am not really sure.
My question:
Could you please explain for me the weird line above and the following line that out put not a dynamic executable?
Could you share me your steps to properly build glibc (GOAL1) and build software using that glibc (GOAL2) ?
What could I do next to solve 2 above scenario?
Thank you.
when you link ELFs, the absolute path to the ldso is hardcoded in it. if you want to use a different one, you can use the -Wl,--dynamic-linker=/path/to/ldso flag to override it. this path is absolute though, so if you try to move your local glibc somewhere else, the ELFs you linked will fail to execute (with errors like no such file). there's no way around this as the system, by design, must have an absolute path in it to the interpreter.
the reason you get weird not a dynamic executable output is that ldd works by actually executing the target ELF and extracting (via debug hooks) the libraries that get loaded. so when you attempt to use a diff ldd like that, glibc gets confused. if you want a stable dependency lister, you might consider something like lddtree from the pax-utils project (most distros have this bundled nowadays). or run readelf -d on the file directly and look at all the DT_NEEDED entries.
trying to build & maintain your own toolchain (glibc, gcc, etc...) is a huge hassle. unless you want to dedicate a lot of time to this, you really should use a project like crosstool-ng to manage it for you. that will allow you to build a full toolchain using an older glibc, and then you can use that to build whatever random packages you like.
if you really really want to spend time doing this all by hand, you should refer to the glibc wiki for building your own glibc and then linking apps against that glibc.
I am building tmux-2.0 from sources on a pretty regular Linux host. First attempt failed as it turned out that the version of libevent installed is older than required, so I proceeded to download and build libevent-2.0.22 from sources (current at the time of writing) first.
Building of libevent succeeded flawlessly, and I thought I could then retry building tmux with the following:
PKG_CONFIG_PATH=$PATH_TO_MY_BUILT_LIBEVENT/lib/pkgconfig ./configure ...
The above invocation succeeded, so did subsequent make and make install.
Running my newly build tmux, however, aborts with a missing shared object, not surprisingly libevent-2.0.so.5:
tmux: error while loading shared libraries: libevent-2.0.so.5: cannot open shared object file: No such file or directory
I thought building against a custom library implies it will also be used at runtime? ldd on my tmux gives me:
linux-vdso.so.1 => (0x00007fff8f5ff000)
libutil.so.1 => /lib64/libutil.so.1 (0x0000003cf8800000)
libncurses.so.5 => /lib64/libncurses.so.5 (0x0000003cf7e00000)
libevent-2.0.so.5 => not found
librt.so.1 => /lib64/librt.so.1 (0x0000003ce8600000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x0000003cea200000)
libc.so.6 => /lib64/libc.so.6 (0x0000003ce7600000)
libtinfo.so.5 => /lib64/libtinfo.so.5 (0x0000003cf7200000)
libdl.so.2 => /lib64/libdl.so.2 (0x0000003ce7e00000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003ce8200000)
/lib64/ld-linux-x86-64.so.2 (0x0000003ce7200000)
So, libevent-2.0.so.5 is not found.
Do I need to resort to setting, I don't know, LIBS, LDFLAGS or some other variables or switches to configure script above, so that, I don't know, the paths to my newly built libevent are embedded in tmux binary, courtesy of ld?
I do not have root access - university Linux workstation - and frankly I don't need one, I think. I also do not want to muck about with LD_LIBRARY_PATH or the like. Suffice to say, doing LD_LIBRARY_PATH=$PATH_TO_MY_LIBEVENT/lib tmux works fine. But I want it to work "by default", locating and using my libevent.
I guess the solution would apply to pretty much any software using the "GNU build system". What's the right thing to do here?
You built against a library, but the system doesn't know where the library is. Since you don't want to install the library, but rather leave it in the place where you built it, you could solve it with -rpath= option of the linker — it embeds a search path for libraries into the executable file.
Just rebuild your application with it being added to your LDFLAGS, like LDFLAGS="-rpath=/home/mypath/to/libevent" (but note, it is a linker option, and it is possible that in the makefile as a linker used the gcc itself — gcc does not know the option, then you need to write it likeLDFLAGS="-Wl,-rpath=/home/mypath/to/libevent" to force gcc to pass the option down to the actual linker)
By the way, actually you can change rpath even without recompiling the application — there's a tool patchelf for that job.
I'm running eclipse on Ubuntu using a g++ compiler and I'm trying to run a sample program that utilizes xerces.
The build produced no errors however, when i attempted to run the program, I would receive this error:
error while loading shared libraries: libxerces-c-3.1.so: cannot open shared object file: No such file or directory
libxerces-c-3.1.so is in the directory /opt/lib which I have included as a library in eclipse. The file is there when I checked the folder. When I perform an echo $LD_LIBRARY_PATH, /opt/lib is also listed.
Any ideas into where the problem lies? Thanks.
An ldd libxerces-c-3.1.so command yields the following output:
linux-vdso.so.1 => (0x00007fffeafff000)
libnsl.so.1 => /lib/libnsl.so.1 (0x00007fa3d2b83000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00007fa3d2966000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007fa3d265f000)
libm.so.6 => /lib/libm.so.6 (0x00007fa3d23dc000)
libc.so.6 => /lib/libc.so.6 (0x00007fa3d2059000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007fa3d1e42000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa3d337d000)
Try running ldconfig as root to see if it solves the problem.
Run ldd libxerces-c-3.1.so and examine the output to see if all dependencies can be found.
There are many ways to do this, most already mentioned here. BUT you want to avoid accidentally copying your library files into/over those of the system. This is easily done since people have little imagination in making original unique names for their libraries.
So there are a couple of things to think about:
Do you need these files to be a permanent part of your system?
Do you only need to install for testing and frequent updates?
Do you only need them for running that particular command once or twice?
Where are your native libraries located?
To find your various library locations on your system (apart from using find), look here:
cat /etc/ld.so.conf
cat /etc/ld.so.conf.d/*
On Linux there are some standard places:
/lib # for base system (don't use this!)
/usr/lib # for package manger installed apps
/usr/local/lib # for user installed apps
There are many others, but you should most likely stay with /usr/local/lib.
Next you need to tell your system where to find these libraries. The cool system dude (who knows what he is doing) way to do this is using ldconfig, however, you may do stuff you regret, if you make a mistake here. The safest way to use that command is by using the flags -v -n to make the command verbose and to specify what library directory you need to add.
sudo ldconfig -v -n /usr/local/lib/your-uber-libs
Done. But if you only wanna test something, then rather use your LD_LIBRARY_PATH directly from command line, like this:
LD_LIBRARY_PATH=/usr/local/lib/your-uber-libs ./your_uber_command
Alternatively, add the following to your .bashrc script.
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/your-uber-libs
Now you can run your dynamically linked command.
I copied all the library files from /opt/lib into /usr/lib and the program works now. Thanks for the response.
Try installing the library libxerces-c3.1 as. Use the command mentioned below to install the library.
sudo apt-get install libxerces-c3.1
This worked like a charm for me.