Klocwork によってインターセプトするビルドコマンドの決定
このセクションには、kwinject によって識別されないまたはサポートされていないコンパイラを使用した統合に関する詳細な情報が記載されています。具体的には、自分自身のビルドまたは kwinject によって生成された build trace (ビルドトレース) のログを使用して、インターセプト (およびコンパイラフィルターファイル<compiler_name>_filter.py
にインクルード) する価値があるビルドコマンドとその価値がないコマンドを判定する方法についての詳細を説明します。
ほとんどの C/C++ コンパイラは同じ (または非常に類似した) 実行パターンを踏襲します。一般的には、さまざまな下位レベルのプログラム (一般的に "ツールチェーン" と呼ばれる) に対して、1 つのユーザー管理下のフロントエンド (GNU での gcc/g++ や Sun Forte での cc/CC など) があります。たとえば、次のようになります。
- プリプロセッサ - コードを前処理、つまり、#include ディレクティブと #define ディレクティブを展開します。
- コンパイラ - ソースコードをパースし、アセンブラ/バイナリコードを特定のターゲットアーキテクチャ用に生成します。
- アセンブラ - アセンブラコードをバイナリオブジェクトファイルに変換します。
多くの場合、リンク作成やオブジェクトファイルとライブラリの実行ファイルまたは動的ライブラリ (共有オブジェクトとも呼ばれる) への結合などのリンク-タイムタスクに同じフロントエンドが使用されます。
たとえば、一般的な gcc の (サブ) プロセスツリーは次のようになります。
gcc -D_EXAMPLE_ -I/blah/blah/include example.c
cpp0 -lang-c -v -I/blah/blah/include -DGNUC=2 ...-D_EXAMPLE_ example.c /tmp/XXX.i
プリプロセッサ。gcc 3.x プリプロセッサとコンパイラが 1 つのツールとしてマージされているため。
cc1 /tmp/XXX.i -quiet ...-o /tmp/XXX.s
gcc 2.x compiler
-- または --
cc1 -quiet -v -I/blah/blah/include -D_EXAMPLE_ example.c ... example.c -o /tmp/XXX.s
gcc 3.x プリプロセッサとコンパイラ。アセンブラコードを生成。
as -V -Qy -o /tmp/XXX.o /tmp/XXX.s
アセンブラ。アセンブラコードをバイナリオブジェクトファイルに変換。
collect2 ...-dynamic-linker /lib/ld-linux.so.2 .../tmp/XXX.o
リンカー。デフォルトのシステム/gcc ライブラリのあるオブジェクトファイルを実行ファイルに結合。
gcc 2.x が、ツールチェーンのそれぞれの部分に対して個別のサブプロセスを使用する一方、3.x は、プリプロセッサとコンパイラを 1 つのステップに結合することに注意してください。
gcc はまったく作業を行わず、単純にタスクを他のプログラムに委任します。
Klocwork をビルドに統合するときには、コンパイラが使用した "内部" プログラムは無視できます。Klocwork コンパイラは、ほとんどのコンパイラフロントエンドと同様に動作するため、kwinject は下位レベルの詳細を必要としません。
ツールチェーンの中にはよく知られたものもあります (gcc = [cpp0 +] cc1+as + collect2
など)。これ以外は build trace (ビルドトレース) を使用すると簡単に検出されます。ビルド統合でインターセプトする価値があるコマンドラインを判定するには、次の規則を使用します。
- 実行されたプログラムの、コンパイラのフロントエンドの呼び出し (ccmips.exe -> build.exe、ecommip.exe など) に続く循環シーケンスを探します。
- コマンドラインが常にコンパイラフロントエンドに続き、そのほとんどの引数 (-D、-I、入力ソースファイルの名前など) を継承する場合、ツールチェーンの一部である可能性が高く、安全に無視できます。または、すべての重要でないオプションおよび引数 (ほとんどの場合 -D、-I、およびソースファイルの名前を除くすべて) を破棄しながら 2 つの連続するコマンドラインを比較します。両方のコマンドラインがインターセプトされ、フィルター処理された場合、重複したコマンドとなりますか? 重複したコマンドになる場合、2 番目のコマンドラインは無視される必要があります。
- 一時ファイル (UNIX では
/tmp/XXX
または/var/tmp/XXX
、Windows ではC:\Documents and Settings\JoeUser\Local Settings\Temp\xxx
) を入出力として使用するコマンドは、ほとんどの場合 "内部" コマンドであるため、無視される必要があります。 - 次の 3 つの種類のコマンドを探します。
- コンパイラタイプ - 1 つまたは複数のソースファイル (.c、.cpp、.cc など) を入力として使用し、出力としてオブジェクトファイルまたは実行可能ファイル (.o、.obj、.exe など) を生成するコマンド。この出力は、-o、-out または -output。
- リンカータイプ - 多数のオブジェクトファイルおよびライブラリを使用し、実行可能ファイルまたはランタイムライブラリ (.exe、.dll、.so など) を生成するコマンド。同じ種類の出力オプションが頻繁に使用されます。
- ライブラリタイプ - 多数のオブジェクトファイルを使用し、静的なライブラリ (xxx.lib、libxxx.a) を生成するコマンド。
- 上記のコマンドタイプの説明に当てはまらないコマンドは、kwinject では重要でない場合が多くなります。たとえば、Green Hills gnm.exe は、オブジェクトファイルとライブラリを入力として使用するためリンカーコマンドのように見えますが、実行可能ファイルも動的または静的なライブラリも生成しません。したがって、インターセプトするべきではありません。