int main(){return(0);}上的浮点exception(SIGFPE) }”
我正在尝试为两个不同的Linux环境构build一个简单的C程序。 在一个设备上,程序运行良好,在另一个设备上程序产生一个浮点exception。 该程序什么都不做,但从主返回0,这使我相信有一些不符合启动代码或ABI?
该程序是与海湾合作委员会与以下生成规范编译:
使用内置的规格。 目标:i386-redhat-linuxconfiguration:../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线程模型:posix gcc version 4.1.2 20080704(Red Hat 4.1.2-52)
程序源代码如下:
int main() { return(0); }
在Celeron设备上,该程序在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 ?? ()
以下是我可以考虑收集的细节,以帮助了解正在发生的事情:
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.
我能做些什么来确定是什么导致了这个问题? 如何试图静态链接到一个特定版本的libc?
在GDB下发生故障后,我执行:
(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)
基于我收到的帮助,似乎出于某种原因,libc启动代码除以0。
现在的问题是,是什么造成了这种明显不好的行为? 有什么东西必须与其他东西不相容?
assembly输出:
[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
这听起来像是一个很长的镜头,但你可以尝试以下吗?
$ readelf -a fail
并寻找一个GNU_HASHdynamic标签? 我的猜测是这个二进制文件使用GNU_HASH
,而你的ld.so
太老了,无法理解它。 在2006年左右,GNU哈希部分被添加到了glibc中,主stream发行版在2007年或2008年左右才开始使用GNU哈希。你的迅驰glibc
是从2003年开始的 ,它早于GNU哈希。
如果ld.so
不理解GNU哈希,它会尝试使用旧的ELF哈希部分,而不是空的。 特别是,我怀疑你的崩溃发生在elf/do-lookup.h
这一行 :
for (symidx = map->l_buckets[hash % map->l_nbuckets];
由于链接器大概不理解GNU哈希, l_nbuckets
将为0,导致崩溃。 请注意, map
是一个大型的结构,大约有100个结构元素,而l_nbuckets
在更新的ld.so
( 0x164 = 4*89
,因此在ld.so
中可能正好是这个成员)的结构的第90个成员。
要确定这是否是确定的问题,请使用-Wl,--hash-style=sysv
或-Wl,--hash-style=both
构build,看看崩溃是否消失。
由于它在ATOM上工作,而不是在旧的Celeron上工作,所以我认为这个问题可能是由于Celeron无法执行的编译器优化生成代码。 尝试使用-O0标志进行编译。 另外,我会build议添加-march = i686来显式声明体系结构。 此外,为了帮助隔离问题,我还build议禁用链接到C ++运行时和JAVA。
您是否构build过一次这个testing程序并在每个设备上运行它,或者是为每个设备构build了不同的可执行文件? 如果您正在构build一个可执行文件,则可能在两个设备或设备上与您的构build计算机上有不同的libc,libstdc ++版本。