70 votes

Exception de virgule flottante ( SIGFPE ) sur 'int main(){ return(0) ; }'.

J'essaie de construire un programme C simple pour deux environnements Linux différents. Sur l'un d'entre eux, le programme s'exécute sans problème, mais sur l'autre, il génère une exception en virgule flottante. Le programme ne fait rien d'autre que de retourner 0 à partir de main, ce qui me pousse à croire qu'il y a une incompatibilité avec le code de démarrage, peut-être ABI ?

Le programme est compilé avec gcc avec les spécifications de construction suivantes :

Utilisation des spécifications intégrées. Cible : i386-redhat-linux Configuré avec : ../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 Modèle de thread : posix gcc version 4.1.2 20080704 (Red Hat 4.1.2-52)

La source du programme est la suivante :

int main()
{
        return(0);
}

Sur le dispositif Celeron, ce programme génère ce qui suit sous 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 ?? ()

Voici les détails que je pense rassembler pour aider à trouver ce qui se passe :

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.

Que puis-je faire pour déterminer la cause de ce problème ? Pourquoi ne pas essayer d'établir une liaison statique avec une certaine version de libc ?

Après l'échec sous GDB j'exécute :

(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) 

D'après l'aide que j'ai reçue, il semble que pour une raison quelconque, le code de démarrage de la libc divise par 0.

La question est maintenant de savoir ce qui provoque ce comportement manifestement mauvais. Quelque chose doit être incompatible avec quelque chose d'autre ?

Sortie d'assemblage :

[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

124voto

nneonneo Points 56821

Cela va vous paraître un peu tiré par les cheveux... mais pouvez-vous essayer ce qui suit ?

$ readelf -a fail

et chercher une balise dynamique GNU_HASH ? Je pense que le binaire utilise GNU_HASH et votre ld.so est trop vieux pour le comprendre. La prise en charge de la section de hachage GNU a été ajoutée à la glibc vers 2006, et les distributions principales ont commencé à être exclusivement GNU-hash vers 2007 ou 2008. Votre Centrino glibc vient de 2003 qui a précédé le hachage GNU.

Si le ld.so ne comprend pas le hachage GNU, il essaiera d'utiliser l'ancienne section de hachage ELF à la place, qui est vide. En particulier, je soupçonne que votre crash se produit à l'endroit suivant cette ligne dans elf/do-lookup.h :

for (symidx = map->l_buckets[hash % map->l_nbuckets];

Puisque l'éditeur de liens ne comprend vraisemblablement pas les hachages GNU, l_nbuckets serait égal à 0, ce qui entraînerait l'accident. Notez que map est une grande structure avec environ 100 éléments de structure, et l_nbuckets se situe autour du 90ème membre de la structure dans les plus récents ld.so ( 0x164 = 4*89 Ainsi, dans les pays plus anciens ld.so il s'agit probablement précisément de ce membre).

Pour voir si c'est de manière concluante le problème, construire avec -Wl,--hash-style=sysv ou -Wl,--hash-style=both et voir si le crash disparaît.

4voto

syplex Points 674

Puisque cela fonctionne sur l'ATOM mais pas sur l'ancien Celeron, je pense que le problème pourrait provenir d'une optimisation du compilateur générant un code que le Celeron ne peut pas exécuter. Essayez de compiler avec l'option -O0. De plus, je suggère d'ajouter -march=i686 pour indiquer explicitement l'architecture. De plus, pour aider à isoler le problème, je suggérerais également de désactiver la liaison avec le runtime C++ et JAVA.

Avez-vous construit ce programme de test une fois et l'avez-vous exécuté sur chaque appareil, ou avez-vous construit un exécutable différent pour chaque appareil ? Si vous construisez un seul exécutable, il se peut que vous ayez des versions différentes de libc, libstdc++ sur les deux appareils ou sur les appareils par rapport à votre machine de construction.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X