我正在尝试为两个不同的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 version 4.1.2 20080704(红帽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。
现在的问题是,导致这种明显不良行为的原因是什么?某些东西必须与其他东西不相容?
装配输出:
[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
答案 0 :(得分:123)
这听起来像是一个很长的镜头......但是你可以试试以下吗?
$ readelf -a fail
并寻找GNU_HASH动态标签?我的猜测是二进制文件使用GNU_HASH
,而您的ld.so
太旧了,无法理解。 2006年左右,glibc增加了对GNU哈希部分的支持,主线发行版在2007年或2008年左右开始仅使用GNU-hash。您的Centrino的glibc
来自 2003 ,早于GNU散列。
如果ld.so
不理解GNU哈希,它将尝试使用旧的ELF哈希部分,它是空的。特别是,我怀疑你的崩溃发生在this line in 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
的结构的第90个成员周围,因此在较早的ld.so
中1}}它可能就是这个成员。)
要查看这是最终问题,请使用-Wl,--hash-style=sysv
或-Wl,--hash-style=both
进行构建,并查看崩溃是否消失。
答案 1 :(得分:4)
由于它适用于ATOM但不适用于较旧的Celeron,我认为问题可能在于编译器优化生成Celeron无法执行的代码。尝试使用标志-O0进行编译。另外,我建议添加-march = i686来明确说明架构。另外,为了帮助隔离问题,我还建议禁用链接到C ++运行时和JAVA。
您是否构建了此测试程序并在每台设备上运行它,或者您是否为每个设备构建了不同的可执行文件?如果要构建一个可执行文件,则可能在两个设备上或在设备上与构建计算机上具有不同版本的libc,libstdc ++。