Making Proprietary Elf Binaries Portable on Linux

making proprietary ELF binaries portable on Linux

Searching all linked libraries and their dependencies and include them in a subdirectory of the binary and changing the Library-Path to that directory.

This would work for most shared libraries, but will not work for libc.so.6 (which is the one most likely to give problems if your target system doesn't have new enough version).

The reason: glibc consists of over 200 separate shared libraries, which have un-versioned binary interfaces between them, and do not have a stable ABI between them. Because of this, all parts of glibc must come from the same build. One of these parts is libc.so.6. Another is ld-linux.so. An absolute path to the latter is hard coded into every dynamic executable. The end result: if you supply your own copy of libc.so.6, and if that copy doesn't match /lib/ld-linux*.so.2 present on the system, then you'll see very strange crashes which you would have very hard time to explain or debug.

Relinking the libraries statically into the binary file to one big executable.

That can't work on any UNIX system other than AIX: they all consider a.out and foo.so to be the final link product, which can't be linked any further.

There exists statifier, which does create a (huge) static executable out of a dynamic one. I have no experience using it.

libelf corrupts ARM elf binaries

Found it myself.

After opening the elf-file a call to:

elf_flagelf (e, ELF_C_SET, ELF_F_LAYOUT);

will tell libelf to not touch the segment and section layout. This prevents libelf from rewriting the executable and we'll get an unmodified file as exepcted.

After any modifications to the section data a call to elf_flagdata is required like this:

 Elf_Data *data = elf_getdata ( ...

// do modification to data here..

elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY);

is required to let libelf know that the data has been changed and that the elf checksum has to be recalculated.

Building linux binaries for multiple platforms

You may try to focus on a few major platforms rather than individual distributions. What I mean by that is to build on what I call the "foundational distros" (Debian and RedHat) and hope for the best on the others.

Most likely, Debian binaries (that are statically linked) will run just fine on Ubuntu and Mint and other Debian derived distributions. RedHat binaries will probably run on Centos, Scientific Linux and SuSE Linux. If you care about less popular distros (Say you have a lot of customers running some uncommon Linux), and neither your Debian or RedHat executable works on them or can be made to work somehow, then setup a VM of that distro and build one executable specifically for that flavor.

I've taken this approach in the past and it has worked well.

Is assembler portable between Linux distros?

At a very high level, the ABI consists of { instruction set, system calls, binary format, libraries }.

Distribution as .s may free you from the binary format. This is still rather pointless, because you are fixed to a particular ISA and still need to use libraries and/or make system calls. Libraries vary from distribution to distribution (although this isn't really that bad, especially if you just use libc) and syscalls vary from OS to OS.



Related Topics



Leave a reply



Submit