マニュアルページセク ション 1: ユーザーコマンド

印刷ビューの終了

更新: 2014 年 7 月
 
 

lari(1)

名前

lari - 実行時インタフェースのリンク分析

形式

lari [-bCDsVv] [-a | -i | -o] file | directory...
lari [-CDosv] [-m [-d mapdir]] file

説明

lari ユーティリティーは、動的 ELF オブジェクトのインタフェース要件を分析します。2 つの基本操作モードを利用できます。最初のモードでは、実行時インタフェース情報を表示します。2 番目のモードでは、インタフェース定義を生成します。

動的オブジェクトは、外部コンシューマに提供するインタフェースを表すシンボル定義を提供します。実行時に、あるオブジェクトのシンボル参照から、別のオブジェクトのシンボル定義への結合が確立されます。lari は、指定されたオブジェクトのインタフェース定義と実行時結合の両方を分析します。

実行時インタフェース情報を表示するときに、lari は、ファイルまたはディレクトリの数を分析できます。lari は、コマンド行で指定したそれぞれの file を分析します。lari は、コマンド行で指定したそれぞれの directory の下位に再帰的に移動して、見つかったそれぞれのファイルを処理します。

インタフェース定義を生成するときに、lari は、コマンド行で指定した単一の file だけを処理できます。

–D オプションを指定しない場合、lari は、ldd(1) を使用することによって、動的 ELF オブジェクトとしてファイルを処理します。この処理では次のオプションを使用します。

–r and –e LD_DEBUG=files,bindings,detail

これらのオプションは、オブジェクトを読み込む過程で確立されたすべての結合に関する情報を提示します。ldd を使用することによって、指定されたオブジェクトが実行されず、したがって、たとえば dlopen(3C) による、オブジェクトのユーザー制御の読み込みが行われないことに注意してください。実行プロセスからすべての結合情報を取得するために、次の環境変数を直接実行時リンカー ld.so.1(1) に渡すことができます。

LD_DEBUG=files,bindings,detail LD_DEBUG_OUTPUT=lari.dbg \ 
LD_BIND_NOW=yes

結果として得られるデバッグ出力 lari.dbg.pid は、lari–D オプションを使用して処理できます。注: lari は、デバッグ出力で定義されたパス名を使用して処理された各オブジェクトを分析しようとします。したがって、完全な正確な分析を行うために、各オブジェクトには lari からアクセスできる必要があります。デバッグ出力ファイルは、C ロケールで生成する必要があります。

lari は、インタフェース情報を表示するときに、処理された動的オブジェクトのインタフェースを分析し、デフォルトで、関心を引く情報を表示します。「拡張機能説明」の「関心を引く情報」を参照してください。表示される情報は、ほかのツールへのパイピングにも適しています。この機能は、開発者がプロセス結合を分析したり、複雑な結合シナリオをデバッグしたりするときに役立ちます。

lari を使ってインタフェース定義を生成すると、処理対象の動的オブジェクトのインタフェース要件をより正確に定義できるようになります。動的オブジェクトを作成するときに、明示的にバージョン定義されたインタフェースを定義するようにしてください。この定義は、外部ユーザーが利用できるシンボル定義を制御します。また、この定義によって、実行時のオブジェクトの実行コスト全体を削減できることがよくあります。インタフェース定義は、リンカーで –M オプションおよび関連付けられた mapfile 指令を使用することによって、作成時にオブジェクトに割り当てることができます。mapfile を使用してオブジェクトのバージョンを定義する方法の詳細は、Oracle Solaris 11.2 リンカーとライブラリガイド を参照してください。これらの mapfile の初期バージョンは、lari で作成できます。

オプション

以下のオプションがサポートされています。

–a

分析対象のオブジェクトに関するすべてのインタフェース情報を表示します。注: このオプションからの出力は大量になることがありますが、多くの場合、ほかの分析ツールへのパイピングに役立ちます。

–b

インタフェース情報を、明示的に結合されているシンボルに制限します。注: protected と定義したシンボルは、定義用オブジェクト内から結合されている可能性があります。この結合はリンク編集時に満たされるので、実行時環境では表示されません。protected シンボルは、このオプションで表示されます。

–C

DemanglesC++ シンボル名を復号化します。このオプションは、実行時インタフェース情報を拡張するときに役立ちます。インタフェース定義の生成時に、demangled 名がコメントとして mapfile に追加されます。

–d mapdir

mapfile が作成されるディレクトリ (mapdir) を定義します。デフォルトでは、現在の作業ディレクトリが使用されます。

–D

動的オブジェクトではなくデバッグ情報として入力ファイルを解釈します。

–i

