Search code examples
c++linuxshared-librariesglibcportable-applications

Linux c++ portable binary issue


I try to package my binary and all its shared libraries into an archive. I want user only extracts the archive to make the binary work. The executable is launched via a shell script where I set LD_LIBRARY_PATH to shared library path contained in the archive.

On a first time I wanted to make it work on a RHEL 6.7 distribution so I have compiled my binary with this distribution, and when I tested it it works well. The problem is that I have now to make it work on a RHEL 7.2 (and keep RHEL 6.7 working) and when I launched the binary it don't work... it crashes inside a glibc function (isspace with no garbage in argument). I see that behind these two RHEL releases glibc version has changed. In the shared libraries that are contained in the archive there was not glibc shared library, so I tried to add it and now I got the following error :

./XXX: ���:ELF: zR: Error 892688562

It seems to be an ELF error (verbose is present each time I launch it), I check all my shared libraries and they are x64 libraries (like the binary)... I don't want to compile on RHEL 7.2 because I have a lot of dependancies and I don't want to compile all of it, and also it is easier for me to maintain one version.

I tried many things like Statifier and Ermine, that both work but the first has a bug and have to had Address Space Layout Randomization disabled and the second one is a shareware and I prefer a free solution. I also tried CDE that also work, but it generates such a big package, it is a bit a mess...

Why with this kind of solution it works and with my homemade solution it don't work ? What am I not doing well ?

Thank you for reading, I hope someone has a solution for me because I search for a long time...

EDIT :

I found solution, before my shell script was like :

# Binary location
LOCATION=$(dirname $0)
# Shared libraries directory
BINDIR=${LOCATION}/bin/
# Define LD_LIBRARY_PATH
export LD_LIBRARY_PATH=${BINDIR}:${LD_LIBRARY_PATH}
# Launch binary
${LOCATION}/XXX $*

I changed by :

# Binary location
LOCATION=$(dirname $0)
# Shared libraries directory
BINDIR=${LOCATION}/bin/
# Changed shared library default location and launch binary
${BINDIR}/ld-linux-x86-64.so.2 --library-path ${BINDIR} ${LOCATION}/XXX $*

I don't really understand why but it works, someone can explain me please ? (ld-linux-x86-64.so.2 came from RHEL 6.7 distribution)


Solution

  • I don't really understand why but it works, someone can explain me please ?

    It's explained here. Your solution is "explicit loader invocation" mentioned here.

    BTW, this is wrong: ${LOCATION}/XXX $* You should do this instead:

    ${LOCATION}/XXX "$@"
    

    (Your variant will not handle arguments with embedded spaces correctly.)