Solaris リンカーには、デバッギングライブラリが付いていて、これを使用すると実行時のリンクプロセスをより詳細に監視できます。このライブラリは、アプリケーションと依存関係の実行を理解したり、デバッグする場合に役立ちます。これはビジュアルエイドで、このライブラリを使用して表示される情報のタイプは定数のままであると予期されますが、この情報の正確な形式は、リリースごとにわずかに変更される場合があります。
実行時リンカーをよく理解していないと、デバッギング出力のなかには理解できないものがある可能性がありまが、一般的には、興味深い面が多いといえます。
デバッギングは、環境変数 LD_DEBUG
を使用して実行します。すべてのデバッギングの出力は、接頭辞としてプロセス識別子を持っていて、デフォルトごとに、標準的なエラーに対して送信されます。この環境変数は、1 つまたは複数のトークンを使用して、必要なデバッギングタイプを示す必要があります。
このデバッギングオプションとともに使用できるトークンは、LD_DEBUG=help
を使って表示できます。どの動的実行プログラムを使用しても、この情報を要求することができます。この場合、プロセス自体が終了した後でこの情報が表示されます。次に例を示します。
$ LD_DEBUG=help prog 11693: 11693: For debugging the runtime linking of an application: 11693: LD_DEBUG=token1,token2 prog 11693: enables diagnostics to the stderr. The additional 11693: option: 11693: LD_DEBUG_OUTPUT=file 11693: redirects the diagnostics to an output file created 11593: using the specified name and the process id as a 11693: suffix. All diagnostics are prepended with the 11693: process id. 11693: 11693: 11693: basic provide basic trace information/warnings 11693: bindings display symbol binding; detail flag shows 11693: absolute:relative addresses 11693: detail provide more information in conjunction with other 11693: options 11693: files display input file processing (files and libraries) 11693: help display this help message 11693: libs display library search paths 11693: move display move section processing 11693: reloc display relocation processing 11693: symbols display symbol table processing; 11693: detail flag shows resolution and linker table addition 11693: versions display version processing 11693: audit display runtime link-audit processing |
これは一例で、実行時リンカーに有効なオプションを示しています。正確なオプションについては、リリースごとに異なる場合があります。
環境変数 LD_DEBUG_OUTPUT
を使用すると、出力ファイルを標準エラーの代わりに使用するように指定できます。出力ファイルの名前には、接尾辞としてプロセス ID が付きます。
セキュアアプリケーションのデバッギングは実行できません。
実行時に発生するシンボル結合の表示機能は、最も有効なデバッギングオプションの 1 つです。たとえば、2 つのローカル共有オブジェクト上に依存関係を持つ、非常に単純な動的実行プログラムを取り上げてみます。
$ cat bar.c int bar = 10; $ cc -o bar.so.1 -Kpic -G bar.c $ cat foo.c foo(int data) { return (data); } $ cc -o foo.so.1 -Kpic -G foo.c $ cat main.c extern int foo(); extern int bar; main() { return (foo(bar)); } $ cc -o prog main.c -R/tmp:. foo.so.1 bar.so.1 |
実行時シンボルは、LD_DEBUG=bindings
を設定することによって表示されます。
$ LD_DEBUG=bindings prog 11753: ....... 11753: binding file=prog to file=./bar.so.1: symbol bar 11753: ....... 11753: transferring control: prog 11753: ....... 11753: binding file=prog to file=./foo.so.1: symbol foo 11753: ....... |
ここでは、データの再配置に必要なシンボル bar が、アプリケーションが制御を受け取る前に結合されます。これに対して、関数の再配置に必要なシンボル foo は、関数が最初に呼び出されたときに、アプリケーションが制御を受け取った後で結合されます。これは、レイジー結合のデフォルトモードを示しています。環境変数 LD_BIND_NOW
が設定されている場合、シンボル結合はすべて、アプリケーションが制御を受け取る前に実行されます。
現在の結合ロケーションの実際の相対アドレスに関する追加情報は、LD_DEBUG=bindings,detail
を設定すると入手できます。
実行時リンカーが、関数の再配置を実行すると、関数 .plt に関連したデータも書き換えられるため、この後に発生する呼び出しは、関数に直接送信されます。環境変数 LD_BIND_NOT
は、あらゆる値に設定されて、このデータの更新を防ぐことができます。この変数を、詳細結合に対するデバッギング要求とともに使用すると、関数結合すべての完全な実行時アカウントを入手できます。この組み合わせによる出力は、膨大なものになるため、アプリケーションのパフォーマンスは低下します。
この他にも、実行時のさまざまな検索パスの使用状況が表示できます。たとえば、依存関係の配置に使用される検索パスのメカニズムは、次のように LD_DEBUG=libs
を設定して表示できます。
$ LD_DEBUG=libs prog 11775: 11775: find object=foo.so.1; searching 11775: search path=/tmp:. (RPATH from file prog) 11775: trying path=/tmp/foo.so.1 11775: trying path=./foo.so.1 11775: 11775: find object=bar.so.1; searching 11775: search path=/tmp:. (RPATH from file prog) 11775: trying path=/tmp/bar.so.1 11775: trying path=./bar.so.1 11775: ....... |
ここでは、アプリケーション prog 内に記録された実行パスは、2 つの依存関係 foo.so.1 と bar.so.1 の検索に影響を与えます。
これと同様の方法で、各シンボルを検索する検索パスは、LD_DEBUG=symbols
を設定して表示できます。これを bindings 要求と結合すると、次のように、シンボル再配置プロセスが完全に表示されます。
$ LD_DEBUG=bindings,symbols 11782: ....... 11782: symbol=bar; lookup in file=./foo.so.1 [ ELF ] 11782: symbol=bar; lookup in file=./bar.so.1 [ ELF ] 11782: binding file=prog to file=./bar.so.1: symbol bar 11782: ....... 11782: transferring control: prog 11782: ....... 11782: symbol=foo; lookup in file=prog [ ELF ] 11782: symbol=foo; lookup in file=./foo.so.1 [ ELF ] 11782: binding file=prog to file=./foo.so.1: symbol foo 11782: ....... |
上記の例では、シンボル bar は、アプリケーション prog 内では検索されません。これは、コピーの再配置を処理するときに行なわれる最適化が原因です (この再配置タイプの詳細については、「コピー再配置」を参照)。