2つの異なるLinux環境用の単純なCプログラムを構築しようとしています。一方のデバイスではプログラムは正常に実行され、もう一方のデバイスではプログラムは浮動小数点例外を生成します。プログラムはメインから0を返すだけで、スタートアップコードとの互換性がない可能性があると私は信じていますか?
プログラムは、次のビルド仕様の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スレッドモデル:posixgccバージョン4.1.220080704(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ハッシュよりも前のものです。
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
の構造体の約90番目のメンバーです(0x164 = 4*89
なので、古いld.so
ではおそらく正確にこのメンバーです)。
これが決定的に問題であるかどうかを確認するには、-Wl,--hash-style=sysv
または-Wl,--hash-style=both
でビルドし、クラッシュが解消されるかどうかを確認します。
ATOMで動作しますが、古いCeleronでは動作しないため、Celeronが実行できないコードを生成するコンパイラ最適化に問題がある可能性があります。フラグ-O0を使用してコンパイルしてみてください。 、アーキテクチャを明示的に示すために-march = i686を追加することをお勧めします。また、問題を切り分けるために、C++ランタイムとJavaへのリンクを無効にすることもお勧めします。
このテストプログラムを一度ビルドして各デバイスで実行しましたか、それともデバイスごとに異なる実行可能ファイルをビルドしましたか? 1つの実行可能ファイルをビルドしている場合、2つのデバイスまたはデバイスとビルドマシンで異なるバージョンのlibc、libstdc ++が存在する可能性があります。