I am trying to build a simple C program for two different Linux environments. On one device the program runs fine, on the other device the program generates a floating point exception. The program does nothing but return 0 from main which leads me to believe there is some incompatibility with the start-up code perhaps ABI?
The program is compiled with gcc with the following build specs:
Using built-in specs. Target: i386-redhat-linux Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --disable-plugin --with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre --with-cpu=generic --host=i386-redhat-linux Thread model: posix gcc version 4.1.2 20080704 (Red Hat 4.1.2-52)
The program source is the following:
int main() { return(0); }
On the Celeron device this program generates the following under GDB:
[root@n00200C30AA2F jrn]# /jrn/gdb fail GNU gdb Red Hat Linux (5.3post-0.20021129.18rh) (gdb) run Starting program: /jrn/fail Program received signal SIGFPE, Arithmetic exception. 0x40001cce in ?? () (gdb) bt #0 0x40001cce in ?? () #1 0x4000c6b0 in ?? () #2 0x40000cb5 in ?? ()
Below are the details that I can think to gather to help find out what is happening:
CELERON: ( fails on this device ) 2.6.8 #21 Mon Oct 1 11:41:47 PDT 2007 i686 i686 i386 GNU/Linux ============ [root@n00200C30AA2F proc]# cat cpuinfo processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 9 model name : Intel(R) Celeron(R) M processor 600MHz stepping : 5 cpu MHz : 599.925 cache size : 512 KB fdiv_bug : no hlt_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 2 wp : yes flags : fpu vme de pse tsc msr mce cx8 sep mtrr pge mca cmov pat clflush dts acpi mmx fxsr sse sse2 tm pbe bogomips : 1179.64 GNU C Library stable release version 2.3.2, by Roland McGrath et al. Compiled by GNU CC version 3.2.2 20030222 (Red Hat Linux 3.2.2-5). Compiled on a Linux 2.4.20 system on 2003-03-13. Available extensions: GNU libio by Per Bothner crypt add-on version 2.1 by Michael Glad and others linuxthreads-0.10 by Xavier Leroy BIND-8.2.3-T5B libthread_db work sponsored by Alpha Processor Inc NIS(YP)/NIS+ NSS modules 0.19 by Thorsten Kukuk ATOM: ( works fine on this device ) 2.6.35 #25 SMP Mon Mar 12 09:02:45 PDT 2012 i686 i686 i386 GNU/Linux ========== [root@n00E04B36ECE5 ~]# cat /proc/cpuinfo processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 28 model name : Genuine Intel(R) CPU N270 @ 1.60GHz stepping : 2 cpu MHz : 1599.874 cache size : 512 KB fdiv_bug : no hlt_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 10 wp : yes flags : fpu vme de tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx constant_tsc up arch_perfmon pebs bts aperfmperf pni dtes64 monitor ds_cpl est tm2 ssse3 xtpr pdcm movbe lahf_lm bogomips : 3199.74 clflush size : 64 cache_alignment : 64 address sizes : 32 bits physical, 32 bits virtual power management: GNU C Library stable release version 2.5, by Roland McGrath et al. Compiled by GNU CC version 4.1.2 20080704 (Red Hat 4.1.2-44). Compiled on a Linux 2.6.9 system on 2009-09-02. Available extensions: The C stubs add-on version 2.1.2. crypt add-on version 2.1 by Michael Glad and others GNU Libidn by Simon Josefsson GNU libio by Per Bothner NIS(YP)/NIS+ NSS modules 0.19 by Thorsten Kukuk Native POSIX Threads Library by Ulrich Drepper et al BIND-8.2.3-T5B RT using linux kernel aio Thread-local storage support included.
What can I do to determine what is causing this problem? How about trying to statically link against a certain version of libc?
After failure occurs under GDB I execute:
(gdb) x/1i $eip 0x40001cce: divl 0x164(%ecx)
(gdb) info reg eax 0x6c994f 7117135 ecx 0x40012858 1073817688 edx 0x0 0 ebx 0x40012680 1073817216 esp 0xbffff740 0xbffff740 ebp 0xbffff898 0xbffff898 esi 0x8049580 134518144 edi 0x400125cc 1073817036 eip 0x40001cce 0x40001cce eflags 0x10246 66118 cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x0 0 (gdb) x/1wx 0x164+$ecx 0x400129bc: 0x00000000 (gdb)
Based on the help I've received it appears that for some reason the libc startup code is dividing by 0.
The question now is, what is causing this obviously bad behavior? Something must be incompatible with something else?
Assembly output:
[jrn@localhost ~]$ more fail.s .file "fail.c" .text .globl main .type main, @function main: leal 4(%esp), %ecx andl $-16, %esp pushl -4(%ecx) pushl %ebp movl %esp, %ebp pushl %ecx movl $0, %eax popl %ecx popl %ebp leal -4(%ecx), %esp ret .size main, .-main .ident "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-52)" .section .note.GNU-stack,"",@progbits
When a floating-point exception raises the SIGFPE signal, the process terminates and produces a core file if no signal-handler subroutine is present in the process. Otherwise, the process calls the signal-handler subroutine. Floating-point exception subroutines.
A floating point exception is an error that occurs when you try to do something impossible with a floating point number, such as divide by zero.
If a floating-point exception interrupt occurs and you do not have an exception handling routine, the run-time system will respond to the interrupt according to the behavior selected by the compiler option /fpe. Remember, interrupts only occur if an exception is enabled (set to 0).
Floating point exception occurs because of several reasons such as invalid operation, division by zero, overflow, underflow, or inexact.
This is going to sound like a really long shot...but can you try the following?
$ readelf -a fail
and look for a GNU_HASH dynamic tag? My guess is that the binary uses GNU_HASH
, and your ld.so
is too old to understand it. Support for the GNU hash section was added to glibc around 2006, and mainline distros began to be GNU-hash-only around 2007 or 2008. Your Centrino's glibc
is from 2003, which predates GNU hashing.
If the ld.so
doesn't understand GNU hash, it will try to use the old ELF hash section instead, which is empty. In particular, I suspect your crash is occurring at this line in elf/do-lookup.h
:
for (symidx = map->l_buckets[hash % map->l_nbuckets];
Since the linker presumably doesn't understand GNU hashes, l_nbuckets
would be 0, resulting in the crash. Note that map
is a large structure with around 100 structure elements, and l_nbuckets
is around the 90th member of the structure in newer ld.so
(0x164 = 4*89
, so in older ld.so
it is probably precisely this member).
To see if this is conclusively the problem, build with -Wl,--hash-style=sysv
or -Wl,--hash-style=both
and see if the crash goes away.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With