GCCコンパイル - __stack_chk_fail@GLIBC_2.4シンボルはどこから来たのですか?

GCCコンパイル - __stack_chk_fail@GLIBC_2.4シンボルはどこから来たのですか?

GCC 4.7.2を使用しています。開発ツールセットCentOS 5のパッケージ(CentOS 5は以前のLinuxバージョンとの互換性が必要で、GCC 4.7は4.4よりも最適化されているため)。

私のバイナリがRHEL4で実行されるのを防ぐためのシンボルがあります__stack_chk_fail@GLIBC_2.4。一部のC ++プログラムにのみ含まれており、この-fno-stack-protectorフラグは役に立ちません。

以下は、問題を再現するための最小プログラムです(ただし、同じstdio.h方法を使用します)。

#include <iostream>
int main(int argc, char *argv[]) {
    for(int i=0; i < argc; i++)
        std::cout << " " << argv[i];
    return 0;
}

最適化(-O/)で-O2コンパイルするときに引用されます__stack_chk_fail

$ g++ -fno-stack-protector -O2 foo.cc
$ readelf -s a.out | grep chk
    15: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail@GLIBC_2.4 (5)
   105: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __stack_chk_fail@@GLIBC_2

このシンボルがここに表示される理由とそれを削除する方法をご存知ですか?

場合に備えて、全体のreadelf出力は次のとおりgcc -vです。ここ

編集:この問題はRed Hat Developer Toolset 1.1にのみ当てはまります。デフォルトのCentOSコンパイラ__stack_chk_failは参照されません。

答え1

この記号はから由来していますlibstdc++_nonshared.a

ディストリビューションのGCCとは異なり、devtoolsetのGCCにはlibstdc ++の非共有部分があります。 GCC 4.7 の libstdc++.so は、GCC 4.1 の libstdc++ に静的に関連付けられた追加関数を使用するリンカスクリプトです。

$ cat /opt/centos/devtoolset-1.1/root/usr/lib/gcc/i386-CentOS-linux/4.7.2/libstdc++.so
/* GNU ld script
   Use the shared library, but some functions are only in
   the static library, so try that secondarily.  */
OUTPUT_FORMAT(elf32-i386)
INPUT ( /usr/lib/libstdc++.so.6 -lstdc++_nonshared )

スタックセーバーを無効にして再コンパイルした後、libstdc++_nonshared.a最終プログラムはRHEL4で動作します。

答え2

GLibCに付属しています。古いGLibC用にビルドします。

GCC 4.7に最適化されたアセンブリコードを生成し、それを以前のシステムで組み立ててリンクするように指示できます。

関連情報