'int main(){return(0);上的浮点异常(SIGFPE); }"

Chi*_*era 70 c linux gcc elf sigfpe

我正在尝试为两个不同的Linux环境构建一个简单的C程序.在一个设备上程序运行正常,在另一个设备上程序生成浮点异常.该程序什么都不做,但从main返回0,这让我相信可能与启动代码ABI有一些不兼容?

该程序使用gcc编译,具有以下构建规范:

使用内置规格.目标:i386-redhat-linux配置:../ 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版本4.1.2 20080704(Red Hat 4.1.2-52)

程序源如下:

int main()
{
        return(0);
}
Run Code Online (Sandbox Code Playgroud)

在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 ?? ()
Run Code Online (Sandbox Code Playgroud)

以下是我可以考虑收集的详细信息,以帮助了解发生的情况:

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.
Run Code Online (Sandbox Code Playgroud)

我该怎么做才能确定导致此问题的原因?如何尝试静态链接某个版本的libc?

在GDB下发生故障后我执行:

(gdb) x/1i $eip
0x40001cce:     divl   0x164(%ecx)
Run Code Online (Sandbox Code Playgroud)
(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) 
Run Code Online (Sandbox Code Playgroud)

基于我收到的帮助,似乎由于某种原因libc启动代码除以0.

现在的问题是,导致这种明显不良行为的原因是什么?某些东西必须与其他东西不相容?

装配输出:

[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
Run Code Online (Sandbox Code Playgroud)

nne*_*neo 124

这听起来像是一个很长的镜头......但你可以试试以下吗?

$ readelf -a fail
Run Code Online (Sandbox Code Playgroud)

并寻找GNU_HASH动态标签?我的猜测是二进制文件使用GNU_HASH,你的ld.so年龄太大,无法理解.2006年左右,glibc增加了对GNU哈希部分的支持,主流发行版在2007年或2008年左右开始仅使用GNU-hash.您的Centrino glibc是从2003年开始的,早于GNU哈希.

如果ld.so不理解GNU哈希,它将尝试使用旧的ELF哈希部分,这是空的.特别是,我怀疑你的崩溃发生在这一行elf/do-lookup.h:

for (symidx = map->l_buckets[hash % map->l_nbuckets];
Run Code Online (Sandbox Code Playgroud)

由于链接器可能不理解GNU哈希值,因此l_nbuckets会为0,从而导致崩溃.请注意,这map是一个包含大约100个结构元素的大型结构,并且l_nbuckets在较新的结构的第90个成员周围ld.so(0x164 = 4*89因此在较旧的ld.so时候可能恰好是这个成员).

要看到,如果这是决定性的问题,构建具有-Wl,--hash-style=sysv或者-Wl,--hash-style=both,看看是否崩溃消失.

  • 先生,你有很好的通灵调试技巧.Raymond Chen会感到自豪. (31认同)
  • 哇.哇哇.很好的分析.+1无论是否修复了OP的问题 (22认同)
  • 你摇滚!那就是问题所在.使用-Wl进行编译, - hash-style =都会生成可在旧环境和新环境中运行的可执行文件. (11认同)
  • 是的 - 这是一个很好的尝试,它应该是正确的,(即使海报的名字似乎永远不会结束).+1. (2认同)