1

共有ライブラリ (この例ではlibcryto & libsslですが、実際のライブラリは関係ありません)に対してリンクされているプログラム (myprog と呼びましょう) をコンパイルしてリンクしようとしています。Centos 5.5でビルドしていますが、同じバイナリを他のRHELのようなディストリビューション (CloudLinux など) でも実行したいと考えています。両方とも、同じライブラリの同じバージョンを持っていますSO_NAME(つまり、DT_NEEDEDバージョンが対応しています)。

私の問題はこれです。Centos でコンパイルすると、次のように表示されます。

centos$ objdump -T myprog | fgrep SSL_new
0000000000000000      DF *UND*  0000000000000000  libssl.so.10 SSL_new

次の理由により、これは正常に機能します。

centos$ objdump -T /usr/lib64/libssl.so.10 | fgrep SSL_new
00000000000447d0 g    DF .text  0000000000000390  libssl.so.10 SSL_new

ただし、CloudLinux では:

cloudlinux$ objdump -T /usr/lib64/libssl.so.10 | fgrep SSL_new
00000033a623a120 g    DF .text  0000000000000390  Base        SSL_new

SSL シンボルのバージョンが からlibssl.so.10に変更されていることに注意してくださいBase

これは、バイナリを実行すると次のようになることを意味します。

cloudlinux$ ./myprog
./myprog: /usr/lib64/libcrypto.so.10: no version information available (required by ./myprog)
./myprog: /usr/lib64/libssl.so.10: no version information available (required by ./myprog)

これは「単なる警告」であることは理解していますが、これを取り除きたいと考えています。

私が望むのは、バイナリが警告なしで cloudlinux と centos の両方で実行されることです。私が知る限り、openssl ライブラリの ABI は、少なくとも私が使用する部分では同一です。myprog現在、cloudlinux または centos ライブラリで実行することを意図しているため、共有ライブラリを変更できません。インストール時に(何らかの方法で)シンボルを修正するソリューションを受け入れobjcopyます。

SSL_new@libssl.so.101 つのアプローチは、 のエイリアスである弱いシンボルを導入するようなものですSSL_new@Base。明らかに、それは ssl ライブラリ内のすべての単一シンボルに適用されます (したがって、ラッパーは適切ではありません)。しかし、記号を含む と の値を取得することは-Wl,--defsym=x=yできません。xy@

機能する可能性のある別のアプローチは、単純にバイナリからシンボルのバージョン管理情報を削除することです (つまり、libssl.so.10各 ssl シンボルからバージョンを削除し、名前内のバージョン管理に依存しますDT_NEEDED)。これは単純な要求のように思えますが、その方法もわかりません。何かobjcopy呪文はありますか?

最悪の場合、Centos 上に CloudLinux で動作する (別の) バージョンを構築しても問題ありません。私はこれをやってみました:

#define OSLB(SYMNAME) __asm__(".symver " #SYMNAME "," #SYMNAME "@Base");
OSLB (SSL_new);

ただし、未定義のシンボルであると不平を言うリンクでは失敗します(CentosにはそのシンボルがないためSSL_new@Base、Centosではそうです)。.so

これを回避する方法はありますか?

4

2 に答える 2

6

機能する可能性のある別のアプローチは、バイナリからシンボルのバージョン管理情報を削除することです (つまり、各 ssl シンボルから libssl.so.10 バージョンを削除し、DT_NEEDED 名内のバージョン管理に依存します)。これは単純な要求のように思えますが、その方法もわかりません。objcopy の呪文はありますか?

リンク後のバージョン情報を削除するのは現実的ではありません。これらの文字列はハッシュ テーブルに入力され、これらのハッシュ テーブルを再構築するのは複雑すぎますobjcopy

あなたがしたいのは、必要なすべてのシンボルを定義するが、バージョン情報なしで、 に設定してスタブ libssl.so.10を作成することです。たとえば、シンボルのみが必要な場合は、次のようになります。DT_SONAMElibssl.so.10SSL_new

 echo "void SSL_new() { }" > t.c &&
 gcc -fPIC -shared -o libssl.so -Wl,--soname='libssl.so.10' t.c

このスタブ ライブラリに対してプログラムをリンクすると、バージョン管理されたシンボルは必要ありません。

ランタイム リンカーは、CentOS およびCloudLinuxSSL_newで、この未定義のバージョン管理されていない条件を満たします。SSL_new@libssl.so.10SSL_new@Base

于 2014-01-11T07:10:55.253 に答える
1

この方法でこれらの警告を取り除くことができました (CentOS/Cloud Linux ではなく Debian/Arch を使用していますが、あなたにも役立つはずです)。

  1. 混乱を避けるために libssl-devel パッケージを削除します

  2. ソースから libssl をコンパイルする

    ./config --prefix=/usr/local --openssldir=/usr/local/openssl shared

  3. それに対してソフトウェアを構築します。

私の場合、これらのバージョン参照は消え、警告なしで実行されました。

Version References:
  required from libcrypto.so.1.0.0:
    0x066a2b20 0x00 10 OPENSSL_1.0.0
  required from libssl.so.1.0.0:
    0x066a2b20 0x00 05 OPENSSL_1.0.0
于 2014-01-09T16:22:06.213 に答える