4
nm -D /lib32/libc.so.6 | grep '\<fopen\>'
0005d0c0 T fopen
00109750 T fopen

readelf -s  /lib32/libc.so.6 | egrep '0005d0c0|00109750'
181: 0005d0c0    50 FUNC    GLOBAL DEFAULT   12 fopen@@GLIBC_2.1
182: 00109750   136 FUNC    GLOBAL DEFAULT   12 fopen@GLIBC_2.0
679: 0005d0c0    50 FUNC    GLOBAL DEFAULT   12 _IO_fopen@@GLIBC_2.1
680: 00109750   136 FUNC    GLOBAL DEFAULT   12 _IO_fopen@GLIBC_2.0

ここに私の質問があります:

  1. /lib32/libc.so.6に2つのfopenシンボルが含まれているのはなぜですか?同じターゲットファイル内の同一のシンボルは禁止されるべきですよね?

  2. readelf -sがfopenの代わりにfopen@@GLIBC_2.1とfopen@GLIBC_2.0をダンプするのはなぜですか?

ありがとう

4

2 に答える 2

9

ここで何が起こっているのかを理解するには、まず、バイナリ互換性が従来どのように処理されてきたかを理解する必要があります。

メカニズムは「外部バージョン管理」でした。あなたはから始めましたlibfoo.so.1、そしてあなたが既存の関数のABIを変更する必要があるとき、あなたはを導入することを余儀なくされましlibfoo.so.2た。

以前にリンクされていたアプリケーションは、libfoo.so.2引き続きlibfoo.so.1古いABIで使用され、新しいアプリケーションlibfoo.so.2は新しいABIで使用されました。

これはすべてここで詳細に説明されています。

しかし、その後glibcは拡張機能を導入しました。この拡張機能では、まったく新しいライブラリ(以前のバージョンとコードの99%を共有する)を導入する代わりに、既存のライブラリに新しいシンボルを導入します。

その拡張機能は、古いバイナリが機能し、ABIが進化することを可能にしながら、libc.so.6バージョン6に何年も留まることを可能にしたものです。

の特定のケースでfopenは、互換性のない変更struct FILEがglibcのバージョン2.1で行われました。glibc-2.0システムでリンクされていたバイナリは、引き続き古いものstruct FILE(当時利用可能だったもの)を使用し、呼び出しを続けます_IO_old_fopen(これfopen@GLIBC_2.0はエイリアスです)。glibc-2.1以降に対してリンクされたバイナリは、new struct FILE、およびcall _IO_new_fopenfopen@GLIBC_2.1エイリアス)を使用します。

これは、現在のデフォルトのシンボルバージョン@@を示す単なる表記です。

于 2012-02-06T07:34:18.690 に答える
3

実際には、同じシンボルの複数の定義は問題なく、さまざまな方法で発生する可能性があります。それらの1つ(ここではそうではありません)は弱いシンボルです。

ここで何が起こるかというと、glibcダイナミックリンカーはシンボルのバージョン管理をサポートし、glibcはそれを使用します。fopenglibc 2.1からのバージョンと、インターフェイスが異なるglibc2.0からの下位互換性のあるバージョンをエクスポートします。

動的リンク時に、アプリケーションは特定のバージョンまたはデフォルトのバージョンを選択できます。

于 2012-02-06T06:53:24.180 に答える