72

2 つの異なる 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
4

2 に答える 2

125

これは本当にロングショットのように聞こえるでしょう...しかし、あなたは次のことを試すことができますか?

$ readelf -a fail

そしてGNU_HASH動的タグを探しますか?私の推測では、バイナリはを使用してGNU_HASHおり、あなたld.soはそれを理解するには古すぎます。GNUハッシュセクションのサポートは2006年頃にglibcに追加され、メインラインディストリビューションは2007年または2008年頃にGNUハッシュのみになり始めました。Centrinoglibc2003年のもので、GNUハッシュよりも前のものです。

ld.soがGNUハッシュを理解しない場合は、代わりに空の古いELFハッシュセクションを使用しようとします。特に、次の行でelf/do-lookup.hクラッシュが発生していると思われます。

for (symidx = map->l_buckets[hash % map->l_nbuckets];

リンカはおそらくGNUハッシュを理解しないため、l_nbuckets0になり、クラッシュが発生します。これmapは、約100の構造要素を持つ大きな構造でありl_nbuckets、新しい構造の約90番目のメンバーであることに注意してくださいld.so0x164 = 4*89したがって、古い構造でld.soは、おそらく正確にこのメンバーです)。

これが最終-Wl,--hash-style=sysv的に問題であるかどうかを確認するには、またはを使用してビルドし-Wl,--hash-style=both、クラッシュが解消されるかどうかを確認します。

于 2012-09-25T01:22:21.917 に答える
4

ATOM では動作しますが、古い Celeron では動作しないため、Celeron では実行できないコードを生成するコンパイラの最適化に問題があると考えられます。フラグ -O0 でコンパイルしてみてください。さらに、 -march=i686 を追加して、アーキテクチャを明示的に記述することをお勧めします。また、問題を切り分けるために、C++ ランタイムと Java へのリンクを無効にすることもお勧めします。

このテスト プログラムを一度ビルドして各デバイスで実行しましたか? それとも、デバイスごとに異なる実行可能ファイルをビルドしましたか? 1 つの実行可能ファイルをビルドする場合、2 つのデバイスまたはデバイスとビルド マシンで libc、libstdc++ のバージョンが異なる場合があります。

于 2012-09-24T22:37:27.953 に答える