Linux – Join the executable and all its libraries

executablelinux

Lets say I have a /bin/cat executable that uses the following shared libraries:

linux-vdso.so.1
libc.so.6
/lib64/ld-linux-x86-64.so.2

Is it possible to somehow "join" that stuff together (executable archive or something like that)?

I don't have the code of the program I want to do that to, so I can't just compile it with -static flag.

Best Answer

You can copy all of its libraries from their system locations into a subdirectory of where your executable is and use patchelf, to make the executable look for its libdependencies there instead of the system lib directories.

E.g.:

relativize_libs:

#!/bin/bash -e
[ -n "$1" ] || set -- a.out
mkdir -p ./lib/ #<copy the libraries here
#use ldd to resolve the libs and use `patchelf --print-needed to filter out
# "magic" libs kernel-interfacing libs such as linux-vdso.so, ld-linux-x86-65.so or libpthread
# which you probably should not relativize anyway
join \
    <(ldd "$1" |awk '{if(substr($3,0,1)=="/") print $1,$3}' |sort) \
    <(patchelf --print-needed "$1" |sort) |cut -d\  -f2 |

#copy the lib selection to ./lib
xargs -d '\n' -I{} cp --copy-contents {} ./lib 
#make the relative lib paths override the system lib path
patchelf --set-rpath "\$ORIGIN/lib" "$1"

(I believe that unlike LD_LIBRARY_PATH hacking, this should work with setuid executables too).

After that, all you've got to do is move that ./lib directory along with the executable.

Related Question