There are certain specific changes in ELF binary format causing this issue.
Lets have a quick look!
The ELF binaries have hash section for runtime symbol lookup to be used by dynamic linker. On RHEL4 and older system with older toolchain set, gcc emits code which has the hash section (SHT_HASH) in standard 'sysv' format for symbol resolution.
However on RHEL5, FC6 or newer systems, this section is absent and the same purpose is achieved by a new section(SHT_GNU_HASH) in format called 'gnu'. This is said to have improved the dynamic linking by 50%.
Which section would be present in the binary is dictated by a new linker switch '--hash-style' with possible values gnu, sysv or both. On systems with new tool-chain set, gcc (esp. v 4.1 onwards) passes '--hash-style=gnu' to the linker, by default and hence the code generated has just SHT_GNU_HASH section. And when this binary is run on older system, it would fail to run, as the dynamic linker on those machine won't find SHT_HASH section, it is looking for.
While on RHEL5 or newer machines, dynamic linker can handle both types of hash format, 'sysv' with less performance than is capable to deliver with 'gnu'.
'readelf' utility can lets us know about this ....
[avinesh@dodge ~]$ readelf -S hello [ on RHEL5]
There are 28 section headers, starting at offset 0x754:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 08048114 000114 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048128 000128 000020 00 A 0 0 4
[ 3] .gnu.hash GNU_HASH 08048148 000148 000020 04 A 4 0 4
[ 4] .dynsym DYNSYM 08048168 000168 000050 10 A 5 1 4
[ 5] .dynstr STRTAB 080481b8 0001b8 00004a 00 A 0 0 1
.......................
.........................
[root@kilbuck ~]# readelf -S hello [ on RHEL4]
There are 29 section headers, starting at offset 0xa80:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000400200 00000200
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 000000000040021c 0000021c
0000000000000020 0000000000000000 A 0 0 4
[ 3] .hash HASH 0000000000400240 00000240
0000000000000028 0000000000000004 A 4 0 8
[ 4] .dynsym DYNSYM 0000000000400268 00000268
0000000000000078 0000000000000018 A 5 1 8
[ 5] .dynstr STRTAB 00000000004002e0 000002e0
0000000000000053 0000000000000000 A 0 0 1
So, if you want to make binaries which is compatible to older systems as well, then you need to pass the linker option '--hash-style=(sysv|both)' via gcc switch "-Wl" The advised way over here is to use 'sysv' rather than 'both' due to some issues with some older ld.
[avinesh@dodge ~]$ gcc -o hello -Wl,--hash-style=sysv hello.c