関心を引くインタフェース結合情報を表示します。ほかの出力制御オプションが指定されていない場合、このモードがデフォルトです。「拡張機能説明」の「関心を引く情報」を参照してください。

–m

処理される動的オブジェクトごとに mapfile を作成します。これらの mapfile には、処理されている入力ファイルで必要になる各オブジェクトのインタフェース要件が反映されます。

–o

インタフェース情報を、オーバーヘッドとみなされているシンボルに制限します。mapfile の作成時、オーバーヘッドシンボルがローカルシンボルとして項目化されます。「拡張機能説明」の「オーバーヘッド情報」を参照してください。

–s

さらに分析するために、ldd(1) からの結合情報を保存します。「ファイル」を参照してください。

–V

関心を引くシンボル可視設定を追加します。singleton または protected と定義されたシンボルは、このオプションで識別されます。

–v

すでにバージョン定義されているオブジェクトを無視します。バージョン定義されているオブジェクトのインタフェースはすでに定義されていますが、表示されるインタフェース情報にはその情報が含まれています。たとえば、バージョン定義されている共有オブジェクトであれば、特定のプロセスのオーバーヘッドシンボルが表示される場合があります。共有オブジェクトは多くの場合、複数のプロセスで使用できるように設計されているので、これらのオブジェクトで用意されているインタフェースは、単一のプロセスの要件を超えるときがあります。したがって –v オプションを使用すると、インタフェース情報を表示するときにノイズを軽減できます。

lari から生成される実行時インタフェース情報は、次の形式になります。

[information]: symbol-name [demangled-name]: object-name

各行には、インタフェースシンボル (symbol-name) と、シンボルが定義されるオブジェクト (object-name) が記述されます。シンボルが関数を表す場合、シンボル名のあとに () が続きます。シンボルがデータオブジェクトを表す場合、シンボル名のあとに [] で囲まれたシンボルサイズが続きます。–C オプションが使用された場合、シンボル名は、シンボルの復号化された名前 (demangled-name) とともに表示されます。情報フィールドには、シンボルの使用について記述した次のトークンの 1 つまたは複数が表示されます。

cnt:bnd

2 つの 10 進数値は、シンボル数 (cnt) と、このオブジェクトへの結合の数 (bnd) を示します。シンボル数は、分析対象のオブジェクトで見つかったこのシンボル定義の出現数です。1 より大きな数は、シンボル定義が複数回出現したことを示しています。結合の数は、実行時リンカーによってこのシンボル定義に結合されたオブジェクトの数を示しています。

E

このシンボル定義は、外部オブジェクトから結合されています。

S

このシンボル定義は、同じオブジェクトから結合されています。

D

このシンボル定義は、直接結合されています。

I

このシンボル定義は割り込みシンボルを規定します。明示的に割り込みオブジェクトであることを示すオブジェクトは、すべてのグローバルシンボルを割り込みシンボルとして定義します。ld(1)–z interpose オプションおよび ld.so.1(1) の LD_PRELOAD 変数を参照してください。動的実行可能ファイル内の個々のシンボルは、INTERPOSE mapfile 指令を使用することによって、割り込みシンボルとして定義できます。

C

このシンボル定義は、コピー再配置の参照データです。

F

このシンボル定義は filtee にあります。

P

このシンボルは protected と定義されています。このシンボルには、シンボルが宣言されたオブジェクトからの内部結合が存在する可能性があります。この属性を持つ内部結合には、別のシンボル定義が割り込むことはできません。

A

このシンボル定義は、動的実行可能ファイル内でのプロシージャリンケージテーブルエントリのアドレスです。

U

このシンボル参照は dlsym(3C) などのユーザー要求に起因します。

R

このシンボル定義はフィルタとして機能し、フィルタ対象へのリダイレクションを規定します。

r

このシンボルへの結合は、シンボル検索中のある時点で拒否されました。直接結合要求が、直接結合を防止するタグが付けられているシンボルを見つけると、結合が拒否されます。このシナリオでは、シンボル検索は、デフォルトの検索モデルを使用して繰り返されます。結合はまだ、元の拒否されたシンボルに解決できます。デフォルト以外のシンボル検索が、singleton として識別されたシンボルを見つけたときにも、結合は拒否されます。この場合も、シンボル検索は、デフォルトの検索モデルを使用して繰り返されます。

N

このシンボル定義は、定義に直接結合することを明示的に禁止します。

これらのシンボル分類の詳細は、Oracle Solaris 11.2 リンカーとライブラリガイド を参照してください。

詳細説明

関心を引く情報

