対応カーネル |
2.6.8 - 2.6.30 (i386) 2.6.18 - 2.6.30 (x86_64) |
---|---|
対応プロセッサ |
x86, x86_64 Pentium4, PentiumM, Atom, Core, Core2, Core i series |
ライブラリ | binutils, elfutils, kernel-debuginfo |
対応ディストリビューション |
Red Hat Enterprise Linux 4.0 Red Hat Enterprise Linux 4.3 Red Hat Enterprise Linux 5.0 Red Hat Enterprise Linux 5.1 Red Hat Enterprise Linux 5.4 Miracle Linux 4.0 SP1 Fedora 12 |
procfs, kallsyms, apic, kprobes, relayfsがサポートされている必要がある。
OProfileなど、プロセッサの機能の一つである性能モニタリング機能(PEBS)を用いる ツールとの併用はできない。 (プロセッサの仕様により、性能モニタリング機能と分岐命令トレース機能が 同じメモリ領域で管理されるため)
一般的なソフトウェアと同じように、tarボールを解凍し、configureスクリプトを走らせ、 make, make installすることでビルドとインストールは完了する。
BtraxはプロセッサにあるBTS(Branch Trace Store)と呼ばれる機能を利用している。 BTS機能はジャンプや割り込みがあったときに、ジャンプ元とジャンプ先を逐一記録する機能であり、 Btraxはこの情報を取得することでカバレッジ解析を行っている。
Btraxは以下のコマンドから構成される。
コマンド名 | 概要 |
---|---|
bt_collect_log |
BTSログ取得する。 ログ取得はプロセスの開始から終了まですべてを得る方法、 既に実行しているプロセスの任意のタイミングでログ取得する方法、 ある関数からある関数までのログ取得を行う方法、 特定のシステムコールからログ取得を開始する方法などがある。 |
bt_split |
BTSログをPIDで分離する。 |
bt_coverage |
BTSログからカバレッジを解析し、HTML形式で出力する。 解析範囲を限定することも可能である。 |
bt_execpath |
BTSログから、どのような実行パスを通ったかを表示する。 解析範囲を限定することも可能である。 |
各コマンドで利用可能なオプションについては リファレンスを参照のこと
アプリケーション全体のカバレージ解析ではなく、一部のみのカバレージを解析したい場合、 以下の関数を使うことで、BTSログの取得範囲を限定することができる。 これらの関数は"btrax/bt_for_ap.h"をincludeすることで利用可能となる。 なお、Btraxはデフォルトでアプリケーションの先頭からログ取得を開始してしまうため、 特定の領域のみのカバレージ解析を行いたい場合、あらかじめmain関数の頭でBTSログ取得を 停止しておく必要がある。
関数名 | 概要 |
---|---|
bt_start_from_ap() |
この関数からBTSログの取得を開始する |
bt_stop_from_ap() |
この関数からBTSログの取得を停止する |
btraxでは、トレース対象がカーネルかアプリケーションかによって、必要な手順が異なる。 以下の表にトレース対象とトレース手順の概要を示す。
# | トレース対象 | バイナリ再構築 | トレース手順の概要 | |
---|---|---|---|---|
カーネル/アプリ | トレース範囲 | |||
1 | カーネル | 任意の部分だけをトレース。例えば、ある関数だけトレース | なし |
|
2 | アプリ | 実行直後からの全挙動をトレース | なし |
|
3 | アプリ | 任意の部分だけをトレース | フック関数追加要 |
|
4 | アプリ | 実行中のアプリケーションをトレース | なし |
|
5 | システムコール | トレース開始時に指定したアプリ(およびその子プロセス/スレッド)から 発行されるシステムコールの実行をトレース | なし |
|
カーネルの任意の部分のカバレージ解析を行う場合、bt_collect_log
に
--start
および--stop
オプションを追加し、
関数名で開始/終了箇所を指定する。
具体的には次のように指定する。
この例では、ext4_create
関数が呼ばれたらトレースを開始し、
ext4_unlink
関数が呼ばれたらトレースを終了するように指定している。
なお、-d log_dir
はログを出力するディレクトリを指定している。
このコマンドは自動的に終了しないため、トレースを終了させるにははCtrl+Cを
bt_collect_log
に送信する必要がある。
ログ取得が完了したら、次はカバレージ解析を行う。
カバレージ解析はbt_coverage
コマンドを用いる。
具体的には次のようなコマンドを発行する
解析対象ログは-f
オプションでログディレクトリ内のcpu0,cpu1...というファイルを渡す。
複数cpu*ファイルがある場合は、カンマ区切りで指定する。
また、今回は解析対象がカーネルであるため、カーネル空間を指定するオプション--ker
を
指定する。
カバレージ解析結果の出力先は-o
オプションで指定する。
bt_coverage
は指定されたディレクトリを作成し、内部にHTMLファイルを書き出す。
アプリケーションの全挙動の解析を行う場合、
bt_collect_log
でBTSログを取得する際、-c
オプションで
トレース対象のアプリケーションを実行するコマンドを指定する。
ログ取得が完了すると、-d
オプションで指定したディレクトリが作成され、
その中にBTSログが格納される。
次にログディレクトリに入り、bt_splitコマンドでCPUごとのBTSログを
PID単位に分離する。
最後に、bt_splitコマンドによってPIDごとに分離されたログファイルを
bt_coverageコマンドで解析する。
-o
オプションで指定したディレクトリに
カバレージ解析結果がHTMLで出力される。
また、例ではターゲットアプリケーションだけを解析するため、
ユーザ空間指定フラグである--usr
オプションを渡している。
カーネル空間も合わせてカバレージ解析結果を取得する場合は、--usr
のかわりに
--all
を使うこともできる。
アプリケーションの任意の部分のみのカバレージ解析を行いたい場合、 アプリケーションのソースコードにトレース開始/終了用フック間数を埋め込み、 再コンパイルする必要がある。それらの関数は"btrax/bt_for_ap.h"をインクルード することで利用可能になる。
Btraxはデフォルトでアプリケーションの先頭から トレースを開始してしまうため、アプリケーションのmain関数の先頭に、 トレース終了フック間数を入れておく必要がある。 例えば、次のようにトレース開始/終了フック間数を入れる。
#include "btrax/bt_for_ap.h" int main(int argc, char *argv[]) bt_stop_from_ap(); /* トレース終了フック関数 */ ... ... bt_start_from_ap(); /* トレース開始フック関数 */ ... /* 解析対象コード */ ... bt_stop_from_ap(); /* トレース終了 */ ... }
このようにトレース開始/終了フック間数を入れ、再ビルドした後は、 「アプリケーションの実行直後からの全挙動をトレース」 と同じ手順を踏むことでカバレージ解析が可能となる。
既に実行されているアプリケーションのカバレージ解析を行いたい場合、
bt_collect_log
でログを収集する際に-p
オプションと、
解析したいアプリケーションのPIDを指定する。具体的には、以下のようなコマンドを実行する。
-p 12345
はPID=12345のアプリケーションを意味している。
ログの取得はプロセスが終了するか、bt_collect_log
にCtrl+Cを送信するまで続く。
ログ取得が完了したら、カバレージ解析を行うが、この方法は 「アプリケーションの実行直後からの全挙動をトレース」と 同じである。
# cd log_dir # bt_split -d . # bt_coverage --usr -f PID -o html_dir # firefox html_dir/top.html
システムコールの実行をトレースするには、bt_collect_log
で
ログを収集する際に--syscall
オプションとカーネル内のシステムコールを処理する
関数名を渡す必要がある。
次の例では、gettimeofday
システムコールをトレースする例を示す。
sys_gettimeofday
はシステムコールgettimeofdayのカーネル内エントリポイントである。
次に、bt_coverage
コマンドでカバレージ解析を行い、結果を出力する。
今回はシステムコール内部のカバレージ測定を行うため、カーネル空間のみを解析対象にする--ker
オプションを指定し、さらに解析対象を限定する為に-I
オプションで
エントリポイントsys_gettimeofday
を指定している。
また、余分な解析を行わせないため-E
オプションでschedule(), dump_stack(), printk()
を省いている。
なお、今回は解析対象としてカーネルのみを指定したが、アプリケーションとカーネル、
あわせてカバレージ解析を行いたい場合は、--ker
のかわりに
--all
を指定することもできる。
Btraxはカバレージの比較をサポートしており、 あるアプリケーションの入力を変えるなどして、カバレージがどのように変わるかを知ることができる。 今回はlsコマンドを例にとって説明する。
まず、bt_collect_log
コマンドでログを取得する。
次の例では'ls'
と'ls -l'
を実行したときのログを取得している。
次に、それぞれのログファイルをbt_split
コマンドによって
PIDごとに分離する。
最後に、bt_coverage
コマンドでカバレージ解析を行うが、
--f2
オプションで比較対象のログファイルを指定することで、
カバレージ比較結果を得ることができる。
過去に得られた複数のログファイルと、新しく実行して得られたログファイルの
カバレージを比較する場合、bt_coverage
コマンドに指定する
-f
オプションに複数のログファイルを渡すことでカバレージ比較をすることができる。
図中のOK,NT,HTはそれぞれ分岐命令の分類を表しており、OKはTaken,Untaken両方実行したことを、 NTは実行されていないことを、HTは分岐/通過の片方のみを実行したことを意味している。
Btraxはカバレージ解析だけでなく、bt_execpath
コマンドを使うことで、
実行経路を表示することもできる。
bt_execpath
コマンドで指定できるオプションは
リファレンス#bt_execpathを参照。
bt_execpath
の使用例を示す。
例では、プロセスごとに分割されたログファイルを読み、 ユーザ空間だけを解析対象にし、サマリ表示を行うように指定している。
bt_collect_log
で利用可能なオプションオプション | 意味 |
---|---|
-d DIR_NAME |
ログ出力先ディレクトリを指定する |
--start SYMBOL |
トレース開始/終了する関数名を指定する |
-p PID |
指定したPIDのアプリケーションをトレースする |
-c COMMAND |
COMMAND によって実行されるアプリケーションをトレースする |
--syscall FUNC_NAME,FUNCNAME2,... |
システムコールのトレースを行う。
FUNC_NAME にはカーネル内のシステムコールエントリポイントを指定する。例: sys_open |
bt_split
で利用可能なオプションオプション | 意味 |
---|---|
-d DIR_NAME |
ログディレクトリを指定する |
bt_coverage
で利用可能なオプションオプション | 意味 |
---|---|
-f LOG_FILE,LOG_FILE2,... |
解析対象ログファイルを指定する |
-o DIR_NAME |
カバレージ解析結果HTMLの出力先ディレクトリを指定する |
--usr |
解析対象アドレス範囲を指定する。--usr はユーザ空間のみ--ker はカーネル空間のみ--all は全空間-a ADDR:ADDR ではユーザがアドレス範囲を直接指定することができる例えば、 -a 0xffffffff80000000:0xffffffffffffffff のように指定可能である。
|
-I FUNC_NAME,FUNC_NAME2,... |
解析対象の関数を指定する |
-E FUNC_NAME,FUNC_NAME2,... |
解析対象から除外する関数を指定する |
--f2 LOG_FILE,LOG_FILE2,... |
-f で指定したログファイルとの比較用ログファイルを指定する |
-S SOURCE_DIR |
Btraxが自動的にソースコードの情報を得ることができなかった場合、 このオプションを使い、ソースコードのディレクトリを指定することができる。 |
bt_execpath
で利用可能なオプションオプション | 意味 |
---|---|
-s |
サマリ表示をする |
--usr |
解析対象アドレス範囲を指定する。--usr はユーザ空間のみ--ker はカーネル空間のみ--all は全空間-a ADDR:ADDR ではユーザがアドレス範囲を直接指定することができる例えば、 -a 0xffffffff80000000:0xffffffffffffffff のように指定可能である。
|
-f FILENAME |
ログファイルを指定する |