Exception en virgule flottante (SIGFPE) sur ‘int main () {return (0); } ‘

J’essaie de construire un programme C simple pour deux environnements Linux différents. Sur un appareil, le programme fonctionne correctement, sur l’autre, le programme génère une exception en virgule flottante. Le programme ne fait rien mais retourne 0 de main ce qui m’amène à penser qu’il existe une incompatibilité avec le code de démarrage, peut-être ABI?

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

Utiliser 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 = libère –avec-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 –avec-java-home = / usr / lib / jvm / java-1.4.2-gcj-1.4. 2.0 / jre –with-cpu = générique –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 périphérique Celeron, ce programme génère les éléments suivants 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 ?? () 

Vous trouverez ci-dessous les détails que je peux penser pour vous aider à découvrir 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. Comstackd by GNU CC version 3.2.2 20030222 (Red Hat Linux 3.2.2-5). Comstackd 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. Comstackd by GNU CC version 4.1.2 20080704 (Red Hat 4.1.2-44). Comstackd 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 ce qui cause ce problème? Que diriez-vous d’essayer d’établir un lien 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) 

Sur la base de l’aide que j’ai reçue, il semble que pour une raison quelconque, le code de démarrage de la libc se divise par 0.

La question est maintenant, qu’est-ce qui cause ce comportement manifestement mauvais? Quelque chose doit être incompatible avec autre chose?

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 

Cela va sonner comme un long cliché … mais pouvez-vous essayer ce qui suit?

 $ readelf -a fail 

et recherchez une balise dynamic GNU_HASH? Je pense que le binary utilise GNU_HASH et que votre ld.so est trop vieux pour le comprendre. Le support de la section de hachage GNU a été ajouté à la glibc vers 2006, et les dissortingbutions de la ligne principale ont commencé à être GNU-hash uniquement vers 2007 ou 2008. La glibc votre Censortingno date de 2003 , avant le hachage GNU.

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

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

Comme l’éditeur de liens ne comprend probablement pas les hachages GNU, l_nbuckets serait 0, ce qui entraînerait le crash. Notez que map est une grande structure avec environ 100 éléments de structure, et l_nbuckets est autour du 90ème membre de la structure dans ld.so plus récent ( 0x164 = 4*89 , donc dans ld.so plus ancien, c’est probablement précisément ce membre).

Pour voir si c’est définitivement le problème, construisez avec -Wl,--hash-style=sysv ou -Wl,--hash-style=both et voyez si le plantage disparaît.

Comme cela fonctionne sur l’ATOM mais pas sur l’ancien Celeron, je pense que le problème pourrait être dû à un code de génération d’optimisation du compilateur que le Celeron ne peut pas exécuter. Essayez de comstackr avec le drapeau -O0. En outre, je suggère d’append -march = i686 pour indiquer explicitement l’architecture. En outre, pour vous aider à identifier le problème, je suggère également de désactiver la liaison au runtime C ++ et à JAVA.

Avez-vous construit ce programme de test une fois et exécuté sur chaque périphérique, ou avez-vous créé un exécutable différent pour chaque périphérique? Si vous construisez un exécutable, vous pouvez avoir différentes versions de libc, libstdc ++ sur les deux périphériques ou sur les périphériques par rapport à votre machine de génération.