1)Ubuntu 10.04でOpenSSL 0.9.8を使用する:

1)Ubuntu 10.04でOpenSSL 0.9.8を使用する:

progソースからビルドしてインストールされたOpenSSL 1.0.2ベータにプログラムをコンパイルして接続しようとしています/usr/local/ssl-1.0.2。 0.9.8を使用する以前のシステムでは、これを問題なく実行できます。 1.0.1がインストールされた最新のシステムでは、より多くの作業が必要です。理由を知りたいです。

1)Ubuntu 10.04でOpenSSL 0.9.8を使用する:

1.0.2でコンパイルしてリンクするためにとった手順は次のとおりです。

$ ./config shared --openssldir=/usr/local/ssl-1.0.2 && make && make install
$ ldconfig
$ ldconfig -p | grep libcrypto

=> 0.9.8ファイルのみを表示し、1.0.2ファイルパスを追加しました...

$ ldconfig /usr/local/ssl-1.0.2/lib
$ ldconfig -p | grep libcrypto

=>

 libcrypto.so.1.0.0 (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0
 libcrypto.so.0.9.8 (libc6, hwcap: 0x0008000000008000) => /lib/i686/cmov/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6, hwcap: 0x0004000000000000) => /lib/i586/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6, hwcap: 0x0002000000000000) => /lib/i486/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6) => /lib/libcrypto.so.0.9.8
 libcrypto.so.0.9.8 (libc6) => /usr/lib/libcrypto.so.0.9.8
 libcrypto.so (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so

これによりコンパイルが可能ですprog...

$ gcc -o prog ... -L/usr/local/ssl-1.0.2/lib -lcrypto
$ ldd prog

=>

    libcrypto.so.1.0.0 => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0 (0x0083b000)

... 1.0.2と正しく接続されています。

2)Debian WheezyでOpenSSL 1.0.1を使用する:

同じステップ、異なる結果。

$ ./config shared --openssldir=/usr/local/ssl-1.0.2 && make && make install
$ ldconfig
$ ldconfig -p | grep libcrypto

=>

 libcrypto.so.1.0.0 (libc6, hwcap: 0x0008000000008000) => /usr/lib/i386-linux-gnu/i686/cmov/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6, hwcap: 0x0004000000000000) => /usr/lib/i386-linux-gnu/i586/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6) => /usr/lib/i386-linux-gnu/libcrypto.so.1.0.0

同様に、1.0.2にパスを追加しました...

$ ldconfig /usr/local/ssl-1.0.2/lib
$ ldconfig -p | grep libcrypto

=>

 libcrypto.so.1.0.0 (libc6, hwcap: 0x0008000000008000) => /usr/lib/i386-linux-gnu/i686/cmov/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6, hwcap: 0x0004000000000000) => /usr/lib/i386-linux-gnu/i586/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0
 libcrypto.so.1.0.0 (libc6) => /usr/lib/i386-linux-gnu/libcrypto.so.1.0.0
 libcrypto.so (libc6) => /usr/local/ssl-1.0.2/lib/libcrypto.so

それでは、コンパイルしてみましょう...

$ gcc -o prog ... -L/usr/local/ssl-1.0.2/lib -lcrypto
$ ldd prog

=>

    libcrypto.so.1.0.0 => /usr/lib/i386-linux-gnu/i686/cmov/libcrypto.so.1.0.0 (0xb7591000)

しかし、ここでは1.0.2に関連付けられていません。コンパイル時のライブラリパスは正確ですが(指定されて-Lgccないと、使用されている一部の関数は1.0.2に固有のものであるため失敗しますprog)、ランタイムライブラリのパスはそうではありません。

3) Wheezyで実行する方法

実行するかどうかにかかわらずldconfig /usr/local/ssl-1.0.2/lib

$ gcc -o prog ... -Wl,--rpath=/usr/local/ssl-1.0.2/lib -L/usr/local/ssl-1.0.2/lib -lcrypto
$ ldd prog

=>

    libcrypto.so.1.0.0 => /usr/local/ssl-1.0.2/lib/libcrypto.so.1.0.0 (0xb7592000)

またはexport LD_LIBRARY_PATH=/usr/local/ssl-1.0.2/lib実行する前に実行してくださいgcc

私が知りたいこと

提案されているように、mr.spuraticを使用してLD_DEBUG=libs ./progパスが/etc/ld.so.cache。ファイルを開き、.soの検索順序が.soの出力と一致することがわかりましたldconfig -p

実際の質問は次のとおりです。

  • 1.0.2ファイルが1)のldconfigリストの上部にあるが2)のリストにない理由は何ですか?純粋なランダム性? 1.0.1と1.0.2ファイルのサフィックスが同じで混乱していますか? (「1.0.0」)

または言い換えれば、

  • 3)に追加されたフラグが1)に必要でないのはなぜですか?

ベストアンサー1