デフォルトで、または –i オプションを明示的に使用すると、lari は、実行時インタフェース情報をフィルタ処理して、関心を引くイベントを示します。このフィルタ処理は主に、大きなアプリケーションから生成される情報量を減らすときに実行します。また、この情報を使用すると、複雑な結合シナリオをデバッグするときに注目すべき箇所がわかります。多くの場合で、問題領域を強調します。ただし、特定のアプリケーション用に意味のある情報を正確に分類することは困難です。–a オプションを使用すると、調査対象のアプリケーションに固有のイベントの結合情報を自由に検索できます。

関心を引くシンボル定義が検出された場合、同じシンボルのほかのすべての定義が出力されます。

関心を引くインタフェース情報がフォーカスしているのは、シンボルの複数の定義の存在です。この場合、通常、1 つのシンボルがほかの 1 つまたは複数のシンボル定義に割り込みます。ある定義の結合数 (bnd) が 0 でなく、ほかのすべての定義の結合数が 0 である場合に、この割り込みが発生しています。コンパイル環境 (つまりリンク環境) に起因する割り込みは、関心を引くものとは判断されません。これらの割り込みの出現例としては、コピー再配置 ([C]) や、プロシージャリンケージアドレスへの結合 ([A]) などがあります。

多くの場合、割り込みは望ましいものです。その目的は、共有オブジェクトからのシンボル定義を多重定義する、つまり置き換えることです。ld(1)–z interpose オプションを使用すると、割り込むオブジェクトに明示的にタグ ([I]) を付けることができます。これらのオブジェクトは、プロセスでオブジェクトを読み込む順番とは無関係に、安全にシンボルに割り込むことができます。ただし、明示的でない割り込みが使用される場合には注意してください。この割り込みは、プロセスを構成するオブジェクトの読み込み順序に起因するためです。

ユーザーが作成した多重定義シンボルは、関心を引く情報として lari から出力されます。この例では、interpose1() の 2 つの定義が存在しますが、main の定義だけが参照されます。

[2:1E]: interpose1(): ./main
[2:0]: interpose1(): ./libA.so

割り込みは、予期しないシンボル名の衝突によって生じた、想定外の好ましくないイベントである場合もあります。このような割り込みの症状としては、関数への参照が存在することがわかっているのに、その関数が呼び出されない場合などがあります。このシナリオは、前の例で説明したように、多重定義シンボルとして識別できます。しかし、オブジェクトが特定のシンボルを定義および参照する場合に、より意外なシナリオが多く発生します。

このシナリオの例は、2 つの動的オブジェクトが同じ関数 interpose2() を定義し参照する場合です。このシンボルへの参照はすべて、プロセスで読み込まれる最初の動的オブジェクトに結合します。この場合、オブジェクト libA.sointerpose2() の定義は、オブジェクト libB.sointerpose2() の定義に割り込み、これを隠ぺいします。lari からの出力は次のようになります。

[2:2ES]: interpose2(): ./libA.so
[2:0]: interpose2(): ./libB.so

多重定義シンボルに個別に結合する場合もあります。直接結合が有効になっている場合や ([D])、シンボルの可視性が protected の場合は ([P])、個別に結合されます。個別の結合は明示的に確立できますが、予期しない想定外の結合が存在する場合もあります。直接結合されたシンボルと、可視性が protected のシンボルは、関心を引く情報として出力されます。

オーバーヘッド情報

–o オプションを使用した場合、lari は、オーバーヘッドとみなされるシンボル定義を表示します。

参照されないグローバルシンボルはオーバーヘッドとみなされます。オブジェクト内で提供されるシンボル情報によって、オブジェクトのテキストセグメントのサイズが必要以上に増加します。さらに、シンボル情報によって、実行時にオブジェクト内でほかのシンボル参照を検索するために必要な処理が増える場合があります。

同じオブジェクトからしか参照されないグローバルシンボルは、同じ特性を持っています。シンボル参照の実行時検索は、結果として、参照を行なった同じオブジェクトへの結合になり、追加のオーバーヘッドになります。

これらの両方のシンボル定義は、オブジェクトのインタフェースを定義することによってローカルスコープに降格できます。インタフェース定義は、リンカーで、–M オプションおよび関連付けられた mapfile 指令を使用することによって、作成時にファイルに割り当てることができます。mapfile の詳細は、Oracle Solaris 11.2 リンカーとライブラリガイド を参照してください。–m オプションを付けて lari を使用して、これらの mapfile の初期バージョンを作成します。

lari を使用して mapfile を生成すると、バージョン定義された共有オブジェクトには、オーバーヘッドシンボルをローカルに降格すべきであることを示す mapfile が作成されます。このモデルでは、lari は、既存のインタフェース定義と比較するための mapfile を生成できます。–v オプションを使用して、mapfile を作成するときに、バージョン定義された共有オブジェクトを無視します。

