views:

321

answers:

3

I compiled a PHP extension on Fedora Core 12, but when I send it to someone using CentOS they get the error: "ELF file OS ABI invalid"

I'm not sure what causes this running file provides the following info: ELF 64-bit LSB shared object, AMD x86-64, version 1 (GNU/Linux), not stripped

An extension that loads fine provides the following from file: ELF 64-bit LSB shared object, AMD x86-64, version 1 (SYSV), not stripped

So it seems I need to generate a SYSV type file for some distributions, instead of a GNU/LINUX file, no idea how though. Any pointers?

Also should I be statically linking?

A: 

It's most likely that your friend is not running a 64-bit system. ELF is the standard format for Linux executables, but 32-bit systems can't run 64-bit executables.

Get the output for uname -a from your friend. If the output doesn't contain "x86_64", then he's on a 32-bit version of CentOS.

If so, you either need to set up a cross-compiling environment, or a virtual machine for compiling 32-bit binaries on, or just provide your friend with the sources so that he can compile it himself.

Adrian
He actually is running on 64bit, I had previously sent him a 32bit file and he got an error from that. So I had to install a 64bit OS to re-compile. The only difference I notice between the PHP extension that I sent, and the one he compiled is that his says 'SYSV' vs mine saying 'GNU/Linux'.
Andrew M
Did you run the `file` command on both binaries on the same system?
jschmier
Yeah, both of them were run by him on CentOS
Andrew M
+1  A: 

Compiled object files don't usually transfer well between different linux distributions. Different Distributions often have different policies regarding libraries, where they're stored, how they're loaded.

There's so many differences between them (yes, even in Fedora & RedHat/CentOS). They're likely to supply their own patches to componenets at every level (kernel, PHP, library location). If they're using the distribution PHP package, the distribution might have patched it better intergrate into their system.

The major issue you'll likely run into is that the distribution have used a different libraries/compiler settings. Check to see what verision gcc is on his computer and compare it to what's on yours. (Fedora 12 has quite a few newer libraries than CentOS). That's where your issue might be.

Another possible issue is that your binary is fine, but its incompatible with all the libraries it uses. I'm not sure if there's a good way to get around this one without compiling on the target-distribution (or a varient). You can see what libraries each shared object/executable uses by using the lld <file> command.

Also, was there any output before the error ELF file OS ABI invalid? Most places I see it being referenced there's more information than that.

AlReece45
I know that IonCube (a php extension) has binaries for linux that work across all distributions, I checked one of theirs with file and it outputted "ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, stripped".I can't find any options to change the OS header to SYSV when I compile instead of GNU/LINUX though, that seems to be the problem. ldd displays 'not a dynamic executable' on his CentOS.
Andrew M
You may want to check out the Linux Standard Base (LSB). I personally don't have experience with it, but it might provide the binary compatibility you need. Ioncube developing a PHP library that works accross distributions is no small task, maybe its a little simpler doing just a library rather than a full application like Firefox (where on some distributions there have been conflicts with Firefox's downloadable linux client)
AlReece45
+2  A: 

The statement: "ELF file OS ABI invalid", means that the Application Binary Interface is non compatible between binaries used (i.e. one is trying to mix host and target binaries, which may not work as expected). The e_ident[EI_OSABI] byte of the ELF header contains the operating system/ABI identification. Your Fedora system is setting this to ELFOSABI_LINUX (3) while your friend's CentOS system is setting it to ELFOSABI_SYSV (ELFOSABI_NONE or 0).

You may be able to compile the FreeBSD brandelf utility (brandelf.c) and use it to set the OSABI to ELFOSABI_SYSV (brandelf -f 0 <file> or brandelf -t SVR4 <file>.

I am not aware of any gcc flags for specifying this value at compile/link time. I believe that the version of binutils used by gcc on your Fedora system is responsible for setting the OSABI to Linux. It is my understanding that the linker only specifies the ABI if a STT_GNU_IFUNC symbol ends up in the output file (see ifunc.txt at http://groups.google.com/group/generic-abi for details on STT_GNU_IFUNC).


The readelf(1) command can be used to retrieve and display the ABI information stored in the ELF header (readelf -h <file>).


This similar question may also be of interest.

jschmier
Wow thanks a lot for all the info, I was able to compile brandelf and change the OS header. I've sent off the modified binary and hopefully it will run. I'll try to find a way to get rid of the STT_GNU_IFUNC symbol, not sure how I'll do that; doesn't seem like a simple thing.
Andrew M
You might try searching your source code for `attribute ((ifunc))`. I was able to change the OSABI from `ELFOSABI_LINUX` to `ELFOSABI_SYSV` on the *static* Linux/ia32 binary of prog.C (C++ program with ifunc attribute) downloaded from the following site and still execute it without any noticable side effects. This binary is statically linked, which *may* explain the lack of side effects. - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40528
jschmier