デフォルト以外のパッケージに対してコンパイル/リンクするときに注意すべき3つのことがあります。

  • ヘッダー(通常CFLAGS
  • コンパイル時ライブラリパス(通常LDFLAGS
  • ランタイムライブラリパス(LDFLAGSLD_RUN_PATHまたは)LD_LIBRARY_PATHを通してld.so.conf

それが何であるかを言っていないprogので、それがどのようにうまく設定されているか(またはautoconfを使用しているか)はわかりません。最初の2つのステップだけを安定して実行することをたくさん見ました。

CFLAGSリンクフェーズでは、ライブラリパスの順序が関連しています。 GNUツールチェーン(gccとbinutils)を使用していると仮定すると、以前に設定またはconfigure直接設定してMakefile何が起こっているかを確認できます。

export CFLAGS="-Wl,-t"

これにより、トレースオプションがリンカーに渡されます。 makeプロセス中に簡潔な「CC」および「LD」行のみが出力される場合は、-tmakeコマンドにまたはを追加する必要がありますV=1。 )VERBOSE=1

実行時にld.so慎重に設定して、試している内容を確認できますLD_DEBUG

LD_DEBUG=libs ./myprog

files(または詳細については、またはの値を試してくださいsymbols

ビルド時に3つのパラメーターをすべて正しく指定するには、次のことができる必要があります。

  • export CFLAGS="-I/usr/local/ssl-1.0.2/include"
  • export LDFLAGS="-L/usr/local/ssl-1.0.2/lib -R/usr/local/ssl-1.0.2/lib"

次に、再構成/再コンパイルします。

--openssldir代わりに、より伝統的なものを使用しています--prefix(後者をお勧めし、make install_sw基本インストールで提供する1000個程度のマニュアルページとシンボリックリンクが必要ない場合でも使用できます)。これが問題の一部である可能性があります。何らかの理由で表示される.soライブラリにはld.soバージョンサフィックスがないことが知られています(例.so.1.0.2:)。正しい" make install"はこれを設定する必要があります(link-sharedメインのターゲットを介してMakefile)。

このオプションは特定のOpenSSLライブラリの実行可能出力にRPATHを含めるようにリンカに指示するため、通常は-Rランタイムリンカ()ld.soによって提供されるデフォルト値に依存する必要はありません。次のコマンドを使用して既存のバイナリを変更できます。chrpath代わりに。

これはエクスポートとほぼ同じですLD_LIBRARY_PATH=/usr/local/ssl-1.0.2/lib。 RPATH および関連 RUNPATH の詳細については、こちらをご覧ください。http://blog.tremily.us/posts/rpath/

最後の手段として、「共有」または「何も共有しない」ことなくOpenSSLを構築できます。これにより、この問題のない静的ライブラリが提供されます(ただし、ELFで使用されるときなどの他の問題が発生する可能性が高いため、PIC / PIEの問題が発生します)


更新された詳細によると、問題は1.0.1と1.0.2betaの両方で.soバージョンサフィックス(SONAME)が1.0.0に設定されていることです。 0.9.8しかない最初のシステムでは問題は発生しません。 2番目のバージョンは1.0.1で、1.0.2はすべて1.0.0で、これは順番に「最初のゲームの勝利」ですld.so.{conf,d}ldコンパイル時リンカーはランタイムリンカーとは異なるプログラムであり、異なる動作を持つ可能性があることに留意してくださいld.so(このように、しばしばシンボルエラーまたはより深刻な結果につながります)。

$ cd /usr/local/src/openssl/openssl/1.0.2beta1
$ readelf -a libssl.so | grep SONAME
0x0000000e (SONAME)                     Library soname: [libssl.so.1.0.0]

$ cat verchk.c
int main(int argc, char *argv[]) {
    printf("build: %s\n",OPENSSL_VERSION_TEXT);
    printf("run  : %s\n",SSLeay_version(SSLEAY_VERSION));
    return 0;
}

$ gcc -Wall  -I/usr/local/src/openssl/openssl-1.0.2-beta1/include \
    -Wl,-rpath /usr/local/src/openssl/openssl-1.0.2-beta1/ \
    -o verchk /usr/local/src/openssl/openssl-1.0.2-beta1/libcrypto.so verchk.c

$ ./verchk
build: OpenSSL 1.0.2-beta1 24 Feb 2014
run  : OpenSSL 1.0.2-beta1 24 Feb 2014

$ grep SHLIB_M...R= Makefile
SHLIB_MAJOR=1
SHLIB_MINOR=0.0

修正する OpenSSL-1.1では、APIレベルが一部変更されており、上記のコードはv1.1ヘッダーと古いライブラリ(undefined reference to `OpenSSL_version')でコンパイルされません。

SSLeay_version()これで廃止され(適切に応じて)、正しいAPI関数に対して-dにOPENSSL_API_COMPATなります。#defineOpenSSL_version()

おすすめ記事