コピー再配置はオーバーヘッドともみなされるため、通常は回避すべきです。コピーされたデータのサイズは、そのインタフェースの定義です。この定義は、データが定義されている共有オブジェクトのより新しいバージョンでのデータサイズを変更する機能を制限します。この制限、およびコピー再配置を処理するコストは、関数インタフェースを使用してデータを参照することによって回避できます。コピー再配置の lari からの出力は次のようになります。

[2:1EC]: __iob[0x140]: ./main
[2:0]: __iob[0x140]: ./libA.so.1

前の例で使用された __iob など、いくつかの小さなコピー再配置が存在することに注意してください。これは、システムライブラリのプログラミング操作のために歴史的な理由により存在しています。

オーバーヘッド情報の別の例は、動的実行可能ファイルのプロシージャリンケージテーブルエントリに、動的オブジェクトを結合する場合です。動的実行可能ファイルが外部関数を参照する場合、プロシージャリンケージテーブルエントリが作成されます。この構造では、関数呼び出しが実際に行われるまで、参照結合を延期できます。動的オブジェクトがこの参照された同じ関数のアドレスを取得した場合、動的オブジェクトは、動的実行可能ファイルのプロシージャリンケージテーブルエントリに結合します。このタイプのイベントの例は、次の点を明らかにします。

[2:1EA]: foo(): ./main
[2:1E]: foo(): ./libA.so

このタイプの少数の結合は、通常は心配する必要はありません。ただし、ジャンプテーブルプログラミング技法などによって、これらの結合が多数発生する場合は、オーバーヘッドを起こす一因となることが考えられます。このタイプのアドレス再配置結合では、直接関数を呼び出したときに使用される遅延再配置処理ではなく、アプリケーション起動時の再配置処理が必要になります。このアドレスを使用するために、実行時に間接参照も必要になります。

使用例 1 複数の結合がある場合の分析

次の例では、複数のシンボル定義が存在するプロセスの分析を示します。共有オブジェクト libX.solibY.so は関数 interpose() を呼び出します。この関数は、アプリケーション main と、共有オブジェクト libA.so の両方に存在します。割り込みのため、両方の参照は maininterpose() の定義に結合します。

共有オブジェクト libX.solibY.so は関数 foo() も呼び出します。この関数は、アプリケーション main と、共有オブジェクト libA.solibX.so、および libY.so に存在します。libX.solibY.so の両方は直接結合を有効にして構築されているので、各オブジェクトはそれぞれ独自の定義に結合します。

example% lari ./main
[3:0]: foo(): ./libA.so
[3:1SD]: foo(): ./libX.so
[3:1SD]: foo(): ./libY.so
[2:0]: interpose(): ./libA.so
[2:2EP]: interpose(): ./main

結合情報をさらに分析するために、結合データをその後の検査用に保存できます。たとえば、前の出力は、関数 interpose() が、main の外部にある 2 つのオブジェクトから呼び出されたことを示しています。結合の出力を検査することによって、この関数への参照が行われた場所を明らかにできます。

example% lari -s ./main
lari: ./main: bindings information saved as: /usr/tmp/lari.dbg.main
.....
example% fgrep foo /usr/tmp/lari.dbg.main
binding file=./libX.so to file=./main: symbol `interpose'
binding file=./libY.so to file=./main: symbol `interpose'

注: 結合の出力にはプロセス識別子、アドレス、その他の結合情報が伴うので、出力は通常、ここに示すよりも多くなります。

使用例 2 インタフェース定義の生成

次の例では、アプリケーションとその依存関係のインタフェース定義を作成しますが、バージョンが定義されたシステムライブラリは無視します。アプリケーション main は、foo.so のインタフェース one()two()、および three() を参照します。

example% lari -omv ./main
example% cat mapfile-foo.so
#
# Interface Definition mapfile for:
#       Dynamic Object: ./foo.so
#       Process:        ./main
#

foo.so {
        global:
                one;
                three;
                two;
        local:
                _one;
                _three;
                _two;
                *;
};

ファイル

$TMPDIR/lari.dbg.file

ldd(1) によって生成された結合の出力。

属性

属性についての詳細は、マニュアルページの attributes(5) を参照してください。

属性タイプ
属性値
使用条件
developer/base-developer-utilities
インタフェースの安定性
下記を参照。

人間が読める形式の出力は「不確実」です。オプションは「確実」です。

関連項目

ld(1), ldd(1), ld.so.1(1), dlopen(3C), dlsym(3C), attributes(5)

Oracle Solaris 11.2 リンカーとライブラリガイド