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に関連付けられていません。コンパイル時のライブラリパスは正確ですが(指定されて-L
いgcc
ないと、使用されている一部の関数は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
) - ランタイムライブラリパス(道
LDFLAGS
、LD_RUN_PATH
または)LD_LIBRARY_PATH
を通してld.so.conf
それが何であるかを言っていないprog
ので、それがどのようにうまく設定されているか(またはautoconfを使用しているか)はわかりません。最初の2つのステップだけを安定して実行することをたくさん見ました。
CFLAGS
リンクフェーズでは、ライブラリパスの順序が関連しています。 GNUツールチェーン(gccとbinutils)を使用していると仮定すると、以前に設定またはconfigure
直接設定してMakefile
何が起こっているかを確認できます。
export CFLAGS="-Wl,-t"
これにより、トレースオプションがリンカーに渡されます。 makeプロセス中に簡潔な「CC」および「LD」行のみが出力される場合は、-t
makeコマンドにまたはを追加する必要があります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
なります。#define
OpenSSL_version()
答え2
新しいライブラリへのパスはファイルの1つにありますか/etc/ld.so.conf.d
?次の実行:-
#ldconfig -v
キャッシュを再構築します。十分に迅速に対処すると、印刷された長いリストに新しいライブラリが表示されます(またはまたはパイプgrep
)less
。
パスはすでに最初のサーバーにはありますが、2番目のサーバーにはない可能性があります。