我正在尝试为两个不同的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); }
在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
这听起来像是很远的事…但是您可以尝试以下方法吗?
$ readelf -a fail
并寻找GNU_HASH动态标签?我的猜测是二进制文件使用GNU_HASH,而您ld.so太旧了,无法理解。对GNU哈希部分的支持是在2006年左右添加到glibc的,并且主线发行版在2007年或2008年左右才成为仅GNU哈希的发行版。您的Centrino发行glibc于 2003年 ,它早于GNU哈希。
GNU_HASH
ld.so
glibc
如果ld.so不能理解GNU哈希,它将尝试改用旧的ELF哈希部分,该部分为空。特别是,我怀疑您的崩溃发生在此行中elf/do- lookup.h:
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个成员附近。
l_nbuckets
map
0x164 = 4*89
要查看这是否 最终 是问题,请使用-Wl,--hash-style=sysv或进行构建,-Wl,--hash- style=both并查看崩溃是否消失。
-Wl,--hash-style=sysv
-Wl,--hash- style=both